Mercurial > pidgin.yaz
changeset 4678:9ce3c698ff5e
[gaim-migrate @ 4989]
Now we try all the results that getaddrinfo gives us, instead of just the
first one. This should fix the issues people have been having connecting
to certain jabber servers (like amessage.de) that have an IPv6 record as
well as an IPv4 record. It's also more correct and stuff.
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Sat, 08 Mar 2003 17:54:36 +0000 |
parents | 24657a33e9e5 |
children | 5b372a95b9a8 |
files | src/proxy.c |
diffstat | 1 files changed, 72 insertions(+), 66 deletions(-) [+] |
line wrap: on
line diff
--- a/src/proxy.c Sat Mar 08 17:46:17 2003 +0000 +++ b/src/proxy.c Sat Mar 08 17:54:36 2003 +0000 @@ -129,8 +129,8 @@ } -typedef void (*dns_callback_t)(struct sockaddr *addr, size_t addrlen, - gpointer data, const char *error_message); +typedef void (*dns_callback_t)(GSList *hosts, gpointer data, + const char *error_message); #ifdef __unix__ @@ -248,6 +248,7 @@ { pending_dns_request_t *req = (pending_dns_request_t*)data; int rc, err; + GSList *hosts = NULL; struct sockaddr *addr = NULL; socklen_t addrlen; @@ -265,42 +266,50 @@ #endif req->dns_pid); debug_printf("%s\n",message); - req->callback(NULL, 0, req->data, message); - release_dns_child(req); + req->callback(NULL, req->data, message); + release_dns_child(req); return; } if(rc>0) { - rc=read(req->fd_out, &addrlen, sizeof(addrlen)); - if(rc>0) { - addr=g_malloc(addrlen); - rc=read(req->fd_out, addr, addrlen); + while(rc > 0) { + rc=read(req->fd_out, &addrlen, sizeof(addrlen)); + if(rc>0 && addrlen > 0) { + addr=g_malloc(addrlen); + rc=read(req->fd_out, addr, addrlen); + hosts = g_slist_append(hosts, GINT_TO_POINTER(addrlen)); + hosts = g_slist_append(hosts, addr); + } else { + break; + } } - } - if(rc==-1) { + } else if(rc==-1) { char message[1024]; g_snprintf(message, sizeof(message), "Error reading from DNS child: %s",strerror(errno)); debug_printf("%s\n",message); - req->callback(NULL, 0, req->data, message); + req->callback(NULL, req->data, message); req_free(req); return; - } - if(rc==0) { + } else if(rc==0) { char message[1024]; g_snprintf(message, sizeof(message), "EOF reading from DNS child"); close(req->fd_out); debug_printf("%s\n",message); - req->callback(NULL, 0, req->data, message); + req->callback(NULL, req->data, message); req_free(req); return; } /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */ - req->callback(addr, addrlen, req->data, NULL); - - g_free(addr); + req->callback(hosts, req->data, NULL); - release_dns_child(req); + while(hosts) { + hosts = g_slist_remove(hosts, hosts->data); + g_free(hosts->data); + hosts = g_slist_remove(hosts, hosts->data); + } + + release_dns_child(req); } static void trap_gdb_bug() @@ -397,7 +406,7 @@ int rc; #ifdef HAVE_GETADDRINFO - struct addrinfo hints, *res; + struct addrinfo hints, *res, *tmp; char servname[20]; #else struct sockaddr_in sin; @@ -468,9 +477,14 @@ continue; } write(child_out[1], &zero, sizeof(zero)); - write(child_out[1], &(res->ai_addrlen), sizeof(res->ai_addrlen)); - write(child_out[1], res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); + while(res) { + write(child_out[1], &(res->ai_addrlen), sizeof(res->ai_addrlen)); + write(child_out[1], res->ai_addr, res->ai_addrlen); + tmp = res; + res = res->ai_next; + freeaddrinfo(tmp); + } + write(child_out[1], &zero, sizeof(zero)); #else if (!inet_aton(hostname, &sin.sin_addr)) { struct hostent *hp; @@ -490,6 +504,7 @@ write(child_out[1], &zero, sizeof(zero)); write(child_out[1], &addrlen, sizeof(addrlen)); write(child_out[1], &sin, addrlen); + write(child_out[1], &zero, sizeof(zero)); #endif dns_params.hostname[0] = '\0'; } @@ -529,7 +544,11 @@ static gboolean host_resolved(gpointer data) { pending_dns_request_t *req = (pending_dns_request_t*)data; - req->callback(req->addr, req->addrlen, req->data, NULL); + GSList *hosts = NULL; + hosts = g_slist_append(hosts, GINT_TO_POINTER(req->addrlen)); + hosts = g_slist_append(hosts, req->addr); + req->callback(hosts, req->data, NULL); + g_slist_free(hosts); g_free(req->addr); g_free(req); return FALSE; @@ -614,8 +633,6 @@ if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { debug_printf("unable to create socket: %s\n", strerror(errno)); - g_free(phb->host); - g_free(phb); return -1; } fcntl(fd, F_SETFL, O_NONBLOCK); @@ -627,8 +644,6 @@ } else { debug_printf("connect failed (errno %d)\n", errno); close(fd); - g_free(phb->host); - g_free(phb); return -1; } } else { @@ -639,8 +654,6 @@ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { debug_printf("getsockopt failed\n"); close(fd); - g_free(phb->host); - g_free(phb); return -1; } fcntl(fd, F_SETFL, 0); @@ -761,8 +774,6 @@ debug_printf("connecting to %s:%d via %s:%d using HTTP\n", phb->host, phb->port, phb->gpi->proxyhost, phb->gpi->proxyport); if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { - g_free(phb->host); - g_free(phb); return -1; } @@ -774,8 +785,6 @@ phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, http_canwrite, phb); } else { close(fd); - g_free(phb->host); - g_free(phb); return -1; } } else { @@ -786,8 +795,6 @@ len = sizeof(error); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(fd); - g_free(phb->host); - g_free(phb); return -1; } fcntl(fd, F_SETFL, 0); @@ -877,8 +884,6 @@ debug_printf("connecting to %s:%d via %s:%d using SOCKS4\n", phb->host, phb->port, phb->gpi->proxyhost, phb->gpi->proxyport); if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { - g_free(phb->host); - g_free(phb); return -1; } @@ -889,8 +894,6 @@ phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb); } else { close(fd); - g_free(phb->host); - g_free(phb); return -1; } } else { @@ -901,8 +904,6 @@ len = sizeof(error); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(fd); - g_free(phb->host); - g_free(phb); return -1; } fcntl(fd, F_SETFL, 0); @@ -1095,8 +1096,6 @@ debug_printf("connecting to %s:%d via %s:%d using SOCKS5\n", phb->host, phb->port, phb->gpi->proxyhost, phb->gpi->proxyport); if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { - g_free(phb->host); - g_free(phb); return -1; } @@ -1107,8 +1106,6 @@ phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb); } else { close(fd); - g_free(phb->host); - g_free(phb); return -1; } } else { @@ -1119,8 +1116,6 @@ len = sizeof(error); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(fd); - g_free(phb->host); - g_free(phb); return -1; } fcntl(fd, F_SETFL, 0); @@ -1130,30 +1125,41 @@ return fd; } -static void connection_host_resolved(struct sockaddr *addr, size_t addrlen, gpointer data, const char *error_message) +static void connection_host_resolved(GSList *hosts, gpointer data, const char *error_message) { struct PHB *phb = (struct PHB*)data; + size_t addrlen; + struct sockaddr *addr; + int ret = -1; - if(!addr) - { - phb->func(phb->data, -1, GAIM_INPUT_READ); - return; - } + while(hosts) { + addrlen = GPOINTER_TO_INT(hosts->data); + hosts = hosts->next; + addr = hosts->data; + hosts = hosts->next; - switch(phb->gpi->proxytype) - { - case PROXY_NONE: - proxy_connect_none(phb, addr, addrlen); + switch(phb->gpi->proxytype) + { + case PROXY_NONE: + ret = proxy_connect_none(phb, addr, addrlen); + break; + case PROXY_HTTP: + ret = proxy_connect_http(phb, addr, addrlen); + break; + case PROXY_SOCKS4: + ret = proxy_connect_socks4(phb, addr, addrlen); + break; + case PROXY_SOCKS5: + ret = proxy_connect_socks5(phb, addr, addrlen); + break; + } + if (ret > 0) break; - case PROXY_HTTP: - proxy_connect_http(phb, addr, addrlen); - break; - case PROXY_SOCKS4: - proxy_connect_socks4(phb, addr, addrlen); - break; - case PROXY_SOCKS5: - proxy_connect_socks5(phb, addr, addrlen); - break; + } + if(ret < 0) { + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); } }