]> andersk Git - libfaim.git/blame_incremental - aim_rxhandlers.c
- Sun Feb 11 01:07:36 UTC 2001
[libfaim.git] / aim_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 <faim/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 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
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(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_conn_t *conn,
245 u_short family,
246 u_short type)
247{
248 struct aim_rxcblist_t *cur;
249
250 if (!conn)
251 return NULL;
252
253 faimdprintf(1, "aim_callhandler: calling for %04x/%04x\n", family, type);
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;
265
266 return aim_callhandler(conn, family, 0xffff);
267}
268
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)
274{
275 rxcallback_t userfunc = NULL;
276 userfunc = aim_callhandler(conn, family, type);
277 if (userfunc)
278 return userfunc(sess, ptr);
279 return 1; /* XXX */
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 */
305faim_export int aim_rxdispatch(struct aim_session_t *sess)
306{
307 int i = 0;
308 struct command_rx_struct *workingPtr = NULL;
309
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;
315 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
316 /*
317 * XXX: This is still fairly ugly.
318 */
319 if (workingPtr->handled)
320 continue;
321
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
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: {
347 unsigned long head;
348
349 head = aimutil_get32(workingPtr->data);
350 if ((head == 0x00000001) && (workingPtr->commandlen == 4)) {
351 faimdprintf(1, "got connection ack on auth line\n");
352 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
353 } else if (workingPtr->hdr.oscar.type == 0x04) {
354 /* Used only by the older login protocol */
355 workingPtr->handled = aim_authparse(sess, workingPtr);
356 } else {
357 unsigned short family,subtype;
358
359 family = aimutil_get16(workingPtr->data);
360 subtype = aimutil_get16(workingPtr->data+2);
361
362 switch (family) {
363 /* New login protocol */
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)
370 workingPtr->handled = aim_authkeyparse(sess, workingPtr);
371 else
372 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
373 break;
374
375 case 0x0001:
376 if (subtype == 0x0003)
377 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
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);
382 else
383 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0xffff, workingPtr);
384 break;
385
386 case 0x0007:
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);
393 break;
394
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;
402
403 default:
404 break;
405 }
406 }
407 break;
408 }
409 case AIM_CONN_TYPE_BOS: {
410 u_short family;
411 u_short subtype;
412
413 if (workingPtr->hdr.oscar.type == 0x04) {
414 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
415 break;
416 }
417
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)
424 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
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:
434 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
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:
443 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
444 break;
445 case 0x000f:
446 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
447 break;
448 case 0x0010:
449 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
450 break;
451 case 0x0013:
452 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
453 break;
454 case 0x0018:
455 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
456 break;
457 default:
458 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
459 break;
460 }
461 break;
462 case 0x0002: /* Family: Location */
463 switch (subtype) {
464 case 0x0001:
465 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
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 }
477 break;
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:
484 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
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;
496 case 0x0004: /* Family: Messaging */
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;
504 case 0x0006:
505 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
506 break;
507 case 0x0007:
508 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
509 break;
510 case 0x000a:
511 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
512 break;
513 case 0x000c:
514 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
515 break;
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)
524 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
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:
531 workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
532 break;
533 case 0x0003:
534 workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
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;
540 case 0x000b: {
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;
548 }
549 case 0x0013: {
550 printf("lalala: 0x%04x/0x%04x\n", family, subtype);
551 break;
552 }
553 case AIM_CB_FAM_SPECIAL:
554 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
555 break;
556 default:
557 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
558 break;
559 } /* switch(family) */
560 break;
561 } /* AIM_CONN_TYPE_BOS */
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 }
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);
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);
586 } else if ((family == 0x0001) && (subtype == 0x0003)) {
587 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
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);
592 }
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
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) {
604 if (subtype == 0x0001)
605 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
606 else if (subtype == 0x0003)
607 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
608 else if (subtype == 0x0007)
609 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
610 else if (subtype == 0x000a)
611 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
612 else
613 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
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 }
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 }
644 case AIM_CONN_TYPE_RENDEZVOUS_OUT: {
645 /* not possible */
646 break;
647 }
648 default:
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);
650 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
651 break;
652 }
653 }
654 }
655
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);
663
664 return 0;
665}
666
667faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
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));
683 strncpy(sn, (char *)command->data+i, snlen);
684
685 if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c)))
686 ret = userfunc(sess, command, type, sn);
687
688 return ret;
689}
690
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 */
740faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
741{
742 rxcallback_t userfunc = NULL;
743 int ret = 1;
744 int i;
745 int code;
746 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
747 unsigned long currentavg, maxavg;
748
749 i = 10;
750
751 code = aimutil_get16(command->data+i);
752 i += 2;
753
754 rateclass = aimutil_get16(command->data+i);
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;
771
772 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a)))
773 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
774
775 return ret;
776}
777
778faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
779{
780 rxcallback_t userfunc = NULL;
781 int ret = 1;
782 int i;
783 unsigned short newevil;
784 struct aim_userinfo_s userinfo;
785
786 i = 10;
787 newevil = aimutil_get16(command->data+10);
788 i += 2;
789
790 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
791 if (command->commandlen-i)
792 i += aim_extractuserinfo(command->data+i, &userinfo);
793
794 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010)))
795 ret = userfunc(sess, command, newevil, &userinfo);
796
797 return ret;
798}
799
800faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
801 struct command_rx_struct *command, ...)
802{
803 rxcallback_t userfunc = NULL;
804 char *msg;
805 int ret=1;
806 struct aim_tlvlist_t *tlvlist;
807 u_short id;
808
809 /*
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 *
818 */
819 id = aimutil_get16(command->data+10);
820
821 /*
822 * TLVs follow
823 */
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 }
831
832 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
833 if (userfunc)
834 ret = userfunc(sess, command, id, msg);
835
836 aim_freetlvchain(&tlvlist);
837 free(msg);
838
839 return ret;
840}
841
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
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
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
952faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
953 struct command_rx_struct *command, ...)
954{
955 int serviceid = 0;
956 unsigned char *cookie = NULL;
957 char *ip = NULL;
958 rxcallback_t userfunc = NULL;
959 struct aim_tlvlist_t *tlvlist;
960 int ret = 1;
961
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);
979 free(sess->pendingjoin);
980 sess->pendingjoin = NULL;
981 sess->pendingjoinexchange = 0;
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);
993
994 aim_freetlvchain(&tlvlist);
995
996 return ret;
997}
998
999faim_internal int aim_parse_unknown(struct aim_session_t *sess,
1000 struct command_rx_struct *command, ...)
1001{
1002 u_int i = 0;
1003
1004 if (!sess || !command)
1005 return 1;
1006
1007 faimdprintf(1, "\nRecieved unknown packet:");
1008
1009 for (i = 0; i < command->commandlen; i++)
1010 {
1011 if ((i % 8) == 0)
1012 faimdprintf(1, "\n\t");
1013
1014 faimdprintf(1, "0x%2x ", command->data[i]);
1015 }
1016
1017 faimdprintf(1, "\n\n");
1018
1019 return 1;
1020}
1021
1022
1023faim_internal int aim_negchan_middle(struct aim_session_t *sess,
1024 struct command_rx_struct *command)
1025{
1026 struct aim_tlvlist_t *tlvlist;
1027 char *msg = NULL;
1028 unsigned short code = 0;
1029 rxcallback_t userfunc = NULL;
1030 int ret = 1;
1031
1032 tlvlist = aim_readtlvchain(command->data, command->commandlen);
1033
1034 if (aim_gettlv(tlvlist, 0x0009, 1))
1035 code = aim_gettlv16(tlvlist, 0x0009, 1);
1036
1037 if (aim_gettlv(tlvlist, 0x000b, 1))
1038 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
1039
1040 if ((userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
1041 ret = userfunc(sess, command, code, msg);
1042
1043 aim_freetlvchain(&tlvlist);
1044
1045 if (msg)
1046 free(msg);
1047
1048 return ret;
1049}
1050
1051/*
1052 * aim_parse_generalerrs()
1053 *
1054 * Middle handler for 0x0001 snac of each family.
1055 *
1056 */
1057faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
1058 struct command_rx_struct *command, ...)
1059{
1060 unsigned short family;
1061 unsigned short subtype;
1062 int ret = 1;
1063 int error = 0;
1064 rxcallback_t userfunc = NULL;
1065
1066 family = aimutil_get16(command->data+0);
1067 subtype= aimutil_get16(command->data+2);
1068
1069 if (command->commandlen > 10)
1070 error = aimutil_get16(command->data+10);
1071
1072 if ((userfunc = aim_callhandler(command->conn, family, subtype)))
1073 ret = userfunc(sess, command, error);
1074
1075 return ret;
1076}
1077
1078
1079
This page took 1.441932 seconds and 5 git commands to generate.