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