]> andersk Git - libfaim.git/commitdiff
- Thu Aug 17 22:53:03 UTC 2000
authormid <mid>
Thu, 17 Aug 2000 23:00:26 +0000 (23:00 +0000)
committermid <mid>
Thu, 17 Aug 2000 23:00:26 +0000 (23:00 +0000)
   - Change the SNAC cache to a hash instead of list
   - Fixed a few leaks relating to aim_gettlv_str()

CHANGES
aim_conn.c
aim_login.c
aim_rxhandlers.c
aim_snac.c
faim/aim.h
faim/faimconfig.h

diff --git a/CHANGES b/CHANGES
index 9b2faf336b2d9f810951e14cf2a3bea74598b6af..3d08a8ecc20be49fcab590c739044f5ce20db00c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
 
 No release numbers
 ------------------
+ - 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
 
index f31fb8ab23e663ab7a36b9e0345d7ab16c837997..7caef93665d9f893aa9f591e08d46a1999020c53 100644 (file)
@@ -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 @@ static void aim_conn_init(struct aim_conn_t *deadconn)
   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 @@ void aim_session_init(struct aim_session_t *sess)
   sess->queue_outgoing = NULL;
   sess->queue_incoming = NULL;
   sess->pendingjoin = NULL;
-  sess->outstanding_snacs = NULL;
+  aim_initsnachash(sess);
   sess->snac_nextid = 0x00000001;
 
   /*
index 1af14201000fd65a269483884a0ef5ef9f4cc9f9..44ed08d38f10413e8d47fc7e9344589b734d264b 100644 (file)
@@ -253,9 +253,9 @@ int aim_authparse(struct aim_session_t *sess,
    * 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.
index b1f8f9bcf40ccaf8b7f9fb6487f876e953a34c4f..2a71d3739297509fe4763848ef10129d54eba45b 100644 (file)
@@ -639,7 +639,6 @@ int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct
 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 @@ int aim_parsemotd_middle(struct aim_session_t *sess,
   /* 
    * 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 @@ int aim_handleredirect_middle(struct aim_session_t *sess,
   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 @@ int aim_handleredirect_middle(struct aim_session_t *sess,
   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 @@ int aim_handleredirect_middle(struct aim_session_t *sess,
        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;
index e3d5970f5aeec492e9ba4df5aa97929ff4954448..6cea5d5e897356876fd5a3bed2783c9fd4ba2930 100644 (file)
  *
  * 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);
-  }
-  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);
+  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;
     }
-    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 @@ int aim_cleansnacs(struct aim_session_t *sess,
   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;
 }
 
index 6e000c7c420325c2684c1384571c268a92afe866..66b1ca0761854227436ff7a7f895dfd562f6002a 100644 (file)
 #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 @@ struct aim_session_t {
    * 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 @@ struct aim_snac_t {
   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_unknown(struct aim_session_t *, struct command_rx_struct *, ...);
 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 {
index a43ef446473d7713b6ecef51a4cafa2b5a2e3278..222ff447a6aff502f219a8ce6c7aa7be3d8252a8 100644 (file)
 #define FAIM_USEFAKELOCKS
 #endif
 
+/*
+ * Size of the SNAC caching hash.
+ *
+ * Default: 16
+ *
+ */
+#define FAIM_SNAC_HASH_SIZE 16
+
 #endif /* __FAIMCONFIG_H__ */
 
 
This page took 0.197911 seconds and 5 git commands to generate.