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 ||