Add IPv6 support from the IMAP account plug-in

This commit is contained in:
Pierre Pronchery 2015-03-14 14:16:41 +01:00
parent 6c8a534afa
commit d521872a5e

View File

@ -161,7 +161,7 @@ static int _pop3_refresh(POP3 * pop3, AccountFolder * folder,
static POP3Command * _pop3_command(POP3 * pop3, POP3Context context, static POP3Command * _pop3_command(POP3 * pop3, POP3Context context,
char const * command); char const * command);
static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port, static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port,
struct sockaddr_in * sa); struct addrinfo ** ai);
static int _pop3_parse(POP3 * pop3); static int _pop3_parse(POP3 * pop3);
/* events */ /* events */
@ -376,18 +376,19 @@ static POP3Command * _pop3_command(POP3 * pop3, POP3Context context,
/* pop3_lookup */ /* pop3_lookup */
static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port, static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port,
struct sockaddr_in * sa) struct addrinfo ** ai)
{ {
struct hostent * he; struct addrinfo hints;
int res;
if(hostname == NULL) if(hostname == NULL)
return -error_set_code(1, "%s", strerror(errno)); return -error_set_code(1, "%s", strerror(errno));
if((he = gethostbyname(hostname)) == NULL) memset(&hints, 0, sizeof(hints));
return -error_set_code(1, "%s", hstrerror(h_errno)); hints.ai_family = AF_UNSPEC;
memset(sa, 0, sizeof(*sa)); hints.ai_socktype = SOCK_STREAM;
sa->sin_family = AF_INET; hints.ai_protocol = IPPROTO_TCP;
sa->sin_port = htons(port); if((res = getaddrinfo(hostname, NULL, &hints, ai)) != 0)
sa->sin_addr.s_addr = *((uint32_t*)he->h_addr_list[0]); return -error_set_code(1, "%s", gai_strerror(res));
return 0; return 0;
} }
@ -661,7 +662,8 @@ static gboolean _on_connect(gpointer data)
char const * hostname; char const * hostname;
char const * p; char const * p;
uint16_t port; uint16_t port;
struct sockaddr_in sa; struct addrinfo * ai;
struct sockaddr_in * sa;
int res; int res;
char buf[128]; char buf[128];
@ -679,7 +681,7 @@ static gboolean _on_connect(gpointer data)
return FALSE; return FALSE;
port = (unsigned long)p; port = (unsigned long)p;
/* lookup the address */ /* lookup the address */
if(_pop3_lookup(pop3, hostname, port, &sa) != 0) if(_pop3_lookup(pop3, hostname, port, &ai) != 0)
{ {
helper->error(helper->account, error_get(), 1); helper->error(helper->account, error_get(), 1);
return FALSE; return FALSE;
@ -697,8 +699,14 @@ static gboolean _on_connect(gpointer data)
/* FIXME report properly as a warning instead */ /* FIXME report properly as a warning instead */
helper->error(NULL, strerror(errno), 1); helper->error(NULL, strerror(errno), 1);
/* report the current status */ /* report the current status */
snprintf(buf, sizeof(buf), "Connecting to %s (%s:%u)", hostname, if(ai->ai_family == AF_INET)
inet_ntoa(sa.sin_addr), port); {
sa = (struct sockaddr_in *)ai->ai_addr;
snprintf(buf, sizeof(buf), "Connecting to %s (%s:%u)", hostname,
inet_ntoa(sa->sin_addr), port);
}
else
snprintf(buf, sizeof(buf), "Connecting to %s", hostname);
_pop3_event_status(pop3, AS_CONNECTING, buf); _pop3_event_status(pop3, AS_CONNECTING, buf);
/* connect to the remote host */ /* connect to the remote host */
if((connect(pop3->fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 if((connect(pop3->fd, (struct sockaddr *)&sa, sizeof(sa)) != 0
@ -709,10 +717,12 @@ static gboolean _on_connect(gpointer data)
strerror(errno)); strerror(errno));
helper->error(helper->account, buf, 1); helper->error(helper->account, buf, 1);
_pop3_stop(pop3); _pop3_stop(pop3);
freeaddrinfo(ai);
return FALSE; return FALSE;
} }
pop3->wr_source = g_io_add_watch(pop3->channel, G_IO_OUT, pop3->wr_source = g_io_add_watch(pop3->channel, G_IO_OUT,
_on_watch_can_connect, pop3); _on_watch_can_connect, pop3);
freeaddrinfo(ai);
return FALSE; return FALSE;
} }
@ -761,7 +771,8 @@ static gboolean _on_watch_can_connect(GIOChannel * source,
socklen_t s = sizeof(res); socklen_t s = sizeof(res);
char const * hostname = pop3->config[P3CV_HOSTNAME].value; char const * hostname = pop3->config[P3CV_HOSTNAME].value;
uint16_t port = (unsigned long)pop3->config[P3CV_PORT].value; uint16_t port = (unsigned long)pop3->config[P3CV_PORT].value;
struct sockaddr_in sa; struct addrinfo * ai;
struct sockaddr_in * sa;
SSL_CTX * ssl_ctx; SSL_CTX * ssl_ctx;
char buf[128]; char buf[128];
@ -780,11 +791,19 @@ static gboolean _on_watch_can_connect(GIOChannel * source,
return FALSE; return FALSE;
} }
/* XXX remember the address instead */ /* XXX remember the address instead */
if(_pop3_lookup(pop3, hostname, port, &sa) == 0) if(_pop3_lookup(pop3, hostname, port, &ai) == 0)
{ {
snprintf(buf, sizeof(buf), "Connected to %s (%s:%u)", if(ai->ai_family == AF_INET)
hostname, inet_ntoa(sa.sin_addr), port); {
sa = (struct sockaddr_in *)ai->ai_addr;
snprintf(buf, sizeof(buf), "Connected to %s (%s:%u)",
hostname, inet_ntoa(sa->sin_addr),
port);
}
else
snprintf(buf, sizeof(buf), "Connected to %s", hostname);
_pop3_event_status(pop3, AS_CONNECTED, buf); _pop3_event_status(pop3, AS_CONNECTED, buf);
freeaddrinfo(ai);
} }
pop3->wr_source = 0; pop3->wr_source = 0;
/* setup SSL */ /* setup SSL */