aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlurchi <lurchi@strangeplace.net>2018-06-24 23:31:07 +0200
committerlurchi <lurchi@strangeplace.net>2018-06-24 23:31:07 +0200
commitc38455c65f9968ccf7e870c3cce30fa19f319376 (patch)
tree523075af0d81a9f460d60b90b51557ad83bd5b42
parent92e03f9117f5dc29909d73707897d28d8e27e048 (diff)
downloadgnunet-c38455c65f9968ccf7e870c3cce30fa19f319376.tar.gz
gnunet-c38455c65f9968ccf7e870c3cce30fa19f319376.zip
use the asynchronous DNS resolution API (getaddrinfo_a) in the resolver module
-rw-r--r--configure.ac8
-rw-r--r--src/util/Makefile.am3
-rw-r--r--src/util/gnunet-service-resolver.c269
-rw-r--r--src/util/resolver.h27
-rw-r--r--src/util/resolver_api.c37
-rw-r--r--src/util/test_resolver_api.c2
6 files changed, 299 insertions, 47 deletions
diff --git a/configure.ac b/configure.ac
index 99eeeba8a..fc44dcf5a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,7 +58,7 @@ fi
58# Use Linux interface name unless the OS has a different preference 58# Use Linux interface name unless the OS has a different preference
59DEFAULT_INTERFACE="\"eth0\"" 59DEFAULT_INTERFACE="\"eth0\""
60 60
61funcstocheck="getnameinfo gethostname gethostbyname gethostbyaddr getaddrinfo" 61funcstocheck="getnameinfo gethostname gethostbyname gethostbyaddr getaddrinfo getaddrinfo_a"
62 62
63# Srcdir in a form that native compiler understands (i.e. DOS path on W32) 63# Srcdir in a form that native compiler understands (i.e. DOS path on W32)
64native_srcdir=$srcdir 64native_srcdir=$srcdir
@@ -230,6 +230,10 @@ AC_CHECK_DECLS([_stati64])
230# will be more selective! 230# will be more selective!
231SAVE_LIBS=$LIBS 231SAVE_LIBS=$LIBS
232 232
233have_addrinfo_a=0
234AC_CHECK_LIB(anl, getaddrinfo_a, [have_addrinfo_a=1 AC_DEFINE(HAVE_GETADDRINFO_A,1,[getaddrinfo_a supported])])
235AM_CONDITIONAL(HAVE_GETADDRINFO_A, [test "$have_addrinfo_a" = 1])
236
233# tests only run on Windows 237# tests only run on Windows
234if test "x$build_target" = "xmingw" 238if test "x$build_target" = "xmingw"
235then 239then
@@ -1537,7 +1541,7 @@ AC_LINK_IFELSE(
1537 ],[ 1541 ],[
1538 AC_DEFINE_UNQUOTED([HAVE_GETADDRINFO],1,[Define this if getaddrinfo() is available]) 1542 AC_DEFINE_UNQUOTED([HAVE_GETADDRINFO],1,[Define this if getaddrinfo() is available])
1539 ],[ 1543 ],[
1540 AC_DEFINE_UNQUOTED([HAVE_GETADDRINFO],1,[Define this if getaddrinfo() is available]) 1544 AC_DEFINE_UNQUOTED([HAVE_GETADDRINFO],0,[Define this if getaddrinfo() is available])
1541 ]) 1545 ])
1542 1546
1543else 1547else
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 208cab07b..4296199db 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -199,6 +199,9 @@ gnunet_service_resolver_SOURCES = \
199gnunet_service_resolver_LDADD = \ 199gnunet_service_resolver_LDADD = \
200 libgnunetutil.la \ 200 libgnunetutil.la \
201 $(GN_LIBINTL) 201 $(GN_LIBINTL)
202if HAVE_GETADDRINFO_A
203gnunet_service_resolver_LDADD += -lanl
204endif
202 205
203 206
204gnunet_resolver_SOURCES = \ 207gnunet_resolver_SOURCES = \
diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c
index d26ec659f..d90d8ec10 100644
--- a/src/util/gnunet-service-resolver.c
+++ b/src/util/gnunet-service-resolver.c
@@ -84,6 +84,16 @@ static struct IPCache *cache_head;
84 */ 84 */
85static struct IPCache *cache_tail; 85static struct IPCache *cache_tail;
86 86
87/**
88 * Pipe for asynchronously notifying about resolve result
89 */
90static struct GNUNET_DISK_PipeHandle *resolve_result_pipe;
91
92/**
93 * Task for reading from resolve_result_pipe
94 */
95static struct GNUNET_SCHEDULER_Task *resolve_result_pipe_task;
96
87 97
88#if HAVE_GETNAMEINFO 98#if HAVE_GETNAMEINFO
89/** 99/**
@@ -223,14 +233,15 @@ notify_service_client_done (void *cls)
223static void 233static void
224get_ip_as_string (struct GNUNET_SERVICE_Client *client, 234get_ip_as_string (struct GNUNET_SERVICE_Client *client,
225 int af, 235 int af,
226 const void *ip) 236 const void *ip,
237 uint32_t request_id)
227{ 238{
228 struct IPCache *pos; 239 struct IPCache *pos;
229 struct IPCache *next; 240 struct IPCache *next;
230 struct GNUNET_TIME_Absolute now; 241 struct GNUNET_TIME_Absolute now;
231 struct GNUNET_MQ_Envelope *env; 242 struct GNUNET_MQ_Envelope *env;
232 struct GNUNET_MQ_Handle *mq; 243 struct GNUNET_MQ_Handle *mq;
233 struct GNUNET_MessageHeader *msg; 244 struct GNUNET_RESOLVER_ResponseMessage *msg;
234 size_t ip_len; 245 size_t ip_len;
235 struct in6_addr ix; 246 struct in6_addr ix;
236 size_t alen; 247 size_t alen;
@@ -304,13 +315,16 @@ get_ip_as_string (struct GNUNET_SERVICE_Client *client,
304 env = GNUNET_MQ_msg_extra (msg, 315 env = GNUNET_MQ_msg_extra (msg,
305 alen, 316 alen,
306 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 317 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
318 msg->id = request_id;
307 GNUNET_memcpy (&msg[1], 319 GNUNET_memcpy (&msg[1],
308 pos->addr, 320 pos->addr,
309 alen); 321 alen);
310 GNUNET_MQ_send (mq, 322 GNUNET_MQ_send (mq,
311 env); 323 env);
324 // send end message
312 env = GNUNET_MQ_msg (msg, 325 env = GNUNET_MQ_msg (msg,
313 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 326 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
327 msg->id = request_id;
314 GNUNET_MQ_notify_sent (env, 328 GNUNET_MQ_notify_sent (env,
315 &notify_service_client_done, 329 &notify_service_client_done,
316 client); 330 client);
@@ -319,17 +333,152 @@ get_ip_as_string (struct GNUNET_SERVICE_Client *client,
319} 333}
320 334
321 335
322#if HAVE_GETADDRINFO 336#if HAVE_GETADDRINFO_A
337struct AsyncCls
338{
339 struct gaicb *host;
340 struct sigevent *sig;
341 struct GNUNET_MQ_Handle *mq;
342 uint32_t request_id;
343};
344
345
346static void
347resolve_result_pipe_cb (void *cls)
348{
349 struct AsyncCls *async_cls;
350 struct gaicb *host;
351 struct GNUNET_RESOLVER_ResponseMessage *msg;
352 struct GNUNET_MQ_Envelope *env;
353
354 GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle (resolve_result_pipe,
355 GNUNET_DISK_PIPE_END_READ),
356 &async_cls,
357 sizeof (struct AsyncCls *));
358 resolve_result_pipe_task =
359 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
360 GNUNET_DISK_pipe_handle (resolve_result_pipe,
361 GNUNET_DISK_PIPE_END_READ),
362 &resolve_result_pipe_cb,
363 NULL);
364 host = async_cls->host;
365 for (struct addrinfo *pos = host->ar_result; pos != NULL; pos = pos->ai_next)
366 {
367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 "Lookup result for hostname %s: %s (request ID %u)\n",
369 host->ar_name,
370 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen),
371 async_cls->request_id);
372 switch (pos->ai_family)
373 {
374 case AF_INET:
375 env = GNUNET_MQ_msg_extra (msg,
376 sizeof (struct in_addr),
377 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
378 msg->id = async_cls->request_id;
379 GNUNET_memcpy (&msg[1],
380 &((struct sockaddr_in*) pos->ai_addr)->sin_addr,
381 sizeof (struct in_addr));
382 GNUNET_MQ_send (async_cls->mq,
383 env);
384 break;
385 case AF_INET6:
386 env = GNUNET_MQ_msg_extra (msg,
387 sizeof (struct in6_addr),
388 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
389 msg->id = async_cls->request_id;
390 GNUNET_memcpy (&msg[1],
391 &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr,
392 sizeof (struct in6_addr));
393 GNUNET_MQ_send (async_cls->mq,
394 env);
395 break;
396 default:
397 /* unsupported, skip */
398 break;
399 }
400 }
401 // send end message
402 env = GNUNET_MQ_msg (msg,
403 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
404 msg->id = async_cls->request_id;
405 GNUNET_MQ_send (async_cls->mq,
406 env);
407 freeaddrinfo (host->ar_result);
408 GNUNET_free ((struct gaicb *)host->ar_request); // free hints
409 GNUNET_free (host);
410 GNUNET_free (async_cls->sig);
411 GNUNET_free (async_cls);
412}
413
414
415static void
416handle_async_result (union sigval val)
417{
418 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (resolve_result_pipe,
419 GNUNET_DISK_PIPE_END_WRITE),
420 &val.sival_ptr,
421 sizeof (val.sival_ptr));
422}
423
424
425static int
426getaddrinfo_a_resolve (struct GNUNET_MQ_Handle *mq,
427 const char *hostname,
428 int af,
429 uint32_t request_id)
430{
431 int ret;
432 struct gaicb *host;
433 struct addrinfo *hints;
434 struct sigevent *sig;
435 struct AsyncCls *async_cls;
436
437 host = GNUNET_new (struct gaicb);
438 hints = GNUNET_new (struct addrinfo);
439 sig = GNUNET_new (struct sigevent);
440 async_cls = GNUNET_new (struct AsyncCls);
441 memset (hints,
442 0,
443 sizeof (struct addrinfo));
444 memset (sig,
445 0,
446 sizeof (struct sigevent));
447 hints->ai_family = af;
448 hints->ai_socktype = SOCK_STREAM; /* go for TCP */
449 host->ar_name = hostname;
450 host->ar_service = NULL;
451 host->ar_request = hints;
452 host->ar_result = NULL;
453 sig->sigev_notify = SIGEV_THREAD;
454 sig->sigev_value.sival_ptr = async_cls;
455 sig->sigev_notify_function = &handle_async_result;
456 async_cls->host = host;
457 async_cls->sig = sig;
458 async_cls->mq = mq;
459 async_cls->request_id = request_id;
460 ret = getaddrinfo_a (GAI_NOWAIT,
461 &host,
462 1,
463 sig);
464 if (0 != ret)
465 return GNUNET_SYSERR;
466 return GNUNET_OK;
467}
468
469
470#elif HAVE_GETADDRINFO
323static int 471static int
324getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq, 472getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq,
325 const char *hostname, 473 const char *hostname,
326 int af) 474 int af,
475 uint32_t request_id)
327{ 476{
328 int s; 477 int s;
329 struct addrinfo hints; 478 struct addrinfo hints;
330 struct addrinfo *result; 479 struct addrinfo *result;
331 struct addrinfo *pos; 480 struct addrinfo *pos;
332 struct GNUNET_MessageHeader *msg; 481 struct GNUNET_RESOLVER_ResponseMessage *msg;
333 struct GNUNET_MQ_Envelope *env; 482 struct GNUNET_MQ_Envelope *env;
334 483
335#ifdef WINDOWS 484#ifdef WINDOWS
@@ -340,10 +489,12 @@ getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq,
340 int ret2; 489 int ret2;
341 ret1 = getaddrinfo_resolve (mq, 490 ret1 = getaddrinfo_resolve (mq,
342 hostname, 491 hostname,
343 AF_INET); 492 AF_INET,
493 request_id);
344 ret2 = getaddrinfo_resolve (mq, 494 ret2 = getaddrinfo_resolve (mq,
345 hostname, 495 hostname,
346 AF_INET6); 496 AF_INET6,
497 request_id);
347 if ( (ret1 == GNUNET_OK) || 498 if ( (ret1 == GNUNET_OK) ||
348 (ret2 == GNUNET_OK) ) 499 (ret2 == GNUNET_OK) )
349 return GNUNET_OK; 500 return GNUNET_OK;
@@ -389,6 +540,7 @@ getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq,
389 env = GNUNET_MQ_msg_extra (msg, 540 env = GNUNET_MQ_msg_extra (msg,
390 sizeof (struct in_addr), 541 sizeof (struct in_addr),
391 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 542 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
543 msg->id = request_id;
392 GNUNET_memcpy (&msg[1], 544 GNUNET_memcpy (&msg[1],
393 &((struct sockaddr_in*) pos->ai_addr)->sin_addr, 545 &((struct sockaddr_in*) pos->ai_addr)->sin_addr,
394 sizeof (struct in_addr)); 546 sizeof (struct in_addr));
@@ -399,6 +551,7 @@ getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq,
399 env = GNUNET_MQ_msg_extra (msg, 551 env = GNUNET_MQ_msg_extra (msg,
400 sizeof (struct in6_addr), 552 sizeof (struct in6_addr),
401 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 553 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
554 msg->id = request_id;
402 GNUNET_memcpy (&msg[1], 555 GNUNET_memcpy (&msg[1],
403 &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr, 556 &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr,
404 sizeof (struct in6_addr)); 557 sizeof (struct in6_addr));
@@ -421,13 +574,14 @@ getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq,
421static int 574static int
422gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq, 575gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq,
423 const char *hostname, 576 const char *hostname,
424 int af) 577 int af,
578 uint32_t request_id)
425{ 579{
426 struct hostent *hp; 580 struct hostent *hp;
427 int ret1; 581 int ret1;
428 int ret2; 582 int ret2;
429 struct GNUNET_MQ_Envelope *env; 583 struct GNUNET_MQ_Envelope *env;
430 struct GNUNET_MessageHeader *msg; 584 struct GNUNET_RESOLVER_ResponseMessage *msg;
431 585
432#ifdef WINDOWS 586#ifdef WINDOWS
433 /* gethostbyname2() in plibc is a compat dummy that calls gethostbyname(). */ 587 /* gethostbyname2() in plibc is a compat dummy that calls gethostbyname(). */
@@ -438,10 +592,12 @@ gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq,
438 { 592 {
439 ret1 = gethostbyname2_resolve (mq, 593 ret1 = gethostbyname2_resolve (mq,
440 hostname, 594 hostname,
441 AF_INET); 595 AF_INET,
596 request_id);
442 ret2 = gethostbyname2_resolve (mq, 597 ret2 = gethostbyname2_resolve (mq,
443 hostname, 598 hostname,
444 AF_INET6); 599 AF_INET6,
600 request_id);
445 if ( (ret1 == GNUNET_OK) || 601 if ( (ret1 == GNUNET_OK) ||
446 (ret2 == GNUNET_OK) ) 602 (ret2 == GNUNET_OK) )
447 return GNUNET_OK; 603 return GNUNET_OK;
@@ -468,6 +624,7 @@ gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq,
468 env = GNUNET_MQ_msg_extra (msg, 624 env = GNUNET_MQ_msg_extra (msg,
469 hp->h_length, 625 hp->h_length,
470 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 626 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
627 msg->id = request_id;
471 GNUNET_memcpy (&msg[1], 628 GNUNET_memcpy (&msg[1],
472 hp->h_addr_list[0], 629 hp->h_addr_list[0],
473 hp->h_length); 630 hp->h_length);
@@ -479,6 +636,7 @@ gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq,
479 env = GNUNET_MQ_msg_extra (msg, 636 env = GNUNET_MQ_msg_extra (msg,
480 hp->h_length, 637 hp->h_length,
481 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 638 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
639 msg->id = request_id;
482 GNUNET_memcpy (&msg[1], 640 GNUNET_memcpy (&msg[1],
483 hp->h_addr_list[0], 641 hp->h_addr_list[0],
484 hp->h_length); 642 hp->h_length);
@@ -497,10 +655,11 @@ gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq,
497 655
498static int 656static int
499gethostbyname_resolve (struct GNUNET_MQ_Handle *mq, 657gethostbyname_resolve (struct GNUNET_MQ_Handle *mq,
500 const char *hostname) 658 const char *hostname,
659 uint32_t request_id)
501{ 660{
502 struct hostent *hp; 661 struct hostent *hp;
503 struct GNUNET_MessageHeader *msg; 662 struct GNUNET_RESOLVER_ResponseMessage *msg;
504 struct GNUNET_MQ_Envelope *env; 663 struct GNUNET_MQ_Envelope *env;
505 664
506 hp = GETHOSTBYNAME (hostname); 665 hp = GETHOSTBYNAME (hostname);
@@ -521,6 +680,7 @@ gethostbyname_resolve (struct GNUNET_MQ_Handle *mq,
521 env = GNUNET_MQ_msg_extra (msg, 680 env = GNUNET_MQ_msg_extra (msg,
522 hp->h_length, 681 hp->h_length,
523 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 682 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
683 msg->id = request_id;
524 GNUNET_memcpy (&msg[1], 684 GNUNET_memcpy (&msg[1],
525 hp->h_addr_list[0], 685 hp->h_addr_list[0],
526 hp->h_length); 686 hp->h_length);
@@ -541,34 +701,42 @@ gethostbyname_resolve (struct GNUNET_MQ_Handle *mq,
541static void 701static void
542get_ip_from_hostname (struct GNUNET_SERVICE_Client *client, 702get_ip_from_hostname (struct GNUNET_SERVICE_Client *client,
543 const char *hostname, 703 const char *hostname,
544 int af) 704 int af,
705 uint32_t request_id)
545{ 706{
546 int ret;
547 struct GNUNET_MQ_Handle *mq;
548 struct GNUNET_MQ_Envelope *env; 707 struct GNUNET_MQ_Envelope *env;
549 struct GNUNET_MessageHeader *msg; 708 struct GNUNET_RESOLVER_ResponseMessage *msg;
709 struct GNUNET_MQ_Handle *mq;
550 710
551 mq = GNUNET_SERVICE_client_get_mq (client); 711 mq = GNUNET_SERVICE_client_get_mq (client);
552 ret = GNUNET_NO; 712#if HAVE_GETADDRINFO_A
553#if HAVE_GETADDRINFO 713 getaddrinfo_a_resolve (mq,
554 if (ret == GNUNET_NO) 714 hostname,
555 ret = getaddrinfo_resolve (mq, 715 af,
556 hostname, 716 request_id);
557 af); 717 GNUNET_SERVICE_client_continue (client);
718 return;
719#elif HAVE_GETADDRINFO
720 getaddrinfo_resolve (mq,
721 hostname,
722 af,
723 request_id);
558#elif HAVE_GETHOSTBYNAME2 724#elif HAVE_GETHOSTBYNAME2
559 if (ret == GNUNET_NO) 725 gethostbyname2_resolve (mq,
560 ret = gethostbyname2_resolve (mq, 726 hostname,
561 hostname, 727 af,
562 af); 728 request_id);
563#elif HAVE_GETHOSTBYNAME 729#elif HAVE_GETHOSTBYNAME
564 if ( (ret == GNUNET_NO) && 730 if ( ( (af == AF_UNSPEC) ||
565 ( (af == AF_UNSPEC) ||
566 (af == PF_INET) ) ) 731 (af == PF_INET) ) )
567 gethostbyname_resolve (mq, 732 gethostbyname_resolve (mq,
568 hostname); 733 hostname,
734 request_id);
569#endif 735#endif
736 // send end message
570 env = GNUNET_MQ_msg (msg, 737 env = GNUNET_MQ_msg (msg,
571 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 738 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
739 msg->id = request_id;
572 GNUNET_MQ_notify_sent (env, 740 GNUNET_MQ_notify_sent (env,
573 &notify_service_client_done, 741 &notify_service_client_done,
574 client); 742 client);
@@ -647,21 +815,21 @@ handle_get (void *cls,
647 const void *ip; 815 const void *ip;
648 int direction; 816 int direction;
649 int af; 817 int af;
818 uint32_t id;
650 819
651 direction = ntohl (msg->direction); 820 direction = ntohl (msg->direction);
652 af = ntohl (msg->af); 821 af = ntohl (msg->af);
822 id = ntohl (msg->id);
653 if (GNUNET_NO == direction) 823 if (GNUNET_NO == direction)
654 { 824 {
655 /* IP from hostname */ 825 /* IP from hostname */
656 const char *hostname; 826 const char *hostname;
657 827
658 hostname = (const char *) &msg[1]; 828 hostname = (const char *) &msg[1];
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "Resolver asked to look up `%s'.\n",
661 hostname);
662 get_ip_from_hostname (client, 829 get_ip_from_hostname (client,
663 hostname, 830 hostname,
664 af); 831 af,
832 id);
665 return; 833 return;
666 } 834 }
667 ip = &msg[1]; 835 ip = &msg[1];
@@ -671,16 +839,18 @@ handle_get (void *cls,
671 char buf[INET6_ADDRSTRLEN]; 839 char buf[INET6_ADDRSTRLEN];
672 840
673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
674 "Resolver asked to look up IP address `%s'.\n", 842 "Resolver asked to look up IP address `%s (request ID %u)'.\n",
675 inet_ntop (af, 843 inet_ntop (af,
676 ip, 844 ip,
677 buf, 845 buf,
678 sizeof (buf))); 846 sizeof (buf)),
847 id);
679 } 848 }
680#endif 849#endif
681 get_ip_as_string (client, 850 get_ip_as_string (client,
682 af, 851 af,
683 ip); 852 ip,
853 id);
684} 854}
685 855
686 856
@@ -700,6 +870,19 @@ connect_cb (void *cls,
700 (void) cls; 870 (void) cls;
701 (void) mq; 871 (void) mq;
702 872
873#if HAVE_GETADDRINFO_A
874 resolve_result_pipe = GNUNET_DISK_pipe (GNUNET_NO,
875 GNUNET_NO,
876 GNUNET_NO,
877 GNUNET_NO);
878 GNUNET_assert (NULL != resolve_result_pipe);
879 resolve_result_pipe_task =
880 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
881 GNUNET_DISK_pipe_handle (resolve_result_pipe,
882 GNUNET_DISK_PIPE_END_READ),
883 &resolve_result_pipe_cb,
884 NULL);
885#endif
703 return c; 886 return c;
704} 887}
705 888
@@ -718,6 +901,18 @@ disconnect_cb (void *cls,
718{ 901{
719 (void) cls; 902 (void) cls;
720 903
904#if HAVE_GETADDRINFO_A
905 if (NULL != resolve_result_pipe_task)
906 {
907 GNUNET_SCHEDULER_cancel (resolve_result_pipe_task);
908 resolve_result_pipe_task = NULL;
909 }
910 if (NULL != resolve_result_pipe)
911 {
912 GNUNET_DISK_pipe_close (resolve_result_pipe);
913 resolve_result_pipe = NULL;
914 }
915#endif
721 GNUNET_assert (c == internal_cls); 916 GNUNET_assert (c == internal_cls);
722} 917}
723 918
diff --git a/src/util/resolver.h b/src/util/resolver.h
index 0b137f085..a0f105afa 100644
--- a/src/util/resolver.h
+++ b/src/util/resolver.h
@@ -56,10 +56,37 @@ struct GNUNET_RESOLVER_GetMessage
56 */ 56 */
57 int32_t af GNUNET_PACKED; 57 int32_t af GNUNET_PACKED;
58 58
59 /**
60 * identifies the request and is contained in the response message. The
61 * client has to match response to request by this identifier.
62 */
63 uint32_t id GNUNET_PACKED;
64
59 /* followed by 0-terminated string for A/AAAA-lookup or 65 /* followed by 0-terminated string for A/AAAA-lookup or
60 by 'struct in_addr' / 'struct in6_addr' for reverse lookup */ 66 by 'struct in_addr' / 'struct in6_addr' for reverse lookup */
61 67
62}; 68};
69
70
71struct GNUNET_RESOLVER_ResponseMessage
72{
73 /**
74 * Type: GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE
75 */
76 struct GNUNET_MessageHeader header;
77
78 /**
79 * identifies the request this message responds to. The client
80 * has to match response to request by this identifier.
81 */
82 uint32_t id GNUNET_PACKED;
83
84 /* followed by 0-terminated string for response to a reverse lookup
85 * or by 'struct in_addr' / 'struct in6_addr' for response to
86 * A/AAAA-lookup
87 */
88};
89
63GNUNET_NETWORK_STRUCT_END 90GNUNET_NETWORK_STRUCT_END
64 91
65#endif 92#endif
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c
index afebabf08..b94819f06 100644
--- a/src/util/resolver_api.c
+++ b/src/util/resolver_api.c
@@ -69,6 +69,11 @@ static struct GNUNET_RESOLVER_RequestHandle *req_head;
69static struct GNUNET_RESOLVER_RequestHandle *req_tail; 69static struct GNUNET_RESOLVER_RequestHandle *req_tail;
70 70
71/** 71/**
72 * ID of the last request we sent to the service
73 */
74static uint32_t last_request_id;
75
76/**
72 * How long should we wait to reconnect? 77 * How long should we wait to reconnect?
73 */ 78 */
74static struct GNUNET_TIME_Relative backoff; 79static struct GNUNET_TIME_Relative backoff;
@@ -137,6 +142,11 @@ struct GNUNET_RESOLVER_RequestHandle
137 int af; 142 int af;
138 143
139 /** 144 /**
145 * Identifies the request. The response will contain this id.
146 */
147 uint32_t id;
148
149 /**
140 * Has this request been transmitted to the service? 150 * Has this request been transmitted to the service?
141 * #GNUNET_YES if transmitted 151 * #GNUNET_YES if transmitted
142 * #GNUNET_YES if not transmitted 152 * #GNUNET_YES if not transmitted
@@ -435,11 +445,13 @@ process_requests ()
435 GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST); 445 GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
436 msg->direction = htonl (rh->direction); 446 msg->direction = htonl (rh->direction);
437 msg->af = htonl (rh->af); 447 msg->af = htonl (rh->af);
448 msg->id = htonl (rh->id);
438 GNUNET_memcpy (&msg[1], 449 GNUNET_memcpy (&msg[1],
439 &rh[1], 450 &rh[1],
440 rh->data_len); 451 rh->data_len);
441 LOG (GNUNET_ERROR_TYPE_DEBUG, 452 LOG (GNUNET_ERROR_TYPE_DEBUG,
442 "Transmitting DNS resolution request to DNS service\n"); 453 "Transmitting DNS resolution request (ID %u) to DNS service\n",
454 rh->id);
443 GNUNET_MQ_send (mq, 455 GNUNET_MQ_send (mq,
444 env); 456 env);
445 rh->was_transmitted = GNUNET_YES; 457 rh->was_transmitted = GNUNET_YES;
@@ -454,7 +466,7 @@ process_requests ()
454 */ 466 */
455static int 467static int
456check_response (void *cls, 468check_response (void *cls,
457 const struct GNUNET_MessageHeader *msg) 469 const struct GNUNET_RESOLVER_ResponseMessage *msg)
458{ 470{
459 (void) cls; 471 (void) cls;
460 (void) msg; 472 (void) msg;
@@ -474,11 +486,18 @@ check_response (void *cls,
474 */ 486 */
475static void 487static void
476handle_response (void *cls, 488handle_response (void *cls,
477 const struct GNUNET_MessageHeader *msg) 489 const struct GNUNET_RESOLVER_ResponseMessage *msg)
478{ 490{
479 struct GNUNET_RESOLVER_RequestHandle *rh = req_head; 491 struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
480 uint16_t size; 492 uint16_t size;
481 char *nret; 493 char *nret;
494 uint32_t request_id = msg->id;
495
496 for (; rh != NULL; rh = rh->next)
497 {
498 if (rh->id == request_id)
499 break;
500 }
482 501
483 (void) cls; 502 (void) cls;
484 if (NULL == rh) 503 if (NULL == rh)
@@ -490,8 +509,8 @@ handle_response (void *cls,
490 reconnect (); 509 reconnect ();
491 return; 510 return;
492 } 511 }
493 size = ntohs (msg->size); 512 size = ntohs (msg->header.size);
494 if (size == sizeof (struct GNUNET_MessageHeader)) 513 if (size == sizeof (struct GNUNET_RESOLVER_ResponseMessage))
495 { 514 {
496 LOG (GNUNET_ERROR_TYPE_DEBUG, 515 LOG (GNUNET_ERROR_TYPE_DEBUG,
497 "Received empty response from DNS service\n"); 516 "Received empty response from DNS service\n");
@@ -532,7 +551,7 @@ handle_response (void *cls,
532 const char *hostname; 551 const char *hostname;
533 552
534 hostname = (const char *) &msg[1]; 553 hostname = (const char *) &msg[1];
535 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0') 554 if (hostname[size - sizeof (struct GNUNET_RESOLVER_ResponseMessage) - 1] != '\0')
536 { 555 {
537 GNUNET_break (0); 556 GNUNET_break (0);
538 if (GNUNET_SYSERR != rh->was_transmitted) 557 if (GNUNET_SYSERR != rh->was_transmitted)
@@ -566,7 +585,7 @@ handle_response (void *cls,
566 size_t ip_len; 585 size_t ip_len;
567 586
568 ip = &msg[1]; 587 ip = &msg[1];
569 ip_len = size - sizeof (struct GNUNET_MessageHeader); 588 ip_len = size - sizeof (struct GNUNET_RESOLVER_ResponseMessage);
570 if (ip_len == sizeof (struct in_addr)) 589 if (ip_len == sizeof (struct in_addr))
571 { 590 {
572 memset (&v4, 0, sizeof (v4)); 591 memset (&v4, 0, sizeof (v4));
@@ -763,7 +782,7 @@ reconnect_task (void *cls)
763 struct GNUNET_MQ_MessageHandler handlers[] = { 782 struct GNUNET_MQ_MessageHandler handlers[] = {
764 GNUNET_MQ_hd_var_size (response, 783 GNUNET_MQ_hd_var_size (response,
765 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE, 784 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE,
766 struct GNUNET_MessageHeader, 785 struct GNUNET_RESOLVER_ResponseMessage,
767 NULL), 786 NULL),
768 GNUNET_MQ_handler_end () 787 GNUNET_MQ_handler_end ()
769 }; 788 };
@@ -926,6 +945,7 @@ GNUNET_RESOLVER_ip_get (const char *hostname,
926 hostname); 945 hostname);
927 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen); 946 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
928 rh->af = af; 947 rh->af = af;
948 rh->id = ++last_request_id;
929 rh->addr_callback = callback; 949 rh->addr_callback = callback;
930 rh->cls = callback_cls; 950 rh->cls = callback_cls;
931 GNUNET_memcpy (&rh[1], 951 GNUNET_memcpy (&rh[1],
@@ -1072,6 +1092,7 @@ GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
1072 rh->name_callback = callback; 1092 rh->name_callback = callback;
1073 rh->cls = cls; 1093 rh->cls = cls;
1074 rh->af = sa->sa_family; 1094 rh->af = sa->sa_family;
1095 rh->id = ++last_request_id;
1075 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); 1096 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1076 GNUNET_memcpy (&rh[1], 1097 GNUNET_memcpy (&rh[1],
1077 ip, 1098 ip,
diff --git a/src/util/test_resolver_api.c b/src/util/test_resolver_api.c
index c89fad865..5a8f95093 100644
--- a/src/util/test_resolver_api.c
+++ b/src/util/test_resolver_api.c
@@ -258,6 +258,8 @@ run (void *cls, char *const *args, const char *cfgfile,
258 /* Resolve the same using GNUNET */ 258 /* Resolve the same using GNUNET */
259 GNUNET_RESOLVER_ip_get (ROOTSERVER_NAME, AF_INET, timeout, 259 GNUNET_RESOLVER_ip_get (ROOTSERVER_NAME, AF_INET, timeout,
260 &check_rootserver_ip, cls); 260 &check_rootserver_ip, cls);
261 GNUNET_RESOLVER_ip_get (ROOTSERVER_NAME, AF_INET, timeout,
262 &check_rootserver_ip, cls);
261 263
262 /* 264 /*
263 * Success: forward lookups work as expected 265 * Success: forward lookups work as expected