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