comparison src/proxy.c @ 9656:2ea77e275b85

[gaim-migrate @ 10504] I cleaned some stuff up. I'm picky. This code is mildly important to Gaim. So, uh, lemme know if I broke anything. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Wed, 04 Aug 2004 00:43:53 +0000
parents 00f96f4cc775
children 51464cbbdc1a
comparison
equal deleted inserted replaced
9655:00f96f4cc775 9656:2ea77e275b85
419 419
420 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)
421 { 421 {
422 pending_dns_request_t *req = NULL; 422 pending_dns_request_t *req = NULL;
423 dns_params_t dns_params; 423 dns_params_t dns_params;
424 424 gchar *host_temp;
425 char *host_temp = g_strdup(hostname); 425
426 strncpy(dns_params.hostname, g_strstrip(host_temp), sizeof(dns_params.hostname)-1); 426 host_temp = g_strstrip(g_strdup(hostname));
427 strncpy(dns_params.hostname, host_temp, sizeof(dns_params.hostname) - 1);
427 g_free(host_temp); 428 g_free(host_temp);
428 dns_params.hostname[sizeof(dns_params.hostname)-1] = '\0'; 429 dns_params.hostname[sizeof(dns_params.hostname) - 1] = '\0';
429 dns_params.port = port; 430 dns_params.port = port;
430 431
431 /* Is there a free available child? */ 432 /*
432 while(free_dns_children && !req) { 433 * If we have any children, attempt to have them perform the DNS
433 GSList *l = free_dns_children; 434 * query. If we're able to send the query to a child, then req
434 free_dns_children = g_slist_remove_link(free_dns_children, l); 435 * will be set to the pending_dns_request_t. Otherwise, req will
435 req = l->data; 436 * be NULL and we'll need to create a new DNS request child.
436 g_slist_free(l); 437 */
437 438 while (free_dns_children != NULL) {
438 if(send_dns_request_to_child(req, &dns_params) != 0) { 439 req = free_dns_children->data;
439 req_free(req); 440 free_dns_children = g_slist_remove(free_dns_children, req);
440 req = NULL; 441
441 continue; 442 if (send_dns_request_to_child(req, &dns_params) == 0)
442 } 443 /* We found an acceptable child, yay */
443 444 break;
444 } 445
445 446 req_free(req);
446 if(!req) { 447 }
448
449 /*
450 * We need to create a new DNS request child.
451 */
452 if (req == NULL) {
447 int child_out[2], child_in[2]; 453 int child_out[2], child_in[2];
448 454
449 if(number_of_dns_children >= MAX_DNS_CHILDREN) { 455 if (number_of_dns_children >= MAX_DNS_CHILDREN) {
450 queued_dns_request_t *r = g_new(queued_dns_request_t, 1); 456 queued_dns_request_t *r = g_new(queued_dns_request_t, 1);
451 memcpy(&(r->params), &dns_params, sizeof(dns_params)); 457 memcpy(&(r->params), &dns_params, sizeof(dns_params));
452 r->callback = callback; 458 r->callback = callback;
453 r->data = data; 459 r->data = data;
454 if(!queued_requests) 460 if (!queued_requests)
455 queued_requests = g_queue_new(); 461 queued_requests = g_queue_new();
456 g_queue_push_tail(queued_requests, r); 462 g_queue_push_tail(queued_requests, r);
457 463
458 gaim_debug(GAIM_DEBUG_INFO, "dns", 464 gaim_debug(GAIM_DEBUG_INFO, "dns",
459 "DNS query for '%s' queued\n", hostname); 465 "DNS query for '%s' queued\n", dns_params.hostname);
460 466
461 return 0; 467 return 0;
462 } 468 }
463 469
464 if(pipe(child_out) || pipe(child_in)) { 470 if (pipe(child_out) || pipe(child_in)) {
465 gaim_debug(GAIM_DEBUG_ERROR, "dns", 471 gaim_debug(GAIM_DEBUG_ERROR, "dns",
466 "Could not create pipes: %s\n", strerror(errno)); 472 "Could not create pipes: %s\n", strerror(errno));
467 return -1; 473 return -1;
468 } 474 }
469 475
470 /* We need to create a new child. */ 476 /* We need to create a new child. */
471 req = g_new(pending_dns_request_t,1); 477 req = g_new(pending_dns_request_t,1);
472 478
473 cope_with_gdb_brokenness(); 479 cope_with_gdb_brokenness();
474 480
475 req->dns_pid=fork(); 481 req->dns_pid = fork();
476 if(req->dns_pid==0) { 482
483 /* If we are a child... */
484 if (req->dns_pid == 0) {
477 const int zero = 0; 485 const int zero = 0;
478 int rc; 486 int rc;
479 487
480 #if HAVE_GETADDRINFO 488 #if HAVE_GETADDRINFO
481 struct addrinfo hints, *res, *tmp; 489 struct addrinfo hints, *res, *tmp;
491 signal(SIGCHLD, SIG_DFL); 499 signal(SIGCHLD, SIG_DFL);
492 signal(SIGTERM, SIG_DFL); 500 signal(SIGTERM, SIG_DFL);
493 signal(SIGTRAP, trap_gdb_bug); 501 signal(SIGTRAP, trap_gdb_bug);
494 #endif 502 #endif
495 503
496 504 /* We should not access the parent's side of the pipe, so close them... */
497 close(child_out[0]); 505 close(child_out[0]);
498 close(child_in[1]); 506 close(child_in[1]);
499 507
500 while(1) { 508 while (1) {
501 if(dns_params.hostname[0] == '\0') { 509 if (dns_params.hostname[0] == '\0') {
502 const char Y = 'Y'; 510 const char Y = 'Y';
503 fd_set fds; 511 fd_set fds;
504 struct timeval tv = { .tv_sec = 40 , .tv_usec = 0 }; 512 struct timeval tv = { .tv_sec = 40 , .tv_usec = 0 };
505 FD_ZERO(&fds); 513 FD_ZERO(&fds);
506 FD_SET(child_in[0], &fds); 514 FD_SET(child_in[0], &fds);
507 rc = select(child_in[0]+1, &fds, NULL, NULL, &tv); 515 rc = select(child_in[0]+1, &fds, NULL, NULL, &tv);
508 if(!rc) { 516 if (!rc) {
509 if (opt_debug) 517 if (opt_debug)
510 fprintf(stderr,"dns[%d]: nobody needs me... =(\n", getpid()); 518 fprintf(stderr,"dns[%d]: Nobody needs me... =(\n", getpid());
511 break; 519 break;
512 } 520 }
513 rc = read(child_in[0], &dns_params, sizeof(dns_params)); 521 rc = read(child_in[0], &dns_params, sizeof(dns_params));
514 if(rc < 0) { 522 if (rc < 0) {
515 perror("read()"); 523 perror("read()");
516 break; 524 break;
517 } 525 }
518 if(rc==0) { 526 if (rc==0) {
519 if(opt_debug) 527 if (opt_debug)
520 fprintf(stderr,"dns[%d]: Ops, father has gone, wait for me, wait...!\n", getpid()); 528 fprintf(stderr,"dns[%d]: Father has gone, wait for me, wait...!\n", getpid());
521 _exit(0); 529 _exit(0);
522 } 530 }
523 if(dns_params.hostname[0] == '\0') { 531 if (dns_params.hostname[0] == '\0') {
524 fprintf(stderr, "dns[%d]: hostname = \"\" (port = %d)!!!\n", getpid(), dns_params.port); 532 fprintf(stderr, "dns[%d]: Hostname = \"\" (port = %d)!!!\n", getpid(), dns_params.port);
525 _exit(1); 533 _exit(1);
526 } 534 }
527 write(child_out[1], &Y, 1); 535 write(child_out[1], &Y, 1);
528 } 536 }
529 537
537 * value will not be really used by the C 545 * value will not be really used by the C
538 * library. 546 * library.
539 */ 547 */
540 hints.ai_socktype = SOCK_STREAM; 548 hints.ai_socktype = SOCK_STREAM;
541 rc = getaddrinfo(dns_params.hostname, servname, &hints, &res); 549 rc = getaddrinfo(dns_params.hostname, servname, &hints, &res);
542 if(rc) { 550 if (rc) {
543 write(child_out[1], &rc, sizeof(int)); 551 write(child_out[1], &rc, sizeof(int));
544 close(child_out[1]); 552 close(child_out[1]);
545 if(opt_debug) 553 if (opt_debug)
546 fprintf(stderr,"dns[%d] Error: getaddrinfo returned %d\n", 554 fprintf(stderr,"dns[%d] Error: getaddrinfo returned %d\n",
547 getpid(), rc); 555 getpid(), rc);
548 dns_params.hostname[0] = '\0'; 556 dns_params.hostname[0] = '\0';
549 continue; 557 continue;
550 } 558 }
551 write(child_out[1], &zero, sizeof(zero)); 559 write(child_out[1], &zero, sizeof(zero));
552 tmp = res; 560 tmp = res;
553 while(res) { 561 while (res) {
554 size_t ai_addrlen = res->ai_addrlen; 562 size_t ai_addrlen = res->ai_addrlen;
555 write(child_out[1], &ai_addrlen, sizeof(ai_addrlen)); 563 write(child_out[1], &ai_addrlen, sizeof(ai_addrlen));
556 write(child_out[1], res->ai_addr, res->ai_addrlen); 564 write(child_out[1], res->ai_addr, res->ai_addrlen);
557 res = res->ai_next; 565 res = res->ai_next;
558 } 566 }
559 freeaddrinfo(tmp); 567 freeaddrinfo(tmp);
560 write(child_out[1], &zero, sizeof(zero)); 568 write(child_out[1], &zero, sizeof(zero));
561 #else 569 #else
570 /* XXX - Should hostname be changed to dns_params.hostname? */
562 if (!inet_aton(hostname, &sin.sin_addr)) { 571 if (!inet_aton(hostname, &sin.sin_addr)) {
563 struct hostent *hp; 572 struct hostent *hp;
564 if(!(hp = gethostbyname(dns_params.hostname))) { 573 if (!(hp = gethostbyname(dns_params.hostname))) {
565 write(child_out[1], &h_errno, sizeof(int)); 574 write(child_out[1], &h_errno, sizeof(int));
566 close(child_out[1]); 575 close(child_out[1]);
567 if(opt_debug) 576 if (opt_debug)
568 fprintf(stderr,"DNS Error: %d\n", h_errno); 577 fprintf(stderr,"DNS Error: %d\n", h_errno);
569 _exit(0); 578 _exit(0);
570 } 579 }
571 memset(&sin, 0, sizeof(struct sockaddr_in)); 580 memset(&sin, 0, sizeof(struct sockaddr_in));
572 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); 581 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
582 dns_params.hostname[0] = '\0'; 591 dns_params.hostname[0] = '\0';
583 } 592 }
584 close(child_out[1]); 593 close(child_out[1]);
585 close(child_in[0]); 594 close(child_in[0]);
586 _exit(0); 595 _exit(0);
587 } 596 } /* End of child process */
597
598 /* We should not access the child's side of the pipe, so close them... */
588 close(child_out[1]); 599 close(child_out[1]);
589 close(child_in[0]); 600 close(child_in[0]);
590 if(req->dns_pid==-1) { 601 if (req->dns_pid==-1) {
591 gaim_debug(GAIM_DEBUG_ERROR, "dns", 602 gaim_debug(GAIM_DEBUG_ERROR, "dns",
592 "Could not create child process for DNS: %s\n", 603 "Could not create child process for DNS: %s\n",
593 strerror(errno)); 604 strerror(errno));
594 g_free(req); 605 g_free(req);
595 return -1; 606 return -1;
596 } 607 }
608 req->fd_out = child_out[0];
597 req->fd_in = child_in[1]; 609 req->fd_in = child_in[1];
598 req->fd_out = child_out[0];
599 number_of_dns_children++; 610 number_of_dns_children++;
600 gaim_debug(GAIM_DEBUG_INFO, "dns", 611 gaim_debug(GAIM_DEBUG_INFO, "dns",
601 "Created new DNS child %d, there are now %d children.\n", 612 "Created new DNS child %d, there are now %d children.\n",
602 req->dns_pid, number_of_dns_children); 613 req->dns_pid, number_of_dns_children);
603 } 614 }
604 req->host=g_strdup(hostname); 615
605 req->port=port; 616 req->host = g_strdup(dns_params.hostname);
606 req->callback=callback; 617 req->port = port;
607 req->data=data; 618 req->callback = callback;
619 req->data = data;
608 req->inpa = gaim_input_add(req->fd_out, GAIM_INPUT_READ, host_resolved, req); 620 req->inpa = gaim_input_add(req->fd_out, GAIM_INPUT_READ, host_resolved, req);
621
609 return 0; 622 return 0;
610 } 623 }
611 #else 624 #else /* __unix__ */
612 625
613 typedef struct { 626 typedef struct {
614 gpointer data; 627 gpointer data;
615 size_t addrlen; 628 size_t addrlen;
616 struct sockaddr *addr; 629 struct sockaddr *addr;
657 req->callback = callback; 670 req->callback = callback;
658 gaim_timeout_add(10, host_resolved, req); 671 gaim_timeout_add(10, host_resolved, req);
659 return 0; 672 return 0;
660 } 673 }
661 674
662 #endif 675 #endif /* __unix__ */
663 676
664 static void 677 static void
665 no_one_calls(gpointer data, gint source, GaimInputCondition cond) 678 no_one_calls(gpointer data, gint source, GaimInputCondition cond)
666 { 679 {
667 struct PHB *phb = data; 680 struct PHB *phb = data;