]> andersk Git - libfaim.git/blame - aim_rxhandlers.c
Commented out some of my testing shit (uhg its a mess).
[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;
345 } else {
346 u_short family,subtype;
347
348 family = aimutil_get16(workingPtr->data);
349 subtype = aimutil_get16(workingPtr->data+2);
350
351 switch (family) {
352 /* New login protocol */
01b59e1e 353#ifdef SNACLOGIN
b8d0da45 354 case 0x0017:
355 if (subtype == 0x0001)
356 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
357 else if (subtype == 0x0003)
358 workingPtr->handled = aim_authparse(sess, workingPtr);
359 else if (subtype == 0x0007)
360 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr);
361 else
362 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
363 break;
364#else
365 /* XXX: this isnt foolproof */
366 case 0x0001:
367 if (subtype == 0x0003)
368 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr);
369 else
370 workingPtr->handled = aim_authparse(sess, workingPtr);
371 break;
372 case 0x0007:
373 if (subtype == 0x0005)
374 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
375 break;
376 default:
377 /* Old login protocol */
378 /* any user callbacks will be called from here */
379 workingPtr->handled = aim_authparse(sess, workingPtr);
01b59e1e 380#endif
b8d0da45 381 }
382 }
383 break;
384 }
385 case AIM_CONN_TYPE_BOS: {
386 u_short family;
387 u_short subtype;
5e02cf44 388
b69540e3 389 if (workingPtr->hdr.oscar.type == 0x04) {
5e02cf44 390 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
391 break;
392 }
393
b8d0da45 394 family = aimutil_get16(workingPtr->data);
395 subtype = aimutil_get16(workingPtr->data+2);
396
397 switch (family) {
398 case 0x0000: /* not really a family, but it works */
399 if (subtype == 0x0001)
400 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
401 else
402 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
403 break;
404 case 0x0001: /* Family: General */
405 switch (subtype) {
406 case 0x0001:
407 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
408 break;
409 case 0x0003:
410 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
411 break;
412 case 0x0005:
413 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
414 break;
415 case 0x0007:
416 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
417 break;
418 case 0x000a:
419 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr);
420 break;
421 case 0x000f:
422 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
423 break;
424 case 0x0013:
425 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
426 break;
427 default:
428 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
429 break;
430 }
431 case 0x0002: /* Family: Location */
432 switch (subtype) {
433 case 0x0001:
434 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
435 break;
436 case 0x0003:
437 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
438 break;
439 case 0x0006:
440 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
441 break;
442 default:
443 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
444 break;
445 }
446 case 0x0003: /* Family: Buddy List */
447 switch (subtype) {
448 case 0x0001:
449 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
450 break;
451 case 0x0003:
452 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr);
453 break;
454 case 0x000b: /* oncoming buddy */
455 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
456 break;
457 case 0x000c: /* offgoing buddy */
458 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
459 break;
460 default:
461 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
462 }
463 break;
464 case 0x0004: /* Family: Messeging */
465 switch (subtype) {
466 case 0x0001:
467 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
468 break;
469 case 0x0005:
470 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
471 break;
472 case 0x0007:
473 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
474 break;
475 case 0x000a:
476 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
477 break;
478 default:
479 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
480 }
481 break;
482 case 0x0009:
483 if (subtype == 0x0001)
484 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
485 else if (subtype == 0x0003)
486 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr);
487 else
488 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
489 break;
490 case 0x000a: /* Family: User lookup */
491 switch (subtype) {
492 case 0x0001:
493 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
494 break;
495 case 0x0003:
496 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
497 break;
498 default:
499 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
500 }
501 break;
502 case 0x000b:
503 if (subtype == 0x0001)
504 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
505 else if (subtype == 0x0002)
506 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
507 else
508 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
509 break;
510 default:
511 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
512 break;
513 }
514 break;
515 }
516 case AIM_CONN_TYPE_CHATNAV: {
517 u_short family;
518 u_short subtype;
519 family = aimutil_get16(workingPtr->data);
520 subtype= aimutil_get16(workingPtr->data+2);
521
522 if ((family == 0x0002) && (subtype == 0x0006)) {
523 workingPtr->handled = 1;
524 aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
525 } else if ((family == 0x000d) && (subtype == 0x0009)) {
526 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
527 } else {
528 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
9de3ca7e 529 }
b8d0da45 530 break;
531 }
532 case AIM_CONN_TYPE_CHAT: {
533 u_short family, subtype;
534
535 family = aimutil_get16(workingPtr->data);
536 subtype= aimutil_get16(workingPtr->data+2);
537
538 if ((family == 0x0000) && (subtype == 0x00001))
539 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
540 else if (family == 0x0001) {
541 if (subtype == 0x0001)
542 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
543 else if (subtype == 0x0003)
544 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
545 else if (subtype == 0x0007)
546 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
547 else
548 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
549 } else if (family == 0x000e) {
550 if (subtype == 0x0002)
551 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
552 else if (subtype == 0x0003)
553 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
554 else if (subtype == 0x0004)
555 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
556 else if (subtype == 0x0006)
557 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
558 else
559 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
560 } else {
561 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
562 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
563 }
564 break;
565 }
b69540e3 566 case AIM_CONN_TYPE_RENDEZVOUS: {
567 /* make sure that we only get OFT frames on these connections */
568 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
569 printf("faim: internal error: non-OFT frames on OFT connection\n");
570 workingPtr->handled = 1; /* get rid of it */
571 break;
572 }
573
574 /* XXX: implement this */
575 printf("faim: OFT frame!\n");
576
577 break;
578 }
b8d0da45 579 default:
b69540e3 580 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 581 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
582 break;
583 }
9de3ca7e 584 }
b8d0da45 585 }
9de3ca7e 586
b8d0da45 587 /*
588 * This doesn't have to be called here. It could easily be done
589 * by a seperate thread or something. It's an administrative operation,
590 * and can take a while. Though the less you call it the less memory
591 * you'll have :)
592 */
593 aim_purge_rxqueue(sess);
9de3ca7e 594
595 return 0;
596}
597
01b59e1e 598int aim_parsemotd_middle(struct aim_session_t *sess,
599 struct command_rx_struct *command, ...)
9de3ca7e 600{
601 rxcallback_t userfunc = NULL;
01b59e1e 602 char *msg;
603 int ret=1;
604 struct aim_tlvlist_t *tlvlist;
605 u_short id;
606
607 /*
608 * Dunno.
609 */
610 id = aimutil_get16(command->data+10);
611
612 /*
613 * TLVs follow
614 */
615 tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12);
a25832e6 616
01b59e1e 617 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
618
619 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
620 if (userfunc)
621 ret = userfunc(sess, command, id, msg);
9de3ca7e 622
01b59e1e 623 aim_freetlvchain(&tlvlist);
9de3ca7e 624
01b59e1e 625 return ret;
626
9de3ca7e 627}
628
a25832e6 629int aim_handleredirect_middle(struct aim_session_t *sess,
630 struct command_rx_struct *command, ...)
9de3ca7e 631{
01b59e1e 632 struct aim_tlv_t *tmptlv = NULL;
9de3ca7e 633 int serviceid = 0x00;
01b59e1e 634 char cookie[AIM_COOKIELEN];
9de3ca7e 635 char *ip = NULL;
636 rxcallback_t userfunc = NULL;
01b59e1e 637 struct aim_tlvlist_t *tlvlist;
638 int ret = 1;
639
0e2be272 640 if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
641 {
642 printf("libfaim: major bug: unable to read tlvchain from redirect\n");
643 return ret;
644 }
01b59e1e 645
0e2be272 646 if (!(tmptlv = aim_gettlv(tlvlist, 0x000d, 1)))
647 {
648 printf("libfaim: major bug: no service ID in tlvchain from redirect\n");
649 aim_freetlvchain(&tlvlist);
650 return ret;
651 }
01b59e1e 652 serviceid = aimutil_get16(tmptlv->value);
653
0e2be272 654 if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1)))
655 {
656 printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
657 aim_freetlvchain(&tlvlist);
658 return ret;
659 }
01b59e1e 660
0e2be272 661 if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
662 {
663 printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
664 aim_freetlvchain(&tlvlist);
665 return ret;
666 }
01b59e1e 667 memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
9de3ca7e 668
0c20631f 669 if (serviceid == AIM_CONN_TYPE_CHAT)
670 {
671 /*
672 * Chat hack.
673 *
674 */
675 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
676 if (userfunc)
677 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin);
678 free(sess->pendingjoin);
679 sess->pendingjoin = NULL;
680 }
681 else
682 {
683 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
684 if (userfunc)
685 ret = userfunc(sess, command, serviceid, ip, cookie);
686 }
0e2be272 687
688 /*
689 * XXX: Is there a leak here? Where does IP get freed?
690 */
01b59e1e 691 aim_freetlvchain(&tlvlist);
692
693 return ret;
9de3ca7e 694}
695
a25832e6 696int aim_parse_unknown(struct aim_session_t *sess,
697 struct command_rx_struct *command, ...)
9de3ca7e 698{
699 u_int i = 0;
700
b8d0da45 701 faimdprintf(1, "\nRecieved unknown packet:");
9de3ca7e 702
703 for (i = 0; i < command->commandlen; i++)
704 {
705 if ((i % 8) == 0)
706 printf("\n\t");
707
708 printf("0x%2x ", command->data[i]);
709 }
710
711 printf("\n\n");
712
713 return 1;
714}
715
716
5e02cf44 717int aim_negchan_middle(struct aim_session_t *sess,
718 struct command_rx_struct *command)
719{
720 struct aim_tlvlist_t *tlvlist;
721 char *msg = NULL;
722 unsigned short code = 0;
723 struct aim_tlv_t *tmptlv;
724 rxcallback_t userfunc = NULL;
725 int ret = 1;
726
727 tlvlist = aim_readtlvchain(command->data, command->commandlen);
728
729 if ((tmptlv = aim_gettlv(tlvlist, 0x0009, 1)))
730 code = aimutil_get16(tmptlv->value);
731
732 if ((tmptlv = aim_gettlv(tlvlist, 0x000b, 1)))
733 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
734
735 userfunc = aim_callhandler(command->conn,
736 AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR);
737 if (userfunc)
738 ret = userfunc(sess, command, code, msg);
739
740 aim_freetlvchain(&tlvlist);
741 free(msg);
742
743 return ret;
744}
745
9de3ca7e 746/*
747 * aim_parse_generalerrs()
748 *
749 * Middle handler for 0x0001 snac of each family.
750 *
751 */
a25832e6 752int aim_parse_generalerrs(struct aim_session_t *sess,
753 struct command_rx_struct *command, ...)
9de3ca7e 754{
755 u_short family;
756 u_short subtype;
a25832e6 757
758 family = aimutil_get16(command->data+0);
759 subtype= aimutil_get16(command->data+2);
9de3ca7e 760
761 switch(family)
762 {
763 default:
764 /* Unknown family */
a25832e6 765 return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command);
9de3ca7e 766 }
767
768 return 1;
769}
770
771
772
This page took 1.713158 seconds and 5 git commands to generate.