|
|
@ -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 |
|
|
|