changeset 279:501e09c51cbc

[gaim-migrate @ 289] Updates to libfaim -> updates to gaim. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Mon, 29 May 2000 20:30:48 +0000
parents 29e1669b006b
children e606585a38bd
files libfaim/CHANGES libfaim/CHANGES.gaim libfaim/aim.h libfaim/aim_conn.c libfaim/aim_misc.c libfaim/aim_rxhandlers.c libfaim/aim_rxqueue.c libfaim/aim_txqueue.c libfaim/faimconfig.h src/oscar.c
diffstat 10 files changed, 231 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/libfaim/CHANGES	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/CHANGES	Mon May 29 20:30:48 2000 +0000
@@ -1,6 +1,24 @@
 
 No release numbers
 ------------------
+ - Mon May 29 12:08:28 GMT 2000
+   - Rearranged aim_tx_flushqueue(); moved write operation 
+       to aim_tx_sendframe()
+   - Turned aim_tx_enqueue() into a macro that calls sess->tx_enqueue,
+       a function pointer to whatever you want to use to enqueue
+       things for transmition (or not)
+   - Old aim_tx_enqueue becomes aim_tx_enqueue__queuebased.  Added
+       aim_tx_enqueue__immediate for doing immediate writes.  Default
+       is to use queue-based procedure.
+   - Cleaned up parts of aim_conn.c
+   - Added locking around the sockets themselves.  Should allow
+       for full cross-thread usage.
+     - Unfortunatly, only pthreads are supported at this time.
+       If you don't have pthreads on your arch, implement the
+       macros your arch needs and send me a patch.  (A SysV
+       semaphore implementation would be trivial, as would a 
+       simple integer-based lock.)
+
  - Sun May 21 14:59:20 GMT 2000
    - Added infotype parameter to aim_getinfo() for requesting
        different types of messages.  AIM_GETINFO_GENERALINFO
--- a/libfaim/CHANGES.gaim	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/CHANGES.gaim	Mon May 29 20:30:48 2000 +0000
@@ -1,3 +1,17 @@
+
+Mon May 29 20:24:24 UTC 2000 EWarmenhoven
+	- Updated the libfaim code to the latest that's in libfaim's CVS. The
+	  new code has one nice feature and one feature that may or may not
+	  cause problems. The nice feature is aim_tx_enqueue__immediate, which
+	  means that the change to aim_txenqueue I made no longer applies, I
+	  just have to set gaim_sess->tx_enqueue to the __immediate function.
+	  The one that may cause problems is libfaim has the beginnings of
+	  threads. The way the code worked in libfaim was if you were using
+	  linux, FAIM_USEPTHREADS was defined, otherwise, you couldn't use
+	  libfaim. Since gaim requires pthreads at ./configure-time, we can
+	  let anyone use it. So I changed that in faimconfig.h.
+	- The changes clued me in to a few bugs in oscar.c that were causing
+	  signon problems. Those should be fixed now.
 
 Sun May 28 21:33:43 UTC 2000 EWarmenhoven
 	- Figured out how aim_set_latency works, and why I thought it wasn't
--- a/libfaim/aim.h	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/aim.h	Mon May 29 20:30:48 2000 +0000
@@ -9,6 +9,10 @@
 #include <faimconfig.h>
 #include <aim_cbtypes.h>
 
+#ifndef FAIM_USEPTHREADS
+#error pthreads are currently required.
+#endif
+
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
@@ -17,6 +21,14 @@
 #include <stdarg.h>
 #include <errno.h>
 
+#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
+#endif
+
 #ifdef _WIN32
 #include <windows.h>
 #include <time.h>
@@ -121,6 +133,9 @@
   time_t lastactivity; /* time of last transmit */
   int forcedlatency; 
   struct aim_rxcblist_t *handlerlist;
+#ifdef FAIM_USEPTHREADS
+  faim_mutex_t active;
+#endif
 };
 
 /* struct for incoming commands */
@@ -180,10 +195,15 @@
   /* 
    * TX/RX queues 
    */
-  struct command_tx_struct *queue_outgoing; 
+  struct command_tx_struct *queue_outgoing;   
   struct command_rx_struct *queue_incoming; 
   
   /*
+   * Tx Enqueuing function
+   */
+  int (*tx_enqueue)(struct aim_session_t *, struct command_tx_struct *);
+
+  /*
    * This is a dreadful solution to the what-room-are-we-joining
    * problem.  (There's no connection between the service
    * request and the resulting redirect.)
@@ -301,7 +321,10 @@
 int aim_parse_last_bad(struct aim_session_t *, struct command_rx_struct *, ...);
 
 struct command_tx_struct *aim_tx_new(int, struct aim_conn_t *, int);
-int aim_tx_enqueue(struct aim_session_t *, struct command_tx_struct *);
+int aim_tx_enqueue__queuebased(struct aim_session_t *, struct command_tx_struct *);
+int aim_tx_enqueue__immediate(struct aim_session_t *, struct command_tx_struct *);
+#define aim_tx_enqueue(x, y) ((*(x->tx_enqueue))(x, y))
+int aim_tx_sendframe(struct command_tx_struct *cur);
 u_int aim_get_next_txseqnum(struct aim_conn_t *);
 int aim_tx_flushqueue(struct aim_session_t *);
 int aim_tx_printqueue(struct aim_session_t *);
--- a/libfaim/aim_conn.c	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/aim_conn.c	Mon May 29 20:30:48 2000 +0000
@@ -11,18 +11,9 @@
 void aim_connrst(struct aim_session_t *sess)
 {
   int i;
-  for (i = 0; i < AIM_CONN_MAX; i++)
-    {
-      sess->conns[i].fd = -1;
-      sess->conns[i].type = -1;
-      sess->conns[i].status = 0;
-      sess->conns[i].seqnum = 0;
-      sess->conns[i].lastactivity = 0;
-      sess->conns[i].forcedlatency = 0;
-      aim_clearhandlers(&(sess->conns[i]));
-      sess->conns[i].handlerlist = NULL;
-    }
-
+  for (i = 0; i < AIM_CONN_MAX; i++) {
+    aim_conn_close(&sess->conns[i]);
+  }
 }
 
 struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess)
@@ -48,6 +39,7 @@
   if (deadconn->priv)
     free(deadconn->priv);
   deadconn->priv = NULL;
+  faim_mutex_init(&deadconn->active, NULL);
 }
 
 struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
@@ -100,13 +92,12 @@
    *
    */
 
-  for(i=0;i<strlen(dest);i++)
-    {
-      if (dest[i] == ':') {
-	port = atoi(&(dest[i+1]));
-	break;
-      }
+  for(i=0;i<strlen(dest);i++) {
+    if (dest[i] == ':') {
+      port = atoi(&(dest[i+1]));
+      break;
     }
+  }
   host = (char *)malloc(i+1);
   strncpy(host, dest, i);
   host[i] = '\0';
@@ -114,11 +105,10 @@
   hp = gethostbyname2(host, AF_INET);
   free(host);
 
-  if (hp == NULL)
-    {
-      connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
-      return connstruct;
-    }
+  if (hp == NULL) {
+    connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
+    return connstruct;
+  }
 
   memset(&sa.sin_zero, 0, 8);
   sa.sin_port = htons(port);
@@ -127,12 +117,11 @@
   
   connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
   ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
-  if( ret < 0)
-    {
-      connstruct->fd = -1;
-      connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
-      return connstruct;
-    }
+  if(ret < 0) {
+    connstruct->fd = -1;
+    connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
+    return connstruct;
+  }
   
   return connstruct;
 }
@@ -140,8 +129,8 @@
 int aim_conngetmaxfd(struct aim_session_t *sess)
 {
   int i,j;
-  j=0;
-  for (i=0;i<AIM_CONN_MAX;i++)
+
+  for (i=0,j=0;i<AIM_CONN_MAX;i++)
     if(sess->conns[i].fd > j)
       j = sess->conns[i].fd;
   return j;
@@ -150,8 +139,8 @@
 int aim_countconn(struct aim_session_t *sess)
 {
   int i,cnt;
-  cnt = 0;
-  for (i=0;i<AIM_CONN_MAX;i++)
+
+  for (i=0,cnt=0;i<AIM_CONN_MAX;i++)
     if (sess->conns[i].fd > -1)
       cnt++;
   return cnt;
@@ -239,8 +228,6 @@
 
 void aim_session_init(struct aim_session_t *sess)
 {
-  int i;
-
   if (!sess)
     return;
 
@@ -250,23 +237,19 @@
   sess->logininfo.email = NULL;
   sess->logininfo.regstatus = 0x00;
 
-  for (i = 0; i < AIM_CONN_MAX; i++)
-    {
-      sess->conns[i].fd = -1;
-      sess->conns[i].type = -1;
-      sess->conns[i].status = 0;
-      sess->conns[i].seqnum = 0;
-      sess->conns[i].lastactivity = 0;
-      sess->conns[i].forcedlatency = 0;
-      sess->conns[i].handlerlist = NULL;
-      sess->conns[i].priv = NULL;
-    }
-  
+  aim_connrst(sess);
+
   sess->queue_outgoing = NULL;
   sess->queue_incoming = NULL;
   sess->pendingjoin = NULL;
   sess->outstanding_snacs = NULL;
   sess->snac_nextid = 0x00000001;
 
+  /*
+   * This must always be set.  Default to the queue-based
+   * version for back-compatibility.  
+   */
+  sess->tx_enqueue = &aim_tx_enqueue__queuebased;
+
   return;
 }
--- a/libfaim/aim_misc.c	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/aim_misc.c	Mon May 29 20:30:48 2000 +0000
@@ -648,7 +648,7 @@
 }
 
 /*
- * aim_bos_reqicbmparaminfo()
+* aim_bos_reqicbmparaminfo()
  *
  * Request ICBM parameter information.
  *
@@ -658,3 +658,4 @@
 {
   return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
 }
+
--- a/libfaim/aim_rxhandlers.c	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/aim_rxhandlers.c	Mon May 29 20:30:48 2000 +0000
@@ -5,7 +5,7 @@
  * with aim_rxdispatch(), the Rx dispatcher.  Queue/list management is
  * actually done in aim_rxqueue.c.
  *
- * Changes by Eric Warmenhoven, Wed May 24 09:33:38 UTC 2000:
+ * Changes by EWarmenhoven, Wed May 24 09:33:38 UTC 2000:
  * - there were some "bleck" printf's i changed to faimdprintf's.
  *
  */
--- a/libfaim/aim_rxqueue.c	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/aim_rxqueue.c	Mon May 29 20:30:48 2000 +0000
@@ -31,10 +31,13 @@
    *   2 short -- Sequence number 
    *   4 short -- Number of data bytes that follow.
    */
+  faim_mutex_lock(&conn->active);
   if (read(conn->fd, generic, 6) < 6){
     aim_conn_close(conn);
+    faim_mutex_unlock(&conn->active);
     return -1;
   }
+  faim_mutex_unlock(&conn->active);
 
   /*
    * This shouldn't happen unless the socket breaks, the server breaks,
@@ -72,12 +75,15 @@
   }
 
   /* read the data portion of the packet */
+  faim_mutex_lock(&conn->active);
   if (read(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){
     free(newrx->data);
     free(newrx);
     aim_conn_close(conn);
+    faim_mutex_unlock(&conn->active);
     return -1;
   }
+  faim_mutex_unlock(&conn->active);
 
   newrx->conn = conn;
 
--- a/libfaim/aim_txqueue.c	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/aim_txqueue.c	Mon May 29 20:30:48 2000 +0000
@@ -3,11 +3,6 @@
  *
  * Herein lies all the mangement routines for the transmit (Tx) queue.
  *
- * Changes by EWarmenhoven Fri May 26 22:52:46 UTC 2000:
- * - added aim_tx_flushqueue() to the end of aim_tx_enqueue() so that I don't
- * have to worry about it any more. mid tells me that doing so will solve the
- * 100% bug. Thanks mid!
- *
  */
 
 #include <aim.h>
@@ -24,8 +19,10 @@
 {
   struct command_tx_struct *new;
 
-  if (!conn)
+  if (!conn) {
+    printf("aim_tx_new: ERROR: no connection specified\n");
     return NULL;
+  }
 
   new = (struct command_tx_struct *)malloc(sizeof(struct command_tx_struct));
   if (!new)
@@ -44,7 +41,7 @@
 }
 
 /*
- * aim_tx_enqeue()
+ * aim_tx_enqeue__queuebased()
  *
  * The overall purpose here is to enqueue the passed in command struct
  * into the outgoing (tx) queue.  Basically...
@@ -55,9 +52,12 @@
  *   5) Unlock the struct once it's linked in
  *   6) Return
  *
+ * Note that this is only used when doing queue-based transmitting;
+ * that is, when sess->tx_enqueue is set to &aim_tx_enqueue__queuebased.
+ *
  */
-int aim_tx_enqueue(struct aim_session_t *sess,
-		   struct command_tx_struct *newpacket)
+int aim_tx_enqueue__queuebased(struct aim_session_t *sess,
+			       struct command_tx_struct *newpacket)
 {
   struct command_tx_struct *cur;
 
@@ -92,8 +92,40 @@
   faimdprintf(2, "back from aim_tx_printqueue()\n");
 #endif
 
-  /* mid tells me this should solve a lot of my problems */
-  aim_tx_flushqueue(sess);
+  return 0;
+}
+
+/*
+ * aim_tx_enqueue__immediate()
+ *
+ * Parallel to aim_tx_enqueue__queuebased, however, this bypasses
+ * the whole queue mess when you want immediate writes to happen.
+ *
+ * Basically the same as its __queuebased couterpart, however
+ * instead of doing a list append, it just calls aim_tx_sendframe()
+ * right here. 
+ * 
+ */
+int aim_tx_enqueue__immediate(struct aim_session_t *sess, struct command_tx_struct *newpacket)
+{
+  if (newpacket->conn == NULL) {
+    faimdprintf(1, "aim_tx_enqueue: ERROR: packet has no connection\n");
+    if (newpacket->data)
+      free(newpacket->data);
+    free(newpacket);
+    return -1;
+  }
+
+  newpacket->seqnum = aim_get_next_txseqnum(newpacket->conn);
+
+  newpacket->lock = 1; /* lock */
+  newpacket->sent = 0; /* not sent yet */
+
+  aim_tx_sendframe(newpacket);
+
+  if (newpacket->data)
+    free(newpacket->data);
+  free(newpacket);
 
   return 0;
 }
@@ -169,10 +201,72 @@
  *    9) Step to next struct in list and go back to 1.
  *
  */
+int aim_tx_sendframe(struct command_tx_struct *cur)
+{
+  u_char *curPacket;
+
+  if (!cur)
+    return -1; /* fatal */
+
+  cur->lock = 1; /* lock the struct */
+
+  /* allocate full-packet buffer */
+  curPacket = (char *) malloc(cur->commandlen + 6);
+      
+  /* command byte */
+  curPacket[0] = 0x2a;
+      
+  /* type/family byte */
+  curPacket[1] = cur->type;
+      
+  /* bytes 3+4: word: FLAP sequence number */
+  aimutil_put16(curPacket+2, cur->seqnum);
+
+  /* bytes 5+6: word: SNAC len */
+  aimutil_put16(curPacket+4, cur->commandlen);
+      
+  /* bytes 7 and on: raw: SNAC data */  /* XXX: ye gods! get rid of this! */
+  memcpy(&(curPacket[6]), cur->data, cur->commandlen);
+      
+  /* full image of raw packet data now in curPacket */
+  faim_mutex_lock(&cur->conn->active);
+  if ( (u_int)write(cur->conn->fd, curPacket, (cur->commandlen + 6)) != (cur->commandlen + 6)) {
+    faim_mutex_unlock(&cur->conn->active);
+    printf("\nWARNING: Error in sending packet 0x%4x -- will try again next time\n\n", cur->seqnum);
+    cur->sent = 0; /* mark it unsent */
+    return 0; /* bail out -- continuable error */
+  } else {
+    faimdprintf(2, "\nSENT 0x%4x\n\n", cur->seqnum);
+    
+    cur->sent = 1; /* mark the struct as sent */
+    cur->conn->lastactivity = time(NULL);
+  }
+  faim_mutex_unlock(&cur->conn->active);
+
+#if debug > 2
+  faimdprintf(2, "\nPacket:");
+  for (i = 0; i < (cur->commandlen + 6); i++) {
+    if ((i % 8) == 0) {
+      faimdprintf(2, "\n\t");
+    }
+    if (curPacket[i] >= ' ' && curPacket[i]<127) {
+      faimdprintf(2, "%c=%02x ", curPacket[i], curPacket[i]);
+    } else {
+      faimdprintf(2, "0x%2x ", curPacket[i]);
+    }
+  }
+  faimdprintf(2, "\n");
+#endif
+  cur->lock = 0; /* unlock the struct */
+  free(curPacket); /* free up full-packet buffer */
+
+  return 1; /* success */
+}
+
 int aim_tx_flushqueue(struct aim_session_t *sess)
 {
   struct command_tx_struct *cur;
-  u_char *curPacket = NULL;
+   
 #if debug > 1
   int i = 0;
 #endif
@@ -193,54 +287,9 @@
 	/* FIXME FIXME -- should be a break! we dont want to block the upper layers */
 	sleep((cur->conn->lastactivity + cur->conn->forcedlatency) - time(NULL));
       }
-      
-      cur->lock = 1; /* lock the struct */
-      
-      /* allocate full-packet buffer */
-      curPacket = (char *) malloc(cur->commandlen + 6);
-      
-      /* command byte */
-      curPacket[0] = 0x2a;
-      
-      /* type/family byte */
-      curPacket[1] = cur->type;
-      
-      /* bytes 3+4: word: FLAP sequence number */
-      aimutil_put16(curPacket+2, cur->seqnum);
 
-      /* bytes 5+6: word: SNAC len */
-      aimutil_put16(curPacket+4, cur->commandlen);
-      
-      /* bytes 7 and on: raw: SNAC data */
-      memcpy(&(curPacket[6]), cur->data, cur->commandlen);
-      
-      /* full image of raw packet data now in curPacket */
-      if ( (u_int)write(cur->conn->fd, curPacket, (cur->commandlen + 6)) != (cur->commandlen + 6)) {
-	printf("\nWARNING: Error in sending packet 0x%4x -- will try again next time\n\n", cur->seqnum);
-	cur->sent = 0; /* mark it unsent */
-	continue; /* bail out */
-      } else {
-	faimdprintf(2, "\nSENT 0x%4x\n\n", cur->seqnum);
-
-	cur->sent = 1; /* mark the struct as sent */
-	cur->conn->lastactivity = time(NULL);
-      }
-#if debug > 2
-      faimdprintf(2, "\nPacket:");
-      for (i = 0; i < (cur->commandlen + 6); i++) {
-	if ((i % 8) == 0) {
-	  faimdprintf(2, "\n\t");
-	}
-	if (curPacket[i] >= ' ' && curPacket[i]<127) {
-	  faimdprintf(2, "%c=%02x ", curPacket[i], curPacket[i]);
-	} else {
-	  faimdprintf(2, "0x%2x ", curPacket[i]);
-	}
-      }
-      faimdprintf(2, "\n");
-#endif
-      cur->lock = 0; /* unlock the struct */
-      free(curPacket); /* free up full-packet buffer */
+      if (aim_tx_sendframe(cur) == -1)
+	break;
     }
   }
 
--- a/libfaim/faimconfig.h	Mon May 29 00:56:37 2000 +0000
+++ b/libfaim/faimconfig.h	Mon May 29 20:30:48 2000 +0000
@@ -6,6 +6,13 @@
  * that they'll get set here.  Notably, the 'debug' of this file is _not_ 
  * the same as the frontend 'debug'.  They can be different values.
  *
+ * Changes by EWarmenhoven Mon May 29 20:08:17 UTC 2000:
+ * - since gaim requires pthreads to be present at ./configure-time, all
+ * systems gaim runs on theoretically have pthreads (this may not be true
+ * since gaim does not use pthreads itself, hence there are ways around it).
+ * Therefore, #define FAIM_USEPTHREADS should not be surrounded by
+ * #ifdef __linux__/#endif.
+ *
  */
 
 #ifndef __FAIMCONFIG_H__
@@ -103,4 +110,19 @@
  */
 #define AIMUTIL_USEMACROS
 
+/*
+ * Select whether or not to use POSIX thread functionality.
+ * 
+ * Default: defined on Linux, otherwise undefined
+ */
+/* gaim requires pthreads (though only at configure time), so this applies to
+ * more than just linux
+#ifdef __linux__
+#define FAIM_USEPTHREADS
+#endif
+*/
+#define FAIM_USEPTHREADS
+
 #endif /* __FAIMCONFIG_H__ */
+
+
--- a/src/oscar.c	Mon May 29 00:56:37 2000 +0000
+++ b/src/oscar.c	Mon May 29 20:30:48 2000 +0000
@@ -92,6 +92,10 @@
 
 	sess = g_new0(struct aim_session_t, 1);
 	aim_session_init(sess);
+	/* we need an immediate queue because we don't use a while-loop to
+	 * see if things need to be sent. */
+	sess->tx_enqueue = &aim_tx_enqueue__immediate;
+	gaim_sess = sess;
 
 	sprintf(buf, "Looking up %s", FAIM_LOGIN_SERVER);
 	set_login_progress(1, buf);
@@ -222,6 +226,7 @@
 		hide_login_progress("Could Not Connect");
 		return -1;
 	}
+	gaim_conn = bosconn;
 
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, gaim_server_ready, 0);
@@ -320,9 +325,6 @@
 
 		aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
 
-		gaim_sess = sess;
-		gaim_conn = command->conn;
-
 		debug_print("Roger that, all systems go\n");
 #ifdef USE_APPLET
 		make_buddy();