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