changeset 835:88f8f98de02d

[gaim-migrate @ 845] libfaim changes. should improve reliablity and stability. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sun, 03 Sep 2000 23:22:05 +0000
parents bac7089491c1
children 15d005f8baaf
files libfaim/CHANGES libfaim/aim_buddylist.c libfaim/aim_im.c libfaim/aim_info.c libfaim/aim_misc.c libfaim/aim_rxhandlers.c libfaim/aim_rxqueue.c libfaim/aim_snac.c libfaim/faim/aim.h
diffstat 9 files changed, 234 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/libfaim/CHANGES	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/CHANGES	Sun Sep 03 23:22:05 2000 +0000
@@ -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
--- a/libfaim/aim_buddylist.c	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/aim_buddylist.c	Sun Sep 03 23:22:05 2000 +0000
@@ -86,3 +86,43 @@
    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;  
+}
--- a/libfaim/aim_im.c	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/aim_im.c	Sun Sep 03 23:22:05 2000 +0000
@@ -856,6 +856,8 @@
   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 @@
 
   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_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;
+}
--- a/libfaim/aim_info.c	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/aim_info.c	Sun Sep 03 23:22:05 2000 +0000
@@ -57,6 +57,49 @@
   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.  
--- a/libfaim/aim_misc.c	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/aim_misc.c	Sun Sep 03 23:22:05 2000 +0000
@@ -260,6 +260,45 @@
   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()
  * 
--- a/libfaim/aim_rxhandlers.c	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/aim_rxhandlers.c	Sun Sep 03 23:22:05 2000 +0000
@@ -431,10 +431,11 @@
 	    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 @@
 	    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 @@
 	    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 @@
 	  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 @@
 	    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 @@
 	  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;
--- a/libfaim/aim_rxqueue.c	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/aim_rxqueue.c	Sun Sep 03 23:22:05 2000 +0000
@@ -42,7 +42,6 @@
    */
   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 @@
 
   /* 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);
--- a/libfaim/aim_snac.c	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/aim_snac.c	Sun Sep 03 23:22:05 2000 +0000
@@ -37,7 +37,7 @@
 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 @@
   sess->snac_hash[index] = snac;
   faim_mutex_unlock(&sess->snac_hash_locks[index]);
 
+  printf("faim: cached snac %lx\n", snac->id);
+
   return(snac->id);
 }
 
@@ -77,11 +79,9 @@
   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 @@
 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;
+    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;
       }
-    } 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;
-      }
+      cur = next;
     }
+
     faim_mutex_unlock(&sess->snac_hash_locks[i]);
   }
 
--- a/libfaim/faim/aim.h	Sat Sep 02 12:46:05 2000 +0000
+++ b/libfaim/faim/aim.h	Sun Sep 03 23:22:05 2000 +0000
@@ -544,6 +544,8 @@
 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_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 @@
 /* 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 *);