# HG changeset patch # User Nathan Walp # Date 1085945414 0 # Node ID 3e94a77ee0c7b77012e906f7bc17f83625a6f090 # Parent b5c5c1d13783327b3b93f6f1c517e6ae7125501f [gaim-migrate @ 9907] this will attempt connection to all the hosts that a hostname resolves to, so if people have ipv6 support, but no ipv6 routes, we can still connect to servers that have both AAAA and A records. It also makes things a bunch cleaner, and may fix a bug or two. committer: Tailor Script diff -r b5c5c1d13783 -r 3e94a77ee0c7 src/proxy.c --- a/src/proxy.c Sun May 30 19:28:25 2004 +0000 +++ b/src/proxy.c Sun May 30 19:30:14 2004 +0000 @@ -48,8 +48,11 @@ gint inpa; GaimProxyInfo *gpi; GaimAccount *account; + GSList *hosts; }; +static void try_connect(struct PHB *); + const char* socks5errors[] = { "succeeded\n", "general SOCKS server failure\n", @@ -242,7 +245,7 @@ "DNS child %d no longer exists\n", req->dns_pid); return -1; } - + /* Let's contact this lost child! */ rc = write(req->fd_in, dns_params, sizeof(*dns_params)); if(rc<0) { @@ -252,9 +255,9 @@ close(req->fd_in); return -1; } - + g_return_val_if_fail(rc == sizeof(*dns_params), -1); - + /* Did you hear me? (This avoids some race conditions) */ rc = read(req->fd_out, &ch, 1); if(rc != 1 || ch!='Y') { @@ -368,12 +371,6 @@ req->callback(hosts, req->data, NULL); - while(hosts) { - hosts = g_slist_remove(hosts, hosts->data); - g_free(hosts->data); - hosts = g_slist_remove(hosts, hosts->data); - } - release_dns_child(req); } @@ -424,24 +421,24 @@ { pending_dns_request_t *req = NULL; dns_params_t dns_params; - + strncpy(dns_params.hostname, hostname, sizeof(dns_params.hostname)-1); dns_params.hostname[sizeof(dns_params.hostname)-1] = '\0'; dns_params.port = port; - + /* Is there a free available child? */ while(free_dns_children && !req) { GSList *l = free_dns_children; free_dns_children = g_slist_remove_link(free_dns_children, l); req = l->data; g_slist_free(l); - + if(send_dns_request_to_child(req, &dns_params) != 0) { req_free(req); req = NULL; continue; } - + } if(!req) { @@ -694,17 +691,10 @@ close(source); gaim_input_remove(phb->inpa); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); - gaim_debug(GAIM_DEBUG_ERROR, "proxy", "getsockopt SO_ERROR check: %s\n", strerror(error)); + + try_connect(phb); return; } @@ -793,10 +783,13 @@ http_complete(struct PHB *phb, gint source) { gaim_debug(GAIM_DEBUG_INFO, "http proxy", "proxy connection established\n"); - if(!phb->account || phb->account->gc) + if(source < 0) { + try_connect(phb); + } else if(!phb->account || phb->account->gc) { phb->func(phb->data, source, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); + g_free(phb->host); + g_free(phb); + } } @@ -836,7 +829,7 @@ } } } - + if(error) { gaim_debug(GAIM_DEBUG_ERROR, "proxy", "Unable to parse proxy's response: %s\n", inputline); @@ -846,9 +839,10 @@ else if(status!=200) { gaim_debug(GAIM_DEBUG_ERROR, "proxy", "Proxy server replied with:\n%s\n", p); - close(source); + close(source); source = -1; - + + /* XXX: why in the hell are we calling gaim_connection_error() here? */ if ( status == 403 /* Forbidden */ ) { gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port); gaim_connection_error(phb->account->gc, msg); @@ -858,11 +852,11 @@ gaim_connection_error(phb->account->gc, msg); g_free(msg); } - + } else { http_complete(phb, source); } - + return; } @@ -885,14 +879,7 @@ if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -923,14 +910,7 @@ if (write(source, request, request_len) < 0) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1015,14 +995,7 @@ close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); } static void @@ -1044,14 +1017,7 @@ if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } fcntl(source, F_SETFL, 0); @@ -1060,14 +1026,7 @@ if (!(hp = gethostbyname(phb->host))) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1084,14 +1043,7 @@ if (write(source, packet, 9) != 9) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1158,14 +1110,7 @@ gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy", "or not...\n"); close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, source, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } if ((buf[0] != 0x05) || (buf[1] != 0x00)) { @@ -1175,14 +1120,7 @@ gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Bad data.\n"); close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1234,14 +1172,7 @@ if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1260,28 +1191,14 @@ if (read(source, buf, 2) < 2) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } if ((buf[0] != 0x01) || (buf[1] != 0x00)) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1300,34 +1217,20 @@ if (read(source, buf, 2) < 2) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, source, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } if ((buf[0] != 0x05) || (buf[1] == 0xff)) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } if (buf[1] == 0x02) { unsigned int i, j; - + i = strlen(gaim_proxy_info_get_username(phb->gpi)); j = strlen(gaim_proxy_info_get_password(phb->gpi)); @@ -1340,14 +1243,7 @@ if (write(source, buf, 3 + i + j) < 3 + i + j) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1375,14 +1271,8 @@ len = sizeof(error); if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } fcntl(source, F_SETFL, 0); @@ -1406,14 +1296,7 @@ gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Unable to write\n"); close(source); - if (phb->account == NULL || - gaim_account_get_connection(phb->account) != NULL) { - - phb->func(phb->data, -1, GAIM_INPUT_READ); - } - - g_free(phb->host); - g_free(phb); + try_connect(phb); return; } @@ -1469,23 +1352,19 @@ return fd; } -static void -connection_host_resolved(GSList *hosts, gpointer data, - const char *error_message) +static void try_connect(struct PHB *phb) { - struct PHB *phb = (struct PHB*)data; size_t addrlen; struct sockaddr *addr; int ret = -1; - while (hosts) { - addrlen = GPOINTER_TO_INT(hosts->data); - hosts = hosts->next; - addr = hosts->data; - hosts = hosts->next; + while (phb->hosts) { + addrlen = GPOINTER_TO_INT(phb->hosts->data); + phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); + addr = phb->hosts->data; + phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); - switch (gaim_proxy_info_get_type(phb->gpi)) - { + switch (gaim_proxy_info_get_type(phb->gpi)) { case GAIM_PROXY_NONE: ret = proxy_connect_none(phb, addr, addrlen); break; @@ -1510,6 +1389,8 @@ break; } + g_free(addr); + if (ret > 0) break; } @@ -1526,6 +1407,17 @@ } } +static void +connection_host_resolved(GSList *hosts, gpointer data, + const char *error_message) +{ + struct PHB *phb = (struct PHB*)data; + + phb->hosts = hosts; + + try_connect(phb); +} + int gaim_proxy_connect(GaimAccount *account, const char *host, int port, GaimInputFunction func, gpointer data) @@ -1559,8 +1451,8 @@ char *proxyhost,*proxypath; int proxyport; - /* http_proxy-format: - * export http_proxy="http://your.proxy.server:port/" + /* http_proxy-format: + * export http_proxy="http://your.proxy.server:port/" */ if(gaim_url_parse(tmp, &proxyhost, &proxyport, &proxypath)) { gaim_proxy_info_set_host(phb->gpi, proxyhost); @@ -1568,12 +1460,12 @@ g_free(proxypath); /* only for backward compatibility */ - if (proxyport == 80 && + if (proxyport == 80 && ((tmp = g_getenv("HTTP_PROXY_PORT")) != NULL || (tmp = g_getenv("http_proxy_port")) != NULL || (tmp = g_getenv("HTTPPROXYPORT")) != NULL)) proxyport = atoi(tmp); - + gaim_proxy_info_set_port(phb->gpi, proxyport); } }