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.
13 * Bleck functions get called when there's no non-bleck functions
14 * around to cleanup the mess...
16 int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
24 /* XXX: this is ugly. and big just for debugging. */
25 char *literals[14][25] = {
36 "Rate Information Request",
38 "Rate Information Ack",
40 "Rate Information Change",
44 "Request Personal User Information",
45 "Personal User Information",
59 "Set user information",
60 "Request User Information",
62 "Watcher Sub Request",
63 "Watcher Notification"
65 {"Buddy List Management",
73 "Watcher List Response",
75 "Watcher Notification",
76 "Reject Notification",
84 "Remove ICBM Parameter",
85 "Request Parameter Information",
86 "Parameter Information",
101 {"Invitation / Client-to-Client",
110 "Information Request",
112 "Information Change Request",
113 "Information Chat Reply",
114 "Account Confirm Request",
115 "Account Confirm Reply",
116 "Account Delete Request",
117 "Account Delete Reply"
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",
145 "Set minimum report interval",
158 "Request Exchange Information",
159 "Request Room Information",
160 "Request Occupant List",
170 maxf = sizeof(literals) / sizeof(literals[0]);
171 maxs = sizeof(literals[0]) / sizeof(literals[0][0]);
173 family = aimutil_get16(workingPtr->data+0);
174 subtype= aimutil_get16(workingPtr->data+2);
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]);
179 printf("bleck: null handler for %04x/%04x (no literal)\n",family,subtype);
184 int aim_conn_addhandler(struct aim_session_t *sess,
185 struct aim_conn_t *conn,
188 rxcallback_t newhandler,
191 struct aim_rxcblist_t *new,*cur;
197 printf("aim_conn_addhandler: adding for %04x/%04x\n", family, type);
200 new = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t));
201 new->family = family;
205 new->handler = &bleck;
207 new->handler = newhandler;
210 cur = conn->handlerlist;
212 conn->handlerlist = new;
223 int aim_clearhandlers(struct aim_conn_t *conn)
225 struct aim_rxcblist_t *cur,*tmp;
229 cur = conn->handlerlist;
239 rxcallback_t aim_callhandler(struct aim_conn_t *conn,
243 struct aim_rxcblist_t *cur;
249 printf("aim_callhandler: calling for %04x/%04x\n", family, type);
252 cur = conn->handlerlist;
255 if ( (cur->family == family) && (cur->type == type) )
262 return aim_callhandler(conn, family, 0xffff);
265 int aim_callhandler_noparam(struct aim_session_t *sess,
266 struct aim_conn_t *conn,
269 struct command_rx_struct *ptr)
271 rxcallback_t userfunc = NULL;
272 userfunc = aim_callhandler(conn, family, type);
274 return userfunc(sess, ptr);
281 Basically, heres what this should do:
282 1) Determine correct packet handler for this packet
283 2) Mark the packet handled (so it can be dequeued in purge_queue())
284 3) Send the packet to the packet handler
285 4) Go to next packet in the queue and start over
286 5) When done, run purge_queue() to purge handled commands
288 Note that any unhandlable packets should probably be left in the
289 queue. This is the best way to prevent data loss. This means
290 that a single packet may get looked at by this function multiple
291 times. This is more good than bad! This behavior may change.
295 TODO: Get rid of all the ugly if's.
297 TODO: More support for mid-level handlers.
298 TODO: Allow for NULL handlers.
301 int aim_rxdispatch(struct aim_session_t *sess)
304 struct command_rx_struct *workingPtr = NULL;
306 if (sess->queue_incoming == NULL)
307 /* this shouldn't really happen, unless the main loop's select is broke */
308 printf("parse_generic: incoming packet queue empty.\n");
311 workingPtr = sess->queue_incoming;
312 for (i = 0; workingPtr != NULL; i++)
314 switch(workingPtr->conn->type)
316 case AIM_CONN_TYPE_AUTH:
320 head = aimutil_get32(workingPtr->data);
321 if (head == 0x00000001)
324 printf("got connection ack on auth line\n");
326 workingPtr->handled = 1;
330 u_short family,subtype;
332 family = aimutil_get16(workingPtr->data);
333 subtype = aimutil_get16(workingPtr->data+2);
337 /* New login protocol */
340 if (subtype == 0x0001)
341 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
342 else if (subtype == 0x0003)
343 workingPtr->handled = aim_authparse(sess, workingPtr);
344 else if (subtype == 0x0007)
345 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr);
347 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
350 /* XXX: this isnt foolproof */
352 if (subtype == 0x0003)
353 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr);
355 workingPtr->handled = aim_authparse(sess, workingPtr);
358 if (subtype == 0x0005)
359 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
362 /* Old login protocol */
363 /* any user callbacks will be called from here */
364 workingPtr->handled = aim_authparse(sess, workingPtr);
370 case AIM_CONN_TYPE_BOS:
375 family = aimutil_get16(workingPtr->data);
376 subtype = aimutil_get16(workingPtr->data+2);
380 case 0x0000: /* not really a family, but it works */
381 if (subtype == 0x0001)
382 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
384 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
386 case 0x0001: /* Family: General */
390 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
393 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
396 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
399 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
402 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr);
405 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
408 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
411 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
414 case 0x0002: /* Family: Location */
418 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
421 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
424 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
427 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
430 case 0x0003: /* Family: Buddy List */
434 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
437 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr);
439 case 0x000b: /* oncoming buddy */
440 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
442 case 0x000c: /* offgoing buddy */
443 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
446 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
449 case 0x0004: /* Family: Messeging */
453 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
456 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
459 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
462 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
465 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
469 if (subtype == 0x0001)
470 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
471 else if (subtype == 0x0003)
472 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr);
474 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
476 case 0x000a: /* Family: User lookup */
480 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
483 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
486 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
490 if (subtype == 0x0001)
491 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
492 else if (subtype == 0x0002)
493 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
495 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
498 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
503 case AIM_CONN_TYPE_CHATNAV:
507 family = aimutil_get16(workingPtr->data);
508 subtype= aimutil_get16(workingPtr->data+2);
510 if ((family == 0x0002) && (subtype == 0x0006))
512 workingPtr->handled = 1;
513 aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
517 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
521 case AIM_CONN_TYPE_CHAT:
522 printf("\nAHH! Dont know what to do with CHAT stuff yet!\n");
523 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
526 printf("\nAHHHHH! UNKNOWN CONNECTION TYPE! (0x%02x)\n\n", workingPtr->conn->type);
527 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
530 /* move to next command */
531 workingPtr = workingPtr->next;
535 sess->queue_incoming = aim_purge_rxqueue(sess->queue_incoming);
540 int aim_parsemotd_middle(struct aim_session_t *sess,
541 struct command_rx_struct *command, ...)
543 rxcallback_t userfunc = NULL;
546 struct aim_tlvlist_t *tlvlist;
552 id = aimutil_get16(command->data+10);
557 tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12);
559 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
561 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
563 ret = userfunc(sess, command, id, msg);
565 aim_freetlvchain(&tlvlist);
571 int aim_handleredirect_middle(struct aim_session_t *sess,
572 struct command_rx_struct *command, ...)
574 struct aim_tlv_t *tmptlv = NULL;
575 int serviceid = 0x00;
576 char cookie[AIM_COOKIELEN];
578 rxcallback_t userfunc = NULL;
579 struct aim_tlvlist_t *tlvlist;
582 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
584 tmptlv = aim_gettlv(tlvlist, 0x000d, 1);
585 serviceid = aimutil_get16(tmptlv->value);
587 ip = aim_gettlv_str(tlvlist, 0x0005, 1);
589 tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
590 memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
592 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
594 ret = userfunc(sess, command, serviceid, ip, cookie);
596 aim_freetlvchain(&tlvlist);
601 int aim_parse_unknown(struct aim_session_t *sess,
602 struct command_rx_struct *command, ...)
606 printf("\nRecieved unknown packet:");
608 for (i = 0; i < command->commandlen; i++)
613 printf("0x%2x ", command->data[i]);
623 * aim_parse_generalerrs()
625 * Middle handler for 0x0001 snac of each family.
628 int aim_parse_generalerrs(struct aim_session_t *sess,
629 struct command_rx_struct *command, ...)
634 family = aimutil_get16(command->data+0);
635 subtype= aimutil_get16(command->data+2);
641 return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command);