]> andersk Git - libfaim.git/commitdiff
- Fri Nov 10 08:24:34 UTC 2000
authormid <mid>
Fri, 10 Nov 2000 08:35:06 +0000 (08:35 +0000)
committermid <mid>
Fri, 10 Nov 2000 08:35:06 +0000 (08:35 +0000)
  - Add sess->flags (replaces sess->snaclogin)
  - Remove odd setstatus call in chat parser
  - Remove aim_tx_enqueue macro, replace with a smarter one
    - If a connection is in progress, enqueue instead of calling
      the client-specified queuer
  - Add support for nonblocking connects through the
     AIM_SESS_FLAG_NONBLOCKCONNECT flag to aim_session_init()
  - Add AIM_CB_SPECIAL_CONNCOMPLETE callback. Not real useful.
  - Add AIM_CB_SPECIAL_FLAPVER callback. Can be used as an alternate
     way of starting the login process, or just to look like you
     know what you're doing. Fixed associated inconsistencies
     in aim_rxhandlers too.
  - Fix some connection status stupidities in faimtest.

CHANGES
aim_conn.c
aim_login.c
aim_rxhandlers.c
aim_rxqueue.c
aim_txqueue.c
faim/aim.h
faim/aim_cbtypes.h
utils/faimtest/faimtest.c

diff --git a/CHANGES b/CHANGES
index 7b0f3d1e17bf2e70aff49824cb87774d87fccd39..e261088fcfe19306dc829e377f29d5f9256ecacc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,21 @@
 
 No release numbers
 ------------------
+ - Fri Nov 10 08:24:34 UTC 2000
+  - Add sess->flags (replaces sess->snaclogin)
+  - Remove odd setstatus call in chat parser
+  - Remove aim_tx_enqueue macro, replace with a smarter one
+    - If a connection is in progress, enqueue instead of calling
+      the client-specified queuer
+  - Add support for nonblocking connects through the 
+     AIM_SESS_FLAG_NONBLOCKCONNECT flag to aim_session_init()
+  - Add AIM_CB_SPECIAL_CONNCOMPLETE callback. Not real useful.
+  - Add AIM_CB_SPECIAL_FLAPVER callback. Can be used as an alternate
+     way of starting the login process, or just to look like you 
+     know what you're doing. Fixed associated inconsistencies
+     in aim_rxhandlers too.
+  - Fix some connection status stupidities in faimtest.
+
  - Wed Nov  8 13:11:18 UTC 2000
   - Reenable/reimplement older login, but only use for ICQ UINs
     - This is a fairly ugly hack.  But...eh.  It works.
index ca42aead8798052a1a89fddbb4980d991d98b889..b630145f304283e4df4bec1a6d2d5a429faedc75 100644 (file)
@@ -194,7 +194,7 @@ faim_internal struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
 
   faim_mutex_lock(&sess->connlistlock);
   for (cur = sess->connlist; cur; cur = cur->next) {
-    if (cur->type == type)
+    if ((cur->type == type) && !(cur->status & AIM_CONN_STATUS_INPROGRESS))
       break;
   }
   faim_mutex_unlock(&sess->connlistlock);
@@ -344,13 +344,24 @@ static int aim_proxyconnect(struct aim_session_t *sess,
       return -1;
     }
 
-    memset(&sa.sin_zero, 0, 8);
+    memset(&sa, 0, sizeof(struct sockaddr_in));
     sa.sin_port = htons(port);
     memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
     sa.sin_family = hp->h_addrtype;
   
     fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
+
+    if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT)
+      fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */
+
     if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
+      if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) {
+       if ((errno == EINPROGRESS) || (errno == EINTR)) {
+         if (statusret)
+           *statusret |= AIM_CONN_STATUS_INPROGRESS;
+         return fd;
+       }
+      }
       close(fd);
       fd = -1;
     }
@@ -518,9 +529,9 @@ faim_export struct aim_conn_t *aim_select(struct aim_session_t *sess,
                                          struct timeval *timeout, int *status)
 {
   struct aim_conn_t *cur;
-  fd_set fds;
+  fd_set fds, wfds;
   int maxfd = 0;
-  int i;
+  int i, haveconnecting = 0;
 
   faim_mutex_lock(&sess->connlistlock);
   if (sess->connlist == NULL) {
@@ -530,32 +541,50 @@ faim_export struct aim_conn_t *aim_select(struct aim_session_t *sess,
   }
   faim_mutex_unlock(&sess->connlistlock);
 
-  /* 
-   * If we have data waiting to be sent, return immediatly
-   */
-  if (sess->queue_outgoing != NULL) {
-    *status = 1;
-    return NULL;
-  } 
-
   FD_ZERO(&fds);
+  FD_ZERO(&wfds);
   maxfd = 0;
 
   faim_mutex_lock(&sess->connlistlock);
   for (cur = sess->connlist; cur; cur = cur->next) {
+    if (cur->status & AIM_CONN_STATUS_INPROGRESS) {
+      FD_SET(cur->fd, &wfds);
+      haveconnecting++;
+    }
     FD_SET(cur->fd, &fds);
     if (cur->fd > maxfd)
       maxfd = cur->fd;
   }
   faim_mutex_unlock(&sess->connlistlock);
 
-  if ((i = select(maxfd+1, &fds, NULL, NULL, timeout))>=1) {
+  /* 
+   * If we have data waiting to be sent, return
+   *
+   * We have to not do this if theres at least one
+   * connection thats still connecting, since that connection
+   * may have queued data and this return would prevent
+   * the connection from ever completing!  This is a major
+   * inadequacy of the libfaim way of doing things.  It means
+   * that nothing can transmit as long as there's connecting
+   * sockets. Evil.
+   *
+   * But its still better than having blocking connects.
+   *
+   */
+  if (!haveconnecting && (sess->queue_outgoing != NULL)) {
+    *status = 1;
+    return NULL;
+  } 
+
+  if ((i = select(maxfd+1, &fds, &wfds, NULL, timeout))>=1) {
     faim_mutex_lock(&sess->connlistlock);
     for (cur = sess->connlist; cur; cur = cur->next) {
-      if (FD_ISSET(cur->fd, &fds)) {
+      if ((FD_ISSET(cur->fd, &fds)) || 
+         ((cur->status & AIM_CONN_STATUS_INPROGRESS) && 
+          FD_ISSET(cur->fd, &wfds))) {
        *status = 2;
        faim_mutex_unlock(&sess->connlistlock);
-       return cur;
+       return cur; /* XXX race condition here -- shouldnt unlock connlist */
       }
     }
     *status = 0; /* shouldn't happen */
@@ -593,6 +622,8 @@ faim_export int aim_conn_isready(struct aim_conn_t *conn)
  * @newstatus is %XOR'd with the previous value of the connection
  * status and returned.  Returns -1 if the connection is invalid.
  *
+ * This isn't real useful.
+ *
  */
 faim_export int aim_conn_setstatus(struct aim_conn_t *conn, int status)
 {
@@ -669,11 +700,12 @@ faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *
 /**
  * aim_session_init - Initializes a session structure
  * @sess: Session to initialize
+ * @flags: Flags to use. Any of %AIM_SESS_FLAGS %OR'd together.
  *
  * Sets up the initial values for a session.
  *
  */
-faim_export void aim_session_init(struct aim_session_t *sess)
+faim_export void aim_session_init(struct aim_session_t *sess, unsigned long flags)
 {
   if (!sess)
     return;
@@ -685,7 +717,15 @@ faim_export void aim_session_init(struct aim_session_t *sess)
   sess->pendingjoin = NULL;
   aim_initsnachash(sess);
   sess->snac_nextid = 0x00000001;
-  sess->snaclogin = 1; /* default to yes, oh gods yes. */
+
+  sess->flags = 0;
+
+  /*
+   * Default to SNAC login unless XORLOGIN is explicitly set.
+   */
+  if (!(flags & AIM_SESS_FLAGS_XORLOGIN))
+    sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
+  sess->flags |= flags;
 
   /*
    * This must always be set.  Default to the queue-based
@@ -695,3 +735,75 @@ faim_export void aim_session_init(struct aim_session_t *sess)
 
   return;
 }
+
+/**
+ * aim_conn_isconnecting - Determine if a connection is connecting
+ * @conn: Connection to examine
+ *
+ * Returns nonzero if the connection is in the process of
+ * connecting (or if it just completed and aim_conn_completeconnect()
+ * has yet to be called on it).
+ *
+ */
+faim_export int aim_conn_isconnecting(struct aim_conn_t *conn)
+{
+  if (!conn)
+    return 0;
+  return (conn->status & AIM_CONN_STATUS_INPROGRESS)?1:0;
+}
+
+faim_export int aim_conn_completeconnect(struct aim_session_t *sess, struct aim_conn_t *conn)
+{
+  fd_set fds, wfds;
+  struct timeval tv;
+  int res, error = ETIMEDOUT;
+  rxcallback_t userfunc;
+
+  if (!conn || (conn->fd == -1))
+    return -1;
+
+  if (!(conn->status & AIM_CONN_STATUS_INPROGRESS))
+    return -1;
+
+  FD_ZERO(&fds);
+  FD_SET(conn->fd, &fds);
+  FD_ZERO(&wfds);
+  FD_SET(conn->fd, &wfds);
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+
+  if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) {
+    error = errno;
+    aim_conn_close(conn);
+    errno = error;
+    return -1;
+  } else if (res == 0) {
+    printf("faim: aim_conn_completeconnect: false alarm on %d\n", conn->fd);
+    return 0; /* hasn't really completed yet... */
+  } 
+
+  if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) {
+    int len = sizeof(error);
+
+    if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+      error = errno;
+  }
+
+  if (error) {
+    aim_conn_close(conn);
+    errno = error;
+    return -1;
+  }
+
+  fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */
+
+  conn->status &= ~AIM_CONN_STATUS_INPROGRESS;
+
+  if ((userfunc = aim_callhandler(conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE)))
+    userfunc(sess, NULL, conn);
+
+  /* Flush out the queues if there was something waiting for this conn  */
+  aim_tx_flushqueue(sess);
+
+  return 0;
+}
index 49cf7f8b0eba80355bf24ae27ea673184ce0fd96..51aedd4f07205a0dfbc98a00e5c09f14e72715a1 100644 (file)
@@ -100,11 +100,12 @@ faim_export int aim_request_login(struct aim_session_t *sess,
 
     newrx->lock = 0;
 
-    sess->snaclogin = 0;
+    sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN;
+
     return 0;
   } 
 
-  sess->snaclogin = 1;
+  sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
 
   aim_sendconnack(sess, conn);
 
@@ -149,9 +150,9 @@ faim_export int aim_send_login (struct aim_session_t *sess,
 
   newpacket->lock = 1;
 
-  newpacket->hdr.oscar.type = sess->snaclogin?0x02:0x01;
+  newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01;
   
-  if (sess->snaclogin)
+  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)
     curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000);
   else {
     curbyte  = aimutil_put16(newpacket->data, 0x0000);
@@ -160,7 +161,7 @@ faim_export int aim_send_login (struct aim_session_t *sess,
 
   curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
   
-  if (sess->snaclogin) {
+  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
     md5_byte_t digest[16];
 
     aim_encode_password_md5(password, key, digest);
@@ -178,7 +179,7 @@ faim_export int aim_send_login (struct aim_session_t *sess,
   if (strlen(clientinfo->clientstring))
     curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring);
 
-  if (sess->snaclogin) {
+  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
     curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, (unsigned short)clientinfo->major2);
     curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, (unsigned short)clientinfo->major);
     curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, (unsigned short)clientinfo->minor);
@@ -292,7 +293,7 @@ faim_internal int aim_authparse(struct aim_session_t *sess,
    * For SNAC login, there's a 17/3 SNAC header in front.
    *
    */
-  if (sess->snaclogin)
+  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)
     tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
   else
     tlvlist = aim_readtlvchain(command->data, command->commandlen);
index 220394f2abf907ce6a8aa264b42caf83449a0555..bc67cbf0193783064e1936238b4ca85131d3eadc 100644 (file)
@@ -348,7 +348,7 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
        head = aimutil_get32(workingPtr->data);
        if ((head == 0x00000001) && (workingPtr->commandlen == 4)) {
          faimdprintf(1, "got connection ack on auth line\n");
-         workingPtr->handled = 1;
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
        } else if (workingPtr->hdr.oscar.type == 0x04) {
          /* Used only by the older login protocol */
          workingPtr->handled = aim_authparse(sess, workingPtr);
@@ -405,7 +405,7 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
        switch (family) {
        case 0x0000: /* not really a family, but it works */
          if (subtype == 0x0001)
-           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
+           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
          else
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
          break;
@@ -541,10 +541,9 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
        u_short subtype;
        family = aimutil_get16(workingPtr->data);
        subtype= aimutil_get16(workingPtr->data+2);
-       
-       if ((family == 0x0002) && (subtype == 0x0006)) {
-         workingPtr->handled = 1;
-         aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
+
+       if ((family == 0x0000) && (subtype == 0x00001)) {
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
        } else if ((family == 0x000d) && (subtype == 0x0009)) {
          workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
        } else {
@@ -558,9 +557,9 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
        family = aimutil_get16(workingPtr->data);
        subtype= aimutil_get16(workingPtr->data+2);
        
-       if ((family == 0x0000) && (subtype == 0x00001))
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
-       else if (family == 0x0001) {
+       if ((family == 0x0000) && (subtype == 0x00001)) {
+         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
+       else if (family == 0x0001) {
          if (subtype == 0x0001)
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
          else if (subtype == 0x0003)
@@ -804,6 +803,9 @@ faim_internal int aim_parse_unknown(struct aim_session_t *sess,
 {
   u_int i = 0;
 
+  if (!sess || !command)
+    return 1;
+
   faimdprintf(1, "\nRecieved unknown packet:");
 
   for (i = 0; i < command->commandlen; i++)
index c625bc2628c9957f0d30e807ee41af70e7bd5bb4..a26648afa234719f637e9e440cd31f9a320bc390 100644 (file)
@@ -60,6 +60,9 @@ faim_export int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *c
   if (conn->fd < 3)  /* can happen when people abuse the interface */
     return 0;
 
+  if (conn->status & AIM_CONN_STATUS_INPROGRESS)
+    return aim_conn_completeconnect(sess, conn);
+
   /*
    * Rendezvous (client-client) connections do not speak
    * FLAP, so this function will break on them.
index 6f6b3c10d301313f1e354c8d81ffe2e8ff1cf454..9871f938c523691feec5ab0905175e4eb8ec04d2 100644 (file)
@@ -151,6 +151,19 @@ faim_internal int aim_tx_enqueue__immediate(struct aim_session_t *sess, struct c
   return 0;
 }
 
+faim_internal int aim_tx_enqueue(struct aim_session_t *sess, struct command_tx_struct *command)
+{
+  /*
+   * If we want to send a connection thats inprogress, we have to force
+   * them to use the queue based version. Otherwise, use whatever they
+   * want.
+   */
+  if (command && command->conn && (command->conn->status & AIM_CONN_STATUS_INPROGRESS)) {
+    return aim_tx_enqueue__queuebased(sess, command);
+  }
+  return (*sess->tx_enqueue)(sess, command);
+}
+
 /* 
  *  aim_get_next_txseqnum()
  *
@@ -347,6 +360,9 @@ faim_export int aim_tx_flushqueue(struct aim_session_t *sess)
     /* only process if its unlocked and unsent */
     if (!cur->lock && !cur->sent) {
 
+      if (cur->conn && (cur->conn->status & AIM_CONN_STATUS_INPROGRESS))
+       continue;
+
       /*
        * And now for the meager attempt to force transmit
        * latency and avoid missed messages.
index 645b06b1941479da465ce123b4aec3e6ec7d7f95..46e2e8f88f6b1697daf70ee802885df855f7dce2 100644 (file)
@@ -208,8 +208,9 @@ struct client_info_s {
  */
 #define AIM_CONN_STATUS_READY       0x0001
 #define AIM_CONN_STATUS_INTERNALERR 0x0002
-#define AIM_CONN_STATUS_RESOLVERR   0x0080
-#define AIM_CONN_STATUS_CONNERR     0x0040
+#define AIM_CONN_STATUS_RESOLVERR   0x0040
+#define AIM_CONN_STATUS_CONNERR     0x0080
+#define AIM_CONN_STATUS_INPROGRESS  0x0100
 
 #define AIM_FRAMETYPE_OSCAR 0x0000
 #define AIM_FRAMETYPE_OFT 0x0001
@@ -350,11 +351,15 @@ struct aim_session_t {
     char password[128];
   } socksproxy;
 
-  int snaclogin;
+  unsigned long flags;
 
   struct aim_msgcookie_t *msgcookies;
 };
 
+/* Values for sess->flags */
+#define AIM_SESS_FLAGS_SNACLOGIN       0x00000001
+#define AIM_SESS_FLAGS_XORLOGIN        0x00000002
+#define AIM_SESS_FLAGS_NONBLOCKCONNECT 0x00000004
 
 /*
  * AIM User Info, Standard Form.
@@ -468,7 +473,7 @@ faim_internal int aim_get_command_rendezvous(struct aim_session_t *sess, struct
 faim_internal struct command_tx_struct *aim_tx_new(unsigned char framing, int chan, struct aim_conn_t *conn, int datalen);
 faim_internal int aim_tx_enqueue__queuebased(struct aim_session_t *, struct command_tx_struct *);
 faim_internal int aim_tx_enqueue__immediate(struct aim_session_t *, struct command_tx_struct *);
-#define aim_tx_enqueue(x, y) ((*(x->tx_enqueue))(x, y))
+faim_internal int aim_tx_enqueue(struct aim_session_t *, struct command_tx_struct *);
 faim_internal int aim_tx_sendframe(struct aim_session_t *sess, struct command_tx_struct *cur);
 faim_internal unsigned int aim_get_next_txseqnum(struct aim_conn_t *);
 faim_export int aim_tx_flushqueue(struct aim_session_t *);
@@ -517,7 +522,9 @@ faim_export int aim_conngetmaxfd(struct aim_session_t *);
 faim_export struct aim_conn_t *aim_select(struct aim_session_t *, struct timeval *, int *);
 faim_export int aim_conn_isready(struct aim_conn_t *);
 faim_export int aim_conn_setstatus(struct aim_conn_t *, int);
-faim_export void aim_session_init(struct aim_session_t *);
+faim_export int aim_conn_completeconnect(struct aim_session_t *sess, struct aim_conn_t *conn);
+faim_export int aim_conn_isconnecting(struct aim_conn_t *conn);
+faim_export void aim_session_init(struct aim_session_t *, unsigned long flags);
 faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *username, char *password);
 
 /* aim_misc.c */
index 6e8fa74227d5a874b84aa68c6f7c6b0be9ffd786..c0705ba9b037dbe10b8bc724acc4a0337a08cd1b 100644 (file)
 #define AIM_CB_SPECIAL_AUTHSUCCESS 0x0001
 #define AIM_CB_SPECIAL_AUTHOTHER 0x0002
 #define AIM_CB_SPECIAL_CONNERR 0x0003
+#define AIM_CB_SPECIAL_CONNCOMPLETE 0x0004
+#define AIM_CB_SPECIAL_FLAPVER 0x0005
 #define AIM_CB_SPECIAL_DEBUGCONN_CONNECT 0xe001
 #define AIM_CB_SPECIAL_UNKNOWN 0xffff
 #define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN
index cfd6c647c6bec60b1bd3fd746c708ed92b364fab..687ca7ced5a78b67fdbfa8bc371d233934b46475 100644 (file)
@@ -116,6 +116,8 @@ static char *msgerrreasons[] = {
   "Not while on AOL"};
 static int msgerrreasonslen = 25;
 
+static char *screenname,*password,*server=NULL;
+
 int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
   if (command->data) {
@@ -125,6 +127,49 @@ int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct
   return 1;
 }
 
+int faimtest_flapversion(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+
+  printf("faimtest: using FLAP version %u\n", aimutil_get32(command->data));
+
+#if 0
+  /* 
+   * This is an alternate location for starting the login process.
+   */
+  /* XXX should do more checking to make sure its really the right AUTH conn */
+  if (command->conn->type == AIM_CONN_TYPE_AUTH) {
+    /* do NOT send a connack/flapversion, request_login will send it if needed */
+    aim_request_login(sess, command->conn, screenname);
+    printf("faimtest: login request sent\n");
+  }
+#endif
+
+  return 1;
+}
+
+/*
+ * This is a frivilous callback. You don't need it. I only used it for
+ * debugging non-blocking connects.
+ *
+ * If packets are sent to a conn before its fully connected, they
+ * will be queued and then transmitted when the connection completes.
+ *
+ */
+int faimtest_conncomplete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  va_list ap;
+  struct aim_conn_t *conn;
+
+  va_start(ap, command);
+  conn = va_arg(ap, struct aim_conn_t *);
+  va_end(ap);
+  
+  if (conn)
+    printf("faimtest: connection on %d completed\n", conn->fd);
+
+  return 1;
+}
+
 #ifdef _WIN32
 /*
  * This is really all thats needed to link against libfaim on win32.
@@ -142,8 +187,6 @@ int initwsa(void)
 }
 #endif /* _WIN32 */
 
-static char *screenname,*password,*server=NULL;
-
 int main(void)
 {
   struct aim_session_t aimsess;
@@ -183,7 +226,8 @@ int main(void)
   }
 #endif /* _WIN32 */
 
-  aim_session_init(&aimsess);
+  /* Pass zero as flags if you want blocking connects */
+  aim_session_init(&aimsess, AIM_SESS_FLAGS_NONBLOCKCONNECT);
 
 #ifdef FILESUPPORT
   if(listingpath) {
@@ -221,14 +265,15 @@ int main(void)
     return -1;
   }
 
+  aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
+  aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
   aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
-  aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
-    
-  /* do NOT send a connack/flapversion, request_login will send it if needed */
-  aim_request_login(&aimsess, authconn, screenname);
+  aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);    
 
   aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, faimtest_debugconn_connect, 0);
 
+  /* If the connection is in progress, this will just be queued */
+  aim_request_login(&aimsess, authconn, screenname);
   printf("faimtest: login request sent\n");
 
   while (keepgoing) {
@@ -432,11 +477,13 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
        struct aim_conn_t *tstconn;
        /* Open a connection to the Auth */
        tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
-       if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR) )
+       if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR) )
          fprintf(stderr, "faimtest: unable to reconnect with authorizer\n");
-       else
+       else {
+         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
          /* Send the cookie to the Auth */
          aim_auth_sendcookie(sess, tstconn, cookie);
+       }
 
       }  
       break;
@@ -444,7 +491,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
       {
        struct aim_conn_t *tstconn = NULL;
        tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
-       if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) {
+       if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
          fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
          if (tstconn) aim_conn_kill(sess, &tstconn);
          return 1;
@@ -454,6 +501,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
        aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
 #endif
        aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
+       aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
        aim_auth_sendcookie(sess, tstconn, cookie);
        fprintf(stderr, "\achatnav: connected\n");
       }
@@ -466,7 +514,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
        roomname = va_arg(ap, char *);
 
        tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
-       if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
+       if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR))
          {
            fprintf(stderr, "faimtest: unable to connect to chat server\n");
            if (tstconn) aim_conn_kill(sess, &tstconn);
@@ -480,6 +528,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
        aim_chat_attachname(tstconn, roomname);
 
        aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
+       aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
        aim_auth_sendcookie(sess, tstconn, cookie);
       }
       break;
@@ -520,10 +569,11 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct
   bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, sess->logininfo.BOSIP);
   if (bosconn == NULL) {
     fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
-  } else if (bosconn->status != 0) {   
+  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {      
     fprintf(stderr, "faimtest: could not connect to BOS\n");
     aim_conn_kill(sess, &bosconn);
   } else {
+    aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
     aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
     aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
This page took 0.0956630000000001 seconds and 5 git commands to generate.