changeset 715:58106806ac2b

[gaim-migrate @ 725] yay committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 18 Aug 2000 00:21:53 +0000
parents d7557252bfb1
children 0995382d0c46
files libfaim/CHANGES libfaim/CHANGES.gaim libfaim/README.gaim libfaim/aim_buddylist.c libfaim/aim_chatnav.c libfaim/aim_conn.c libfaim/aim_login.c libfaim/aim_rxhandlers.c libfaim/aim_snac.c libfaim/faim/aim.h libfaim/faim/faimconfig.h
diffstat 11 files changed, 181 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/libfaim/CHANGES	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/CHANGES	Fri Aug 18 00:21:53 2000 +0000
@@ -1,6 +1,19 @@
 
 No release numbers
 ------------------
+ - Thu Aug 17 23:19:40 UTC 2000
+   - A few more leak fixes (only a few left to go...)
+
+ - Thu Aug 17 23:08:08 UTC 2000
+   - More leak fixes (eric, eric, eric...)
+
+ - Thu Aug 17 22:53:03 UTC 2000
+   - Change the SNAC cache to a hash instead of list
+   - Fixed a few leaks relating to aim_gettlv_str()
+
+ - Thu Aug 17 14:04:18 UTC 2000
+   - Fix the fd closing bug introduced last week
+
  - Tue Aug  8 04:25:35 UTC 2000
    - Preserve subtype and priv after aim_conn_close
 
--- a/libfaim/CHANGES.gaim	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/CHANGES.gaim	Fri Aug 18 00:21:53 2000 +0000
@@ -1,3 +1,6 @@
+
+Fri Aug 18 00:21:11 UTC 2000 EWarmenhoven
+	- Adam got rid of a lot of leaks thanks to me :)
 
 Thu Aug 17 07:56:49 UTC 2000 EWarmenhoven
 	- The permit/deny stuff is warped. It's untested and just doesn't
--- a/libfaim/README.gaim	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/README.gaim	Fri Aug 18 00:21:53 2000 +0000
@@ -13,7 +13,6 @@
 included with the libfaim source on sourceforge) with the Gaim GTK front-end.
 So far the changes to libfaim that I've made are:
 - remove mkbuildinfo.sh and put the #defines it creates into Makefile.am
-- fix a typo in aim.h - "aim_directim_initiate", not "aim_directim_intiate"
 - add #if HAVE_GETADDRINFO in aim_ft.c for Solaris people
 
 And finally, a word of warning. Gaim/Faim is VERY buggy. Please, don't use this
--- a/libfaim/aim_buddylist.c	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/aim_buddylist.c	Fri Aug 18 00:21:53 2000 +0000
@@ -28,6 +28,7 @@
 
    aim_tx_enqueue(sess, newpacket );
 
+#if 0 /* do we really need this code? */
    {
       struct aim_snac_t snac;
     
@@ -41,6 +42,7 @@
 
       aim_newsnac(sess, &snac);
    }
+#endif
 
    return( sess->snac_nextid++ );
 }
--- a/libfaim/aim_chatnav.c	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/aim_chatnav.c	Fri Aug 18 00:21:53 2000 +0000
@@ -68,6 +68,7 @@
   struct aim_snac_t *snac;
   u_long snacid;
   rxcallback_t userfunc;
+  int ret=1;
   
   snacid = aimutil_get32(command->data+6);
   snac = aim_remsnac(sess, snacid);
@@ -96,7 +97,6 @@
 	  int curexchange = 0;
 	  struct aim_tlv_t *exchangetlv;
 	  u_char maxrooms = 0;
-	  int ret = 1;
 	  struct aim_tlvlist_t *innerlist;
 	 
 	  tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
@@ -215,7 +215,8 @@
 		exchanges[curexchange-1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1);
 	      else
 		exchanges[curexchange-1].lang2 = NULL;
-
+	      
+	      aim_freetlvchain(&innerlist);
 	    }
 	  
 	  /*
@@ -245,33 +246,38 @@
 	      curexchange--;
 	    }
 	  free(exchanges);
-	  aim_freetlvchain(&innerlist);
 	  aim_freetlvchain(&tlvlist);
-	  return ret;
+	  
+	  break;
       }
     case 0x0003: /* request exchange info */
       printf("faim: chatnav_parse_info: resposne to exchange info\n");
-      return 1;
+      break;
     case 0x0004: /* request room info */
       printf("faim: chatnav_parse_info: response to room info\n");
-      return 1;
+      break;
     case 0x0005: /* request more room info */
       printf("faim: chatnav_parse_info: response to more room info\n");
-      return 1;
+      break;
     case 0x0006: /* request occupant list */
       printf("faim: chatnav_parse_info: response to occupant info\n");
-      return 1;
+      break;
     case 0x0007: /* search for a room */
       printf("faim: chatnav_parse_info: search results\n");
-      return 1;
+      break;
     case 0x0008: /* create room */
       printf("faim: chatnav_parse_info: response to create room\n");
-      return 1;
+      break;
     default: /* unknown */
       printf("faim: chatnav_parse_info: unknown request subtype (%04x)\n", snac->type);
     }
 
-  return 1; /* shouldn't get here */
+  if (snac && snac->data)
+    free(snac->data);
+  if (snac)
+    free(snac);
+  
+  return ret;
 }
 
 u_long aim_chatnav_createroom(struct aim_session_t *sess,
--- a/libfaim/aim_conn.c	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/aim_conn.c	Fri Aug 18 00:21:53 2000 +0000
@@ -13,7 +13,7 @@
  */
 void aim_connrst(struct aim_session_t *sess)
 {
-  faim_mutex_init(&sess->connlistlock, NULL);
+  faim_mutex_init(&sess->connlistlock);
   if (sess->connlist) {
     struct aim_conn_t *cur = sess->connlist, *tmp;
 
@@ -68,8 +68,8 @@
   deadconn->forcedlatency = 0;
   deadconn->handlerlist = NULL;
   deadconn->priv = NULL;
-  faim_mutex_init(&deadconn->active, NULL);
-  faim_mutex_init(&deadconn->seqnum_lock, NULL);
+  faim_mutex_init(&deadconn->active);
+  faim_mutex_init(&deadconn->seqnum_lock);
   
   return;
 }
@@ -373,7 +373,7 @@
   sess->queue_outgoing = NULL;
   sess->queue_incoming = NULL;
   sess->pendingjoin = NULL;
-  sess->outstanding_snacs = NULL;
+  aim_initsnachash(sess);
   sess->snac_nextid = 0x00000001;
 
   /*
--- a/libfaim/aim_login.c	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/aim_login.c	Fri Aug 18 00:21:53 2000 +0000
@@ -253,9 +253,9 @@
    * No matter what, we should have a screen name.
    */
   sn = aim_gettlv_str(tlvlist, 0x0001, 1);
-  memcpy(sess->logininfo.screen_name, sn, strlen(sn));
-  sn[(strlen(sn))] = '\0';
-  
+  strncpy(sess->logininfo.screen_name, sn, strlen(sn));
+  free(sn);
+
   /*
    * Check for an error code.  If so, we should also
    * have an error url.
@@ -311,10 +311,18 @@
 
   aim_freetlvchain(&tlvlist);
 
-  /* These have been clobbered by the freetlvchain */
-  sess->logininfo.BOSIP = NULL;
-  sess->logininfo.email = NULL;
-  sess->logininfo.errorurl = NULL;
+  if (sess->logininfo.BOSIP) {
+    free(sess->logininfo.BOSIP);
+    sess->logininfo.BOSIP = NULL;
+  }
+  if (sess->logininfo.email) {
+    free(sess->logininfo.email);
+    sess->logininfo.email = NULL;
+  }
+  if (sess->logininfo.errorurl) {
+    free(sess->logininfo.errorurl);
+    sess->logininfo.errorurl = NULL;
+  }
 
   return ret;
 }
--- a/libfaim/aim_rxhandlers.c	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/aim_rxhandlers.c	Fri Aug 18 00:21:53 2000 +0000
@@ -639,7 +639,6 @@
 int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
 {
   rxcallback_t userfunc = NULL;
-  int i = 10; /* skip SNAC */
   int ret = 1;
   unsigned long newrate;
 
@@ -673,18 +672,22 @@
   /* 
    * TLVs follow 
    */
-  tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12);
-  
-  msg = aim_gettlv_str(tlvlist, 0x000b, 1);
+  if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
+    return ret;
+
+  if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
+    aim_freetlvchain(&tlvlist);
+    return ret;
+  }
   
   userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
   if (userfunc)
     ret =  userfunc(sess, command, id, msg);
 
   aim_freetlvchain(&tlvlist);
+  free(msg);
 
-  return ret;
-  
+  return ret;  
 }
 
 int aim_handleredirect_middle(struct aim_session_t *sess,
@@ -715,6 +718,7 @@
   if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1))) 
     {
       printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
+      free(ip);
       aim_freetlvchain(&tlvlist);
       return ret;
     }
@@ -722,6 +726,7 @@
   if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
     {
       printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
+      free(ip);
       aim_freetlvchain(&tlvlist);
       return ret;
     }
@@ -746,9 +751,7 @@
 	ret =  userfunc(sess, command, serviceid, ip, cookie);
     }
 
-  /*
-   * XXX: Is there a leak here?  Where does IP get freed?
-   */
+  free(ip);
   aim_freetlvchain(&tlvlist);
 
   return ret;
--- a/libfaim/aim_snac.c	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/aim_snac.c	Fri Aug 18 00:21:53 2000 +0000
@@ -5,76 +5,112 @@
  *
  * outstanding_snacs is a list of aim_snac_t structs.  A SNAC should be added
  * whenever a new SNAC is sent and it should remain in the list until the
- * response for it has been receieved.
+ * response for it has been receieved.  
  *
- * First edition badly written by Adam Fritzler (afritz@delphid.ml.org)
- * Current edition nicely rewritten (it even works) by n (n@ml.org)
+ * cleansnacs() should be called periodically by the client in order
+ * to facilitate the aging out of unreplied-to SNACs. This can and does
+ * happen, so it should be handled.
  *
  */
 
 #include <faim/aim.h>
 
+/*
+ * Called from aim_session_init() to initialize the hash.
+ */
+void aim_initsnachash(struct aim_session_t *sess)
+{
+  int i;
+
+  for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
+    sess->snac_hash[i] = NULL;
+    faim_mutex_init(&sess->snac_hash_locks[i]);
+  }
+
+  return;
+}
+
+/*
+ * Clones the passed snac structure and caches it in the
+ * list/hash.
+ */
 u_long aim_newsnac(struct aim_session_t *sess,
 		   struct aim_snac_t *newsnac) 
 {
   struct aim_snac_t *snac = NULL, *cur = NULL;
-  
+  int index;
+
   if (!newsnac)
     return 0;
 
-  cur = sess->outstanding_snacs;
-
   snac = calloc(1, sizeof(struct aim_snac_t));
   if (!snac)
     return 0;
   memcpy(snac, newsnac, sizeof(struct aim_snac_t));
   snac->issuetime = time(&snac->issuetime);
   snac->next = NULL;
-  
-  if (cur == NULL) {
-    sess->outstanding_snacs = snac;
-    return(snac->id);
+
+  index = snac->id % FAIM_SNAC_HASH_SIZE;
+
+  faim_mutex_lock(&sess->snac_hash_locks[index]);
+  if (!sess->snac_hash[index])
+    sess->snac_hash[index] = snac;
+  else {
+    snac->next = sess->snac_hash[index];
+    sess->snac_hash[index] = snac;
   }
-  while (cur->next != NULL)
-    cur = cur->next;
-  cur->next = snac;
+  faim_mutex_unlock(&sess->snac_hash_locks[index]);
 
   return(snac->id);
 }
 
+/*
+ * Finds a snac structure with the passed SNAC ID, 
+ * removes it from the list/hash, and returns a pointer to it.
+ *
+ * The returned structure must be freed by the caller.
+ *
+ */
 struct aim_snac_t *aim_remsnac(struct aim_session_t *sess, 
 			       u_long id) 
 {
   struct aim_snac_t *cur;
+  int index;
 
-  cur = sess->outstanding_snacs;
+  index = id % FAIM_SNAC_HASH_SIZE;
 
-  if (cur == NULL)
-    return(NULL);
-
-  if (cur->id == id) {
-    sess->outstanding_snacs = cur->next;
-    return(cur);
+  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 {
+    cur = sess->snac_hash[index];
+    while (cur->next) {
+      if (cur->next->id == id) {
+	struct aim_snac_t *tmp;
+	
+	tmp = cur->next;
+	cur->next = cur->next->next;
+	cur = tmp;
+	break;
+      }
+      cur = cur->next;
+    }
   }
-  while (cur->next != NULL) {
-    if (cur->next->id == id) {
-      struct aim_snac_t	*tmp = NULL;
-      
-      tmp = cur->next;
-      cur->next = cur->next->next;
-      return(tmp);
-    }
-    cur = cur->next;
-  }
-  return(NULL);
+  faim_mutex_unlock(&sess->snac_hash_locks[index]);
+
+  return cur;
 }
 
 /*
  * This is for cleaning up old SNACs that either don't get replies or
  * a reply was never received for.  Garabage collection. Plain and simple.
  *
- * maxage is the _minimum_ age in seconds to keep SNACs (though I don't know
- * why its called _max_age).
+ * maxage is the _minimum_ age in seconds to keep SNACs.
  *
  */
 int aim_cleansnacs(struct aim_session_t *sess,
@@ -83,29 +119,36 @@
   struct aim_snac_t *cur;
   struct aim_snac_t *remed = NULL;
   time_t curtime;
- 
-  cur = sess->outstanding_snacs;
-  
-  curtime = time(&curtime);
- 
-  while (cur)
-    {
-      if ( (cur) && (((cur->issuetime) + maxage) < curtime))
-	{
-#if DEBUG > 1
-	  printf("aimsnac: WARNING purged obsolete snac %08lx\n", cur->id);
-#endif
-	  remed = aim_remsnac(sess, cur->id);
-	  if (remed)
-	    {
-	      if (remed->data)
-		free(remed->data);
-	      free(remed);
-	    }
+  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;
+	cur = cur->next;
+      }
     }
-  
+    faim_mutex_unlock(&sess->snac_hash_locks[i]);
+  }
+
   return 0;
 }
 
--- a/libfaim/faim/aim.h	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/faim/aim.h	Fri Aug 18 00:21:53 2000 +0000
@@ -40,10 +40,10 @@
 #ifdef FAIM_USEPTHREADS
 #include <pthread.h>
 #define faim_mutex_t pthread_mutex_t 
-#define faim_mutex_init pthread_mutex_init
-#define faim_mutex_lock pthread_mutex_lock
-#define faim_mutex_unlock pthread_mutex_unlock
-#define faim_mutex_destroy pthread_mutex_destroy
+#define faim_mutex_init(x) pthread_mutex_init(x, NULL)
+#define faim_mutex_lock(x) pthread_mutex_lock(x)
+#define faim_mutex_unlock(x) pthread_mutex_unlock(x)
+#define faim_mutex_destroy(x) pthread_mutex_destroy(x)
 #elif defined(FAIM_USEFAKELOCKS)
 /*
  * For platforms without pthreads, we also assume
@@ -306,8 +306,9 @@
    * Outstanding snac handling 
    *
    * XXX: Should these be per-connection? -mid
-   **/
-  struct aim_snac_t *outstanding_snacs;
+   */
+  struct aim_snac_t *snac_hash[FAIM_SNAC_HASH_SIZE];
+  faim_mutex_t snac_hash_locks[FAIM_SNAC_HASH_SIZE];
   u_long snac_nextid;
 
   struct aim_msgcookie_t *msgcookies;
@@ -457,6 +458,7 @@
   time_t issuetime;
   struct aim_snac_t *next;
 };
+void aim_initsnachash(struct aim_session_t *sess);
 u_long aim_newsnac(struct aim_session_t *, struct aim_snac_t *newsnac);
 struct aim_snac_t *aim_remsnac(struct aim_session_t *, u_long id);
 int aim_cleansnacs(struct aim_session_t *, int maxage);
@@ -510,6 +512,8 @@
 int aim_parse_last_bad(struct aim_session_t *, struct command_rx_struct *, ...);
 int aim_parse_generalerrs(struct aim_session_t *, struct command_rx_struct *command, ...);
 int aim_parsemotd_middle(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command);
 
 /* aim_im.c */
 struct aim_directim_priv {
--- a/libfaim/faim/faimconfig.h	Thu Aug 17 23:23:24 2000 +0000
+++ b/libfaim/faim/faimconfig.h	Fri Aug 18 00:21:53 2000 +0000
@@ -118,6 +118,14 @@
 #define FAIM_USEFAKELOCKS
 #endif
 
+/*
+ * Size of the SNAC caching hash.
+ *
+ * Default: 16
+ *
+ */
+#define FAIM_SNAC_HASH_SIZE 16
+
 #endif /* __FAIMCONFIG_H__ */