]> andersk Git - libfaim.git/blame - aim_rxhandlers.c
- Fri Feb 9 22:31:22 UTC 2001
[libfaim.git] / aim_rxhandlers.c
CommitLineData
9de3ca7e 1/*
24286d93 2 * aim_rxhandlers.c
3 *
4 * This file contains most all of the incoming packet handlers, along
5 * with aim_rxdispatch(), the Rx dispatcher. Queue/list management is
6 * actually done in aim_rxqueue.c.
7 *
9de3ca7e 8 */
9
37ee990e 10#define FAIM_INTERNAL
a25832e6 11#include <faim/aim.h>
9de3ca7e 12
24286d93 13/*
14 * Bleck functions get called when there's no non-bleck functions
15 * around to cleanup the mess...
16 */
78b3fb13 17faim_internal int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
9de3ca7e 18{
19 u_short family;
20 u_short subtype;
01b59e1e 21
22 u_short maxf;
23 u_short maxs;
24
25 /* XXX: this is ugly. and big just for debugging. */
26 char *literals[14][25] = {
27 {"Invalid",
28 NULL
29 },
30 {"General",
31 "Invalid",
32 "Error",
33 "Client Ready",
34 "Server Ready",
35 "Service Request",
36 "Redirect",
37 "Rate Information Request",
38 "Rate Information",
39 "Rate Information Ack",
40 NULL,
41 "Rate Information Change",
42 "Server Pause",
43 NULL,
44 "Server Resume",
45 "Request Personal User Information",
46 "Personal User Information",
47 "Evil Notification",
48 NULL,
49 "Migration notice",
50 "Message of the Day",
51 "Set Privacy Flags",
52 "Well Known URL",
53 "NOP"
54 },
55 {"Location",
56 "Invalid",
57 "Error",
58 "Request Rights",
59 "Rights Information",
60 "Set user information",
61 "Request User Information",
62 "User Information",
63 "Watcher Sub Request",
64 "Watcher Notification"
65 },
66 {"Buddy List Management",
67 "Invalid",
68 "Error",
69 "Request Rights",
70 "Rights Information",
71 "Add Buddy",
72 "Remove Buddy",
73 "Watcher List Query",
74 "Watcher List Response",
75 "Watcher SubRequest",
76 "Watcher Notification",
77 "Reject Notification",
78 "Oncoming Buddy",
79 "Offgoing Buddy"
80 },
81 {"Messeging",
82 "Invalid",
83 "Error",
84 "Add ICBM Parameter",
85 "Remove ICBM Parameter",
86 "Request Parameter Information",
87 "Parameter Information",
88 "Outgoing Message",
89 "Incoming Message",
90 "Evil Request",
91 "Evil Reply",
92 "Missed Calls",
93 "Message Error",
94 "Host Ack"
95 },
96 {"Advertisements",
97 "Invalid",
98 "Error",
99 "Request Ad",
100 "Ad Data (GIFs)"
101 },
102 {"Invitation / Client-to-Client",
103 "Invalid",
104 "Error",
105 "Invite a Friend",
106 "Invitation Ack"
107 },
108 {"Administrative",
109 "Invalid",
110 "Error",
111 "Information Request",
112 "Information Reply",
113 "Information Change Request",
114 "Information Chat Reply",
115 "Account Confirm Request",
116 "Account Confirm Reply",
117 "Account Delete Request",
118 "Account Delete Reply"
119 },
120 {"Popups",
121 "Invalid",
122 "Error",
123 "Display Popup"
124 },
125 {"BOS",
126 "Invalid",
127 "Error",
128 "Request Rights",
129 "Rights Response",
130 "Set group permission mask",
131 "Add permission list entries",
132 "Delete permission list entries",
133 "Add deny list entries",
134 "Delete deny list entries",
135 "Server Error"
136 },
137 {"User Lookup",
138 "Invalid",
139 "Error",
140 "Search Request",
141 "Search Response"
142 },
143 {"Stats",
144 "Invalid",
145 "Error",
146 "Set minimum report interval",
147 "Report Events"
148 },
149 {"Translate",
150 "Invalid",
151 "Error",
152 "Translate Request",
153 "Translate Reply",
154 },
155 {"Chat Navigation",
156 "Invalid",
157 "Error",
158 "Request rights",
159 "Request Exchange Information",
160 "Request Room Information",
161 "Request Occupant List",
162 "Search for Room",
163 "Outgoing Message",
164 "Incoming Message",
165 "Evil Request",
166 "Evil Reply",
167 "Chat Error",
168 }
169 };
170
171 maxf = sizeof(literals) / sizeof(literals[0]);
172 maxs = sizeof(literals[0]) / sizeof(literals[0][0]);
173
174 family = aimutil_get16(workingPtr->data+0);
175 subtype= aimutil_get16(workingPtr->data+2);
176
177 if((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL))
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
9de3ca7e 182 return 1;
183}
184
78b3fb13 185faim_export int aim_conn_addhandler(struct aim_session_t *sess,
a25832e6 186 struct aim_conn_t *conn,
9de3ca7e 187 u_short family,
188 u_short type,
189 rxcallback_t newhandler,
190 u_short flags)
191{
871e2fd0 192 struct aim_rxcblist_t *newcb;
9de3ca7e 193
194 if (!conn)
195 return -1;
196
b8d0da45 197 faimdprintf(1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
9de3ca7e 198
871e2fd0 199 if (!(newcb = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t))))
200 return -1;
a15d82b1 201 newcb->family = family;
202 newcb->type = type;
203 newcb->flags = flags;
9de3ca7e 204 if (!newhandler)
a15d82b1 205 newcb->handler = &bleck;
9de3ca7e 206 else
a15d82b1 207 newcb->handler = newhandler;
208 newcb->next = NULL;
9de3ca7e 209
871e2fd0 210 if (!conn->handlerlist)
a15d82b1 211 conn->handlerlist = newcb;
871e2fd0 212 else {
213 struct aim_rxcblist_t *cur;
214
215 cur = conn->handlerlist;
216
217 while (cur->next)
218 cur = cur->next;
219 cur->next = newcb;
220 }
9de3ca7e 221
222 return 0;
223}
224
78b3fb13 225faim_export int aim_clearhandlers(struct aim_conn_t *conn)
9de3ca7e 226{
871e2fd0 227 struct aim_rxcblist_t *cur;
228
9de3ca7e 229 if (!conn)
230 return -1;
231
55e77c8a 232 for (cur = conn->handlerlist; cur; ) {
871e2fd0 233 struct aim_rxcblist_t *tmp;
234
235 tmp = cur->next;
236 free(cur);
237 cur = tmp;
238 }
55e77c8a 239 conn->handlerlist = NULL;
871e2fd0 240
9de3ca7e 241 return 0;
242}
243
78b3fb13 244faim_internal rxcallback_t aim_callhandler(struct aim_conn_t *conn,
245 u_short family,
246 u_short type)
9de3ca7e 247{
248 struct aim_rxcblist_t *cur;
249
250 if (!conn)
251 return NULL;
252
b8d0da45 253 faimdprintf(1, "aim_callhandler: calling for %04x/%04x\n", family, type);
9de3ca7e 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;
871e2fd0 265
9de3ca7e 266 return aim_callhandler(conn, family, 0xffff);
267}
268
78b3fb13 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)
9de3ca7e 274{
275 rxcallback_t userfunc = NULL;
276 userfunc = aim_callhandler(conn, family, type);
277 if (userfunc)
a25832e6 278 return userfunc(sess, ptr);
b8d0da45 279 return 1; /* XXX */
9de3ca7e 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 */
78b3fb13 305faim_export int aim_rxdispatch(struct aim_session_t *sess)
9de3ca7e 306{
307 int i = 0;
308 struct command_rx_struct *workingPtr = NULL;
309
b8d0da45 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;
50443ea0 315 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
b8d0da45 316 /*
317 * XXX: This is still fairly ugly.
318 */
50443ea0 319 if (workingPtr->handled)
320 continue;
321
b69540e3 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
b8d0da45 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: {
5daacaa3 347 unsigned long head;
b8d0da45 348
349 head = aimutil_get32(workingPtr->data);
5daacaa3 350 if ((head == 0x00000001) && (workingPtr->commandlen == 4)) {
b8d0da45 351 faimdprintf(1, "got connection ack on auth line\n");
22517493 352 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
5daacaa3 353 } else if (workingPtr->hdr.oscar.type == 0x04) {
354 /* Used only by the older login protocol */
f0a7908e 355 workingPtr->handled = aim_authparse(sess, workingPtr);
356 } else {
5daacaa3 357 unsigned short family,subtype;
b8d0da45 358
359 family = aimutil_get16(workingPtr->data);
360 subtype = aimutil_get16(workingPtr->data+2);
361
362 switch (family) {
363 /* New login protocol */
b8d0da45 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)
b5bc2a8c 370 workingPtr->handled = aim_authkeyparse(sess, workingPtr);
b8d0da45 371 else
372 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
373 break;
ee49b735 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:
78b3fb13 392 break;
b8d0da45 393 }
394 }
395 break;
396 }
397 case AIM_CONN_TYPE_BOS: {
398 u_short family;
399 u_short subtype;
5e02cf44 400
b69540e3 401 if (workingPtr->hdr.oscar.type == 0x04) {
5e02cf44 402 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
403 break;
404 }
405
b8d0da45 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)
22517493 412 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
b8d0da45 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:
ee49b735 422 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 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:
1a8c261b 431 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
b8d0da45 432 break;
433 case 0x000f:
434 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
435 break;
98c88242 436 case 0x0010:
437 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
438 break;
b8d0da45 439 case 0x0013:
440 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
441 break;
ee49b735 442 case 0x0018:
443 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
444 break;
b8d0da45 445 default:
446 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
447 break;
448 }
96f8b1ed 449 break;
b8d0da45 450 case 0x0002: /* Family: Location */
451 switch (subtype) {
452 case 0x0001:
96f8b1ed 453 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
b8d0da45 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 }
96f8b1ed 465 break;
b8d0da45 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:
96f8b1ed 472 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
b8d0da45 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;
3e2c7bcf 484 case 0x0004: /* Family: Messaging */
b8d0da45 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;
e5012450 492 case 0x0006:
493 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
494 break;
b8d0da45 495 case 0x0007:
496 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
497 break;
498 case 0x000a:
96f8b1ed 499 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
b8d0da45 500 break;
1a8c261b 501 case 0x000c:
502 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
503 break;
b8d0da45 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)
96f8b1ed 512 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
b8d0da45 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:
37ee990e 519 workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
b8d0da45 520 break;
521 case 0x0003:
37ee990e 522 workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
b8d0da45 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;
96f8b1ed 528 case 0x000b: {
b8d0da45 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;
96f8b1ed 536 }
3e2c7bcf 537 case 0x0013: {
538 printf("lalala: 0x%04x/0x%04x\n", family, subtype);
539 break;
540 }
96f8b1ed 541 case AIM_CB_FAM_SPECIAL:
542 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
543 break;
b8d0da45 544 default:
545 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
546 break;
96f8b1ed 547 } /* switch(family) */
b8d0da45 548 break;
96f8b1ed 549 } /* AIM_CONN_TYPE_BOS */
b8d0da45 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);
22517493 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);
ee49b735 558 } else if ((family == 0x0001) && (subtype == 0x0003)) {
559 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 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);
9de3ca7e 564 }
b8d0da45 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
22517493 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) {
b8d0da45 576 if (subtype == 0x0001)
577 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
578 else if (subtype == 0x0003)
ee49b735 579 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 580 else if (subtype == 0x0007)
581 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
275a2ff8 582 else if (subtype == 0x000a)
583 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
b8d0da45 584 else
cd71e19b 585 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
b8d0da45 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 }
b69540e3 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 }
7392c79f 616 case AIM_CONN_TYPE_RENDEZVOUS_OUT: {
617 /* not possible */
618 break;
619 }
b8d0da45 620 default:
b69540e3 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);
b8d0da45 622 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
623 break;
624 }
9de3ca7e 625 }
b8d0da45 626 }
9de3ca7e 627
b8d0da45 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);
9de3ca7e 635
636 return 0;
637}
638
78b3fb13 639faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 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));
78b3fb13 655 strncpy(sn, (char *)command->data+i, snlen);
1a8c261b 656
657 if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c)))
658 ret = userfunc(sess, command, type, sn);
659
660 return ret;
661}
662
d6c9fcf0 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 */
78b3fb13 712faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 713{
714 rxcallback_t userfunc = NULL;
1a8c261b 715 int ret = 1;
275a2ff8 716 int i;
717 int code;
d6c9fcf0 718 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 719 unsigned long currentavg, maxavg;
1a8c261b 720
275a2ff8 721 i = 10;
722
723 code = aimutil_get16(command->data+i);
724 i += 2;
725
d6c9fcf0 726 rateclass = aimutil_get16(command->data+i);
275a2ff8 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;
1a8c261b 743
744 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a)))
d6c9fcf0 745 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
1a8c261b 746
747 return ret;
748}
749
78b3fb13 750faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
98c88242 751{
752 rxcallback_t userfunc = NULL;
06bc8607 753 int ret = 1;
754 int i;
755 unsigned short newevil;
756 struct aim_userinfo_s userinfo;
98c88242 757
06bc8607 758 i = 10;
759 newevil = aimutil_get16(command->data+10);
760 i += 2;
98c88242 761
06bc8607 762 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
763 if (command->commandlen-i)
764 i += aim_extractuserinfo(command->data+i, &userinfo);
98c88242 765
766 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010)))
06bc8607 767 ret = userfunc(sess, command, newevil, &userinfo);
98c88242 768
769 return ret;
770}
771
78b3fb13 772faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
773 struct command_rx_struct *command, ...)
9de3ca7e 774{
775 rxcallback_t userfunc = NULL;
01b59e1e 776 char *msg;
777 int ret=1;
778 struct aim_tlvlist_t *tlvlist;
779 u_short id;
780
781 /*
98c88242 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 *
01b59e1e 790 */
791 id = aimutil_get16(command->data+10);
792
793 /*
794 * TLVs follow
795 */
b13c9e13 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 }
01b59e1e 803
804 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
805 if (userfunc)
806 ret = userfunc(sess, command, id, msg);
9de3ca7e 807
01b59e1e 808 aim_freetlvchain(&tlvlist);
b13c9e13 809 free(msg);
9de3ca7e 810
b13c9e13 811 return ret;
9de3ca7e 812}
813
ee49b735 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
78b3fb13 852faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
ee49b735 853 struct command_rx_struct *command, ...)
9de3ca7e 854{
1ea867e3 855 int serviceid = 0;
856 unsigned char *cookie = NULL;
9de3ca7e 857 char *ip = NULL;
858 rxcallback_t userfunc = NULL;
01b59e1e 859 struct aim_tlvlist_t *tlvlist;
860 int ret = 1;
861
1ea867e3 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);
0c20631f 879 free(sess->pendingjoin);
880 sess->pendingjoin = NULL;
9f20a4e3 881 sess->pendingjoinexchange = 0;
1ea867e3 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);
0e2be272 893
01b59e1e 894 aim_freetlvchain(&tlvlist);
895
896 return ret;
9de3ca7e 897}
898
78b3fb13 899faim_internal int aim_parse_unknown(struct aim_session_t *sess,
900 struct command_rx_struct *command, ...)
9de3ca7e 901{
902 u_int i = 0;
903
22517493 904 if (!sess || !command)
905 return 1;
906
b8d0da45 907 faimdprintf(1, "\nRecieved unknown packet:");
9de3ca7e 908
909 for (i = 0; i < command->commandlen; i++)
910 {
911 if ((i % 8) == 0)
71e609e9 912 faimdprintf(1, "\n\t");
9de3ca7e 913
71e609e9 914 faimdprintf(1, "0x%2x ", command->data[i]);
9de3ca7e 915 }
916
b1a4ea45 917 faimdprintf(1, "\n\n");
9de3ca7e 918
919 return 1;
920}
921
922
78b3fb13 923faim_internal int aim_negchan_middle(struct aim_session_t *sess,
924 struct command_rx_struct *command)
5e02cf44 925{
926 struct aim_tlvlist_t *tlvlist;
927 char *msg = NULL;
928 unsigned short code = 0;
5e02cf44 929 rxcallback_t userfunc = NULL;
930 int ret = 1;
931
932 tlvlist = aim_readtlvchain(command->data, command->commandlen);
933
1ea867e3 934 if (aim_gettlv(tlvlist, 0x0009, 1))
935 code = aim_gettlv16(tlvlist, 0x0009, 1);
5e02cf44 936
1ea867e3 937 if (aim_gettlv(tlvlist, 0x000b, 1))
5e02cf44 938 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
939
1ea867e3 940 if ((userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
5e02cf44 941 ret = userfunc(sess, command, code, msg);
942
943 aim_freetlvchain(&tlvlist);
1ea867e3 944
945 if (msg)
946 free(msg);
5e02cf44 947
948 return ret;
949}
950
9de3ca7e 951/*
952 * aim_parse_generalerrs()
953 *
954 * Middle handler for 0x0001 snac of each family.
955 *
956 */
78b3fb13 957faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
958 struct command_rx_struct *command, ...)
9de3ca7e 959{
1449ad2b 960 unsigned short family;
961 unsigned short subtype;
962 int ret = 1;
963 int error = 0;
964 rxcallback_t userfunc = NULL;
a25832e6 965
966 family = aimutil_get16(command->data+0);
967 subtype= aimutil_get16(command->data+2);
9de3ca7e 968
1449ad2b 969 if (command->commandlen > 10)
970 error = aimutil_get16(command->data+10);
9de3ca7e 971
1449ad2b 972 if ((userfunc = aim_callhandler(command->conn, family, subtype)))
973 ret = userfunc(sess, command, error);
974
975 return ret;
9de3ca7e 976}
977
978
979
This page took 3.566105 seconds and 5 git commands to generate.