Mercurial > pidgin
comparison src/proxy.c @ 10711:00483ba950bf
[gaim-migrate @ 12301]
Add some comments to the proxy code, rename some functions, and shuffle
things around in a way that I think makes it much more readable.
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Mon, 21 Mar 2005 02:14:46 +0000 |
| parents | cc9922ce3a52 |
| children | dcbc56eb3f37 |
comparison
equal
deleted
inserted
replaced
| 10710:a2c0ce632bec | 10711:00483ba950bf |
|---|---|
| 189 typedef void (*dns_callback_t)(GSList *hosts, gpointer data, | 189 typedef void (*dns_callback_t)(GSList *hosts, gpointer data, |
| 190 const char *error_message); | 190 const char *error_message); |
| 191 | 191 |
| 192 #ifdef __unix__ | 192 #ifdef __unix__ |
| 193 | 193 |
| 194 /* This structure represents both a pending DNS request and | 194 /* |
| 195 * a free child process. | 195 * This structure represents both a pending DNS request and |
| 196 * a free child process. | |
| 196 */ | 197 */ |
| 197 typedef struct { | 198 typedef struct { |
| 198 char *host; | 199 char *host; |
| 199 int port; | 200 int port; |
| 200 dns_callback_t callback; | 201 dns_callback_t callback; |
| 220 dns_params_t params; | 221 dns_params_t params; |
| 221 dns_callback_t callback; | 222 dns_callback_t callback; |
| 222 gpointer data; | 223 gpointer data; |
| 223 } queued_dns_request_t; | 224 } queued_dns_request_t; |
| 224 | 225 |
| 225 static void req_free(pending_dns_request_t *req) | 226 /* |
| 227 * Begin the DNS resolver child process functions. | |
| 228 */ | |
| 229 #ifdef HAVE_SIGNAL_H | |
| 230 static void | |
| 231 trap_gdb_bug() | |
| 232 { | |
| 233 const char *message = | |
| 234 "Gaim's DNS child got a SIGTRAP signal. \n" | |
| 235 "This can be caused by trying to run gaim inside gdb.\n" | |
| 236 "There is a known gdb bug which prevents this. Supposedly gaim\n" | |
| 237 "should have detected you were using gdb and used an ugly hack,\n" | |
| 238 "check cope_with_gdb_brokenness() in proxy.c.\n\n" | |
| 239 "For more info about this bug, see http://sources.redhat.com/ml/gdb/2001-07/msg00349.html\n"; | |
| 240 fputs("\n* * *\n",stderr); | |
| 241 fputs(message,stderr); | |
| 242 fputs("* * *\n\n",stderr); | |
| 243 execlp("xmessage","xmessage","-center", message, NULL); | |
| 244 _exit(1); | |
| 245 } | |
| 246 #endif | |
| 247 | |
| 248 static void | |
| 249 cope_with_gdb_brokenness() | |
| 250 { | |
| 251 #ifdef __linux__ | |
| 252 static gboolean already_done = FALSE; | |
| 253 char s[256], e[512]; | |
| 254 int n; | |
| 255 pid_t ppid; | |
| 256 | |
| 257 if(already_done) | |
| 258 return; | |
| 259 already_done = TRUE; | |
| 260 ppid = getppid(); | |
| 261 snprintf(s, sizeof(s), "/proc/%d/exe", ppid); | |
| 262 n = readlink(s, e, sizeof(e)); | |
| 263 if(n < 0) | |
| 264 return; | |
| 265 | |
| 266 e[MIN(n,sizeof(e)-1)] = '\0'; | |
| 267 | |
| 268 if(strstr(e,"gdb")) { | |
| 269 gaim_debug_info("dns", | |
| 270 "Debugger detected, performing useless query...\n"); | |
| 271 gethostbyname("x.x.x.x.x"); | |
| 272 } | |
| 273 #endif | |
| 274 } | |
| 275 | |
| 276 static void | |
| 277 gaim_dns_resolverthread(int child_out, int child_in, gboolean show_debug) | |
| 278 { | |
| 279 dns_params_t dns_params; | |
| 280 const size_t zero = 0; | |
| 281 int rc; | |
| 282 #if HAVE_GETADDRINFO | |
| 283 struct addrinfo hints, *res, *tmp; | |
| 284 char servname[20]; | |
| 285 #else | |
| 286 struct sockaddr_in sin; | |
| 287 const size_t addrlen = sizeof(sin); | |
| 288 #endif | |
| 289 | |
| 290 #ifdef HAVE_SIGNAL_H | |
| 291 signal(SIGHUP, SIG_DFL); | |
| 292 signal(SIGINT, SIG_DFL); | |
| 293 signal(SIGQUIT, SIG_DFL); | |
| 294 signal(SIGCHLD, SIG_DFL); | |
| 295 signal(SIGTERM, SIG_DFL); | |
| 296 signal(SIGTRAP, trap_gdb_bug); | |
| 297 #endif | |
| 298 | |
| 299 /* | |
| 300 * We resolve 1 host name for each iteration of this | |
| 301 * while loop. | |
| 302 * | |
| 303 * The top half of this reads in the hostname and port | |
| 304 * number from the socket with our parent. The bottom | |
| 305 * half of this resolves the IP (blocking) and sends | |
| 306 * the result back to our parent, when finished. | |
| 307 */ | |
| 308 while (1) { | |
| 309 const char ch = 'Y'; | |
| 310 fd_set fds; | |
| 311 struct timeval tv = { .tv_sec = 40 , .tv_usec = 0 }; | |
| 312 FD_ZERO(&fds); | |
| 313 FD_SET(child_in, &fds); | |
| 314 rc = select(child_in + 1, &fds, NULL, NULL, &tv); | |
| 315 if (!rc) { | |
| 316 if (show_debug) | |
| 317 fprintf(stderr,"dns[%d]: nobody needs me... =(\n", getpid()); | |
| 318 break; | |
| 319 } | |
| 320 rc = read(child_in, &dns_params, sizeof(dns_params_t)); | |
| 321 if (rc < 0) { | |
| 322 perror("read()"); | |
| 323 break; | |
| 324 } | |
| 325 if (rc == 0) { | |
| 326 if (show_debug) | |
| 327 fprintf(stderr,"dns[%d]: Oops, father has gone, wait for me, wait...!\n", getpid()); | |
| 328 _exit(0); | |
| 329 } | |
| 330 if (dns_params.hostname[0] == '\0') { | |
| 331 fprintf(stderr, "dns[%d]: hostname = \"\" (port = %d)!!!\n", getpid(), dns_params.port); | |
| 332 _exit(1); | |
| 333 } | |
| 334 /* Tell our parent that we read the data successfully */ | |
| 335 write(child_out, &ch, sizeof(ch)); | |
| 336 | |
| 337 /* We have the hostname and port, now resolve the IP */ | |
| 338 | |
| 339 #if HAVE_GETADDRINFO | |
| 340 g_snprintf(servname, sizeof(servname), "%d", dns_params.port); | |
| 341 memset(&hints, 0, sizeof(hints)); | |
| 342 | |
| 343 /* This is only used to convert a service | |
| 344 * name to a port number. As we know we are | |
| 345 * passing a number already, we know this | |
| 346 * value will not be really used by the C | |
| 347 * library. | |
| 348 */ | |
| 349 hints.ai_socktype = SOCK_STREAM; | |
| 350 rc = getaddrinfo(dns_params.hostname, servname, &hints, &res); | |
| 351 write(child_out, &rc, sizeof(rc)); | |
| 352 if (rc != 0) { | |
| 353 close(child_out); | |
| 354 if (show_debug) | |
| 355 fprintf(stderr,"dns[%d] Error: getaddrinfo returned %d\n", | |
| 356 getpid(), rc); | |
| 357 dns_params.hostname[0] = '\0'; | |
| 358 continue; | |
| 359 } | |
| 360 tmp = res; | |
| 361 while (res) { | |
| 362 size_t ai_addrlen = res->ai_addrlen; | |
| 363 write(child_out, &ai_addrlen, sizeof(ai_addrlen)); | |
| 364 write(child_out, res->ai_addr, res->ai_addrlen); | |
| 365 res = res->ai_next; | |
| 366 } | |
| 367 freeaddrinfo(tmp); | |
| 368 write(child_out, &zero, sizeof(zero)); | |
| 369 #else | |
| 370 if (!inet_aton(dns_params.hostname, &sin.sin_addr)) { | |
| 371 struct hostent *hp; | |
| 372 if (!(hp = gethostbyname(dns_params.hostname))) { | |
| 373 write(child_out, &h_errno, sizeof(int)); | |
| 374 close(child_out); | |
| 375 if (show_debug) | |
| 376 fprintf(stderr,"DNS Error: %d\n", h_errno); | |
| 377 _exit(0); | |
| 378 } | |
| 379 memset(&sin, 0, sizeof(struct sockaddr_in)); | |
| 380 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); | |
| 381 sin.sin_family = hp->h_addrtype; | |
| 382 } else | |
| 383 sin.sin_family = AF_INET; | |
| 384 | |
| 385 sin.sin_port = htons(dns_params.port); | |
| 386 write(child_out, &addrlen, sizeof(addrlen)); | |
| 387 write(child_out, &sin, addrlen); | |
| 388 write(child_out, &zero, sizeof(zero)); | |
| 389 #endif | |
| 390 dns_params.hostname[0] = '\0'; | |
| 391 } | |
| 392 | |
| 393 close(child_out); | |
| 394 close(child_in); | |
| 395 | |
| 396 _exit(0); | |
| 397 } | |
| 398 | |
| 399 static pending_dns_request_t * | |
| 400 gaim_dns_new_resolverthread(gboolean show_debug) | |
| 401 { | |
| 402 pending_dns_request_t *req; | |
| 403 int child_out[2], child_in[2]; | |
| 404 | |
| 405 /* Create pipes for communicating with the child process */ | |
| 406 if (pipe(child_out) || pipe(child_in)) { | |
| 407 gaim_debug_error("dns", | |
| 408 "Could not create pipes: %s\n", strerror(errno)); | |
| 409 return NULL; | |
| 410 } | |
| 411 | |
| 412 req = g_new(pending_dns_request_t, 1); | |
| 413 | |
| 414 cope_with_gdb_brokenness(); | |
| 415 | |
| 416 /* Fork! */ | |
| 417 req->dns_pid = fork(); | |
| 418 | |
| 419 /* If we are the child process... */ | |
| 420 if (req->dns_pid == 0) { | |
| 421 /* We should not access the parent's side of the pipes, so close them */ | |
| 422 close(child_out[0]); | |
| 423 close(child_in[1]); | |
| 424 | |
| 425 gaim_dns_resolverthread(child_out[1], child_in[0], show_debug); | |
| 426 /* The thread calls _exit() rather than returning, so we never get here */ | |
| 427 } | |
| 428 | |
| 429 /* We should not access the child's side of the pipes, so close them */ | |
| 430 close(child_out[1]); | |
| 431 close(child_in[0]); | |
| 432 if (req->dns_pid == -1) { | |
| 433 gaim_debug_error("dns", | |
| 434 "Could not create child process for DNS: %s\n", | |
| 435 strerror(errno)); | |
| 436 g_free(req); | |
| 437 return NULL; | |
| 438 } | |
| 439 | |
| 440 req->fd_out = child_out[0]; | |
| 441 req->fd_in = child_in[1]; | |
| 442 number_of_dns_children++; | |
| 443 gaim_debug_info("dns", | |
| 444 "Created new DNS child %d, there are now %d children.\n", | |
| 445 req->dns_pid, number_of_dns_children); | |
| 446 | |
| 447 return req; | |
| 448 } | |
| 449 /* | |
| 450 * End the DNS resolver child process functions. | |
| 451 */ | |
| 452 | |
| 453 /* | |
| 454 * Begin the functions for dealing with the DNS child processes. | |
| 455 */ | |
| 456 static void | |
| 457 req_free(pending_dns_request_t *req) | |
| 226 { | 458 { |
| 227 g_return_if_fail(req != NULL); | 459 g_return_if_fail(req != NULL); |
| 228 | 460 |
| 229 close(req->fd_in); | 461 close(req->fd_in); |
| 230 close(req->fd_out); | 462 close(req->fd_out); |
| 233 g_free(req); | 465 g_free(req); |
| 234 | 466 |
| 235 number_of_dns_children--; | 467 number_of_dns_children--; |
| 236 } | 468 } |
| 237 | 469 |
| 238 static int send_dns_request_to_child(pending_dns_request_t *req, dns_params_t *dns_params) | 470 static int |
| 471 send_dns_request_to_child(pending_dns_request_t *req, dns_params_t *dns_params) | |
| 239 { | 472 { |
| 240 char ch; | 473 char ch; |
| 241 int rc; | 474 int rc; |
| 242 | 475 |
| 243 /* Are you alive? */ | 476 /* Are you alive? */ |
| 274 "Successfully sent DNS request to child %d\n", req->dns_pid); | 507 "Successfully sent DNS request to child %d\n", req->dns_pid); |
| 275 | 508 |
| 276 return 0; | 509 return 0; |
| 277 } | 510 } |
| 278 | 511 |
| 279 static void host_resolved(gpointer data, gint source, GaimInputCondition cond); | 512 static void |
| 280 | 513 host_resolved(gpointer data, gint source, GaimInputCondition cond); |
| 281 static void release_dns_child(pending_dns_request_t *req) | 514 |
| 515 static void | |
| 516 release_dns_child(pending_dns_request_t *req) | |
| 282 { | 517 { |
| 283 g_free(req->host); | 518 g_free(req->host); |
| 284 req->host = NULL; | 519 req->host = NULL; |
| 285 | 520 |
| 286 if (queued_requests && !g_queue_is_empty(queued_requests)) { | 521 if (queued_requests && !g_queue_is_empty(queued_requests)) { |
| 313 req->data = NULL; | 548 req->data = NULL; |
| 314 free_dns_children = g_slist_append(free_dns_children, req); | 549 free_dns_children = g_slist_append(free_dns_children, req); |
| 315 } | 550 } |
| 316 } | 551 } |
| 317 | 552 |
| 318 static void host_resolved(gpointer data, gint source, GaimInputCondition cond) | 553 static void |
| 554 host_resolved(gpointer data, gint source, GaimInputCondition cond) | |
| 319 { | 555 { |
| 320 pending_dns_request_t *req = (pending_dns_request_t*)data; | 556 pending_dns_request_t *req = (pending_dns_request_t*)data; |
| 321 int rc, err; | 557 int rc, err; |
| 322 GSList *hosts = NULL; | 558 GSList *hosts = NULL; |
| 323 struct sockaddr *addr = NULL; | 559 struct sockaddr *addr = NULL; |
| 376 | 612 |
| 377 req->callback(hosts, req->data, NULL); | 613 req->callback(hosts, req->data, NULL); |
| 378 | 614 |
| 379 release_dns_child(req); | 615 release_dns_child(req); |
| 380 } | 616 } |
| 381 | 617 /* |
| 382 static void trap_gdb_bug() | 618 * End the functions for dealing with the DNS child processes. |
| 383 { | 619 */ |
| 384 const char *message = | 620 |
| 385 "Gaim's DNS child got a SIGTRAP signal. \n" | 621 int |
| 386 "This can be caused by trying to run gaim inside gdb.\n" | 622 gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data) |
| 387 "There is a known gdb bug which prevents this. Supposedly gaim\n" | |
| 388 "should have detected you were using gdb and used an ugly hack,\n" | |
| 389 "check cope_with_gdb_brokenness() in proxy.c.\n\n" | |
| 390 "For more info about this bug, see http://sources.redhat.com/ml/gdb/2001-07/msg00349.html\n"; | |
| 391 fputs("\n* * *\n",stderr); | |
| 392 fputs(message,stderr); | |
| 393 fputs("* * *\n\n",stderr); | |
| 394 execlp("xmessage","xmessage","-center", message, NULL); | |
| 395 _exit(1); | |
| 396 } | |
| 397 | |
| 398 static void cope_with_gdb_brokenness() | |
| 399 { | |
| 400 #ifdef __linux__ | |
| 401 static gboolean already_done = FALSE; | |
| 402 char s[256], e[512]; | |
| 403 int n; | |
| 404 pid_t ppid; | |
| 405 | |
| 406 if(already_done) | |
| 407 return; | |
| 408 already_done = TRUE; | |
| 409 ppid = getppid(); | |
| 410 snprintf(s, sizeof(s), "/proc/%d/exe", ppid); | |
| 411 n = readlink(s, e, sizeof(e)); | |
| 412 if(n < 0) | |
| 413 return; | |
| 414 | |
| 415 e[MIN(n,sizeof(e)-1)] = '\0'; | |
| 416 | |
| 417 if(strstr(e,"gdb")) { | |
| 418 gaim_debug_info("dns", | |
| 419 "Debugger detected, performing useless query...\n"); | |
| 420 gethostbyname("x.x.x.x.x"); | |
| 421 } | |
| 422 #endif | |
| 423 } | |
| 424 | |
| 425 static void | |
| 426 gaim_dns_childthread(int child_out, int child_in, dns_params_t *dns_params, gboolean show_debug) | |
| 427 { | |
| 428 const size_t zero = 0; | |
| 429 int rc; | |
| 430 #if HAVE_GETADDRINFO | |
| 431 struct addrinfo hints, *res, *tmp; | |
| 432 char servname[20]; | |
| 433 #else | |
| 434 struct sockaddr_in sin; | |
| 435 const size_t addrlen = sizeof(sin); | |
| 436 #endif | |
| 437 | |
| 438 #ifdef HAVE_SIGNAL_H | |
| 439 signal(SIGHUP, SIG_DFL); | |
| 440 signal(SIGINT, SIG_DFL); | |
| 441 signal(SIGQUIT, SIG_DFL); | |
| 442 signal(SIGCHLD, SIG_DFL); | |
| 443 signal(SIGTERM, SIG_DFL); | |
| 444 signal(SIGTRAP, trap_gdb_bug); | |
| 445 #endif | |
| 446 | |
| 447 while (1) { | |
| 448 if (dns_params->hostname[0] == '\0') { | |
| 449 const char ch = 'Y'; | |
| 450 fd_set fds; | |
| 451 struct timeval tv = { .tv_sec = 40 , .tv_usec = 0 }; | |
| 452 FD_ZERO(&fds); | |
| 453 FD_SET(child_in, &fds); | |
| 454 rc = select(child_in + 1, &fds, NULL, NULL, &tv); | |
| 455 if (!rc) { | |
| 456 if (show_debug) | |
| 457 fprintf(stderr,"dns[%d]: nobody needs me... =(\n", getpid()); | |
| 458 break; | |
| 459 } | |
| 460 rc = read(child_in, dns_params, sizeof(dns_params_t)); | |
| 461 if (rc < 0) { | |
| 462 perror("read()"); | |
| 463 break; | |
| 464 } | |
| 465 if (rc == 0) { | |
| 466 if (show_debug) | |
| 467 fprintf(stderr,"dns[%d]: Oops, father has gone, wait for me, wait...!\n", getpid()); | |
| 468 _exit(0); | |
| 469 } | |
| 470 if (dns_params->hostname[0] == '\0') { | |
| 471 fprintf(stderr, "dns[%d]: hostname = \"\" (port = %d)!!!\n", getpid(), dns_params->port); | |
| 472 _exit(1); | |
| 473 } | |
| 474 write(child_out, &ch, sizeof(ch)); | |
| 475 } | |
| 476 | |
| 477 #if HAVE_GETADDRINFO | |
| 478 g_snprintf(servname, sizeof(servname), "%d", dns_params->port); | |
| 479 memset(&hints, 0, sizeof(hints)); | |
| 480 | |
| 481 /* This is only used to convert a service | |
| 482 * name to a port number. As we know we are | |
| 483 * passing a number already, we know this | |
| 484 * value will not be really used by the C | |
| 485 * library. | |
| 486 */ | |
| 487 hints.ai_socktype = SOCK_STREAM; | |
| 488 rc = getaddrinfo(dns_params->hostname, servname, &hints, &res); | |
| 489 write(child_out, &rc, sizeof(rc)); | |
| 490 if (rc != 0) { | |
| 491 close(child_out); | |
| 492 if (show_debug) | |
| 493 fprintf(stderr,"dns[%d] Error: getaddrinfo returned %d\n", | |
| 494 getpid(), rc); | |
| 495 dns_params->hostname[0] = '\0'; | |
| 496 continue; | |
| 497 } | |
| 498 tmp = res; | |
| 499 while (res) { | |
| 500 size_t ai_addrlen = res->ai_addrlen; | |
| 501 write(child_out, &ai_addrlen, sizeof(ai_addrlen)); | |
| 502 write(child_out, res->ai_addr, res->ai_addrlen); | |
| 503 res = res->ai_next; | |
| 504 } | |
| 505 freeaddrinfo(tmp); | |
| 506 write(child_out, &zero, sizeof(zero)); | |
| 507 #else | |
| 508 if (!inet_aton(dns_params->hostname, &sin.sin_addr)) { | |
| 509 struct hostent *hp; | |
| 510 if (!(hp = gethostbyname(dns_params->hostname))) { | |
| 511 write(child_out, &h_errno, sizeof(int)); | |
| 512 close(child_out); | |
| 513 if (show_debug) | |
| 514 fprintf(stderr,"DNS Error: %d\n", h_errno); | |
| 515 _exit(0); | |
| 516 } | |
| 517 memset(&sin, 0, sizeof(struct sockaddr_in)); | |
| 518 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); | |
| 519 sin.sin_family = hp->h_addrtype; | |
| 520 } else | |
| 521 sin.sin_family = AF_INET; | |
| 522 | |
| 523 sin.sin_port = htons(dns_params->port); | |
| 524 write(child_out, &addrlen, sizeof(addrlen)); | |
| 525 write(child_out, &sin, addrlen); | |
| 526 write(child_out, &zero, sizeof(zero)); | |
| 527 #endif | |
| 528 dns_params->hostname[0] = '\0'; | |
| 529 } | |
| 530 | |
| 531 close(child_out); | |
| 532 close(child_in); | |
| 533 | |
| 534 _exit(0); | |
| 535 } | |
| 536 | |
| 537 int gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data) | |
| 538 { | 623 { |
| 539 pending_dns_request_t *req = NULL; | 624 pending_dns_request_t *req = NULL; |
| 540 dns_params_t dns_params; | 625 dns_params_t dns_params; |
| 541 gchar *host_temp; | 626 gchar *host_temp; |
| 542 gboolean show_debug; | 627 gboolean show_debug; |
| 567 req = NULL; | 652 req = NULL; |
| 568 } | 653 } |
| 569 | 654 |
| 570 /* We need to create a new DNS request child */ | 655 /* We need to create a new DNS request child */ |
| 571 if (req == NULL) { | 656 if (req == NULL) { |
| 572 int child_out[2], child_in[2]; | |
| 573 | |
| 574 if (number_of_dns_children >= MAX_DNS_CHILDREN) { | 657 if (number_of_dns_children >= MAX_DNS_CHILDREN) { |
| 575 queued_dns_request_t *r = g_new(queued_dns_request_t, 1); | 658 queued_dns_request_t *r = g_new(queued_dns_request_t, 1); |
| 576 memcpy(&(r->params), &dns_params, sizeof(dns_params)); | 659 memcpy(&(r->params), &dns_params, sizeof(dns_params)); |
| 577 r->callback = callback; | 660 r->callback = callback; |
| 578 r->data = data; | 661 r->data = data; |
| 584 "DNS query for '%s' queued\n", dns_params.hostname); | 667 "DNS query for '%s' queued\n", dns_params.hostname); |
| 585 | 668 |
| 586 return 0; | 669 return 0; |
| 587 } | 670 } |
| 588 | 671 |
| 589 /* Create pipes for communicating with the child process */ | 672 req = gaim_dns_new_resolverthread(show_debug); |
| 590 if (pipe(child_out) || pipe(child_in)) { | 673 send_dns_request_to_child(req, &dns_params); |
| 591 gaim_debug_error("dns", | |
| 592 "Could not create pipes: %s\n", strerror(errno)); | |
| 593 return -1; | |
| 594 } | |
| 595 | |
| 596 req = g_new(pending_dns_request_t, 1); | |
| 597 | |
| 598 cope_with_gdb_brokenness(); | |
| 599 | |
| 600 /* Fork! */ | |
| 601 req->dns_pid = fork(); | |
| 602 | |
| 603 /* If we are the child process... */ | |
| 604 if (req->dns_pid == 0) { | |
| 605 /* We should not access the parent's side of the pipe, so close them... */ | |
| 606 close(child_out[0]); | |
| 607 close(child_in[1]); | |
| 608 | |
| 609 gaim_dns_childthread(child_out[1], child_in[0], &dns_params, show_debug); | |
| 610 /* The thread calls _exit() rather than returning, so we never get here */ | |
| 611 } | |
| 612 | |
| 613 /* We should not access the child's side of the pipe, so close them... */ | |
| 614 close(child_out[1]); | |
| 615 close(child_in[0]); | |
| 616 if (req->dns_pid == -1) { | |
| 617 gaim_debug_error("dns", | |
| 618 "Could not create child process for DNS: %s\n", | |
| 619 strerror(errno)); | |
| 620 g_free(req); | |
| 621 return -1; | |
| 622 } | |
| 623 | |
| 624 req->fd_out = child_out[0]; | |
| 625 req->fd_in = child_in[1]; | |
| 626 number_of_dns_children++; | |
| 627 gaim_debug_info("dns", | |
| 628 "Created new DNS child %d, there are now %d children.\n", | |
| 629 req->dns_pid, number_of_dns_children); | |
| 630 } | 674 } |
| 631 | 675 |
| 632 req->host = g_strdup(hostname); | 676 req->host = g_strdup(hostname); |
| 633 req->port = port; | 677 req->port = port; |
| 634 req->callback = callback; | 678 req->callback = callback; |
| 715 /* back to main thread */ | 759 /* back to main thread */ |
| 716 g_idle_add(dns_main_thread_cb, td); | 760 g_idle_add(dns_main_thread_cb, td); |
| 717 return 0; | 761 return 0; |
| 718 } | 762 } |
| 719 | 763 |
| 720 int gaim_gethostbyname_async(const char *hostname, int port, | 764 int |
| 721 dns_callback_t callback, gpointer data) { | 765 gaim_gethostbyname_async(const char *hostname, int port, |
| 766 dns_callback_t callback, gpointer data) | |
| 767 { | |
| 722 dns_tdata *td; | 768 dns_tdata *td; |
| 723 struct sockaddr_in sin; | 769 struct sockaddr_in sin; |
| 724 GError* err = NULL; | 770 GError* err = NULL; |
| 725 | 771 |
| 726 if(inet_aton(hostname, &sin.sin_addr)) { | 772 if(inet_aton(hostname, &sin.sin_addr)) { |
