]> andersk Git - libfaim.git/blame_incremental - aim_rxhandlers.c
- Thu Feb 8 02:31:25 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 case 0x0001:
375 if (subtype == 0x0003)
376 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
377 else
378 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
379 break;
380 case 0x0007:
381 if (subtype == 0x0005)
382 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
383 break;
384 case AIM_CB_FAM_SPECIAL:
385 if (subtype == AIM_CB_SPECIAL_DEBUGCONN_CONNECT) {
386 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
387 break;
388 } else
389 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
390 break;
391 default:
392 break;
393 }
394 }
395 break;
396 }
397 case AIM_CONN_TYPE_BOS: {
398 u_short family;
399 u_short subtype;
400
401 if (workingPtr->hdr.oscar.type == 0x04) {
402 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
403 break;
404 }
405
406 family = aimutil_get16(workingPtr->data);
407 subtype = aimutil_get16(workingPtr->data+2);
408
409 switch (family) {
410 case 0x0000: /* not really a family, but it works */
411 if (subtype == 0x0001)
412 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
413 else
414 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
415 break;
416 case 0x0001: /* Family: General */
417 switch (subtype) {
418 case 0x0001:
419 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
420 break;
421 case 0x0003:
422 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
423 break;
424 case 0x0005:
425 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
426 break;
427 case 0x0007:
428 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
429 break;
430 case 0x000a:
431 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
432 break;
433 case 0x000f:
434 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
435 break;
436 case 0x0010:
437 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
438 break;
439 case 0x0013:
440 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
441 break;
442 case 0x0018:
443 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
444 break;
445 default:
446 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
447 break;
448 }
449 break;
450 case 0x0002: /* Family: Location */
451 switch (subtype) {
452 case 0x0001:
453 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
454 break;
455 case 0x0003:
456 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
457 break;
458 case 0x0006:
459 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
460 break;
461 default:
462 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
463 break;
464 }
465 break;
466 case 0x0003: /* Family: Buddy List */
467 switch (subtype) {
468 case 0x0001:
469 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
470 break;
471 case 0x0003:
472 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
473 break;
474 case 0x000b: /* oncoming buddy */
475 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
476 break;
477 case 0x000c: /* offgoing buddy */
478 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
479 break;
480 default:
481 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
482 }
483 break;
484 case 0x0004: /* Family: Messaging */
485 switch (subtype) {
486 case 0x0001:
487 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
488 break;
489 case 0x0005:
490 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
491 break;
492 case 0x0006:
493 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
494 break;
495 case 0x0007:
496 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
497 break;
498 case 0x000a:
499 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
500 break;
501 case 0x000c:
502 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
503 break;
504 default:
505 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
506 }
507 break;
508 case 0x0009:
509 if (subtype == 0x0001)
510 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
511 else if (subtype == 0x0003)
512 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
513 else
514 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
515 break;
516 case 0x000a: /* Family: User lookup */
517 switch (subtype) {
518 case 0x0001:
519 workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
520 break;
521 case 0x0003:
522 workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
523 break;
524 default:
525 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
526 }
527 break;
528 case 0x000b: {
529 if (subtype == 0x0001)
530 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
531 else if (subtype == 0x0002)
532 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
533 else
534 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
535 break;
536 }
537 case 0x0013: {
538 printf("lalala: 0x%04x/0x%04x\n", family, subtype);
539 break;
540 }
541 case AIM_CB_FAM_SPECIAL:
542 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
543 break;
544 default:
545 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
546 break;
547 } /* switch(family) */
548 break;
549 } /* AIM_CONN_TYPE_BOS */
550 case AIM_CONN_TYPE_CHATNAV: {
551 u_short family;
552 u_short subtype;
553 family = aimutil_get16(workingPtr->data);
554 subtype= aimutil_get16(workingPtr->data+2);
555
556 if ((family == 0x0000) && (subtype == 0x00001)) {
557 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
558 } else if ((family == 0x0001) && (subtype == 0x0003)) {
559 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
560 } else if ((family == 0x000d) && (subtype == 0x0009)) {
561 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
562 } else {
563 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
564 }
565 break;
566 }
567 case AIM_CONN_TYPE_CHAT: {
568 u_short family, subtype;
569
570 family = aimutil_get16(workingPtr->data);
571 subtype= aimutil_get16(workingPtr->data+2);
572
573 if ((family == 0x0000) && (subtype == 0x00001)) {
574 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
575 } else if (family == 0x0001) {
576 if (subtype == 0x0001)
577 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
578 else if (subtype == 0x0003)
579 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
580 else if (subtype == 0x0007)
581 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
582 else if (subtype == 0x000a)
583 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
584 else
585 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
586 } else if (family == 0x000e) {
587 if (subtype == 0x0002)
588 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
589 else if (subtype == 0x0003)
590 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
591 else if (subtype == 0x0004)
592 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
593 else if (subtype == 0x0006)
594 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
595 else
596 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
597 } else {
598 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
599 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
600 }
601 break;
602 }
603 case AIM_CONN_TYPE_RENDEZVOUS: {
604 /* make sure that we only get OFT frames on these connections */
605 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
606 printf("faim: internal error: non-OFT frames on OFT connection\n");
607 workingPtr->handled = 1; /* get rid of it */
608 break;
609 }
610
611 /* XXX: implement this */
612 printf("faim: OFT frame!\n");
613
614 break;
615 }
616 case AIM_CONN_TYPE_RENDEZVOUS_OUT: {
617 /* not possible */
618 break;
619 }
620 default:
621 printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->commandlen);
622 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
623 break;
624 }
625 }
626 }
627
628 /*
629 * This doesn't have to be called here. It could easily be done
630 * by a seperate thread or something. It's an administrative operation,
631 * and can take a while. Though the less you call it the less memory
632 * you'll have :)
633 */
634 aim_purge_rxqueue(sess);
635
636 return 0;
637}
638
639faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
640{
641 rxcallback_t userfunc = NULL;
642 char sn[MAXSNLEN];
643 unsigned short type;
644 int i = 10+8; /* skip SNAC and cookie */
645 int ret = 1;
646 unsigned char snlen;
647
648 type = aimutil_get16(command->data+i);
649 i += 2;
650
651 snlen = aimutil_get8(command->data+i);
652 i++;
653
654 memset(sn, 0, sizeof(sn));
655 strncpy(sn, (char *)command->data+i, snlen);
656
657 if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c)))
658 ret = userfunc(sess, command, type, sn);
659
660 return ret;
661}
662
663/*
664 * The Rate Limiting System, An Abridged Guide to Nonsense.
665 *
666 * OSCAR defines several 'rate classes'. Each class has seperate
667 * rate limiting properties (limit level, alert level, disconnect
668 * level, etc), and a set of SNAC family/type pairs associated with
669 * it. The rate classes, their limiting properties, and the definitions
670 * of which SNACs are belong to which class, are defined in the
671 * Rate Response packet at login to each host.
672 *
673 * Logically, all rate offenses within one class count against further
674 * offenses for other SNACs in the same class (ie, sending messages
675 * too fast will limit the number of user info requests you can send,
676 * since those two SNACs are in the same rate class).
677 *
678 * Since the rate classes are defined dynamically at login, the values
679 * below may change. But they seem to be fairly constant.
680 *
681 * Currently, BOS defines five rate classes, with the commonly used
682 * members as follows...
683 *
684 * Rate class 0x0001:
685 * - Everything thats not in any of the other classes
686 *
687 * Rate class 0x0002:
688 * - Buddy list add/remove
689 * - Permit list add/remove
690 * - Deny list add/remove
691 *
692 * Rate class 0x0003:
693 * - User information requests
694 * - Outgoing ICBMs
695 *
696 * Rate class 0x0004:
697 * - A few unknowns: 2/9, 2/b, and f/2
698 *
699 * Rate class 0x0005:
700 * - Chat room create
701 * - Outgoing chat ICBMs
702 *
703 * The only other thing of note is that class 5 (chat) has slightly looser
704 * limiting properties than class 3 (normal messages). But thats just a
705 * small bit of trivia for you.
706 *
707 * The last thing that needs to be learned about the rate limiting
708 * system is how the actual numbers relate to the passing of time. This
709 * seems to be a big mystery.
710 *
711 */
712faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
713{
714 rxcallback_t userfunc = NULL;
715 int ret = 1;
716 int i;
717 int code;
718 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
719 unsigned long currentavg, maxavg;
720
721 i = 10;
722
723 code = aimutil_get16(command->data+i);
724 i += 2;
725
726 rateclass = aimutil_get16(command->data+i);
727 i += 2;
728
729 windowsize = aimutil_get32(command->data+i);
730 i += 4;
731 clear = aimutil_get32(command->data+i);
732 i += 4;
733 alert = aimutil_get32(command->data+i);
734 i += 4;
735 limit = aimutil_get32(command->data+i);
736 i += 4;
737 disconnect = aimutil_get32(command->data+i);
738 i += 4;
739 currentavg = aimutil_get32(command->data+i);
740 i += 4;
741 maxavg = aimutil_get32(command->data+i);
742 i += 4;
743
744 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a)))
745 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
746
747 return ret;
748}
749
750faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
751{
752 rxcallback_t userfunc = NULL;
753 int ret = 1;
754 int i;
755 unsigned short newevil;
756 struct aim_userinfo_s userinfo;
757
758 i = 10;
759 newevil = aimutil_get16(command->data+10);
760 i += 2;
761
762 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
763 if (command->commandlen-i)
764 i += aim_extractuserinfo(command->data+i, &userinfo);
765
766 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010)))
767 ret = userfunc(sess, command, newevil, &userinfo);
768
769 return ret;
770}
771
772faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
773 struct command_rx_struct *command, ...)
774{
775 rxcallback_t userfunc = NULL;
776 char *msg;
777 int ret=1;
778 struct aim_tlvlist_t *tlvlist;
779 u_short id;
780
781 /*
782 * Code.
783 *
784 * Valid values:
785 * 1 Mandatory upgrade
786 * 2 Advisory upgrade
787 * 3 System bulletin
788 * 4 Nothing's wrong ("top o the world" -- normal)
789 *
790 */
791 id = aimutil_get16(command->data+10);
792
793 /*
794 * TLVs follow
795 */
796 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
797 return ret;
798
799 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
800 aim_freetlvchain(&tlvlist);
801 return ret;
802 }
803
804 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
805 if (userfunc)
806 ret = userfunc(sess, command, id, msg);
807
808 aim_freetlvchain(&tlvlist);
809 free(msg);
810
811 return ret;
812}
813
814faim_internal int aim_parse_hostonline(struct aim_session_t *sess,
815 struct command_rx_struct *command, ...)
816{
817 rxcallback_t userfunc = NULL;
818 int ret = 1;
819 unsigned short *families = NULL;
820 int famcount = 0, i;
821
822 famcount = (command->commandlen-10)/2;
823 if (!(families = malloc(command->commandlen-10)))
824 return ret;
825
826 for (i = 0; i < famcount; i++)
827 families[i] = aimutil_get16(command->data+((i*2)+10));
828
829 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0003)))
830 ret = userfunc(sess, command, famcount, families);
831
832 free(families);
833
834 return ret;
835}
836
837faim_internal int aim_parse_hostversions(struct aim_session_t *sess,
838 struct command_rx_struct *command, ...)
839{
840 rxcallback_t userfunc = NULL;
841 int ret = 1;
842 int vercount;
843
844 vercount = (command->commandlen-10)/4;
845
846 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0018)))
847 ret = userfunc(sess, command, vercount, command->data+10);
848
849 return ret;
850}
851
852faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
853 struct command_rx_struct *command, ...)
854{
855 int serviceid = 0;
856 unsigned char *cookie = NULL;
857 char *ip = NULL;
858 rxcallback_t userfunc = NULL;
859 struct aim_tlvlist_t *tlvlist;
860 int ret = 1;
861
862 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
863
864 if (aim_gettlv(tlvlist, 0x000d, 1))
865 serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
866 if (aim_gettlv(tlvlist, 0x0005, 1))
867 ip = aim_gettlv_str(tlvlist, 0x0005, 1);
868 if (aim_gettlv(tlvlist, 0x0006, 1))
869 cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
870
871 if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
872
873 /*
874 * Chat hack.
875 *
876 */
877 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0005)))
878 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
879 free(sess->pendingjoin);
880 sess->pendingjoin = NULL;
881 sess->pendingjoinexchange = 0;
882 } else if (!serviceid || !ip || !cookie) { /* yeep! */
883 ret = 1;
884 } else {
885 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0005)))
886 ret = userfunc(sess, command, serviceid, ip, cookie);
887 }
888
889 if (ip)
890 free(ip);
891 if (cookie)
892 free(cookie);
893
894 aim_freetlvchain(&tlvlist);
895
896 return ret;
897}
898
899faim_internal int aim_parse_unknown(struct aim_session_t *sess,
900 struct command_rx_struct *command, ...)
901{
902 u_int i = 0;
903
904 if (!sess || !command)
905 return 1;
906
907 faimdprintf(1, "\nRecieved unknown packet:");
908
909 for (i = 0; i < command->commandlen; i++)
910 {
911 if ((i % 8) == 0)
912 faimdprintf(1, "\n\t");
913
914 faimdprintf(1, "0x%2x ", command->data[i]);
915 }
916
917 faimdprintf(1, "\n\n");
918
919 return 1;
920}
921
922
923faim_internal int aim_negchan_middle(struct aim_session_t *sess,
924 struct command_rx_struct *command)
925{
926 struct aim_tlvlist_t *tlvlist;
927 char *msg = NULL;
928 unsigned short code = 0;
929 rxcallback_t userfunc = NULL;
930 int ret = 1;
931
932 tlvlist = aim_readtlvchain(command->data, command->commandlen);
933
934 if (aim_gettlv(tlvlist, 0x0009, 1))
935 code = aim_gettlv16(tlvlist, 0x0009, 1);
936
937 if (aim_gettlv(tlvlist, 0x000b, 1))
938 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
939
940 if ((userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
941 ret = userfunc(sess, command, code, msg);
942
943 aim_freetlvchain(&tlvlist);
944
945 if (msg)
946 free(msg);
947
948 return ret;
949}
950
951/*
952 * aim_parse_generalerrs()
953 *
954 * Middle handler for 0x0001 snac of each family.
955 *
956 */
957faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
958 struct command_rx_struct *command, ...)
959{
960 unsigned short family;
961 unsigned short subtype;
962 int ret = 1;
963 int error = 0;
964 rxcallback_t userfunc = NULL;
965
966 family = aimutil_get16(command->data+0);
967 subtype= aimutil_get16(command->data+2);
968
969 if (command->commandlen > 10)
970 error = aimutil_get16(command->data+10);
971
972 if ((userfunc = aim_callhandler(command->conn, family, subtype)))
973 ret = userfunc(sess, command, error);
974
975 return ret;
976}
977
978
979
This page took 0.064801 seconds and 5 git commands to generate.