comparison libpurple/protocols/oscar/snac.c @ 15373:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 32c366eeeb99
comparison
equal deleted inserted replaced
15372:f79e0f4df793 15373:5fe8042783c1
1 /*
2 * Gaim's oscar protocol plugin
3 * This file is the legal property of its developers.
4 * Please see the AUTHORS file distributed alongside this file.
5 *
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.
10 *
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.
15 *
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 *
23 * Various SNAC-related dodads...
24 *
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.
28 *
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.
32 *
33 */
34
35 #include "oscar.h"
36
37 /*
38 * Called from oscar_session_new() to initialize the hash.
39 */
40 void aim_initsnachash(OscarData *od)
41 {
42 int i;
43
44 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
45 od->snac_hash[i] = NULL;
46
47 return;
48 }
49
50 aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen)
51 {
52 aim_snac_t snac;
53
54 snac.id = od->snacid_next++;
55 snac.family = family;
56 snac.type = type;
57 snac.flags = flags;
58
59 if (datalen) {
60 if (!(snac.data = malloc(datalen)))
61 return 0; /* er... */
62 memcpy(snac.data, data, datalen);
63 } else
64 snac.data = NULL;
65
66 return aim_newsnac(od, &snac);
67 }
68
69 /*
70 * Clones the passed snac structure and caches it in the
71 * list/hash.
72 */
73 aim_snacid_t aim_newsnac(OscarData *od, aim_snac_t *newsnac)
74 {
75 aim_snac_t *snac;
76 int index;
77
78 if (!newsnac)
79 return 0;
80
81 if (!(snac = malloc(sizeof(aim_snac_t))))
82 return 0;
83 memcpy(snac, newsnac, sizeof(aim_snac_t));
84 snac->issuetime = time(NULL);
85
86 index = snac->id % FAIM_SNAC_HASH_SIZE;
87
88 snac->next = (aim_snac_t *)od->snac_hash[index];
89 od->snac_hash[index] = (void *)snac;
90
91 return snac->id;
92 }
93
94 /*
95 * Finds a snac structure with the passed SNAC ID,
96 * removes it from the list/hash, and returns a pointer to it.
97 *
98 * The returned structure must be freed by the caller.
99 *
100 */
101 aim_snac_t *aim_remsnac(OscarData *od, aim_snacid_t id)
102 {
103 aim_snac_t *cur, **prev;
104 int index;
105
106 index = id % FAIM_SNAC_HASH_SIZE;
107
108 for (prev = (aim_snac_t **)&od->snac_hash[index]; (cur = *prev); ) {
109 if (cur->id == id) {
110 *prev = cur->next;
111 if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) {
112 free(cur->data);
113 cur->data = NULL;
114 }
115 return cur;
116 } else
117 prev = &cur->next;
118 }
119
120 return cur;
121 }
122
123 /*
124 * This is for cleaning up old SNACs that either don't get replies or
125 * a reply was never received for. Garbage collection. Plain and simple.
126 *
127 * maxage is the _minimum_ age in seconds to keep SNACs.
128 *
129 */
130 void aim_cleansnacs(OscarData *od, int maxage)
131 {
132 int i;
133
134 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
135 aim_snac_t *cur, **prev;
136 time_t curtime;
137
138 if (!od->snac_hash[i])
139 continue;
140
141 curtime = time(NULL); /* done here in case we waited for the lock */
142
143 for (prev = (aim_snac_t **)&od->snac_hash[i]; (cur = *prev); ) {
144 if ((curtime - cur->issuetime) > maxage) {
145
146 *prev = cur->next;
147
148 free(cur->data);
149 free(cur);
150 } else
151 prev = &cur->next;
152 }
153 }
154
155 return;
156 }
157
158 int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, guint16 flags, aim_snacid_t snacid)
159 {
160
161 byte_stream_put16(bs, family);
162 byte_stream_put16(bs, subtype);
163 byte_stream_put16(bs, flags);
164 byte_stream_put32(bs, snacid);
165
166 return 10;
167 }