Mercurial > pidgin.yaz
comparison src/proxy.c @ 9129:3e94a77ee0c7
[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 <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Sun, 30 May 2004 19:30:14 +0000 |
parents | 4b3e5a5063f9 |
children | 39155e87c470 |
comparison
equal
deleted
inserted
replaced
9128:b5c5c1d13783 | 9129:3e94a77ee0c7 |
---|---|
46 char *host; | 46 char *host; |
47 int port; | 47 int port; |
48 gint inpa; | 48 gint inpa; |
49 GaimProxyInfo *gpi; | 49 GaimProxyInfo *gpi; |
50 GaimAccount *account; | 50 GaimAccount *account; |
51 GSList *hosts; | |
51 }; | 52 }; |
53 | |
54 static void try_connect(struct PHB *); | |
52 | 55 |
53 const char* socks5errors[] = { | 56 const char* socks5errors[] = { |
54 "succeeded\n", | 57 "succeeded\n", |
55 "general SOCKS server failure\n", | 58 "general SOCKS server failure\n", |
56 "connection not allowed by ruleset\n", | 59 "connection not allowed by ruleset\n", |
240 if(kill(req->dns_pid, 0) != 0) { | 243 if(kill(req->dns_pid, 0) != 0) { |
241 gaim_debug(GAIM_DEBUG_WARNING, "dns", | 244 gaim_debug(GAIM_DEBUG_WARNING, "dns", |
242 "DNS child %d no longer exists\n", req->dns_pid); | 245 "DNS child %d no longer exists\n", req->dns_pid); |
243 return -1; | 246 return -1; |
244 } | 247 } |
245 | 248 |
246 /* Let's contact this lost child! */ | 249 /* Let's contact this lost child! */ |
247 rc = write(req->fd_in, dns_params, sizeof(*dns_params)); | 250 rc = write(req->fd_in, dns_params, sizeof(*dns_params)); |
248 if(rc<0) { | 251 if(rc<0) { |
249 gaim_debug(GAIM_DEBUG_ERROR, "dns", | 252 gaim_debug(GAIM_DEBUG_ERROR, "dns", |
250 "Unable to write to DNS child %d: %d\n", | 253 "Unable to write to DNS child %d: %d\n", |
251 req->dns_pid, strerror(errno)); | 254 req->dns_pid, strerror(errno)); |
252 close(req->fd_in); | 255 close(req->fd_in); |
253 return -1; | 256 return -1; |
254 } | 257 } |
255 | 258 |
256 g_return_val_if_fail(rc == sizeof(*dns_params), -1); | 259 g_return_val_if_fail(rc == sizeof(*dns_params), -1); |
257 | 260 |
258 /* Did you hear me? (This avoids some race conditions) */ | 261 /* Did you hear me? (This avoids some race conditions) */ |
259 rc = read(req->fd_out, &ch, 1); | 262 rc = read(req->fd_out, &ch, 1); |
260 if(rc != 1 || ch!='Y') { | 263 if(rc != 1 || ch!='Y') { |
261 gaim_debug(GAIM_DEBUG_WARNING, "dns", | 264 gaim_debug(GAIM_DEBUG_WARNING, "dns", |
262 "DNS child %d not responding. Killing it!\n", | 265 "DNS child %d not responding. Killing it!\n", |
366 | 369 |
367 /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */ | 370 /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */ |
368 | 371 |
369 req->callback(hosts, req->data, NULL); | 372 req->callback(hosts, req->data, NULL); |
370 | 373 |
371 while(hosts) { | |
372 hosts = g_slist_remove(hosts, hosts->data); | |
373 g_free(hosts->data); | |
374 hosts = g_slist_remove(hosts, hosts->data); | |
375 } | |
376 | |
377 release_dns_child(req); | 374 release_dns_child(req); |
378 } | 375 } |
379 | 376 |
380 static void trap_gdb_bug() | 377 static void trap_gdb_bug() |
381 { | 378 { |
422 | 419 |
423 int gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data) | 420 int gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data) |
424 { | 421 { |
425 pending_dns_request_t *req = NULL; | 422 pending_dns_request_t *req = NULL; |
426 dns_params_t dns_params; | 423 dns_params_t dns_params; |
427 | 424 |
428 strncpy(dns_params.hostname, hostname, sizeof(dns_params.hostname)-1); | 425 strncpy(dns_params.hostname, hostname, sizeof(dns_params.hostname)-1); |
429 dns_params.hostname[sizeof(dns_params.hostname)-1] = '\0'; | 426 dns_params.hostname[sizeof(dns_params.hostname)-1] = '\0'; |
430 dns_params.port = port; | 427 dns_params.port = port; |
431 | 428 |
432 /* Is there a free available child? */ | 429 /* Is there a free available child? */ |
433 while(free_dns_children && !req) { | 430 while(free_dns_children && !req) { |
434 GSList *l = free_dns_children; | 431 GSList *l = free_dns_children; |
435 free_dns_children = g_slist_remove_link(free_dns_children, l); | 432 free_dns_children = g_slist_remove_link(free_dns_children, l); |
436 req = l->data; | 433 req = l->data; |
437 g_slist_free(l); | 434 g_slist_free(l); |
438 | 435 |
439 if(send_dns_request_to_child(req, &dns_params) != 0) { | 436 if(send_dns_request_to_child(req, &dns_params) != 0) { |
440 req_free(req); | 437 req_free(req); |
441 req = NULL; | 438 req = NULL; |
442 continue; | 439 continue; |
443 } | 440 } |
444 | 441 |
445 } | 442 } |
446 | 443 |
447 if(!req) { | 444 if(!req) { |
448 int child_out[2], child_in[2]; | 445 int child_out[2], child_in[2]; |
449 | 446 |
692 if (ret < 0 || error != 0) { | 689 if (ret < 0 || error != 0) { |
693 if(ret!=0) error = errno; | 690 if(ret!=0) error = errno; |
694 close(source); | 691 close(source); |
695 gaim_input_remove(phb->inpa); | 692 gaim_input_remove(phb->inpa); |
696 | 693 |
697 if (phb->account == NULL || | |
698 gaim_account_get_connection(phb->account) != NULL) { | |
699 | |
700 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
701 } | |
702 | |
703 g_free(phb->host); | |
704 g_free(phb); | |
705 | |
706 gaim_debug(GAIM_DEBUG_ERROR, "proxy", | 694 gaim_debug(GAIM_DEBUG_ERROR, "proxy", |
707 "getsockopt SO_ERROR check: %s\n", strerror(error)); | 695 "getsockopt SO_ERROR check: %s\n", strerror(error)); |
696 | |
697 try_connect(phb); | |
708 return; | 698 return; |
709 } | 699 } |
710 | 700 |
711 fcntl(source, F_SETFL, 0); | 701 fcntl(source, F_SETFL, 0); |
712 gaim_input_remove(phb->inpa); | 702 gaim_input_remove(phb->inpa); |
791 | 781 |
792 static void | 782 static void |
793 http_complete(struct PHB *phb, gint source) | 783 http_complete(struct PHB *phb, gint source) |
794 { | 784 { |
795 gaim_debug(GAIM_DEBUG_INFO, "http proxy", "proxy connection established\n"); | 785 gaim_debug(GAIM_DEBUG_INFO, "http proxy", "proxy connection established\n"); |
796 if(!phb->account || phb->account->gc) | 786 if(source < 0) { |
787 try_connect(phb); | |
788 } else if(!phb->account || phb->account->gc) { | |
797 phb->func(phb->data, source, GAIM_INPUT_READ); | 789 phb->func(phb->data, source, GAIM_INPUT_READ); |
798 g_free(phb->host); | 790 g_free(phb->host); |
799 g_free(phb); | 791 g_free(phb); |
792 } | |
800 } | 793 } |
801 | 794 |
802 | 795 |
803 /* read the response to the CONNECT request, if we are requesting a non-port-80 tunnel */ | 796 /* read the response to the CONNECT request, if we are requesting a non-port-80 tunnel */ |
804 static void | 797 static void |
834 status = strtol(p, &p, 10); | 827 status = strtol(p, &p, 10); |
835 error = (*p!=' '); | 828 error = (*p!=' '); |
836 } | 829 } |
837 } | 830 } |
838 } | 831 } |
839 | 832 |
840 if(error) { | 833 if(error) { |
841 gaim_debug(GAIM_DEBUG_ERROR, "proxy", | 834 gaim_debug(GAIM_DEBUG_ERROR, "proxy", |
842 "Unable to parse proxy's response: %s\n", inputline); | 835 "Unable to parse proxy's response: %s\n", inputline); |
843 close(source); | 836 close(source); |
844 source=-1; | 837 source=-1; |
845 } | 838 } |
846 else if(status!=200) { | 839 else if(status!=200) { |
847 gaim_debug(GAIM_DEBUG_ERROR, "proxy", | 840 gaim_debug(GAIM_DEBUG_ERROR, "proxy", |
848 "Proxy server replied with:\n%s\n", p); | 841 "Proxy server replied with:\n%s\n", p); |
849 close(source); | 842 close(source); |
850 source = -1; | 843 source = -1; |
851 | 844 |
845 /* XXX: why in the hell are we calling gaim_connection_error() here? */ | |
852 if ( status == 403 /* Forbidden */ ) { | 846 if ( status == 403 /* Forbidden */ ) { |
853 gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port); | 847 gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port); |
854 gaim_connection_error(phb->account->gc, msg); | 848 gaim_connection_error(phb->account->gc, msg); |
855 g_free(msg); | 849 g_free(msg); |
856 } else { | 850 } else { |
857 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | 851 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); |
858 gaim_connection_error(phb->account->gc, msg); | 852 gaim_connection_error(phb->account->gc, msg); |
859 g_free(msg); | 853 g_free(msg); |
860 } | 854 } |
861 | 855 |
862 } else { | 856 } else { |
863 http_complete(phb, source); | 857 http_complete(phb, source); |
864 } | 858 } |
865 | 859 |
866 return; | 860 return; |
867 } | 861 } |
868 | 862 |
869 static void | 863 static void |
870 http_canwrite(gpointer data, gint source, GaimInputCondition cond) | 864 http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
883 len = sizeof(error); | 877 len = sizeof(error); |
884 | 878 |
885 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 879 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
886 close(source); | 880 close(source); |
887 | 881 |
888 if (phb->account == NULL || | 882 try_connect(phb); |
889 gaim_account_get_connection(phb->account) != NULL) { | |
890 | |
891 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
892 } | |
893 | |
894 g_free(phb->host); | |
895 g_free(phb); | |
896 return; | 883 return; |
897 } | 884 } |
898 | 885 |
899 gaim_debug(GAIM_DEBUG_INFO, "proxy", "using CONNECT tunnelling for %s:%d\n", phb->host, phb->port); | 886 gaim_debug(GAIM_DEBUG_INFO, "proxy", "using CONNECT tunnelling for %s:%d\n", phb->host, phb->port); |
900 request_len = g_snprintf(request, sizeof(request), | 887 request_len = g_snprintf(request, sizeof(request), |
921 request_len += 2; | 908 request_len += 2; |
922 | 909 |
923 if (write(source, request, request_len) < 0) { | 910 if (write(source, request, request_len) < 0) { |
924 close(source); | 911 close(source); |
925 | 912 |
926 if (phb->account == NULL || | 913 try_connect(phb); |
927 gaim_account_get_connection(phb->account) != NULL) { | |
928 | |
929 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
930 } | |
931 | |
932 g_free(phb->host); | |
933 g_free(phb); | |
934 return; | 914 return; |
935 } | 915 } |
936 | 916 |
937 /* register the response handler for the CONNECT request */ | 917 /* register the response handler for the CONNECT request */ |
938 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); | 918 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); |
1013 return; | 993 return; |
1014 } | 994 } |
1015 | 995 |
1016 close(source); | 996 close(source); |
1017 | 997 |
1018 if (phb->account == NULL || | 998 try_connect(phb); |
1019 gaim_account_get_connection(phb->account) != NULL) { | |
1020 | |
1021 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1022 } | |
1023 | |
1024 g_free(phb->host); | |
1025 g_free(phb); | |
1026 } | 999 } |
1027 | 1000 |
1028 static void | 1001 static void |
1029 s4_canwrite(gpointer data, gint source, GaimInputCondition cond) | 1002 s4_canwrite(gpointer data, gint source, GaimInputCondition cond) |
1030 { | 1003 { |
1042 len = sizeof(error); | 1015 len = sizeof(error); |
1043 | 1016 |
1044 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1017 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1045 close(source); | 1018 close(source); |
1046 | 1019 |
1047 if (phb->account == NULL || | 1020 try_connect(phb); |
1048 gaim_account_get_connection(phb->account) != NULL) { | |
1049 | |
1050 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1051 } | |
1052 | |
1053 g_free(phb->host); | |
1054 g_free(phb); | |
1055 return; | 1021 return; |
1056 } | 1022 } |
1057 fcntl(source, F_SETFL, 0); | 1023 fcntl(source, F_SETFL, 0); |
1058 | 1024 |
1059 /* XXX does socks4 not support host name lookups by the proxy? */ | 1025 /* XXX does socks4 not support host name lookups by the proxy? */ |
1060 if (!(hp = gethostbyname(phb->host))) { | 1026 if (!(hp = gethostbyname(phb->host))) { |
1061 close(source); | 1027 close(source); |
1062 | 1028 |
1063 if (phb->account == NULL || | 1029 try_connect(phb); |
1064 gaim_account_get_connection(phb->account) != NULL) { | |
1065 | |
1066 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1067 } | |
1068 | |
1069 g_free(phb->host); | |
1070 g_free(phb); | |
1071 return; | 1030 return; |
1072 } | 1031 } |
1073 | 1032 |
1074 packet[0] = 4; | 1033 packet[0] = 4; |
1075 packet[1] = 1; | 1034 packet[1] = 1; |
1082 packet[8] = 0; | 1041 packet[8] = 0; |
1083 | 1042 |
1084 if (write(source, packet, 9) != 9) { | 1043 if (write(source, packet, 9) != 9) { |
1085 close(source); | 1044 close(source); |
1086 | 1045 |
1087 if (phb->account == NULL || | 1046 try_connect(phb); |
1088 gaim_account_get_connection(phb->account) != NULL) { | |
1089 | |
1090 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1091 } | |
1092 | |
1093 g_free(phb->host); | |
1094 g_free(phb); | |
1095 return; | 1047 return; |
1096 } | 1048 } |
1097 | 1049 |
1098 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s4_canread, phb); | 1050 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s4_canread, phb); |
1099 } | 1051 } |
1156 | 1108 |
1157 if (read(source, buf, 4) < 4) { | 1109 if (read(source, buf, 4) < 4) { |
1158 gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy", "or not...\n"); | 1110 gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy", "or not...\n"); |
1159 close(source); | 1111 close(source); |
1160 | 1112 |
1161 if (phb->account == NULL || | 1113 try_connect(phb); |
1162 gaim_account_get_connection(phb->account) != NULL) { | |
1163 | |
1164 phb->func(phb->data, source, GAIM_INPUT_READ); | |
1165 } | |
1166 | |
1167 g_free(phb->host); | |
1168 g_free(phb); | |
1169 return; | 1114 return; |
1170 } | 1115 } |
1171 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { | 1116 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { |
1172 if ((buf[0] == 0x05) && (buf[1] < 0x09)) | 1117 if ((buf[0] == 0x05) && (buf[1] < 0x09)) |
1173 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", socks5errors[buf[1]]); | 1118 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", socks5errors[buf[1]]); |
1174 else | 1119 else |
1175 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Bad data.\n"); | 1120 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Bad data.\n"); |
1176 close(source); | 1121 close(source); |
1177 | 1122 |
1178 if (phb->account == NULL || | 1123 try_connect(phb); |
1179 gaim_account_get_connection(phb->account) != NULL) { | |
1180 | |
1181 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1182 } | |
1183 | |
1184 g_free(phb->host); | |
1185 g_free(phb); | |
1186 return; | 1124 return; |
1187 } | 1125 } |
1188 | 1126 |
1189 /* Skip past BND.ADDR */ | 1127 /* Skip past BND.ADDR */ |
1190 switch(buf[3]) { | 1128 switch(buf[3]) { |
1232 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; | 1170 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; |
1233 | 1171 |
1234 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { | 1172 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { |
1235 close(source); | 1173 close(source); |
1236 | 1174 |
1237 if (phb->account == NULL || | 1175 try_connect(phb); |
1238 gaim_account_get_connection(phb->account) != NULL) { | |
1239 | |
1240 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1241 } | |
1242 | |
1243 g_free(phb->host); | |
1244 g_free(phb); | |
1245 return; | 1176 return; |
1246 } | 1177 } |
1247 | 1178 |
1248 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb); | 1179 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb); |
1249 } | 1180 } |
1258 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got auth response.\n"); | 1189 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got auth response.\n"); |
1259 | 1190 |
1260 if (read(source, buf, 2) < 2) { | 1191 if (read(source, buf, 2) < 2) { |
1261 close(source); | 1192 close(source); |
1262 | 1193 |
1263 if (phb->account == NULL || | 1194 try_connect(phb); |
1264 gaim_account_get_connection(phb->account) != NULL) { | |
1265 | |
1266 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1267 } | |
1268 | |
1269 g_free(phb->host); | |
1270 g_free(phb); | |
1271 return; | 1195 return; |
1272 } | 1196 } |
1273 | 1197 |
1274 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { | 1198 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { |
1275 close(source); | 1199 close(source); |
1276 | 1200 |
1277 if (phb->account == NULL || | 1201 try_connect(phb); |
1278 gaim_account_get_connection(phb->account) != NULL) { | |
1279 | |
1280 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1281 } | |
1282 | |
1283 g_free(phb->host); | |
1284 g_free(phb); | |
1285 return; | 1202 return; |
1286 } | 1203 } |
1287 | 1204 |
1288 s5_sendconnect(phb, source); | 1205 s5_sendconnect(phb, source); |
1289 } | 1206 } |
1298 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read.\n"); | 1215 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read.\n"); |
1299 | 1216 |
1300 if (read(source, buf, 2) < 2) { | 1217 if (read(source, buf, 2) < 2) { |
1301 close(source); | 1218 close(source); |
1302 | 1219 |
1303 if (phb->account == NULL || | 1220 try_connect(phb); |
1304 gaim_account_get_connection(phb->account) != NULL) { | |
1305 | |
1306 phb->func(phb->data, source, GAIM_INPUT_READ); | |
1307 } | |
1308 | |
1309 g_free(phb->host); | |
1310 g_free(phb); | |
1311 return; | 1221 return; |
1312 } | 1222 } |
1313 | 1223 |
1314 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { | 1224 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { |
1315 close(source); | 1225 close(source); |
1316 | 1226 |
1317 if (phb->account == NULL || | 1227 try_connect(phb); |
1318 gaim_account_get_connection(phb->account) != NULL) { | |
1319 | |
1320 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1321 } | |
1322 | |
1323 g_free(phb->host); | |
1324 g_free(phb); | |
1325 return; | 1228 return; |
1326 } | 1229 } |
1327 | 1230 |
1328 if (buf[1] == 0x02) { | 1231 if (buf[1] == 0x02) { |
1329 unsigned int i, j; | 1232 unsigned int i, j; |
1330 | 1233 |
1331 i = strlen(gaim_proxy_info_get_username(phb->gpi)); | 1234 i = strlen(gaim_proxy_info_get_username(phb->gpi)); |
1332 j = strlen(gaim_proxy_info_get_password(phb->gpi)); | 1235 j = strlen(gaim_proxy_info_get_password(phb->gpi)); |
1333 | 1236 |
1334 buf[0] = 0x01; /* version 1 */ | 1237 buf[0] = 0x01; /* version 1 */ |
1335 buf[1] = i; | 1238 buf[1] = i; |
1338 memcpy(buf + 2 + i + 1, gaim_proxy_info_get_password(phb->gpi), j); | 1241 memcpy(buf + 2 + i + 1, gaim_proxy_info_get_password(phb->gpi), j); |
1339 | 1242 |
1340 if (write(source, buf, 3 + i + j) < 3 + i + j) { | 1243 if (write(source, buf, 3 + i + j) < 3 + i + j) { |
1341 close(source); | 1244 close(source); |
1342 | 1245 |
1343 if (phb->account == NULL || | 1246 try_connect(phb); |
1344 gaim_account_get_connection(phb->account) != NULL) { | |
1345 | |
1346 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1347 } | |
1348 | |
1349 g_free(phb->host); | |
1350 g_free(phb); | |
1351 return; | 1247 return; |
1352 } | 1248 } |
1353 | 1249 |
1354 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_readauth, phb); | 1250 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_readauth, phb); |
1355 } | 1251 } |
1373 gaim_input_remove(phb->inpa); | 1269 gaim_input_remove(phb->inpa); |
1374 | 1270 |
1375 len = sizeof(error); | 1271 len = sizeof(error); |
1376 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1272 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1377 close(source); | 1273 close(source); |
1378 if (phb->account == NULL || | 1274 |
1379 gaim_account_get_connection(phb->account) != NULL) { | 1275 try_connect(phb); |
1380 | |
1381 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1382 } | |
1383 | |
1384 g_free(phb->host); | |
1385 g_free(phb); | |
1386 return; | 1276 return; |
1387 } | 1277 } |
1388 fcntl(source, F_SETFL, 0); | 1278 fcntl(source, F_SETFL, 0); |
1389 | 1279 |
1390 i = 0; | 1280 i = 0; |
1404 | 1294 |
1405 if (write(source, buf, i) < i) { | 1295 if (write(source, buf, i) < i) { |
1406 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Unable to write\n"); | 1296 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Unable to write\n"); |
1407 close(source); | 1297 close(source); |
1408 | 1298 |
1409 if (phb->account == NULL || | 1299 try_connect(phb); |
1410 gaim_account_get_connection(phb->account) != NULL) { | |
1411 | |
1412 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1413 } | |
1414 | |
1415 g_free(phb->host); | |
1416 g_free(phb); | |
1417 return; | 1300 return; |
1418 } | 1301 } |
1419 | 1302 |
1420 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread, phb); | 1303 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread, phb); |
1421 } | 1304 } |
1467 } | 1350 } |
1468 | 1351 |
1469 return fd; | 1352 return fd; |
1470 } | 1353 } |
1471 | 1354 |
1355 static void try_connect(struct PHB *phb) | |
1356 { | |
1357 size_t addrlen; | |
1358 struct sockaddr *addr; | |
1359 int ret = -1; | |
1360 | |
1361 while (phb->hosts) { | |
1362 addrlen = GPOINTER_TO_INT(phb->hosts->data); | |
1363 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | |
1364 addr = phb->hosts->data; | |
1365 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | |
1366 | |
1367 switch (gaim_proxy_info_get_type(phb->gpi)) { | |
1368 case GAIM_PROXY_NONE: | |
1369 ret = proxy_connect_none(phb, addr, addrlen); | |
1370 break; | |
1371 | |
1372 case GAIM_PROXY_HTTP: | |
1373 ret = proxy_connect_http(phb, addr, addrlen); | |
1374 break; | |
1375 | |
1376 case GAIM_PROXY_SOCKS4: | |
1377 ret = proxy_connect_socks4(phb, addr, addrlen); | |
1378 break; | |
1379 | |
1380 case GAIM_PROXY_SOCKS5: | |
1381 ret = proxy_connect_socks5(phb, addr, addrlen); | |
1382 break; | |
1383 | |
1384 case GAIM_PROXY_USE_ENVVAR: | |
1385 ret = proxy_connect_http(phb, addr, addrlen); | |
1386 break; | |
1387 | |
1388 default: | |
1389 break; | |
1390 } | |
1391 | |
1392 g_free(addr); | |
1393 | |
1394 if (ret > 0) | |
1395 break; | |
1396 } | |
1397 | |
1398 if (ret < 0) { | |
1399 if (phb->account == NULL || | |
1400 gaim_account_get_connection(phb->account) != NULL) { | |
1401 | |
1402 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1403 } | |
1404 | |
1405 g_free(phb->host); | |
1406 g_free(phb); | |
1407 } | |
1408 } | |
1409 | |
1472 static void | 1410 static void |
1473 connection_host_resolved(GSList *hosts, gpointer data, | 1411 connection_host_resolved(GSList *hosts, gpointer data, |
1474 const char *error_message) | 1412 const char *error_message) |
1475 { | 1413 { |
1476 struct PHB *phb = (struct PHB*)data; | 1414 struct PHB *phb = (struct PHB*)data; |
1477 size_t addrlen; | 1415 |
1478 struct sockaddr *addr; | 1416 phb->hosts = hosts; |
1479 int ret = -1; | 1417 |
1480 | 1418 try_connect(phb); |
1481 while (hosts) { | |
1482 addrlen = GPOINTER_TO_INT(hosts->data); | |
1483 hosts = hosts->next; | |
1484 addr = hosts->data; | |
1485 hosts = hosts->next; | |
1486 | |
1487 switch (gaim_proxy_info_get_type(phb->gpi)) | |
1488 { | |
1489 case GAIM_PROXY_NONE: | |
1490 ret = proxy_connect_none(phb, addr, addrlen); | |
1491 break; | |
1492 | |
1493 case GAIM_PROXY_HTTP: | |
1494 ret = proxy_connect_http(phb, addr, addrlen); | |
1495 break; | |
1496 | |
1497 case GAIM_PROXY_SOCKS4: | |
1498 ret = proxy_connect_socks4(phb, addr, addrlen); | |
1499 break; | |
1500 | |
1501 case GAIM_PROXY_SOCKS5: | |
1502 ret = proxy_connect_socks5(phb, addr, addrlen); | |
1503 break; | |
1504 | |
1505 case GAIM_PROXY_USE_ENVVAR: | |
1506 ret = proxy_connect_http(phb, addr, addrlen); | |
1507 break; | |
1508 | |
1509 default: | |
1510 break; | |
1511 } | |
1512 | |
1513 if (ret > 0) | |
1514 break; | |
1515 } | |
1516 | |
1517 if (ret < 0) { | |
1518 if (phb->account == NULL || | |
1519 gaim_account_get_connection(phb->account) != NULL) { | |
1520 | |
1521 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
1522 } | |
1523 | |
1524 g_free(phb->host); | |
1525 g_free(phb); | |
1526 } | |
1527 } | 1419 } |
1528 | 1420 |
1529 int | 1421 int |
1530 gaim_proxy_connect(GaimAccount *account, const char *host, int port, | 1422 gaim_proxy_connect(GaimAccount *account, const char *host, int port, |
1531 GaimInputFunction func, gpointer data) | 1423 GaimInputFunction func, gpointer data) |
1557 (tmp = g_getenv("http_proxy")) != NULL || | 1449 (tmp = g_getenv("http_proxy")) != NULL || |
1558 (tmp= g_getenv("HTTPPROXY")) != NULL) { | 1450 (tmp= g_getenv("HTTPPROXY")) != NULL) { |
1559 char *proxyhost,*proxypath; | 1451 char *proxyhost,*proxypath; |
1560 int proxyport; | 1452 int proxyport; |
1561 | 1453 |
1562 /* http_proxy-format: | 1454 /* http_proxy-format: |
1563 * export http_proxy="http://your.proxy.server:port/" | 1455 * export http_proxy="http://your.proxy.server:port/" |
1564 */ | 1456 */ |
1565 if(gaim_url_parse(tmp, &proxyhost, &proxyport, &proxypath)) { | 1457 if(gaim_url_parse(tmp, &proxyhost, &proxyport, &proxypath)) { |
1566 gaim_proxy_info_set_host(phb->gpi, proxyhost); | 1458 gaim_proxy_info_set_host(phb->gpi, proxyhost); |
1567 g_free(proxyhost); | 1459 g_free(proxyhost); |
1568 g_free(proxypath); | 1460 g_free(proxypath); |
1569 | 1461 |
1570 /* only for backward compatibility */ | 1462 /* only for backward compatibility */ |
1571 if (proxyport == 80 && | 1463 if (proxyport == 80 && |
1572 ((tmp = g_getenv("HTTP_PROXY_PORT")) != NULL || | 1464 ((tmp = g_getenv("HTTP_PROXY_PORT")) != NULL || |
1573 (tmp = g_getenv("http_proxy_port")) != NULL || | 1465 (tmp = g_getenv("http_proxy_port")) != NULL || |
1574 (tmp = g_getenv("HTTPPROXYPORT")) != NULL)) | 1466 (tmp = g_getenv("HTTPPROXYPORT")) != NULL)) |
1575 proxyport = atoi(tmp); | 1467 proxyport = atoi(tmp); |
1576 | 1468 |
1577 gaim_proxy_info_set_port(phb->gpi, proxyport); | 1469 gaim_proxy_info_set_port(phb->gpi, proxyport); |
1578 } | 1470 } |
1579 } | 1471 } |
1580 | 1472 |
1581 if ((tmp = g_getenv("HTTP_PROXY_USER")) != NULL || | 1473 if ((tmp = g_getenv("HTTP_PROXY_USER")) != NULL || |