]> andersk Git - libfaim.git/blame - aim_rxhandlers.c
- Sun Feb 11 01:07:36 UTC 2001
[libfaim.git] / aim_rxhandlers.c
CommitLineData
9de3ca7e 1/*
24286d93 2 * aim_rxhandlers.c
3 *
4 * This file contains most all of the incoming packet handlers, along
5 * with aim_rxdispatch(), the Rx dispatcher. Queue/list management is
6 * actually done in aim_rxqueue.c.
7 *
9de3ca7e 8 */
9
37ee990e 10#define FAIM_INTERNAL
a25832e6 11#include <faim/aim.h>
9de3ca7e 12
24286d93 13/*
14 * Bleck functions get called when there's no non-bleck functions
15 * around to cleanup the mess...
16 */
78b3fb13 17faim_internal int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
9de3ca7e 18{
19 u_short family;
20 u_short subtype;
01b59e1e 21
22 u_short maxf;
23 u_short maxs;
24
25 /* XXX: this is ugly. and big just for debugging. */
26 char *literals[14][25] = {
27 {"Invalid",
28 NULL
29 },
30 {"General",
31 "Invalid",
32 "Error",
33 "Client Ready",
34 "Server Ready",
35 "Service Request",
36 "Redirect",
37 "Rate Information Request",
38 "Rate Information",
39 "Rate Information Ack",
40 NULL,
41 "Rate Information Change",
42 "Server Pause",
43 NULL,
44 "Server Resume",
45 "Request Personal User Information",
46 "Personal User Information",
47 "Evil Notification",
48 NULL,
49 "Migration notice",
50 "Message of the Day",
51 "Set Privacy Flags",
52 "Well Known URL",
53 "NOP"
54 },
55 {"Location",
56 "Invalid",
57 "Error",
58 "Request Rights",
59 "Rights Information",
60 "Set user information",
61 "Request User Information",
62 "User Information",
63 "Watcher Sub Request",
64 "Watcher Notification"
65 },
66 {"Buddy List Management",
67 "Invalid",
68 "Error",
69 "Request Rights",
70 "Rights Information",
71 "Add Buddy",
72 "Remove Buddy",
73 "Watcher List Query",
74 "Watcher List Response",
75 "Watcher SubRequest",
76 "Watcher Notification",
77 "Reject Notification",
78 "Oncoming Buddy",
79 "Offgoing Buddy"
80 },
81 {"Messeging",
82 "Invalid",
83 "Error",
84 "Add ICBM Parameter",
85 "Remove ICBM Parameter",
86 "Request Parameter Information",
87 "Parameter Information",
88 "Outgoing Message",
89 "Incoming Message",
90 "Evil Request",
91 "Evil Reply",
92 "Missed Calls",
93 "Message Error",
94 "Host Ack"
95 },
96 {"Advertisements",
97 "Invalid",
98 "Error",
99 "Request Ad",
100 "Ad Data (GIFs)"
101 },
102 {"Invitation / Client-to-Client",
103 "Invalid",
104 "Error",
105 "Invite a Friend",
106 "Invitation Ack"
107 },
108 {"Administrative",
109 "Invalid",
110 "Error",
111 "Information Request",
112 "Information Reply",
113 "Information Change Request",
114 "Information Chat Reply",
115 "Account Confirm Request",
116 "Account Confirm Reply",
117 "Account Delete Request",
118 "Account Delete Reply"
119 },
120 {"Popups",
121 "Invalid",
122 "Error",
123 "Display Popup"
124 },
125 {"BOS",
126 "Invalid",
127 "Error",
128 "Request Rights",
129 "Rights Response",
130 "Set group permission mask",
131 "Add permission list entries",
132 "Delete permission list entries",
133 "Add deny list entries",
134 "Delete deny list entries",
135 "Server Error"
136 },
137 {"User Lookup",
138 "Invalid",
139 "Error",
140 "Search Request",
141 "Search Response"
142 },
143 {"Stats",
144 "Invalid",
145 "Error",
146 "Set minimum report interval",
147 "Report Events"
148 },
149 {"Translate",
150 "Invalid",
151 "Error",
152 "Translate Request",
153 "Translate Reply",
154 },
155 {"Chat Navigation",
156 "Invalid",
157 "Error",
158 "Request rights",
159 "Request Exchange Information",
160 "Request Room Information",
161 "Request Occupant List",
162 "Search for Room",
163 "Outgoing Message",
164 "Incoming Message",
165 "Evil Request",
166 "Evil Reply",
167 "Chat Error",
168 }
169 };
170
171 maxf = sizeof(literals) / sizeof(literals[0]);
172 maxs = sizeof(literals[0]) / sizeof(literals[0][0]);
173
174 family = aimutil_get16(workingPtr->data+0);
175 subtype= aimutil_get16(workingPtr->data+2);
176
177 if((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL))
178 printf("bleck: null handler for %04x/%04x (%s)\n", family, subtype, literals[family][subtype+1]);
179 else
180 printf("bleck: null handler for %04x/%04x (no literal)\n",family,subtype);
181
9de3ca7e 182 return 1;
183}
184
78b3fb13 185faim_export int aim_conn_addhandler(struct aim_session_t *sess,
a25832e6 186 struct aim_conn_t *conn,
9de3ca7e 187 u_short family,
188 u_short type,
189 rxcallback_t newhandler,
190 u_short flags)
191{
871e2fd0 192 struct aim_rxcblist_t *newcb;
9de3ca7e 193
194 if (!conn)
195 return -1;
196
b8d0da45 197 faimdprintf(1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
9de3ca7e 198
871e2fd0 199 if (!(newcb = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t))))
200 return -1;
a15d82b1 201 newcb->family = family;
202 newcb->type = type;
203 newcb->flags = flags;
9de3ca7e 204 if (!newhandler)
a15d82b1 205 newcb->handler = &bleck;
9de3ca7e 206 else
a15d82b1 207 newcb->handler = newhandler;
208 newcb->next = NULL;
9de3ca7e 209
871e2fd0 210 if (!conn->handlerlist)
a15d82b1 211 conn->handlerlist = newcb;
871e2fd0 212 else {
213 struct aim_rxcblist_t *cur;
214
215 cur = conn->handlerlist;
216
217 while (cur->next)
218 cur = cur->next;
219 cur->next = newcb;
220 }
9de3ca7e 221
222 return 0;
223}
224
78b3fb13 225faim_export int aim_clearhandlers(struct aim_conn_t *conn)
9de3ca7e 226{
871e2fd0 227 struct aim_rxcblist_t *cur;
228
9de3ca7e 229 if (!conn)
230 return -1;
231
55e77c8a 232 for (cur = conn->handlerlist; cur; ) {
871e2fd0 233 struct aim_rxcblist_t *tmp;
234
235 tmp = cur->next;
236 free(cur);
237 cur = tmp;
238 }
55e77c8a 239 conn->handlerlist = NULL;
871e2fd0 240
9de3ca7e 241 return 0;
242}
243
78b3fb13 244faim_internal rxcallback_t aim_callhandler(struct aim_conn_t *conn,
245 u_short family,
246 u_short type)
9de3ca7e 247{
248 struct aim_rxcblist_t *cur;
249
250 if (!conn)
251 return NULL;
252
b8d0da45 253 faimdprintf(1, "aim_callhandler: calling for %04x/%04x\n", family, type);
9de3ca7e 254
255 cur = conn->handlerlist;
256 while(cur)
257 {
258 if ( (cur->family == family) && (cur->type == type) )
259 return cur->handler;
260 cur = cur->next;
261 }
262
263 if (type==0xffff)
264 return NULL;
871e2fd0 265
9de3ca7e 266 return aim_callhandler(conn, family, 0xffff);
267}
268
78b3fb13 269faim_internal int aim_callhandler_noparam(struct aim_session_t *sess,
270 struct aim_conn_t *conn,
271 u_short family,
272 u_short type,
273 struct command_rx_struct *ptr)
9de3ca7e 274{
275 rxcallback_t userfunc = NULL;
276 userfunc = aim_callhandler(conn, family, type);
277 if (userfunc)
a25832e6 278 return userfunc(sess, ptr);
b8d0da45 279 return 1; /* XXX */
9de3ca7e 280}
281
282/*
283 aim_rxdispatch()
284
285 Basically, heres what this should do:
286 1) Determine correct packet handler for this packet
287 2) Mark the packet handled (so it can be dequeued in purge_queue())
288 3) Send the packet to the packet handler
289 4) Go to next packet in the queue and start over
290 5) When done, run purge_queue() to purge handled commands
291
292 Note that any unhandlable packets should probably be left in the
293 queue. This is the best way to prevent data loss. This means
294 that a single packet may get looked at by this function multiple
295 times. This is more good than bad! This behavior may change.
296
297 Aren't queue's fun?
298
299 TODO: Get rid of all the ugly if's.
300 TODO: Clean up.
301 TODO: More support for mid-level handlers.
302 TODO: Allow for NULL handlers.
303
304 */
78b3fb13 305faim_export int aim_rxdispatch(struct aim_session_t *sess)
9de3ca7e 306{
307 int i = 0;
308 struct command_rx_struct *workingPtr = NULL;
309
b8d0da45 310 if (sess->queue_incoming == NULL) {
311 faimdprintf(1, "parse_generic: incoming packet queue empty.\n");
312 return 0;
313 } else {
314 workingPtr = sess->queue_incoming;
50443ea0 315 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
b8d0da45 316 /*
317 * XXX: This is still fairly ugly.
318 */
50443ea0 319 if (workingPtr->handled)
320 continue;
321
b69540e3 322 /*
323 * This is a debugging/sanity check only and probably could/should be removed
324 * for stable code.
325 */
326 if (((workingPtr->hdrtype == AIM_FRAMETYPE_OFT) &&
327 (workingPtr->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) ||
328 ((workingPtr->hdrtype == AIM_FRAMETYPE_OSCAR) &&
329 (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS))) {
330 printf("faim: rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type);
331 workingPtr->handled = 1;
332 continue;
333 }
334
b8d0da45 335 switch(workingPtr->conn->type) {
336 case -1:
337 /*
338 * This can happen if we have a queued command
339 * that was recieved after a connection has
340 * been terminated. In which case, the handler
341 * list has been cleared, and there's nothing we
342 * can do for it. We can only cancel it.
343 */
344 workingPtr->handled = 1;
345 break;
346 case AIM_CONN_TYPE_AUTH: {
5daacaa3 347 unsigned long head;
b8d0da45 348
349 head = aimutil_get32(workingPtr->data);
5daacaa3 350 if ((head == 0x00000001) && (workingPtr->commandlen == 4)) {
b8d0da45 351 faimdprintf(1, "got connection ack on auth line\n");
22517493 352 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
5daacaa3 353 } else if (workingPtr->hdr.oscar.type == 0x04) {
354 /* Used only by the older login protocol */
f0a7908e 355 workingPtr->handled = aim_authparse(sess, workingPtr);
356 } else {
5daacaa3 357 unsigned short family,subtype;
b8d0da45 358
359 family = aimutil_get16(workingPtr->data);
360 subtype = aimutil_get16(workingPtr->data+2);
361
362 switch (family) {
363 /* New login protocol */
b8d0da45 364 case 0x0017:
365 if (subtype == 0x0001)
366 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
367 else if (subtype == 0x0003)
368 workingPtr->handled = aim_authparse(sess, workingPtr);
369 else if (subtype == 0x0007)
b5bc2a8c 370 workingPtr->handled = aim_authkeyparse(sess, workingPtr);
b8d0da45 371 else
372 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
373 break;
64c78745 374
ee49b735 375 case 0x0001:
376 if (subtype == 0x0003)
377 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
64c78745 378 else if (subtype == 0x0007)
379 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
380 else if (subtype == 0x0018)
381 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
ee49b735 382 else
64c78745 383 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0xffff, workingPtr);
ee49b735 384 break;
64c78745 385
ee49b735 386 case 0x0007:
64c78745 387 if (subtype == 0x0003)
388 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
389 else if (subtype == 0x0005)
390 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
391 else if (subtype == 0x0007)
392 workingPtr->handled = aim_parse_accountconfirm(sess, workingPtr);
ee49b735 393 break;
64c78745 394
ee49b735 395 case AIM_CB_FAM_SPECIAL:
396 if (subtype == AIM_CB_SPECIAL_DEBUGCONN_CONNECT) {
397 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
398 break;
399 } else
400 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
401 break;
64c78745 402
ee49b735 403 default:
78b3fb13 404 break;
b8d0da45 405 }
406 }
407 break;
408 }
409 case AIM_CONN_TYPE_BOS: {
410 u_short family;
411 u_short subtype;
5e02cf44 412
b69540e3 413 if (workingPtr->hdr.oscar.type == 0x04) {
5e02cf44 414 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
415 break;
416 }
417
b8d0da45 418 family = aimutil_get16(workingPtr->data);
419 subtype = aimutil_get16(workingPtr->data+2);
420
421 switch (family) {
422 case 0x0000: /* not really a family, but it works */
423 if (subtype == 0x0001)
22517493 424 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
b8d0da45 425 else
426 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
427 break;
428 case 0x0001: /* Family: General */
429 switch (subtype) {
430 case 0x0001:
431 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
432 break;
433 case 0x0003:
ee49b735 434 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 435 break;
436 case 0x0005:
437 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
438 break;
439 case 0x0007:
440 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
441 break;
442 case 0x000a:
1a8c261b 443 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
b8d0da45 444 break;
445 case 0x000f:
446 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
447 break;
98c88242 448 case 0x0010:
449 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
450 break;
b8d0da45 451 case 0x0013:
452 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
453 break;
ee49b735 454 case 0x0018:
455 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
456 break;
b8d0da45 457 default:
458 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
459 break;
460 }
96f8b1ed 461 break;
b8d0da45 462 case 0x0002: /* Family: Location */
463 switch (subtype) {
464 case 0x0001:
96f8b1ed 465 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
b8d0da45 466 break;
467 case 0x0003:
468 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
469 break;
470 case 0x0006:
471 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
472 break;
473 default:
474 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
475 break;
476 }
96f8b1ed 477 break;
b8d0da45 478 case 0x0003: /* Family: Buddy List */
479 switch (subtype) {
480 case 0x0001:
481 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
482 break;
483 case 0x0003:
96f8b1ed 484 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
b8d0da45 485 break;
486 case 0x000b: /* oncoming buddy */
487 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
488 break;
489 case 0x000c: /* offgoing buddy */
490 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
491 break;
492 default:
493 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
494 }
495 break;
3e2c7bcf 496 case 0x0004: /* Family: Messaging */
b8d0da45 497 switch (subtype) {
498 case 0x0001:
499 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
500 break;
501 case 0x0005:
502 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
503 break;
e5012450 504 case 0x0006:
505 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
506 break;
b8d0da45 507 case 0x0007:
508 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
509 break;
510 case 0x000a:
96f8b1ed 511 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
b8d0da45 512 break;
1a8c261b 513 case 0x000c:
514 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
515 break;
b8d0da45 516 default:
517 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
518 }
519 break;
520 case 0x0009:
521 if (subtype == 0x0001)
522 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
523 else if (subtype == 0x0003)
96f8b1ed 524 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
b8d0da45 525 else
526 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
527 break;
528 case 0x000a: /* Family: User lookup */
529 switch (subtype) {
530 case 0x0001:
37ee990e 531 workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
b8d0da45 532 break;
533 case 0x0003:
37ee990e 534 workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
b8d0da45 535 break;
536 default:
537 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
538 }
539 break;
96f8b1ed 540 case 0x000b: {
b8d0da45 541 if (subtype == 0x0001)
542 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
543 else if (subtype == 0x0002)
544 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
545 else
546 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
547 break;
96f8b1ed 548 }
3e2c7bcf 549 case 0x0013: {
550 printf("lalala: 0x%04x/0x%04x\n", family, subtype);
551 break;
552 }
96f8b1ed 553 case AIM_CB_FAM_SPECIAL:
554 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
555 break;
b8d0da45 556 default:
557 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
558 break;
96f8b1ed 559 } /* switch(family) */
b8d0da45 560 break;
96f8b1ed 561 } /* AIM_CONN_TYPE_BOS */
64c78745 562 case AIM_CONN_TYPE_ADS: {
563 unsigned short family;
564 unsigned short subtype;
565
566 family = aimutil_get16(workingPtr->data);
567 subtype= aimutil_get16(workingPtr->data+2);
568
569 if ((family == 0x0000) && (subtype == 0x00001)) {
570 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
571 } else if ((family == 0x0001) && (subtype == 0x0003)) {
572 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
573 } else {
574 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
575 }
576 break;
577 }
b8d0da45 578 case AIM_CONN_TYPE_CHATNAV: {
579 u_short family;
580 u_short subtype;
581 family = aimutil_get16(workingPtr->data);
582 subtype= aimutil_get16(workingPtr->data+2);
22517493 583
584 if ((family == 0x0000) && (subtype == 0x00001)) {
585 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
ee49b735 586 } else if ((family == 0x0001) && (subtype == 0x0003)) {
587 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 588 } else if ((family == 0x000d) && (subtype == 0x0009)) {
589 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
590 } else {
591 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
9de3ca7e 592 }
b8d0da45 593 break;
594 }
595 case AIM_CONN_TYPE_CHAT: {
596 u_short family, subtype;
597
598 family = aimutil_get16(workingPtr->data);
599 subtype= aimutil_get16(workingPtr->data+2);
600
22517493 601 if ((family == 0x0000) && (subtype == 0x00001)) {
602 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
603 } else if (family == 0x0001) {
b8d0da45 604 if (subtype == 0x0001)
605 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
606 else if (subtype == 0x0003)
ee49b735 607 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 608 else if (subtype == 0x0007)
609 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
275a2ff8 610 else if (subtype == 0x000a)
611 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
b8d0da45 612 else
cd71e19b 613 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
b8d0da45 614 } else if (family == 0x000e) {
615 if (subtype == 0x0002)
616 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
617 else if (subtype == 0x0003)
618 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
619 else if (subtype == 0x0004)
620 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
621 else if (subtype == 0x0006)
622 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
623 else
624 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
625 } else {
626 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
627 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
628 }
629 break;
630 }
b69540e3 631 case AIM_CONN_TYPE_RENDEZVOUS: {
632 /* make sure that we only get OFT frames on these connections */
633 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
634 printf("faim: internal error: non-OFT frames on OFT connection\n");
635 workingPtr->handled = 1; /* get rid of it */
636 break;
637 }
638
639 /* XXX: implement this */
640 printf("faim: OFT frame!\n");
641
642 break;
643 }
7392c79f 644 case AIM_CONN_TYPE_RENDEZVOUS_OUT: {
645 /* not possible */
646 break;
647 }
b8d0da45 648 default:
b69540e3 649 printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->commandlen);
b8d0da45 650 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
651 break;
652 }
9de3ca7e 653 }
b8d0da45 654 }
9de3ca7e 655
b8d0da45 656 /*
657 * This doesn't have to be called here. It could easily be done
658 * by a seperate thread or something. It's an administrative operation,
659 * and can take a while. Though the less you call it the less memory
660 * you'll have :)
661 */
662 aim_purge_rxqueue(sess);
9de3ca7e 663
664 return 0;
665}
666
78b3fb13 667faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 668{
669 rxcallback_t userfunc = NULL;
670 char sn[MAXSNLEN];
671 unsigned short type;
672 int i = 10+8; /* skip SNAC and cookie */
673 int ret = 1;
674 unsigned char snlen;
675
676 type = aimutil_get16(command->data+i);
677 i += 2;
678
679 snlen = aimutil_get8(command->data+i);
680 i++;
681
682 memset(sn, 0, sizeof(sn));
78b3fb13 683 strncpy(sn, (char *)command->data+i, snlen);
1a8c261b 684
685 if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c)))
686 ret = userfunc(sess, command, type, sn);
687
688 return ret;
689}
690
d6c9fcf0 691/*
692 * The Rate Limiting System, An Abridged Guide to Nonsense.
693 *
694 * OSCAR defines several 'rate classes'. Each class has seperate
695 * rate limiting properties (limit level, alert level, disconnect
696 * level, etc), and a set of SNAC family/type pairs associated with
697 * it. The rate classes, their limiting properties, and the definitions
698 * of which SNACs are belong to which class, are defined in the
699 * Rate Response packet at login to each host.
700 *
701 * Logically, all rate offenses within one class count against further
702 * offenses for other SNACs in the same class (ie, sending messages
703 * too fast will limit the number of user info requests you can send,
704 * since those two SNACs are in the same rate class).
705 *
706 * Since the rate classes are defined dynamically at login, the values
707 * below may change. But they seem to be fairly constant.
708 *
709 * Currently, BOS defines five rate classes, with the commonly used
710 * members as follows...
711 *
712 * Rate class 0x0001:
713 * - Everything thats not in any of the other classes
714 *
715 * Rate class 0x0002:
716 * - Buddy list add/remove
717 * - Permit list add/remove
718 * - Deny list add/remove
719 *
720 * Rate class 0x0003:
721 * - User information requests
722 * - Outgoing ICBMs
723 *
724 * Rate class 0x0004:
725 * - A few unknowns: 2/9, 2/b, and f/2
726 *
727 * Rate class 0x0005:
728 * - Chat room create
729 * - Outgoing chat ICBMs
730 *
731 * The only other thing of note is that class 5 (chat) has slightly looser
732 * limiting properties than class 3 (normal messages). But thats just a
733 * small bit of trivia for you.
734 *
735 * The last thing that needs to be learned about the rate limiting
736 * system is how the actual numbers relate to the passing of time. This
737 * seems to be a big mystery.
738 *
739 */
78b3fb13 740faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 741{
742 rxcallback_t userfunc = NULL;
1a8c261b 743 int ret = 1;
275a2ff8 744 int i;
745 int code;
d6c9fcf0 746 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 747 unsigned long currentavg, maxavg;
1a8c261b 748
275a2ff8 749 i = 10;
750
751 code = aimutil_get16(command->data+i);
752 i += 2;
753
d6c9fcf0 754 rateclass = aimutil_get16(command->data+i);
275a2ff8 755 i += 2;
756
757 windowsize = aimutil_get32(command->data+i);
758 i += 4;
759 clear = aimutil_get32(command->data+i);
760 i += 4;
761 alert = aimutil_get32(command->data+i);
762 i += 4;
763 limit = aimutil_get32(command->data+i);
764 i += 4;
765 disconnect = aimutil_get32(command->data+i);
766 i += 4;
767 currentavg = aimutil_get32(command->data+i);
768 i += 4;
769 maxavg = aimutil_get32(command->data+i);
770 i += 4;
1a8c261b 771
772 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a)))
d6c9fcf0 773 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
1a8c261b 774
775 return ret;
776}
777
78b3fb13 778faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
98c88242 779{
780 rxcallback_t userfunc = NULL;
06bc8607 781 int ret = 1;
782 int i;
783 unsigned short newevil;
784 struct aim_userinfo_s userinfo;
98c88242 785
06bc8607 786 i = 10;
787 newevil = aimutil_get16(command->data+10);
788 i += 2;
98c88242 789
06bc8607 790 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
791 if (command->commandlen-i)
792 i += aim_extractuserinfo(command->data+i, &userinfo);
98c88242 793
794 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010)))
06bc8607 795 ret = userfunc(sess, command, newevil, &userinfo);
98c88242 796
797 return ret;
798}
799
78b3fb13 800faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
801 struct command_rx_struct *command, ...)
9de3ca7e 802{
803 rxcallback_t userfunc = NULL;
01b59e1e 804 char *msg;
805 int ret=1;
806 struct aim_tlvlist_t *tlvlist;
807 u_short id;
808
809 /*
98c88242 810 * Code.
811 *
812 * Valid values:
813 * 1 Mandatory upgrade
814 * 2 Advisory upgrade
815 * 3 System bulletin
816 * 4 Nothing's wrong ("top o the world" -- normal)
817 *
01b59e1e 818 */
819 id = aimutil_get16(command->data+10);
820
821 /*
822 * TLVs follow
823 */
b13c9e13 824 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
825 return ret;
826
827 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
828 aim_freetlvchain(&tlvlist);
829 return ret;
830 }
01b59e1e 831
832 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
833 if (userfunc)
834 ret = userfunc(sess, command, id, msg);
9de3ca7e 835
01b59e1e 836 aim_freetlvchain(&tlvlist);
b13c9e13 837 free(msg);
9de3ca7e 838
b13c9e13 839 return ret;
9de3ca7e 840}
841
ee49b735 842faim_internal int aim_parse_hostonline(struct aim_session_t *sess,
843 struct command_rx_struct *command, ...)
844{
845 rxcallback_t userfunc = NULL;
846 int ret = 1;
847 unsigned short *families = NULL;
848 int famcount = 0, i;
849
850 famcount = (command->commandlen-10)/2;
851 if (!(families = malloc(command->commandlen-10)))
852 return ret;
853
854 for (i = 0; i < famcount; i++)
855 families[i] = aimutil_get16(command->data+((i*2)+10));
856
857 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0003)))
858 ret = userfunc(sess, command, famcount, families);
859
860 free(families);
861
862 return ret;
863}
864
64c78745 865faim_internal int aim_parse_accountconfirm(struct aim_session_t *sess,
866 struct command_rx_struct *command)
867{
868 rxcallback_t userfunc = NULL;
869 int ret = 1;
870 int status = -1;
871
872 status = aimutil_get16(command->data+10);
873
874 if ((userfunc = aim_callhandler(command->conn, 0x0007, 0x0007)))
875 ret = userfunc(sess, command, status);
876
877 return ret;
878}
879
880faim_internal int aim_parse_infochange(struct aim_session_t *sess,
881 struct command_rx_struct *command)
882{
883 unsigned short subtype; /* called for both reply and change-reply */
884 int i;
885
886 subtype = aimutil_get16(command->data+2);
887
888 /*
889 * struct {
890 * unsigned short perms;
891 * unsigned short tlvcount;
892 * aim_tlv_t tlvs[tlvcount];
893 * } admin_info[n];
894 */
895 for (i = 10; i < command->commandlen; ) {
896 int perms, tlvcount;
897
898 perms = aimutil_get16(command->data+i);
899 i += 2;
900
901 tlvcount = aimutil_get16(command->data+i);
902 i += 2;
903
904 while (tlvcount) {
905 rxcallback_t userfunc;
906 struct aim_tlv_t *tlv;
907 int str = 0;
908
909 if ((aimutil_get16(command->data+i) == 0x0011) ||
910 (aimutil_get16(command->data+i) == 0x0004))
911 str = 1;
912
913 if (str)
914 tlv = aim_grabtlvstr(command->data+i);
915 else
916 tlv = aim_grabtlv(command->data+i);
917
918 /* XXX fix so its only called once for the entire packet */
919 if ((userfunc = aim_callhandler(command->conn, 0x0007, subtype)))
920 userfunc(sess, command, perms, tlv->type, tlv->length, tlv->value, str);
921
922 if (tlv)
923 i += 2+2+tlv->length;
924
925 if (tlv && tlv->value)
926 free(tlv->value);
927 if (tlv)
928 free(tlv);
929
930 tlvcount--;
931 }
932 }
933
934 return 1;
935}
936
ee49b735 937faim_internal int aim_parse_hostversions(struct aim_session_t *sess,
938 struct command_rx_struct *command, ...)
939{
940 rxcallback_t userfunc = NULL;
941 int ret = 1;
942 int vercount;
943
944 vercount = (command->commandlen-10)/4;
945
946 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0018)))
947 ret = userfunc(sess, command, vercount, command->data+10);
948
949 return ret;
950}
951
78b3fb13 952faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
ee49b735 953 struct command_rx_struct *command, ...)
9de3ca7e 954{
1ea867e3 955 int serviceid = 0;
956 unsigned char *cookie = NULL;
9de3ca7e 957 char *ip = NULL;
958 rxcallback_t userfunc = NULL;
01b59e1e 959 struct aim_tlvlist_t *tlvlist;
960 int ret = 1;
961
1ea867e3 962 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
963
964 if (aim_gettlv(tlvlist, 0x000d, 1))
965 serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
966 if (aim_gettlv(tlvlist, 0x0005, 1))
967 ip = aim_gettlv_str(tlvlist, 0x0005, 1);
968 if (aim_gettlv(tlvlist, 0x0006, 1))
969 cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
970
971 if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
972
973 /*
974 * Chat hack.
975 *
976 */
977 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0005)))
978 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
0c20631f 979 free(sess->pendingjoin);
980 sess->pendingjoin = NULL;
9f20a4e3 981 sess->pendingjoinexchange = 0;
1ea867e3 982 } else if (!serviceid || !ip || !cookie) { /* yeep! */
983 ret = 1;
984 } else {
985 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0005)))
986 ret = userfunc(sess, command, serviceid, ip, cookie);
987 }
988
989 if (ip)
990 free(ip);
991 if (cookie)
992 free(cookie);
0e2be272 993
01b59e1e 994 aim_freetlvchain(&tlvlist);
995
996 return ret;
9de3ca7e 997}
998
78b3fb13 999faim_internal int aim_parse_unknown(struct aim_session_t *sess,
1000 struct command_rx_struct *command, ...)
9de3ca7e 1001{
1002 u_int i = 0;
1003
22517493 1004 if (!sess || !command)
1005 return 1;
1006
b8d0da45 1007 faimdprintf(1, "\nRecieved unknown packet:");
9de3ca7e 1008
1009 for (i = 0; i < command->commandlen; i++)
1010 {
1011 if ((i % 8) == 0)
71e609e9 1012 faimdprintf(1, "\n\t");
9de3ca7e 1013
71e609e9 1014 faimdprintf(1, "0x%2x ", command->data[i]);
9de3ca7e 1015 }
1016
b1a4ea45 1017 faimdprintf(1, "\n\n");
9de3ca7e 1018
1019 return 1;
1020}
1021
1022
78b3fb13 1023faim_internal int aim_negchan_middle(struct aim_session_t *sess,
1024 struct command_rx_struct *command)
5e02cf44 1025{
1026 struct aim_tlvlist_t *tlvlist;
1027 char *msg = NULL;
1028 unsigned short code = 0;
5e02cf44 1029 rxcallback_t userfunc = NULL;
1030 int ret = 1;
1031
1032 tlvlist = aim_readtlvchain(command->data, command->commandlen);
1033
1ea867e3 1034 if (aim_gettlv(tlvlist, 0x0009, 1))
1035 code = aim_gettlv16(tlvlist, 0x0009, 1);
5e02cf44 1036
1ea867e3 1037 if (aim_gettlv(tlvlist, 0x000b, 1))
5e02cf44 1038 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
1039
1ea867e3 1040 if ((userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
5e02cf44 1041 ret = userfunc(sess, command, code, msg);
1042
1043 aim_freetlvchain(&tlvlist);
1ea867e3 1044
1045 if (msg)
1046 free(msg);
5e02cf44 1047
1048 return ret;
1049}
1050
9de3ca7e 1051/*
1052 * aim_parse_generalerrs()
1053 *
1054 * Middle handler for 0x0001 snac of each family.
1055 *
1056 */
78b3fb13 1057faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
1058 struct command_rx_struct *command, ...)
9de3ca7e 1059{
1449ad2b 1060 unsigned short family;
1061 unsigned short subtype;
1062 int ret = 1;
1063 int error = 0;
1064 rxcallback_t userfunc = NULL;
a25832e6 1065
1066 family = aimutil_get16(command->data+0);
1067 subtype= aimutil_get16(command->data+2);
9de3ca7e 1068
1449ad2b 1069 if (command->commandlen > 10)
1070 error = aimutil_get16(command->data+10);
9de3ca7e 1071
1449ad2b 1072 if ((userfunc = aim_callhandler(command->conn, family, subtype)))
1073 ret = userfunc(sess, command, error);
1074
1075 return ret;
9de3ca7e 1076}
1077
1078
1079
This page took 1.120618 seconds and 5 git commands to generate.