diff options
author | Mike Ruprecht <cmaiku@gmail.com> | 2016-01-10 03:23:46 -0600 |
---|---|---|
committer | Mike Ruprecht <cmaiku@gmail.com> | 2016-01-10 03:23:46 -0600 |
commit | d6331ebb1c3c72c21bb843933ac32b8381231bae (patch) | |
tree | e65d166c1412820eca039ffd1fff43c204c84359 | |
parent | 8d4b677b1b598038a1fff3e75aca9b1a93dd90c9 (diff) | |
download | pidgin-d6331ebb1c3c72c21bb843933ac32b8381231bae.tar.gz |
Clear ununused functions from proxy.[ch] including purple_proxy_connect_udp()
Since porting libpurple's proxy API to internally use Gio, a lot of
functions remain unused. purple_proxy_connect_udp() was added for the
QQ prpl (ticket #6589), but no longer appears to be used. This patch
removes all of these functions in favor of the Gio versions.
-rw-r--r-- | libpurple/proxy.c | 1676 | ||||
-rw-r--r-- | libpurple/proxy.h | 30 |
2 files changed, 4 insertions, 1702 deletions
diff --git a/libpurple/proxy.c b/libpurple/proxy.c index 3cae2b9bff..38aec2c63e 100644 --- a/libpurple/proxy.c +++ b/libpurple/proxy.c @@ -99,8 +99,6 @@ static PurpleProxyInfo *global_proxy_info = NULL; static GSList *handles = NULL; -static void try_connect(PurpleProxyConnectData *connect_data); - /* * TODO: Eventually (GObjectification) this bad boy will be removed, because it is * a gross fix for a crashy problem. @@ -639,33 +637,11 @@ purple_proxy_connect_data_disconnect(PurpleProxyConnectData *connect_data, const { purple_debug_error("proxy", "Connection attempt failed: %s\n", error_message); - if (connect_data->hosts != NULL) - try_connect(connect_data); - else - { - /* Everything failed! Tell the originator of the request. */ - connect_data->connect_cb(connect_data->data, -1, error_message); - purple_proxy_connect_data_destroy(connect_data); - } - } -} -/* - * This calls purple_proxy_connect_data_disconnect(), but it lets you - * specify the error_message using a printf()-like syntax. - */ -static void -purple_proxy_connect_data_disconnect_formatted(PurpleProxyConnectData *connect_data, const char *format, ...) -{ - va_list args; - gchar *tmp; - - va_start(args, format); - tmp = g_strdup_vprintf(format, args); - va_end(args); - - purple_proxy_connect_data_disconnect(connect_data, tmp); - g_free(tmp); + /* Everything failed! Tell the originator of the request. */ + connect_data->connect_cb(connect_data->data, -1, error_message); + purple_proxy_connect_data_destroy(connect_data); + } } static void @@ -687,1572 +663,6 @@ purple_proxy_connect_data_connected(PurpleProxyConnectData *connect_data) purple_proxy_connect_data_destroy(connect_data); } -static void -socket_ready_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleProxyConnectData *connect_data = data; - int error = 0; - int ret; - - /* If the socket-connected message had already been triggered when connect_data - * was destroyed via purple_proxy_connect_cancel(), we may get here with a freed connect_data. - */ - if (!PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data)) - return; - - purple_debug_info("proxy", "Connecting to %s:%d.\n", - connect_data->host, connect_data->port); - - /* - * purple_input_get_error after a non-blocking connect returns -1 if something is - * really messed up (bad descriptor, usually). Otherwise, it returns 0 and - * error holds what connect would have returned if it blocked until now. - * Thus, error == 0 is success, error == EINPROGRESS means "try again", - * and anything else is a real error. - * - * (error == EINPROGRESS can happen after a select because the kernel can - * be overly optimistic sometimes. select is just a hint that you might be - * able to do something.) - */ - ret = purple_input_get_error(connect_data->fd, &error); - - if (ret == 0 && error == EINPROGRESS) { - /* No worries - we'll be called again later */ - /* TODO: Does this ever happen? */ - purple_debug_info("proxy", "(ret == 0 && error == EINPROGRESS)\n"); - return; - } - - if (ret != 0 || error != 0) { - if (ret != 0) - error = errno; - purple_debug_error("proxy", "Error connecting to %s:%d (%s).\n", - connect_data->host, connect_data->port, g_strerror(error)); - - purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); - return; - } - - purple_proxy_connect_data_connected(connect_data); -} - -static gboolean -clean_connect(gpointer data) -{ - purple_proxy_connect_data_connected(data); - - return FALSE; -} - -static void -proxy_connect_udp_none(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen) -{ - purple_debug_info("proxy", "UDP Connecting to %s:%d with no proxy\n", - connect_data->host, connect_data->port); - - connect_data->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0); - if (connect_data->fd < 0) - { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Unable to create socket: %s"), g_strerror(errno)); - return; - } - _purple_network_set_common_socket_flags(connect_data->fd); - - if (connect(connect_data->fd, &addr->sa, addrlen) != 0) - { - if ((errno == EINPROGRESS) || (errno == EINTR)) - { - purple_debug_info("proxy", "UDP connection in progress\n"); - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, socket_ready_cb, connect_data); - } - else - { - purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); - } - } - else - { - /* - * The connection happened IMMEDIATELY... strange, but whatever. - */ - int error = ETIMEDOUT; - int ret; - - purple_debug_info("proxy", "UDP Connected immediately.\n"); - - ret = purple_input_get_error(connect_data->fd, &error); - if ((ret != 0) || (error != 0)) - { - if (ret != 0) - error = errno; - purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); - return; - } - - /* - * We want to call the "connected" callback eventually, but we - * don't want to call it before we return, just in case. - */ - purple_timeout_add(10, clean_connect, connect_data); - } -} - -static void -proxy_connect_none(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen) -{ - purple_debug_info("proxy", "Connecting to %s:%d with no proxy\n", - connect_data->host, connect_data->port); - - connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0); - if (connect_data->fd < 0) - { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Unable to create socket: %s"), g_strerror(errno)); - return; - } - _purple_network_set_common_socket_flags(connect_data->fd); - - if (connect(connect_data->fd, &addr->sa, addrlen) != 0) - { - if ((errno == EINPROGRESS) || (errno == EINTR)) - { - purple_debug_info("proxy", "Connection in progress\n"); - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, socket_ready_cb, connect_data); - } - else - { - purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); - } - } - else - { - /* - * The connection happened IMMEDIATELY... strange, but whatever. - */ - int error = ETIMEDOUT; - int ret; - - purple_debug_info("proxy", "Connected immediately.\n"); - - ret = purple_input_get_error(connect_data->fd, &error); - if ((ret != 0) || (error != 0)) - { - if (ret != 0) - error = errno; - purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); - return; - } - - /* - * We want to call the "connected" callback eventually, but we - * don't want to call it before we return, just in case. - */ - purple_timeout_add(10, clean_connect, connect_data); - } -} - -/* - * This is a utility function used by the HTTP, SOCKS4 and SOCKS5 - * connect functions. It writes data from a buffer to a socket. - * When all the data is written it sets up a watcher to read a - * response and call a specified function. - */ -static void -proxy_do_write(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleProxyConnectData *connect_data; - const guchar *request; - gsize request_len; - int ret; - - connect_data = data; - request = connect_data->write_buffer + connect_data->written_len; - request_len = connect_data->write_buf_len - connect_data->written_len; - - ret = write(connect_data->fd, request, request_len); - if (ret <= 0) - { - if (errno == EAGAIN) - /* No worries */ - return; - - /* Error! */ - purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); - return; - } - if ((gsize)ret < request_len) { - connect_data->written_len += ret; - return; - } - - /* We're done writing data! Wait for a response. */ - g_free(connect_data->write_buffer); - connect_data->write_buffer = NULL; - purple_input_remove(connect_data->inpa); - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_READ, connect_data->read_cb, connect_data); -} - -/* - * We're using an HTTP proxy for a non-port 80 tunnel. Read the - * response to the CONNECT request. - */ -static void -http_canread(gpointer data, gint source, PurpleInputCondition cond) -{ - int len, headers_len, status = 0; - gboolean error; - PurpleProxyConnectData *connect_data = data; - char *p; - gsize max_read; - - if (connect_data->read_buffer == NULL) { - connect_data->read_buf_len = 8192; - connect_data->read_buffer = g_malloc(connect_data->read_buf_len); - connect_data->read_len = 0; - } - - p = (char *)connect_data->read_buffer + connect_data->read_len; - max_read = connect_data->read_buf_len - connect_data->read_len - 1; - - len = read(connect_data->fd, p, max_read); - - if (len == 0) { - purple_proxy_connect_data_disconnect(connect_data, - _("Server closed the connection")); - return; - } - - if (len < 0) { - if (errno == EAGAIN) - /* No worries */ - return; - - /* Error! */ - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Lost connection with server: %s"), g_strerror(errno)); - return; - } - - connect_data->read_len += len; - p[len] = '\0'; - - p = g_strstr_len((const gchar *)connect_data->read_buffer, - connect_data->read_len, "\r\n\r\n"); - if (p != NULL) { - *p = '\0'; - headers_len = (p - (char *)connect_data->read_buffer) + 4; - } else if((gsize)len == max_read) - headers_len = len; - else - return; - - error = strncmp((const char *)connect_data->read_buffer, "HTTP/", 5) != 0; - if (!error) { - int major; - p = (char *)connect_data->read_buffer + 5; - major = strtol(p, &p, 10); - error = (major == 0) || (*p != '.'); - if(!error) { - int minor; - p++; - minor = strtol(p, &p, 10); - error = (*p != ' '); - if(!error) { - p++; - status = strtol(p, &p, 10); - error = (*p != ' '); - (void)minor; /* we don't need its value */ - } - } - } - - /* Read the contents */ - p = g_strrstr((const gchar *)connect_data->read_buffer, "Content-Length: "); - if (p != NULL) { - gchar *tmp; - gsize content_len; - char tmpc; - - p += strlen("Content-Length: "); - tmp = strchr(p, '\r'); - if(tmp) - *tmp = '\0'; - if (sscanf(p, "%" G_GSIZE_FORMAT, &content_len) != 1) { - /* Couldn't read content length */ - purple_debug_error("proxy", "Couldn't read content length value " - "from %s\n", p); - if(tmp) - *tmp = '\r'; - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Unable to parse response from HTTP proxy: %s"), - connect_data->read_buffer); - return; - } - if(tmp) - *tmp = '\r'; - - /* Compensate for what has already been read */ - content_len -= connect_data->read_len - headers_len; - /* I'm assuming that we're doing this to prevent the server from - complaining / breaking since we don't read the whole page */ - while (content_len--) { - /* TODO: deal with EAGAIN (and other errors) better */ - /* TODO: Reading 1 byte at a time is horrible and stupid. */ - if (read(connect_data->fd, &tmpc, 1) < 0 && errno != EAGAIN) - break; - } - } - - if (error) { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Unable to parse response from HTTP proxy: %s"), - connect_data->read_buffer); - return; - } - else if (status != 200) { - purple_debug_error("proxy", - "Proxy server replied with:\n%s\n", - connect_data->read_buffer); - - if (status == 407 /* Proxy Auth */) { - const char *header; - gchar *request; - - header = g_strrstr((const gchar *)connect_data->read_buffer, - "Proxy-Authenticate: NTLM"); - if (header != NULL) { - const char *header_end = header + strlen("Proxy-Authenticate: NTLM"); - const char *domain = purple_proxy_info_get_username(connect_data->gpi); - char *username = NULL, hostname[256]; - gchar *response; - int ret; - - ret = gethostname(hostname, sizeof(hostname)); - hostname[sizeof(hostname) - 1] = '\0'; - if (ret < 0 || hostname[0] == '\0') { - purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?"); - g_strlcpy(hostname, "localhost", sizeof(hostname)); - } - - if (domain != NULL) - username = (char*) strchr(domain, '\\'); - if (username == NULL) { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("HTTP proxy connection error %d"), status); - return; - } - *username = '\0'; - - /* Is there a message? */ - if (*header_end == ' ') { - /* Check for Type-2 */ - char *tmp = (char*) header; - guint8 *nonce; - - header_end++; - username++; - while(*tmp != '\r' && *tmp != '\0') tmp++; - *tmp = '\0'; - nonce = purple_ntlm_parse_type2(header_end, NULL); - response = purple_ntlm_gen_type3(username, - (gchar*) purple_proxy_info_get_password(connect_data->gpi), - hostname, - domain, nonce, NULL); - username--; - } else /* Empty message */ - response = purple_ntlm_gen_type1(hostname, domain); - - *username = '\\'; - - request = g_strdup_printf( - "CONNECT %s:%d HTTP/1.1\r\n" - "Host: %s:%d\r\n" - "Proxy-Authorization: NTLM %s\r\n" - "Proxy-Connection: Keep-Alive\r\n\r\n", - connect_data->host, connect_data->port, - connect_data->host, connect_data->port, - response); - - g_free(response); - - } else if (g_strrstr((const char *)connect_data->read_buffer, "Proxy-Authenticate: Basic") != NULL) { - gchar *t1, *t2; - const char *username, *password; - - username = purple_proxy_info_get_username(connect_data->gpi); - password = purple_proxy_info_get_password(connect_data->gpi); - - t1 = g_strdup_printf("%s:%s", - username ? username : "", - password ? password : ""); - t2 = purple_base64_encode((guchar *)t1, strlen(t1)); - g_free(t1); - - request = g_strdup_printf( - "CONNECT %s:%d HTTP/1.1\r\n" - "Host: %s:%d\r\n" - "Proxy-Authorization: Basic %s\r\n", - connect_data->host, connect_data->port, - connect_data->host, connect_data->port, - t2); - - g_free(t2); - - } else { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("HTTP proxy connection error %d"), status); - return; - } - - purple_input_remove(connect_data->inpa); - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - - connect_data->write_buffer = (guchar *)request; - connect_data->write_buf_len = strlen(request); - connect_data->written_len = 0; - - connect_data->read_cb = http_canread; - - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - - proxy_do_write(connect_data, connect_data->fd, cond); - - return; - } - - if (status == 403) { - /* Forbidden */ - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Access denied: HTTP proxy server forbids port %d tunneling"), - connect_data->port); - } else { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("HTTP proxy connection error %d"), status); - } - } else { - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - purple_debug_info("proxy", "HTTP proxy connection established\n"); - purple_proxy_connect_data_connected(connect_data); - return; - } -} - -static void -http_start_connect_tunneling(PurpleProxyConnectData *connect_data) { - GString *request; - int ret; - - purple_debug_info("proxy", "Using CONNECT tunneling for %s:%d\n", - connect_data->host, connect_data->port); - - request = g_string_sized_new(4096); - g_string_append_printf(request, - "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", - connect_data->host, connect_data->port, - connect_data->host, connect_data->port); - - if (purple_proxy_info_get_username(connect_data->gpi) != NULL) - { - char *t1, *t2, *ntlm_type1; - char hostname[256]; - - ret = gethostname(hostname, sizeof(hostname)); - hostname[sizeof(hostname) - 1] = '\0'; - if (ret < 0 || hostname[0] == '\0') { - purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?"); - g_strlcpy(hostname, "localhost", sizeof(hostname)); - } - - t1 = g_strdup_printf("%s:%s", - purple_proxy_info_get_username(connect_data->gpi), - purple_proxy_info_get_password(connect_data->gpi) ? - purple_proxy_info_get_password(connect_data->gpi) : ""); - t2 = purple_base64_encode((const guchar *)t1, strlen(t1)); - g_free(t1); - - ntlm_type1 = purple_ntlm_gen_type1(hostname, ""); - - g_string_append_printf(request, - "Proxy-Authorization: Basic %s\r\n" - "Proxy-Authorization: NTLM %s\r\n" - "Proxy-Connection: Keep-Alive\r\n", - t2, ntlm_type1); - g_free(ntlm_type1); - g_free(t2); - } - - g_string_append(request, "\r\n"); - - connect_data->write_buf_len = request->len; - connect_data->write_buffer = (guchar *)g_string_free(request, FALSE); - connect_data->written_len = 0; - connect_data->read_cb = http_canread; - - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); -} - -static void -http_canwrite(gpointer data, gint source, PurpleInputCondition cond) { - PurpleProxyConnectData *connect_data = data; - int ret, error = ETIMEDOUT; - - purple_debug_info("proxy", "Connected to %s:%d.\n", - connect_data->host, connect_data->port); - - if (connect_data->inpa > 0) { - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - } - - ret = purple_input_get_error(connect_data->fd, &error); - if (ret != 0 || error != 0) { - if (ret != 0) - error = errno; - purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); - return; - } - - if (connect_data->port == 80) { - /* - * If we're trying to connect to something running on - * port 80 then we assume the traffic using this - * connection is going to be HTTP traffic. If it's - * not then this will fail (uglily). But it's good - * to avoid using the CONNECT method because it's - * not always allowed. - */ - purple_debug_info("proxy", "HTTP proxy connection established\n"); - purple_proxy_connect_data_connected(connect_data); - } else { - http_start_connect_tunneling(connect_data); - } - -} - -static void -proxy_connect_http(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen) -{ - purple_debug_info("proxy", - "Connecting to %s:%d via %s:%d using HTTP\n", - connect_data->host, connect_data->port, - (purple_proxy_info_get_host(connect_data->gpi) ? purple_proxy_info_get_host(connect_data->gpi) : "(null)"), - purple_proxy_info_get_port(connect_data->gpi)); - - connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0); - if (connect_data->fd < 0) - { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Unable to create socket: %s"), g_strerror(errno)); - return; - } - _purple_network_set_common_socket_flags(connect_data->fd); - - if (connect(connect_data->fd, &addr->sa, addrlen) != 0) { - if (errno == EINPROGRESS || errno == EINTR) { - purple_debug_info("proxy", "HTTP connection in progress\n"); - - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, http_canwrite, connect_data); - } else - purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); - } else { - purple_debug_info("proxy", "Connected immediately.\n"); - - http_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - } -} - -static void -s4_canread(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleProxyConnectData *connect_data = data; - guchar *buf; - int len, max_read; - - /* This is really not going to block under normal circumstances, but to - * be correct, we deal with the unlikely scenario */ - - if (connect_data->read_buffer == NULL) { - connect_data->read_buf_len = 12; - connect_data->read_buffer = g_malloc(connect_data->read_buf_len); - connect_data->read_len = 0; - } - - buf = connect_data->read_buffer + connect_data->read_len; - max_read = connect_data->read_buf_len - connect_data->read_len; - - len = read(connect_data->fd, buf, max_read); - - if ((len < 0 && errno == EAGAIN) || (len > 0 && len + connect_data->read_len < 4)) - return; - else if (len + connect_data->read_len >= 4) { - if (connect_data->read_buffer[1] == 90) { - purple_proxy_connect_data_connected(connect_data); - return; - } - } - - purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); -} - -static void -s4_host_resolved(GObject *source_object, GAsyncResult *res, gpointer data) -{ - GInetAddress *address = NULL; - GError *error = NULL; - GList *hosts = NULL, *l = NULL; - PurpleProxyConnectData *connect_data = data; - unsigned char packet[9]; - - if(G_IS_CANCELLABLE(connect_data->cancellable)) { - g_object_unref(G_OBJECT(connect_data->cancellable)); - - connect_data->cancellable = NULL; - } - - hosts = g_resolver_lookup_by_name_finish(G_RESOLVER(source_object), - res, &error); - - if (error->message != NULL) { - purple_proxy_connect_data_disconnect(connect_data, error->message); - - g_error_free(error); - - return; - } - - if (hosts == NULL) { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Error resolving %s"), connect_data->host); - return; - } - - for(l = hosts; l; l = l->next) { - address = G_INET_ADDRESS(l->data); - - if(!g_inet_address_get_is_loopback(address) && !g_inet_address_get_is_link_local(address)) - break; - - address = NULL; - } - - if(address != NULL) { - packet[0] = 0x04; - packet[1] = 0x01; - packet[2] = connect_data->port >> 8; - packet[3] = connect_data->port & 0xff; - memcpy(packet + 4, g_inet_address_to_bytes(address), 4); - packet[8] = 0x00; - - connect_data->write_buffer = g_memdup(packet, sizeof(packet)); - connect_data->write_buf_len = sizeof(packet); - connect_data->written_len = 0; - connect_data->read_cb = s4_canread; - - connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - } else { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Error resolving %s"), connect_data->host); - } - - g_resolver_free_addresses(hosts); -} - -static void -s4_canwrite(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleProxyConnectData *connect_data = data; - int error = ETIMEDOUT; - int ret; - - purple_debug_info("socks4 proxy", "Connected.\n"); - - if (connect_data->inpa > 0) { - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - } - - ret = purple_input_get_error(connect_data->fd, &error); - if ((ret != 0) || (error != 0)) { - if (ret != 0) - error = errno; - purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); - return; - } - - /* - * The socks4 spec doesn't include support for doing host name lookups by - * the proxy. Many socks4 servers do this via the "socks4a" extension to - * the protocol. There doesn't appear to be a way to detect if a server - * supports this, so we require that the user set a global option. - */ - if (purple_prefs_get_bool("/purple/proxy/socks4_remotedns")) { - unsigned char packet[9]; - int len; - - purple_debug_info("socks4 proxy", "Attempting to use remote DNS.\n"); - - packet[0] = 0x04; - packet[1] = 0x01; - packet[2] = connect_data->port >> 8; - packet[3] = connect_data->port & 0xff; - packet[4] = 0x00; - packet[5] = 0x00; - packet[6] = 0x00; - packet[7] = 0x01; - packet[8] = 0x00; - - len = sizeof(packet) + strlen(connect_data->host) + 1; - - connect_data->write_buffer = g_malloc0(len); - memcpy(connect_data->write_buffer, packet, sizeof(packet)); - memcpy(connect_data->write_buffer + sizeof(packet), connect_data->host, strlen(connect_data->host)); - connect_data->write_buf_len = len; - connect_data->written_len = 0; - connect_data->read_cb = s4_canread; - - connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - } else { - GResolver *resolver = NULL; - - connect_data->cancellable = g_cancellable_new(); - - resolver = g_resolver_get_default(); - - g_resolver_lookup_by_name_async(resolver, - connect_data->host, - connect_data->cancellable, - s4_host_resolved, - connect_data); - - g_object_unref(G_OBJECT(resolver)); - - if (connect_data->cancellable == NULL) { - purple_debug_error("proxy", "dns query failed unexpectedly.\n"); - purple_proxy_connect_data_destroy(connect_data); - } - } -} - -static void -proxy_connect_socks4(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen) -{ - purple_debug_info("proxy", - "Connecting to %s:%d via %s:%d using SOCKS4\n", - connect_data->host, connect_data->port, - purple_proxy_info_get_host(connect_data->gpi), - purple_proxy_info_get_port(connect_data->gpi)); - - connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0); - if (connect_data->fd < 0) - { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Unable to create socket: %s"), g_strerror(errno)); - return; - } - _purple_network_set_common_socket_flags(connect_data->fd); - - if (connect(connect_data->fd, &addr->sa, addrlen) != 0) - { - if ((errno == EINPROGRESS) || (errno == EINTR)) - { - purple_debug_info("proxy", "SOCKS4 connection in progress\n"); - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, s4_canwrite, connect_data); - } - else - { - purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); - } - } - else - { - purple_debug_info("proxy", "Connected immediately.\n"); - - s4_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - } -} - -static gboolean -s5_ensure_buffer_length(PurpleProxyConnectData *connect_data, guint len) -{ - if(connect_data->read_len < len) { - if(connect_data->read_buf_len < len) { - /* it's not just that we haven't read enough, it's that we haven't tried to read enough yet */ - purple_debug_info("s5", "reallocing from %" G_GSIZE_FORMAT - " to %d\n", connect_data->read_buf_len, len); - connect_data->read_buf_len = len; - connect_data->read_buffer = g_realloc(connect_data->read_buffer, connect_data->read_buf_len); - } - return FALSE; - } - - return TRUE; -} - -static void -s5_canread_again(gpointer data, gint source, PurpleInputCondition cond) -{ - guchar *dest, *buf; - PurpleProxyConnectData *connect_data = data; - int len; - - if (connect_data->read_buffer == NULL) { - connect_data->read_buf_len = 5; - connect_data->read_buffer = g_malloc(connect_data->read_buf_len); - connect_data->read_len = 0; - } - - dest = connect_data->read_buffer + connect_data->read_len; - buf = connect_data->read_buffer; - - len = read(connect_data->fd, dest, (connect_data->read_buf_len - connect_data->read_len)); - - if (len == 0) - { - purple_proxy_connect_data_disconnect(connect_data, - _("Server closed the connection")); - return; - } - - if (len < 0) - { - if (errno == EAGAIN) - /* No worries */ - return; - - /* Error! */ - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Lost connection with server: %s"), g_strerror(errno)); - return; - } - - connect_data->read_len += len; - - if(connect_data->read_len < 4) - return; - - if ((buf[0] != 0x05) || (buf[1] != 0x00)) { - if ((buf[0] == 0x05) && (buf[1] < 0x09)) { - purple_debug_error("socks5 proxy", "%s", socks5errors[buf[1]]); - purple_proxy_connect_data_disconnect(connect_data, - socks5errors[buf[1]]); - } else { - purple_debug_error("socks5 proxy", "Bad data.\n"); - purple_proxy_connect_data_disconnect(connect_data, - _("Received invalid data on connection with server")); - } - return; - } - - /* Skip past BND.ADDR */ - switch(buf[3]) { - case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */ - if(!s5_ensure_buffer_length(connect_data, 4 + 4)) - return; - buf += 4 + 4; - break; - case 0x03: /* the address field contains a fully-qualified domain name. The first - octet of the address field contains the number of octets of name that - follow, there is no terminating NUL octet. */ - if(!s5_ensure_buffer_length(connect_data, 4 + 1)) - return; - buf += 4; - if(!s5_ensure_buffer_length(connect_data, 4 + 1 + buf[0])) - return; - buf += buf[0] + 1; - break; - case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */ - if(!s5_ensure_buffer_length(connect_data, 4 + 16)) - return; - buf += 4 + 16; - break; - default: - purple_debug_error("socks5 proxy", "Invalid ATYP received (0x%X)\n", buf[3]); - purple_proxy_connect_data_disconnect(connect_data, - _("Received invalid data on connection with server")); - return; - } - - /* Skip past BND.PORT */ - if(!s5_ensure_buffer_length(connect_data, (buf - connect_data->read_buffer) + 2)) - return; - - purple_proxy_connect_data_connected(connect_data); -} - -static void -s5_sendconnect(gpointer data, int source) -{ - PurpleProxyConnectData *connect_data = data; - size_t hlen = strlen(connect_data->host); - connect_data->write_buf_len = 5 + hlen + 2; - connect_data->write_buffer = g_malloc(connect_data->write_buf_len); - connect_data->written_len = 0; - - connect_data->write_buffer[0] = 0x05; - connect_data->write_buffer[1] = 0x01; /* CONNECT */ - connect_data->write_buffer[2] = 0x00; /* reserved */ - connect_data->write_buffer[3] = 0x03; /* address type -- host name */ - connect_data->write_buffer[4] = hlen; - memcpy(connect_data->write_buffer + 5, connect_data->host, hlen); - connect_data->write_buffer[5 + hlen] = connect_data->port >> 8; - connect_data->write_buffer[5 + hlen + 1] = connect_data->port & 0xff; - - connect_data->read_cb = s5_canread_again; - - connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); -} - -static void -s5_readauth(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleProxyConnectData *connect_data = data; - int len; - - if (connect_data->read_buffer == NULL) { - connect_data->read_buf_len = 2; - connect_data->read_buffer = g_malloc(connect_data->read_buf_len); - connect_data->read_len = 0; - } - - purple_debug_info("socks5 proxy", "Got auth response.\n"); - - len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len, - connect_data->read_buf_len - connect_data->read_len); - - if (len == 0) - { - purple_proxy_connect_data_disconnect(connect_data, - _("Server closed the connection")); - return; - } - - if (len < 0) - { - if (errno == EAGAIN) - /* No worries */ - return; - - /* Error! */ - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Lost connection with server: %s"), g_strerror(errno)); - return; - } - - connect_data->read_len += len; - if (connect_data->read_len < 2) - return; - - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - - if ((connect_data->read_buffer[0] != 0x01) || (connect_data->read_buffer[1] != 0x00)) { - purple_proxy_connect_data_disconnect(connect_data, - _("Received invalid data on connection with server")); - return; - } - - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - - s5_sendconnect(connect_data, connect_data->fd); -} - -static void -hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response) -{ - PurpleHash *hash; - int i; - unsigned char Kxoripad[65]; - unsigned char Kxoropad[65]; - size_t pwlen; - - hash = purple_md5_hash_new(); - - memset(Kxoripad,0,sizeof(Kxoripad)); - memset(Kxoropad,0,sizeof(Kxoropad)); - - pwlen=strlen(passwd); - if (pwlen>64) { - purple_hash_append(hash, (const guchar *)passwd, strlen(passwd)); - purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad)); - pwlen=16; - } else { - memcpy(Kxoripad, passwd, pwlen); - } - memcpy(Kxoropad,Kxoripad,pwlen); - - for (i=0;i<64;i++) { - Kxoripad[i]^=0x36; - Kxoropad[i]^=0x5c; - } - - purple_hash_reset(hash); - purple_hash_append(hash, Kxoripad, 64); - purple_hash_append(hash, challenge, challen); - purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad)); - - purple_hash_reset(hash); - purple_hash_append(hash, Kxoropad, 64); - purple_hash_append(hash, Kxoripad, 16); - purple_hash_digest(hash, response, 16); - - g_object_unref(hash); -} - -static void -s5_readchap(gpointer data, gint source, PurpleInputCondition cond); - -/* - * Return how many bytes we processed - * -1 means we've shouldn't keep reading from the buffer - */ -static gssize -s5_parse_chap_msg(PurpleProxyConnectData *connect_data) -{ - guchar *buf, *cmdbuf = connect_data->read_buffer; - int len, navas, currentav; - - purple_debug_misc("socks5 proxy", "Reading CHAP message: %x\n", *cmdbuf); - - if (*cmdbuf != 0x01) { - purple_proxy_connect_data_disconnect(connect_data, - _("Received invalid data on connection with server")); - return -1; - } - cmdbuf++; - - navas = *cmdbuf; - - purple_debug_misc("socks5 proxy", "Expecting %d attribute(s).\n", navas); - if (G_UNLIKELY(navas < 0 || navas > 10000)) { /* XXX: what's the threshold? */ - purple_proxy_connect_data_disconnect(connect_data, - _("Received invalid data on connection with server")); - return -1; - } - - cmdbuf++; - - for (currentav = 0; currentav < navas; currentav++) { - - len = connect_data->read_len - (cmdbuf - connect_data->read_buffer); - /* We don't have enough data to even know how long the next attribute is, - * or we don't have the full length of the next attribute. */ - if (len < 2 || len < (cmdbuf[1] + 2)) { - /* Clear out the attributes that have been read - decrease the attribute count */ - connect_data->read_buffer[1] = navas - currentav; - /* Move the unprocessed data into the first attribute position */ - memmove((connect_data->read_buffer + 2), cmdbuf, len); - /* Decrease the read count accordingly */ - connect_data->read_len = len + 2; - - purple_debug_info("socks5 proxy", "Need more data to retrieve attribute %d.\n", currentav); - - return -1; - } - - buf = cmdbuf + 2; - - if (cmdbuf[1] == 0) { - purple_debug_error("socks5 proxy", "Attribute %x Value length of 0; ignoring.\n", cmdbuf[0]); - cmdbuf = buf; - continue; - } - - switch (cmdbuf[0]) { - case 0x00: - purple_debug_info("socks5 proxy", "Received STATUS of %x\n", buf[0]); - /* Did auth work? */ - if (buf[0] == 0x00) { - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - /* Success */ - s5_sendconnect(connect_data, connect_data->fd); - } else { - /* Failure */ - purple_debug_warning("proxy", - "socks5 CHAP authentication " - "failed. Disconnecting..."); - purple_proxy_connect_data_disconnect(connect_data, - _("Authentication failed")); - } - return -1; - case 0x01: - /* We've already validated that cmdbuf[1] is sane. */ - purple_debug_info("socks5 proxy", "Received TEXT-MESSAGE of '%.*s'\n", (int) cmdbuf[1], buf); - break; - case 0x03: - purple_debug_info("socks5 proxy", "Received CHALLENGE\n"); - /* Server wants our credentials */ - - connect_data->write_buf_len = 16 + 4; - connect_data->write_buffer = g_malloc(connect_data->write_buf_len); - connect_data->written_len = 0; - - hmacmd5_chap(buf, cmdbuf[1], - purple_proxy_info_get_password(connect_data->gpi), - connect_data->write_buffer + 4); - /* TODO: What about USER-IDENTITY? */ - connect_data->write_buffer[0] = 0x01; - connect_data->write_buffer[1] = 0x01; - connect_data->write_buffer[2] = 0x04; - connect_data->write_buffer[3] = 0x10; - - purple_input_remove(connect_data->inpa); - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - - connect_data->read_cb = s5_readchap; - - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - return -1; - case 0x11: - purple_debug_info("socks5 proxy", "Received ALGORIGTHMS of %x\n", buf[0]); - /* Server wants to select an algorithm */ - if (buf[0] != 0x85) { - /* Only currently support HMAC-MD5 */ - purple_debug_warning("proxy", - "Server tried to select an " - "algorithm that we did not advertise " - "as supporting. This is a violation " - "of the socks5 CHAP specification. " - "Disconnecting..."); - purple_proxy_connect_data_disconnect(connect_data, - _("Received invalid data on connection with server")); - return -1; - } - break; - default: - purple_debug_info("socks5 proxy", "Received unused command %x, length=%d\n", cmdbuf[0], cmdbuf[1]); - } - cmdbuf = buf + cmdbuf[1]; - } - - return (cmdbuf - connect_data->read_buffer); -} - -static void -s5_readchap(gpointer data, gint source, PurpleInputCondition cond) -{ - gssize msg_ret; - PurpleProxyConnectData *connect_data = data; - int len; - - purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Got CHAP response.\n"); - - if (connect_data->read_buffer == NULL) { - /* A big enough butfer to read the message header (2 bytes) and at least one complete attribute and value (1 + 1 + 255). */ - connect_data->read_buf_len = 259; - connect_data->read_buffer = g_malloc(connect_data->read_buf_len); - connect_data->read_len = 0; - } - - if (connect_data->read_buf_len - connect_data->read_len == 0) { - /*If the stuff below is right, this shouldn't be possible. */ - purple_debug_error("socks5 proxy", "This is about to suck because the read buffer is full (shouldn't happen).\n"); - } - - len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len, - connect_data->read_buf_len - connect_data->read_len); - - if (len == 0) { - purple_proxy_connect_data_disconnect(connect_data, - _("Server closed the connection")); - return; - } - - if (len < 0) { - if (errno == EAGAIN) - /* No worries */ - return; - - /* Error! */ - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Lost connection with server: %s"), g_strerror(errno)); - return; - } - - connect_data->read_len += len; - - /* We may have read more than one message into the buffer, we need to make sure to process them all */ - while (1) { - - /* We need more to be able to read this message */ - if (connect_data->read_len < 2) - return; - - msg_ret = s5_parse_chap_msg(connect_data); - - if (msg_ret < 0) - return; - - /* See if we have another message already in the buffer */ - if ((len = connect_data->read_len - msg_ret) > 0) { - - /* Move on to the next message */ - memmove(connect_data->read_buffer, connect_data->read_buffer + msg_ret, len); - /* Decrease the read count accordingly */ - connect_data->read_len = len; - - /* Try to read the message that connect_data->read_buffer now points to */ - continue; - } - - break; - } - - /* Fell through. We ran out of CHAP events to process, but haven't - * succeeded or failed authentication - there may be more to come. - * If this is the case, come straight back here. */ - - purple_debug_info("socks5 proxy", "Waiting for another message from which to read CHAP info.\n"); - - /* We've processed all the available attributes, so get ready for a whole new message */ - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; -} - -static void -s5_canread(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleProxyConnectData *connect_data = data; - int len; - - if (connect_data->read_buffer == NULL) { - connect_data->read_buf_len = 2; - connect_data->read_buffer = g_malloc(connect_data->read_buf_len); - connect_data->read_len = 0; - } - - purple_debug_info("socks5 proxy", "Able to read.\n"); - - len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len, - connect_data->read_buf_len - connect_data->read_len); - - if (len == 0) - { - purple_proxy_connect_data_disconnect(connect_data, - _("Server closed the connection")); - return; - } - - if (len < 0) - { - if (errno == EAGAIN) - /* No worries */ - return; - - /* Error! */ - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Lost connection with server: %s"), g_strerror(errno)); - return; - } - - connect_data->read_len += len; - if (connect_data->read_len < 2) - return; - - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - - if ((connect_data->read_buffer[0] != 0x05) || (connect_data->read_buffer[1] == 0xff)) { - purple_proxy_connect_data_disconnect(connect_data, - _("Received invalid data on connection with server")); - return; - } - - if (connect_data->read_buffer[1] == 0x02) { - size_t i, j; - const char *u, *p; - - u = purple_proxy_info_get_username(connect_data->gpi); - p = purple_proxy_info_get_password(connect_data->gpi); - - i = (u == NULL) ? 0 : strlen(u); - j = (p == NULL) ? 0 : strlen(p); - - connect_data->write_buf_len = 1 + 1 + i + 1 + j; - connect_data->write_buffer = g_malloc(connect_data->write_buf_len); - connect_data->written_len = 0; - - connect_data->write_buffer[0] = 0x01; /* version 1 */ - connect_data->write_buffer[1] = i; - if (u != NULL) - memcpy(connect_data->write_buffer + 2, u, i); - connect_data->write_buffer[2 + i] = j; - if (p != NULL) - memcpy(connect_data->write_buffer + 2 + i + 1, p, j); - - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - - connect_data->read_cb = s5_readauth; - - connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, - proxy_do_write, connect_data); - - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - - return; - } else if (connect_data->read_buffer[1] == 0x03) { - size_t userlen; - userlen = strlen(purple_proxy_info_get_username(connect_data->gpi)); - - connect_data->write_buf_len = 7 + userlen; - connect_data->write_buffer = g_malloc(connect_data->write_buf_len); - connect_data->written_len = 0; - - connect_data->write_buffer[0] = 0x01; - connect_data->write_buffer[1] = 0x02; - connect_data->write_buffer[2] = 0x11; - connect_data->write_buffer[3] = 0x01; - connect_data->write_buffer[4] = 0x85; - connect_data->write_buffer[5] = 0x02; - connect_data->write_buffer[6] = userlen; - memcpy(connect_data->write_buffer + 7, - purple_proxy_info_get_username(connect_data->gpi), userlen); - - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - - connect_data->read_cb = s5_readchap; - - connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, - proxy_do_write, connect_data); - - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - - return; - } else { - g_free(connect_data->read_buffer); - connect_data->read_buffer = NULL; - - s5_sendconnect(connect_data, connect_data->fd); - } -} - -static void -s5_canwrite(gpointer data, gint source, PurpleInputCondition cond) -{ - unsigned char buf[5]; - int i; - PurpleProxyConnectData *connect_data = data; - int error = ETIMEDOUT; - int ret; - - purple_debug_info("socks5 proxy", "Connected.\n"); - - if (connect_data->inpa > 0) - { - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - } - - ret = purple_input_get_error(connect_data->fd, &error); - if ((ret != 0) || (error != 0)) - { - if (ret != 0) - error = errno; - purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); - return; - } - - buf[0] = 0x05; /* SOCKS version 5 */ - - if (purple_proxy_info_get_username(connect_data->gpi) != NULL) { - buf[1] = 0x03; /* three methods */ - buf[2] = 0x00; /* no authentication */ - buf[3] = 0x03; /* CHAP authentication */ - buf[4] = 0x02; /* username/password authentication */ - i = 5; - } - else { - buf[1] = 0x01; - buf[2] = 0x00; - i = 3; - } - - connect_data->write_buf_len = i; - connect_data->write_buffer = g_malloc(connect_data->write_buf_len); - memcpy(connect_data->write_buffer, buf, i); - - connect_data->read_cb = s5_canread; - - connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); -} - -static void -proxy_connect_socks5(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen) -{ - purple_debug_info("proxy", - "Connecting to %s:%d via %s:%d using SOCKS5\n", - connect_data->host, connect_data->port, - purple_proxy_info_get_host(connect_data->gpi), - purple_proxy_info_get_port(connect_data->gpi)); - - connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0); - if (connect_data->fd < 0) - { - purple_proxy_connect_data_disconnect_formatted(connect_data, - _("Unable to create socket: %s"), g_strerror(errno)); - return; - } - _purple_network_set_common_socket_flags(connect_data->fd); - - if (connect(connect_data->fd, &addr->sa, addrlen) != 0) - { - if ((errno == EINPROGRESS) || (errno == EINTR)) - { - purple_debug_info("proxy", "SOCKS5 connection in progress\n"); - connect_data->inpa = purple_input_add(connect_data->fd, - PURPLE_INPUT_WRITE, s5_canwrite, connect_data); - } - else - { - purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); - } - } - else - { - purple_debug_info("proxy", "Connected immediately.\n"); - - s5_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); - } -} - -/* - * This function attempts to connect to the next IP address in the list - * of IP addresses returned to us by purple_dnsquery_a() and attempts - * to connect to each one. This is called after the hostname is - * resolved, and each time a connection attempt fails (assuming there - * is another IP address to try). - */ -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 46 -#endif - -static void try_connect(PurpleProxyConnectData *connect_data) -{ - GInetAddress *address = NULL; - GSocketAddress *socket_address = NULL; - GError *error = NULL; - char *ipaddr; - - common_sockaddr_t addr; - socklen_t addrlen = 0; - - address = G_INET_ADDRESS(connect_data->hosts->data); - ipaddr = g_inet_address_to_string(address); - - purple_debug_info("proxy", "Attempting connection to %s\n", ipaddr); - g_free(ipaddr); - - socket_address = g_inet_socket_address_new(address, connect_data->port); - addrlen = g_socket_address_get_native_size(socket_address); - - g_socket_address_to_native(socket_address, &addr, addrlen, &error); - if(error != NULL) { - purple_debug_info("proxy", "failed connnection : %s\n", error->message); - - g_error_free(error); - - return; - } - - if (connect_data->socket_type == SOCK_DGRAM) { - proxy_connect_udp_none(connect_data, &addr, addrlen); - - return; - } - - switch (purple_proxy_info_get_proxy_type(connect_data->gpi)) { - case PURPLE_PROXY_NONE: - proxy_connect_none(connect_data, &addr, addrlen); - break; - - case PURPLE_PROXY_HTTP: - proxy_connect_http(connect_data, &addr, addrlen); - break; - - case PURPLE_PROXY_SOCKS4: - proxy_connect_socks4(connect_data, &addr, addrlen); - break; - - case PURPLE_PROXY_SOCKS5: - case PURPLE_PROXY_TOR: - proxy_connect_socks5(connect_data, &addr, addrlen); - break; - - case PURPLE_PROXY_USE_ENVVAR: - proxy_connect_http(connect_data, &addr, addrlen); - break; - - default: - break; - } - - g_object_unref(G_OBJECT(socket_address)); -} - -static void -connection_host_resolved(GObject *source, GAsyncResult *res, gpointer data) { - PurpleProxyConnectData *connect_data = (PurpleProxyConnectData *)data; - GError *error = NULL; - GList *addresses = NULL; - - addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(source), - res, &error); - - if(G_IS_CANCELLABLE(connect_data->cancellable)) { - g_object_unref(G_OBJECT(connect_data->cancellable)); - - connect_data->cancellable = NULL; - } - - if (error != NULL) { - purple_proxy_connect_data_disconnect(connect_data, error->message); - - g_error_free(error); - - g_resolver_free_addresses(addresses); - - return; - } - - if (addresses == NULL) { - purple_proxy_connect_data_disconnect(connect_data, _("Unable to resolve hostname")); - - return; - } - - connect_data->hosts = addresses; - - try_connect(connect_data); -} - PurpleProxyInfo * purple_proxy_get_setup(PurpleAccount *account) { @@ -2444,84 +854,6 @@ purple_proxy_connect(void *handle, PurpleAccount *account, return connect_data; } -PurpleProxyConnectData * -purple_proxy_connect_udp(void *handle, PurpleAccount *account, - const char *host, int port, - PurpleProxyConnectFunction connect_cb, gpointer data) -{ - const char *connecthost = host; - int connectport = port; - PurpleProxyConnectData *connect_data; - GResolver *resolver; - - g_return_val_if_fail(host != NULL, NULL); - g_return_val_if_fail(port > 0, NULL); - g_return_val_if_fail(connect_cb != NULL, NULL); - - connect_data = g_new0(PurpleProxyConnectData, 1); - connect_data->fd = -1; - connect_data->socket_type = SOCK_DGRAM; - connect_data->handle = handle; - connect_data->connect_cb = connect_cb; - connect_data->data = data; - connect_data->host = g_strdup(host); - connect_data->port = port; - connect_data->gpi = purple_proxy_get_setup(account); - connect_data->account = account; - - if ((purple_proxy_info_get_proxy_type(connect_data->gpi) != PURPLE_PROXY_NONE) && - (purple_proxy_info_get_host(connect_data->gpi) == NULL || - purple_proxy_info_get_port(connect_data->gpi) <= 0)) { - - purple_notify_error(NULL, NULL, _("Invalid proxy settings"), - _("Either the host name or port number specified for " - "your given proxy type is invalid."), - purple_request_cpar_from_account(account)); - purple_proxy_connect_data_destroy(connect_data); - return NULL; - } - - switch (purple_proxy_info_get_proxy_type(connect_data->gpi)) - { - case PURPLE_PROXY_NONE: - break; - - case PURPLE_PROXY_HTTP: - case PURPLE_PROXY_SOCKS4: - case PURPLE_PROXY_SOCKS5: - case PURPLE_PROXY_TOR: - case PURPLE_PROXY_USE_ENVVAR: - purple_debug_info("proxy", "Ignoring Proxy type (%d) for UDP.\n", - purple_proxy_info_get_proxy_type(connect_data->gpi)); - break; - - default: - purple_debug_error("proxy", "Invalid Proxy type (%d) specified.\n", - purple_proxy_info_get_proxy_type(connect_data->gpi)); - purple_proxy_connect_data_destroy(connect_data); - return NULL; - } - - connect_data->cancellable = g_cancellable_new(); - - resolver = g_resolver_get_default(); - g_resolver_lookup_by_name_async(resolver, - connecthost, - connect_data->cancellable, - connection_host_resolved, - connect_data); - g_object_unref(resolver); - - if (connect_data->cancellable == NULL) { - purple_proxy_connect_data_destroy(connect_data); - return NULL; - } - - handles = g_slist_prepend(handles, connect_data); - - return connect_data; -} - static void socks5_proxy_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) { diff --git a/libpurple/proxy.h b/libpurple/proxy.h index 8ccefbe216..4810e51bc2 100644 --- a/libpurple/proxy.h +++ b/libpurple/proxy.h @@ -277,36 +277,6 @@ PurpleProxyConnectData *purple_proxy_connect(void *handle, PurpleProxyConnectFunction connect_cb, gpointer data); /** - * purple_proxy_connect_udp: - * @handle: A handle that should be associated with this - * connection attempt. The handle can be used - * to cancel the connection attempt using the - * purple_proxy_connect_cancel_with_handle() - * function. - * @account: The account making the connection. - * @host: The destination host. - * @port: The destination port. - * @connect_cb: (scope call): The function to call when the connection is - * established. If the connection failed then - * fd will be -1 and error message will be set - * to something descriptive (hopefully). - * @data: User-defined data. - * - * Makes a connection to the specified host and port. Note that this - * function name can be misleading--although it is called "proxy - * connect," it is used for establishing any outgoing UDP connection, - * whether through a proxy or not. - * - * Returns: NULL if there was an error, or a reference to an - * opaque data structure that can be used to cancel - * the pending connection, if needed. - */ -PurpleProxyConnectData *purple_proxy_connect_udp(void *handle, - PurpleAccount *account, - const char *host, int port, - PurpleProxyConnectFunction connect_cb, gpointer data); - -/** * purple_proxy_connect_socks5_account: * @handle: A handle that should be associated with this * connection attempt. The handle can be used |