]> andersk Git - libfaim.git/blame - aim_rxhandlers.c
- Fri Dec 15 23:35:01 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
55e77c8a 231 for (cur = conn->handlerlist; cur; ) {
871e2fd0 232 struct aim_rxcblist_t *tmp;
233
234 tmp = cur->next;
235 free(cur);
236 cur = tmp;
237 }
55e77c8a 238 conn->handlerlist = NULL;
871e2fd0 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");
22517493 351 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
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;
ee49b735 373 case 0x0001:
374 if (subtype == 0x0003)
375 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
376 else
377 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
378 break;
379 case 0x0007:
380 if (subtype == 0x0005)
381 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
382 break;
383 case AIM_CB_FAM_SPECIAL:
384 if (subtype == AIM_CB_SPECIAL_DEBUGCONN_CONNECT) {
385 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
386 break;
387 } else
388 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
389 break;
390 default:
78b3fb13 391 break;
b8d0da45 392 }
393 }
394 break;
395 }
396 case AIM_CONN_TYPE_BOS: {
397 u_short family;
398 u_short subtype;
5e02cf44 399
b69540e3 400 if (workingPtr->hdr.oscar.type == 0x04) {
5e02cf44 401 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
402 break;
403 }
404
b8d0da45 405 family = aimutil_get16(workingPtr->data);
406 subtype = aimutil_get16(workingPtr->data+2);
407
408 switch (family) {
409 case 0x0000: /* not really a family, but it works */
410 if (subtype == 0x0001)
22517493 411 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
b8d0da45 412 else
413 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
414 break;
415 case 0x0001: /* Family: General */
416 switch (subtype) {
417 case 0x0001:
418 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
419 break;
420 case 0x0003:
ee49b735 421 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 422 break;
423 case 0x0005:
424 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
425 break;
426 case 0x0007:
427 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
428 break;
429 case 0x000a:
1a8c261b 430 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
b8d0da45 431 break;
432 case 0x000f:
433 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
434 break;
98c88242 435 case 0x0010:
436 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
437 break;
b8d0da45 438 case 0x0013:
439 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
440 break;
ee49b735 441 case 0x0018:
442 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
443 break;
b8d0da45 444 default:
445 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
446 break;
447 }
96f8b1ed 448 break;
b8d0da45 449 case 0x0002: /* Family: Location */
450 switch (subtype) {
451 case 0x0001:
96f8b1ed 452 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
b8d0da45 453 break;
454 case 0x0003:
455 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
456 break;
457 case 0x0006:
458 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
459 break;
460 default:
461 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
462 break;
463 }
96f8b1ed 464 break;
b8d0da45 465 case 0x0003: /* Family: Buddy List */
466 switch (subtype) {
467 case 0x0001:
468 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
469 break;
470 case 0x0003:
96f8b1ed 471 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
b8d0da45 472 break;
473 case 0x000b: /* oncoming buddy */
474 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
475 break;
476 case 0x000c: /* offgoing buddy */
477 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
478 break;
479 default:
480 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
481 }
482 break;
3e2c7bcf 483 case 0x0004: /* Family: Messaging */
b8d0da45 484 switch (subtype) {
485 case 0x0001:
486 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
487 break;
488 case 0x0005:
489 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
490 break;
e5012450 491 case 0x0006:
492 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
493 break;
b8d0da45 494 case 0x0007:
495 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
496 break;
497 case 0x000a:
96f8b1ed 498 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
b8d0da45 499 break;
1a8c261b 500 case 0x000c:
501 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
502 break;
b8d0da45 503 default:
504 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
505 }
506 break;
507 case 0x0009:
508 if (subtype == 0x0001)
509 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
510 else if (subtype == 0x0003)
96f8b1ed 511 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
b8d0da45 512 else
513 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
514 break;
515 case 0x000a: /* Family: User lookup */
516 switch (subtype) {
517 case 0x0001:
518 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
519 break;
520 case 0x0003:
521 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
522 break;
523 default:
524 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
525 }
526 break;
96f8b1ed 527 case 0x000b: {
b8d0da45 528 if (subtype == 0x0001)
529 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
530 else if (subtype == 0x0002)
531 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
532 else
533 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
534 break;
96f8b1ed 535 }
3e2c7bcf 536 case 0x0013: {
537 printf("lalala: 0x%04x/0x%04x\n", family, subtype);
538 break;
539 }
96f8b1ed 540 case AIM_CB_FAM_SPECIAL:
541 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
542 break;
b8d0da45 543 default:
544 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
545 break;
96f8b1ed 546 } /* switch(family) */
b8d0da45 547 break;
96f8b1ed 548 } /* AIM_CONN_TYPE_BOS */
b8d0da45 549 case AIM_CONN_TYPE_CHATNAV: {
550 u_short family;
551 u_short subtype;
552 family = aimutil_get16(workingPtr->data);
553 subtype= aimutil_get16(workingPtr->data+2);
22517493 554
555 if ((family == 0x0000) && (subtype == 0x00001)) {
556 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
ee49b735 557 } else if ((family == 0x0001) && (subtype == 0x0003)) {
558 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 559 } else if ((family == 0x000d) && (subtype == 0x0009)) {
560 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
561 } else {
562 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
9de3ca7e 563 }
b8d0da45 564 break;
565 }
566 case AIM_CONN_TYPE_CHAT: {
567 u_short family, subtype;
568
569 family = aimutil_get16(workingPtr->data);
570 subtype= aimutil_get16(workingPtr->data+2);
571
22517493 572 if ((family == 0x0000) && (subtype == 0x00001)) {
573 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
574 } else if (family == 0x0001) {
b8d0da45 575 if (subtype == 0x0001)
576 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
577 else if (subtype == 0x0003)
ee49b735 578 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
b8d0da45 579 else if (subtype == 0x0007)
580 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
275a2ff8 581 else if (subtype == 0x000a)
582 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
b8d0da45 583 else
cd71e19b 584 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
b8d0da45 585 } else if (family == 0x000e) {
586 if (subtype == 0x0002)
587 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
588 else if (subtype == 0x0003)
589 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
590 else if (subtype == 0x0004)
591 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
592 else if (subtype == 0x0006)
593 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
594 else
595 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
596 } else {
597 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
598 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
599 }
600 break;
601 }
b69540e3 602 case AIM_CONN_TYPE_RENDEZVOUS: {
603 /* make sure that we only get OFT frames on these connections */
604 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
605 printf("faim: internal error: non-OFT frames on OFT connection\n");
606 workingPtr->handled = 1; /* get rid of it */
607 break;
608 }
609
610 /* XXX: implement this */
611 printf("faim: OFT frame!\n");
612
613 break;
614 }
7392c79f 615 case AIM_CONN_TYPE_RENDEZVOUS_OUT: {
616 /* not possible */
617 break;
618 }
b8d0da45 619 default:
b69540e3 620 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 621 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
622 break;
623 }
9de3ca7e 624 }
b8d0da45 625 }
9de3ca7e 626
b8d0da45 627 /*
628 * This doesn't have to be called here. It could easily be done
629 * by a seperate thread or something. It's an administrative operation,
630 * and can take a while. Though the less you call it the less memory
631 * you'll have :)
632 */
633 aim_purge_rxqueue(sess);
9de3ca7e 634
635 return 0;
636}
637
78b3fb13 638faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 639{
640 rxcallback_t userfunc = NULL;
641 char sn[MAXSNLEN];
642 unsigned short type;
643 int i = 10+8; /* skip SNAC and cookie */
644 int ret = 1;
645 unsigned char snlen;
646
647 type = aimutil_get16(command->data+i);
648 i += 2;
649
650 snlen = aimutil_get8(command->data+i);
651 i++;
652
653 memset(sn, 0, sizeof(sn));
78b3fb13 654 strncpy(sn, (char *)command->data+i, snlen);
1a8c261b 655
656 if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c)))
657 ret = userfunc(sess, command, type, sn);
658
659 return ret;
660}
661
78b3fb13 662faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 663{
664 rxcallback_t userfunc = NULL;
1a8c261b 665 int ret = 1;
275a2ff8 666 int i;
667 int code;
668 unsigned long parmid, windowsize, clear, alert, limit, disconnect;
669 unsigned long currentavg, maxavg;
1a8c261b 670
275a2ff8 671 i = 10;
672
673 code = aimutil_get16(command->data+i);
674 i += 2;
675
676 parmid = aimutil_get16(command->data+i);
677 i += 2;
678
679 windowsize = aimutil_get32(command->data+i);
680 i += 4;
681 clear = aimutil_get32(command->data+i);
682 i += 4;
683 alert = aimutil_get32(command->data+i);
684 i += 4;
685 limit = aimutil_get32(command->data+i);
686 i += 4;
687 disconnect = aimutil_get32(command->data+i);
688 i += 4;
689 currentavg = aimutil_get32(command->data+i);
690 i += 4;
691 maxavg = aimutil_get32(command->data+i);
692 i += 4;
1a8c261b 693
694 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a)))
275a2ff8 695 ret = userfunc(sess, command, code, parmid, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
1a8c261b 696
697 return ret;
698}
699
78b3fb13 700faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
98c88242 701{
702 rxcallback_t userfunc = NULL;
06bc8607 703 int ret = 1;
704 int i;
705 unsigned short newevil;
706 struct aim_userinfo_s userinfo;
98c88242 707
06bc8607 708 i = 10;
709 newevil = aimutil_get16(command->data+10);
710 i += 2;
98c88242 711
06bc8607 712 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
713 if (command->commandlen-i)
714 i += aim_extractuserinfo(command->data+i, &userinfo);
98c88242 715
716 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010)))
06bc8607 717 ret = userfunc(sess, command, newevil, &userinfo);
98c88242 718
719 return ret;
720}
721
78b3fb13 722faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
723 struct command_rx_struct *command, ...)
9de3ca7e 724{
725 rxcallback_t userfunc = NULL;
01b59e1e 726 char *msg;
727 int ret=1;
728 struct aim_tlvlist_t *tlvlist;
729 u_short id;
730
731 /*
98c88242 732 * Code.
733 *
734 * Valid values:
735 * 1 Mandatory upgrade
736 * 2 Advisory upgrade
737 * 3 System bulletin
738 * 4 Nothing's wrong ("top o the world" -- normal)
739 *
01b59e1e 740 */
741 id = aimutil_get16(command->data+10);
742
743 /*
744 * TLVs follow
745 */
b13c9e13 746 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
747 return ret;
748
749 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
750 aim_freetlvchain(&tlvlist);
751 return ret;
752 }
01b59e1e 753
754 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
755 if (userfunc)
756 ret = userfunc(sess, command, id, msg);
9de3ca7e 757
01b59e1e 758 aim_freetlvchain(&tlvlist);
b13c9e13 759 free(msg);
9de3ca7e 760
b13c9e13 761 return ret;
9de3ca7e 762}
763
ee49b735 764faim_internal int aim_parse_hostonline(struct aim_session_t *sess,
765 struct command_rx_struct *command, ...)
766{
767 rxcallback_t userfunc = NULL;
768 int ret = 1;
769 unsigned short *families = NULL;
770 int famcount = 0, i;
771
772 famcount = (command->commandlen-10)/2;
773 if (!(families = malloc(command->commandlen-10)))
774 return ret;
775
776 for (i = 0; i < famcount; i++)
777 families[i] = aimutil_get16(command->data+((i*2)+10));
778
779 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0003)))
780 ret = userfunc(sess, command, famcount, families);
781
782 free(families);
783
784 return ret;
785}
786
787faim_internal int aim_parse_hostversions(struct aim_session_t *sess,
788 struct command_rx_struct *command, ...)
789{
790 rxcallback_t userfunc = NULL;
791 int ret = 1;
792 int vercount;
793
794 vercount = (command->commandlen-10)/4;
795
796 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0018)))
797 ret = userfunc(sess, command, vercount, command->data+10);
798
799 return ret;
800}
801
78b3fb13 802faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
ee49b735 803 struct command_rx_struct *command, ...)
9de3ca7e 804{
1ea867e3 805 int serviceid = 0;
806 unsigned char *cookie = NULL;
9de3ca7e 807 char *ip = NULL;
808 rxcallback_t userfunc = NULL;
01b59e1e 809 struct aim_tlvlist_t *tlvlist;
810 int ret = 1;
811
1ea867e3 812 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
813
814 if (aim_gettlv(tlvlist, 0x000d, 1))
815 serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
816 if (aim_gettlv(tlvlist, 0x0005, 1))
817 ip = aim_gettlv_str(tlvlist, 0x0005, 1);
818 if (aim_gettlv(tlvlist, 0x0006, 1))
819 cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
820
821 if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
822
823 /*
824 * Chat hack.
825 *
826 */
827 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0005)))
828 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
0c20631f 829 free(sess->pendingjoin);
830 sess->pendingjoin = NULL;
9f20a4e3 831 sess->pendingjoinexchange = 0;
1ea867e3 832 } else if (!serviceid || !ip || !cookie) { /* yeep! */
833 ret = 1;
834 } else {
835 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0005)))
836 ret = userfunc(sess, command, serviceid, ip, cookie);
837 }
838
839 if (ip)
840 free(ip);
841 if (cookie)
842 free(cookie);
0e2be272 843
01b59e1e 844 aim_freetlvchain(&tlvlist);
845
846 return ret;
9de3ca7e 847}
848
78b3fb13 849faim_internal int aim_parse_unknown(struct aim_session_t *sess,
850 struct command_rx_struct *command, ...)
9de3ca7e 851{
852 u_int i = 0;
853
22517493 854 if (!sess || !command)
855 return 1;
856
b8d0da45 857 faimdprintf(1, "\nRecieved unknown packet:");
9de3ca7e 858
859 for (i = 0; i < command->commandlen; i++)
860 {
861 if ((i % 8) == 0)
71e609e9 862 faimdprintf(1, "\n\t");
9de3ca7e 863
71e609e9 864 faimdprintf(1, "0x%2x ", command->data[i]);
9de3ca7e 865 }
866
b1a4ea45 867 faimdprintf(1, "\n\n");
9de3ca7e 868
869 return 1;
870}
871
872
78b3fb13 873faim_internal int aim_negchan_middle(struct aim_session_t *sess,
874 struct command_rx_struct *command)
5e02cf44 875{
876 struct aim_tlvlist_t *tlvlist;
877 char *msg = NULL;
878 unsigned short code = 0;
5e02cf44 879 rxcallback_t userfunc = NULL;
880 int ret = 1;
881
882 tlvlist = aim_readtlvchain(command->data, command->commandlen);
883
1ea867e3 884 if (aim_gettlv(tlvlist, 0x0009, 1))
885 code = aim_gettlv16(tlvlist, 0x0009, 1);
5e02cf44 886
1ea867e3 887 if (aim_gettlv(tlvlist, 0x000b, 1))
5e02cf44 888 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
889
1ea867e3 890 if ((userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
5e02cf44 891 ret = userfunc(sess, command, code, msg);
892
893 aim_freetlvchain(&tlvlist);
1ea867e3 894
895 if (msg)
896 free(msg);
5e02cf44 897
898 return ret;
899}
900
9de3ca7e 901/*
902 * aim_parse_generalerrs()
903 *
904 * Middle handler for 0x0001 snac of each family.
905 *
906 */
78b3fb13 907faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
908 struct command_rx_struct *command, ...)
9de3ca7e 909{
1449ad2b 910 unsigned short family;
911 unsigned short subtype;
912 int ret = 1;
913 int error = 0;
914 rxcallback_t userfunc = NULL;
a25832e6 915
916 family = aimutil_get16(command->data+0);
917 subtype= aimutil_get16(command->data+2);
9de3ca7e 918
1449ad2b 919 if (command->commandlen > 10)
920 error = aimutil_get16(command->data+10);
9de3ca7e 921
1449ad2b 922 if ((userfunc = aim_callhandler(command->conn, family, subtype)))
923 ret = userfunc(sess, command, error);
924
925 return ret;
9de3ca7e 926}
927
928
929
This page took 0.227107 seconds and 5 git commands to generate.