| 263 #else |
264 #else |
| 264 hstrerror(err), |
265 hstrerror(err), |
| 265 #endif |
266 #endif |
| 266 req->dns_pid); |
267 req->dns_pid); |
| 267 debug_printf("%s\n",message); |
268 debug_printf("%s\n",message); |
| 268 req->callback(NULL, 0, req->data, message); |
269 req->callback(NULL, req->data, message); |
| 269 release_dns_child(req); |
270 release_dns_child(req); |
| 270 return; |
271 return; |
| 271 } |
272 } |
| 272 if(rc>0) { |
273 if(rc>0) { |
| 273 rc=read(req->fd_out, &addrlen, sizeof(addrlen)); |
274 while(rc > 0) { |
| 274 if(rc>0) { |
275 rc=read(req->fd_out, &addrlen, sizeof(addrlen)); |
| 275 addr=g_malloc(addrlen); |
276 if(rc>0 && addrlen > 0) { |
| 276 rc=read(req->fd_out, addr, addrlen); |
277 addr=g_malloc(addrlen); |
| 277 } |
278 rc=read(req->fd_out, addr, addrlen); |
| 278 } |
279 hosts = g_slist_append(hosts, GINT_TO_POINTER(addrlen)); |
| 279 if(rc==-1) { |
280 hosts = g_slist_append(hosts, addr); |
| |
281 } else { |
| |
282 break; |
| |
283 } |
| |
284 } |
| |
285 } else if(rc==-1) { |
| 280 char message[1024]; |
286 char message[1024]; |
| 281 g_snprintf(message, sizeof(message), "Error reading from DNS child: %s",strerror(errno)); |
287 g_snprintf(message, sizeof(message), "Error reading from DNS child: %s",strerror(errno)); |
| 282 debug_printf("%s\n",message); |
288 debug_printf("%s\n",message); |
| 283 req->callback(NULL, 0, req->data, message); |
289 req->callback(NULL, req->data, message); |
| 284 req_free(req); |
290 req_free(req); |
| 285 return; |
291 return; |
| 286 } |
292 } else if(rc==0) { |
| 287 if(rc==0) { |
|
| 288 char message[1024]; |
293 char message[1024]; |
| 289 g_snprintf(message, sizeof(message), "EOF reading from DNS child"); |
294 g_snprintf(message, sizeof(message), "EOF reading from DNS child"); |
| 290 close(req->fd_out); |
295 close(req->fd_out); |
| 291 debug_printf("%s\n",message); |
296 debug_printf("%s\n",message); |
| 292 req->callback(NULL, 0, req->data, message); |
297 req->callback(NULL, req->data, message); |
| 293 req_free(req); |
298 req_free(req); |
| 294 return; |
299 return; |
| 295 } |
300 } |
| 296 |
301 |
| 297 /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */ |
302 /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */ |
| 298 |
303 |
| 299 req->callback(addr, addrlen, req->data, NULL); |
304 req->callback(hosts, req->data, NULL); |
| 300 |
305 |
| 301 g_free(addr); |
306 while(hosts) { |
| 302 |
307 hosts = g_slist_remove(hosts, hosts->data); |
| 303 release_dns_child(req); |
308 g_free(hosts->data); |
| |
309 hosts = g_slist_remove(hosts, hosts->data); |
| |
310 } |
| |
311 |
| |
312 release_dns_child(req); |
| 304 } |
313 } |
| 305 |
314 |
| 306 static void trap_gdb_bug() |
315 static void trap_gdb_bug() |
| 307 { |
316 { |
| 308 const char *message = |
317 const char *message = |
| 466 getpid(), rc); |
475 getpid(), rc); |
| 467 dns_params.hostname[0] = '\0'; |
476 dns_params.hostname[0] = '\0'; |
| 468 continue; |
477 continue; |
| 469 } |
478 } |
| 470 write(child_out[1], &zero, sizeof(zero)); |
479 write(child_out[1], &zero, sizeof(zero)); |
| 471 write(child_out[1], &(res->ai_addrlen), sizeof(res->ai_addrlen)); |
480 while(res) { |
| 472 write(child_out[1], res->ai_addr, res->ai_addrlen); |
481 write(child_out[1], &(res->ai_addrlen), sizeof(res->ai_addrlen)); |
| 473 freeaddrinfo(res); |
482 write(child_out[1], res->ai_addr, res->ai_addrlen); |
| |
483 tmp = res; |
| |
484 res = res->ai_next; |
| |
485 freeaddrinfo(tmp); |
| |
486 } |
| |
487 write(child_out[1], &zero, sizeof(zero)); |
| 474 #else |
488 #else |
| 475 if (!inet_aton(hostname, &sin.sin_addr)) { |
489 if (!inet_aton(hostname, &sin.sin_addr)) { |
| 476 struct hostent *hp; |
490 struct hostent *hp; |
| 477 if(!(hp = gethostbyname(dns_params.hostname))) { |
491 if(!(hp = gethostbyname(dns_params.hostname))) { |
| 478 write(child_out[1], &h_errno, sizeof(int)); |
492 write(child_out[1], &h_errno, sizeof(int)); |
| 488 sin.sin_family = AF_INET; |
502 sin.sin_family = AF_INET; |
| 489 sin.sin_port = htons(dns_params.port); |
503 sin.sin_port = htons(dns_params.port); |
| 490 write(child_out[1], &zero, sizeof(zero)); |
504 write(child_out[1], &zero, sizeof(zero)); |
| 491 write(child_out[1], &addrlen, sizeof(addrlen)); |
505 write(child_out[1], &addrlen, sizeof(addrlen)); |
| 492 write(child_out[1], &sin, addrlen); |
506 write(child_out[1], &sin, addrlen); |
| |
507 write(child_out[1], &zero, sizeof(zero)); |
| 493 #endif |
508 #endif |
| 494 dns_params.hostname[0] = '\0'; |
509 dns_params.hostname[0] = '\0'; |
| 495 } |
510 } |
| 496 close(child_out[1]); |
511 close(child_out[1]); |
| 497 close(child_in[0]); |
512 close(child_in[0]); |
| 612 |
631 |
| 613 debug_printf("connecting to %s:%d with no proxy\n", phb->host, phb->port); |
632 debug_printf("connecting to %s:%d with no proxy\n", phb->host, phb->port); |
| 614 |
633 |
| 615 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
634 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
| 616 debug_printf("unable to create socket: %s\n", strerror(errno)); |
635 debug_printf("unable to create socket: %s\n", strerror(errno)); |
| 617 g_free(phb->host); |
|
| 618 g_free(phb); |
|
| 619 return -1; |
636 return -1; |
| 620 } |
637 } |
| 621 fcntl(fd, F_SETFL, O_NONBLOCK); |
638 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 622 |
639 |
| 623 if (connect(fd, (struct sockaddr *)addr, addrlen) < 0) { |
640 if (connect(fd, (struct sockaddr *)addr, addrlen) < 0) { |
| 625 debug_printf("Connect would have blocked\n"); |
642 debug_printf("Connect would have blocked\n"); |
| 626 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, phb); |
643 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, phb); |
| 627 } else { |
644 } else { |
| 628 debug_printf("connect failed (errno %d)\n", errno); |
645 debug_printf("connect failed (errno %d)\n", errno); |
| 629 close(fd); |
646 close(fd); |
| 630 g_free(phb->host); |
|
| 631 g_free(phb); |
|
| 632 return -1; |
647 return -1; |
| 633 } |
648 } |
| 634 } else { |
649 } else { |
| 635 unsigned int len; |
650 unsigned int len; |
| 636 int error = ETIMEDOUT; |
651 int error = ETIMEDOUT; |
| 637 debug_printf("Connect didn't block\n"); |
652 debug_printf("Connect didn't block\n"); |
| 638 len = sizeof(error); |
653 len = sizeof(error); |
| 639 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
654 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 640 debug_printf("getsockopt failed\n"); |
655 debug_printf("getsockopt failed\n"); |
| 641 close(fd); |
656 close(fd); |
| 642 g_free(phb->host); |
|
| 643 g_free(phb); |
|
| 644 return -1; |
657 return -1; |
| 645 } |
658 } |
| 646 fcntl(fd, F_SETFL, 0); |
659 fcntl(fd, F_SETFL, 0); |
| 647 phb->port = fd; /* bleh */ |
660 phb->port = fd; /* bleh */ |
| 648 g_timeout_add(50, clean_connect, phb); /* we do this because we never |
661 g_timeout_add(50, clean_connect, phb); /* we do this because we never |
| 772 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
783 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 773 debug_printf("Connect would have blocked\n"); |
784 debug_printf("Connect would have blocked\n"); |
| 774 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, http_canwrite, phb); |
785 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, http_canwrite, phb); |
| 775 } else { |
786 } else { |
| 776 close(fd); |
787 close(fd); |
| 777 g_free(phb->host); |
|
| 778 g_free(phb); |
|
| 779 return -1; |
788 return -1; |
| 780 } |
789 } |
| 781 } else { |
790 } else { |
| 782 unsigned int len; |
791 unsigned int len; |
| 783 int error = ETIMEDOUT; |
792 int error = ETIMEDOUT; |
| 784 |
793 |
| 785 debug_printf("Connect didn't block\n"); |
794 debug_printf("Connect didn't block\n"); |
| 786 len = sizeof(error); |
795 len = sizeof(error); |
| 787 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
796 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 788 close(fd); |
797 close(fd); |
| 789 g_free(phb->host); |
|
| 790 g_free(phb); |
|
| 791 return -1; |
798 return -1; |
| 792 } |
799 } |
| 793 fcntl(fd, F_SETFL, 0); |
800 fcntl(fd, F_SETFL, 0); |
| 794 http_canwrite(phb, fd, GAIM_INPUT_WRITE); |
801 http_canwrite(phb, fd, GAIM_INPUT_WRITE); |
| 795 } |
802 } |
| 875 int fd = -1; |
882 int fd = -1; |
| 876 |
883 |
| 877 debug_printf("connecting to %s:%d via %s:%d using SOCKS4\n", phb->host, phb->port, phb->gpi->proxyhost, phb->gpi->proxyport); |
884 debug_printf("connecting to %s:%d via %s:%d using SOCKS4\n", phb->host, phb->port, phb->gpi->proxyhost, phb->gpi->proxyport); |
| 878 |
885 |
| 879 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
886 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
| 880 g_free(phb->host); |
|
| 881 g_free(phb); |
|
| 882 return -1; |
887 return -1; |
| 883 } |
888 } |
| 884 |
889 |
| 885 fcntl(fd, F_SETFL, O_NONBLOCK); |
890 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 886 if (connect(fd, addr, addrlen) < 0) { |
891 if (connect(fd, addr, addrlen) < 0) { |
| 887 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
892 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 888 debug_printf("Connect would have blocked\n"); |
893 debug_printf("Connect would have blocked\n"); |
| 889 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb); |
894 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb); |
| 890 } else { |
895 } else { |
| 891 close(fd); |
896 close(fd); |
| 892 g_free(phb->host); |
|
| 893 g_free(phb); |
|
| 894 return -1; |
897 return -1; |
| 895 } |
898 } |
| 896 } else { |
899 } else { |
| 897 unsigned int len; |
900 unsigned int len; |
| 898 int error = ETIMEDOUT; |
901 int error = ETIMEDOUT; |
| 899 |
902 |
| 900 debug_printf("Connect didn't block\n"); |
903 debug_printf("Connect didn't block\n"); |
| 901 len = sizeof(error); |
904 len = sizeof(error); |
| 902 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
905 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 903 close(fd); |
906 close(fd); |
| 904 g_free(phb->host); |
|
| 905 g_free(phb); |
|
| 906 return -1; |
907 return -1; |
| 907 } |
908 } |
| 908 fcntl(fd, F_SETFL, 0); |
909 fcntl(fd, F_SETFL, 0); |
| 909 s4_canwrite(phb, fd, GAIM_INPUT_WRITE); |
910 s4_canwrite(phb, fd, GAIM_INPUT_WRITE); |
| 910 } |
911 } |
| 1093 int fd = -1; |
1094 int fd = -1; |
| 1094 |
1095 |
| 1095 debug_printf("connecting to %s:%d via %s:%d using SOCKS5\n", phb->host, phb->port, phb->gpi->proxyhost, phb->gpi->proxyport); |
1096 debug_printf("connecting to %s:%d via %s:%d using SOCKS5\n", phb->host, phb->port, phb->gpi->proxyhost, phb->gpi->proxyport); |
| 1096 |
1097 |
| 1097 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
1098 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
| 1098 g_free(phb->host); |
|
| 1099 g_free(phb); |
|
| 1100 return -1; |
1099 return -1; |
| 1101 } |
1100 } |
| 1102 |
1101 |
| 1103 fcntl(fd, F_SETFL, O_NONBLOCK); |
1102 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 1104 if (connect(fd, addr, addrlen) < 0) { |
1103 if (connect(fd, addr, addrlen) < 0) { |
| 1105 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
1104 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1106 debug_printf("Connect would have blocked\n"); |
1105 debug_printf("Connect would have blocked\n"); |
| 1107 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb); |
1106 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb); |
| 1108 } else { |
1107 } else { |
| 1109 close(fd); |
1108 close(fd); |
| 1110 g_free(phb->host); |
|
| 1111 g_free(phb); |
|
| 1112 return -1; |
1109 return -1; |
| 1113 } |
1110 } |
| 1114 } else { |
1111 } else { |
| 1115 unsigned int len; |
1112 unsigned int len; |
| 1116 int error = ETIMEDOUT; |
1113 int error = ETIMEDOUT; |
| 1117 |
1114 |
| 1118 debug_printf("Connect didn't block\n"); |
1115 debug_printf("Connect didn't block\n"); |
| 1119 len = sizeof(error); |
1116 len = sizeof(error); |
| 1120 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1117 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 1121 close(fd); |
1118 close(fd); |
| 1122 g_free(phb->host); |
|
| 1123 g_free(phb); |
|
| 1124 return -1; |
1119 return -1; |
| 1125 } |
1120 } |
| 1126 fcntl(fd, F_SETFL, 0); |
1121 fcntl(fd, F_SETFL, 0); |
| 1127 s5_canwrite(phb, fd, GAIM_INPUT_WRITE); |
1122 s5_canwrite(phb, fd, GAIM_INPUT_WRITE); |
| 1128 } |
1123 } |
| 1129 |
1124 |
| 1130 return fd; |
1125 return fd; |
| 1131 } |
1126 } |
| 1132 |
1127 |
| 1133 static void connection_host_resolved(struct sockaddr *addr, size_t addrlen, gpointer data, const char *error_message) |
1128 static void connection_host_resolved(GSList *hosts, gpointer data, const char *error_message) |
| 1134 { |
1129 { |
| 1135 struct PHB *phb = (struct PHB*)data; |
1130 struct PHB *phb = (struct PHB*)data; |
| 1136 |
1131 size_t addrlen; |
| 1137 if(!addr) |
1132 struct sockaddr *addr; |
| 1138 { |
1133 int ret = -1; |
| 1139 phb->func(phb->data, -1, GAIM_INPUT_READ); |
1134 |
| 1140 return; |
1135 while(hosts) { |
| 1141 } |
1136 addrlen = GPOINTER_TO_INT(hosts->data); |
| 1142 |
1137 hosts = hosts->next; |
| 1143 switch(phb->gpi->proxytype) |
1138 addr = hosts->data; |
| 1144 { |
1139 hosts = hosts->next; |
| 1145 case PROXY_NONE: |
1140 |
| 1146 proxy_connect_none(phb, addr, addrlen); |
1141 switch(phb->gpi->proxytype) |
| |
1142 { |
| |
1143 case PROXY_NONE: |
| |
1144 ret = proxy_connect_none(phb, addr, addrlen); |
| |
1145 break; |
| |
1146 case PROXY_HTTP: |
| |
1147 ret = proxy_connect_http(phb, addr, addrlen); |
| |
1148 break; |
| |
1149 case PROXY_SOCKS4: |
| |
1150 ret = proxy_connect_socks4(phb, addr, addrlen); |
| |
1151 break; |
| |
1152 case PROXY_SOCKS5: |
| |
1153 ret = proxy_connect_socks5(phb, addr, addrlen); |
| |
1154 break; |
| |
1155 } |
| |
1156 if (ret > 0) |
| 1147 break; |
1157 break; |
| 1148 case PROXY_HTTP: |
1158 } |
| 1149 proxy_connect_http(phb, addr, addrlen); |
1159 if(ret < 0) { |
| 1150 break; |
1160 phb->func(phb->data, -1, GAIM_INPUT_READ); |
| 1151 case PROXY_SOCKS4: |
1161 g_free(phb->host); |
| 1152 proxy_connect_socks4(phb, addr, addrlen); |
1162 g_free(phb); |
| 1153 break; |
|
| 1154 case PROXY_SOCKS5: |
|
| 1155 proxy_connect_socks5(phb, addr, addrlen); |
|
| 1156 break; |
|
| 1157 } |
1163 } |
| 1158 } |
1164 } |
| 1159 |
1165 |
| 1160 int |
1166 int |
| 1161 proxy_connect(struct gaim_account *account, char *host, int port, GaimInputFunction func, gpointer data) |
1167 proxy_connect(struct gaim_account *account, char *host, int port, GaimInputFunction func, gpointer data) |