Mercurial > pidgin
comparison src/proxy.c @ 7834:99ffabc6ce73
[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 <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Fri, 12 Dec 2003 00:14:40 +0000 |
parents | ac6b2b3a9a1f |
children | 58af482c89f7 |
comparison
equal
deleted
inserted
replaced
7833:ecb31b5d728d | 7834:99ffabc6ce73 |
---|---|
194 if (condition & GAIM_READ_COND) | 194 if (condition & GAIM_READ_COND) |
195 gaim_cond |= GAIM_INPUT_READ; | 195 gaim_cond |= GAIM_INPUT_READ; |
196 if (condition & GAIM_WRITE_COND) | 196 if (condition & GAIM_WRITE_COND) |
197 gaim_cond |= GAIM_INPUT_WRITE; | 197 gaim_cond |= GAIM_INPUT_WRITE; |
198 | 198 |
199 /* | 199 #if 0 |
200 gaim_debug(GAIM_DEBUG_MISC, "proxy", | 200 gaim_debug(GAIM_DEBUG_MISC, "proxy", |
201 "CLOSURE: callback for %d, fd is %d\n", | 201 "CLOSURE: callback for %d, fd is %d\n", |
202 closure->result, g_io_channel_unix_get_fd(source)); | 202 closure->result, g_io_channel_unix_get_fd(source)); |
203 */ | 203 #endif |
204 | 204 |
205 closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); | 205 closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); |
206 | 206 |
207 return TRUE; | 207 return TRUE; |
208 } | 208 } |
223 | 223 |
224 channel = g_io_channel_unix_new(source); | 224 channel = g_io_channel_unix_new(source); |
225 closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, | 225 closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, |
226 gaim_io_invoke, closure, gaim_io_destroy); | 226 gaim_io_invoke, closure, gaim_io_destroy); |
227 | 227 |
228 /* | 228 #if 0 |
229 gaim_debug(GAIM_DEBUG_MISC, "proxy", | 229 gaim_debug(GAIM_DEBUG_MISC, "proxy", |
230 "CLOSURE: adding input watcher %d for fd %d\n", | 230 "CLOSURE: adding input watcher %d for fd %d\n", |
231 closure->result, source); | 231 closure->result, source); |
232 */ | 232 #endif |
233 | 233 |
234 g_io_channel_unref(channel); | 234 g_io_channel_unref(channel); |
235 return closure->result; | 235 return closure->result; |
236 } | 236 } |
237 | 237 |
935 | 935 |
936 return TRUE; | 936 return TRUE; |
937 } | 937 } |
938 #endif | 938 #endif |
939 | 939 |
940 | |
941 static void | |
942 http_complete(struct PHB *phb, gint source) | |
943 { | |
944 gaim_debug(GAIM_DEBUG_INFO, "http proxy", "proxy connection established\n"); | |
945 if(!phb->account || phb->account->gc) | |
946 phb->func(phb->data, source, GAIM_INPUT_READ); | |
947 g_free(phb->host); | |
948 g_free(phb); | |
949 } | |
950 | |
951 | |
952 /* read the response to the CONNECT request, if we are requesting a non-port-80 tunnel */ | |
940 static void | 953 static void |
941 http_canread(gpointer data, gint source, GaimInputCondition cond) | 954 http_canread(gpointer data, gint source, GaimInputCondition cond) |
942 { | 955 { |
943 int nlc = 0; | 956 int nlc = 0; |
944 int pos = 0; | 957 int pos = 0; |
979 close(source); | 992 close(source); |
980 source=-1; | 993 source=-1; |
981 } | 994 } |
982 else if(status!=200) { | 995 else if(status!=200) { |
983 gaim_debug(GAIM_DEBUG_ERROR, "proxy", | 996 gaim_debug(GAIM_DEBUG_ERROR, "proxy", |
984 "Proxy server replied: (%s)\n", p); | 997 "Proxy server replied with:\n%s\n", p); |
985 close(source); | 998 close(source); |
986 source=-1; | 999 source = -1; |
987 } | 1000 |
988 | 1001 if ( status == 403 /* Forbidden */ ) |
989 if(!phb->account || phb->account->gc) | 1002 gaim_connection_error(phb->account->gc, _("Access denied: proxy server forbids port 80 tunnelling.")); |
990 phb->func(phb->data, source, GAIM_INPUT_READ); | 1003 else { |
991 g_free(phb->host); | 1004 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); |
992 g_free(phb); | 1005 gaim_connection_error(phb->account->gc, msg); |
1006 g_free(msg); | |
1007 } | |
1008 | |
1009 } else { | |
1010 http_complete(phb, source); | |
1011 } | |
1012 | |
993 return; | 1013 return; |
994 } | 1014 } |
995 | 1015 |
996 static void | 1016 static void |
997 http_canwrite(gpointer data, gint source, GaimInputCondition cond) | 1017 http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
1020 | 1040 |
1021 g_free(phb->host); | 1041 g_free(phb->host); |
1022 g_free(phb); | 1042 g_free(phb); |
1023 return; | 1043 return; |
1024 } | 1044 } |
1045 | |
1046 gaim_debug(GAIM_DEBUG_INFO, "proxy", "using CONNECT tunnelling for %s:%d\n", phb->host, phb->port); | |
1025 request_len = g_snprintf(request, sizeof(request), | 1047 request_len = g_snprintf(request, sizeof(request), |
1026 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", | 1048 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", |
1027 phb->host, phb->port, phb->host, phb->port); | 1049 phb->host, phb->port, phb->host, phb->port); |
1028 | 1050 |
1029 if (gaim_proxy_info_get_username(phb->gpi) != NULL) { | 1051 if (gaim_proxy_info_get_username(phb->gpi) != NULL) { |
1030 char *t1, *t2; | 1052 char *t1, *t2; |
1031 t1 = g_strdup_printf("%s:%s", | 1053 t1 = g_strdup_printf("%s:%s", |
1032 gaim_proxy_info_get_username(phb->gpi), | 1054 gaim_proxy_info_get_username(phb->gpi), |
1033 gaim_proxy_info_get_password(phb->gpi) ? | 1055 gaim_proxy_info_get_password(phb->gpi) ? |
1034 gaim_proxy_info_get_password(phb->gpi) : ""); | 1056 gaim_proxy_info_get_password(phb->gpi) : ""); |
1035 t2 = gaim_base64_encode(t1, strlen(t1)); | 1057 t2 = gaim_base64_encode(t1, strlen(t1)); |
1036 g_free(t1); | 1058 g_free(t1); |
1037 g_return_if_fail(request_len < sizeof(request)); | 1059 g_return_if_fail(request_len < sizeof(request)); |
1038 request_len += g_snprintf(request + request_len, | 1060 request_len += g_snprintf(request + request_len, |
1039 sizeof(request) - request_len, | 1061 sizeof(request) - request_len, |
1040 "Proxy-Authorization: Basic %s\r\n", t2); | 1062 "Proxy-Authorization: Basic %s\r\n", t2); |
1041 g_free(t2); | 1063 g_free(t2); |
1042 } | 1064 } |
1043 | 1065 |
1044 g_return_if_fail(request_len < sizeof(request)); | 1066 g_return_if_fail(request_len < sizeof(request)); |
1045 strcpy(request + request_len, "\r\n"); | 1067 strcpy(request + request_len, "\r\n"); |
1057 g_free(phb->host); | 1079 g_free(phb->host); |
1058 g_free(phb); | 1080 g_free(phb); |
1059 return; | 1081 return; |
1060 } | 1082 } |
1061 | 1083 |
1084 /* register the response handler for the CONNECT request */ | |
1062 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); | 1085 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); |
1063 } | 1086 } |
1064 | 1087 |
1065 static int | 1088 static int |
1066 proxy_connect_http(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) | 1089 proxy_connect_http(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) |
1081 | 1104 |
1082 if (connect(fd, addr, addrlen) < 0) { | 1105 if (connect(fd, addr, addrlen) < 0) { |
1083 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 1106 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
1084 gaim_debug(GAIM_DEBUG_WARNING, "http proxy", | 1107 gaim_debug(GAIM_DEBUG_WARNING, "http proxy", |
1085 "Connect would have blocked.\n"); | 1108 "Connect would have blocked.\n"); |
1086 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, | 1109 |
1087 http_canwrite, phb); | 1110 if (phb->port != 80) { |
1111 /* we need to do CONNECT first */ | |
1112 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, | |
1113 http_canwrite, phb); | |
1114 } else { | |
1115 http_complete(phb, fd); | |
1116 } | |
1088 } else { | 1117 } else { |
1089 close(fd); | 1118 close(fd); |
1090 return -1; | 1119 return -1; |
1091 } | 1120 } |
1092 } | 1121 } |