Mercurial > pidgin.yaz
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; |
