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 }