comparison src/proxy.c @ 14164:879bb47cff8e

[gaim-migrate @ 16814] Revert SVN revision 16811. Kevin says it's crashing for him and I'm tired. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Thu, 17 Aug 2006 10:04:21 +0000
parents c3167a1dd817
children fc92a5a7dd95
comparison
equal deleted inserted replaced
14163:c3167a1dd817 14164:879bb47cff8e
29 , 2nd provide an easy way to add socks support 29 , 2nd provide an easy way to add socks support
30 , 3rd draw women to it like flies to honey */ 30 , 3rd draw women to it like flies to honey */
31 31
32 #include "internal.h" 32 #include "internal.h"
33 #include "cipher.h" 33 #include "cipher.h"
34 #include "dnsquery.h"
35 #include "debug.h" 34 #include "debug.h"
36 #include "notify.h" 35 #include "notify.h"
37 #include "ntlm.h" 36 #include "ntlm.h"
38 #include "prefs.h" 37 #include "prefs.h"
39 #include "proxy.h" 38 #include "proxy.h"
45 char *host; 44 char *host;
46 int port; 45 int port;
47 int fd; 46 int fd;
48 guint inpa; 47 guint inpa;
49 GaimProxyInfo *gpi; 48 GaimProxyInfo *gpi;
50 GaimDnsqueryData *query_data;
51 49
52 /** 50 /**
53 * This contains alternating length/char* values. The char* 51 * This contains alternating length/char* values. The char*
54 * values need to be freed when removed from the linked list. 52 * values need to be freed when removed from the linked list.
55 */ 53 */
307 { 305 {
308 gaim_proxy_connect_info_disconnect(connect_info); 306 gaim_proxy_connect_info_disconnect(connect_info);
309 307
310 connect_infos = g_slist_remove(connect_infos, connect_info); 308 connect_infos = g_slist_remove(connect_infos, connect_info);
311 309
312 /*
313 if (connect_info->query_data != NULL)
314 gaim_dnsquery_destroy(connect_info->query_data);
315 */
316
317 while (connect_info->hosts != NULL) 310 while (connect_info->hosts != NULL)
318 { 311 {
319 /* Discard the length... */ 312 /* Discard the length... */
320 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); 313 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data);
321 /* Free the address... */ 314 /* Free the address... */
355 gaim_proxy_connect_info_error(GaimProxyConnectInfo *connect_info, const gchar *error_message) 348 gaim_proxy_connect_info_error(GaimProxyConnectInfo *connect_info, const gchar *error_message)
356 { 349 {
357 connect_info->connect_cb(connect_info->data, -1, error_message); 350 connect_info->connect_cb(connect_info->data, -1, error_message);
358 gaim_proxy_connect_info_destroy(connect_info); 351 gaim_proxy_connect_info_destroy(connect_info);
359 } 352 }
353
354 #if defined(__unix__) || defined(__APPLE__)
355
356 /*
357 * This structure represents both a pending DNS request and
358 * a free child process.
359 */
360 typedef struct {
361 char *host;
362 int port;
363 GaimProxyDnsConnectFunction callback;
364 gpointer data;
365 guint inpa;
366 int fd_in, fd_out;
367 pid_t dns_pid;
368 } pending_dns_request_t;
369
370 static GSList *free_dns_children = NULL;
371 static GQueue *queued_requests = NULL;
372
373 static int number_of_dns_children = 0;
374
375 static const int MAX_DNS_CHILDREN = 2;
376
377 typedef struct {
378 char hostname[512];
379 int port;
380 } dns_params_t;
381
382 typedef struct {
383 dns_params_t params;
384 GaimProxyDnsConnectFunction callback;
385 gpointer data;
386 } queued_dns_request_t;
387
388 /*
389 * Begin the DNS resolver child process functions.
390 */
391 #ifdef HAVE_SIGNAL_H
392 static void
393 trap_gdb_bug()
394 {
395 const char *message =
396 "Gaim's DNS child got a SIGTRAP signal.\n"
397 "This can be caused by trying to run gaim inside gdb.\n"
398 "There is a known gdb bug which prevents this. Supposedly gaim\n"
399 "should have detected you were using gdb and used an ugly hack,\n"
400 "check cope_with_gdb_brokenness() in proxy.c.\n\n"
401 "For more info about this bug, see http://sources.redhat.com/ml/gdb/2001-07/msg00349.html\n";
402 fputs("\n* * *\n",stderr);
403 fputs(message,stderr);
404 fputs("* * *\n\n",stderr);
405 execlp("xmessage","xmessage","-center", message, NULL);
406 _exit(1);
407 }
408 #endif
409
410 static void
411 cope_with_gdb_brokenness()
412 {
413 #ifdef __linux__
414 static gboolean already_done = FALSE;
415 char s[256], e[512];
416 int n;
417 pid_t ppid;
418
419 if(already_done)
420 return;
421 already_done = TRUE;
422 ppid = getppid();
423 snprintf(s, sizeof(s), "/proc/%d/exe", ppid);
424 n = readlink(s, e, sizeof(e));
425 if(n < 0)
426 return;
427
428 e[MIN(n,sizeof(e)-1)] = '\0';
429
430 if(strstr(e,"gdb")) {
431 gaim_debug_info("dns",
432 "Debugger detected, performing useless query...\n");
433 gethostbyname("x.x.x.x.x");
434 }
435 #endif
436 }
437
438 static void
439 gaim_dns_resolverthread(int child_out, int child_in, gboolean show_debug)
440 {
441 dns_params_t dns_params;
442 const size_t zero = 0;
443 int rc;
444 #ifdef HAVE_GETADDRINFO
445 struct addrinfo hints, *res, *tmp;
446 char servname[20];
447 #else
448 struct sockaddr_in sin;
449 const size_t addrlen = sizeof(sin);
450 #endif
451
452 #ifdef HAVE_SIGNAL_H
453 signal(SIGHUP, SIG_DFL);
454 signal(SIGINT, SIG_DFL);
455 signal(SIGQUIT, SIG_DFL);
456 signal(SIGCHLD, SIG_DFL);
457 signal(SIGTERM, SIG_DFL);
458 signal(SIGTRAP, trap_gdb_bug);
459 #endif
460
461 /*
462 * We resolve 1 host name for each iteration of this
463 * while loop.
464 *
465 * The top half of this reads in the hostname and port
466 * number from the socket with our parent. The bottom
467 * half of this resolves the IP (blocking) and sends
468 * the result back to our parent, when finished.
469 */
470 while (1) {
471 const char ch = 'Y';
472 fd_set fds;
473 struct timeval tv = { .tv_sec = 40 , .tv_usec = 0 };
474 FD_ZERO(&fds);
475 FD_SET(child_in, &fds);
476 rc = select(child_in + 1, &fds, NULL, NULL, &tv);
477 if (!rc) {
478 if (show_debug)
479 printf("dns[%d]: nobody needs me... =(\n", getpid());
480 break;
481 }
482 rc = read(child_in, &dns_params, sizeof(dns_params_t));
483 if (rc < 0) {
484 perror("read()");
485 break;
486 }
487 if (rc == 0) {
488 if (show_debug)
489 printf("dns[%d]: Oops, father has gone, wait for me, wait...!\n", getpid());
490 _exit(0);
491 }
492 if (dns_params.hostname[0] == '\0') {
493 printf("dns[%d]: hostname = \"\" (port = %d)!!!\n", getpid(), dns_params.port);
494 _exit(1);
495 }
496 /* Tell our parent that we read the data successfully */
497 write(child_out, &ch, sizeof(ch));
498
499 /* We have the hostname and port, now resolve the IP */
500
501 #ifdef HAVE_GETADDRINFO
502 g_snprintf(servname, sizeof(servname), "%d", dns_params.port);
503 memset(&hints, 0, sizeof(hints));
504
505 /* This is only used to convert a service
506 * name to a port number. As we know we are
507 * passing a number already, we know this
508 * value will not be really used by the C
509 * library.
510 */
511 hints.ai_socktype = SOCK_STREAM;
512 rc = getaddrinfo(dns_params.hostname, servname, &hints, &res);
513 write(child_out, &rc, sizeof(rc));
514 if (rc != 0) {
515 close(child_out);
516 if (show_debug)
517 printf("dns[%d] Error: getaddrinfo returned %d\n",
518 getpid(), rc);
519 dns_params.hostname[0] = '\0';
520 continue;
521 }
522 tmp = res;
523 while (res) {
524 size_t ai_addrlen = res->ai_addrlen;
525 write(child_out, &ai_addrlen, sizeof(ai_addrlen));
526 write(child_out, res->ai_addr, res->ai_addrlen);
527 res = res->ai_next;
528 }
529 freeaddrinfo(tmp);
530 write(child_out, &zero, sizeof(zero));
531 #else
532 if (!inet_aton(dns_params.hostname, &sin.sin_addr)) {
533 struct hostent *hp;
534 if (!(hp = gethostbyname(dns_params.hostname))) {
535 write(child_out, &h_errno, sizeof(int));
536 close(child_out);
537 if (show_debug)
538 printf("DNS Error: %d\n", h_errno);
539 _exit(0);
540 }
541 memset(&sin, 0, sizeof(struct sockaddr_in));
542 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
543 sin.sin_family = hp->h_addrtype;
544 } else
545 sin.sin_family = AF_INET;
546
547 sin.sin_port = htons(dns_params.port);
548 write(child_out, &addrlen, sizeof(addrlen));
549 write(child_out, &sin, addrlen);
550 write(child_out, &zero, sizeof(zero));
551 #endif
552 dns_params.hostname[0] = '\0';
553 }
554
555 close(child_out);
556 close(child_in);
557
558 _exit(0);
559 }
560
561 static pending_dns_request_t *
562 gaim_dns_new_resolverthread(gboolean show_debug)
563 {
564 pending_dns_request_t *req;
565 int child_out[2], child_in[2];
566
567 /* Create pipes for communicating with the child process */
568 if (pipe(child_out) || pipe(child_in)) {
569 gaim_debug_error("dns",
570 "Could not create pipes: %s\n", strerror(errno));
571 return NULL;
572 }
573
574 req = g_new(pending_dns_request_t, 1);
575
576 cope_with_gdb_brokenness();
577
578 /* Fork! */
579 req->dns_pid = fork();
580
581 /* If we are the child process... */
582 if (req->dns_pid == 0) {
583 /* We should not access the parent's side of the pipes, so close them */
584 close(child_out[0]);
585 close(child_in[1]);
586
587 gaim_dns_resolverthread(child_out[1], child_in[0], show_debug);
588 /* The thread calls _exit() rather than returning, so we never get here */
589 }
590
591 /* We should not access the child's side of the pipes, so close them */
592 close(child_out[1]);
593 close(child_in[0]);
594 if (req->dns_pid == -1) {
595 gaim_debug_error("dns",
596 "Could not create child process for DNS: %s\n",
597 strerror(errno));
598 g_free(req);
599 return NULL;
600 }
601
602 req->fd_out = child_out[0];
603 req->fd_in = child_in[1];
604 number_of_dns_children++;
605 gaim_debug_info("dns",
606 "Created new DNS child %d, there are now %d children.\n",
607 req->dns_pid, number_of_dns_children);
608
609 return req;
610 }
611 /*
612 * End the DNS resolver child process functions.
613 */
614
615 /*
616 * Begin the functions for dealing with the DNS child processes.
617 */
618 static void
619 req_free(pending_dns_request_t *req)
620 {
621 g_return_if_fail(req != NULL);
622
623 close(req->fd_in);
624 close(req->fd_out);
625
626 g_free(req->host);
627 g_free(req);
628
629 number_of_dns_children--;
630 }
631
632 static int
633 send_dns_request_to_child(pending_dns_request_t *req, dns_params_t *dns_params)
634 {
635 char ch;
636 int rc;
637 pid_t pid;
638
639 /* This waitpid might return the child's PID if it has recently
640 * exited, or it might return an error if it exited "long
641 * enough" ago that it has already been reaped; in either
642 * instance, we can't use it. */
643 if ((pid = waitpid (req->dns_pid, NULL, WNOHANG)) > 0) {
644 gaim_debug_warning("dns",
645 "DNS child %d no longer exists\n", req->dns_pid);
646 return -1;
647 } else if (pid < 0) {
648 gaim_debug_warning("dns",
649 "Wait for DNS child %d failed: %s\n",
650 req->dns_pid, strerror(errno));
651 return -1;
652 }
653
654 /* Let's contact this lost child! */
655 rc = write(req->fd_in, dns_params, sizeof(*dns_params));
656 if (rc < 0) {
657 gaim_debug_error("dns",
658 "Unable to write to DNS child %d: %d\n",
659 req->dns_pid, strerror(errno));
660 close(req->fd_in);
661 return -1;
662 }
663
664 g_return_val_if_fail(rc == sizeof(*dns_params), -1);
665
666 /* Did you hear me? (This avoids some race conditions) */
667 rc = read(req->fd_out, &ch, sizeof(ch));
668 if (rc != 1 || ch != 'Y')
669 {
670 gaim_debug_warning("dns",
671 "DNS child %d not responding. Killing it!\n",
672 req->dns_pid);
673 kill(req->dns_pid, SIGKILL);
674 return -1;
675 }
676
677 gaim_debug_info("dns",
678 "Successfully sent DNS request to child %d\n", req->dns_pid);
679
680 return 0;
681 }
682
683 static void
684 host_resolved(gpointer data, gint source, GaimInputCondition cond);
685
686 static void
687 release_dns_child(pending_dns_request_t *req)
688 {
689 g_free(req->host);
690 req->host = NULL;
691
692 if (queued_requests && !g_queue_is_empty(queued_requests)) {
693 queued_dns_request_t *r = g_queue_pop_head(queued_requests);
694 req->host = g_strdup(r->params.hostname);
695 req->port = r->params.port;
696 req->callback = r->callback;
697 req->data = r->data;
698
699 gaim_debug_info("dns",
700 "Processing queued DNS query for '%s' with child %d\n",
701 req->host, req->dns_pid);
702
703 if (send_dns_request_to_child(req, &(r->params)) != 0) {
704 req_free(req);
705 req = NULL;
706
707 gaim_debug_warning("dns",
708 "Intent of process queued query of '%s' failed, "
709 "requeueing...\n", r->params.hostname);
710 g_queue_push_head(queued_requests, r);
711 } else {
712 req->inpa = gaim_input_add(req->fd_out, GAIM_INPUT_READ, host_resolved, req);
713 g_free(r);
714 }
715
716 } else {
717 req->host = NULL;
718 req->callback = NULL;
719 req->data = NULL;
720 free_dns_children = g_slist_append(free_dns_children, req);
721 }
722 }
723
724 static void
725 host_resolved(gpointer data, gint source, GaimInputCondition cond)
726 {
727 pending_dns_request_t *req = (pending_dns_request_t*)data;
728 int rc, err;
729 GSList *hosts = NULL;
730 struct sockaddr *addr = NULL;
731 size_t addrlen;
732
733 gaim_debug_info("dns", "Got response for '%s'\n", req->host);
734 gaim_input_remove(req->inpa);
735
736 rc = read(req->fd_out, &err, sizeof(err));
737 if ((rc == 4) && (err != 0))
738 {
739 char message[1024];
740 #ifdef HAVE_GETADDRINFO
741 g_snprintf(message, sizeof(message), "DNS error: %s (pid=%d)",
742 gai_strerror(err), req->dns_pid);
743 #else
744 g_snprintf(message, sizeof(message), "DNS error: %d (pid=%d)",
745 err, req->dns_pid);
746 #endif
747 gaim_debug_error("dns", "%s\n", message);
748 req->callback(NULL, req->data, message);
749 release_dns_child(req);
750 return;
751 }
752 if (rc > 0)
753 {
754 while (rc > 0) {
755 rc = read(req->fd_out, &addrlen, sizeof(addrlen));
756 if (rc > 0 && addrlen > 0) {
757 addr = g_malloc(addrlen);
758 rc = read(req->fd_out, addr, addrlen);
759 hosts = g_slist_append(hosts, GINT_TO_POINTER(addrlen));
760 hosts = g_slist_append(hosts, addr);
761 } else {
762 break;
763 }
764 }
765 } else if (rc == -1) {
766 char message[1024];
767 g_snprintf(message, sizeof(message), "Error reading from DNS child: %s",strerror(errno));
768 gaim_debug_error("dns", "%s\n", message);
769 req->callback(NULL, req->data, message);
770 req_free(req);
771 return;
772 } else if (rc == 0) {
773 char message[1024];
774 g_snprintf(message, sizeof(message), "EOF reading from DNS child");
775 close(req->fd_out);
776 gaim_debug_error("dns", "%s\n", message);
777 req->callback(NULL, req->data, message);
778 req_free(req);
779 return;
780 }
781
782 /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */
783
784 req->callback(hosts, req->data, NULL);
785
786 release_dns_child(req);
787 }
788 /*
789 * End the functions for dealing with the DNS child processes.
790 */
791
792 int
793 gaim_gethostbyname_async(const char *hostname, int port, GaimProxyDnsConnectFunction callback, gpointer data)
794 {
795 pending_dns_request_t *req = NULL;
796 dns_params_t dns_params;
797 gchar *host_temp;
798 gboolean show_debug;
799
800 show_debug = gaim_debug_is_enabled();
801
802 host_temp = g_strstrip(g_strdup(hostname));
803 strncpy(dns_params.hostname, host_temp, sizeof(dns_params.hostname) - 1);
804 g_free(host_temp);
805 dns_params.hostname[sizeof(dns_params.hostname) - 1] = '\0';
806 dns_params.port = port;
807
808 /*
809 * If we have any children, attempt to have them perform the DNS
810 * query. If we're able to send the query to a child, then req
811 * will be set to the pending_dns_request_t. Otherwise, req will
812 * be NULL and we'll need to create a new DNS request child.
813 */
814 while (free_dns_children != NULL) {
815 req = free_dns_children->data;
816 free_dns_children = g_slist_remove(free_dns_children, req);
817
818 if (send_dns_request_to_child(req, &dns_params) == 0)
819 /* We found an acceptable child, yay */
820 break;
821
822 req_free(req);
823 req = NULL;
824 }
825
826 /* We need to create a new DNS request child */
827 if (req == NULL) {
828 if (number_of_dns_children >= MAX_DNS_CHILDREN) {
829 queued_dns_request_t *r = g_new(queued_dns_request_t, 1);
830 memcpy(&(r->params), &dns_params, sizeof(dns_params));
831 r->callback = callback;
832 r->data = data;
833 if (!queued_requests)
834 queued_requests = g_queue_new();
835 g_queue_push_tail(queued_requests, r);
836
837 gaim_debug_info("dns",
838 "DNS query for '%s' queued\n", dns_params.hostname);
839
840 return 0;
841 }
842
843 req = gaim_dns_new_resolverthread(show_debug);
844 if (req == NULL)
845 {
846 gaim_debug_error("proxy", "oh dear, this is going to explode, I give up\n");
847 return -1;
848 }
849 send_dns_request_to_child(req, &dns_params);
850 }
851
852 req->host = g_strdup(hostname);
853 req->port = port;
854 req->callback = callback;
855 req->data = data;
856 req->inpa = gaim_input_add(req->fd_out, GAIM_INPUT_READ, host_resolved, req);
857
858 return 0;
859 }
860
861 #elif defined _WIN32 /* end __unix__ || __APPLE__ */
862
863 typedef struct _dns_tdata {
864 char *hostname;
865 int port;
866 GaimProxyDnsConnectFunction callback;
867 gpointer data;
868 GSList *hosts;
869 char *errmsg;
870 } dns_tdata;
871
872 static gboolean dns_main_thread_cb(gpointer data) {
873 dns_tdata *td = (dns_tdata*)data;
874 if (td->errmsg != NULL) {
875 gaim_debug_info("dns", "%s\n", td->errmsg);
876 }
877 td->callback(td->hosts, td->data, td->errmsg);
878 g_free(td->hostname);
879 g_free(td->errmsg);
880 g_free(td);
881 return FALSE;
882 }
883
884 static gpointer dns_thread(gpointer data) {
885
886 #ifdef HAVE_GETADDRINFO
887 int rc;
888 struct addrinfo hints, *res, *tmp;
889 char servname[20];
890 #else
891 struct sockaddr_in sin;
892 struct hostent *hp;
893 #endif
894 dns_tdata *td = (dns_tdata*)data;
895
896 #ifdef HAVE_GETADDRINFO
897 g_snprintf(servname, sizeof(servname), "%d", td->port);
898 memset(&hints,0,sizeof(hints));
899
900 /* This is only used to convert a service
901 * name to a port number. As we know we are
902 * passing a number already, we know this
903 * value will not be really used by the C
904 * library.
905 */
906 hints.ai_socktype = SOCK_STREAM;
907 if ((rc = getaddrinfo(td->hostname, servname, &hints, &res)) == 0) {
908 tmp = res;
909 while(res) {
910 td->hosts = g_slist_append(td->hosts,
911 GSIZE_TO_POINTER(res->ai_addrlen));
912 td->hosts = g_slist_append(td->hosts,
913 g_memdup(res->ai_addr, res->ai_addrlen));
914 res = res->ai_next;
915 }
916 freeaddrinfo(tmp);
917 } else {
918 td->errmsg = g_strdup_printf("DNS getaddrinfo(\"%s\", \"%s\") error: %d", td->hostname, servname, rc);
919 }
920 #else
921 if ((hp = gethostbyname(td->hostname))) {
922 memset(&sin, 0, sizeof(struct sockaddr_in));
923 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
924 sin.sin_family = hp->h_addrtype;
925 sin.sin_port = htons(td->port);
926
927 td->hosts = g_slist_append(td->hosts,
928 GSIZE_TO_POINTER(sizeof(sin)));
929 td->hosts = g_slist_append(td->hosts,
930 g_memdup(&sin, sizeof(sin)));
931 } else {
932 td->errmsg = g_strdup_printf("DNS gethostbyname(\"%s\") error: %d", td->hostname, h_errno);
933 }
934 #endif
935 /* back to main thread */
936 g_idle_add(dns_main_thread_cb, td);
937 return 0;
938 }
939
940 int
941 gaim_gethostbyname_async(const char *hostname, int port,
942 GaimProxyDnsConnectFunction callback, gpointer data)
943 {
944 dns_tdata *td;
945 struct sockaddr_in sin;
946 GError* err = NULL;
947
948 if(inet_aton(hostname, &sin.sin_addr)) {
949 GSList *hosts = NULL;
950 sin.sin_family = AF_INET;
951 sin.sin_port = htons(port);
952 hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin)));
953 hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin)));
954 callback(hosts, data, NULL);
955 return 0;
956 }
957
958 gaim_debug_info("dns", "DNS Lookup for: %s\n", hostname);
959 td = g_new0(dns_tdata, 1);
960 td->hostname = g_strdup(hostname);
961 td->port = port;
962 td->callback = callback;
963 td->data = data;
964
965 if(!g_thread_create(dns_thread, td, FALSE, &err)) {
966 gaim_debug_error("dns", "DNS thread create failure: %s\n", err?err->message:"");
967 g_error_free(err);
968 g_free(td->hostname);
969 g_free(td);
970 return -1;
971 }
972 return 0;
973 }
974
975 #else /* not __unix__ or __APPLE__ or _WIN32 */
976
977 typedef struct {
978 gpointer data;
979 size_t addrlen;
980 struct sockaddr *addr;
981 GaimProxyDnsConnectFunction callback;
982 } pending_dns_request_t;
983
984 static gboolean host_resolved(gpointer data)
985 {
986 pending_dns_request_t *req = (pending_dns_request_t*)data;
987 GSList *hosts = NULL;
988 hosts = g_slist_append(hosts, GINT_TO_POINTER(req->addrlen));
989 hosts = g_slist_append(hosts, req->addr);
990 req->callback(hosts, req->data, NULL);
991 g_free(req);
992 return FALSE;
993 }
994
995 int
996 gaim_gethostbyname_async(const char *hostname, int port,
997 GaimProxyDnsConnectFunction callback, gpointer data)
998 {
999 struct sockaddr_in sin;
1000 pending_dns_request_t *req;
1001
1002 if (!inet_aton(hostname, &sin.sin_addr)) {
1003 struct hostent *hp;
1004 if(!(hp = gethostbyname(hostname))) {
1005 gaim_debug_error("dns",
1006 "gaim_gethostbyname(\"%s\", %d) failed: %d\n",
1007 hostname, port, h_errno);
1008 return -1;
1009 }
1010 memset(&sin, 0, sizeof(struct sockaddr_in));
1011 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
1012 sin.sin_family = hp->h_addrtype;
1013 } else
1014 sin.sin_family = AF_INET;
1015 sin.sin_port = htons(port);
1016
1017 req = g_new(pending_dns_request_t, 1);
1018 req->addr = (struct sockaddr*) g_memdup(&sin, sizeof(sin));
1019 req->addrlen = sizeof(sin);
1020 req->data = data;
1021 req->callback = callback;
1022 gaim_timeout_add(10, host_resolved, req);
1023 return 0;
1024 }
1025
1026 #endif /* not __unix__ or __APPLE__ or _WIN32 */
360 1027
361 static void 1028 static void
362 no_one_calls(gpointer data, gint source, GaimInputCondition cond) 1029 no_one_calls(gpointer data, gint source, GaimInputCondition cond)
363 { 1030 {
364 GaimProxyConnectInfo *connect_info = data; 1031 GaimProxyConnectInfo *connect_info = data;
1699 default: 2366 default:
1700 gaim_proxy_connect_info_destroy(connect_info); 2367 gaim_proxy_connect_info_destroy(connect_info);
1701 return NULL; 2368 return NULL;
1702 } 2369 }
1703 2370
1704 connect_info->query_data = gaim_dnsquery_a(connecthost, 2371 if (gaim_gethostbyname_async(connecthost,
1705 connectport, connection_host_resolved, connect_info); 2372 connectport, connection_host_resolved, connect_info) != 0)
1706 if (connect_info->query_data == NULL)
1707 { 2373 {
1708 gaim_proxy_connect_info_destroy(connect_info); 2374 gaim_proxy_connect_info_destroy(connect_info);
1709 return NULL; 2375 return NULL;
1710 } 2376 }
1711 2377
1733 connect_info->data = data; 2399 connect_info->data = data;
1734 connect_info->host = g_strdup(host); 2400 connect_info->host = g_strdup(host);
1735 connect_info->port = port; 2401 connect_info->port = port;
1736 connect_info->gpi = gpi; 2402 connect_info->gpi = gpi;
1737 2403
1738 connect_info->query_data = gaim_dnsquery_a(gaim_proxy_info_get_host(gpi), 2404 if (gaim_gethostbyname_async(gaim_proxy_info_get_host(gpi),
1739 gaim_proxy_info_get_port(gpi), connection_host_resolved, connect_info); 2405 gaim_proxy_info_get_port(gpi), connection_host_resolved, connect_info) != 0)
1740 if (connect_info->query_data == NULL)
1741 { 2406 {
1742 gaim_proxy_connect_info_destroy(connect_info); 2407 gaim_proxy_connect_info_destroy(connect_info);
1743 return NULL; 2408 return NULL;
1744 } 2409 }
1745 2410