Compare commits

..

No commits in common. "65cd4429bb04fafadaed702cff342b7a96678fd0" and "c9e57161cc6f605282b084d63cfd19531576de20" have entirely different histories.

9 changed files with 122 additions and 362 deletions

108
AUTHORS
View File

@ -1,101 +1,17 @@
Contact Oswald Buddenhagen <ossi@users.sf.net>
======= * Contributor, current maintainer
Theodore Ts'o <tytso@mit.edu>
* Contributor, Debian package co-maintainer
Nicolas Boullis <nboullis@debian.org>
* Debian package maintainer and minor upstream contributions
Michael Elkins <me@mutt.org>
* Original author
Send questions and bug reports to the isync-devel@lists.sourceforge.net Send questions and bug reports to the isync-devel@lists.sourceforge.net
mailing list. mailing list.
Do _NOT_ report bugs to Michael, not even in a CC: - he is not actively _DON'T_ report bugs to Michael, not even in a CC: - he is not actively
involved in isync development any more. involved in isync development any more.
Lead Developers
===============
Oswald Buddenhagen <ossi@users.sf.net>
- Current maintainer
Michael Elkins <me@mutt.org>
- Original author
Contributors
============
(Some of these people also contributed bugfixes and optimizations.)
(In chronological order.)
Jeremy Katz <katzj@linuxpower.org>
- UseNamespace & UseSSL* options
Daniel Resare <noa@metamatrix.se>
- Numerous SSL handling improvements
Eivind Eklund <eivind@FreeBSD.org>
- MaxMessages option
Theodore Ts'o <tytso@mit.edu>
- get-cert script
- Maildir UID mapping improvements
- Initial version of partial async IMAP support
Marc Hoersken <info@marc-hoersken.de>
- CopyArrivalDate option
Jack Stone <jwjstone@fastmail.fm>
Jan Synacek <jsynacek@redhat.com>
- SASL support
Jesse Weaver <pianohacker@gmail.com>
- IMAP stream compression support
Anton Khirnov <anton@khirnov.net>
- ClientKey & ClientCertificate options
Michael J Gruber <github@grubix.eu>
- Support for the $Forwarded/Passed flag
Patrick Steinhardt <ps@pks.im>
- UserCmd option
Oliver Runge <oliver.runge@gmail.com>
- UseKeychain option
Georgy Kibardin <georgy@kibardin.name>
- Support for UTF-7 IMAP mailbox names
Honorary Contributors
=====================
(These people contributed patches that were too small or obvious
to claim copyright, or were rewritten from scratch.)
(In alphabetical order.)
Alessandro Ghedini <ghedo@debian.org>
Andreas Grapentin <andreas@grapentin.org>
Aurélien Francillon <aurelien.francillon@eurecom.fr>
Ben Kibbey <bjk@luxsci.net>
Caspar Schutijser <caspar@schutijser.com>
Cedric Ware <cedric.ware__bml@normalesup.org>
Dmitrij D. Czarkoff <czarkoff@gmail.com>
Dmitry Torokhov <dtor@chromium.org>
Felipe Contreras <felipe.contreras@gmail.com>
Felix Janda <felix.janda@posteo.de>
Gergely Risko <gergely@risko.hu>
Sung Pae "guns" <self@sungpae.com>
Helmut Grohne <helmut@subdivi.de>
Hugo Haas <hugo@larve.net>
Jaroslav Suchanek <jaroslav.suchanek@gmail.com>
Jeremie Courreges-Anglas <jca@openbsd.org>
Klemens Nanni <kn@openbsd.org>
Lorenzo Martignoni <lorenzo.martignoni@technologist.com>
Magnus Jonsson <bigfoot@acc.umu.se>
Marcin Niestroj <macius1990w@gmail.com>
Martin Stenberg <martin@gnutiken.se>
Mike Delaney <mdelan@lusars.net>
Nicolas Boullis <nboullis@debian.org>
Nihal Jere <nihal@nihaljere.xyz>
Reimar Döffinger <Reimar.Doeffinger@gmx.de>
Remko Tronçon <remko@el-tramo.be>
sbfnk@users.sf.net
Thomas Roessler <roessler@does-not-exist.org>
Todd T. Fries <todd@fries.net>
Vincent Bernat <vincent@bernat.ch>
Yuri D'Elia <wavexx@thregr.org>

View File

@ -47,7 +47,7 @@ PACKAGE " " VERSION " - mailbox synchronizer\n"
" -c, --config CONFIG read an alternate config file (default: ~/." EXE "rc)\n" " -c, --config CONFIG read an alternate config file (default: ~/." EXE "rc)\n"
" -D, --debug debugging modes (see manual)\n" " -D, --debug debugging modes (see manual)\n"
" -y, --dry-run do not actually modify anything\n" " -y, --dry-run do not actually modify anything\n"
" -e, --ext-exit return extended exit code\n" " -e, --ext-exit return extended exit code\n"
" -V, --verbose display what is happening\n" " -V, --verbose display what is happening\n"
" -q, --quiet don't display progress counters\n" " -q, --quiet don't display progress counters\n"
" -v, --version display version\n" " -v, --version display version\n"
@ -89,26 +89,6 @@ PACKAGE " " VERSION " - mailbox synchronizer\n"
exit( code ); exit( code );
} }
static int child_pipe[2];
static notifier_t child_notifier;
static void
childHandler( int n ATTR_UNUSED )
{
// We can't just reap everything here, as we might steal children
// from popen(). Let the main loop handle it synchronously instead.
char dummy = 0;
write( child_pipe[1], &dummy, 1 );
}
static void
childReaper( int events ATTR_UNUSED, void *aux ATTR_UNUSED )
{
char dummy;
while (read( child_pipe[0], &dummy, 1 ) == 1) {}
while (waitpid( -1, NULL, WNOHANG ) > 0) {}
}
#ifdef __linux__ #ifdef __linux__
static void ATTR_NORETURN static void ATTR_NORETURN
crashHandler( int n ) crashHandler( int n )
@ -561,31 +541,9 @@ main( int argc, char **argv )
if (load_config( config )) if (load_config( config ))
return 1; return 1;
signal( SIGPIPE, SIG_IGN );
if (pipe( child_pipe )) {
perror( "pipe" );
return 1;
}
fcntl( child_pipe[0], F_SETFL, O_NONBLOCK );
fcntl( child_pipe[1], F_SETFL, O_NONBLOCK );
init_notifier( &child_notifier, child_pipe[0], childReaper, NULL );
conf_notifier( &child_notifier, 0, POLLIN );
struct sigaction sa = { 0 };
sa.sa_handler = childHandler;
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
sigaction( SIGCHLD, &sa, NULL );
if (mvars->list_stores) if (mvars->list_stores)
list_stores( mvars, argv + oind ); list_stores( mvars, argv + oind );
else else
sync_chans( mvars, argv + oind ); sync_chans( mvars, argv + oind );
return mvars->ret; return mvars->ret;
} }
void
cleanup_mainloop( void )
{
cleanup_drivers();
wipe_notifier( &child_notifier );
}

View File

@ -126,7 +126,7 @@ do_list_stores( list_vars_t *lvars )
next: next:
advance_store( lvars ); advance_store( lvars );
} }
cleanup_mainloop(); cleanup_drivers();
} }
static void static void

View File

@ -21,6 +21,5 @@ typedef struct {
void sync_chans( core_vars_t *cvars, char **argv ); void sync_chans( core_vars_t *cvars, char **argv );
void list_stores( core_vars_t *cvars, char **argv ); void list_stores( core_vars_t *cvars, char **argv );
void cleanup_mainloop( void );
#endif #endif

View File

@ -43,11 +43,9 @@ print_stats( void )
static void static void
stats_timeout( void *aux ATTR_UNUSED ) stats_timeout( void *aux ATTR_UNUSED )
{ {
if (stats_steps != -1) { stats_steps = -1;
stats_steps = -1;
print_stats();
}
conf_wakeup( &stats_wakeup, 200 ); conf_wakeup( &stats_wakeup, 200 );
print_stats();
} }
void void
@ -57,10 +55,8 @@ stats( void )
return; return;
// If the main loop appears to be running, skip the sync path. // If the main loop appears to be running, skip the sync path.
if (stats_steps < 0) { if (stats_steps < 0)
stats_steps = -2;
return; return;
}
// Rate-limit the (somewhat) expensive timer queries. // Rate-limit the (somewhat) expensive timer queries.
if (++stats_steps < 10) if (++stats_steps < 10)
@ -496,7 +492,7 @@ do_sync_chans( main_vars_t *mvars )
next: next:
advance_chan( mvars ); advance_chan( mvars );
} }
cleanup_mainloop(); cleanup_drivers();
if (!mvars->cvars->list && (DFlags & PROGRESS)) if (!mvars->cvars->list && (DFlags & PROGRESS))
wipe_wakeup( &stats_wakeup ); wipe_wakeup( &stats_wakeup );
} }
@ -672,7 +668,7 @@ static void
do_sync_boxes( main_vars_t *mvars ) do_sync_boxes( main_vars_t *mvars )
{ {
mvars->box_cben = 0; mvars->box_cben = 0;
while (mvars->state[F] == ST_OPEN && mvars->state[N] == ST_OPEN) { for (;;) {
if (mvars->chanptr->boxlist) { if (mvars->chanptr->boxlist) {
box_ent_t *mbox = mvars->boxptr; box_ent_t *mbox = mvars->boxptr;
if (!mbox) if (!mbox)
@ -734,10 +730,12 @@ done_sync( int sts, void *aux )
stats(); stats();
if (sts) { if (sts) {
mvars->cvars->ret = 1; mvars->cvars->ret = 1;
if (sts & SYNC_BAD(F)) if (sts & (SYNC_BAD(F) | SYNC_BAD(N))) {
mvars->state[F] = ST_CLOSED; if (sts & SYNC_BAD(F))
if (sts & SYNC_BAD(N)) mvars->state[F] = ST_CLOSED;
mvars->state[N] = ST_CLOSED; if (sts & SYNC_BAD(N))
mvars->state[N] = ST_CLOSED;
}
} }
mvars->box_done = 1; mvars->box_done = 1;
if (mvars->box_cben) if (mvars->box_cben)

View File

@ -36,7 +36,6 @@ Multiple replicas of each mailbox can be maintained.
Read configuration from \fIfile\fR. Read configuration from \fIfile\fR.
By default, the configuration is read from $XDG_CONFIG_HOME/isyncrc, and By default, the configuration is read from $XDG_CONFIG_HOME/isyncrc, and
if that does not exist, ~/.mbsyncrc is tried in turn. if that does not exist, ~/.mbsyncrc is tried in turn.
$XDG_CONFIG_HOME defaults to ~/.config if not set.
.TP .TP
\fB-a\fR, \fB--all\fR \fB-a\fR, \fB--all\fR
Select all configured Channels. Any Channel/Group specifications on the Select all configured Channels. Any Channel/Group specifications on the
@ -81,10 +80,8 @@ operations are determined, but no modifications are actually made
to either the mailboxes or the state files. to either the mailboxes or the state files.
.TP .TP
\fB-e\fR, \fB--ext-exit\fR \fB-e\fR, \fB--ext-exit\fR
Return an extended exit code: Add 32 or 64 to the code if any Return an extended exit code: Add 32 resp. 64 to the code if any
modifications were made on the far or near side, respectively; these modifications were made on the far resp. near side.
are not mutually exclusive, so the code may be 96 if changes were both
pushed and pulled.
An error may be reported at the same time, so the code may be for example An error may be reported at the same time, so the code may be for example
65 if some changes were successfully pulled, while others failed. 65 if some changes were successfully pulled, while others failed.
.TP .TP
@ -733,8 +730,7 @@ the appended string is made up according to the pattern
(see also \fBFieldDelimiter\fR below). (see also \fBFieldDelimiter\fR below).
.br .br
(Global default: \fI$XDG_STATE_HOME/isync/\fR, with a fallback to (Global default: \fI$XDG_STATE_HOME/isync/\fR, with a fallback to
\fI~/.mbsync/\fR if only that exists. \fI~/.mbsync/\fR if only that exists)
$XDG_STATE_HOME defaults to ~/.local/state if not set.)
. .
.SS Groups .SS Groups
.TP .TP
@ -860,11 +856,11 @@ There is no risk as long as the IMAP mailbox is accessed by only one client
. .
.SH FILES .SH FILES
.TP .TP
\fB$XDG_CONFIG_HOME/isyncrc\fR (usually \fB~/.config/isyncrc\fR) .B $XDG_CONFIG_HOME/isyncrc
Default configuration file. Default configuration file.
See also the example file in the documentation directory. See also the example file in the documentation directory.
.TP .TP
\fB$XDG_STATE_HOME/isync/\fR (usually \fB~/.local/state/isync/\fR) .B $XDG_STATE_HOME/isync/
Directory containing synchronization state files. Directory containing synchronization state files.
.TP .TP
.B ~/.mbsyncrc .B ~/.mbsyncrc

View File

@ -28,7 +28,6 @@
#endif #endif
enum { enum {
SCK_RESOLVING,
SCK_CONNECTING, SCK_CONNECTING,
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
SCK_STARTTLS, SCK_STARTTLS,
@ -416,7 +415,6 @@ static void socket_fd_cb( int, void * );
static void socket_fake_cb( void * ); static void socket_fake_cb( void * );
static void socket_timeout_cb( void * ); static void socket_timeout_cb( void * );
static void socket_resolve( conn_t * );
static void socket_connect_one( conn_t * ); static void socket_connect_one( conn_t * );
static void socket_connect_next( conn_t * ); static void socket_connect_next( conn_t * );
static void socket_connect_failed( conn_t * ); static void socket_connect_failed( conn_t * );
@ -424,21 +422,15 @@ static void socket_connected( conn_t * );
static void socket_connect_bail( conn_t * ); static void socket_connect_bail( conn_t * );
static void static void
socket_register_internal( conn_t *sock, int fd ) socket_open_internal( conn_t *sock, int fd )
{ {
sock->fd = fd; sock->fd = fd;
fcntl( fd, F_SETFL, O_NONBLOCK );
init_notifier( &sock->notify, fd, socket_fd_cb, sock ); init_notifier( &sock->notify, fd, socket_fd_cb, sock );
init_wakeup( &sock->fd_fake, socket_fake_cb, sock ); init_wakeup( &sock->fd_fake, socket_fake_cb, sock );
init_wakeup( &sock->fd_timeout, socket_timeout_cb, sock ); init_wakeup( &sock->fd_timeout, socket_timeout_cb, sock );
} }
static void
socket_open_internal( conn_t *sock, int fd )
{
fcntl( fd, F_SETFL, O_NONBLOCK );
socket_register_internal( sock, fd );
}
static void static void
socket_close_internal( conn_t *sock ) socket_close_internal( conn_t *sock )
{ {
@ -449,6 +441,32 @@ socket_close_internal( conn_t *sock )
sock->fd = -1; sock->fd = -1;
} }
#ifndef HAVE_IPV6
struct addr_info {
struct addr_info *ai_next;
struct sockaddr_in ai_addr[1];
};
#define freeaddrinfo(ai) free( ai )
static struct addr_info *
init_addrinfo( struct hostent *he )
{
uint naddr = 0;
for (char **addr = he->h_addr_list; *addr; addr++)
naddr++;
struct addr_info *caddr = nfzalloc( naddr * sizeof(struct addrinfo) );
struct addr_info *ret, **caddrp = &ret;
for (char **addr = he->h_addr_list; *addr; addr++, caddr++) {
caddr->ai_addr->sin_family = AF_INET;
memcpy( &caddr->ai_addr->sin_addr.s_addr, *addr, sizeof(struct in_addr) );
*caddrp = caddr;
caddrp = &caddr->ai_next;
}
return ret;
}
#endif
void void
socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) ) socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
{ {
@ -483,202 +501,77 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
info( "\vok\n" ); info( "\vok\n" );
socket_connected( sock ); socket_connected( sock );
} else { } else {
socket_resolve( sock );
}
}
static void
pipe_write( int fd, void *buf, int len )
{
do {
int wrote = write( fd, buf, len );
if (wrote < 0) {
perror( "write" );
_exit( 1 );
}
buf = ((char *)buf) + wrote;
len -= wrote;
} while (len);
}
static void
socket_resolve( conn_t *sock )
{
info( "Resolving %s...\n", sock->conf->host );
int pfd[2];
if (pipe( pfd )) {
perror( "pipe" );
exit( 1 );
}
switch (fork()) {
case -1:
perror( "fork" );
exit( 1 );
case 0:
break;
default:
close( pfd[1] );
socket_register_internal( sock, pfd[0] );
sock->state = SCK_RESOLVING;
conf_notifier( &sock->notify, 0, POLLIN );
socket_expect_activity( sock, 1 );
return;
}
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct addrinfo *res, hints = { 0 }; int gaierr;
hints.ai_family = AF_UNSPEC; struct addrinfo hints;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG; memset( &hints, 0, sizeof(hints) );
int gaierr = getaddrinfo( sock->conf->host, NULL, &hints, &res ); hints.ai_family = AF_UNSPEC;
pipe_write( pfd[1], &gaierr, sizeof(gaierr) ); hints.ai_socktype = SOCK_STREAM;
if (gaierr) hints.ai_flags = AI_ADDRCONFIG;
_exit( 1 ); infon( "Resolving %s... ", conf->host );
static_assert( sizeof(((struct addrinfo){ 0 }).ai_family) == sizeof(int), "unexpected size of ai_family" ); if ((gaierr = getaddrinfo( conf->host, NULL, &hints, &sock->addrs ))) {
static_assert( sizeof(struct in_addr) % sizeof(int) == 0, "unexpected size of struct in_addr" ); error( "Error: Cannot resolve server '%s': %s\n", conf->host, gai_strerror( gaierr ) );
static_assert( sizeof(struct in6_addr) % sizeof(int) == 0, "unexpected size of struct in6_addr" ); socket_connect_bail( sock );
int nbytes = 0; return;
for (struct addrinfo *cres = res; cres; cres = cres->ai_next) {
if (cres->ai_family == AF_INET) {
nbytes += sizeof(int) + sizeof(struct in_addr);
} else {
assert( cres->ai_family == AF_INET6 );
nbytes += sizeof(int) + sizeof(struct in6_addr);
} }
} info( "\vok\n" );
pipe_write( pfd[1], &nbytes, sizeof(nbytes) );
for (struct addrinfo *cres = res; cres; cres = cres->ai_next) {
pipe_write( pfd[1], &cres->ai_family, sizeof(int) );
if (cres->ai_family == AF_INET)
pipe_write( pfd[1], &((struct sockaddr_in *)cres->ai_addr)->sin_addr, sizeof(struct in_addr) );
else
pipe_write( pfd[1], &((struct sockaddr_in6 *)cres->ai_addr)->sin6_addr, sizeof(struct in6_addr) );
}
#else #else
struct hostent *he = gethostbyname( sock->conf->host ); struct hostent *he;
int herrno = he ? 0 : h_errno;
pipe_write( pfd[1], &herrno, sizeof(herrno) );
if (!he)
_exit( 1 );
static_assert( sizeof(struct in_addr) % sizeof(int) == 0, "unexpected size of struct in_addr" );
int nbytes = 0;
for (char **addr = he->h_addr_list; *addr; addr++)
nbytes += sizeof(struct in_addr);
pipe_write( pfd[1], &nbytes, sizeof(nbytes) );
for (char **addr = he->h_addr_list; *addr; addr++)
pipe_write( pfd[1], *addr, sizeof(struct in_addr) );
#endif
_exit( 0 );
}
static void infon( "Resolving %s... ", conf->host );
pipe_read( int fd, void *buf, int len ) he = gethostbyname( conf->host );
{ if (!he) {
do { error( "Error: Cannot resolve server '%s': %s\n", conf->host, hstrerror( h_errno ) );
int didrd = read( fd, buf, len ); socket_connect_bail( sock );
if (didrd < 0) { return;
sys_error( "read" );
exit( 1 );
} }
if (!didrd) { info( "\vok\n" );
error( "read: unexpected EOF\n" );
exit( 1 );
}
buf = ((char *)buf) + didrd;
len -= didrd;
} while (len);
}
static void sock->addrs = init_addrinfo( he );
socket_resolve_finalize( conn_t *sock )
{
int errcode;
pipe_read( sock->fd, &errcode, sizeof(errcode) );
if (errcode) {
#ifdef HAVE_IPV6
const char *err = gai_strerror( errcode );
#else
const char *err = hstrerror( errcode );
#endif #endif
error( "Error: Cannot resolve server '%s': %s\n", sock->conf->host, err ); sock->curr_addr = sock->addrs;
socket_close_internal( sock ); socket_connect_one( sock );
socket_connect_bail( sock );
return;
} }
int nbytes;
pipe_read( sock->fd, &nbytes, sizeof(nbytes) );
char *addrs = nfmalloc( nbytes );
pipe_read( sock->fd, addrs, nbytes );
sock->curr_addr = sock->addrs = addrs;
sock->addrs_end = addrs + nbytes;
socket_close_internal( sock ); // Get rid of the pipe
socket_connect_one( sock );
}
static void
socket_resolve_timeout( conn_t *sock )
{
error( "Error: Cannot resolve server '%s': timeout.\n", sock->conf->host );
socket_close_internal( sock );
socket_connect_bail( sock );
} }
static void static void
socket_connect_one( conn_t *sock ) socket_connect_one( conn_t *sock )
{ {
char *ai = sock->curr_addr; int s;
if (ai == sock->addrs_end) { #ifdef HAVE_IPV6
struct addrinfo *ai;
#else
struct addr_info *ai;
#endif
if (!(ai = sock->curr_addr)) {
error( "No working address found for %s\n", sock->conf->host ); error( "No working address found for %s\n", sock->conf->host );
socket_connect_bail( sock ); socket_connect_bail( sock );
return; return;
} }
union {
struct sockaddr any;
struct sockaddr_in ip4;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct sockaddr_in6 ip6; if (ai->ai_family == AF_INET6) {
#endif struct sockaddr_in6 *in6 = ((struct sockaddr_in6 *)ai->ai_addr);
} addr;
#ifdef HAVE_IPV6
int fam = *(int *)ai;
ai += sizeof(int);
int addr_len;
if (fam == AF_INET6) {
addr_len = sizeof(addr.ip6);
addr.ip6.sin6_addr = *(struct in6_addr *)ai;
addr.ip6.sin6_flowinfo = 0;
addr.ip6.sin6_scope_id = 0;
ai += sizeof(struct in6_addr);
} else {
addr_len = sizeof(addr.ip4);
#else
const int fam = AF_INET;
const int addr_len = sizeof(addr.ip4);
{
#endif
addr.ip4.sin_addr = *(struct in_addr *)ai;
ai += sizeof(struct in_addr);
}
sock->curr_addr = ai;
#ifdef HAVE_IPV6
if (fam == AF_INET6) {
char sockname[64]; char sockname[64];
inet_ntop( fam, &addr.ip6.sin6_addr, sockname, sizeof(sockname) ); in6->sin6_port = htons( sock->conf->port );
nfasprintf( &sock->name, "%s ([%s]:%hu)", nfasprintf( &sock->name, "%s ([%s]:%hu)",
sock->conf->host, sockname, sock->conf->port ); sock->conf->host, inet_ntop( AF_INET6, &in6->sin6_addr, sockname, sizeof(sockname) ), sock->conf->port );
} else } else
#endif #endif
{ {
struct sockaddr_in *in = ((struct sockaddr_in *)ai->ai_addr);
in->sin_port = htons( sock->conf->port );
nfasprintf( &sock->name, "%s (%s:%hu)", nfasprintf( &sock->name, "%s (%s:%hu)",
sock->conf->host, inet_ntoa( addr.ip4.sin_addr ), sock->conf->port ); sock->conf->host, inet_ntoa( in->sin_addr ), sock->conf->port );
} }
int s = socket( fam, SOCK_STREAM, 0 ); #ifdef HAVE_IPV6
s = socket( ai->ai_family, SOCK_STREAM, 0 );
#else
s = socket( PF_INET, SOCK_STREAM, 0 );
#endif
if (s < 0) { if (s < 0) {
socket_connect_next( sock ); socket_connect_next( sock );
return; return;
@ -686,9 +579,11 @@ socket_connect_one( conn_t *sock )
socket_open_internal( sock, s ); socket_open_internal( sock, s );
infon( "Connecting to %s... ", sock->name ); infon( "Connecting to %s... ", sock->name );
addr.any.sa_family = fam; #ifdef HAVE_IPV6
addr.ip4.sin_port = htons( sock->conf->port ); // Aliased for ip6 if (connect( s, ai->ai_addr, ai->ai_addrlen )) {
if (connect( s, &addr.any, addr_len )) { #else
if (connect( s, ai->ai_addr, sizeof(*ai->ai_addr) )) {
#endif
if (errno != EINPROGRESS) { if (errno != EINPROGRESS) {
socket_connect_failed( sock ); socket_connect_failed( sock );
return; return;
@ -709,6 +604,7 @@ socket_connect_next( conn_t *conn )
sys_error( "Cannot connect to %s", conn->name ); sys_error( "Cannot connect to %s", conn->name );
free( conn->name ); free( conn->name );
conn->name = NULL; conn->name = NULL;
conn->curr_addr = conn->curr_addr->ai_next;
socket_connect_one( conn ); socket_connect_one( conn );
} }
@ -722,8 +618,10 @@ socket_connect_failed( conn_t *conn )
static void static void
socket_connected( conn_t *conn ) socket_connected( conn_t *conn )
{ {
free( conn->addrs ); if (conn->addrs) {
conn->addrs = NULL; freeaddrinfo( conn->addrs );
conn->addrs = NULL;
}
conf_notifier( &conn->notify, 0, POLLIN ); conf_notifier( &conn->notify, 0, POLLIN );
socket_expect_activity( conn, 0 ); socket_expect_activity( conn, 0 );
conn->state = SCK_READY; conn->state = SCK_READY;
@ -733,8 +631,10 @@ socket_connected( conn_t *conn )
static void static void
socket_cleanup_names( conn_t *conn ) socket_cleanup_names( conn_t *conn )
{ {
free( conn->addrs ); if (conn->addrs) {
conn->addrs = NULL; freeaddrinfo( conn->addrs );
conn->addrs = NULL;
}
free( conn->name ); free( conn->name );
conn->name = NULL; conn->name = NULL;
} }
@ -1206,11 +1106,6 @@ socket_fd_cb( int events, void *aux )
{ {
conn_t *conn = (conn_t *)aux; conn_t *conn = (conn_t *)aux;
if (conn->state == SCK_RESOLVING) {
socket_resolve_finalize( conn );
return;
}
if ((events & POLLERR) || conn->state == SCK_CONNECTING) { if ((events & POLLERR) || conn->state == SCK_CONNECTING) {
int soerr; int soerr;
socklen_t selen = sizeof(soerr); socklen_t selen = sizeof(soerr);
@ -1273,9 +1168,7 @@ socket_timeout_cb( void *aux )
{ {
conn_t *conn = (conn_t *)aux; conn_t *conn = (conn_t *)aux;
if (conn->state == SCK_RESOLVING) { if (conn->state == SCK_CONNECTING) {
socket_resolve_timeout( conn );
} else if (conn->state == SCK_CONNECTING) {
errno = ETIMEDOUT; errno = ETIMEDOUT;
socket_connect_failed( conn ); socket_connect_failed( conn );
} else { } else {

View File

@ -57,7 +57,11 @@ 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 *addrs, *addrs_end, *curr_addr; // needed during connect; assumed to be int-aligned #ifdef HAVE_IPV6
struct addrinfo *addrs, *curr_addr; /* needed during connect */
#else
struct addr_info *addrs, *curr_addr; /* needed during connect */
#endif
char *name; char *name;
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
SSL *ssl; SSL *ssl;

View File

@ -1110,8 +1110,6 @@ event_wait( void )
case 0: case 0:
return; return;
case -1: case -1:
if (errno == EINTR)
return;
perror( "poll() failed in event loop" ); perror( "poll() failed in event loop" );
abort(); abort();
default: default:
@ -1164,8 +1162,6 @@ event_wait( void )
case 0: case 0:
return; return;
case -1: case -1:
if (errno == EINTR)
return;
perror( "select() failed in event loop" ); perror( "select() failed in event loop" );
abort(); abort();
default: default: