]> andersk Git - libfaim.git/blame - aim_rxhandlers.c
More fixes.
[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
a25832e6 10#include <faim/aim.h>
9de3ca7e 11
24286d93 12/*
13 * Bleck functions get called when there's no non-bleck functions
14 * around to cleanup the mess...
15 */
a25832e6 16int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
9de3ca7e 17{
18 u_short family;
19 u_short subtype;
01b59e1e 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
9de3ca7e 181 return 1;
182}
183
a25832e6 184int aim_conn_addhandler(struct aim_session_t *sess,
185 struct aim_conn_t *conn,
9de3ca7e 186 u_short family,
187 u_short type,
188 rxcallback_t newhandler,
189 u_short flags)
190{
191 struct aim_rxcblist_t *new,*cur;
192
193 if (!conn)
194 return -1;
195
b8d0da45 196 faimdprintf(1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
9de3ca7e 197
198 new = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t));
199 new->family = family;
200 new->type = type;
201 new->flags = flags;
202 if (!newhandler)
203 new->handler = &bleck;
204 else
205 new->handler = newhandler;
206 new->next = NULL;
207
208 cur = conn->handlerlist;
209 if (!cur)
210 conn->handlerlist = new;
211 else
212 {
213 while (cur->next)
214 cur = cur->next;
215 cur->next = new;
216 }
217
218 return 0;
219}
220
221int aim_clearhandlers(struct aim_conn_t *conn)
222{
223 struct aim_rxcblist_t *cur,*tmp;
224 if (!conn)
225 return -1;
226
227 cur = conn->handlerlist;
228 while(cur)
229 {
230 tmp = cur->next;
231 free(cur);
232 cur = tmp;
233 }
234 return 0;
235}
236
237rxcallback_t aim_callhandler(struct aim_conn_t *conn,
238 u_short family,
239 u_short type)
240{
241 struct aim_rxcblist_t *cur;
242
243 if (!conn)
244 return NULL;
245
b8d0da45 246 faimdprintf(1, "aim_callhandler: calling for %04x/%04x\n", family, type);
9de3ca7e 247
248 cur = conn->handlerlist;
249 while(cur)
250 {
251 if ( (cur->family == family) && (cur->type == type) )
252 return cur->handler;
253 cur = cur->next;
254 }
255
256 if (type==0xffff)
257 return NULL;
258 return aim_callhandler(conn, family, 0xffff);
259}
260
a25832e6 261int aim_callhandler_noparam(struct aim_session_t *sess,
262 struct aim_conn_t *conn,
9de3ca7e 263 u_short family,
264 u_short type,
265 struct command_rx_struct *ptr)
266{
267 rxcallback_t userfunc = NULL;
268 userfunc = aim_callhandler(conn, family, type);
269 if (userfunc)
a25832e6 270 return userfunc(sess, ptr);
b8d0da45 271 return 1; /* XXX */
9de3ca7e 272}
273
274/*
275 aim_rxdispatch()
276
277 Basically, heres what this should do:
278 1) Determine correct packet handler for this packet
279 2) Mark the packet handled (so it can be dequeued in purge_queue())
280 3) Send the packet to the packet handler
281 4) Go to next packet in the queue and start over
282 5) When done, run purge_queue() to purge handled commands
283
284 Note that any unhandlable packets should probably be left in the
285 queue. This is the best way to prevent data loss. This means
286 that a single packet may get looked at by this function multiple
287 times. This is more good than bad! This behavior may change.
288
289 Aren't queue's fun?
290
291 TODO: Get rid of all the ugly if's.
292 TODO: Clean up.
293 TODO: More support for mid-level handlers.
294 TODO: Allow for NULL handlers.
295
296 */
a25832e6 297int aim_rxdispatch(struct aim_session_t *sess)
9de3ca7e 298{
299 int i = 0;
300 struct command_rx_struct *workingPtr = NULL;
301
b8d0da45 302 if (sess->queue_incoming == NULL) {
303 faimdprintf(1, "parse_generic: incoming packet queue empty.\n");
304 return 0;
305 } else {
306 workingPtr = sess->queue_incoming;
50443ea0 307 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
b8d0da45 308 /*
309 * XXX: This is still fairly ugly.
310 */
50443ea0 311 if (workingPtr->handled)
312 continue;
313
b69540e3 314 /*
315 * This is a debugging/sanity check only and probably could/should be removed
316 * for stable code.
317 */
318 if (((workingPtr->hdrtype == AIM_FRAMETYPE_OFT) &&
319 (workingPtr->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) ||
320 ((workingPtr->hdrtype == AIM_FRAMETYPE_OSCAR) &&
321 (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS))) {
322 printf("faim: rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type);
323 workingPtr->handled = 1;
324 continue;
325 }
326
b8d0da45 327 switch(workingPtr->conn->type) {
328 case -1:
329 /*
330 * This can happen if we have a queued command
331 * that was recieved after a connection has
332 * been terminated. In which case, the handler
333 * list has been cleared, and there's nothing we
334 * can do for it. We can only cancel it.
335 */
336 workingPtr->handled = 1;
337 break;
338 case AIM_CONN_TYPE_AUTH: {
339 u_long head;
340
341 head = aimutil_get32(workingPtr->data);
342 if (head == 0x00000001) {
343 faimdprintf(1, "got connection ack on auth line\n");
344 workingPtr->handled = 1;
f0a7908e 345 } else if (workingPtr->hdr.oscar.type == 0x0004) {
346 workingPtr->handled = aim_authparse(sess, workingPtr);
347 } else {
b8d0da45 348 u_short family,subtype;
349
350 family = aimutil_get16(workingPtr->data);
351 subtype = aimutil_get16(workingPtr->data+2);
352
353 switch (family) {
354 /* New login protocol */
01b59e1e 355#ifdef SNACLOGIN
b8d0da45 356 case 0x0017:
357 if (subtype == 0x0001)
358 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
359 else if (subtype == 0x0003)
360 workingPtr->handled = aim_authparse(sess, workingPtr);
361 else if (subtype == 0x0007)
362 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr);
363 else
364 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
365 break;
366#else
367 /* XXX: this isnt foolproof */
368 case 0x0001:
f0a7908e 369 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr);
b8d0da45 370 break;
371 case 0x0007:
372 if (subtype == 0x0005)
373 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
374 break;
375 default:
376 /* Old login protocol */
377 /* any user callbacks will be called from here */
378 workingPtr->handled = aim_authparse(sess, workingPtr);
01b59e1e 379#endif
b8d0da45 380 }
381 }
382 break;
383 }
384 case AIM_CONN_TYPE_BOS: {
385 u_short family;
386 u_short subtype;
5e02cf44 387
b69540e3 388 if (workingPtr->hdr.oscar.type == 0x04) {
5e02cf44 389 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
390 break;
391 }
392
b8d0da45 393 family = aimutil_get16(workingPtr->data);
394 subtype = aimutil_get16(workingPtr->data+2);
395
396 switch (family) {
397 case 0x0000: /* not really a family, but it works */
398 if (subtype == 0x0001)
399 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
400 else
401 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
402 break;
403 case 0x0001: /* Family: General */
404 switch (subtype) {
405 case 0x0001:
406 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
407 break;
408 case 0x0003:
409 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
410 break;
411 case 0x0005:
412 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
413 break;
414 case 0x0007:
415 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
416 break;
417 case 0x000a:
418 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr);
419 break;
420 case 0x000f:
421 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
422 break;
423 case 0x0013:
424 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
425 break;
426 default:
427 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
428 break;
429 }
430 case 0x0002: /* Family: Location */
431 switch (subtype) {
432 case 0x0001:
433 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
434 break;
435 case 0x0003:
436 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
437 break;
438 case 0x0006:
439 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
440 break;
441 default:
442 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
443 break;
444 }
445 case 0x0003: /* Family: Buddy List */
446 switch (subtype) {
447 case 0x0001:
448 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
449 break;
450 case 0x0003:
451 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr);
452 break;
453 case 0x000b: /* oncoming buddy */
454 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
455 break;
456 case 0x000c: /* offgoing buddy */
457 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
458 break;
459 default:
460 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
461 }
462 break;
463 case 0x0004: /* Family: Messeging */
464 switch (subtype) {
465 case 0x0001:
466 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
467 break;
468 case 0x0005:
469 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
470 break;
471 case 0x0007:
472 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
473 break;
474 case 0x000a:
475 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
476 break;
477 default:
478 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
479 }
480 break;
481 case 0x0009:
482 if (subtype == 0x0001)
483 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
484 else if (subtype == 0x0003)
485 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr);
486 else
487 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
488 break;
489 case 0x000a: /* Family: User lookup */
490 switch (subtype) {
491 case 0x0001:
492 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
493 break;
494 case 0x0003:
495 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
496 break;
497 default:
498 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
499 }
500 break;
501 case 0x000b:
502 if (subtype == 0x0001)
503 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
504 else if (subtype == 0x0002)
505 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
506 else
507 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
508 break;
509 default:
510 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
511 break;
512 }
513 break;
514 }
515 case AIM_CONN_TYPE_CHATNAV: {
516 u_short family;
517 u_short subtype;
518 family = aimutil_get16(workingPtr->data);
519 subtype= aimutil_get16(workingPtr->data+2);
520
521 if ((family == 0x0002) && (subtype == 0x0006)) {
522 workingPtr->handled = 1;
523 aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
524 } else if ((family == 0x000d) && (subtype == 0x0009)) {
525 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
526 } else {
527 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
9de3ca7e 528 }
b8d0da45 529 break;
530 }
531 case AIM_CONN_TYPE_CHAT: {
532 u_short family, subtype;
533
534 family = aimutil_get16(workingPtr->data);
535 subtype= aimutil_get16(workingPtr->data+2);
536
537 if ((family == 0x0000) && (subtype == 0x00001))
538 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
539 else if (family == 0x0001) {
540 if (subtype == 0x0001)
541 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
542 else if (subtype == 0x0003)
543 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
544 else if (subtype == 0x0007)
545 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
546 else
547 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
548 } else if (family == 0x000e) {
549 if (subtype == 0x0002)
550 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
551 else if (subtype == 0x0003)
552 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
553 else if (subtype == 0x0004)
554 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
555 else if (subtype == 0x0006)
556 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
557 else
558 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
559 } else {
560 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
561 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
562 }
563 break;
564 }
b69540e3 565 case AIM_CONN_TYPE_RENDEZVOUS: {
566 /* make sure that we only get OFT frames on these connections */
567 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
568 printf("faim: internal error: non-OFT frames on OFT connection\n");
569 workingPtr->handled = 1; /* get rid of it */
570 break;
571 }
572
573 /* XXX: implement this */
574 printf("faim: OFT frame!\n");
575
576 break;
577 }
b8d0da45 578 default:
b69540e3 579 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 580 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
581 break;
582 }
9de3ca7e 583 }
b8d0da45 584 }
9de3ca7e 585
b8d0da45 586 /*
587 * This doesn't have to be called here. It could easily be done
588 * by a seperate thread or something. It's an administrative operation,
589 * and can take a while. Though the less you call it the less memory
590 * you'll have :)
591 */
592 aim_purge_rxqueue(sess);
9de3ca7e 593
594 return 0;
595}
596
01b59e1e 597int aim_parsemotd_middle(struct aim_session_t *sess,
598 struct command_rx_struct *command, ...)
9de3ca7e 599{
600 rxcallback_t userfunc = NULL;
01b59e1e 601 char *msg;
602 int ret=1;
603 struct aim_tlvlist_t *tlvlist;
604 u_short id;
605
606 /*
607 * Dunno.
608 */
609 id = aimutil_get16(command->data+10);
610
611 /*
612 * TLVs follow
613 */
614 tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12);
a25832e6 615
01b59e1e 616 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
617
618 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
619 if (userfunc)
620 ret = userfunc(sess, command, id, msg);
9de3ca7e 621
01b59e1e 622 aim_freetlvchain(&tlvlist);
9de3ca7e 623
01b59e1e 624 return ret;
625
9de3ca7e 626}
627
a25832e6 628int aim_handleredirect_middle(struct aim_session_t *sess,
629 struct command_rx_struct *command, ...)
9de3ca7e 630{
01b59e1e 631 struct aim_tlv_t *tmptlv = NULL;
9de3ca7e 632 int serviceid = 0x00;
01b59e1e 633 char cookie[AIM_COOKIELEN];
9de3ca7e 634 char *ip = NULL;
635 rxcallback_t userfunc = NULL;
01b59e1e 636 struct aim_tlvlist_t *tlvlist;
637 int ret = 1;
638
0e2be272 639 if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
640 {
641 printf("libfaim: major bug: unable to read tlvchain from redirect\n");
642 return ret;
643 }
01b59e1e 644
0e2be272 645 if (!(tmptlv = aim_gettlv(tlvlist, 0x000d, 1)))
646 {
647 printf("libfaim: major bug: no service ID in tlvchain from redirect\n");
648 aim_freetlvchain(&tlvlist);
649 return ret;
650 }
01b59e1e 651 serviceid = aimutil_get16(tmptlv->value);
652
0e2be272 653 if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1)))
654 {
655 printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
656 aim_freetlvchain(&tlvlist);
657 return ret;
658 }
01b59e1e 659
0e2be272 660 if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
661 {
662 printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
663 aim_freetlvchain(&tlvlist);
664 return ret;
665 }
01b59e1e 666 memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
9de3ca7e 667
0c20631f 668 if (serviceid == AIM_CONN_TYPE_CHAT)
669 {
670 /*
671 * Chat hack.
672 *
673 */
674 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
675 if (userfunc)
676 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin);
677 free(sess->pendingjoin);
678 sess->pendingjoin = NULL;
679 }
680 else
681 {
682 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
683 if (userfunc)
684 ret = userfunc(sess, command, serviceid, ip, cookie);
685 }
0e2be272 686
687 /*
688 * XXX: Is there a leak here? Where does IP get freed?
689 */
01b59e1e 690 aim_freetlvchain(&tlvlist);
691
692 return ret;
9de3ca7e 693}
694
a25832e6 695int aim_parse_unknown(struct aim_session_t *sess,
696 struct command_rx_struct *command, ...)
9de3ca7e 697{
698 u_int i = 0;
699
b8d0da45 700 faimdprintf(1, "\nRecieved unknown packet:");
9de3ca7e 701
702 for (i = 0; i < command->commandlen; i++)
703 {
704 if ((i % 8) == 0)
71e609e9 705 faimdprintf(1, "\n\t");
9de3ca7e 706
71e609e9 707 faimdprintf(1, "0x%2x ", command->data[i]);
9de3ca7e 708 }
709
b1a4ea45 710 faimdprintf(1, "\n\n");
9de3ca7e 711
712 return 1;
713}
714
715
5e02cf44 716int aim_negchan_middle(struct aim_session_t *sess,
717 struct command_rx_struct *command)
718{
719 struct aim_tlvlist_t *tlvlist;
720 char *msg = NULL;
721 unsigned short code = 0;
722 struct aim_tlv_t *tmptlv;
723 rxcallback_t userfunc = NULL;
724 int ret = 1;
725
726 tlvlist = aim_readtlvchain(command->data, command->commandlen);
727
728 if ((tmptlv = aim_gettlv(tlvlist, 0x0009, 1)))
729 code = aimutil_get16(tmptlv->value);
730
731 if ((tmptlv = aim_gettlv(tlvlist, 0x000b, 1)))
732 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
733
734 userfunc = aim_callhandler(command->conn,
735 AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR);
736 if (userfunc)
737 ret = userfunc(sess, command, code, msg);
738
739 aim_freetlvchain(&tlvlist);
740 free(msg);
741
742 return ret;
743}
744
9de3ca7e 745/*
746 * aim_parse_generalerrs()
747 *
748 * Middle handler for 0x0001 snac of each family.
749 *
750 */
a25832e6 751int aim_parse_generalerrs(struct aim_session_t *sess,
752 struct command_rx_struct *command, ...)
9de3ca7e 753{
754 u_short family;
755 u_short subtype;
a25832e6 756
757 family = aimutil_get16(command->data+0);
758 subtype= aimutil_get16(command->data+2);
9de3ca7e 759
760 switch(family)
761 {
762 default:
763 /* Unknown family */
a25832e6 764 return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command);
9de3ca7e 765 }
766
767 return 1;
768}
769
770
771
This page took 0.1602 seconds and 5 git commands to generate.