]> andersk Git - libfaim.git/blame_incremental - aim_rxhandlers.c
- Fri Dec 1 23:48:38 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 cur = conn->handlerlist;
232 while(cur) {
233 struct aim_rxcblist_t *tmp;
234
235 tmp = cur->next;
236 free(cur);
237 cur = tmp;
238 }
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 0x0007:
374 if (subtype == 0x0005)
375 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
376 break;
377 case AIM_CB_FAM_SPECIAL:
378 if (subtype == AIM_CB_SPECIAL_DEBUGCONN_CONNECT) {
379 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
380 break;
381 } /* others fall through */
382 default:
383#if 0
384 /* Old login protocol */
385 /* any user callbacks will be called from here */
386 workingPtr->handled = aim_authparse(sess, workingPtr);
387#endif
388 break;
389 }
390 }
391 break;
392 }
393 case AIM_CONN_TYPE_BOS: {
394 u_short family;
395 u_short subtype;
396
397 if (workingPtr->hdr.oscar.type == 0x04) {
398 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
399 break;
400 }
401
402 family = aimutil_get16(workingPtr->data);
403 subtype = aimutil_get16(workingPtr->data+2);
404
405 switch (family) {
406 case 0x0000: /* not really a family, but it works */
407 if (subtype == 0x0001)
408 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
409 else
410 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
411 break;
412 case 0x0001: /* Family: General */
413 switch (subtype) {
414 case 0x0001:
415 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
416 break;
417 case 0x0003:
418 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
419 break;
420 case 0x0005:
421 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
422 break;
423 case 0x0007:
424 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
425 break;
426 case 0x000a:
427 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
428 break;
429 case 0x000f:
430 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
431 break;
432 case 0x0010:
433 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
434 break;
435 case 0x0013:
436 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
437 break;
438 default:
439 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
440 break;
441 }
442 break;
443 case 0x0002: /* Family: Location */
444 switch (subtype) {
445 case 0x0001:
446 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
447 break;
448 case 0x0003:
449 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
450 break;
451 case 0x0006:
452 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
453 break;
454 default:
455 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
456 break;
457 }
458 break;
459 case 0x0003: /* Family: Buddy List */
460 switch (subtype) {
461 case 0x0001:
462 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
463 break;
464 case 0x0003:
465 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
466 break;
467 case 0x000b: /* oncoming buddy */
468 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
469 break;
470 case 0x000c: /* offgoing buddy */
471 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
472 break;
473 default:
474 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
475 }
476 break;
477 case 0x0004: /* Family: Messeging */
478 switch (subtype) {
479 case 0x0001:
480 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
481 break;
482 case 0x0005:
483 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
484 break;
485 case 0x0006:
486 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
487 break;
488 case 0x0007:
489 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
490 break;
491 case 0x000a:
492 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
493 break;
494 case 0x000c:
495 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
496 break;
497 default:
498 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
499 }
500 break;
501 case 0x0009:
502 if (subtype == 0x0001)
503 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
504 else if (subtype == 0x0003)
505 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
506 else
507 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
508 break;
509 case 0x000a: /* Family: User lookup */
510 switch (subtype) {
511 case 0x0001:
512 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
513 break;
514 case 0x0003:
515 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
516 break;
517 default:
518 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
519 }
520 break;
521 case 0x000b: {
522 if (subtype == 0x0001)
523 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
524 else if (subtype == 0x0002)
525 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
526 else
527 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
528 break;
529 }
530 case AIM_CB_FAM_SPECIAL:
531 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
532 break;
533 default:
534 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
535 break;
536 } /* switch(family) */
537 break;
538 } /* AIM_CONN_TYPE_BOS */
539 case AIM_CONN_TYPE_CHATNAV: {
540 u_short family;
541 u_short subtype;
542 family = aimutil_get16(workingPtr->data);
543 subtype= aimutil_get16(workingPtr->data+2);
544
545 if ((family == 0x0000) && (subtype == 0x00001)) {
546 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
547 } else if ((family == 0x000d) && (subtype == 0x0009)) {
548 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
549 } else {
550 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
551 }
552 break;
553 }
554 case AIM_CONN_TYPE_CHAT: {
555 u_short family, subtype;
556
557 family = aimutil_get16(workingPtr->data);
558 subtype= aimutil_get16(workingPtr->data+2);
559
560 if ((family == 0x0000) && (subtype == 0x00001)) {
561 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
562 } else if (family == 0x0001) {
563 if (subtype == 0x0001)
564 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
565 else if (subtype == 0x0003)
566 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
567 else if (subtype == 0x0007)
568 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
569 else
570 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
571 } else if (family == 0x000e) {
572 if (subtype == 0x0002)
573 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
574 else if (subtype == 0x0003)
575 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
576 else if (subtype == 0x0004)
577 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
578 else if (subtype == 0x0006)
579 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
580 else
581 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
582 } else {
583 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
584 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
585 }
586 break;
587 }
588 case AIM_CONN_TYPE_RENDEZVOUS: {
589 /* make sure that we only get OFT frames on these connections */
590 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
591 printf("faim: internal error: non-OFT frames on OFT connection\n");
592 workingPtr->handled = 1; /* get rid of it */
593 break;
594 }
595
596 /* XXX: implement this */
597 printf("faim: OFT frame!\n");
598
599 break;
600 }
601 case AIM_CONN_TYPE_RENDEZVOUS_OUT: {
602 /* not possible */
603 break;
604 }
605 default:
606 printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->commandlen);
607 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
608 break;
609 }
610 }
611 }
612
613 /*
614 * This doesn't have to be called here. It could easily be done
615 * by a seperate thread or something. It's an administrative operation,
616 * and can take a while. Though the less you call it the less memory
617 * you'll have :)
618 */
619 aim_purge_rxqueue(sess);
620
621 return 0;
622}
623
624faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
625{
626 rxcallback_t userfunc = NULL;
627 char sn[MAXSNLEN];
628 unsigned short type;
629 int i = 10+8; /* skip SNAC and cookie */
630 int ret = 1;
631 unsigned char snlen;
632
633 type = aimutil_get16(command->data+i);
634 i += 2;
635
636 snlen = aimutil_get8(command->data+i);
637 i++;
638
639 memset(sn, 0, sizeof(sn));
640 strncpy(sn, (char *)command->data+i, snlen);
641
642 if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c)))
643 ret = userfunc(sess, command, type, sn);
644
645 return ret;
646}
647
648faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
649{
650 rxcallback_t userfunc = NULL;
651 int ret = 1;
652 unsigned long newrate;
653
654 if (command->commandlen != 0x2f) {
655 printf("faim: unknown rate change length 0x%04x\n", command->commandlen);
656 return 1;
657 }
658
659 newrate = aimutil_get32(command->data+34);
660
661 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a)))
662 ret = userfunc(sess, command, newrate);
663
664 return ret;
665}
666
667faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
668{
669 rxcallback_t userfunc = NULL;
670 int ret = 1, pos;
671 char *sn = NULL;
672
673 if(command->commandlen < 12) /* a warning level dec sends this */
674 return 1;
675
676 if ((pos = aimutil_get8(command->data+ 12)) > MAXSNLEN)
677 return 1;
678
679 if(!(sn = (char *)calloc(1, pos+1)))
680 return 1;
681
682 memcpy(sn, command->data+13, pos);
683
684 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010)))
685 ret = userfunc(sess, command, sn);
686
687 free(sn);
688
689 return ret;
690}
691
692faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
693 struct command_rx_struct *command, ...)
694{
695 rxcallback_t userfunc = NULL;
696 char *msg;
697 int ret=1;
698 struct aim_tlvlist_t *tlvlist;
699 u_short id;
700
701 /*
702 * Code.
703 *
704 * Valid values:
705 * 1 Mandatory upgrade
706 * 2 Advisory upgrade
707 * 3 System bulletin
708 * 4 Nothing's wrong ("top o the world" -- normal)
709 *
710 */
711 id = aimutil_get16(command->data+10);
712
713 /*
714 * TLVs follow
715 */
716 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
717 return ret;
718
719 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
720 aim_freetlvchain(&tlvlist);
721 return ret;
722 }
723
724 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
725 if (userfunc)
726 ret = userfunc(sess, command, id, msg);
727
728 aim_freetlvchain(&tlvlist);
729 free(msg);
730
731 return ret;
732}
733
734faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
735 struct command_rx_struct *command, ...)
736{
737 struct aim_tlv_t *tmptlv = NULL;
738 int serviceid = 0x00;
739 unsigned char cookie[AIM_COOKIELEN];
740 char *ip = NULL;
741 rxcallback_t userfunc = NULL;
742 struct aim_tlvlist_t *tlvlist;
743 int ret = 1;
744
745 if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
746 {
747 printf("libfaim: major bug: unable to read tlvchain from redirect\n");
748 return ret;
749 }
750
751 if (!(tmptlv = aim_gettlv(tlvlist, 0x000d, 1)))
752 {
753 printf("libfaim: major bug: no service ID in tlvchain from redirect\n");
754 aim_freetlvchain(&tlvlist);
755 return ret;
756 }
757 serviceid = aimutil_get16(tmptlv->value);
758
759 if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1)))
760 {
761 printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
762 free(ip);
763 aim_freetlvchain(&tlvlist);
764 return ret;
765 }
766
767 if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
768 {
769 printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
770 free(ip);
771 aim_freetlvchain(&tlvlist);
772 return ret;
773 }
774 memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
775
776 if (serviceid == AIM_CONN_TYPE_CHAT)
777 {
778 /*
779 * Chat hack.
780 *
781 */
782 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
783 if (userfunc)
784 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
785 free(sess->pendingjoin);
786 sess->pendingjoin = NULL;
787 sess->pendingjoinexchange = 0;
788 }
789 else
790 {
791 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
792 if (userfunc)
793 ret = userfunc(sess, command, serviceid, ip, cookie);
794 }
795
796 free(ip);
797 aim_freetlvchain(&tlvlist);
798
799 return ret;
800}
801
802faim_internal int aim_parse_unknown(struct aim_session_t *sess,
803 struct command_rx_struct *command, ...)
804{
805 u_int i = 0;
806
807 if (!sess || !command)
808 return 1;
809
810 faimdprintf(1, "\nRecieved unknown packet:");
811
812 for (i = 0; i < command->commandlen; i++)
813 {
814 if ((i % 8) == 0)
815 faimdprintf(1, "\n\t");
816
817 faimdprintf(1, "0x%2x ", command->data[i]);
818 }
819
820 faimdprintf(1, "\n\n");
821
822 return 1;
823}
824
825
826faim_internal int aim_negchan_middle(struct aim_session_t *sess,
827 struct command_rx_struct *command)
828{
829 struct aim_tlvlist_t *tlvlist;
830 char *msg = NULL;
831 unsigned short code = 0;
832 struct aim_tlv_t *tmptlv;
833 rxcallback_t userfunc = NULL;
834 int ret = 1;
835
836 tlvlist = aim_readtlvchain(command->data, command->commandlen);
837
838 if ((tmptlv = aim_gettlv(tlvlist, 0x0009, 1)))
839 code = aimutil_get16(tmptlv->value);
840
841 if ((tmptlv = aim_gettlv(tlvlist, 0x000b, 1)))
842 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
843
844 userfunc = aim_callhandler(command->conn,
845 AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR);
846 if (userfunc)
847 ret = userfunc(sess, command, code, msg);
848
849 aim_freetlvchain(&tlvlist);
850 free(msg);
851
852 return ret;
853}
854
855/*
856 * aim_parse_generalerrs()
857 *
858 * Middle handler for 0x0001 snac of each family.
859 *
860 */
861faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
862 struct command_rx_struct *command, ...)
863{
864 u_short family;
865 u_short subtype;
866
867 family = aimutil_get16(command->data+0);
868 subtype= aimutil_get16(command->data+2);
869
870 switch(family)
871 {
872 default:
873 /* Unknown family */
874 return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command);
875 }
876
877 return 1;
878}
879
880
881
This page took 0.259094 seconds and 5 git commands to generate.