rename accountopt.[ch] to purpleaccountoption.[ch]
[pidgin-git.git] / libpurple / protocols / oscar / snac.c
blob451dfc6647e966f4eeeb86984dc431c270b40626
1 /*
2 * Purple's oscar protocol plugin
3 * This file is the legal property of its developers.
4 * Please see the AUTHORS file distributed alongside this file.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 * Various SNAC-related dodads...
25 * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added
26 * whenever a new SNAC is sent and it should remain in the list until the
27 * response for it has been received.
29 * cleansnacs() should be called periodically by the client in order
30 * to facilitate the aging out of unreplied-to SNACs. This can and does
31 * happen, so it should be handled.
35 #include "oscar.h"
38 * Called from oscar_session_new() to initialize the hash.
40 void aim_initsnachash(OscarData *od)
42 int i;
44 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
45 od->snac_hash[i] = NULL;
47 return;
50 aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen)
52 aim_snac_t snac;
54 snac.id = od->snacid_next++;
55 snac.family = family;
56 snac.type = type;
57 snac.flags = flags;
59 if (datalen)
60 snac.data = g_memdup(data, datalen);
61 else
62 snac.data = NULL;
64 return aim_newsnac(od, &snac);
68 * Clones the passed snac structure and caches it in the
69 * list/hash.
71 aim_snacid_t aim_newsnac(OscarData *od, aim_snac_t *newsnac)
73 aim_snac_t *snac;
74 int index;
76 if (!newsnac)
77 return 0;
79 snac = g_memdup(newsnac, sizeof(aim_snac_t));
80 snac->issuetime = time(NULL);
82 index = snac->id % FAIM_SNAC_HASH_SIZE;
84 snac->next = (aim_snac_t *)od->snac_hash[index];
85 od->snac_hash[index] = (void *)snac;
87 return snac->id;
91 * Finds a snac structure with the passed SNAC ID,
92 * removes it from the list/hash, and returns a pointer to it.
94 * The returned structure must be freed by the caller.
97 aim_snac_t *aim_remsnac(OscarData *od, aim_snacid_t id)
99 aim_snac_t *cur, **prev;
100 int index;
102 index = id % FAIM_SNAC_HASH_SIZE;
104 for (prev = (aim_snac_t **)&od->snac_hash[index]; (cur = *prev); ) {
105 if (cur->id == id) {
106 *prev = cur->next;
107 if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) {
108 g_free(cur->data);
109 cur->data = NULL;
111 return cur;
112 } else
113 prev = &cur->next;
116 return cur;
120 * This is for cleaning up old SNACs that either don't get replies or
121 * a reply was never received for. Garbage collection. Plain and simple.
123 * maxage is the _minimum_ age in seconds to keep SNACs.
126 void aim_cleansnacs(OscarData *od, int maxage)
128 int i;
130 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
131 aim_snac_t *cur, **prev;
132 time_t curtime;
134 if (!od->snac_hash[i])
135 continue;
137 curtime = time(NULL); /* done here in case we waited for the lock */
139 for (prev = (aim_snac_t **)&od->snac_hash[i]; (cur = *prev); ) {
140 if ((curtime - cur->issuetime) > maxage) {
142 *prev = cur->next;
144 g_free(cur->data);
145 g_free(cur);
146 } else
147 prev = &cur->next;
151 return;
154 int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, aim_snacid_t snacid)
157 byte_stream_put16(bs, family);
158 byte_stream_put16(bs, subtype);
159 byte_stream_put16(bs, 0x0000);
160 byte_stream_put32(bs, snacid);
162 return 10;