]> andersk Git - libfaim.git/blame_incremental - src/rxhandlers.c
- Fri Mar 16 23:12:58 UTC 2001
[libfaim.git] / src / rxhandlers.c
... / ...
CommitLineData
1/*
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 *
8 */
9
10#define FAIM_INTERNAL
11#include <aim.h>
12
13/*
14 * Bleck functions get called when there's no non-bleck functions
15 * around to cleanup the mess...
16 */
17faim_internal int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
18{
19 u_short family;
20 u_short subtype;
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 faimdprintf(sess, 0, "bleck: null handler for %04x/%04x (%s)\n", family, subtype, literals[family][subtype+1]);
179 else
180 faimdprintf(sess, 0, "bleck: null handler for %04x/%04x (no literal)\n",family,subtype);
181
182 return 1;
183}
184
185faim_export int aim_conn_addhandler(struct aim_session_t *sess,
186 struct aim_conn_t *conn,
187 u_short family,
188 u_short type,
189 rxcallback_t newhandler,
190 u_short flags)
191{
192 struct aim_rxcblist_t *newcb;
193
194 if (!conn)
195 return -1;
196
197 faimdprintf(sess, 1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
198
199 if (!(newcb = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t))))
200 return -1;
201 newcb->family = family;
202 newcb->type = type;
203 newcb->flags = flags;
204 if (!newhandler)
205 newcb->handler = &bleck;
206 else
207 newcb->handler = newhandler;
208 newcb->next = NULL;
209
210 if (!conn->handlerlist)
211 conn->handlerlist = newcb;
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 }
221
222 return 0;
223}
224
225faim_export int aim_clearhandlers(struct aim_conn_t *conn)
226{
227 struct aim_rxcblist_t *cur;
228
229 if (!conn)
230 return -1;
231
232 for (cur = conn->handlerlist; cur; ) {
233 struct aim_rxcblist_t *tmp;
234
235 tmp = cur->next;
236 free(cur);
237 cur = tmp;
238 }
239 conn->handlerlist = NULL;
240
241 return 0;
242}
243
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)
248{
249 struct aim_rxcblist_t *cur;
250
251 if (!conn)
252 return NULL;
253
254 faimdprintf(sess, 1, "aim_callhandler: calling for %04x/%04x\n", family, type);
255
256 for (cur = conn->handlerlist; cur; cur = cur->next) {
257 if ((cur->family == family) && (cur->type == type))
258 return cur->handler;
259 }
260
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);
267
268 return aim_callhandler(sess, conn, family, AIM_CB_SPECIAL_DEFAULT);
269}
270
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)
276{
277 rxcallback_t userfunc = NULL;
278 userfunc = aim_callhandler(sess, conn, family, type);
279 if (userfunc)
280 return userfunc(sess, ptr);
281 return 1; /* XXX */
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 */
307faim_export int aim_rxdispatch(struct aim_session_t *sess)
308{
309 int i = 0;
310 struct command_rx_struct *workingPtr = NULL;
311
312 if (sess->queue_incoming == NULL) {
313 faimdprintf(sess, 1, "parse_generic: incoming packet queue empty.\n");
314 return 0;
315 } else {
316 workingPtr = sess->queue_incoming;
317 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
318 unsigned short family,subtype;
319
320 /*
321 * XXX: This is still fairly ugly.
322 */
323 if (workingPtr->handled)
324 continue;
325
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))) {
334 faimdprintf(sess, 0, "rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type);
335 workingPtr->handled = 1;
336 continue;
337 }
338
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 */
348 }
349 continue;
350 }
351
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 }
358
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 }
364
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) {
374
375 if (subtype == 0x0001)
376 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
377 else if (subtype == 0x0003)
378 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
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);
445 break;
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)
477 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
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
509 }
510 }
511 }
512
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);
520
521 return 0;
522}
523
524faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
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));
540 strncpy(sn, (char *)command->data+i, snlen);
541
542 if ((userfunc = aim_callhandler(sess, command->conn, 0x0004, 0x000c)))
543 ret = userfunc(sess, command, type, sn);
544
545 return ret;
546}
547
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 */
597faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
598{
599 rxcallback_t userfunc = NULL;
600 int ret = 1;
601 int i;
602 int code;
603 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
604 unsigned long currentavg, maxavg;
605
606 i = 10;
607
608 code = aimutil_get16(command->data+i);
609 i += 2;
610
611 rateclass = aimutil_get16(command->data+i);
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;
628
629 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x000a)))
630 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
631
632 return ret;
633}
634
635faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
636{
637 rxcallback_t userfunc = NULL;
638 int ret = 1;
639 int i;
640 unsigned short newevil;
641 struct aim_userinfo_s userinfo;
642
643 i = 10;
644 newevil = aimutil_get16(command->data+10);
645 i += 2;
646
647 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
648 if (command->commandlen-i)
649 i += aim_extractuserinfo(sess, command->data+i, &userinfo);
650
651 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0010)))
652 ret = userfunc(sess, command, newevil, &userinfo);
653
654 return ret;
655}
656
657faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
658 struct command_rx_struct *command, ...)
659{
660 rxcallback_t userfunc = NULL;
661 char *msg;
662 int ret=1;
663 struct aim_tlvlist_t *tlvlist;
664 u_short id;
665
666 /*
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 *
675 */
676 id = aimutil_get16(command->data+10);
677
678 /*
679 * TLVs follow
680 */
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 }
688
689 userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0013);
690 if (userfunc)
691 ret = userfunc(sess, command, id, msg);
692
693 aim_freetlvchain(&tlvlist);
694 free(msg);
695
696 return ret;
697}
698
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
714 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0003)))
715 ret = userfunc(sess, command, famcount, families);
716
717 free(families);
718
719 return ret;
720}
721
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
731 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, 0x0007)))
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 */
776 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, subtype)))
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
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
803 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0018)))
804 ret = userfunc(sess, command, vercount, command->data+10);
805
806 return ret;
807}
808
809faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
810 struct command_rx_struct *command, ...)
811{
812 int serviceid = 0;
813 unsigned char *cookie = NULL;
814 char *ip = NULL;
815 rxcallback_t userfunc = NULL;
816 struct aim_tlvlist_t *tlvlist;
817 int ret = 1;
818
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 */
834 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
835 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
836 free(sess->pendingjoin);
837 sess->pendingjoin = NULL;
838 sess->pendingjoinexchange = 0;
839 } else if (!serviceid || !ip || !cookie) { /* yeep! */
840 ret = 1;
841 } else {
842 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
843 ret = userfunc(sess, command, serviceid, ip, cookie);
844 }
845
846 if (ip)
847 free(ip);
848 if (cookie)
849 free(cookie);
850
851 aim_freetlvchain(&tlvlist);
852
853 return ret;
854}
855
856faim_internal int aim_parse_unknown(struct aim_session_t *sess,
857 struct command_rx_struct *command, ...)
858{
859 u_int i = 0;
860
861 if (!sess || !command)
862 return 1;
863
864 faimdprintf(sess, 1, "\nRecieved unknown packet:");
865
866 for (i = 0; i < command->commandlen; i++)
867 {
868 if ((i % 8) == 0)
869 faimdprintf(sess, 1, "\n\t");
870
871 faimdprintf(sess, 1, "0x%2x ", command->data[i]);
872 }
873
874 faimdprintf(sess, 1, "\n\n");
875
876 return 1;
877}
878
879
880faim_internal int aim_negchan_middle(struct aim_session_t *sess,
881 struct command_rx_struct *command)
882{
883 struct aim_tlvlist_t *tlvlist;
884 char *msg = NULL;
885 unsigned short code = 0;
886 rxcallback_t userfunc = NULL;
887 int ret = 1;
888
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
894 tlvlist = aim_readtlvchain(command->data, command->commandlen);
895
896 if (aim_gettlv(tlvlist, 0x0009, 1))
897 code = aim_gettlv16(tlvlist, 0x0009, 1);
898
899 if (aim_gettlv(tlvlist, 0x000b, 1))
900 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
901
902 if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
903 ret = userfunc(sess, command, code, msg);
904
905 aim_freetlvchain(&tlvlist);
906
907 if (msg)
908 free(msg);
909
910 return ret;
911}
912
913/*
914 * aim_parse_generalerrs()
915 *
916 * Middle handler for 0x0001 snac of each family.
917 *
918 */
919faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
920 struct command_rx_struct *command, ...)
921{
922 unsigned short family;
923 unsigned short subtype;
924 int ret = 1;
925 int error = 0;
926 rxcallback_t userfunc = NULL;
927
928 family = aimutil_get16(command->data+0);
929 subtype= aimutil_get16(command->data+2);
930
931 if (command->commandlen > 10)
932 error = aimutil_get16(command->data+10);
933
934 if ((userfunc = aim_callhandler(sess, command->conn, family, subtype)))
935 ret = userfunc(sess, command, error);
936
937 return ret;
938}
939
940
941
This page took 0.322102 seconds and 5 git commands to generate.