Mercurial > pidgin
comparison src/protocols/oscar/rxhandlers.c @ 13592:6519aeb66b31
[gaim-migrate @ 15978]
Holy cow this is crazy.
34 files changed, 5760 insertions(+), 8517 deletions(-)
* Non-blocking I/O for all of oscar. That includes normal FLAP
connections as well as file transfers and direct IM.
* Kick-ass file transfer and direct IM. Either party can request
the connection. Gaim will try both the "public" IP and the
"client" IP. It'll fall back to transferring through a proxy
if that fails. Should be relatively few memleaks (I didn't
have a lot of confidence in the non-memleakiness of the old
code). And the code is reasonably generic, so it shouldn't
be too much work to add voice chat. This might still be a
LITTLE buggy, but it shouldn't be too bad. If anything, file
transfer will be more buggy than direct IM. And sending a
file will be more buggy than receiving a file. Bug reports
with a series of steps to reproduce are welcome.
* I merged OscarData and aim_session_t
* Somewhere between 50 and 100 hours of work.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Fri, 07 Apr 2006 05:10:56 +0000 |
parents | e9802db22b06 |
children |
comparison
equal
deleted
inserted
replaced
13591:dcfda39ad547 | 13592:6519aeb66b31 |
---|---|
16 * You should have received a copy of the GNU Lesser General Public | 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 | 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 | 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 */ | 19 */ |
20 | 20 |
21 /* | |
22 * rxhandlers.c | |
23 * | |
24 * This file contains most all of the incoming packet handlers, along | |
25 * with aim_rxdispatch(), the Rx dispatcher. Queue/list management is | |
26 * actually done in aim_rxqueue.c. | |
27 * | |
28 */ | |
29 | |
30 #include "oscar.h" | 21 #include "oscar.h" |
31 #include "peer.h" | 22 #include "peer.h" |
32 | 23 |
33 struct aim_rxcblist_s { | 24 aim_module_t *aim__findmodulebygroup(OscarData *od, guint16 group) |
34 guint16 family; | |
35 guint16 type; | |
36 aim_rxcallback_t handler; | |
37 guint16 flags; | |
38 struct aim_rxcblist_s *next; | |
39 }; | |
40 | |
41 faim_internal aim_module_t *aim__findmodulebygroup(OscarSession *sess, guint16 group) | |
42 { | 25 { |
43 aim_module_t *cur; | 26 aim_module_t *cur; |
44 | 27 |
45 for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { | 28 for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) { |
46 if (cur->family == group) | 29 if (cur->family == group) |
47 return cur; | 30 return cur; |
48 } | 31 } |
49 | 32 |
50 return NULL; | 33 return NULL; |
51 } | 34 } |
52 | 35 |
53 faim_internal aim_module_t *aim__findmodule(OscarSession *sess, const char *name) | 36 aim_module_t *aim__findmodule(OscarData *od, const char *name) |
54 { | 37 { |
55 aim_module_t *cur; | 38 aim_module_t *cur; |
56 | 39 |
57 for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { | 40 for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) { |
58 if (strcmp(name, cur->name) == 0) | 41 if (strcmp(name, cur->name) == 0) |
59 return cur; | 42 return cur; |
60 } | 43 } |
61 | 44 |
62 return NULL; | 45 return NULL; |
63 } | 46 } |
64 | 47 |
65 faim_internal int aim__registermodule(OscarSession *sess, int (*modfirst)(OscarSession *, aim_module_t *)) | 48 int aim__registermodule(OscarData *od, int (*modfirst)(OscarData *, aim_module_t *)) |
66 { | 49 { |
67 aim_module_t *mod; | 50 aim_module_t *mod; |
68 | 51 |
69 if (!sess || !modfirst) | 52 if (!od || !modfirst) |
70 return -1; | 53 return -1; |
71 | 54 |
72 if (!(mod = malloc(sizeof(aim_module_t)))) | 55 mod = g_new0(aim_module_t, 1); |
73 return -1; | 56 |
74 memset(mod, 0, sizeof(aim_module_t)); | 57 if (modfirst(od, mod) == -1) { |
75 | |
76 if (modfirst(sess, mod) == -1) { | |
77 free(mod); | 58 free(mod); |
78 return -1; | 59 return -1; |
79 } | 60 } |
80 | 61 |
81 if (aim__findmodule(sess, mod->name)) { | 62 if (aim__findmodule(od, mod->name)) { |
82 if (mod->shutdown) | 63 if (mod->shutdown) |
83 mod->shutdown(sess, mod); | 64 mod->shutdown(od, mod); |
84 free(mod); | 65 free(mod); |
85 return -1; | 66 return -1; |
86 } | 67 } |
87 | 68 |
88 mod->next = (aim_module_t *)sess->modlistv; | 69 mod->next = (aim_module_t *)od->modlistv; |
89 sess->modlistv = mod; | 70 od->modlistv = mod; |
90 | 71 |
91 gaim_debug_misc("oscar", "registered module %s (family 0x%04x, version = 0x%04x, tool 0x%04x, tool version 0x%04x)\n", mod->name, mod->family, mod->version, mod->toolid, mod->toolversion); | 72 gaim_debug_misc("oscar", "registered module %s (family 0x%04x, version = 0x%04x, tool 0x%04x, tool version 0x%04x)\n", mod->name, mod->family, mod->version, mod->toolid, mod->toolversion); |
92 | 73 |
93 return 0; | 74 return 0; |
94 } | 75 } |
95 | 76 |
96 faim_internal void aim__shutdownmodules(OscarSession *sess) | 77 void aim__shutdownmodules(OscarData *od) |
97 { | 78 { |
98 aim_module_t *cur; | 79 aim_module_t *cur; |
99 | 80 |
100 for (cur = (aim_module_t *)sess->modlistv; cur; ) { | 81 for (cur = (aim_module_t *)od->modlistv; cur; ) { |
101 aim_module_t *tmp; | 82 aim_module_t *tmp; |
102 | 83 |
103 tmp = cur->next; | 84 tmp = cur->next; |
104 | 85 |
105 if (cur->shutdown) | 86 if (cur->shutdown) |
106 cur->shutdown(sess, cur); | 87 cur->shutdown(od, cur); |
107 | 88 |
108 free(cur); | 89 free(cur); |
109 | 90 |
110 cur = tmp; | 91 cur = tmp; |
111 } | 92 } |
112 | 93 |
113 sess->modlistv = NULL; | 94 od->modlistv = NULL; |
114 | 95 |
115 return; | 96 return; |
116 } | 97 } |
117 | 98 |
118 static int consumesnac(OscarSession *sess, FlapFrame *rx) | 99 #if 0 |
119 { | |
120 aim_module_t *cur; | |
121 aim_modsnac_t snac; | |
122 | |
123 if (aim_bstream_empty(&rx->data) < 10) | |
124 return 0; | |
125 | |
126 snac.family = aimbs_get16(&rx->data); | |
127 snac.subtype = aimbs_get16(&rx->data); | |
128 snac.flags = aimbs_get16(&rx->data); | |
129 snac.id = aimbs_get32(&rx->data); | |
130 | |
131 /* SNAC flags are apparently uniform across all SNACs, so we handle them here */ | |
132 if (snac.flags & 0x0001) { | |
133 /* | |
134 * This means the SNAC will be followed by another SNAC with | |
135 * related information. We don't need to do anything about | |
136 * this here. | |
137 */ | |
138 } | |
139 if (snac.flags & 0x8000) { | |
140 /* | |
141 * This packet contains the version of the family that this SNAC is | |
142 * in. You get this when your SSI module is version 2 or higher. | |
143 * For now we have no need for this, but you could always save | |
144 * it as a part of aim_modnsac_t, or something. The format is... | |
145 * 2 byte length of total mini-header (which is 6 bytes), then TLV | |
146 * of type 0x0001, length 0x0002, value is the 2 byte version | |
147 * number | |
148 */ | |
149 aim_bstream_advance(&rx->data, aimbs_get16(&rx->data)); | |
150 } | |
151 | |
152 for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { | |
153 | |
154 if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && | |
155 (cur->family != snac.family)) | |
156 continue; | |
157 | |
158 if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) | |
159 return 1; | |
160 | |
161 } | |
162 | |
163 return 0; | |
164 } | |
165 | |
166 static int consumenonsnac(OscarSession *sess, FlapFrame *rx, guint16 family, guint16 subtype) | |
167 { | |
168 aim_module_t *cur; | |
169 aim_modsnac_t snac; | |
170 | |
171 snac.family = family; | |
172 snac.subtype = subtype; | |
173 snac.flags = snac.id = 0; | |
174 | |
175 for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { | |
176 | |
177 if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && | |
178 (cur->family != snac.family)) | |
179 continue; | |
180 | |
181 if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) | |
182 return 1; | |
183 | |
184 } | |
185 | |
186 return 0; | |
187 } | |
188 | |
189 static int negchan_middle(OscarSession *sess, FlapFrame *fr) | |
190 { | |
191 aim_tlvlist_t *tlvlist; | |
192 char *msg = NULL; | |
193 guint16 code = 0; | |
194 aim_rxcallback_t userfunc; | |
195 int ret = 1; | |
196 | |
197 if (aim_bstream_empty(&fr->data) == 0) { | |
198 /* XXX should do something with this */ | |
199 return 1; | |
200 } | |
201 | |
202 /* Used only by the older login protocol */ | |
203 /* XXX remove this special case? */ | |
204 if (fr->conn->type == AIM_CONN_TYPE_AUTH) | |
205 return consumenonsnac(sess, fr, 0x0017, 0x0003); | |
206 | |
207 tlvlist = aim_tlvlist_read(&fr->data); | |
208 | |
209 if (aim_tlv_gettlv(tlvlist, 0x0009, 1)) | |
210 code = aim_tlv_get16(tlvlist, 0x0009, 1); | |
211 | |
212 if (aim_tlv_gettlv(tlvlist, 0x000b, 1)) | |
213 msg = aim_tlv_getstr(tlvlist, 0x000b, 1); | |
214 | |
215 if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) | |
216 ret = userfunc(sess, fr, code, msg); | |
217 | |
218 aim_tlvlist_free(&tlvlist); | |
219 | |
220 free(msg); | |
221 | |
222 return ret; | |
223 } | |
224 | |
225 /* | 100 /* |
226 * Bleck functions get called when there's no non-bleck functions | 101 * Bleck functions get called when there's no non-bleck functions |
227 * around to cleanup the mess... | 102 * around to cleanup the mess... |
228 */ | 103 */ |
229 static int bleck(OscarSession *sess, FlapFrame *frame, ...) | 104 static int bleck(OscarData *od, FlapFrame *frame, ...) |
230 { | 105 { |
231 guint16 family, subtype; | 106 guint16 family, subtype; |
232 guint16 maxf, maxs; | 107 guint16 maxf, maxs; |
233 | 108 |
234 static const char *channels[6] = { | 109 static const char *channels[6] = { |
238 "Invalid (3)", | 113 "Invalid (3)", |
239 "Negotiation", | 114 "Negotiation", |
240 "FLAP NOP" | 115 "FLAP NOP" |
241 }; | 116 }; |
242 static const int maxchannels = 5; | 117 static const int maxchannels = 5; |
243 | 118 |
244 /* XXX: this is ugly. and big just for debugging. */ | 119 /* XXX: this is ugly. and big just for debugging. */ |
245 static const char *literals[14][25] = { | 120 static const char *literals[14][25] = { |
246 {"Invalid", | 121 {"Invalid", |
247 NULL | 122 NULL |
248 }, | 123 }, |
249 {"General", | 124 {"General", |
250 "Invalid", | 125 "Invalid", |
251 "Error", | 126 "Error", |
252 "Client Ready", | 127 "Client Ready", |
253 "Server Ready", | 128 "Server Ready", |
254 "Service Request", | 129 "Service Request", |
269 "Message of the Day", | 144 "Message of the Day", |
270 "Set Privacy Flags", | 145 "Set Privacy Flags", |
271 "Well Known URL", | 146 "Well Known URL", |
272 "NOP" | 147 "NOP" |
273 }, | 148 }, |
274 {"Location", | 149 {"Location", |
275 "Invalid", | 150 "Invalid", |
276 "Error", | 151 "Error", |
277 "Request Rights", | 152 "Request Rights", |
278 "Rights Information", | 153 "Rights Information", |
279 "Set user information", | 154 "Set user information", |
280 "Request User Information", | 155 "Request User Information", |
281 "User Information", | 156 "User Information", |
282 "Watcher Sub Request", | 157 "Watcher Sub Request", |
283 "Watcher Notification" | 158 "Watcher Notification" |
284 }, | 159 }, |
285 {"Buddy List Management", | 160 {"Buddy List Management", |
286 "Invalid", | 161 "Invalid", |
287 "Error", | 162 "Error", |
288 "Request Rights", | 163 "Request Rights", |
289 "Rights Information", | 164 "Rights Information", |
290 "Add Buddy", | 165 "Add Buddy", |
291 "Remove Buddy", | 166 "Remove Buddy", |
292 "Watcher List Query", | 167 "Watcher List Query", |
293 "Watcher List Response", | 168 "Watcher List Response", |
294 "Watcher SubRequest", | 169 "Watcher SubRequest", |
295 "Watcher Notification", | 170 "Watcher Notification", |
296 "Reject Notification", | 171 "Reject Notification", |
297 "Oncoming Buddy", | 172 "Oncoming Buddy", |
298 "Offgoing Buddy" | 173 "Offgoing Buddy" |
299 }, | 174 }, |
300 {"Messeging", | 175 {"Messeging", |
301 "Invalid", | 176 "Invalid", |
302 "Error", | 177 "Error", |
303 "Add ICBM Parameter", | 178 "Add ICBM Parameter", |
304 "Remove ICBM Parameter", | 179 "Remove ICBM Parameter", |
305 "Request Parameter Information", | 180 "Request Parameter Information", |
306 "Parameter Information", | 181 "Parameter Information", |
307 "Outgoing Message", | 182 "Outgoing Message", |
308 "Incoming Message", | 183 "Incoming Message", |
309 "Evil Request", | 184 "Evil Request", |
310 "Evil Reply", | 185 "Evil Reply", |
311 "Missed Calls", | 186 "Missed Calls", |
312 "Message Error", | 187 "Message Error", |
313 "Host Ack" | 188 "Host Ack" |
314 }, | 189 }, |
315 {"Advertisements", | 190 {"Advertisements", |
316 "Invalid", | 191 "Invalid", |
317 "Error", | 192 "Error", |
318 "Request Ad", | 193 "Request Ad", |
319 "Ad Data (GIFs)" | 194 "Ad Data (GIFs)" |
320 }, | 195 }, |
321 {"Invitation / Client-to-Client", | 196 {"Invitation / Client-to-Client", |
322 "Invalid", | 197 "Invalid", |
323 "Error", | 198 "Error", |
324 "Invite a Friend", | 199 "Invite a Friend", |
325 "Invitation Ack" | 200 "Invitation Ack" |
326 }, | 201 }, |
327 {"Administrative", | 202 {"Administrative", |
328 "Invalid", | 203 "Invalid", |
329 "Error", | 204 "Error", |
330 "Information Request", | 205 "Information Request", |
331 "Information Reply", | 206 "Information Reply", |
332 "Information Change Request", | 207 "Information Change Request", |
334 "Account Confirm Request", | 209 "Account Confirm Request", |
335 "Account Confirm Reply", | 210 "Account Confirm Reply", |
336 "Account Delete Request", | 211 "Account Delete Request", |
337 "Account Delete Reply" | 212 "Account Delete Reply" |
338 }, | 213 }, |
339 {"Popups", | 214 {"Popups", |
340 "Invalid", | 215 "Invalid", |
341 "Error", | 216 "Error", |
342 "Display Popup" | 217 "Display Popup" |
343 }, | 218 }, |
344 {"BOS", | 219 {"BOS", |
345 "Invalid", | 220 "Invalid", |
346 "Error", | 221 "Error", |
347 "Request Rights", | 222 "Request Rights", |
348 "Rights Response", | 223 "Rights Response", |
349 "Set group permission mask", | 224 "Set group permission mask", |
351 "Delete permission list entries", | 226 "Delete permission list entries", |
352 "Add deny list entries", | 227 "Add deny list entries", |
353 "Delete deny list entries", | 228 "Delete deny list entries", |
354 "Server Error" | 229 "Server Error" |
355 }, | 230 }, |
356 {"User Lookup", | 231 {"User Lookup", |
357 "Invalid", | 232 "Invalid", |
358 "Error", | 233 "Error", |
359 "Search Request", | 234 "Search Request", |
360 "Search Response" | 235 "Search Response" |
361 }, | 236 }, |
362 {"Stats", | 237 {"Stats", |
363 "Invalid", | 238 "Invalid", |
364 "Error", | 239 "Error", |
365 "Set minimum report interval", | 240 "Set minimum report interval", |
366 "Report Events" | 241 "Report Events" |
367 }, | 242 }, |
368 {"Translate", | 243 {"Translate", |
369 "Invalid", | 244 "Invalid", |
370 "Error", | 245 "Error", |
371 "Translate Request", | 246 "Translate Request", |
372 "Translate Reply", | 247 "Translate Reply", |
373 }, | 248 }, |
374 {"Chat Navigation", | 249 {"Chat Navigation", |
375 "Invalid", | 250 "Invalid", |
376 "Error", | 251 "Error", |
377 "Request rights", | 252 "Request rights", |
378 "Request Exchange Information", | 253 "Request Exchange Information", |
379 "Request Room Information", | 254 "Request Room Information", |
380 "Request Occupant List", | 255 "Request Occupant List", |
381 "Search for Room", | 256 "Search for Room", |
382 "Outgoing Message", | 257 "Outgoing Message", |
383 "Incoming Message", | 258 "Incoming Message", |
384 "Evil Request", | 259 "Evil Request", |
385 "Evil Reply", | 260 "Evil Reply", |
386 "Chat Error", | 261 "Chat Error", |
387 } | 262 } |
388 }; | 263 }; |
389 | 264 |
390 maxf = sizeof(literals) / sizeof(literals[0]); | 265 maxf = sizeof(literals) / sizeof(literals[0]); |
391 maxs = sizeof(literals[0]) / sizeof(literals[0][0]); | 266 maxs = sizeof(literals[0]) / sizeof(literals[0][0]); |
392 | 267 |
393 if (frame->hdr.flap.channel == 0x02) { | 268 if (frame->channel == 0x02) { |
394 | 269 |
395 family = aimbs_get16(&frame->data); | 270 family = byte_stream_get16(&frame->data); |
396 subtype = aimbs_get16(&frame->data); | 271 subtype = byte_stream_get16(&frame->data); |
397 | 272 |
398 if ((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL)) | 273 if ((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL)) |
399 gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (%s)\n", channels[frame->hdr.flap.channel], family, subtype, literals[family][subtype+1]); | 274 gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (%s)\n", channels[frame->channel], family, subtype, literals[family][subtype+1]); |
400 else | 275 else |
401 gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (no literal)\n", channels[frame->hdr.flap.channel], family, subtype); | 276 gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (no literal)\n", channels[frame->channel], family, subtype); |
402 } else { | 277 } else { |
403 | 278 |
404 if (frame->hdr.flap.channel <= maxchannels) | 279 if (frame->channel <= maxchannels) |
405 gaim_debug_misc("oscar", "bleck: channel %s (0x%02x)\n", channels[frame->hdr.flap.channel], frame->hdr.flap.channel); | 280 gaim_debug_misc("oscar", "bleck: channel %s (0x%02x)\n", channels[frame->channel], frame->channel); |
406 else | 281 else |
407 gaim_debug_misc("oscar", "bleck: unknown channel 0x%02x\n", frame->hdr.flap.channel); | 282 gaim_debug_misc("oscar", "bleck: unknown channel 0x%02x\n", frame->channel); |
408 | 283 |
409 } | 284 } |
410 | 285 |
411 return 1; | 286 return 1; |
412 } | 287 } |
413 | 288 #endif |
414 faim_export int aim_conn_addhandler(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 type, aim_rxcallback_t newhandler, guint16 flags) | |
415 { | |
416 struct aim_rxcblist_s *newcb; | |
417 | |
418 if (!conn) | |
419 return -1; | |
420 | |
421 gaim_debug_misc("oscar", "aim_conn_addhandler: adding for %04x/%04x\n", family, type); | |
422 | |
423 if (!(newcb = (struct aim_rxcblist_s *)calloc(1, sizeof(struct aim_rxcblist_s)))) | |
424 return -1; | |
425 | |
426 newcb->family = family; | |
427 newcb->type = type; | |
428 newcb->flags = flags; | |
429 newcb->handler = newhandler ? newhandler : bleck; | |
430 newcb->next = NULL; | |
431 | |
432 if (!conn->handlerlist) | |
433 conn->handlerlist = (void *)newcb; | |
434 else { | |
435 struct aim_rxcblist_s *cur; | |
436 | |
437 for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur->next; cur = cur->next) | |
438 ; | |
439 cur->next = newcb; | |
440 } | |
441 | |
442 return 0; | |
443 } | |
444 | |
445 faim_export int aim_clearhandlers(OscarConnection *conn) | |
446 { | |
447 struct aim_rxcblist_s *cur; | |
448 | |
449 if (!conn) | |
450 return -1; | |
451 | |
452 for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; ) { | |
453 struct aim_rxcblist_s *tmp; | |
454 | |
455 tmp = cur->next; | |
456 free(cur); | |
457 cur = tmp; | |
458 } | |
459 conn->handlerlist = NULL; | |
460 | |
461 return 0; | |
462 } | |
463 | |
464 faim_internal aim_rxcallback_t aim_callhandler(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 type) | |
465 { | |
466 struct aim_rxcblist_s *cur; | |
467 | |
468 if (!conn) | |
469 return NULL; | |
470 | |
471 /* gaim_debug_misc("oscar", "aim_callhandler: calling for %04x/%04x\n", family, type); */ | |
472 | |
473 for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; cur = cur->next) { | |
474 if ((cur->family == family) && (cur->type == type)) | |
475 return cur->handler; | |
476 } | |
477 | |
478 return NULL; | |
479 } | |
480 | |
481 faim_internal void aim_clonehandlers(OscarSession *sess, OscarConnection *dest, OscarConnection *src) | |
482 { | |
483 struct aim_rxcblist_s *cur; | |
484 | |
485 for (cur = (struct aim_rxcblist_s *)src->handlerlist; cur; cur = cur->next) { | |
486 aim_conn_addhandler(sess, dest, cur->family, cur->type, | |
487 cur->handler, cur->flags); | |
488 } | |
489 | |
490 return; | |
491 } | |
492 | |
493 faim_internal int aim_callhandler_noparam(OscarSession *sess, OscarConnection *conn,guint16 family, guint16 type, FlapFrame *ptr) | |
494 { | |
495 aim_rxcallback_t userfunc; | |
496 | |
497 if ((userfunc = aim_callhandler(sess, conn, family, type))) | |
498 return userfunc(sess, ptr); | |
499 | |
500 return 1; /* XXX */ | |
501 } | |
502 | |
503 /* | |
504 * aim_rxdispatch() | |
505 * | |
506 * Basically, heres what this should do: | |
507 * 1) Determine correct packet handler for this packet | |
508 * 2) Mark the packet handled (so it can be dequeued in purge_queue()) | |
509 * 3) Send the packet to the packet handler | |
510 * 4) Go to next packet in the queue and start over | |
511 * 5) When done, run purge_queue() to purge handled commands | |
512 * | |
513 * TODO: Clean up. | |
514 * TODO: More support for mid-level handlers. | |
515 * TODO: Allow for NULL handlers. | |
516 * | |
517 */ | |
518 faim_export void aim_rxdispatch(OscarSession *sess) | |
519 { | |
520 int i; | |
521 FlapFrame *cur; | |
522 | |
523 for (cur = sess->queue_incoming, i = 0; cur; cur = cur->next, i++) { | |
524 | |
525 /* | |
526 * XXX: This is still fairly ugly. | |
527 */ | |
528 | |
529 if (cur->handled) | |
530 continue; | |
531 | |
532 if (cur->hdrtype == AIM_FRAMETYPE_FLAP) { | |
533 if (cur->hdr.flap.channel == 0x01) { | |
534 cur->handled = aim_callhandler_noparam(sess, cur->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, cur); /* XXX use consumenonsnac */ | |
535 continue; | |
536 | |
537 } else if (cur->hdr.flap.channel == 0x02) { | |
538 if ((cur->handled = consumesnac(sess, cur))) | |
539 continue; | |
540 | |
541 } else if (cur->hdr.flap.channel == 0x04) { | |
542 cur->handled = negchan_middle(sess, cur); | |
543 continue; | |
544 | |
545 } else if (cur->hdr.flap.channel == 0x05) { | |
546 | |
547 } | |
548 | |
549 } else if (cur->hdrtype == AIM_FRAMETYPE_OFT) { | |
550 if (cur->conn->type == AIM_CONN_TYPE_RENDEZVOUS) { | |
551 aim_rxdispatch_rendezvous(sess, cur); | |
552 cur->handled = 1; | |
553 continue; | |
554 | |
555 } else if (cur->conn->type == AIM_CONN_TYPE_LISTENER) { | |
556 /* not possible */ | |
557 gaim_debug_misc("oscar", "rxdispatch called on LISTENER connection!\n"); | |
558 cur->handled = 1; | |
559 continue; | |
560 } | |
561 } | |
562 | |
563 if (!cur->handled) { | |
564 consumenonsnac(sess, cur, 0xffff, 0xffff); /* last chance! */ | |
565 cur->handled = 1; | |
566 } | |
567 } | |
568 | |
569 /* | |
570 * This doesn't have to be called here. It could easily be done | |
571 * by a separate thread or something. It's an administrative operation, | |
572 * and can take a while. Though the less you call it the less memory | |
573 * you'll have :) | |
574 */ | |
575 aim_purge_rxqueue(sess); | |
576 | |
577 return; | |
578 } | |
579 | |
580 faim_internal int aim_parse_unknown(OscarSession *sess, FlapFrame *frame, ...) | |
581 { | |
582 int i; | |
583 | |
584 gaim_debug_misc("oscar", "\nRecieved unknown packet:"); | |
585 | |
586 for (i = 0; aim_bstream_empty(&frame->data); i++) { | |
587 if ((i % 8) == 0) | |
588 gaim_debug_misc("oscar", "\n\t"); | |
589 | |
590 gaim_debug_misc("oscar", "0x%2x ", aimbs_get8(&frame->data)); | |
591 } | |
592 | |
593 gaim_debug_misc("oscar", "\n\n"); | |
594 | |
595 return 1; | |
596 } |