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