]> andersk Git - libfaim.git/commitdiff
- Sun Mar 19 06:07:52 UTC 2000
authormid <mid>
Sun, 19 Mar 2000 08:55:50 +0000 (08:55 +0000)
committermid <mid>
Sun, 19 Mar 2000 08:55:50 +0000 (08:55 +0000)
   - Added a parameter to aim_select to return event type
     - REQUIRES CLIENT CHANGES.
   - For the most part rewrote the tx and rx queuing code
     - Should fix many, many outstanding problems in and related
         to that code, including one that keeps memory from freeing
   - Fixed several bugs in various places
   - Reformated a lot of code, and did general cleanups
   - Should have a generally more robust lib now.

CHANGES
aim_conn.c
aim_rxhandlers.c
aim_rxqueue.c
aim_txqueue.c
faim/aim.h
utils/faimtest/faimtest.c

diff --git a/CHANGES b/CHANGES
index 3bf1aeb6ce780f16fa162cc36583931a9e4021d0..b70fa8acb04585dc3452f7393ed581307826c1e9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,16 @@
 
 No release numbers
 ------------------
+ - Sun Mar 19 06:07:52 UTC 2000
+   - Added a parameter to aim_select to return event type 
+     - REQUIRES CLIENT CHANGES.
+   - For the most part rewrote the tx and rx queuing code 
+     - Should fix many, many outstanding problems in and related
+         to that code, including one that keeps memory from freeing 
+   - Fixed several bugs in various places
+   - Reformated a lot of code, and did general cleanups
+   - Should have a generally more robust lib now.
+
  - Sun Mar 12 00:07:40 UTC 2000
    - Fixed a robustness problem in aim_handleredirect_middle()
    - Added TLV chain creation routines (yes, aimd is progressing)
index b47b42b430bc20e0796c93a0b70ca58a6689093d..75ad013c09a1ae7bc0d1fb1ff57bd48576ecbf19 100644 (file)
@@ -157,12 +157,17 @@ int aim_countconn(struct aim_session_t *sess)
  * Waits for a socket with data or for timeout, whichever comes first.
  * See select(2).
  * 
+ * Return codes in *status:
+ *   -1  error in select() (NULL returned)
+ *    0  no events pending (NULL returned)
+ *    1  outgoing data pending (NULL returned)
+ *    2  incoming data pending (connection with pending data returned)
+ *
  */ 
 struct aim_conn_t *aim_select(struct aim_session_t *sess,
-                             struct timeval *timeout)
+                             struct timeval *timeout, int *status)
 {
   fd_set fds;
-  fd_set errfds;
   int i;
 
   if (aim_countconn(sess) <= 0)
@@ -171,42 +176,32 @@ struct aim_conn_t *aim_select(struct aim_session_t *sess,
   /* 
    * If we have data waiting to be sent, return immediatly
    */
-  if (sess->queue_outgoing)
-    return (struct aim_conn_t *)1;
+  if (sess->queue_outgoing != NULL) {
+    *status = 1;
+    return NULL;
+  } 
 
   FD_ZERO(&fds);
-  FD_ZERO(&errfds);
   
   for(i=0;i<AIM_CONN_MAX;i++)
     if (sess->conns[i].fd>-1)
-      {
-       FD_SET(sess->conns[i].fd, &fds);
-       FD_SET(sess->conns[i].fd, &errfds);
-      }
+      FD_SET(sess->conns[i].fd, &fds);
   
-  i = select(aim_conngetmaxfd(sess)+1, &fds, NULL, &errfds, timeout);
-  if (i>=1)
-    {
-      int j;
-      for (j=0;j<AIM_CONN_MAX;j++)
-       {
-         if (sess->conns[j].fd > -1)
-           {
-             if ((FD_ISSET(sess->conns[j].fd, &errfds)))
-               {
-                 /* got an exception; close whats left of it up */
-                 aim_conn_close(&(sess->conns[j]));
-                 return (struct aim_conn_t *)-1;
-               }
-             else if ((FD_ISSET(sess->conns[j].fd, &fds)))
-               return &(sess->conns[j]);  /* return the first waiting struct */
+  if ((i = select(aim_conngetmaxfd(sess)+1, &fds, NULL, NULL, timeout))>=1) {
+    int j;
+    for (j=0;j<AIM_CONN_MAX;j++) {
+       if (sess->conns[j].fd > -1) {
+           if ((FD_ISSET(sess->conns[j].fd, &fds))) {
+             *status = 2;
+             return &(sess->conns[j]);  /* return the first waiting struct */
            }
-       }
-      /* should never get here */
-    }
-  else
-    return (struct aim_conn_t *)i;  /* no waiting or error, return -- FIXME: return type funnies */
-  return NULL; /* NO REACH */
+         }     
+       }       
+    /* should never get here */
+  }
+
+  *status = i; /* may be 0 or -1 */
+  return NULL;  /* no waiting or error, return */
 }
 
 int aim_conn_isready(struct aim_conn_t *conn)
index 0022a4eb3a598df4ca0fa39d62013316aa0e058f..7b0a0f94d81c3fcd00a5630c5eb6f2b9f7afa89d 100644 (file)
@@ -193,9 +193,7 @@ int aim_conn_addhandler(struct aim_session_t *sess,
   if (!conn)
     return -1;
 
-#if debug > 0
-  printf("aim_conn_addhandler: adding for %04x/%04x\n", family, type);
-#endif
+  faimdprintf(1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
 
   new = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t));
   new->family = family;
@@ -245,9 +243,7 @@ rxcallback_t aim_callhandler(struct aim_conn_t *conn,
   if (!conn)
     return NULL;
 
-#if debug > 0
-  printf("aim_callhandler: calling for %04x/%04x\n", family, type);
-#endif
+  faimdprintf(1, "aim_callhandler: calling for %04x/%04x\n", family, type);
   
   cur = conn->handlerlist;
   while(cur)
@@ -272,7 +268,7 @@ int aim_callhandler_noparam(struct aim_session_t *sess,
   userfunc = aim_callhandler(conn, family, type);
   if (userfunc)
     return userfunc(sess, ptr);
-  return 0;
+  return 1; /* XXX */
 }
 
 /*
@@ -303,287 +299,266 @@ int aim_rxdispatch(struct aim_session_t *sess)
   int i = 0;
   struct command_rx_struct *workingPtr = NULL;
   
-  if (sess->queue_incoming == NULL)
-    /* this shouldn't really happen, unless the main loop's select is broke  */
-    printf("parse_generic: incoming packet queue empty.\n");
-  else
-    {
-      workingPtr = sess->queue_incoming;
-      for (i = 0; workingPtr != NULL; i++)
-       {
-         /*
-          * XXX: This is still fairly ugly.
-          */
-         switch(workingPtr->conn->type)
-           {
-           case -1:
-             /*
-              * This can happen if we have a queued command
-              * that was recieved after a connection has 
-              * been terminated.  In which case, the handler
-              * list has been cleared, and there's nothing we
-              * can do for it.  We can only cancel it.
-              */
-             workingPtr->handled = 1;
-             break;
-           case AIM_CONN_TYPE_AUTH:
-             {
-               u_long head;
-
-               head = aimutil_get32(workingPtr->data);
-               if (head == 0x00000001)
-                 {
-#if debug > 0
-                   printf("got connection ack on auth line\n");
-#endif
-                   workingPtr->handled = 1;
-                 }
-               else
-                 {
-                   u_short family,subtype;
-
-                   family = aimutil_get16(workingPtr->data);
-                   subtype = aimutil_get16(workingPtr->data+2);
-                   
-                   switch (family)
-                     {
-                       /* New login protocol */
+  if (sess->queue_incoming == NULL) {
+    faimdprintf(1, "parse_generic: incoming packet queue empty.\n");
+    return 0;
+  } else {
+    workingPtr = sess->queue_incoming;
+    for (i = 0; workingPtr != NULL; i++) {
+      /*
+       * XXX: This is still fairly ugly.
+       */
+      switch(workingPtr->conn->type) {
+      case -1:
+       /*
+        * This can happen if we have a queued command
+        * that was recieved after a connection has 
+        * been terminated.  In which case, the handler
+        * list has been cleared, and there's nothing we
+        * can do for it.  We can only cancel it.
+        */
+       workingPtr->handled = 1;
+       break;
+      case AIM_CONN_TYPE_AUTH: {
+       u_long head;
+       
+       head = aimutil_get32(workingPtr->data);
+       if (head == 0x00000001) {
+         faimdprintf(1, "got connection ack on auth line\n");
+         workingPtr->handled = 1;
+       } else {
+         u_short family,subtype;
+         
+         family = aimutil_get16(workingPtr->data);
+         subtype = aimutil_get16(workingPtr->data+2);
+         
+         switch (family) {
+           /* New login protocol */
 #ifdef SNACLOGIN
-                     case 0x0017:
-                       if (subtype == 0x0001)
-                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
-                       else if (subtype == 0x0003)
-                         workingPtr->handled = aim_authparse(sess, workingPtr);
-                       else if (subtype == 0x0007)
-                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr);
-                       else
-                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
-                       break;
-#else
-                       /* XXX: this isnt foolproof */
-                     case 0x0001:
-                       if (subtype == 0x0003)
-                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr);
-                       else
-                         workingPtr->handled = aim_authparse(sess, workingPtr);
-                       break;
-                     case 0x0007:
-                       if (subtype == 0x0005)
-                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
-                       break;
-                     default:
-                       /* Old login protocol */
-                       /* any user callbacks will be called from here */
-                       workingPtr->handled = aim_authparse(sess, workingPtr);
+         case 0x0017:
+           if (subtype == 0x0001)
+             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
+           else if (subtype == 0x0003)
+             workingPtr->handled = aim_authparse(sess, workingPtr);
+           else if (subtype == 0x0007)
+             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr);
+           else
+             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
+           break;
+#else  
+           /* XXX: this isnt foolproof */
+         case 0x0001:
+           if (subtype == 0x0003)
+             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr);
+           else
+             workingPtr->handled = aim_authparse(sess, workingPtr);
+           break;
+         case 0x0007:
+           if (subtype == 0x0005)
+             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
+           break;
+         default:
+           /* Old login protocol */
+           /* any user callbacks will be called from here */
+           workingPtr->handled = aim_authparse(sess, workingPtr);
 #endif
-                     }
-                 }
-             }
-             break;
-           case AIM_CONN_TYPE_BOS:
-             {
-               u_short family;
-               u_short subtype;
-
-               family = aimutil_get16(workingPtr->data);
-               subtype = aimutil_get16(workingPtr->data+2);
-
-               switch (family)
-                 {
-                 case 0x0000: /* not really a family, but it works */
-                   if (subtype == 0x0001)
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
-                   else
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
-                   break;
-                 case 0x0001: /* Family: General */
-                   switch (subtype)
-                     {
-                     case 0x0001:
-                       workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
-                       break;
-                     case 0x0003:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
-                       break;
-                     case 0x0005:
-                       workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
-                       break;
-                     case 0x0007:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
-                       break;
-                     case 0x000a:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr);
-                       break;
-                     case 0x000f:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
-                       break;
-                     case 0x0013:
-                       workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
-                       break;
-                     default:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
-                     }
-                   break;
-                 case 0x0002: /* Family: Location */
-                   switch (subtype)
-                     {
-                     case 0x0001:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
-                       break;
-                     case 0x0003:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
-                       break;
-                     case 0x0006:
-                       workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
-                       break;
-                     default:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
-                     }
-                   break;
-                 case 0x0003: /* Family: Buddy List */
-                   switch (subtype)
-                     {
-                     case 0x0001:
-                       workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
-                       break;
-                     case 0x0003:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr);
-                       break;
-                     case 0x000b: /* oncoming buddy */
-                       workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
-                       break;
-                     case 0x000c: /* offgoing buddy */
-                       workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
-                       break;
-                     default:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
-                     }
-                   break;
-                 case 0x0004: /* Family: Messeging */
-                   switch (subtype)
-                     {
-                     case 0x0001:
-                       workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
-                       break;
-                     case 0x0005:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
-                       break;
-                     case 0x0007:
-                       workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
-                       break;
-                     case 0x000a:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
-                       break;
-                     default:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
-                     }
-                   break;
-                 case 0x0009:
-                   if (subtype == 0x0001)
-                     workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
-                   else if (subtype == 0x0003)
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr);
-                   else
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
-                   break;
-                 case 0x000a:  /* Family: User lookup */
-                   switch (subtype)
-                     {
-                     case 0x0001:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
-                       break;
-                     case 0x0003:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
-                       break;
-                     default:
-                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
-                     }
-                   break;
-                 case 0x000b:
-                   if (subtype == 0x0001)
-                     workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
-                   else if (subtype == 0x0002)
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
-                   else
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
-                   break;
-                 default:
-                   workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
-                   break;
-                 }
-             }
-             break;
-           case AIM_CONN_TYPE_CHATNAV:
-             {
-               u_short family;
-               u_short subtype;
-               family = aimutil_get16(workingPtr->data);
-               subtype= aimutil_get16(workingPtr->data+2);
-
-               if ((family == 0x0002) && (subtype == 0x0006))
-                 {
-                   workingPtr->handled = 1;
-                   aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
-                 }
-               else if ((family == 0x000d) && (subtype == 0x0009))
-                 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
-               else
-                 {
-                   workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
-                 }
-             }
-             break;
-           case AIM_CONN_TYPE_CHAT:
-             {
-               u_short family, subtype;
-
-               family = aimutil_get16(workingPtr->data);
-               subtype= aimutil_get16(workingPtr->data+2);
-               
-               if ((family == 0x0000) && (subtype == 0x00001))
-                 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
-               else if (family == 0x0001)
-                 {
-                   if (subtype == 0x0001)
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
-                   else if (subtype == 0x0003)
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
-                   else if (subtype == 0x0007)
-                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
-                   else
-                     printf("Chat: unknown snac %04x/%04x\n", family, subtype);
-                 }
-               else if (family == 0x000e)
-                 {
-                   if (subtype == 0x0002)
-                     workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
-                   else if (subtype == 0x0003)
-                     workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);    
-                   else if (subtype == 0x0004)
-                     workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);     
-                   else if (subtype == 0x0006)
-                     workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
-                   else        
-                     printf("Chat: unknown snac %04x/%04x\n", family, subtype); 
-                 }
-               else
-                 {
-                   printf("Chat: unknown snac %04x/%04x\n", family, subtype);
-                   workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
-                 }
-             }
-             break;
-           default:
-             printf("\nAHHHHH! UNKNOWN CONNECTION TYPE! (type = %d, fd = %d, channel = %02x, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->type, workingPtr->commandlen);
-             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
-             break;
-           }
-         /* move to next command */
-         workingPtr = workingPtr->next;
+         }
+       }
+       break;
+      }
+      case AIM_CONN_TYPE_BOS: {
+       u_short family;
+       u_short subtype;
+       
+       family = aimutil_get16(workingPtr->data);
+       subtype = aimutil_get16(workingPtr->data+2);
+       
+       switch (family) {
+       case 0x0000: /* not really a family, but it works */
+         if (subtype == 0x0001)
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
+         else
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
+         break;
+       case 0x0001: /* Family: General */
+         switch (subtype) {
+         case 0x0001:
+           workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
+           break;
+         case 0x0003:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
+           break;
+         case 0x0005:
+           workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
+           break;
+         case 0x0007:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
+           break;
+         case 0x000a:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr);
+           break;
+         case 0x000f:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
+           break;
+         case 0x0013:
+           workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
+           break;
+         default:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
+           break;
+         }
+       case 0x0002: /* Family: Location */
+         switch (subtype) {
+         case 0x0001:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
+           break;
+         case 0x0003:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
+           break;
+         case 0x0006:
+           workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
+           break;
+         default:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
+           break;
+         }
+       case 0x0003: /* Family: Buddy List */
+         switch (subtype) {
+         case 0x0001:
+           workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
+           break;
+         case 0x0003:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr);
+           break;
+         case 0x000b: /* oncoming buddy */
+           workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
+           break;
+         case 0x000c: /* offgoing buddy */
+           workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
+           break;
+         default:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
+         }
+         break;
+       case 0x0004: /* Family: Messeging */
+         switch (subtype) {
+         case 0x0001:
+           workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
+           break;
+         case 0x0005:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
+           break;
+         case 0x0007:
+           workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
+           break;
+         case 0x000a:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
+           break;
+         default:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
+         }
+         break;
+       case 0x0009:
+         if (subtype == 0x0001)
+           workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
+         else if (subtype == 0x0003)
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr);
+         else
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
+         break;
+       case 0x000a:  /* Family: User lookup */
+         switch (subtype) {
+         case 0x0001:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
+           break;
+         case 0x0003:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
+           break;
+         default:
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
+         }
+         break;
+       case 0x000b:
+         if (subtype == 0x0001)
+           workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
+         else if (subtype == 0x0002)
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
+         else
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
+         break;
+       default:
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
+         break;
+       }
+       break;
+      }
+      case AIM_CONN_TYPE_CHATNAV: {
+       u_short family;
+       u_short subtype;
+       family = aimutil_get16(workingPtr->data);
+       subtype= aimutil_get16(workingPtr->data+2);
+       
+       if ((family == 0x0002) && (subtype == 0x0006)) {
+         workingPtr->handled = 1;
+         aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
+       } else if ((family == 0x000d) && (subtype == 0x0009)) {
+         workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
+       } else {
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
        }
+       break;
+      }
+      case AIM_CONN_TYPE_CHAT: {
+       u_short family, subtype;
+       
+       family = aimutil_get16(workingPtr->data);
+       subtype= aimutil_get16(workingPtr->data+2);
+       
+       if ((family == 0x0000) && (subtype == 0x00001))
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
+       else if (family == 0x0001) {
+         if (subtype == 0x0001)
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
+         else if (subtype == 0x0003)
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
+         else if (subtype == 0x0007)
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
+         else
+           printf("Chat: unknown snac %04x/%04x\n", family, subtype);
+       } else if (family == 0x000e) {
+         if (subtype == 0x0002)
+           workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
+         else if (subtype == 0x0003)
+           workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);      
+         else if (subtype == 0x0004)
+           workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);       
+         else if (subtype == 0x0006)
+           workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
+         else  
+           printf("Chat: unknown snac %04x/%04x\n", family, subtype); 
+       } else {
+         printf("Chat: unknown snac %04x/%04x\n", family, subtype);
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
+       }
+       break;
+      }
+      default:
+       printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, channel = %02x, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->type, workingPtr->commandlen);
+       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
+       break;
+      }        
+      /* move to next command */
+      workingPtr = workingPtr->next;
     }
+  }
 
-  sess->queue_incoming = aim_purge_rxqueue(sess->queue_incoming);
+  /* 
+   * This doesn't have to be called here.  It could easily be done
+   * by a seperate thread or something. It's an administrative operation,
+   * and can take a while. Though the less you call it the less memory
+   * you'll have :)
+   */
+  aim_purge_rxqueue(sess);
   
   return 0;
 }
@@ -691,7 +666,7 @@ int aim_parse_unknown(struct aim_session_t *sess,
 {
   u_int i = 0;
 
-  printf("\nRecieved unknown packet:");
+  faimdprintf(1, "\nRecieved unknown packet:");
 
   for (i = 0; i < command->commandlen; i++)
     {
index 8baa058409cf48e04155fd568498b296607cf378..88721c4a79d81d15e373a45cb9a222d0844b5f37 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <faim/aim.h> 
 
+
 /*
  * This is a modified read() to make SURE we get the number
  * of bytes we are told to, otherwise block.
@@ -16,7 +17,7 @@
  * Modified to count errno (Sébastien Carpe <scarpe@atos-group.com>)
  * 
 */
-int Read(int fd, u_char *buf, int len)
+int aim_failsaferead(int fd, u_char *buf, int len)
 {
   int i = 0;
   int j = 0;
@@ -59,19 +60,17 @@ int aim_get_command(struct aim_session_t *sess)
   struct timeval tv;
   char generic[6]; 
   struct command_rx_struct *workingStruct = NULL;
-  struct command_rx_struct *workingPtr = NULL;
   struct aim_conn_t *conn = NULL;
-#if debug > 0
-  printf("Reading generic/unknown response...");
-#endif
-  
-  
+  int selstat = 0;
+
+  faimdprintf(1, "Reading generic/unknown response...");
+
   /* dont wait at all (ie, never call this unless something is there) */
   tv.tv_sec = 0; 
   tv.tv_usec = 0;
-  conn = aim_select(sess, &tv);
+  conn = aim_select(sess, &tv, &selstat);
 
-  if (conn==NULL)
+  if (conn==NULL) 
     return 0;  /* nothing waiting */
 
   s = conn->fd;
@@ -92,7 +91,7 @@ int aim_get_command(struct aim_session_t *sess)
   /* read first 6 bytes (the FLAP header only) off the socket */
   while ( (select(s+1, &fds, NULL, NULL, &tv) == 1) && (i < 6))
     {
-      if ((err = Read(s, &(generic[i]), 1)) < 0)
+      if ((err = aim_failsaferead(s, &(generic[i]), 1)) < 0)
        {
          /* error is probably not recoverable...(must be a pessimistic day) */
          aim_conn_close(conn);
@@ -104,26 +103,18 @@ int aim_get_command(struct aim_session_t *sess)
          if (generic[i] == 0x2a)
          {
            readgood = 1;
-#if debug > 1
-           printf("%x ", generic[i]);
-           fflush(stdout);
-#endif
+           faimdprintf(1, "%x ", generic[i]);
            i++;
          }
          else
            {
-#if debug > 1
-             printf("skipping 0x%d ", generic[i]);
-             fflush(stdout);
-#endif
+             faimdprintf(1, "skipping 0x%d ", generic[i]);
              j++;
            }
        }
       else
        {
-#if debug > 1
-         printf("%x ", generic[i]);
-#endif
+         faimdprintf(1, "%x ", generic[i]);
          i++;
        }
       FD_ZERO(&fds);
@@ -132,19 +123,21 @@ int aim_get_command(struct aim_session_t *sess)
       tv.tv_usec= 2;
     }
 
-  if (generic[0] != 0x2a)
-    {
-      /* this really shouldn't happen, since the main loop
-        select() should protect us from entering this function
-        without data waiting  */
-      printf("Bad incoming data!");
-      return -1;
-    }
+  /*
+   * This shouldn't happen unless the socket breaks, the server breaks,
+   * or we break.  We must handle it just in case.
+   */
+  if (generic[0] != 0x2a) {
+    printf("Bad incoming data!");
+    return -1;
+  }    
 
   isav = i;
 
   /* allocate a new struct */
   workingStruct = (struct command_rx_struct *) malloc(sizeof(struct command_rx_struct));
+  memset(workingStruct, 0x00, sizeof(struct command_rx_struct));
+
   workingStruct->lock = 1;  /* lock the struct */
 
   /* store channel -- byte 2 */
@@ -156,20 +149,18 @@ int aim_get_command(struct aim_session_t *sess)
   /* store commandlen -- bytes 5 and 6 */
   workingStruct->commandlen = aimutil_get16(generic+4);
 
+  workingStruct->nofree = 0; /* free by default */
+
   /* malloc for data portion */
   workingStruct->data = (u_char *) malloc(workingStruct->commandlen);
 
   /* read the data portion of the packet */
-  i = Read(s, workingStruct->data, workingStruct->commandlen);
-  if (i < 0)
-    {
-      aim_conn_close(conn);
-      return i;
-    }
+  if (aim_failsaferead(s, workingStruct->data, workingStruct->commandlen) < 0){
+    aim_conn_close(conn);
+    return -1;
+  }
 
-#if debug > 0
-  printf(" done. (%db+%db read, %db skipped)\n", isav, i, j);
-#endif
+  faimdprintf(1, " done. (%db+%db read, %db skipped)\n", isav, i, j);
 
   workingStruct->conn = conn;
 
@@ -177,18 +168,21 @@ int aim_get_command(struct aim_session_t *sess)
   workingStruct->lock = 0; /* unlock */
 
   /* enqueue this packet */
-  if (sess->queue_incoming == NULL)
-    {
-      sess->queue_incoming = workingStruct;
-    }
-  else
-    {
-      workingPtr = sess->queue_incoming;
-      while (workingPtr->next != NULL)
-       workingPtr = workingPtr->next;
-      workingPtr->next = workingStruct;
-    }
-  
+  if (sess->queue_incoming == NULL) {
+    sess->queue_incoming = workingStruct;
+  } else {
+    struct command_rx_struct *cur;
+
+    /*
+     * This append operation takes a while.  It might be faster
+     * if we maintain a pointer to the last entry in the queue
+     * and just update that.  Need to determine if the overhead
+     * to maintain that is lower than the overhead for this loop.
+     */
+    for (cur = sess->queue_incoming; cur->next; cur = cur->next)
+      ;
+    cur->next = workingStruct;
+  }
   
   workingStruct->conn->lastactivity = time(NULL);
 
@@ -196,71 +190,59 @@ int aim_get_command(struct aim_session_t *sess)
 }
 
 /*
- *  purge_rxqueue()
+ * Purge recieve queue of all handled commands (->handled==1).  Also
+ * allows for selective freeing using ->nofree so that the client can
+ * keep the data for various purposes.  
  *
- *  This is just what it sounds.  It purges the receive (rx) queue of
- *  all handled commands.  This is normally called from inside 
- *  aim_rxdispatch() after it's processed all the commands in the queue.
+ * If ->nofree is nonzero, the frame will be delinked from the global list, 
+ * but will not be free'ed.  The client _must_ keep a pointer to the
+ * data -- libfaim will not!  If the client marks ->nofree but
+ * does not keep a pointer, it's lost forever.
  *
  */
-struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue)
+void aim_purge_rxqueue(struct aim_session_t *sess)
 {
-  struct command_rx_struct *workingPtr = NULL;
-  struct command_rx_struct *workingPtr2 = NULL;
+  struct command_rx_struct *cur = NULL;
+  struct command_rx_struct *tmp;
 
-  if (queue == (struct command_rx_struct *)NULL) 
-    {
-    /* do nothing */
-    }
-  else if (queue->next == (struct command_rx_struct *)NULL)
-    {
-      if (queue->handled == 1) {
-       workingPtr = queue;
-       queue = NULL;
-       free(workingPtr->data);
-       free(workingPtr);
-      }
-    }
-  else 
-    {
-      while (queue && queue->handled == 1) 
-       {
-         workingPtr = queue;
-         queue = queue->next;
-         free(workingPtr->data);
-         free(workingPtr);
-       }
-
-      workingPtr = queue;
-
-      while (workingPtr && (workingPtr->next != (struct command_rx_struct *)NULL))
-       {
-         if (workingPtr->next->handled == 1) 
-           {
-             workingPtr2 = workingPtr->next;
-             workingPtr->next = workingPtr->next->next;
-             free(workingPtr2->data);
-             free(workingPtr2);
-           } 
-         else /* TODO: rework this so the additional if isn't needed */
-           {
-             if (workingPtr->next == (struct command_rx_struct *)NULL) 
-               {
-                 if (workingPtr->handled == 1)
-                   {
-                     workingPtr2 = workingPtr;
-                     workingPtr = NULL;
-                     free(workingPtr2->data);
-                     free(workingPtr2);
-                     return queue;
-                   }
-               } 
-             else 
-               {
-                 workingPtr = workingPtr->next;
-               }
-           }
-       }
+  if (sess->queue_incoming == NULL)
+    return;
+  
+  if (sess->queue_incoming->next == NULL) {
+    if (sess->queue_incoming->handled) {
+      tmp = sess->queue_incoming;
+      sess->queue_incoming = NULL;
+
+      if (!tmp->nofree) {
+       free(tmp->data);
+       free(tmp);
+      } else
+       tmp->next = NULL;
     }
-  return queue;
+    return;
+  }
+
+  for(cur = sess->queue_incoming; cur->next != NULL; ) {
+    if (cur->next->handled) {
+      tmp = cur->next;
+      cur->next = tmp->next;
+      if (!tmp->nofree) {
+       free(tmp->data);
+       free(tmp);
+      } else
+       tmp->next = NULL;
+    }  
+    cur = cur->next;
+
+    /* 
+     * Be careful here.  Because of the way we just
+     * manipulated the pointer, cur may be NULL and 
+     * the for() will segfault doing the check unless
+     * we find this case first.
+     */
+    if (cur == NULL)   
+      break;
+  }
+
+  return;
 }
index f2ed1e8b844ebd4737430e5226104e09926da8f1..8a42e333e2a06af6a6309085f881182d3ee7183a 100644 (file)
  *   6) Return
  *
  */
-
 int aim_tx_enqueue(struct aim_session_t *sess,
                   struct command_tx_struct *newpacket)
 {
-  struct command_tx_struct *workingPtr = NULL;
+  struct command_tx_struct *cur;
   struct command_tx_struct *newpacket_copy = NULL;
 
-  if (newpacket->conn == NULL)
-    {
-      printf("aim_tx_enqueue: WARNING: enqueueing packet with no connecetion,  defaulting to BOS\n");
+  if (newpacket->conn == NULL) {
+      faimdprintf(1, "aim_tx_enqueue: WARNING: enqueueing packet with no connecetion,  defaulting to BOS\n");
       newpacket->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
-    }
+  }
  
   newpacket_copy = (struct command_tx_struct *) malloc (sizeof(struct command_tx_struct));
   memcpy(newpacket_copy, newpacket, sizeof(struct command_tx_struct));
@@ -43,33 +41,23 @@ int aim_tx_enqueue(struct aim_session_t *sess,
   newpacket_copy->sent = 0; /* not sent yet */
   newpacket_copy->next = NULL; /* always last */
 
-  if (sess->queue_outgoing == NULL)
-    {
-      sess->queue_outgoing = newpacket_copy;
-    }
-  else
-    {
-      workingPtr = sess->queue_outgoing;
-      while (workingPtr->next != NULL)
-       workingPtr = workingPtr->next;
-      workingPtr->next = newpacket_copy;
-    }
+  /* see overhead note in aim_rxqueue counterpart */
+  if (sess->queue_outgoing == NULL) {
+    sess->queue_outgoing = newpacket_copy;
+  } else {
+    for (cur = sess->queue_outgoing;
+        cur->next;
+        cur = cur->next)
+      ;
+    cur->next = newpacket_copy;
+  }
 
   newpacket_copy->lock = 0; /* unlock so it can be sent */
 
-#if debug > 2
-  printf("calling aim_tx_printqueue()\n");
+#if debug == 2
+  faimdprintf(2, "calling aim_tx_printqueue()\n");
   aim_tx_printqueue(sess);
-  printf("back from aim_tx_printqueue()\n");
-#endif
-
-  /* we'll force a flush for now -- this behavior probably will change */
-#if debug > 1
-  printf("calling aim_tx_flushqueue()\n");
-#endif
-  aim_tx_flushqueue(sess);
-#if debug > 1
-  printf("back from aim_tx_flushqueue()\n");
+  faimdprintf(2, "back from aim_tx_printqueue()\n");
 #endif
 
   return 0;
@@ -97,29 +85,26 @@ u_int aim_get_next_txseqnum(struct aim_conn_t *conn)
  *  if the queue isn't working quite right.
  *
  */
-#if debug > 2
+#if debug == 2
 int aim_tx_printqueue(struct aim_session_t *sess)
 {
-  struct command_tx_struct *workingPtr = NULL;
+  struct command_tx_struct *cur;
 
-  workingPtr = sess->queue_outgoing;
-#if debug > 2
-  printf("\ncurrent aim_queue_outgoing...\n");
-  printf("\ttype seqnum  len  lock sent\n");  
-#endif
-  if (workingPtr == NULL)
-    printf("aim_tx_flushqueue(): queue empty");
-  else
-    {
-      while (workingPtr != NULL)
-       {
-         printf("\t  %2x   %4x %4x   %1d    %1d\n", workingPtr->type, workingPtr->seqnum, workingPtr->commandlen, workingPtr->lock, workingPtr->sent);
-         
-         workingPtr = workingPtr->next;
-       }
-    }
+  faimdprintf(2, "\ncurrent aim_queue_outgoing...\n");
+  faimdprintf(2, "\ttype seqnum  len  lock sent\n");  
+
+  if (sess->queue_outgoing == NULL)
+    faimdprintf(2, "aim_tx_flushqueue(): queue empty");
+  else {
+      for (cur = sess->queue_outgoing; cur; cur = cur->next) {
+         faimdprintf(2, "\t  %2x   %4x %4x   %1d    %1d\n", 
+                     cur->type, cur->seqnum, 
+                     cur->commandlen, cur->lock, 
+                     cur->sent);
+      }
+  }
 
-  printf("\n(done printing queue)\n");
+  faimdprintf(2, "\n(done printing queue)\n");
   
   return 0;
 }
@@ -151,97 +136,81 @@ int aim_tx_printqueue(struct aim_session_t *sess)
  */
 int aim_tx_flushqueue(struct aim_session_t *sess)
 {
-  struct command_tx_struct *workingPtr = NULL;
+  struct command_tx_struct *cur;
   u_char *curPacket = NULL;
 #if debug > 1
   int i = 0;
 #endif
 
-  workingPtr = sess->queue_outgoing;
-#if debug > 1
-  printf("beginning txflush...\n");
-#endif
-  while (workingPtr != NULL)
-    {
-      /* only process if its unlocked and unsent */
-      if ( (workingPtr->lock == 0) &&
-          (workingPtr->sent == 0) )
-       {
-
-         /*
-          * And now for the meager attempt to force transmit
-          * latency and avoid missed messages.
-          */
-         if ((workingPtr->conn->lastactivity + workingPtr->conn->forcedlatency) 
-             >= time(NULL))
-           {
-             /* FIXME FIXME -- should be a break! we dont want to block the upper layers */
-             sleep((workingPtr->conn->lastactivity + workingPtr->conn->forcedlatency) - time(NULL));
-           }
-
-         workingPtr->lock = 1; /* lock the struct */
-         
-         /* allocate full-packet buffer */
-         curPacket = (char *) malloc(workingPtr->commandlen + 6);
-         
-         /* command byte */
-         curPacket[0] = 0x2a;
+  if (sess->queue_outgoing == NULL)
+    return 0;
 
-         /* type/family byte */
-         curPacket[1] = workingPtr->type;
+  faimdprintf(2, "beginning txflush...\n");
+  for (cur = sess->queue_outgoing; cur; cur = cur->next) {
+    /* only process if its unlocked and unsent */
+    if (!cur->lock && !cur->sent) {
 
-         /* bytes 3+4: word: FLAP sequence number */
-         aimutil_put16(curPacket+2, workingPtr->seqnum);
+      /*
+       * And now for the meager attempt to force transmit
+       * latency and avoid missed messages.
+       */
+      if ((cur->conn->lastactivity + cur->conn->forcedlatency) >= time(NULL)) {
+       /* FIXME FIXME -- should be a break! we dont want to block the upper layers */
+       sleep((cur->conn->lastactivity + cur->conn->forcedlatency) - time(NULL));
+      }
+      
+      cur->lock = 1; /* lock the struct */
+      
+      /* allocate full-packet buffer */
+      curPacket = (char *) malloc(cur->commandlen + 6);
+      
+      /* command byte */
+      curPacket[0] = 0x2a;
+      
+      /* type/family byte */
+      curPacket[1] = cur->type;
+      
+      /* bytes 3+4: word: FLAP sequence number */
+      aimutil_put16(curPacket+2, cur->seqnum);
 
-         /* bytes 5+6: word: SNAC len */
-         aimutil_put16(curPacket+4, workingPtr->commandlen);
+      /* bytes 5+6: word: SNAC len */
+      aimutil_put16(curPacket+4, cur->commandlen);
+      
+      /* bytes 7 and on: raw: SNAC data */
+      memcpy(&(curPacket[6]), cur->data, cur->commandlen);
+      
+      /* full image of raw packet data now in curPacket */
+      if ( (u_int)write(cur->conn->fd, curPacket, (cur->commandlen + 6)) != (cur->commandlen + 6)) {
+       printf("\nWARNING: Error in sending packet 0x%4x -- will try again next time\n\n", cur->seqnum);
+       cur->sent = 0; /* mark it unsent */
+       continue; /* bail out */
+      } else {
+       faimdprintf(2, "\nSENT 0x%4x\n\n", cur->seqnum);
 
-         /* bytes 7 and on: raw: SNAC data */
-         memcpy(&(curPacket[6]), workingPtr->data, workingPtr->commandlen);
-         
-         /* full image of raw packet data now in curPacket */
-         if ( (u_int)write(workingPtr->conn->fd, curPacket, (workingPtr->commandlen + 6)) != (workingPtr->commandlen + 6))
-           {
-             printf("\nWARNING: Error in sending packet 0x%4x -- will try again next time\n\n", workingPtr->seqnum);
-             workingPtr->sent = 0; /* mark it unsent */
-             return -1;  /* bail out */
-           }
-         else
-           {
-#if debug > 2
-             printf("\nSENT 0x%4x\n\n", workingPtr->seqnum);
-#endif
-             workingPtr->sent = 1; /* mark the struct as sent */
-             workingPtr->conn->lastactivity = time(NULL);
-           }
+       cur->sent = 1; /* mark the struct as sent */
+       cur->conn->lastactivity = time(NULL);
+      }
 #if debug > 2
-         printf("\nPacket:");
-         for (i = 0; i < (workingPtr->commandlen + 6); i++)
-           {
-             if ((i % 8) == 0)
-               printf("\n\t");
-             if (curPacket[i] >= ' ' && curPacket[i]<127)
-                printf("%c=%02x ",curPacket[i], curPacket[i]);
-             else
-                printf("0x%2x ", curPacket[i]);
-           }
-         printf("\n");
-#endif
-         workingPtr->lock = 0; /* unlock the struct */
-         free(curPacket); /* free up full-packet buffer */
+      faimdprintf(2, "\nPacket:");
+      for (i = 0; i < (cur->commandlen + 6); i++) {
+       if ((i % 8) == 0) {
+         faimdprintf(2, "\n\t");
+       }
+       if (curPacket[i] >= ' ' && curPacket[i]<127) {
+         faimdprintf(2, "%c=%02x ", curPacket[i], curPacket[i]);
+       } else {
+         faimdprintf(2, "0x%2x ", curPacket[i]);
        }
-      workingPtr = workingPtr->next;
+      }
+      faimdprintf(2, "\n");
+#endif
+      cur->lock = 0; /* unlock the struct */
+      free(curPacket); /* free up full-packet buffer */
     }
+  }
 
   /* purge sent commands from queue */
-  /*   this may not always occur explicitly--i may put this on a timer later */
-#if debug > 1
-  printf("calling aim_tx_purgequeue()\n");
-#endif
   aim_tx_purgequeue(sess);
-#if debug > 1
-  printf("back from aim_tx_purgequeu() [you must be a lucky one]\n");
-#endif
 
   return 0;
 }
@@ -254,68 +223,41 @@ int aim_tx_flushqueue(struct aim_session_t *sess)
  *  reduce memory footprint at run time!  
  *
  */
-int aim_tx_purgequeue(struct aim_session_t *sess)
+void aim_tx_purgequeue(struct aim_session_t *sess)
 {
-  struct command_tx_struct *workingPtr = NULL;
-  struct command_tx_struct *workingPtr2 = NULL;
-#if debug > 1
-  printf("purgequeue(): starting purge\n");
-#endif
-  /* Empty queue: nothing to do */
+  struct command_tx_struct *cur = NULL;
+  struct command_tx_struct *tmp;
+
   if (sess->queue_outgoing == NULL)
-    {
-#if debug > 1
-      printf("purgequeue(): purge done (len=0)\n");
-#endif
-      return 0;
-    }
-  /* One Node queue: free node and return */
-  else if (sess->queue_outgoing->next == NULL)
-    {
-#if debug > 1
-      printf("purgequeue(): entered case len=1\n");
-#endif
-      /* only free if sent AND unlocked -- dont assume sent structs are done */
-      if ( (sess->queue_outgoing->lock == 0) &&
-          (sess->queue_outgoing->sent == 1) )
-       {
-#if debug > 1
-         printf("purgequeue(): purging seqnum 0x%04x\n", sess->queue_outgoing->seqnum);
-#endif
-         workingPtr2 = sess->queue_outgoing;
-         sess->queue_outgoing = NULL;
-         free(workingPtr2->data);
-         free(workingPtr2);
-       }
-#if debug > 1
-      printf("purgequeue(): purge done (len=1)\n");
-#endif
-      return 0;
-    }
-  else
-    {
-#if debug > 1
-      printf("purgequeue(): entering case len>1\n");
-#endif
-      while(workingPtr->next != NULL)
-       {
-         if ( (workingPtr->next->lock == 0) &&
-              (workingPtr->next->sent == 1) )
-           {
-#if debug > 1
-             printf("purgequeue(): purging seqnum 0x%04x\n", workingPtr->next->seqnum);
-#endif
-             workingPtr2 = workingPtr->next;
-             workingPtr->next = workingPtr2->next;
-             free(workingPtr2->data);
-             free(workingPtr2);
-           }
-       }
-#if debug > 1
-      printf("purgequeue(): purge done (len>1)\n");
-#endif
-      return 0;
+    return;
+  
+  if (sess->queue_outgoing->next == NULL) {
+    if (!sess->queue_outgoing->lock && sess->queue_outgoing->sent) {
+      tmp = sess->queue_outgoing;
+      sess->queue_outgoing = NULL;
+      free(tmp->data);
+      free(tmp);
     }
+    return;
+  }
+
+  for(cur = sess->queue_outgoing; cur->next != NULL; ) {
+    if (!cur->next->lock && cur->next->sent) {
+      tmp = cur->next;
+      cur->next = tmp->next;
+      free(tmp->data);
+      free(tmp);
+    }  
+    cur = cur->next;
 
-  /* no reach */
+    /* 
+     * Be careful here.  Because of the way we just
+     * manipulated the pointer, cur may be NULL and 
+     * the for() will segfault doing the check unless
+     * we find this case first.
+     */
+    if (cur == NULL)   
+      break;
+  }
+  return;
 }
index bf813bcc4678a3aa9b74e86550dcf15d35380168..96b2059dea4c114fef4845cef50005ad674a8d4d 100644 (file)
  */
 #define AIM_COOKIELEN            0x100
 
+#if debug > 0
+#define faimdprintf(l, x...) {if (l >= debug) printf(x); }
+#else
+#define faimdprintf(l, x...)
+#endif
+
 /*
  * Login info.  Passes information from the Authorization
  * stage of login to the service (BOS, etc) connection
@@ -126,6 +132,7 @@ struct command_rx_struct {
   u_char *data;             /* packet data (from 7 byte on) */
   u_int lock;               /* 0 = open, !0 = locked */
   u_int handled;            /* 0 = new, !0 = been handled */
+  u_int nofree;                    /* 0 = free data on purge, 1 = only unlink */
   struct aim_conn_t *conn;  /* the connection it came in on... */
   struct command_rx_struct *next; /* ptr to next struct in list */
 };
@@ -247,7 +254,6 @@ int aim_puttlv_32(u_char *, u_short, u_long);
 int aim_puttlv_str(u_char *buf, u_short t, u_short l, u_char *v);
 int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list);
 int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val);
-int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val);
 int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str);
 
 /*
@@ -274,7 +280,7 @@ int aim_send_login (struct aim_session_t *, struct aim_conn_t *, char *, char *,
 int aim_encode_password(const char *, u_char *);
 
 
-struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue);
+void aim_purge_rxqueue(struct aim_session_t *);
 
 
 int aim_parse_unknown(struct aim_session_t *, struct command_rx_struct *command, ...);
@@ -285,7 +291,7 @@ int aim_tx_enqueue(struct aim_session_t *, struct command_tx_struct *);
 u_int aim_get_next_txseqnum(struct aim_conn_t *);
 int aim_tx_flushqueue(struct aim_session_t *);
 int aim_tx_printqueue(struct aim_session_t *);
-int aim_tx_purgequeue(struct aim_session_t *);
+void aim_tx_purgequeue(struct aim_session_t *);
 
 struct aim_rxcblist_t {
   u_short family;
@@ -325,7 +331,7 @@ void aim_conn_close(struct aim_conn_t *deadconn);
 struct aim_conn_t *aim_getconn_type(struct aim_session_t *, int type);
 struct aim_conn_t *aim_newconn(struct aim_session_t *, int type, char *dest);
 int aim_conngetmaxfd(struct aim_session_t *);
-struct aim_conn_t *aim_select(struct aim_session_t *, struct timeval *);
+struct aim_conn_t *aim_select(struct aim_session_t *, struct timeval *, int *);
 int aim_conn_isready(struct aim_conn_t *);
 int aim_conn_setstatus(struct aim_conn_t *, int);
 void aim_session_init(struct aim_session_t *);
index 1456a0f99c8dded2b897825c442ecbcb8f3dca44..fc400f504596fe21d6cd5576f920388d65b4c3a0 100644 (file)
@@ -71,9 +71,10 @@ int main(void)
 {
   struct aim_session_t aimsess;
   struct aim_conn_t *authconn = NULL;
-  int stayconnected = 1;
+  int keepgoing = 1, stayconnected = 1;
   struct client_info_s info = {"FAIMtest (Hi guys!)", 3, 5, 1670, "us", "en"};
-    
+  int selstat = 0;
+
   aim_session_init(&aimsess);
 
   if ( !(screenname = getenv("SCREENNAME")) ||
@@ -120,27 +121,40 @@ int main(void)
 #endif
     }
 
-  while (aim_select(&aimsess, NULL) > (struct aim_conn_t *)0)
-    {
-      if (aimsess.queue_outgoing)
-       aim_tx_flushqueue(&aimsess);
+  while (keepgoing) {
+    aim_select(&aimsess, NULL, &selstat);
 
-      if (aim_get_command(&aimsess) < 0)
-       {
+    switch(selstat) {
+    case -1: /* error */
+      keepgoing = 0;
+      break;
+
+    case 0: /* no events pending */
+      break;
+
+    case 1: /* outgoing data pending */
+      aim_tx_flushqueue(&aimsess);
+      break;
+
+    case 2: /* incoming data pending */
+      if (aim_get_command(&aimsess) < 0) {
          printf("\afaimtest: connection error!\n");
-       }
-      else
+      } else
        aim_rxdispatch(&aimsess);
+      break;
+      
+    default:
+      break; /* invalid */
     }
+  }
 
   /* Close up */
-  printf("AIM just decided we didn't need to be here anymore, closing up.,,\n");
+  printf("AIM just decided we didn't need to be here anymore, closing up...\n");
   
   /* close up all connections, dead or no */
   aim_logoff(&aimsess); 
 
-  if (stayconnected)
-    {
+  if (stayconnected) {
       printf("\nTrying to reconnect in 2 seconds...\n");
       sleep(2);
       goto enter;
This page took 0.202825 seconds and 5 git commands to generate.