commit 931e348b78995f3b190209e167b4a96e13100c2e
Author: Oswald Buddenhagen <[email protected]>
Date:   Sun Sep 1 16:32:45 2013 +0200

    support multi-homed servers

 src/isync.h  |    1 +
 src/socket.c |   91 ++++++++++++++++++++++++++++++++-----------------
 2 files changed, 60 insertions(+), 32 deletions(-)

diff --git a/src/isync.h b/src/isync.h
index 5176313..c006d71 100644
--- a/src/isync.h
+++ b/src/isync.h
@@ -85,6 +85,7 @@ typedef struct {
        int fd;
        int state;
        const server_conf_t *conf; /* needed during connect */
+       char **curr_addr; /* needed during connect */
        char *name;
 #ifdef HAVE_LIBSSL
        SSL *ssl;
diff --git a/src/socket.c b/src/socket.c
index ce4e820..a04c686 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -296,6 +296,7 @@ static void start_tls_p3( conn_t *conn, int ok )
 
 static void socket_fd_cb( int, void * );
 
+static void socket_connect_one( conn_t * );
 static void socket_connect_failed( conn_t * );
 static void socket_connected( conn_t * );
 static void socket_connect_bail( conn_t * );
@@ -312,14 +313,13 @@ void
 socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
 {
        const server_conf_t *conf = sock->conf;
-       struct hostent *he;
-       struct sockaddr_in addr;
-       int s, a[2];
 
        sock->callbacks.connect = cb;
 
        /* open connection to IMAP server */
        if (conf->tunnel) {
+               int a[2];
+
                nfasprintf( &sock->name, "tunnel '%s'", conf->tunnel );
                infon( "Starting %s... ", sock->name );
 
@@ -343,14 +343,10 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void 
*aux ) )
                fcntl( a[1], F_SETFL, O_NONBLOCK );
                add_fd( a[1], socket_fd_cb, sock );
 
+               info( "\vok\n" );
+               socket_connected( sock );
        } else {
-               memset( &addr, 0, sizeof(addr) );
-               addr.sin_port = conf->port ? htons( conf->port ) :
-#ifdef HAVE_LIBSSL
-                               conf->use_imaps ? htons( 993 ) :
-#endif
-                               htons( 143 );
-               addr.sin_family = AF_INET;
+               struct hostent *he;
 
                infon( "Resolving %s... ", conf->host );
                he = gethostbyname( conf->host );
@@ -361,35 +357,63 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void 
*aux ) )
                }
                info( "\vok\n" );
 
-               addr.sin_addr.s_addr = *((int *)he->h_addr_list[0]);
+               sock->curr_addr = he->h_addr_list;
+               socket_connect_one( sock );
+       }
+}
 
-               s = socket( PF_INET, SOCK_STREAM, 0 );
-               if (s < 0) {
-                       perror( "socket" );
-                       exit( 1 );
-               }
-               sock->fd = s;
-               fcntl( s, F_SETFL, O_NONBLOCK );
-               add_fd( s, socket_fd_cb, sock );
+static void
+socket_connect_one( conn_t *sock )
+{
+       int s;
+       ushort port;
+       struct {
+               struct sockaddr_in ai_addr[1];
+       } ai[1];
+
+       if (!*sock->curr_addr) {
+               error( "No working address found for %s\n", sock->conf->host );
+               socket_connect_bail( sock );
+               return;
+       }
 
+       port = sock->conf->port ? sock->conf->port :
+#ifdef HAVE_LIBSSL
+              sock->conf->use_imaps ? 993 :
+#endif
+              143;
+       {
+               struct sockaddr_in *in = ((struct sockaddr_in *)ai->ai_addr);
+               memset( in, 0, sizeof(*in) );
+               in->sin_family = AF_INET;
+               in->sin_addr.s_addr = *((int *)*sock->curr_addr);
+               in->sin_port = htons( port );
                nfasprintf( &sock->name, "%s (%s:%hu)",
-                           conf->host, inet_ntoa( addr.sin_addr ), ntohs( 
addr.sin_port ) );
-               infon( "Connecting to %s... ", sock->name );
-               if (connect( s, (struct sockaddr *)&addr, sizeof(addr) )) {
-                       if (errno != EINPROGRESS) {
-                               socket_connect_failed( sock );
-                               return;
-                       }
-                       conf_fd( s, 0, POLLOUT );
-                       sock->state = SCK_CONNECTING;
-                       info( "\v\n" );
+                           sock->conf->host, inet_ntoa( in->sin_addr ), port );
+       }
+
+       s = socket( PF_INET, SOCK_STREAM, 0 );
+       if (s < 0) {
+               perror( "socket" );
+               exit( 1 );
+       }
+       sock->fd = s;
+       fcntl( s, F_SETFL, O_NONBLOCK );
+       add_fd( s, socket_fd_cb, sock );
+
+       infon( "Connecting to %s... ", sock->name );
+       if (connect( s, ai->ai_addr, sizeof(*ai->ai_addr) )) {
+               if (errno != EINPROGRESS) {
+                       socket_connect_failed( sock );
                        return;
                }
-
+               conf_fd( s, 0, POLLOUT );
+               sock->state = SCK_CONNECTING;
+               info( "\v\n" );
+               return;
        }
        info( "\vok\n" );
        socket_connected( sock );
-       return;
 }
 
 static void
@@ -397,7 +421,10 @@ socket_connect_failed( conn_t *conn )
 {
        sys_error( "Cannot connect to %s", conn->name );
        socket_close_internal( conn );
-       socket_connect_bail( conn );
+       free( conn->name );
+       conn->name = 0;
+       conn->curr_addr++;
+       socket_connect_one( conn );
 }
 
 static void

------------------------------------------------------------------------------
Learn the latest--Visual Studio 2012, SharePoint 2013, SQL 2012, more!
Discover the easy way to master current and previous Microsoft technologies
and advance your career. Get an incredible 1,500+ hours of step-by-step
tutorial videos with LearnDevNow. Subscribe today and save!
http://pubads.g.doubleclick.net/gampad/clk?id=58040911&iu=/4140/ostg.clktrk
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to