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