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