]> andersk Git - libfaim.git/commitdiff
- Mon Sep 10 06:15:43 PDT 2001
authormid <mid>
Mon, 10 Sep 2001 13:50:28 +0000 (13:50 +0000)
committermid <mid>
Mon, 10 Sep 2001 13:50:28 +0000 (13:50 +0000)
  - Remove $Id line from md5.h. I really really hate those things.
  - Remove all that locking crap. It never worked right anyway.
  - Add conn->inside for things that should never ever be seen by clients
  - Store supported groups list for each connection
  - Support migrations.
   - faimtest now theoretically supports doing this.  It happens so rarely
       that it makes it difficult to test.  For more complicated clients, a
       flag will have to be kept so that some things that happen during login
       don't get triggered the second time around.  But faimtest doesn't have
       such problems.
  - Added some random commentary.

13 files changed:
CHANGES
include/aim.h
include/aim_internal.h
include/faimconfig.h
include/md5.h
src/chat.c
src/conn.c
src/login.c
src/rxqueue.c
src/snac.c
src/txqueue.c
utils/faimtest/faimtest.c
utils/faimtest/login.c

diff --git a/CHANGES b/CHANGES
index f333ad10d1fc3489c9a9a8b092a28fc5685a15a0..d1bc81e7725510aefe675e069f21015ae8c814f5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,19 @@
 
 No release numbers
 ------------------
+ - Mon Sep 10 06:15:43 PDT 2001
+  - Remove $Id line from md5.h. I really really hate those things.
+  - Remove all that locking crap. It never worked right anyway.
+  - Add conn->inside for things that should never ever be seen by clients
+  - Store supported groups list for each connection
+  - Support migrations.
+   - faimtest now theoretically supports doing this.  It happens so rarely
+       that it makes it difficult to test.  For more complicated clients, a
+       flag will have to be kept so that some things that happen during login
+       don't get triggered the second time around.  But faimtest doesn't have
+       such problems.
+  - Added some random commentary.
+
  - Sun Sep  9 03:01:28 PDT 2001
   - Three fixes in directim for gaim.  It works now. Yay.
 
index ffd7c8c625fc2f375417b8379e44481e9cf849fc..2bc4c344c7fa3ac0ba7967a590173c34157e38d4 100644 (file)
 #include <faimconfig.h>
 #include <aim_cbtypes.h>
 
-#if !defined(FAIM_USEPTHREADS) && !defined(FAIM_USEFAKELOCKS) && !defined(FAIM_USENOPLOCKS)
-#error pthreads, fakelocks, or noplocks are currently required.
-#endif
-
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
@@ -46,40 +42,6 @@ typedef unsigned long fu32_t;
 typedef fu32_t aim_snacid_t;
 typedef fu16_t flap_seqnum_t;
 
-#ifdef FAIM_USEPTHREADS
-#include <pthread.h>
-#define faim_mutex_t pthread_mutex_t 
-#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
- * we're not linking against a threaded app.  Which
- * means we don't have to do real locking.  The 
- * macros below do nothing really.  They're a joke.
- * But they get it to compile.
- * 
- * XXX NOTE that locking hasn't really been tested in a long time,
- * and most code written after dec2000 --is not thread safe--.  You'll
- * want to audit locking use before you use less-than-library level
- * concurrency.
- *
- */
-#define faim_mutex_t fu8_t 
-#define faim_mutex_init(x) *x = 0
-#define faim_mutex_lock(x) while(*x != 0) {/* spin */}; *x = 1;
-#define faim_mutex_unlock(x) while(*x != 0) {/* spin spin spin */}; *x = 0;
-#define faim_mutex_destroy(x) while(*x != 0) {/* spiiiinnn */}; *x = 0;
-#elif defined(FAIM_USENOPLOCKS)
-#define faim_mutex_t fu8_t 
-#define faim_mutex_init(x)
-#define faim_mutex_lock(x)
-#define faim_mutex_unlock(x)
-#define faim_mutex_destroy(x)
-#endif
-
 /* Portability stuff (DMP) */
 
 #ifdef _WIN32
@@ -272,9 +234,8 @@ typedef struct aim_conn_s {
        time_t lastactivity; /* time of last transmit */
        int forcedlatency; 
        void *handlerlist;
-       faim_mutex_t active; /* lock around read/writes */
-       faim_mutex_t seqnum_lock; /* lock around ->seqnum changes */
        void *sessv; /* pointer to parent session */
+       void *inside; /* only accessible from inside libfaim */
        struct aim_conn_s *next;
 } aim_conn_t;
 
@@ -352,7 +313,6 @@ typedef struct aim_session_s {
 
        /* Connection information */
        aim_conn_t *connlist;
-       faim_mutex_t connlistlock;
 
        /*
         * Transmit/receive queues.
@@ -389,7 +349,6 @@ typedef struct aim_session_s {
         * XXX: Should these be per-connection? -mid
         */
        void *snac_hash[FAIM_SNAC_HASH_SIZE];
-       faim_mutex_t snac_hash_locks[FAIM_SNAC_HASH_SIZE];
        aim_snacid_t snacid_next;
 
        struct {
@@ -540,6 +499,7 @@ faim_export int aim_conn_setlatency(aim_conn_t *conn, int newval);
 faim_export int aim_conn_addhandler(aim_session_t *, aim_conn_t *conn, u_short family, u_short type, aim_rxcallback_t newhandler, u_short flags);
 faim_export int aim_clearhandlers(aim_conn_t *conn);
 
+faim_export aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, fu16_t group);
 faim_export aim_session_t *aim_conn_getsess(aim_conn_t *conn);
 faim_export void aim_conn_close(aim_conn_t *deadconn);
 faim_export aim_conn_t *aim_newconn(aim_session_t *, int type, const char *dest);
@@ -571,6 +531,7 @@ faim_export aim_conn_t *aim_getconn_fd(aim_session_t *, int fd);
 
 #define AIM_WARN_ANON                     0x01
 
+faim_export int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn);
 faim_export int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags);
 faim_export int aim_bos_nop(aim_session_t *, aim_conn_t *);
 faim_export int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn);
index 635a47d562f7123c2ab79167ede12e8d95a0dc6e..b82e1cd2a52ca0689effd1c4409b3585d6d30085 100644 (file)
@@ -127,6 +127,28 @@ struct aim_tool_version {
        fu16_t toolversion;
 };
 
+/* 
+ * In SNACland, the terms 'family' and 'group' are synonymous -- the former
+ * is my term, the latter is AOL's.
+ */
+struct snacgroup {
+       fu16_t group;
+       struct snacgroup *next;
+};
+
+/*
+ * This is inside every connection.  But it is a void * to anything
+ * outside of libfaim.  It should remain that way.  It's called data
+ * abstraction.  Maybe you've heard of it.  (Probably not if you're a 
+ * libfaim user.)
+ * 
+ */
+typedef struct aim_conn_inside_s {
+       struct snacgroup *groups;
+} aim_conn_inside_t;
+
+faim_internal void aim_conn_addgroup(aim_conn_t *conn, fu16_t group);
+
 faim_internal fu16_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len);
 faim_internal int aim_putcap(aim_bstream_t *bs, fu16_t caps);
 
index 84dc448552e4357bb1c26752154deeac4e9eaaf3..64987030bacdae005e0120a7e9cb3269a67726b0 100644 (file)
 #define FAIM_LOGIN_SERVER "login.oscar.aol.com"
 #define FAIM_LOGIN_PORT 5190
 
-/*
- * What type of synchronisation to use.
- * 
- * We don't actually use threads, but can use the POSIX mutex
- * in order to maintain thread safety.  You can use the fake locking
- * if you really don't like pthreads (which I don't) or if you don't
- * have it.
- *
- *   USEPTHREADS - Use POSIX mutecies
- *   USEFAKELOCKS - Use little stub spinners to help find locking bugs
- *   USENOPLOCKS - No-op out all synchro calls at compile time
- * 
- * Default: use noplocks by default.
- *
- * !!!NOTE: Even with USEPTHREADS turned on, libfaim is not fully thread
- *          safe.  It will still take some effort to add locking calls to
- *          the places that need them.  In fact, this feature in general
- *          is in danger of being officially deprecated and removed from 
- *          the code.
- *
- */
-#undef FAIM_USEPTHREADS
-#undef FAIM_USEFAKELOCKS
-#define FAIM_USENOPLOCKS
-
 /*
  * Size of the SNAC caching hash.
  *
index a2d7b341563bf9b8aeec8ccc62ad70600c441e66..501cdbe152d1118cc64ea034023157fb193eeb5a 100644 (file)
@@ -21,7 +21,6 @@
   ghost@aladdin.com
 
  */
-/*$Id$ */
 /*
   Independent implementation of MD5 (RFC 1321).
 
index 7a09c0b46221025aaec3e87b3f4fa88aa72dcc7c..ba96e27b2310873979b0495a034bfeefe232f068 100644 (file)
@@ -20,11 +20,11 @@ faim_export char *aim_chat_getname(aim_conn_t *conn)
        return (char *)conn->priv; /* yuck ! */
 }
 
+/* XXX get this into conn.c -- evil!! */
 faim_export aim_conn_t *aim_chat_getconn(aim_session_t *sess, const char *name)
 {
        aim_conn_t *cur;
 
-       faim_mutex_lock(&sess->connlistlock);
        for (cur = sess->connlist; cur; cur = cur->next) {
                if (cur->type != AIM_CONN_TYPE_CHAT)
                        continue;
@@ -35,7 +35,6 @@ faim_export aim_conn_t *aim_chat_getconn(aim_session_t *sess, const char *name)
                if (strcmp((char *)cur->priv, name) == 0)
                        break;
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        return cur;
 }
index e489b1c035191a22c96f78eac59976f50bae2456..7744e503aca93571981766d5e9d6ac77c58384c5 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- *  aim_conn.c
+ * conn.c
  *
  * Does all this gloriously nifty connection handling stuff...
  *
 #include <netinet/in.h>
 #endif
 
+/*
+ * In OSCAR, every connection has a set of SNAC groups associated
+ * with it.  These are the groups that you can send over this connection
+ * without being guarenteed a "Not supported" SNAC error.  
+ *
+ * The grand theory of things says that these associations transcend 
+ * what libfaim calls "connection types" (conn->type).  You can probably
+ * see the elegance here, but since I want to revel in it for a bit, you 
+ * get to hear it all spelled out.
+ *
+ * So let us say that you have your core BOS connection running.  One
+ * of your modules has just given you a SNAC of the group 0x0004 to send
+ * you.  Maybe an IM destined for some twit in Greenland.  So you start
+ * at the top of your connection list, looking for a connection that 
+ * claims to support group 0x0004.  You find one.  Why, that neat BOS
+ * connection of yours can do that.  So you send it on its way.
+ *
+ * Now, say, that fellow from Greenland has friends and they all want to
+ * meet up with you in a lame chat room.  This has landed you a SNAC
+ * in the family 0x000e and you have to admit you're a bit lost.  You've
+ * searched your connection list for someone who wants to make your life
+ * easy and deliver this SNAC for you, but there isn't one there.
+ *
+ * Here comes the good bit.  Without even letting anyone know, particularly
+ * the module that decided to send this SNAC, and definitly not that twit
+ * in Greenland, you send out a service request.  In this request, you have
+ * marked the need for a connection supporting group 0x000e.  A few seconds
+ * later, you receive a service redirect with an IP address and a cookie in
+ * it.  Great, you say.  Now I have something to do.  Off you go, making
+ * that connection.  One of the first things you get from this new server
+ * is a message saying that indeed it does support the group you were looking
+ * for.  So you continue and send rate confirmation and all that.  
+ * 
+ * Then you remember you had that SNAC to send, and now you have a means to
+ * do it, and you do, and everyone is happy.  Except the Greenlander, who is
+ * still stuck in the bitter cold.
+ *
+ * Oh, and this is useful for building the Migration SNACs, too.  In the
+ * future, this may help convince me to implement rate limit mitigation
+ * for real.  We'll see.
+ *
+ * Just to make me look better, I'll say that I've known about this great
+ * scheme for quite some time now.  But I still haven't convinced myself
+ * to make libfaim work that way.  It would take a fair amount of effort,
+ * and probably some client API changes as well.  (Whenever I don't want
+ * to do something, I just say it would change the client API.  Then I 
+ * instantly have a couple of supporters of not doing it.)
+ *
+ * Generally, addgroup is only called by the internal handling of the
+ * server ready SNAC.  So if you want to do something before that, you'll
+ * have to be more creative.  That is done rather early, though, so I don't
+ * think you have to worry about it.  Unless you're me.  I care deeply
+ * about such inane things.
+ *
+ */
+faim_internal void aim_conn_addgroup(aim_conn_t *conn, fu16_t group)
+{
+       aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
+       struct snacgroup *sg;
+
+       if (!(sg = malloc(sizeof(struct snacgroup))))
+               return;
+
+       faimdprintf(aim_conn_getsess(conn), 1, "adding group 0x%04x\n", group);
+       sg->group = group;
+
+       sg->next = ins->groups;
+       ins->groups = sg;
+
+       return;
+}
+
+faim_export aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, fu16_t group)
+{
+       aim_conn_t *cur;
+
+       for (cur = sess->connlist; cur; cur = cur->next) {
+               aim_conn_inside_t *ins = (aim_conn_inside_t *)cur->inside;
+               struct snacgroup *sg;
+
+               for (sg = ins->groups; sg; sg = sg->next) {
+                       if (sg->group == group)
+                               return cur;
+               }
+       }
+
+       return NULL;
+}
+
+static struct snacgroup *connkill_snacgroups(struct snacgroup *sg)
+{
+
+       while (sg) {
+               struct snacgroup *tmp;
+
+               tmp = sg->next;
+               free(sg);
+               sg = tmp;
+       }
+
+       return NULL;
+}
+
 static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn)
 {
 
@@ -38,6 +141,14 @@ static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn)
        if ((*deadconn)->type == AIM_CONN_TYPE_RENDEZVOUS)
                aim_conn_kill_rend(sess, *deadconn);
 
+       if ((*deadconn)->inside) {
+               aim_conn_inside_t *inside = (aim_conn_inside_t *)(*deadconn)->inside;
+
+               inside->groups = connkill_snacgroups(inside->groups);
+
+               free(inside);
+       }
+
        free(*deadconn);
        deadconn = NULL;
 
@@ -54,8 +165,6 @@ static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn)
 static void aim_connrst(aim_session_t *sess)
 {
 
-       faim_mutex_init(&sess->connlistlock);
-
        if (sess->connlist) {
                aim_conn_t *cur = sess->connlist, *tmp;
 
@@ -93,8 +202,7 @@ static void aim_conn_init(aim_conn_t *deadconn)
        deadconn->forcedlatency = 0;
        deadconn->handlerlist = NULL;
        deadconn->priv = NULL;
-       faim_mutex_init(&deadconn->active);
-       faim_mutex_init(&deadconn->seqnum_lock);
+       memset(deadconn->inside, 0, sizeof(aim_conn_inside_t));
 
        return;
 }
@@ -114,6 +222,12 @@ static aim_conn_t *aim_conn_getnext(aim_session_t *sess)
                return NULL;
        memset(newconn, 0, sizeof(aim_conn_t));
 
+       if (!(newconn->inside = malloc(sizeof(aim_conn_inside_t)))) {
+               free(newconn);
+               return NULL;
+       }
+       memset(newconn->inside, 0, sizeof(aim_conn_inside_t));
+
        aim_conn_init(newconn);
 
        newconn->next = sess->connlist;
@@ -168,8 +282,6 @@ faim_export void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn)
 faim_export void aim_conn_close(aim_conn_t *deadconn)
 {
 
-       faim_mutex_destroy(&deadconn->active);
-       faim_mutex_destroy(&deadconn->seqnum_lock);
        if (deadconn->fd >= 3)
                close(deadconn->fd);
        deadconn->fd = -1;
@@ -178,7 +290,6 @@ faim_export void aim_conn_close(aim_conn_t *deadconn)
        if (deadconn->type == AIM_CONN_TYPE_RENDEZVOUS)
                aim_conn_close_rend((aim_session_t *)deadconn->sessv, deadconn);
 
-
        return;
 }
 
@@ -191,18 +302,18 @@ faim_export void aim_conn_close(aim_conn_t *deadconn)
  * specified session.  Returns the first connection of that
  * type found.
  *
+ * XXX except for RENDEZVOUS, all uses of this should be removed and
+ * use aim_conn_findbygroup() instead.
  */
 faim_export aim_conn_t *aim_getconn_type(aim_session_t *sess, int type)
 {
        aim_conn_t *cur;
 
-       faim_mutex_lock(&sess->connlistlock);
        for (cur = sess->connlist; cur; cur = cur->next) {
                if ((cur->type == type) && 
                                !(cur->status & AIM_CONN_STATUS_INPROGRESS))
                        break;
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        return cur;
 }
@@ -211,12 +322,10 @@ faim_export aim_conn_t *aim_getconn_type_all(aim_session_t *sess, int type)
 {
        aim_conn_t *cur;
 
-       faim_mutex_lock(&sess->connlistlock);
        for (cur = sess->connlist; cur; cur = cur->next) {
                if (cur->type == type)
                        break;
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        return cur;
 }
@@ -226,12 +335,10 @@ faim_export aim_conn_t *aim_getconn_fd(aim_session_t *sess, int fd)
 {
        aim_conn_t *cur;
 
-       faim_mutex_lock(&sess->connlistlock);
        for (cur = sess->connlist; cur; cur = cur->next) {
                if (cur->fd == fd)
                        break;
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        return cur;
 }
@@ -425,8 +532,6 @@ faim_internal aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src)
        if (!(conn = aim_conn_getnext(sess)))
                return NULL;
 
-       faim_mutex_lock(&conn->active);
-
        conn->fd = src->fd;
        conn->type = src->type;
        conn->subtype = src->subtype;
@@ -438,7 +543,15 @@ faim_internal aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src)
        conn->sessv = src->sessv;
        aim_clonehandlers(sess, conn, src);
 
-       faim_mutex_unlock(&conn->active);
+       if (src->inside) {
+               /*
+                * XXX should clone this section as well, but since currently
+                * this function only gets called for some of that rendezvous
+                * crap, and not on SNAC connections, its probably okay for
+                * now. 
+                *
+                */
+       }
 
        return conn;
 }
@@ -467,15 +580,12 @@ faim_export aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *d
        if (!(connstruct = aim_conn_getnext(sess)))
                return NULL;
 
-       faim_mutex_lock(&connstruct->active);
-
        connstruct->sessv = (void *)sess;
        connstruct->type = type;
 
        if (!dest) { /* just allocate a struct */
                connstruct->fd = -1;
                connstruct->status = 0;
-               faim_mutex_unlock(&connstruct->active);
                return connstruct;
        }
 
@@ -503,13 +613,10 @@ faim_export aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *d
                connstruct->fd = -1;
                connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
                free(host);
-               faim_mutex_unlock(&connstruct->active);
                return connstruct;
        } else
                connstruct->fd = ret;
 
-       faim_mutex_unlock(&connstruct->active);
-
        free(host);
 
        return connstruct;
@@ -528,12 +635,10 @@ faim_export int aim_conngetmaxfd(aim_session_t *sess)
        int j;
        aim_conn_t *cur;
 
-       faim_mutex_lock(&sess->connlistlock);
        for (cur = sess->connlist, j = 0; cur; cur = cur->next) {
                if (cur->fd > j)
                        j = cur->fd;
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        return j;
 }
@@ -551,14 +656,10 @@ faim_export int aim_conn_in_sess(aim_session_t *sess, aim_conn_t *conn)
 {
        aim_conn_t *cur;
 
-       faim_mutex_lock(&sess->connlistlock);
        for (cur = sess->connlist; cur; cur = cur->next) {
-               if (cur == conn) {
-                       faim_mutex_unlock(&sess->connlistlock);
+               if (cur == conn)
                        return 1;
-               }
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        return 0;
 }
@@ -578,8 +679,6 @@ faim_export int aim_conn_in_sess(aim_session_t *sess, aim_conn_t *conn)
  *    1  outgoing data pending (%NULL returned)
  *    2  incoming data pending (connection with pending data returned)
  *
- * XXX: we could probably stand to do a little courser locking here.
- *
  */ 
 faim_export aim_conn_t *aim_select(aim_session_t *sess, struct timeval *timeout, int *status)
 {
@@ -587,23 +686,18 @@ faim_export aim_conn_t *aim_select(aim_session_t *sess, struct timeval *timeout,
        fd_set fds, wfds;
        int maxfd, i, haveconnecting = 0;
 
-       faim_mutex_lock(&sess->connlistlock);
        if (!sess->connlist) {
-               faim_mutex_unlock(&sess->connlistlock);
                *status = -1;
                return NULL;
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        FD_ZERO(&fds);
        FD_ZERO(&wfds);
 
-       faim_mutex_lock(&sess->connlistlock);
        for (cur = sess->connlist, maxfd = 0; cur; cur = cur->next) {
                if (cur->fd == -1) {
                        /* don't let invalid/dead connections sit around */
                        *status = 2;
-                       faim_mutex_unlock(&sess->connlistlock);
                        return cur;
                } else if (cur->status & AIM_CONN_STATUS_INPROGRESS) {
                        FD_SET(cur->fd, &wfds);
@@ -614,7 +708,6 @@ faim_export aim_conn_t *aim_select(aim_session_t *sess, struct timeval *timeout,
                if (cur->fd > maxfd)
                        maxfd = cur->fd;
        }
-       faim_mutex_unlock(&sess->connlistlock);
 
        /* 
         * If we have data waiting to be sent, return
@@ -636,14 +729,12 @@ faim_export aim_conn_t *aim_select(aim_session_t *sess, struct timeval *timeout,
        } 
 
        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)) || 
                                        ((cur->status & AIM_CONN_STATUS_INPROGRESS) && 
                                        FD_ISSET(cur->fd, &wfds))) {
                                *status = 2;
-                               faim_mutex_unlock(&sess->connlistlock);
-                               return cur; /* XXX race condition here -- shouldnt unlock connlist */
+                               return cur;
                        }
                }
                *status = 0; /* shouldn't happen */
@@ -652,8 +743,6 @@ faim_export aim_conn_t *aim_select(aim_session_t *sess, struct timeval *timeout,
        else
                *status = i; /* can be 0 or -1 */
 
-       faim_mutex_unlock(&sess->connlistlock);
-
        return NULL;  /* no waiting or error, return */
 }
 
@@ -677,10 +766,8 @@ faim_export int aim_conn_setlatency(aim_conn_t *conn, int newval)
        if (!conn)
                return -1;
 
-       faim_mutex_lock(&conn->active);
        conn->forcedlatency = newval;
        conn->lastactivity = 0; /* reset this just to make sure */
-       faim_mutex_unlock(&conn->active);
 
        return 0;
 }
index f7776f5f32a416b408a68328b264f1abd1d90a0c..4cce808a4ba51ab721491dbd970db7fa872cbe69 100644 (file)
@@ -382,6 +382,10 @@ faim_export int aim_gencookie(fu8_t *buf)
 
 /*
  * Send Server Ready.  (Non-client)
+ * 
+ * XXX If anyone cares, this should be made to use the conn-stored group
+ * system.
+ *
  */
 faim_export int aim_sendserverready(aim_session_t *sess, aim_conn_t *conn)
 {
@@ -412,7 +416,6 @@ faim_export int aim_sendserverready(aim_session_t *sess, aim_conn_t *conn)
        return 0;
 }
 
-
 /* 
  * Send service redirect.  (Non-Client)
  */
@@ -440,7 +443,13 @@ faim_export int aim_sendredirect(aim_session_t *sess, aim_conn_t *conn, fu16_t s
        return 0;
 }
 
-
+/*
+ * See comments in conn.c about how the group associations are supposed
+ * to work, and how they really work.
+ *
+ * This info probably doesn't even need to make it to the client.
+ *
+ */
 static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
 {
        aim_rxcallback_t userfunc;
@@ -451,8 +460,10 @@ static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a
        if (!(families = malloc(aim_bstream_empty(bs))))
                return 0;
 
-       for (famcount = 0; aim_bstream_empty(bs); famcount++)
+       for (famcount = 0; aim_bstream_empty(bs); famcount++) {
                families[famcount] = aimbs_get16(bs);
+               aim_conn_addgroup(rx->conn, families[famcount]);
+       }
 
        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
                ret = userfunc(sess, rx, famcount, families);
@@ -622,6 +633,114 @@ static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a
        return 0;
 }
 
+/*
+ * How Migrations work.  
+ *
+ * The server sends a Server Pause message, which the client should respond to 
+ * with a Server Pause Ack, which contains the families it needs on this 
+ * connection. The server will send a Migration Notice with an IP address, and 
+ * then disconnect. Next the client should open the connection and send the 
+ * cookie.  Repeat the normal login process and pretend this never happened.
+ *
+ * The Server Pause contains no data.
+ *
+ */
+static int serverpause(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
+{
+       aim_rxcallback_t userfunc;
+
+       if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+               return userfunc(sess, rx);
+
+       return 0;
+}
+
+/*
+ * It is rather important that aim_sendpauseack() gets called for the exact
+ * same connection that the Server Pause callback was called for, since
+ * libfaim extracts the data for the SNAC from the connection structure.
+ *
+ * Of course, if you don't do that, more bad things happen than just what
+ * libfaim can cause.
+ *
+ */
+faim_export int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn)
+{
+       aim_frame_t *fr;
+       aim_snacid_t snacid;
+       aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
+       struct snacgroup *sg;
+
+       if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1024)))
+               return -ENOMEM;
+
+       snacid = aim_cachesnac(sess, 0x0001, 0x000c, 0x0000, NULL, 0);
+       aim_putsnac(&fr->data, 0x0001, 0x000c, 0x0000, snacid);
+
+       /*
+        * This list should have all the groups that the original 
+        * Host Online / Server Ready said this host supports.  And 
+        * we want them all back after the migration.
+        */
+       for (sg = ins->groups; sg; sg = sg->next)
+               aimbs_put16(&fr->data, sg->group);
+
+       aim_tx_enqueue(sess, fr);
+
+       return 0;
+}
+
+/*
+ * This is the final SNAC sent on the original connection during a migration.
+ * It contains the IP and cookie used to connect to the new server, and 
+ * optionally a list of the SNAC groups being migrated.
+ *
+ */
+static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
+{
+       aim_rxcallback_t userfunc;
+       int ret = 0;
+       fu16_t groupcount, i;
+       aim_tlvlist_t *tl;
+       char *ip = NULL;
+       aim_tlv_t *cktlv;
+
+       /*
+        * Apparently there's some fun stuff that can happen right here. The
+        * migration can actually be quite selective about what groups it
+        * moves to the new server.  When not all the groups for a connection
+        * are migrated, or they are all migrated but some groups are moved
+        * to a different server than others, it is called a bifurcated 
+        * migration.
+        *
+        * Let's play dumb and not support that.
+        *
+        */
+       groupcount = aimbs_get16(bs);
+       for (i = 0; i < groupcount; i++) {
+               fu16_t group;
+
+               group = aimbs_get16(bs);
+
+               faimdprintf(sess, 0, "bifurcated migration unsupported -- group 0x%04x\n", group);
+       }
+
+       tl = aim_readtlvchain(bs);
+
+       if (aim_gettlv(tl, 0x0005, 1))
+               ip = aim_gettlv_str(tl, 0x0005, 1);
+
+       cktlv = aim_gettlv(tl, 0x0006, 1);
+
+       if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+               ret = userfunc(sess, rx, ip, cktlv ? cktlv->value : NULL);
+
+       aim_freetlvchain(&tl);
+       free(ip);
+
+       return ret;
+}
+
 static int motd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
 {
        aim_rxcallback_t userfunc;
@@ -857,10 +976,14 @@ static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx,
                return rateresp(sess, mod, rx, snac, bs);
        else if (snac->subtype == 0x000a)
                return ratechange(sess, mod, rx, snac, bs);
+       else if (snac->subtype == 0x000b)
+               return serverpause(sess, mod, rx, snac, bs);
        else if (snac->subtype == 0x000f)
                return selfinfo(sess, mod, rx, snac, bs);
        else if (snac->subtype == 0x0010)
                return evilnotify(sess, mod, rx, snac, bs);
+       else if (snac->subtype == 0x0012)
+               return migrate(sess, mod, rx, snac, bs);
        else if (snac->subtype == 0x0013)
                return motd(sess, mod, rx, snac, bs);
        else if (snac->subtype == 0x0018)
index be2a85e9a07c33ce89de7761c91de6029e1533e4..737bbbdfa2cb3b5473e07f85b2665aec4d64c869 100644 (file)
@@ -318,10 +318,8 @@ faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
         *   2 short -- Sequence number 
         *   4 short -- Number of data bytes that follow.
         */
-       faim_mutex_lock(&conn->active);
        if (aim_bstream_recv(&flaphdr, conn->fd, 6) < 6) {
                aim_conn_close(conn);
-               faim_mutex_unlock(&conn->active);
                return -1;
        }
 
@@ -334,15 +332,12 @@ faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
        if (aimbs_get8(&flaphdr) != 0x2a) {
                faimdprintf(sess, 0, "FLAP framing disrupted");
                aim_conn_close(conn);
-               faim_mutex_unlock(&conn->active);
                return -1;
        }       
 
        /* allocate a new struct */
-       if (!(newrx = (aim_frame_t *)malloc(sizeof(aim_frame_t)))) {
-               faim_mutex_unlock(&conn->active);
+       if (!(newrx = (aim_frame_t *)malloc(sizeof(aim_frame_t))))
                return -1;
-       }
        memset(newrx, 0, sizeof(aim_frame_t));
 
        /* we're doing FLAP if we're here */
@@ -359,7 +354,6 @@ faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
 
                if (!(payload = (fu8_t *) malloc(payloadlen))) {
                        aim_frame_destroy(newrx);
-                       faim_mutex_unlock(&conn->active);
                        return -1;
                }
 
@@ -370,13 +364,11 @@ faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
                        free(payload);
                        aim_frame_destroy(newrx);
                        aim_conn_close(conn);
-                       faim_mutex_unlock(&conn->active);
                        return -1;
                }
        } else
                aim_bstream_init(&newrx->data, NULL, 0);
 
-       faim_mutex_unlock(&conn->active);
 
        aim_bstream_rewind(&newrx->data);
 
index 4ab1bbbf0f88199ca0cb453096ac121e38d0cf1b..d6a2c8dce0efedd6dc17328f534514ea4587727b 100644 (file)
@@ -22,10 +22,8 @@ faim_internal void aim_initsnachash(aim_session_t *sess)
 {
        int i;
 
-       for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
+       for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
                sess->snac_hash[i] = NULL;
-               faim_mutex_init(&sess->snac_hash_locks[i]);
-       }
 
        return;
 }
@@ -68,10 +66,8 @@ faim_internal aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac)
 
        index = snac->id % FAIM_SNAC_HASH_SIZE;
 
-       faim_mutex_lock(&sess->snac_hash_locks[index]);
        snac->next = (aim_snac_t *)sess->snac_hash[index];
        sess->snac_hash[index] = (void *)snac;
-       faim_mutex_unlock(&sess->snac_hash_locks[index]);
 
        return snac->id;
 }
@@ -90,7 +86,6 @@ faim_internal aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id)
 
        index = id % FAIM_SNAC_HASH_SIZE;
 
-       faim_mutex_lock(&sess->snac_hash_locks[index]);
        for (prev = (aim_snac_t **)&sess->snac_hash[index]; (cur = *prev); ) {
                if (cur->id == id) {
                        *prev = cur->next;
@@ -98,7 +93,6 @@ faim_internal aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id)
                } else
                        prev = &cur->next;
        }
-       faim_mutex_unlock(&sess->snac_hash_locks[index]);
 
        return cur;
 }
@@ -118,11 +112,8 @@ faim_internal void aim_cleansnacs(aim_session_t *sess, int maxage)
                aim_snac_t *cur, **prev;
                time_t curtime;
 
-               faim_mutex_lock(&sess->snac_hash_locks[i]);
-               if (!sess->snac_hash[i]) {
-                       faim_mutex_unlock(&sess->snac_hash_locks[i]);
+               if (!sess->snac_hash[i])
                        continue;
-               }
 
                curtime = time(NULL); /* done here in case we waited for the lock */
 
@@ -138,7 +129,6 @@ faim_internal void aim_cleansnacs(aim_session_t *sess, int maxage)
                        } else
                                prev = &cur->next;
                }
-               faim_mutex_unlock(&sess->snac_hash_locks[i]);
        }
 
        return;
index 8e2d4e82bf1d36df289d6941fd37dd44495411cf..8b17863c7b1258b1d08d5e2b74407835cc0484d8 100644 (file)
@@ -202,9 +202,7 @@ faim_internal flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *conn)
 {
        flap_seqnum_t ret;
        
-       faim_mutex_lock(&conn->seqnum_lock);
        ret = ++conn->seqnum;
-       faim_mutex_unlock(&conn->seqnum_lock);
 
        return ret;
 }
index 041b08f8329bd412720377970e5cdb5cb35d0b73..f9ee277e1dfae5f0cf69c957d6ed6f514447e33b 100644 (file)
@@ -1623,6 +1623,46 @@ static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
        return 1;
 }
 
+static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...)
+{
+
+       aim_sendpauseack(sess, fr->conn);
+
+       return 1;
+}
+
+static int migrate(aim_session_t *sess, aim_frame_t *fr, ...)
+{
+       va_list ap;
+       aim_conn_t *bosconn;
+       char *bosip;
+       fu8_t *cookie;
+
+       va_start(ap, fr);
+       bosip = va_arg(ap, char *);
+       cookie = va_arg(ap, fu8_t *);
+       va_end(ap);
+
+       dvprintf("migration in progress -- new BOS is %s -- disconnecting\n", bosip);
+       aim_conn_kill(sess, &fr->conn);
+
+       if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
+               dprintf("migrate: could not connect to BOS: internal error\n");
+               return 1;
+       } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) { 
+               dprintf("migrate: could not connect to BOS\n");
+               aim_conn_kill(sess, &bosconn);
+               return 1;
+       }
+
+       /* Login will happen all over again. */
+       addcb_bos(sess, bosconn);
+
+       aim_auth_sendcookie(sess, bosconn, cookie);
+
+       return 1;
+}
+
 void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
 {
 
@@ -1657,6 +1697,8 @@ void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
        aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
        aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
        aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
+       aim_conn_addhandler(sess, bosconn, 0x0001, 0x000b, serverpause, 0);
+       aim_conn_addhandler(sess, bosconn, 0x0001, 0x0012, migrate, 0);
        
 #ifdef MID_REWROTE_ALL_THE_CRAP
        aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
index f7933a463836cff174d15d012a01a7b6e2c434a9..bb4e03af5d97965154ff6b2cbc3dcf829d40419e 100644 (file)
@@ -85,7 +85,7 @@ static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...)
        regstatus = va_arg(ap, int);
        email = va_arg(ap, char *);
        bosip = va_arg(ap, char *);
-       cookie = va_arg(ap, unsigned char *);
+       cookie = va_arg(ap, fu8_t *);
 
        latestrelease = va_arg(ap, char *);
        latestbuild = va_arg(ap, int);
This page took 0.131974 seconds and 5 git commands to generate.