]> andersk Git - libfaim.git/blame - src/rxhandlers.c
- Fri Mar 16 23:12:58 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
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))
646c6b52 178 faimdprintf(sess, 0, "bleck: null handler for %04x/%04x (%s)\n", family, subtype, literals[family][subtype+1]);
01b59e1e 179 else
646c6b52 180 faimdprintf(sess, 0, "bleck: null handler for %04x/%04x (no literal)\n",family,subtype);
01b59e1e 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
646c6b52 197 faimdprintf(sess, 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
646c6b52 244faim_internal rxcallback_t aim_callhandler(struct aim_session_t *sess,
245 struct aim_conn_t *conn,
246 unsigned short family,
247 unsigned short type)
9de3ca7e 248{
249 struct aim_rxcblist_t *cur;
250
251 if (!conn)
252 return NULL;
253
646c6b52 254 faimdprintf(sess, 1, "aim_callhandler: calling for %04x/%04x\n", family, type);
9de3ca7e 255
646c6b52 256 for (cur = conn->handlerlist; cur; cur = cur->next) {
257 if ((cur->family == family) && (cur->type == type))
258 return cur->handler;
259 }
9de3ca7e 260
646c6b52 261 if (type == AIM_CB_SPECIAL_DEFAULT) {
262 faimdprintf(sess, 1, "aim_callhandler: no default handler for family 0x%04x\n", family);
263 return NULL; /* prevent infinite recursion */
264 }
265
266 faimdprintf(sess, 1, "aim_callhandler: no handler for 0x%04x/0x%04x\n", family, type);
871e2fd0 267
646c6b52 268 return aim_callhandler(sess, conn, family, AIM_CB_SPECIAL_DEFAULT);
9de3ca7e 269}
270
78b3fb13 271faim_internal int aim_callhandler_noparam(struct aim_session_t *sess,
272 struct aim_conn_t *conn,
273 u_short family,
274 u_short type,
275 struct command_rx_struct *ptr)
9de3ca7e 276{
277 rxcallback_t userfunc = NULL;
646c6b52 278 userfunc = aim_callhandler(sess, conn, family, type);
9de3ca7e 279 if (userfunc)
a25832e6 280 return userfunc(sess, ptr);
b8d0da45 281 return 1; /* XXX */
9de3ca7e 282}
283
284/*
285 aim_rxdispatch()
286
287 Basically, heres what this should do:
288 1) Determine correct packet handler for this packet
289 2) Mark the packet handled (so it can be dequeued in purge_queue())
290 3) Send the packet to the packet handler
291 4) Go to next packet in the queue and start over
292 5) When done, run purge_queue() to purge handled commands
293
294 Note that any unhandlable packets should probably be left in the
295 queue. This is the best way to prevent data loss. This means
296 that a single packet may get looked at by this function multiple
297 times. This is more good than bad! This behavior may change.
298
299 Aren't queue's fun?
300
301 TODO: Get rid of all the ugly if's.
302 TODO: Clean up.
303 TODO: More support for mid-level handlers.
304 TODO: Allow for NULL handlers.
305
306 */
78b3fb13 307faim_export int aim_rxdispatch(struct aim_session_t *sess)
9de3ca7e 308{
309 int i = 0;
310 struct command_rx_struct *workingPtr = NULL;
311
b8d0da45 312 if (sess->queue_incoming == NULL) {
646c6b52 313 faimdprintf(sess, 1, "parse_generic: incoming packet queue empty.\n");
b8d0da45 314 return 0;
315 } else {
316 workingPtr = sess->queue_incoming;
50443ea0 317 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
bb010ae0 318 unsigned short family,subtype;
319
b8d0da45 320 /*
321 * XXX: This is still fairly ugly.
322 */
50443ea0 323 if (workingPtr->handled)
324 continue;
325
b69540e3 326 /*
327 * This is a debugging/sanity check only and probably could/should be removed
328 * for stable code.
329 */
330 if (((workingPtr->hdrtype == AIM_FRAMETYPE_OFT) &&
331 (workingPtr->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) ||
332 ((workingPtr->hdrtype == AIM_FRAMETYPE_OSCAR) &&
333 (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS))) {
646c6b52 334 faimdprintf(sess, 0, "rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type);
b69540e3 335 workingPtr->handled = 1;
336 continue;
337 }
338
bb010ae0 339 if (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
340 /* make sure that we only get OFT frames on these connections */
341 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
342 faimdprintf(sess, 0, "internal error: non-OFT frames on OFT connection\n");
343 workingPtr->handled = 1; /* get rid of it */
344 } else {
345 /* XXX: implement this */
346 faimdprintf(sess, 0, "faim: OFT frame!\n");
347 workingPtr->handled = 1; /* get rid of it */
b8d0da45 348 }
bb010ae0 349 continue;
b8d0da45 350 }
5e02cf44 351
bb010ae0 352 if (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
353 /* not possible */
354 faimdprintf(sess, 0, "rxdispatch called on RENDEZVOUS_OUT connection!\n");
355 workingPtr->handled = 1;
356 continue;
357 }
5e02cf44 358
bb010ae0 359 if ((workingPtr->commandlen == 4) &&
360 (aimutil_get32(workingPtr->data) == 0x00000001)) {
361 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
362 continue;
363 }
64c78745 364
bb010ae0 365 if (workingPtr->hdr.oscar.type == 0x04) {
366 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
367 continue;
368 }
369
370 family = aimutil_get16(workingPtr->data);
371 subtype = aimutil_get16(workingPtr->data+2);
372
373 if (family == 0x0001) {
64c78745 374
bb010ae0 375 if (subtype == 0x0001)
376 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
377 else if (subtype == 0x0003)
64c78745 378 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
bb010ae0 379 else if (subtype == 0x0005)
380 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
381 else if (subtype == 0x0007)
382 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
383 else if (subtype == 0x000a)
384 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
385 else if (subtype == 0x000f)
386 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
387 else if (subtype == 0x0010)
388 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
389 else if (subtype == 0x0013)
390 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
391 else if (subtype == 0x0018)
392 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
393 else
394 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0xffff, workingPtr);
395
396 } else if (family == 0x0002) {
397
398 if (subtype == 0x0001)
399 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
400 else if (subtype == 0x0003)
401 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
402 else if (subtype == 0x0006)
403 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
404 else
405 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
406
407 } else if (family == 0x0003) {
408
409 if (subtype == 0x0001)
410 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
411 else if (subtype == 0x0003)
412 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
413 else if (subtype == 0x000b)
414 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
415 else if (subtype == 0x000c)
416 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
417 else
418 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
419
420 } else if (family == 0x0004) {
421
422 if (subtype == 0x0001)
423 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
424 else if (subtype == 0x0005)
425 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
426 else if (subtype == 0x0006)
427 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
428 else if (subtype == 0x0007)
429 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
430 else if (subtype == 0x000a)
431 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
432 else if (subtype == 0x000c)
433 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
434 else
435 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
436
437 } else if (family == 0x0007) {
438
439 if (subtype == 0x0003)
440 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
441 else if (subtype == 0x0005)
442 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
443 else if (subtype == 0x0007)
444 workingPtr->handled = aim_parse_accountconfirm(sess, workingPtr);
64c78745 445 break;
bb010ae0 446
447 } else if (family == 0x0009) {
448
449 if (subtype == 0x0001)
450 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
451 else if (subtype == 0x0003)
452 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
453 else
454 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
455
456 } else if (family == 0x000a) {
457
458 if (subtype == 0x0001)
459 workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
460 else if (subtype == 0x0003)
461 workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
462 else
463 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
464
465 } else if (family == 0x000b) {
466
467 if (subtype == 0x0001)
468 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
469 else if (subtype == 0x0002)
470 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
471 else
472 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
473
474 } else if (family == 0x000d) {
475
476 if (subtype == 0x0009)
b8d0da45 477 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
bb010ae0 478
479 } else if (family == 0x000e) {
480
481 if (subtype == 0x0002)
482 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
483 else if (subtype == 0x0003)
484 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
485 else if (subtype == 0x0004)
486 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
487 else if (subtype == 0x0006)
488 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
489
490 } else if (family == 0x0013) {
491
492 faimdprintf(sess, 0, "lalala: 0x%04x/0x%04x\n", family, subtype);
493
494 } else if (family == 0x0017) { /* New login protocol */
495
496 if (subtype == 0x0001)
497 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
498 else if (subtype == 0x0003)
499 workingPtr->handled = aim_authparse(sess, workingPtr);
500 else if (subtype == 0x0007)
501 workingPtr->handled = aim_authkeyparse(sess, workingPtr);
502 else
503 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
504
505 } else if (family == AIM_CB_FAM_SPECIAL) {
506
507 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
508
7392c79f 509 }
9de3ca7e 510 }
b8d0da45 511 }
9de3ca7e 512
b8d0da45 513 /*
514 * This doesn't have to be called here. It could easily be done
515 * by a seperate thread or something. It's an administrative operation,
516 * and can take a while. Though the less you call it the less memory
517 * you'll have :)
518 */
519 aim_purge_rxqueue(sess);
9de3ca7e 520
521 return 0;
522}
523
78b3fb13 524faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 525{
526 rxcallback_t userfunc = NULL;
527 char sn[MAXSNLEN];
528 unsigned short type;
529 int i = 10+8; /* skip SNAC and cookie */
530 int ret = 1;
531 unsigned char snlen;
532
533 type = aimutil_get16(command->data+i);
534 i += 2;
535
536 snlen = aimutil_get8(command->data+i);
537 i++;
538
539 memset(sn, 0, sizeof(sn));
78b3fb13 540 strncpy(sn, (char *)command->data+i, snlen);
1a8c261b 541
646c6b52 542 if ((userfunc = aim_callhandler(sess, command->conn, 0x0004, 0x000c)))
1a8c261b 543 ret = userfunc(sess, command, type, sn);
544
545 return ret;
546}
547
d6c9fcf0 548/*
549 * The Rate Limiting System, An Abridged Guide to Nonsense.
550 *
551 * OSCAR defines several 'rate classes'. Each class has seperate
552 * rate limiting properties (limit level, alert level, disconnect
553 * level, etc), and a set of SNAC family/type pairs associated with
554 * it. The rate classes, their limiting properties, and the definitions
555 * of which SNACs are belong to which class, are defined in the
556 * Rate Response packet at login to each host.
557 *
558 * Logically, all rate offenses within one class count against further
559 * offenses for other SNACs in the same class (ie, sending messages
560 * too fast will limit the number of user info requests you can send,
561 * since those two SNACs are in the same rate class).
562 *
563 * Since the rate classes are defined dynamically at login, the values
564 * below may change. But they seem to be fairly constant.
565 *
566 * Currently, BOS defines five rate classes, with the commonly used
567 * members as follows...
568 *
569 * Rate class 0x0001:
570 * - Everything thats not in any of the other classes
571 *
572 * Rate class 0x0002:
573 * - Buddy list add/remove
574 * - Permit list add/remove
575 * - Deny list add/remove
576 *
577 * Rate class 0x0003:
578 * - User information requests
579 * - Outgoing ICBMs
580 *
581 * Rate class 0x0004:
582 * - A few unknowns: 2/9, 2/b, and f/2
583 *
584 * Rate class 0x0005:
585 * - Chat room create
586 * - Outgoing chat ICBMs
587 *
588 * The only other thing of note is that class 5 (chat) has slightly looser
589 * limiting properties than class 3 (normal messages). But thats just a
590 * small bit of trivia for you.
591 *
592 * The last thing that needs to be learned about the rate limiting
593 * system is how the actual numbers relate to the passing of time. This
594 * seems to be a big mystery.
595 *
596 */
78b3fb13 597faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 598{
599 rxcallback_t userfunc = NULL;
1a8c261b 600 int ret = 1;
275a2ff8 601 int i;
602 int code;
d6c9fcf0 603 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 604 unsigned long currentavg, maxavg;
1a8c261b 605
275a2ff8 606 i = 10;
607
608 code = aimutil_get16(command->data+i);
609 i += 2;
610
d6c9fcf0 611 rateclass = aimutil_get16(command->data+i);
275a2ff8 612 i += 2;
613
614 windowsize = aimutil_get32(command->data+i);
615 i += 4;
616 clear = aimutil_get32(command->data+i);
617 i += 4;
618 alert = aimutil_get32(command->data+i);
619 i += 4;
620 limit = aimutil_get32(command->data+i);
621 i += 4;
622 disconnect = aimutil_get32(command->data+i);
623 i += 4;
624 currentavg = aimutil_get32(command->data+i);
625 i += 4;
626 maxavg = aimutil_get32(command->data+i);
627 i += 4;
1a8c261b 628
646c6b52 629 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x000a)))
d6c9fcf0 630 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
1a8c261b 631
632 return ret;
633}
634
78b3fb13 635faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
98c88242 636{
637 rxcallback_t userfunc = NULL;
06bc8607 638 int ret = 1;
639 int i;
640 unsigned short newevil;
641 struct aim_userinfo_s userinfo;
98c88242 642
06bc8607 643 i = 10;
644 newevil = aimutil_get16(command->data+10);
645 i += 2;
98c88242 646
06bc8607 647 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
648 if (command->commandlen-i)
646c6b52 649 i += aim_extractuserinfo(sess, command->data+i, &userinfo);
98c88242 650
646c6b52 651 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0010)))
06bc8607 652 ret = userfunc(sess, command, newevil, &userinfo);
98c88242 653
654 return ret;
655}
656
78b3fb13 657faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
658 struct command_rx_struct *command, ...)
9de3ca7e 659{
660 rxcallback_t userfunc = NULL;
01b59e1e 661 char *msg;
662 int ret=1;
663 struct aim_tlvlist_t *tlvlist;
664 u_short id;
665
666 /*
98c88242 667 * Code.
668 *
669 * Valid values:
670 * 1 Mandatory upgrade
671 * 2 Advisory upgrade
672 * 3 System bulletin
673 * 4 Nothing's wrong ("top o the world" -- normal)
674 *
01b59e1e 675 */
676 id = aimutil_get16(command->data+10);
677
678 /*
679 * TLVs follow
680 */
b13c9e13 681 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
682 return ret;
683
684 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
685 aim_freetlvchain(&tlvlist);
686 return ret;
687 }
01b59e1e 688
646c6b52 689 userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0013);
01b59e1e 690 if (userfunc)
691 ret = userfunc(sess, command, id, msg);
9de3ca7e 692
01b59e1e 693 aim_freetlvchain(&tlvlist);
b13c9e13 694 free(msg);
9de3ca7e 695
b13c9e13 696 return ret;
9de3ca7e 697}
698
ee49b735 699faim_internal int aim_parse_hostonline(struct aim_session_t *sess,
700 struct command_rx_struct *command, ...)
701{
702 rxcallback_t userfunc = NULL;
703 int ret = 1;
704 unsigned short *families = NULL;
705 int famcount = 0, i;
706
707 famcount = (command->commandlen-10)/2;
708 if (!(families = malloc(command->commandlen-10)))
709 return ret;
710
711 for (i = 0; i < famcount; i++)
712 families[i] = aimutil_get16(command->data+((i*2)+10));
713
646c6b52 714 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0003)))
ee49b735 715 ret = userfunc(sess, command, famcount, families);
716
717 free(families);
718
719 return ret;
720}
721
64c78745 722faim_internal int aim_parse_accountconfirm(struct aim_session_t *sess,
723 struct command_rx_struct *command)
724{
725 rxcallback_t userfunc = NULL;
726 int ret = 1;
727 int status = -1;
728
729 status = aimutil_get16(command->data+10);
730
646c6b52 731 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, 0x0007)))
64c78745 732 ret = userfunc(sess, command, status);
733
734 return ret;
735}
736
737faim_internal int aim_parse_infochange(struct aim_session_t *sess,
738 struct command_rx_struct *command)
739{
740 unsigned short subtype; /* called for both reply and change-reply */
741 int i;
742
743 subtype = aimutil_get16(command->data+2);
744
745 /*
746 * struct {
747 * unsigned short perms;
748 * unsigned short tlvcount;
749 * aim_tlv_t tlvs[tlvcount];
750 * } admin_info[n];
751 */
752 for (i = 10; i < command->commandlen; ) {
753 int perms, tlvcount;
754
755 perms = aimutil_get16(command->data+i);
756 i += 2;
757
758 tlvcount = aimutil_get16(command->data+i);
759 i += 2;
760
761 while (tlvcount) {
762 rxcallback_t userfunc;
763 struct aim_tlv_t *tlv;
764 int str = 0;
765
766 if ((aimutil_get16(command->data+i) == 0x0011) ||
767 (aimutil_get16(command->data+i) == 0x0004))
768 str = 1;
769
770 if (str)
771 tlv = aim_grabtlvstr(command->data+i);
772 else
773 tlv = aim_grabtlv(command->data+i);
774
775 /* XXX fix so its only called once for the entire packet */
646c6b52 776 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, subtype)))
64c78745 777 userfunc(sess, command, perms, tlv->type, tlv->length, tlv->value, str);
778
779 if (tlv)
780 i += 2+2+tlv->length;
781
782 if (tlv && tlv->value)
783 free(tlv->value);
784 if (tlv)
785 free(tlv);
786
787 tlvcount--;
788 }
789 }
790
791 return 1;
792}
793
ee49b735 794faim_internal int aim_parse_hostversions(struct aim_session_t *sess,
795 struct command_rx_struct *command, ...)
796{
797 rxcallback_t userfunc = NULL;
798 int ret = 1;
799 int vercount;
800
801 vercount = (command->commandlen-10)/4;
802
646c6b52 803 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0018)))
ee49b735 804 ret = userfunc(sess, command, vercount, command->data+10);
805
806 return ret;
807}
808
78b3fb13 809faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
ee49b735 810 struct command_rx_struct *command, ...)
9de3ca7e 811{
1ea867e3 812 int serviceid = 0;
813 unsigned char *cookie = NULL;
9de3ca7e 814 char *ip = NULL;
815 rxcallback_t userfunc = NULL;
01b59e1e 816 struct aim_tlvlist_t *tlvlist;
817 int ret = 1;
818
1ea867e3 819 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
820
821 if (aim_gettlv(tlvlist, 0x000d, 1))
822 serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
823 if (aim_gettlv(tlvlist, 0x0005, 1))
824 ip = aim_gettlv_str(tlvlist, 0x0005, 1);
825 if (aim_gettlv(tlvlist, 0x0006, 1))
826 cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
827
828 if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
829
830 /*
831 * Chat hack.
832 *
833 */
646c6b52 834 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
1ea867e3 835 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
0c20631f 836 free(sess->pendingjoin);
837 sess->pendingjoin = NULL;
9f20a4e3 838 sess->pendingjoinexchange = 0;
1ea867e3 839 } else if (!serviceid || !ip || !cookie) { /* yeep! */
840 ret = 1;
841 } else {
646c6b52 842 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
1ea867e3 843 ret = userfunc(sess, command, serviceid, ip, cookie);
844 }
845
846 if (ip)
847 free(ip);
848 if (cookie)
849 free(cookie);
0e2be272 850
01b59e1e 851 aim_freetlvchain(&tlvlist);
852
853 return ret;
9de3ca7e 854}
855
78b3fb13 856faim_internal int aim_parse_unknown(struct aim_session_t *sess,
857 struct command_rx_struct *command, ...)
9de3ca7e 858{
859 u_int i = 0;
860
22517493 861 if (!sess || !command)
862 return 1;
863
646c6b52 864 faimdprintf(sess, 1, "\nRecieved unknown packet:");
9de3ca7e 865
866 for (i = 0; i < command->commandlen; i++)
867 {
868 if ((i % 8) == 0)
646c6b52 869 faimdprintf(sess, 1, "\n\t");
9de3ca7e 870
646c6b52 871 faimdprintf(sess, 1, "0x%2x ", command->data[i]);
9de3ca7e 872 }
873
646c6b52 874 faimdprintf(sess, 1, "\n\n");
9de3ca7e 875
876 return 1;
877}
878
879
78b3fb13 880faim_internal int aim_negchan_middle(struct aim_session_t *sess,
881 struct command_rx_struct *command)
5e02cf44 882{
883 struct aim_tlvlist_t *tlvlist;
884 char *msg = NULL;
885 unsigned short code = 0;
5e02cf44 886 rxcallback_t userfunc = NULL;
887 int ret = 1;
888
bb010ae0 889 /* Used only by the older login protocol */
890 /* XXX remove this special case? */
891 if (command->conn->type == AIM_CONN_TYPE_AUTH)
892 return aim_authparse(sess, command);
893
5e02cf44 894 tlvlist = aim_readtlvchain(command->data, command->commandlen);
895
1ea867e3 896 if (aim_gettlv(tlvlist, 0x0009, 1))
897 code = aim_gettlv16(tlvlist, 0x0009, 1);
5e02cf44 898
1ea867e3 899 if (aim_gettlv(tlvlist, 0x000b, 1))
5e02cf44 900 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
901
646c6b52 902 if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
5e02cf44 903 ret = userfunc(sess, command, code, msg);
904
905 aim_freetlvchain(&tlvlist);
1ea867e3 906
907 if (msg)
908 free(msg);
5e02cf44 909
910 return ret;
911}
912
9de3ca7e 913/*
914 * aim_parse_generalerrs()
915 *
916 * Middle handler for 0x0001 snac of each family.
917 *
918 */
78b3fb13 919faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
920 struct command_rx_struct *command, ...)
9de3ca7e 921{
1449ad2b 922 unsigned short family;
923 unsigned short subtype;
924 int ret = 1;
925 int error = 0;
926 rxcallback_t userfunc = NULL;
a25832e6 927
928 family = aimutil_get16(command->data+0);
929 subtype= aimutil_get16(command->data+2);
9de3ca7e 930
1449ad2b 931 if (command->commandlen > 10)
932 error = aimutil_get16(command->data+10);
9de3ca7e 933
646c6b52 934 if ((userfunc = aim_callhandler(sess, command->conn, family, subtype)))
1449ad2b 935 ret = userfunc(sess, command, error);
936
937 return ret;
9de3ca7e 938}
939
940
941
This page took 0.352899 seconds and 5 git commands to generate.