| |
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 } |