# HG changeset patch # User Christian Hammond # Date 1071188080 0 # Node ID 99ffabc6ce736742071e95aae0fa0c6c262ef74f # Parent ecb31b5d728d527681bffa88a667a3b7a1e709c0 [gaim-migrate @ 8487] This patch from Mike Hearn should fix HTTP proxy support for MSN, and provides another step toward the MSN HTTP access method working. The HTTP proxy may need testing from other people, but looks like it shouldn't give any problems. committer: Tailor Script diff -r ecb31b5d728d -r 99ffabc6ce73 plugins/ssl/ssl-gnutls.c --- a/plugins/ssl/ssl-gnutls.c Thu Dec 11 19:28:00 2003 +0000 +++ b/plugins/ssl/ssl-gnutls.c Fri Dec 12 00:14:40 2003 +0000 @@ -88,7 +88,14 @@ gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(source)); gaim_debug_info("gnutls", "Handshaking\n"); - ret = gnutls_handshake(gnutls_data->session); + + do + { + ret = gnutls_handshake(gnutls_data->session); + } + while ((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)); + + gaim_debug_info("gnutls", "Handshake complete\n"); if (ret < 0) { @@ -127,10 +134,17 @@ GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc); int s; - s = gnutls_record_recv(gnutls_data->session, data, len); + do + { + s = gnutls_record_recv(gnutls_data->session, data, len); + } + while ((s == GNUTLS_E_AGAIN) || (s == GNUTLS_E_INTERRUPTED)); if (s < 0) + { + gaim_debug_error("gnutls", "receive failed: %d\n", s); s = 0; + } return s; } diff -r ecb31b5d728d -r 99ffabc6ce73 src/protocols/msn/httpmethod.c --- a/src/protocols/msn/httpmethod.c Thu Dec 11 19:28:00 2003 +0000 +++ b/src/protocols/msn/httpmethod.c Fri Dec 12 00:14:40 2003 +0000 @@ -50,9 +50,10 @@ { MsnServConn *servconn = data; +#if 0 gaim_debug_info("msn", "Polling server %s.\n", servconn->http_data->gateway_ip); - +#endif msn_http_servconn_poll(servconn); servconn->http_data->timer = 0; @@ -82,10 +83,11 @@ msn_http_servconn_write(MsnServConn *servconn, const char *buf, size_t size, const char *server_type) { - size_t s; + size_t s, needed; char *params; char *temp; gboolean first; + int res; /* result of the write operation */ g_return_val_if_fail(servconn != NULL, 0); g_return_val_if_fail(buf != NULL, 0); @@ -143,7 +145,9 @@ "Content-Length: %d\r\n" "\r\n" "%s", - servconn->http_data->gateway_ip, + ((strcmp(server_type, "SB") == 0) && first + ? "gateway.messenger.hotmail.com" + : servconn->http_data->gateway_ip), params, servconn->http_data->gateway_ip, (int)size, @@ -151,12 +155,26 @@ g_free(params); -#if 0 - gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp); +#if 1 + gaim_debug_misc("msn", "Writing HTTP to fd %d: {%s}\n", + servconn->fd, temp); #endif - s = write(servconn->fd, temp, strlen(temp)); - + s = 0; + needed = strlen(temp); + + do { + res = write(servconn->fd, temp, needed); + if (res >= 0) + s += res; + else if (errno != EAGAIN) { + char *msg = g_strdup_printf("Unable to write to MSN server via HTTP (error %d)", errno); + gaim_connection_error(servconn->session->account->gc, msg); + g_free(msg); + return -1; + } + } while (s < needed); + g_free(temp); servconn->http_data->waiting_response = TRUE; @@ -234,6 +252,9 @@ g_return_val_if_fail(ret_size != NULL, FALSE); g_return_val_if_fail(error != NULL, FALSE); +#if 0 + gaim_debug_info("msn", "parsing data {%s} from fd %d\n", buf, servconn->fd); +#endif servconn->http_data->waiting_response = FALSE; gc = gaim_account_get_connection(servconn->session->account); @@ -244,12 +265,12 @@ *error = FALSE; /* First, some tests to see if we have a full block of stuff. */ - - if (strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0 && - strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0) + if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) && + (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) && + ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) && + (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0))) { *error = TRUE; - return FALSE; } diff -r ecb31b5d728d -r 99ffabc6ce73 src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Thu Dec 11 19:28:00 2003 +0000 +++ b/src/protocols/msn/msn.c Fri Dec 12 00:14:40 2003 +0000 @@ -463,6 +463,8 @@ { http_method = TRUE; + gaim_debug(GAIM_DEBUG_INFO, "msn", "using http method\n"); + server = "gateway.messenger.hotmail.com"; port = 80; } @@ -1661,12 +1663,10 @@ prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); -#if 0 option = gaim_account_option_bool_new(_("Use HTTP Method"), "http_method", FALSE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); -#endif my_protocol = plugin; diff -r ecb31b5d728d -r 99ffabc6ce73 src/proxy.c --- a/src/proxy.c Thu Dec 11 19:28:00 2003 +0000 +++ b/src/proxy.c Fri Dec 12 00:14:40 2003 +0000 @@ -196,11 +196,11 @@ if (condition & GAIM_WRITE_COND) gaim_cond |= GAIM_INPUT_WRITE; - /* +#if 0 gaim_debug(GAIM_DEBUG_MISC, "proxy", "CLOSURE: callback for %d, fd is %d\n", closure->result, g_io_channel_unix_get_fd(source)); - */ +#endif closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); @@ -225,11 +225,11 @@ closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, gaim_io_invoke, closure, gaim_io_destroy); - /* +#if 0 gaim_debug(GAIM_DEBUG_MISC, "proxy", "CLOSURE: adding input watcher %d for fd %d\n", closure->result, source); - */ +#endif g_io_channel_unref(channel); return closure->result; @@ -937,6 +937,19 @@ } #endif + +static void +http_complete(struct PHB *phb, gint source) +{ + gaim_debug(GAIM_DEBUG_INFO, "http proxy", "proxy connection established\n"); + if(!phb->account || phb->account->gc) + phb->func(phb->data, source, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); +} + + +/* read the response to the CONNECT request, if we are requesting a non-port-80 tunnel */ static void http_canread(gpointer data, gint source, GaimInputCondition cond) { @@ -981,15 +994,22 @@ } else if(status!=200) { gaim_debug(GAIM_DEBUG_ERROR, "proxy", - "Proxy server replied: (%s)\n", p); - close(source); - source=-1; + "Proxy server replied with:\n%s\n", p); + close(source); + source = -1; + + if ( status == 403 /* Forbidden */ ) + gaim_connection_error(phb->account->gc, _("Access denied: proxy server forbids port 80 tunnelling.")); + else { + char *msg = g_strdup_printf(_("Proxy connection error %d"), status); + gaim_connection_error(phb->account->gc, msg); + g_free(msg); + } + + } else { + http_complete(phb, source); } - - if(!phb->account || phb->account->gc) - phb->func(phb->data, source, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); + return; } @@ -1022,22 +1042,24 @@ g_free(phb); return; } + + gaim_debug(GAIM_DEBUG_INFO, "proxy", "using CONNECT tunnelling for %s:%d\n", phb->host, phb->port); request_len = g_snprintf(request, sizeof(request), - "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", - phb->host, phb->port, phb->host, phb->port); + "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", + phb->host, phb->port, phb->host, phb->port); if (gaim_proxy_info_get_username(phb->gpi) != NULL) { char *t1, *t2; t1 = g_strdup_printf("%s:%s", - gaim_proxy_info_get_username(phb->gpi), - gaim_proxy_info_get_password(phb->gpi) ? - gaim_proxy_info_get_password(phb->gpi) : ""); + gaim_proxy_info_get_username(phb->gpi), + gaim_proxy_info_get_password(phb->gpi) ? + gaim_proxy_info_get_password(phb->gpi) : ""); t2 = gaim_base64_encode(t1, strlen(t1)); g_free(t1); g_return_if_fail(request_len < sizeof(request)); request_len += g_snprintf(request + request_len, - sizeof(request) - request_len, - "Proxy-Authorization: Basic %s\r\n", t2); + sizeof(request) - request_len, + "Proxy-Authorization: Basic %s\r\n", t2); g_free(t2); } @@ -1059,6 +1081,7 @@ return; } + /* register the response handler for the CONNECT request */ phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); } @@ -1083,8 +1106,14 @@ if ((errno == EINPROGRESS) || (errno == EINTR)) { gaim_debug(GAIM_DEBUG_WARNING, "http proxy", "Connect would have blocked.\n"); - phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, - http_canwrite, phb); + + if (phb->port != 80) { + /* we need to do CONNECT first */ + phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, + http_canwrite, phb); + } else { + http_complete(phb, fd); + } } else { close(fd); return -1;