]> andersk Git - libfaim.git/commitdiff
- Tue Jun 6 01:36:48 UTC 2000
authormid <mid>
Tue, 6 Jun 2000 02:52:55 +0000 (02:52 +0000)
committermid <mid>
Tue, 6 Jun 2000 02:52:55 +0000 (02:52 +0000)
   - Inverted gethostbyname2() check.  Not sure how that ended up
       in that state.
   - Added some of the initial framework to support file transfers
   - Added in a few checks for that
     - Can currently parse and send a denial message.
   - Added cookie caching.  (Sorry, I just like saying that.)
   - Rearranged channel 2 ICBM parsing (detects the different
       rendezvous types better and hopefully accuratly).
   - Killed the connection array.  Now a list.  (Suits the
       upcoming features better.)  --- REQUIRES CLIENT CHANGES...
     - In most cases, you need to change aim_conn_close() calls
         to aim_conn_kill().  This will free them as well as
         close them.  If you don't do this, you'll pollute the
         connection list and leak memory.
   - Possibly a few other minor things (some cleanups to faimtest for one)

CHANGES
Makefile
aim_chat.c
aim_conn.c
aim_im.c
aim_logoff.c
aim_msgcookie.c [new file with mode: 0644]
aim_rxqueue.c
faim/aim.h
mkbuildinfo.sh
utils/faimtest/faimtest.c

diff --git a/CHANGES b/CHANGES
index 8007e7d3f9b3ae08d386764ae19537efcd4610e2..268afdb969d42432002b35bdcd5f0147bc133357 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,23 @@
 
 No release numbers
 ------------------
+ - Tue Jun  6 01:36:48 UTC 2000
+   - Inverted gethostbyname2() check.  Not sure how that ended up 
+       in that state.
+   - Added some of the initial framework to support file transfers
+   - Added in a few checks for that
+     - Can currently parse and send a denial message.
+   - Added cookie caching.  (Sorry, I just like saying that.)
+   - Rearranged channel 2 ICBM parsing (detects the different
+       rendezvous types better and hopefully accuratly).
+   - Killed the connection array.  Now a list.  (Suits the
+       upcoming features better.)  --- REQUIRES CLIENT CHANGES...
+     - In most cases, you need to change aim_conn_close() calls
+         to aim_conn_kill().  This will free them as well as 
+         close them.  If you don't do this, you'll pollute the
+         connection list and leak memory.
+   - Possibly a few other minor things (some cleanups to faimtest for one)
+
  - Fri Jun  2 23:27:28 UTC 2000
    - Cleaned up aim_send_login slightly
    - Added aimicq_encode_password to support the new hash
index 150a156bd68d769b550e2490690e05e6383351fc..937f844d5324d7603eb4b1ed8ca7fb2ba6e193ad 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,8 @@ LIBFAIM_OBJECTS = \
        aim_chat.o \
        aim_chatnav.o \
        aim_util.o \
-       aim_meta.o
+       aim_meta.o \
+       aim_msgcookie.o
 
 all: libfaim allutils
 
index 85cf21564f70b0af8e636ca4be5f92eadf27188c..0543ade2b06f0c56359fc020cbb1eccd2f72032b 100644 (file)
@@ -19,20 +19,18 @@ char *aim_chat_getname(struct aim_conn_t *conn)
 
 struct aim_conn_t *aim_chat_getconn(struct aim_session_t *sess, char *name)
 {
-  int i;
+  struct aim_conn_t *cur;
+  
+  faim_mutex_lock(&sess->connlistlock);
+  for (cur = sess->connlist; cur; cur = cur->next) {
+    if (cur->type != AIM_CONN_TYPE_CHAT)
+      continue;
+    if (strcmp((char *)cur->priv, name) == 0)
+      break;
+  }
+  faim_mutex_unlock(&sess->connlistlock);
 
-  for (i=0;i<AIM_CONN_MAX;i++)
-    {
-      if (sess->conns[i].type == AIM_CONN_TYPE_CHAT)
-       {
-         if (sess->conns[i].priv)
-           if (!strcmp((char *)sess->conns[i].priv, name))
-             {
-               return &sess->conns[i];
-             }
-       }
-    }
-  return NULL;
+  return cur;
 }
 
 int aim_chat_attachname(struct aim_conn_t *conn, char *roomname)
@@ -542,21 +540,14 @@ u_long aim_chat_clientready(struct aim_session_t *sess,
 
 int aim_chat_leaveroom(struct aim_session_t *sess, char *name)
 {
-  int i;
+  struct aim_conn_t *conn;
 
-  for (i=0;i<AIM_CONN_MAX;i++)
-    {
-      if (sess->conns[i].type == AIM_CONN_TYPE_CHAT)
-       {
-         if (sess->conns[i].priv)
-           if (!strcmp((char *)sess->conns[i].priv, name))
-             {
-               aim_conn_close(&sess->conns[i]);
-               return 0;
-             }
-       }
-    }
-  return -1;
+  if ((conn = aim_chat_getconn(sess, name)))
+    aim_conn_kill(sess, &conn);
+
+  if (!conn)
+    return -1;
+  return 0;
 }
 
 /*
index ff81277ded4759dfc32ffe139cb7bfd97e9c7938..061409f74b78a672d39eda164e2f76b21683c18f 100644 (file)
@@ -8,21 +8,83 @@
 
 #include <faim/aim.h> 
 
+/*
+ * Clears out connection list, killing remaining connections.
+ */
 void aim_connrst(struct aim_session_t *sess)
 {
-  int i;
-  for (i = 0; i < AIM_CONN_MAX; i++) {
-    aim_conn_close(&sess->conns[i]);
+  faim_mutex_init(&sess->connlistlock, NULL);
+  if (sess->connlist) {
+    struct aim_conn_t *cur = sess->connlist, *tmp;
+
+    while(cur) {
+      tmp = cur->next;
+      aim_conn_close(cur);
+      free(cur);
+      cur = tmp;
+    }
   }
+  sess->connlist = NULL;
+  return;
 }
 
+/*
+ * Gets a new connection structure.
+ */
 struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess)
 {
-  int i;
-  for (i=0;i<AIM_CONN_MAX;i++)
-    if (sess->conns[i].fd == -1)
-      return &(sess->conns[i]);
-  return NULL;
+  struct aim_conn_t *newconn, *cur;
+
+  if (!(newconn = malloc(sizeof(struct aim_conn_t))))  
+    return NULL;
+
+  memset(newconn, 0, sizeof(struct aim_conn_t));
+  aim_conn_close(newconn);
+  newconn->next = NULL;
+
+  faim_mutex_lock(&sess->connlistlock);
+  if (sess->connlist == NULL)
+    sess->connlist = newconn;
+  else {
+    for (cur = sess->connlist; cur->next; cur = cur->next)
+      ;
+    cur->next = newconn;
+  }
+  faim_mutex_unlock(&sess->connlistlock);
+
+  return newconn;
+}
+
+void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn)
+{
+  struct aim_conn_t *cur;
+
+  if (!deadconn || !*deadconn) 
+    return;
+
+  faim_mutex_lock(&sess->connlistlock);
+  if (sess->connlist == NULL)
+    ;
+  else if (sess->connlist->next == NULL) {
+    if (sess->connlist == *deadconn)
+      sess->connlist = NULL;
+  } else {
+    cur = sess->connlist;
+    while (cur->next) {
+      if (cur->next == *deadconn) {
+       cur->next = cur->next->next;
+       break;
+      }
+      cur = cur->next;
+    }
+  }
+  faim_mutex_unlock(&sess->connlistlock);
+
+  aim_conn_close(*deadconn);
+  free(*deadconn);
+  deadconn = NULL;
+
+  return;
 }
 
 void aim_conn_close(struct aim_conn_t *deadconn)
@@ -47,11 +109,15 @@ void aim_conn_close(struct aim_conn_t *deadconn)
 struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
                                    int type)
 {
-  int i;
-  for (i=0; i<AIM_CONN_MAX; i++)
-    if (sess->conns[i].type == type)
-      return &(sess->conns[i]);
-  return NULL;
+  struct aim_conn_t *cur;
+
+  faim_mutex_lock(&sess->connlistlock);
+  for (cur = sess->connlist; cur; cur = cur->next) {
+    if (cur->type == type)
+      break;
+  }
+  faim_mutex_unlock(&sess->connlistlock);
+  return cur;
 }
 
 /*
@@ -73,15 +139,18 @@ struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
   u_short port = FAIM_LOGIN_PORT;
   char *host = NULL;
   int i=0;
-  
+
   if ((connstruct=aim_conn_getnext(sess))==NULL)
     return NULL;
 
+  faim_mutex_lock(&connstruct->active);
+  
   connstruct->type = type;
 
   if (!dest) { /* just allocate a struct */
     connstruct->fd = -1;
     connstruct->status = 0;
+    faim_mutex_unlock(&connstruct->active);
     return connstruct;
   }
 
@@ -104,11 +173,12 @@ struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
   strncpy(host, dest, i);
   host[i] = '\0';
 
-  hp = gethostbyname2(host, AF_INET);
+  hp = gethostbyname(host);
   free(host);
 
   if (hp == NULL) {
     connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
+    faim_mutex_unlock(&connstruct->active);
     return connstruct;
   }
 
@@ -122,29 +192,40 @@ struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
   if(ret < 0) {
     connstruct->fd = -1;
     connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
+    faim_mutex_unlock(&connstruct->active);
     return connstruct;
   }
   
+  faim_mutex_unlock(&connstruct->active);
+
   return connstruct;
 }
 
 int aim_conngetmaxfd(struct aim_session_t *sess)
 {
-  int i,j;
+  int j = 0;
+  struct aim_conn_t *cur;
+
+  faim_mutex_lock(&sess->connlistlock);
+  for (cur = sess->connlist; cur; cur = cur->next) {
+    if (cur->fd > j)
+      j = cur->fd;
+  }
+  faim_mutex_unlock(&sess->connlistlock);
 
-  for (i=0,j=0;i<AIM_CONN_MAX;i++)
-    if(sess->conns[i].fd > j)
-      j = sess->conns[i].fd;
   return j;
 }
 
 int aim_countconn(struct aim_session_t *sess)
 {
-  int i,cnt;
+  int cnt = 0;
+  struct aim_conn_t *cur;
+
+  faim_mutex_lock(&sess->connlistlock);
+  for (cur = sess->connlist; cur; cur = cur->next)
+    cnt++;
+  faim_mutex_unlock(&sess->connlistlock);
 
-  for (i=0,cnt=0;i<AIM_CONN_MAX;i++)
-    if (sess->conns[i].fd > -1)
-      cnt++;
   return cnt;
 }
 
@@ -160,15 +241,23 @@ int aim_countconn(struct aim_session_t *sess)
  *    1  outgoing data pending (NULL returned)
  *    2  incoming data pending (connection with pending data returned)
  *
+ * XXX: we could probably stand to do a little courser locking here.
+ *
  */ 
 struct aim_conn_t *aim_select(struct aim_session_t *sess,
                              struct timeval *timeout, int *status)
 {
+  struct aim_conn_t *cur;
   fd_set fds;
+  int maxfd = 0;
   int i;
 
-  if (aim_countconn(sess) <= 0)
+  faim_mutex_lock(&sess->connlistlock);
+  if (sess->connlist == NULL) {
+    faim_mutex_unlock(&sess->connlistlock);
     return 0;
+  }
+  faim_mutex_unlock(&sess->connlistlock);
 
   /* 
    * If we have data waiting to be sent, return immediatly
@@ -179,24 +268,28 @@ struct aim_conn_t *aim_select(struct aim_session_t *sess,
   } 
 
   FD_ZERO(&fds);
-  
-  for(i=0;i<AIM_CONN_MAX;i++)
-    if (sess->conns[i].fd>-1)
-      FD_SET(sess->conns[i].fd, &fds);
-  
-  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 */
+  maxfd = 0;
+
+  faim_mutex_lock(&sess->connlistlock);
+  for (cur = sess->connlist; cur; cur = cur->next) {
+    FD_SET(cur->fd, &fds);
+    if (cur->fd > maxfd)
+      maxfd = cur->fd;
+  }
+  faim_mutex_unlock(&sess->connlistlock);
+
+  if ((i = select(maxfd+1, &fds, NULL, NULL, timeout))>=1) {
+    faim_mutex_lock(&sess->connlistlock);
+    for (cur = sess->connlist; cur; cur = cur->next) {
+      if (FD_ISSET(cur->fd, &fds)) {
+       *status = 2;
+       faim_mutex_unlock(&sess->connlistlock);
+       return cur;
+      }
+    }
   }
 
+  faim_mutex_unlock(&sess->connlistlock);
   *status = i; /* may be 0 or -1 */
   return NULL;  /* no waiting or error, return */
 }
@@ -205,25 +298,31 @@ int aim_conn_isready(struct aim_conn_t *conn)
 {
   if (conn)
     return (conn->status & 0x0001);
-  else
-    return -1;
+  return -1;
 }
 
 int aim_conn_setstatus(struct aim_conn_t *conn, int status)
 {
-  if (conn)
-    return (conn->status ^= status);
-  else
+  int val;
+
+  if (!conn)
     return -1;
+  
+  faim_mutex_lock(&conn->active);
+  val = conn->status ^= status;
+  faim_mutex_unlock(&conn->active);
+  return val;
 }
 
 int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
 {
   if (!conn)
     return -1;
-  
+
+  faim_mutex_lock(&conn->active);
   conn->forcedlatency = newval;
   conn->lastactivity = 0; /* reset this just to make sure */
+  faim_mutex_unlock(&conn->active);
 
   return 0;
 }
@@ -233,15 +332,8 @@ void aim_session_init(struct aim_session_t *sess)
   if (!sess)
     return;
 
-  memset(sess->logininfo.screen_name, 0x00, MAXSNLEN);
-  sess->logininfo.BOSIP = NULL;
-  memset(sess->logininfo.cookie, 0x00, AIM_COOKIELEN);
-  sess->logininfo.email = NULL;
-  sess->logininfo.regstatus = 0x00;
-
-  memset(sess->conns, 0, sizeof(struct aim_conn_t)*AIM_CONN_MAX);
+  memset(sess, 0, sizeof(struct aim_session_t));
   aim_connrst(sess);
-
   sess->queue_outgoing = NULL;
   sess->queue_incoming = NULL;
   sess->pendingjoin = NULL;
index d39a3ae9ad5fa46f56eed80f7f4288c322c1155e..3be7e40b4960e63deb6d1a3506034126b60900f1 100644 (file)
--- a/aim_im.c
+++ b/aim_im.c
@@ -350,10 +350,11 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess,
     }
   else if (channel == 0x0002)
     {  
-      int rendtype;
       struct aim_tlv_t *block1;
       struct aim_tlvlist_t *list2;
       struct aim_tlv_t *tmptlv;
+      struct aim_tlv_t *miscinfo;
+      unsigned short reqclass = 0;
       int a;
       
       /* Class. */
@@ -376,8 +377,11 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess,
        * There's another block of TLVs embedded in the type 5 here. 
        */
       block1 = aim_gettlv(tlvlist, 0x0005, 1);
-      if (!block1)
+      if (!block1) {
+       printf("faim: no tlv 0x0005 in rendezvous transaction!\n");
+       aim_freetlvchain(&tlvlist);
        return 1; /* major problem */
+      }
 
       a = 0x1a; /* skip -- not sure what this information is! */
 
@@ -387,77 +391,187 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess,
        * Its probably just an accepted invitation or something.
        *  
        */
-      if (block1->length <= 0x1a)
-       {
+      if (block1->length <= 0x1a) {
+       aim_freetlvchain(&tlvlist);
+       return 1;
+      }
+
+      list2 = aim_readtlvchain(block1->value+a, block1->length-a);
+
+      if (!(miscinfo = aim_gettlv(list2, 0x2711, 1))) {
+       struct aim_msgcookie_t *cook;
+
+       if ((cook = aim_uncachecookie(sess, cookie)) == NULL) {
+         printf("faim: no 0x2711 info TLV in rendezvous and its not in cache!\n");
+         aim_freetlvchain(&list2);
          aim_freetlvchain(&tlvlist);
          return 1;
        }
 
-      list2 = aim_readtlvchain(block1->value+a, block1->length-a);
+       if (cook->type == 1) {
+         struct aim_filetransfer_t *ft;
 
-      if (aim_gettlv(list2, 0x0004, 1) /* start connection */ ||  
-         aim_gettlv(list2, 0x000b, 1) /* close conncetion */)
-       {
-         rendtype = 1; /* voice request */
-
-         /*
-          * Call client.
-          */
-         userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
-         if (userfunc)
-           i = userfunc(sess, 
-                        command, 
-                        channel, 
-                        rendtype,
-                        &userinfo);
-         else 
-           i = 0;
-       }
-      else
-       {
-         struct aim_chat_roominfo roominfo;
-         char *msg=NULL,*encoding=NULL,*lang=NULL;
-
-         rendtype = 0; /* chat invite */
-         if (aim_gettlv(list2, 0x2711, 1))
-           {
-             struct aim_tlv_t *nametlv;
-             
-             nametlv = aim_gettlv(list2, 0x2711, 1);
-             aim_chat_readroominfo(nametlv->value, &roominfo);
+         if (cook->data) {
+           struct aim_tlv_t *errortlv;
+           int errorcode = -1;
+
+           ft = (struct aim_filetransfer_t *)cook->data;
+
+           if ((errortlv = aim_gettlv(list2, 0x000b, 1))) {
+             errorcode = aimutil_get16(errortlv->value);
            }
+           printf("faim: transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sender, ft->ip, ft->filename, errorcode);
+           free(cook->data);
+         } else {
+           printf("faim: not data attached to file transfer\n");
+         }
+
+       } else {
+         printf("faim: unknown cookie cache type %d\n", cook->type);
+       }
+
+       free(cook);
+       return 1;
+      }
+
+
+      /*
+       * Parse the first two bytes of the 0x2711 TLV.  
+       *
+       * This can be interpretted in a couple ways.  
+       *
+       * It could be said that its a service type or some such and
+       * that voice is 0, file transfer is 1, and chat is 4 (and 5).
+       *
+       * Or it could be said that its an exchange value.  Exchanges
+       * four and five are for chat, voice is on exchange zero and
+       * file transfer is done on exchange 1.  
+       *
+       * It should work out the same no how its thought of.
+       *
+       */
+      reqclass = aimutil_get16(miscinfo->value+0);
+   
+      switch (reqclass) {      
+      case AIM_RENDEZVOUS_VOICE: {
+
+       /* XXX: implement all this */
+
+       /*
+        * Call client.
+        */
+       userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
+       if (userfunc || (i = 0)) {
+         i = userfunc(sess, 
+                      command, 
+                      channel, 
+                      reqclass,
+                      &userinfo);
+       }
+       break;
+      }
+      case AIM_RENDEZVOUS_FILETRANSFER: {
+       char ip[30];
+       char *desc = NULL;
+       struct aim_msgcookie_t cachedcook;
+       struct aim_filetransfer_t *ft;
+
+       memset(ip, 0, sizeof(ip));
+       
+       if (aim_gettlv(list2, 0x0003, 1) && aim_gettlv(list2, 0x0003, 1)) {
+         struct aim_tlv_t *iptlv, *porttlv;
          
-         if (aim_gettlv(list2, 0x000c, 1))
-           msg = aim_gettlv_str(list2, 0x000c, 1);
+         iptlv = aim_gettlv(list2, 0x0003, 1);
+         porttlv = aim_gettlv(list2, 0x0005, 1);
+
+         snprintf(ip, sizeof(ip)-1, "%d.%d.%d.%d:%d", 
+                 aimutil_get8(iptlv->value+0),
+                 aimutil_get8(iptlv->value+1),
+                 aimutil_get8(iptlv->value+2),
+                 aimutil_get8(iptlv->value+3),
+                 aimutil_get16(porttlv->value));
+       }
+
+       if (aim_gettlv(list2, 0x000c, 1)) {
+         desc = aim_gettlv_str(list2, 0x000c, 1);
+       }
+
+       printf("faim: rend: file transfer request from %s for %s: %s (%s)\n",
+              userinfo.sn,
+              miscinfo->value+8,
+              desc, 
+              ip);
+       
+       memcpy(cachedcook.cookie, cookie, 8);
+       memcpy(cachedcook.extended, block1->value+10, 16);
+       
+       ft = malloc(sizeof(struct aim_filetransfer_t));
+       strncpy(ft->sender, userinfo.sn, sizeof(ft->sender));
+       strncpy(ft->ip, ip, sizeof(ft->ip));
+       ft->filename = strdup(miscinfo->value+8);
+       cachedcook.type = 1; 
+       cachedcook.data = ft;
+
+       if (aim_cachecookie(sess, &cachedcook) != 0)
+         printf("faim: ERROR caching message cookie\n");
+       
+       
+       aim_denytransfer(sess, command->conn, ft->sender, cookie, 0);
+
+       free(desc);
+       
+       i = 1;
+       break;
+      }
+      case AIM_RENDEZVOUS_FILETRANSFER_GET: {
+       printf("faim: file get request (unsupported)\n");
+       i = 1;
+       break;
+      }
+      case AIM_RENDEZVOUS_CHAT_EX3:
+      case AIM_RENDEZVOUS_CHAT_EX4:
+      case AIM_RENDEZVOUS_CHAT_EX5: {
+       struct aim_chat_roominfo roominfo;
+       char *msg=NULL,*encoding=NULL,*lang=NULL;
+
+       aim_chat_readroominfo(miscinfo->value, &roominfo);
+                 
+       if (aim_gettlv(list2, 0x000c, 1))
+         msg = aim_gettlv_str(list2, 0x000c, 1);
          
-         if (aim_gettlv(list2, 0x000d, 1))
-           encoding = aim_gettlv_str(list2, 0x000d, 1);
+       if (aim_gettlv(list2, 0x000d, 1))
+         encoding = aim_gettlv_str(list2, 0x000d, 1);
          
-         if (aim_gettlv(list2, 0x000e, 1))
-           lang = aim_gettlv_str(list2, 0x000e, 1);
-      
-         /*
-          * Call client.
-          */
-         userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
-         if (userfunc)
-           i = userfunc(sess, 
-                        command, 
-                        channel, 
-                        rendtype,
-                        &userinfo, 
-                        &roominfo, 
-                        msg, 
-                        encoding?encoding+1:NULL, 
-                        lang?lang+1:NULL);
-         else 
-           i = 0;
+       if (aim_gettlv(list2, 0x000e, 1))
+         lang = aim_gettlv_str(list2, 0x000e, 1);
       
+       /*
+        * Call client.
+        */
+       userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
+       if (userfunc || (i = 0))
+         i = userfunc(sess, 
+                      command, 
+                      channel, 
+                      reqclass, /* == roominfo->exchange */
+                      &userinfo, 
+                      &roominfo, 
+                      msg, 
+                      encoding?encoding+1:NULL, 
+                      lang?lang+1:NULL);
          free(roominfo.name);
          free(msg);
          free(encoding);
          free(lang);
-       }
+         break;
+      }
+      default: {
+       printf("faim: rendezvous: unknown rend class 0x%04x\n", reqclass);
+       i = 1;
+       break;
+      }
+      } /* switch */
+
       aim_freetlvchain(&list2);
     }
 
@@ -470,6 +584,41 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess,
   return i;
 }
 
+/*
+ * Possible codes:
+ *    AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support"
+ *    AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer"
+ *    AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers"
+ * 
+ */
+u_long aim_denytransfer(struct aim_session_t *sess,
+                       struct aim_conn_t *conn, 
+                       char *sender,
+                       char *cookie, 
+                       unsigned short code)
+{
+  struct command_tx_struct *newpacket;
+  int curbyte, i;
+
+  if(!(newpacket = aim_tx_new(0x0002, conn, 10+8+2+1+strlen(sender)+6)))
+    return -1;
+
+  newpacket->lock = 1;
+
+  curbyte = aim_putsnac(newpacket->data, 0x0004, 0x000b, 0x0000, sess->snac_nextid);
+  for (i = 0; i < 8; i++)
+    curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
+  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
+  curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sender));
+  curbyte += aimutil_putstr(newpacket->data+curbyte, sender, strlen(sender));
+  curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0003, code);
+
+  newpacket->lock = 0;
+  aim_tx_enqueue(sess, newpacket);
+
+  return (sess->snac_nextid++);
+}
+
 /*
  * Not real sure what this does, nor does anyone I've talk to.
  *
index b16eef16ab974e95c1de9469c7fc6123bbc4bb98..f5d03752dc2e168d89fd75dc197ae9c9522b44fc 100644 (file)
  */
 int aim_logoff(struct aim_session_t *sess)
 {
-  int i = AIM_CONN_MAX-1;
-  while (i > -1)
-    {
-      if (sess->conns[i].fd>-1)
-       aim_conn_close(&(sess->conns[i]));
-      i--;
-    }
   aim_connrst(sess);  /* in case we want to connect again */
 
   return 0;
diff --git a/aim_msgcookie.c b/aim_msgcookie.c
new file mode 100644 (file)
index 0000000..3481162
--- /dev/null
@@ -0,0 +1,99 @@
+
+/*
+ *
+ *
+ */
+
+#include <faim/aim.h>
+
+int aim_cachecookie(struct aim_session_t *sess,
+                   struct aim_msgcookie_t *cookie)
+{
+  struct aim_msgcookie_t *newcook = NULL, *cur = NULL;
+  
+  if (!cookie)
+    return -1;
+
+  if (!(newcook = malloc(sizeof(struct aim_msgcookie_t))))
+    return -1;
+  memcpy(newcook, cookie, sizeof(struct aim_msgcookie_t));
+  newcook->addtime = time(NULL);
+  newcook->next = NULL;
+
+  cur = sess->msgcookies;
+  
+  if (cur == NULL) {
+    sess->msgcookies = newcook;
+    return 0;
+  }
+  while (cur->next != NULL)
+    cur = cur->next;
+  cur->next = newcook;
+
+  return 0;
+}
+
+struct aim_msgcookie_t *aim_uncachecookie(struct aim_session_t *sess, 
+                                         char *cookie)
+{
+  struct aim_msgcookie_t *cur;
+
+  if (!cookie)
+    return NULL;
+
+  if (!sess->msgcookies)
+    return NULL;
+
+  if (memcmp(sess->msgcookies->cookie, cookie, 8) == 0) {
+    cur = sess->msgcookies;
+    sess->msgcookies = cur->next;
+    return cur;
+  } 
+
+  cur = sess->msgcookies;
+  while (cur->next) {
+    if (memcmp(cur->next->cookie, cookie, 8) == 0) {
+      struct aim_msgcookie_t *tmp;
+      
+      tmp = cur->next;
+      cur->next = cur->next->next;
+      return tmp;
+    }
+    cur = cur->next;
+  }
+  return NULL;
+}
+
+/*
+ */
+int aim_purgecookies(struct aim_session_t *sess)
+{
+  int maxage = 5*60;
+  struct aim_msgcookie_t *cur;
+  struct aim_msgcookie_t *remed = NULL;
+  time_t curtime;
+  cur = sess->msgcookies;
+  
+  curtime = time(&curtime);
+  while (cur) {
+    if ( (cur) && (((cur->addtime) + maxage) < curtime)) {
+#if DEBUG > 1
+      printf("aimmsgcookie: WARNING purged obsolete message cookie %x%x%x%x %x%x%x%x\n",
+            cur->cookie[0], cur->cookie[1], cur->cookie[2], cur->cookie[3],
+            cur->cookie[4], cur->cookie[5], cur->cookie[6], cur->cookie[7]);
+#endif
+      remed = aim_uncachecookie(sess, cur->cookie);
+      if (remed) {
+       if (remed->data)
+         free(remed->data);
+       free(remed);
+      }
+    }
+    cur = cur->next;
+  }
+  
+  return 0;
+}
+
index d82d6f49072ef8bef259f4e9b1c7266ff3ed84f2..481e49b07c713e82d9ba68f2e28e165b2826ef97 100644 (file)
@@ -23,6 +23,13 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn)
   if (conn->fd < 3)  /* can happen when people abuse the interface */
     return 0;
 
+  /*
+   * Rendezvous (client-client) connections do not speak
+   * FLAP, so this function will break on them.
+   */
+  if (conn->type > 0x01000)
+    return 0;
+
   /*
    * Read FLAP header.  Six bytes:
    *    
index 24cb4ce8fb0cfbeb0b64f5d0262c4bc6837e7845..d0d2da4d49e0266b5914d5dbfb1ce349895e1c06 100644 (file)
@@ -52,9 +52,9 @@
 #define strlen(x) (int)strlen(x)  /* win32 has a unsigned size_t */
 #endif
 
-#if defined(_WIN32) || (defined(mach) && defined(__APPLE__)) 
-#define gethostbyname2(x,y) gethostbyname(x) /* revert to IPv4 */
-#endif 
+#if defined(mach) && defined(__APPLE__)
+#define gethostbyname(x) gethostbyname2(x, AF_INET) 
+#endif
 
 /* 
  * Current Maximum Length for Screen Names (not including NULL) 
@@ -144,6 +144,7 @@ struct client_info_s {
 #define AIM_CONN_TYPE_BOS           0x0002
 #define AIM_CONN_TYPE_CHAT          0x000e
 #define AIM_CONN_TYPE_CHATNAV       0x000d
+#define AIM_CONN_TYPE_RENDEZVOUS    0x0101 /* these do not speak OSCAR! */
 
 /*
  * Status values returned from aim_conn_new().  ORed together.
@@ -164,6 +165,7 @@ struct aim_conn_t {
   struct aim_rxcblist_t *handlerlist;
   faim_mutex_t active; /* lock around read/writes */
   faim_mutex_t seqnum_lock; /* lock around ->seqnum changes */
+  struct aim_conn_t *next;
 };
 
 /* struct for incoming commands */
@@ -218,7 +220,8 @@ struct aim_session_t {
   /* 
    * Connection information
    */
-  struct aim_conn_t conns[AIM_CONN_MAX];
+  struct aim_conn_t *connlist;
+  faim_mutex_t connlistlock;
   
   /* 
    * TX/RX queues 
@@ -245,6 +248,8 @@ struct aim_session_t {
    **/
   struct aim_snac_t *outstanding_snacs;
   u_long snac_nextid;
+
+  struct aim_msgcookie_t *msgcookies;
 };
 
 
@@ -316,6 +321,7 @@ int aim_rxdispatch(struct aim_session_t *);
 
 int aim_logoff(struct aim_session_t *);
 
+void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn);
 
 typedef int (*rxcallback_t)(struct aim_session_t *, struct command_rx_struct *, ...);
 int aim_register_callbacks(rxcallback_t *);
@@ -457,6 +463,36 @@ extern u_char aim_caps[6][16];
 #define AIM_GETINFO_GENERALINFO 0x00001
 #define AIM_GETINFO_AWAYMESSAGE 0x00003
 
+#define AIM_RENDEZVOUS_VOICE 0x0000
+#define AIM_RENDEZVOUS_FILETRANSFER 0x0001
+#define AIM_RENDEZVOUS_CHAT_EX3 0x0003
+#define AIM_RENDEZVOUS_CHAT_EX4 0x0004
+#define AIM_RENDEZVOUS_CHAT_EX5 0x0005
+#define AIM_RENDEZVOUS_FILETRANSFER_GET 0x0012
+
+struct aim_msgcookie_t {
+  unsigned char cookie[8];
+  unsigned char extended[16];
+  int type;
+  void *data;
+  time_t addtime;
+  struct aim_msgcookie_t *next;
+};
+
+struct aim_filetransfer_t {
+  char sender[MAXSNLEN];       
+  char ip[30];
+  char *filename;
+};
+int aim_cachecookie(struct aim_session_t *sess, struct aim_msgcookie_t *cookie);
+struct aim_msgcookie_t *aim_uncachecookie(struct aim_session_t *sess, char *cookie);
+int aim_purgecookies(struct aim_session_t *sess);
+
+#define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000
+#define AIM_TRANSFER_DENY_DECLINE 0x0001
+#define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002
+u_long aim_denytransfer(struct aim_session_t *sess, struct aim_conn_t *conn, char *sender, char *cookie, unsigned short code);
+
 u_long aim_getinfo(struct aim_session_t *, struct aim_conn_t *, const char *, unsigned short);
 int aim_extractuserinfo(u_char *, struct aim_userinfo_s *);
 int aim_parse_userinfo_middle(struct aim_session_t *, struct command_rx_struct *);
index ed36c5a7499db4925bb31e2da42e0b04e266548f..2c4fc97f93ea05f1d8dc5184068f89589fa5e17a 100755 (executable)
@@ -2,9 +2,9 @@
 rm -rf aim_meta.o aim_buildcode.h
 
 echo -n "#define AIM_BUILDDATE \"" > aim_buildcode.h
-echo -n `date +%Y%m%e` >> aim_buildcode.h
+echo -n `date +%Y%m%d` >> aim_buildcode.h
 echo "\"" >> aim_buildcode.h
 
 echo -n "#define AIM_BUILDTIME \"" >> aim_buildcode.h
 echo -n `date +%H%M%S` >> aim_buildcode.h
-echo "\"" >> aim_buildcode.h
\ No newline at end of file
+echo "\"" >> aim_buildcode.h
index 2ac66ec1419b94551bfaa4216f79cf86c7657c38..1bf7414fda115b0b24704bfa08213b4cc5629a2a 100644 (file)
@@ -101,35 +101,30 @@ int main(void)
  enter:
   authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER);
 
-  if (authconn == NULL)
-    {
-      fprintf(stderr, "faimtest: internal connection error while in aim_login.  bailing out.\n");
-      return -1;
-    }
-  else if (authconn->fd == -1)
-    {
-      if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
-       fprintf(stderr, "faimtest: could not resolve authorizer name\n");
-      else if (authconn->status & AIM_CONN_STATUS_CONNERR)
-       fprintf(stderr, "faimtest: could not connect to authorizer\n");
-      return -1;
-    }
-  else
-    {
+  if (authconn == NULL) {
+    fprintf(stderr, "faimtest: internal connection error while in aim_login.  bailing out.\n");
+    return -1;
+  } else if (authconn->fd == -1) {
+    if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
+      fprintf(stderr, "faimtest: could not resolve authorizer name\n");
+    else if (authconn->status & AIM_CONN_STATUS_CONNERR)
+      fprintf(stderr, "faimtest: could not connect to authorizer\n");
+    aim_conn_kill(&aimsess, &authconn);
+    return -1;
+  } else {
 #ifdef SNACLOGIN
-      /* new login code -- not default -- pending new password encryption algo */
-      aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
-      aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
-
-      aim_sendconnack(&aimsess, authconn);
-      aim_request_login(&aimsess, authconn, FAIMTEST_SCREENNAME);
+    /* new login code -- not default -- pending new password encryption algo */
+    aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
+    aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
+    
+    aim_sendconnack(&aimsess, authconn);
+    aim_request_login(&aimsess, authconn, FAIMTEST_SCREENNAME);
 #else
-      aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_parse_authresp, 0);
-      aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
-      aim_send_login(&aimsess, authconn, screenname, password, &info);
+    aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_parse_authresp, 0);
+    aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
+    aim_send_login(&aimsess, authconn, screenname, password, &info);
 #endif
-    }
+  }
 
   while (keepgoing) {
     waitingconn = aim_select(&aimsess, NULL, &selstat);
@@ -297,11 +292,11 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
       {
        struct aim_conn_t *tstconn = NULL;
        tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
-       if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
-         {
-           fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
-           return 1;
-         }
+       if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) {
+         fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
+         if (tstconn) aim_conn_kill(sess, &tstconn);
+         return 1;
+       }
 #if 0
        aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
        aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
@@ -322,6 +317,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
        if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
          {
            fprintf(stderr, "faimtest: unable to connect to chat server\n");
+           if (tstconn) aim_conn_kill(sess, &tstconn);
            return 1;
          }             
        printf("faimtest: chat: connected\n");
@@ -359,7 +355,7 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct
     {
       printf("Login Error Code 0x%04x\n", sess->logininfo.errorcode);
       printf("Error URL: %s\n", sess->logininfo.errorurl);
-      aim_conn_close(command->conn);
+      aim_conn_kill(sess, &command->conn);
       exit(0); /* XXX: should return in order to let the above things get free()'d. */
     }
 
@@ -368,40 +364,36 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct
   printf("BOS IP: %s\n", sess->logininfo.BOSIP);
 
   printf("Closing auth connection...\n");
-  aim_conn_close(command->conn);
+  aim_conn_kill(sess, &command->conn);
   bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, sess->logininfo.BOSIP);
-  if (bosconn == NULL)
-    {
-      fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
-    }
-  else if (bosconn->status != 0)
-    {
-      fprintf(stderr, "faimtest: could not connect to BOS\n");
-    }
-  else
-    {
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, NULL, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
-
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
-
-      aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
-
-      aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie);
-    }
+  if (bosconn == NULL) {
+    fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
+  } else if (bosconn->status != 0) {   
+    fprintf(stderr, "faimtest: could not connect to BOS\n");
+    aim_conn_kill(sess, &bosconn);
+  } else {
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, NULL, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
+    
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
+    
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
+    
+    aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie);
+  }
   return 1;
 }
 
@@ -446,6 +438,8 @@ int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct
     printf("UNKNOWN_BIT4 ");
   if (userinfo->class & 0x0010)
     printf("FREE ");
+  if (userinfo->class & 0x0040)
+    printf("ICQ? ");
   printf("\n");
   
   printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
@@ -490,24 +484,97 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str
   /*
    * Channel 1: Standard Message
    */
-  if (channel == 1)
-    {
-      struct aim_userinfo_s *userinfo;
-      char *msg = NULL;
-      u_int icbmflags = 0;
-      char *tmpstr = NULL;
-      u_short flag1, flag2;
-  
+  if (channel == 1) {
+    struct aim_userinfo_s *userinfo;
+    char *msg = NULL;
+    u_int icbmflags = 0;
+    char *tmpstr = NULL;
+    u_short flag1, flag2;
+    
+    userinfo = va_arg(ap, struct aim_userinfo_s *);
+    msg = va_arg(ap, char *);
+    icbmflags = va_arg(ap, u_int);
+    flag1 = va_arg(ap, u_short);
+    flag2 = va_arg(ap, u_short);
+    va_end(ap);
+    
+    printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
+    printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
+    printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
+    if (userinfo->class & 0x0010)
+      printf("(FREE) ");
+    if (userinfo->class & 0x0001)
+      printf("(TRIAL) ");
+    if (userinfo->class & 0x0004)
+      printf("(AOL) ");
+    printf("\n");
+    printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
+    printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
+    printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
+    
+    printf("faimtest: icbm: icbmflags = ");
+    if (icbmflags & AIM_IMFLAGS_AWAY)
+      printf("away ");
+    if (icbmflags & AIM_IMFLAGS_ACK)
+      printf("ackrequest ");
+    printf("\n");
+    
+    printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
+    
+    printf("faimtest: icbm: message: %s\n", msg);
+    
+    if (msg) {
+      tmpstr = index(msg, '>');
+      if (tmpstr != NULL)
+       tmpstr+=1;
+      else
+       tmpstr = msg;
+      
+      if ( (strlen(tmpstr) >= 10) &&
+          (!strncmp(tmpstr, "disconnect", 10)) ) {
+         aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
+         aim_logoff(sess);
+      } else if (strstr(tmpstr, "goodday")) {
+       printf("faimtest: icbm: sending response\n");
+       aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too.");
+      } else if (!strncmp(tmpstr, "open chatnav", 12)) {
+       aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
+       //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
+      } else if (!strncmp(tmpstr, "create", 6)) {
+       aim_chatnav_createroom(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), "WorldDomination", 0x0004);
+      } else if (!strncmp(tmpstr, "close chatnav", 13)) {
+       struct aim_conn_t *chatnavconn;
+       chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
+       aim_conn_kill(sess, &chatnavconn);
+      } else if (!strncmp(tmpstr, "join", 4)) {
+         aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
+      } else if (!strncmp(tmpstr, "leave", 5))
+           aim_chat_leaveroom(sess, "worlddomination");
+      else if (!strncmp(tmpstr, "getinfo", 7)) {
+       aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
+       aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
+      } else {
+       printf("unknown command.\n");
+      }
+      
+    }
+  }
+  /*
+   * Channel 2: Rendevous Request
+   */
+  else if (channel == 2) {
+    struct aim_userinfo_s *userinfo;
+    unsigned short reqclass;
+    
+    reqclass = va_arg(ap, unsigned short);
+    switch (reqclass) {
+    case AIM_RENDEZVOUS_VOICE: {
       userinfo = va_arg(ap, struct aim_userinfo_s *);
-      msg = va_arg(ap, char *);
-      icbmflags = va_arg(ap, u_int);
-      flag1 = va_arg(ap, u_short);
-      flag2 = va_arg(ap, u_short);
       va_end(ap);
       
-      printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
-      printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
-      printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
+      printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
+      printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
+      printf("faimtest: voice invitation: \tclass = 0x%04x ", userinfo->class);
       if (userinfo->class & 0x0010)
        printf("(FREE) ");
       if (userinfo->class & 0x0001)
@@ -515,143 +582,60 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str
       if (userinfo->class & 0x0004)
        printf("(AOL) ");
       printf("\n");
-      printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
-      printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
-      printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
+      /* we dont get membersince on chat invites! */
+      printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
+      printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
       
-      printf("faimtest: icbm: icbmflags = ");
-      if (icbmflags & AIM_IMFLAGS_AWAY)
-       printf("away ");
-      if (icbmflags & AIM_IMFLAGS_ACK)
-       printf("ackrequest ");
-      printf("\n");
+      break;
+    }
+    case AIM_RENDEZVOUS_FILETRANSFER: {
+      printf("faimtset: file transfer!\n");
+      break;
+    }
+    case AIM_RENDEZVOUS_CHAT_EX3:
+    case AIM_RENDEZVOUS_CHAT_EX4:
+    case AIM_RENDEZVOUS_CHAT_EX5: {
+      char *msg,*encoding,*lang;
+      struct aim_chat_roominfo *roominfo;
       
-      printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
+      userinfo = va_arg(ap, struct aim_userinfo_s *);
+      roominfo = va_arg(ap, struct aim_chat_roominfo *);
+      msg = va_arg(ap, char *);
+      encoding = va_arg(ap, char *);
+      lang = va_arg(ap, char *);
+      va_end(ap);
       
-      printf("faimtest: icbm: message: %s\n", msg);
+      printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
+      printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
+      printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class);
+      if (userinfo->class & 0x0010)
+       printf("(FREE) ");
+      if (userinfo->class & 0x0001)
+       printf("(TRIAL) ");
+      if (userinfo->class & 0x0004)
+       printf("(AOL) ");
+      printf("\n");
+      /* we dont get membersince on chat invites! */
+      printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
+      printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
       
-      if (msg)
-       {
-         tmpstr = index(msg, '>');
-         if (tmpstr != NULL)
-           tmpstr+=1;
-         else
-           tmpstr = msg;
-         
-         if ( (strlen(tmpstr) >= 10) &&
-              (!strncmp(tmpstr, "disconnect", 10)) )
-           {
-             aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
-             aim_logoff(sess);
-           }
-         else if (strstr(tmpstr, "goodday"))
-           {
-             printf("faimtest: icbm: sending response\n");
-             aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too.");
-           }
-         else if (!strncmp(tmpstr, "open chatnav", 12))
-           {
-             aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
-             //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
-           }
-         else if (!strncmp(tmpstr, "create", 6))
-           {
-             aim_chatnav_createroom(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), "WorldDomination", 0x0004);
-           }
-         else if (!strncmp(tmpstr, "close chatnav", 13))
-           aim_conn_close(aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV));
-         else if (!strncmp(tmpstr, "join", 4))
-           {
-             aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
-           }
-         else if (!strncmp(tmpstr, "leave", 5))
-           aim_chat_leaveroom(sess, "worlddomination");
-         else if (!strncmp(tmpstr, "getinfo", 7)) {
-           aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO);
-           aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
-         } else 
-           {
-#if 0
-             printf("faimtest: icbm:  starting chat...\n");
-             aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
-#else
-             aim_bos_setidle(sess, command->conn, 0x0ffffffe);
-#endif
-           }
-         
-       }
-    }
-  /*
-   * Channel 2: Rendevous Request
-   */
-  else if (channel == 2)
-    {
-      struct aim_userinfo_s *userinfo;
-      int rendtype = 0;
-
-      rendtype = va_arg(ap, int);
-      if (rendtype == 0)
-       {
-         char *msg,*encoding,*lang;
-         struct aim_chat_roominfo *roominfo;
-         
-         userinfo = va_arg(ap, struct aim_userinfo_s *);
-         roominfo = va_arg(ap, struct aim_chat_roominfo *);
-         msg = va_arg(ap, char *);
-         encoding = va_arg(ap, char *);
-         lang = va_arg(ap, char *);
-         va_end(ap);
-         
-         printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
-         printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
-         printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class);
-         if (userinfo->class & 0x0010)
-           printf("(FREE) ");
-         if (userinfo->class & 0x0001)
-           printf("(TRIAL) ");
-         if (userinfo->class & 0x0004)
-           printf("(AOL) ");
-         printf("\n");
-         /* we dont get membersince on chat invites! */
-         printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
-         printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
-         
-         printf("faimtest: chat invitation: message = %s\n", msg);
-         printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
-         printf("faimtest: chat invitation: encoding = %s\n", encoding);
-         printf("faimtest: chat invitation: language = %s\n", lang);
-         printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
-         printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
-         printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
-         /*
-          * Automatically join room...
-          */ 
-         aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
-       }       
-      else if (rendtype == 1)
-       {
-         userinfo = va_arg(ap, struct aim_userinfo_s *);
-         va_end(ap);
-         
-         printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
-         printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
-         printf("faimtest: voice invitation: \tclass = 0x%04x ", userinfo->class);
-         if (userinfo->class & 0x0010)
-           printf("(FREE) ");
-         if (userinfo->class & 0x0001)
-           printf("(TRIAL) ");
-         if (userinfo->class & 0x0004)
-           printf("(AOL) ");
-         printf("\n");
-         /* we dont get membersince on chat invites! */
-         printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
-         printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
-         
-       }
-      else
-       printf("faimtest: icbm: unknown rendtype (%d)\n", rendtype);
-    }
-  else
+      printf("faimtest: chat invitation: message = %s\n", msg);
+      printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
+      printf("faimtest: chat invitation: encoding = %s\n", encoding);
+      printf("faimtest: chat invitation: language = %s\n", lang);
+      printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
+      printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
+      printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
+      /*
+       * Automatically join room...
+       */ 
+      aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
+      break;
+    }  
+    default:
+      printf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
+    } /* switch */
+  } else
     printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
   printf("faimtest: icbm: done with ICBM handling\n");
 
This page took 0.155838 seconds and 5 git commands to generate.