support multi-homed servers
This commit is contained in:
parent
0b59ee0df3
commit
4a39cae8c4
|
@ -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
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…
Reference in New Issue
Block a user