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