| 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] = { |
| 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", |
| 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 } |
|