]> andersk Git - libfaim.git/commitdiff
- Sat Sep 2 23:42:37 UTC 2000
authormid <mid>
Sun, 3 Sep 2000 01:45:35 +0000 (01:45 +0000)
committermid <mid>
Sun, 3 Sep 2000 01:45:35 +0000 (01:45 +0000)
   - Hopefully fix aim_snac.c bugs
   - Add Buddy List Rights parser (max buddies and max watchers)
   - Fix rather major problem in rxhandlers caused by missing breaks
   - Add reason code for msgerr (0004/0001) callback
   - Add BOS Rights parser (max permit / max deny)
   - Add locate error (0002/0001) parser
   - Add parser for missed calls (0004/000a)

CHANGES
aim_buddylist.c
aim_im.c
aim_info.c
aim_misc.c
aim_rxhandlers.c
aim_rxqueue.c
aim_snac.c
faim/aim.h
utils/faimtest/faimtest.c

diff --git a/CHANGES b/CHANGES
index 87eecb037aa5ce94ac84cae4befc35a8df9ba77e..4b57c98e5003abed90acf91fdae04375d549c65a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,15 @@
 
 No release numbers
 ------------------
+ - Sat Sep  2 23:42:37 UTC 2000
+   - Hopefully fix aim_snac.c bugs
+   - Add Buddy List Rights parser (max buddies and max watchers)
+   - Fix rather major problem in rxhandlers caused by missing breaks
+   - Add reason code for msgerr (0004/0001) callback
+   - Add BOS Rights parser (max permit / max deny)
+   - Add locate error (0002/0001) parser
+   - Add parser for missed calls (0004/000a)
+
  - Fri Sep  1 23:34:28 UTC 2000
    - Switched the read()s in rxqueue to use recv()
      - Should fix the big message problem and the big buddy list problem
index 6947931c49904070d0f32023aec5204fbe68bc34..d043a562f5afc35fc23c0c1af89ba43524068fc6 100644 (file)
@@ -86,3 +86,43 @@ u_long aim_remove_buddy(struct aim_session_t *sess,
    return( sess->snac_nextid++ );
 }
 
+int aim_parse_buddyrights(struct aim_session_t *sess,
+                         struct command_rx_struct *command, ...)
+{
+  rxcallback_t userfunc = NULL;
+  int ret=1;
+  struct aim_tlvlist_t *tlvlist;
+  struct aim_tlv_t *tlv;
+  unsigned short maxbuddies = 0, maxwatchers = 0;
+
+  /* 
+   * TLVs follow 
+   */
+  if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
+    return ret;
+
+  /*
+   * TLV type 0x0001: Maximum number of buddies.
+   */
+  if ((tlv = aim_gettlv(tlvlist, 0x0001, 1))) {
+    maxbuddies = aimutil_get16(tlv->value);
+  }
+
+  /*
+   * TLV type 0x0002: Maximum number of watchers.
+   *
+   * XXX: what the hell is a watcher? 
+   *
+   */
+  if ((tlv = aim_gettlv(tlvlist, 0x0002, 1))) {
+    maxwatchers = aimutil_get16(tlv->value);
+  }
+  
+  userfunc = aim_callhandler(command->conn, 0x0003, 0x0003);
+  if (userfunc)
+    ret =  userfunc(sess, command, maxbuddies, maxwatchers);
+
+  aim_freetlvchain(&tlvlist);
+
+  return ret;  
+}
index 531e01846d79f825da3f0a2b5d22311c0ca23fcd..f316192f05e52c79405974b7319681d829d57b8a 100644 (file)
--- a/aim_im.c
+++ b/aim_im.c
@@ -856,6 +856,8 @@ int aim_parse_msgerror_middle(struct aim_session_t *sess,
   struct aim_snac_t *snac = NULL;
   int ret = 0;
   rxcallback_t userfunc = NULL;
+  char *dest;
+  unsigned short reason = 0;
 
   /*
    * Get SNAC from packet and look it up 
@@ -872,14 +874,18 @@ int aim_parse_msgerror_middle(struct aim_session_t *sess,
 
   if (!snac) {
     printf("faim: msgerr: got an ICBM-failed error on an unknown SNAC ID! (%08lx)\n", snacid);
-  }
+    dest = NULL;
+  } else
+    dest = snac->data;
+
+  reason = aimutil_get16(command->data+10);
 
   /*
    * Call client.
    */
   userfunc = aim_callhandler(command->conn, 0x0004, 0x0001);
   if (userfunc)
-    ret =  userfunc(sess, command, (snac)?snac->data:"(UNKNOWN)");
+    ret =  userfunc(sess, command, dest, reason);
   else
     ret = 0;
   
@@ -892,3 +898,47 @@ int aim_parse_msgerror_middle(struct aim_session_t *sess,
 }
 
 
+int aim_parse_missedcall(struct aim_session_t *sess,
+                        struct command_rx_struct *command)
+{
+  int i, ret = 1;
+  rxcallback_t userfunc = NULL;
+  unsigned short channel, nummissed, reason;
+  struct aim_userinfo_s userinfo;
+  i = 10; /* Skip SNAC header */
+
+
+  /*
+   * XXX: supposedly, this entire packet can repeat as many times
+   * as necessary. Should implement that.
+   */
+
+  /*
+   * Channel ID.
+   */
+  channel = aimutil_get16(command->data+i);
+  i += 2;
+  
+  /*
+   * Extract the standard user info block.
+   */
+  i += aim_extractuserinfo(command->data+i, &userinfo);
+  
+  nummissed = aimutil_get16(command->data+i);
+  i += 2;
+  
+  reason = aimutil_get16(command->data+i);
+  i += 2;
+
+  /*
+   * Call client.
+   */
+  userfunc = aim_callhandler(command->conn, 0x0004, 0x000a);
+  if (userfunc)
+    ret =  userfunc(sess, command, channel, &userinfo, nummissed, reason);
+  else
+    ret = 0;
+  
+  return ret;
+}
index 8015916a0b72362c1339e67f58743a6d3c310882..fcf11958ce5ffa7e28dc3f9b62ec49771bae8f2d 100644 (file)
@@ -57,6 +57,49 @@ u_long aim_getinfo(struct aim_session_t *sess,
   return (sess->snac_nextid++);
 }
 
+int aim_parse_locateerr(struct aim_session_t *sess,
+                       struct command_rx_struct *command)
+{
+  u_long snacid = 0x000000000;
+  struct aim_snac_t *snac = NULL;
+  int ret = 0;
+  rxcallback_t userfunc = NULL;
+  char *dest;
+  unsigned short reason = 0;
+
+  /*
+   * Get SNAC from packet and look it up 
+   * the list of unrepliedto/outstanding
+   * SNACs.
+   *
+   */
+  snacid = aimutil_get32(command->data+6);
+  snac = aim_remsnac(sess, snacid);
+
+  if (!snac) {
+    printf("faim: locerr: got an locate-failed error on an unknown SNAC ID! (%08lx)\n", snacid);
+    dest = NULL;
+  } else
+    dest = snac->data;
+
+  reason = aimutil_get16(command->data+10);
+
+  /*
+   * Call client.
+   */
+  userfunc = aim_callhandler(command->conn, 0x0002, 0x0001);
+  if (userfunc)
+    ret =  userfunc(sess, command, dest, reason);
+  else
+    ret = 0;
+  
+  if (snac) {
+    free(snac->data);
+    free(snac);
+  }
+
+  return ret;
+}
 
 /*
  * Capability blocks.  
index 4b38852197bb0cbf8ccb00ebaa6c0c331a722439..eddf377d4da77c3222cdc7278fe3192807b110de 100644 (file)
@@ -260,6 +260,45 @@ u_long aim_bos_setgroupperm(struct aim_session_t *sess,
   return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
 }
 
+int aim_parse_bosrights(struct aim_session_t *sess,
+                       struct command_rx_struct *command, ...)
+{
+  rxcallback_t userfunc = NULL;
+  int ret=1;
+  struct aim_tlvlist_t *tlvlist;
+  struct aim_tlv_t *tlv;
+  unsigned short maxpermits = 0, maxdenies = 0;
+
+  /* 
+   * TLVs follow 
+   */
+  if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
+    return ret;
+
+  /*
+   * TLV type 0x0001: Maximum number of buddies on permit list.
+   */
+  if ((tlv = aim_gettlv(tlvlist, 0x0001, 1))) {
+    maxpermits = aimutil_get16(tlv->value);
+  }
+
+  /*
+   * TLV type 0x0002: Maximum number of buddies on deny list.
+   *
+   */
+  if ((tlv = aim_gettlv(tlvlist, 0x0002, 1))) {
+    maxdenies = aimutil_get16(tlv->value);
+  }
+  
+  userfunc = aim_callhandler(command->conn, 0x0009, 0x0003);
+  if (userfunc)
+    ret =  userfunc(sess, command, maxpermits, maxdenies);
+
+  aim_freetlvchain(&tlvlist);
+
+  return ret;  
+}
+
 /*
  * aim_bos_clientready()
  * 
index aaeba3ba98c9da2fbcb150789bd1f3c0cb40301e..4e76e2a3dbfc65dc8e016a5e303643efbf78f884 100644 (file)
@@ -431,10 +431,11 @@ int aim_rxdispatch(struct aim_session_t *sess)
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
            break;
          }
+         break;
        case 0x0002: /* Family: Location */
          switch (subtype) {
          case 0x0001:
-           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
+           workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
            break;
          case 0x0003:
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
@@ -446,13 +447,14 @@ int aim_rxdispatch(struct aim_session_t *sess)
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
            break;
          }
+         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);
+           workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
            break;
          case 0x000b: /* oncoming buddy */
            workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
@@ -479,7 +481,7 @@ int aim_rxdispatch(struct aim_session_t *sess)
            workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
            break;
          case 0x000a:
-           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
+           workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
            break;
          case 0x000c:
            workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
@@ -492,7 +494,7 @@ int aim_rxdispatch(struct aim_session_t *sess)
          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);
+           workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
          else
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
          break;
@@ -508,7 +510,7 @@ int aim_rxdispatch(struct aim_session_t *sess)
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
          }
          break;
-       case 0x000b:
+       case 0x000b: {
          if (subtype == 0x0001)
            workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
          else if (subtype == 0x0002)
@@ -516,15 +518,16 @@ int aim_rxdispatch(struct aim_session_t *sess)
          else
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
          break;
-      case AIM_CB_FAM_SPECIAL: 
-       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
-       break;
+       }
+       case AIM_CB_FAM_SPECIAL: 
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
+         break;
        default:
          workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
          break;
-       }
+       } /* switch(family) */
        break;
-      }
+      } /* AIM_CONN_TYPE_BOS */
       case AIM_CONN_TYPE_CHATNAV: {
        u_short family;
        u_short subtype;
index 9d8dd7f228a5f5314308116e6ef6385d1d2224cc..72f4481b392fb829feda20628cf9676ba0c5d65d 100644 (file)
@@ -42,7 +42,6 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn)
    */
   faim_mutex_lock(&conn->active);
   if (recv(conn->fd, generic, 6, MSG_WAITALL) < 6){
-    printf("faim: flap: read underflow (header)\n");
     aim_conn_close(conn);
     faim_mutex_unlock(&conn->active);
     return -1;
@@ -91,7 +90,6 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn)
 
   /* read the data portion of the packet */
   if (recv(conn->fd, newrx->data, newrx->commandlen, MSG_WAITALL) < newrx->commandlen){
-    printf("faim: flap: read underflow (payload)\n");
     free(newrx->data);
     free(newrx);
     aim_conn_close(conn);
index 2a44674579a3929bb5ce389e5686f5b3ae9ef070..dd878499403d9bf35399c93b4e222ff3b2181f97 100644 (file)
@@ -37,7 +37,7 @@ void aim_initsnachash(struct aim_session_t *sess)
 u_long aim_newsnac(struct aim_session_t *sess,
                   struct aim_snac_t *newsnac) 
 {
-  struct aim_snac_t *snac = NULL, *cur = NULL;
+  struct aim_snac_t *snac = NULL;
   int index;
 
   if (!newsnac)
@@ -56,6 +56,8 @@ u_long aim_newsnac(struct aim_session_t *sess,
   sess->snac_hash[index] = snac;
   faim_mutex_unlock(&sess->snac_hash_locks[index]);
 
+  printf("faim: cached snac %lx\n", snac->id);
+
   return(snac->id);
 }
 
@@ -69,7 +71,7 @@ u_long aim_newsnac(struct aim_session_t *sess,
 struct aim_snac_t *aim_remsnac(struct aim_session_t *sess, 
                               u_long id) 
 {
-  struct aim_snac_t *cur;
+  struct aim_snac_t *cur = NULL;
   int index;
 
   index = id % FAIM_SNAC_HASH_SIZE;
@@ -77,11 +79,9 @@ struct aim_snac_t *aim_remsnac(struct aim_session_t *sess,
   faim_mutex_lock(&sess->snac_hash_locks[index]);
   if (!sess->snac_hash[index])
     ;
-  else if (!sess->snac_hash[index]->next) {
-    if (sess->snac_hash[index]->id == id) {
-      cur = sess->snac_hash[index];
-      sess->snac_hash[index] = NULL;
-    }
+  else if (sess->snac_hash[index]->id == id) {
+    cur = sess->snac_hash[index];
+    sess->snac_hash[index] = cur->next;
   } else {
     cur = sess->snac_hash[index];
     while (cur->next) {
@@ -111,36 +111,41 @@ struct aim_snac_t *aim_remsnac(struct aim_session_t *sess,
 int aim_cleansnacs(struct aim_session_t *sess,
                   int maxage)
 {
-  struct aim_snac_t *cur;
-  struct aim_snac_t *remed = NULL;
+  struct aim_snac_t *cur, *next, *prev = NULL;
   time_t curtime;
   int i;
 
   for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
     faim_mutex_lock(&sess->snac_hash_locks[i]);
-    if (!sess->snac_hash[i])
-      ;
-    else if (!sess->snac_hash[i]->next) {
-      if ((sess->snac_hash[i]->issuetime + maxage) >= curtime) {
-       remed = sess->snac_hash[i];
-       if(remed->data)
-         free(remed->data);
-       free(remed);
-       sess->snac_hash[i] = NULL;
-      }
-    } else {
-      cur = sess->snac_hash[i];        
-      while(cur && cur->next) {
-       if ((cur->next->issuetime + maxage) >= curtime) {
-         remed = cur->next;
-         cur->next = cur->next->next;
-         if (remed->data)
-           free(remed->data);  
-         free(remed);
-       }
-       cur = cur->next;
+    if (!sess->snac_hash[i]) {
+      faim_mutex_unlock(&sess->snac_hash_locks[i]);
+      continue;
+    }
+
+    curtime = time(NULL); /* done here in case we waited for the lock */
+
+    cur = sess->snac_hash[i];
+    while (cur) {
+      next = cur->next;
+      if ((curtime - cur->issuetime) > maxage) {
+       if (sess->snac_hash[i] == cur)
+         prev = sess->snac_hash[i] = next;
+       else
+         prev->next = next;
+
+       printf("faim: killing ancient snac %lx (%lx)\n", cur->id, curtime - cur->issuetime);
+       
+       /* XXX should we have destructors here? */
+       if (cur->data)
+         free(cur->data);
+       free(cur);
+
+      } else {
+       prev = cur;
       }
+      cur = next;
     }
+
     faim_mutex_unlock(&sess->snac_hash_locks[i]);
   }
 
index f5f5603dabbdcf418b7c0abcb1679f1880cf4805..0327561f5af802259936d8aaa90b791c3d718735 100644 (file)
@@ -544,6 +544,8 @@ int aim_parse_outgoing_im_middle(struct aim_session_t *, struct command_rx_struc
 u_long aim_seticbmparam(struct aim_session_t *, struct aim_conn_t *conn);
 int aim_parse_msgerror_middle(struct aim_session_t *, struct command_rx_struct *);
 int aim_negchan_middle(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_parse_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int aim_parse_missedcall(struct aim_session_t *sess, struct command_rx_struct *command);
 
 struct aim_conn_t * aim_directim_initiate(struct aim_session_t *, struct aim_conn_t *, struct aim_directim_priv *, char *);
 int aim_send_im_direct(struct aim_session_t *, struct aim_conn_t *, char *);
@@ -654,7 +656,7 @@ int aim_parse_offgoing_middle(struct aim_session_t *, struct command_rx_struct *
 int aim_putuserinfo(u_char *buf, int buflen, struct aim_userinfo_s *info);
 int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_userinfo_s *info);
 int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn);
-
+int aim_parse_locateerr(struct aim_session_t *sess, struct command_rx_struct *command);
 
 /* aim_auth.c */
 int aim_auth_sendcookie(struct aim_session_t *, struct aim_conn_t *, u_char *);
@@ -664,6 +666,7 @@ u_long aim_auth_changepasswd(struct aim_session_t *, struct aim_conn_t *, char *
 /* aim_buddylist.c */
 u_long aim_add_buddy(struct aim_session_t *, struct aim_conn_t *, char *);
 u_long aim_remove_buddy(struct aim_session_t *, struct aim_conn_t *, char *);
+int aim_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 
 /* aim_search.c */
 u_long aim_usersearch_address(struct aim_session_t *, struct aim_conn_t *, char *);
index 7ebb441db994db8a76b9d36fa6eac5b7705af465..a6e3cbf2c3ffd9568c1b332d8118b71de4851bb8 100644 (file)
@@ -76,6 +76,37 @@ int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_s
 int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+
+static char *msgerrreasons[] = {
+  "Invalid error",
+  "Invalid SNAC",
+  "Rate to host",
+  "Rate to client",
+  "Not logged on",
+  "Service unavailable",
+  "Service not defined",
+  "Obsolete SNAC",
+  "Not supported by host",
+  "Not supported by client",
+  "Refused by client",
+  "Reply too big",
+  "Responses lost",
+  "Request denied",
+  "Busted SNAC payload",
+  "Insufficient rights",
+  "In local permit/deny",
+  "Too evil (sender)",
+  "Too evil (receiver)",
+  "User temporarily unavailable",
+  "No match",
+  "List overflow",
+  "Request ambiguous",
+  "Queue full",
+  "Not while on AOL"};
+static int msgerrreasonslen = 25;
 
 int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
@@ -261,8 +292,33 @@ int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *c
   return 1;
 }
 
+int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{      
+  va_list ap;
+  unsigned short maxbuddies, maxwatchers;
+
+  va_start(ap, command);
+  maxbuddies = va_arg(ap, unsigned short);
+  maxwatchers = va_arg(ap, unsigned short);
+  va_end(ap);
+
+  printf("faimtest: buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
+
+  return 1;
+}
+
 int faimtest_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
+  unsigned short maxpermits, maxdenies;
+  va_list ap;
+
+  va_start(ap, command);
+  maxpermits = va_arg(ap, unsigned short);
+  maxdenies = va_arg(ap, unsigned short);
+  va_end(ap);
+
+  printf("faimtest: BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
+
   aim_bos_clientready(sess, command->conn);
 
   printf("faimtest: officially connected to BOS.\n");
@@ -403,14 +459,15 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct
     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, faimtest_reportinterval, 0);
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 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_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 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_ratechange, 0);
     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 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_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 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_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
 
@@ -599,6 +656,8 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str
        struct aim_conn_t *newconn;
        newconn = aim_directim_initiate(sess, command->conn, NULL, userinfo->sn);
        //aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate, 0);
+      } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
+       aim_send_im(sess, command->conn, "vaxherder", 0, "sendmsg 7986");
       } else if (!strncmp(tmpstr, "sendmsg", 7)) {
        int i;
        i = atoi(tmpstr+8);
@@ -896,56 +955,84 @@ int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct
 
 int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
+  static char *codes[] = {
+    "Unknown",
+    "Mandatory upgrade",
+    "Advisory upgrade",
+    "System bulletin",
+    "Top o' the world!"};
+  static int codeslen = 5;
+
   char *msg;
-  u_short id;
+  unsigned short id;
   va_list ap;
   
   va_start(ap, command);
-  id = va_arg(ap, u_short);
+  id = va_arg(ap, unsigned short);
   msg = va_arg(ap, char *);
   va_end(ap);
 
-  printf("faimtest: motd: %s (%d)\n", msg, id);
+  printf("faimtest: motd: %s (%d / %s)\n", msg, id, 
+        (id < codeslen)?codes[id]:"unknown");
+
+  return 1;
+}
+
+int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  va_list ap;
+  char *destsn;
+  unsigned short reason;
+
+  va_start(ap, command);
+  destsn = va_arg(ap, char *);
+  reason = va_arg(ap, unsigned short);
+  va_end(ap);
+
+  printf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
+  
+  return 1;
+}
 
+int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  va_list ap;
+  char *destsn;
+  unsigned short reason;
+
+  va_start(ap, command);
+  destsn = va_arg(ap, char *);
+  reason = va_arg(ap, unsigned short);
+  va_end(ap);
+
+  printf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
+  
   return 1;
 }
 
 /* 
- * Handles callbacks for: AIM_CB_RATECHANGE, AIM_CB_USERERROR, 
- *   AIM_CB_MISSED_IM, and AIM_CB_MISSED_CALL.
+ * Handles callbacks for AIM_CB_MISSED_CALL.
  */
 int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
-  u_short family;
-  u_short subtype;
+  static char *missedreasons[] = {
+    "Unknown",
+    "Message too large"};
+  static int missedreasonslen = 2;
 
-  family = aimutil_get16(command->data+0);
-  subtype= aimutil_get16(command->data+2);
+  va_list ap;
+  unsigned short chan, nummissed, reason;
+  struct aim_userinfo_s *userinfo;
   
-  switch (family)
-    {
-    case 0x0001:
-      if (subtype == 0x000a) /* or AIM_CB_RATECHANGE */
-       printf("\n****STOP SENDING/RECIEVING MESSAGES SO FAST!****\n\n");
-      break;
-    case 0x0002:
-      if (subtype == 0x0001) /* or AIM_CB_USERERROR */
-       {
-         u_long snacid = 0x00000000;
-         
-         snacid = aimutil_get32(&command->data[6]);
-         
-         printf("Received unknown error in SNAC family 0x0002 (snacid = %08lx)\n", snacid);
-       }
-      break;
-    case 0x0004:
-      if (subtype == 0x0001) /* or AIM_CB_MISSED_IM */
-       printf("\n***LAST IM DIDN\'T MAKE IT BECAUSE THE BUDDY IS NOT ONLINE***\n\n");
-      else if (subtype == 0x000a) /* or AIM_CB_MISSED_CALL */
-       printf("You missed some messages from %s because they were sent too fast\n", &(command->data[13]));
-      break;
-    }
+  va_start(ap, command);
+  chan = va_arg(ap, unsigned short);
+  userinfo = va_arg(ap, struct aim_userinfo_s *);
+  nummissed = va_arg(ap, unsigned short);
+  reason = va_arg(ap, unsigned short);
+  va_end(ap);
 
+  printf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
+  
   return 0;
 }
 
This page took 0.36945 seconds and 5 git commands to generate.