Browse Source

support multi-homed servers

wip/maildir-uid-dupes-test
Oswald Buddenhagen 11 years ago
parent
commit
4a39cae8c4
  1. 1
      src/isync.h
  2. 91
      src/socket.c

1
src/isync.h

@ -85,6 +85,7 @@ typedef struct {
int fd; int fd;
int state; int state;
const server_conf_t *conf; /* needed during connect */ const server_conf_t *conf; /* needed during connect */
char **curr_addr; /* needed during connect */
char *name; char *name;
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
SSL *ssl; SSL *ssl;

91
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_fd_cb( int, void * );
static void socket_connect_one( conn_t * );
static void socket_connect_failed( conn_t * ); static void socket_connect_failed( conn_t * );
static void socket_connected( conn_t * ); static void socket_connected( conn_t * );
static void socket_connect_bail( 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 ) ) socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
{ {
const server_conf_t *conf = sock->conf; const server_conf_t *conf = sock->conf;
struct hostent *he;
struct sockaddr_in addr;
int s, a[2];
sock->callbacks.connect = cb; sock->callbacks.connect = cb;
/* open connection to IMAP server */ /* open connection to IMAP server */
if (conf->tunnel) { if (conf->tunnel) {
int a[2];
nfasprintf( &sock->name, "tunnel '%s'", conf->tunnel ); nfasprintf( &sock->name, "tunnel '%s'", conf->tunnel );
infon( "Starting %s... ", sock->name ); 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 ); fcntl( a[1], F_SETFL, O_NONBLOCK );
add_fd( a[1], socket_fd_cb, sock ); add_fd( a[1], socket_fd_cb, sock );
info( "\vok\n" );
socket_connected( sock );
} else { } else {
memset( &addr, 0, sizeof(addr) ); struct hostent *he;
addr.sin_port = conf->port ? htons( conf->port ) :
#ifdef HAVE_LIBSSL
conf->use_imaps ? htons( 993 ) :
#endif
htons( 143 );
addr.sin_family = AF_INET;
infon( "Resolving %s... ", conf->host ); infon( "Resolving %s... ", conf->host );
he = gethostbyname( conf->host ); he = gethostbyname( conf->host );
@ -361,35 +357,63 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
} }
info( "\vok\n" ); 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 ); static void
if (s < 0) { socket_connect_one( conn_t *sock )
perror( "socket" ); {
exit( 1 ); int s;
} ushort port;
sock->fd = s; struct {
fcntl( s, F_SETFL, O_NONBLOCK ); struct sockaddr_in ai_addr[1];
add_fd( s, socket_fd_cb, sock ); } 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)", nfasprintf( &sock->name, "%s (%s:%hu)",
conf->host, inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) ); sock->conf->host, inet_ntoa( in->sin_addr ), port );
infon( "Connecting to %s... ", sock->name ); }
if (connect( s, (struct sockaddr *)&addr, sizeof(addr) )) {
if (errno != EINPROGRESS) { s = socket( PF_INET, SOCK_STREAM, 0 );
socket_connect_failed( sock ); if (s < 0) {
return; perror( "socket" );
} exit( 1 );
conf_fd( s, 0, POLLOUT ); }
sock->state = SCK_CONNECTING; sock->fd = s;
info( "\v\n" ); 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; return;
} }
conf_fd( s, 0, POLLOUT );
sock->state = SCK_CONNECTING;
info( "\v\n" );
return;
} }
info( "\vok\n" ); info( "\vok\n" );
socket_connected( sock ); socket_connected( sock );
return;
} }
static void static void
@ -397,7 +421,10 @@ socket_connect_failed( conn_t *conn )
{ {
sys_error( "Cannot connect to %s", conn->name ); sys_error( "Cannot connect to %s", conn->name );
socket_close_internal( conn ); socket_close_internal( conn );
socket_connect_bail( conn ); free( conn->name );
conn->name = 0;
conn->curr_addr++;
socket_connect_one( conn );
} }
static void static void

Loading…
Cancel
Save