libfaim/aim_snac.c

changeset 715
96292ef864c9
parent 283
dbf3342692e9
child 771
4ca7e1a4b1e4
--- 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;
 }
 

mercurial