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