# HG changeset patch # User Nathan Walp # Date 1047146076 0 # Node ID 9ce3c698ff5eccc91791c47b319d477c5ca042d1 # Parent 24657a33e9e560109f5985a9dc41f592110fd73d [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 diff -r 24657a33e9e5 -r 9ce3c698ff5e src/proxy.c --- 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); } }