diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-06-27 18:17:45 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-06-27 18:17:45 +0000 |
commit | 6da8cb2e81a46c5658711e70312d4523d33c0d1d (patch) | |
tree | 2f1927955aa56a2a137786bb5ea219de384a06e8 /src/util/resolver_api.c | |
parent | 13396b0fdbfa5b5fa35fd3cafebbb8cc3a1332b3 (diff) | |
download | gnunet-6da8cb2e81a46c5658711e70312d4523d33c0d1d.tar.gz gnunet-6da8cb2e81a46c5658711e70312d4523d33c0d1d.zip |
-convert resolver_api to MQ
Diffstat (limited to 'src/util/resolver_api.c')
-rw-r--r-- | src/util/resolver_api.c | 316 |
1 files changed, 165 insertions, 151 deletions
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c index 0488d6a3c..ba9a6cd71 100644 --- a/src/util/resolver_api.c +++ b/src/util/resolver_api.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2009-2015 GNUnet e.V. | 3 | Copyright (C) 2009-2016 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -58,7 +58,7 @@ static const struct GNUNET_CONFIGURATION_Handle *resolver_cfg; | |||
58 | * Our connection to the resolver service, created on-demand, but then | 58 | * Our connection to the resolver service, created on-demand, but then |
59 | * persists until error or shutdown. | 59 | * persists until error or shutdown. |
60 | */ | 60 | */ |
61 | static struct GNUNET_CLIENT_Connection *client; | 61 | static struct GNUNET_MQ_Handle *mq; |
62 | 62 | ||
63 | /** | 63 | /** |
64 | * Head of DLL of requests. | 64 | * Head of DLL of requests. |
@@ -252,12 +252,12 @@ GNUNET_RESOLVER_disconnect () | |||
252 | { | 252 | { |
253 | GNUNET_assert (NULL == req_head); | 253 | GNUNET_assert (NULL == req_head); |
254 | GNUNET_assert (NULL == req_tail); | 254 | GNUNET_assert (NULL == req_tail); |
255 | if (NULL != client) | 255 | if (NULL != mq) |
256 | { | 256 | { |
257 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 257 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
258 | "Disconnecting from DNS service\n"); | 258 | "Disconnecting from DNS service\n"); |
259 | GNUNET_CLIENT_disconnect (client); | 259 | GNUNET_MQ_destroy (mq); |
260 | client = NULL; | 260 | mq = NULL; |
261 | } | 261 | } |
262 | if (NULL != r_task) | 262 | if (NULL != r_task) |
263 | { | 263 | { |
@@ -282,7 +282,8 @@ GNUNET_RESOLVER_disconnect () | |||
282 | */ | 282 | */ |
283 | static char * | 283 | static char * |
284 | no_resolve (int af, | 284 | no_resolve (int af, |
285 | const void *ip, socklen_t ip_len) | 285 | const void *ip, |
286 | socklen_t ip_len) | ||
286 | { | 287 | { |
287 | char buf[INET6_ADDRSTRLEN]; | 288 | char buf[INET6_ADDRSTRLEN]; |
288 | 289 | ||
@@ -326,81 +327,110 @@ reconnect (void); | |||
326 | 327 | ||
327 | 328 | ||
328 | /** | 329 | /** |
329 | * Process pending requests to the resolver. | 330 | * Generic error handler, called with the appropriate error code and |
331 | * the same closure specified at the creation of the message queue. | ||
332 | * Not every message queue implementation supports an error handler. | ||
333 | * | ||
334 | * @param cls NULL | ||
335 | * @param error error code | ||
330 | */ | 336 | */ |
331 | static void | 337 | static void |
332 | process_requests (void); | 338 | mq_error_handler (void *cls, |
339 | enum GNUNET_MQ_Error error) | ||
340 | { | ||
341 | GNUNET_break (0); | ||
342 | GNUNET_MQ_destroy (mq); | ||
343 | mq = NULL; | ||
344 | reconnect (); | ||
345 | } | ||
333 | 346 | ||
334 | 347 | ||
335 | /** | 348 | /** |
336 | * Process response with a hostname for a DNS lookup. | 349 | * Task executed on system shutdown. |
337 | * | ||
338 | * @param cls our `struct GNUNET_RESOLVER_RequestHandle *` context | ||
339 | * @param msg message with the hostname, NULL on error | ||
340 | */ | 350 | */ |
341 | static void | 351 | static void |
342 | handle_response (void *cls, | 352 | shutdown_task (void *cls) |
343 | const struct GNUNET_MessageHeader *msg) | ||
344 | { | 353 | { |
345 | struct GNUNET_RESOLVER_RequestHandle *rh = cls; | 354 | s_task = NULL; |
346 | uint16_t size; | 355 | GNUNET_RESOLVER_disconnect (); |
347 | char *nret; | 356 | backoff = GNUNET_TIME_UNIT_MILLISECONDS; |
357 | } | ||
348 | 358 | ||
349 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
350 | "Receiving response from DNS service\n"); | ||
351 | if (NULL == msg) | ||
352 | { | ||
353 | char buf[INET6_ADDRSTRLEN]; | ||
354 | 359 | ||
355 | if (NULL != rh->name_callback) | 360 | /** |
356 | LOG (GNUNET_ERROR_TYPE_INFO, | 361 | * Process pending requests to the resolver. |
357 | _("Timeout trying to resolve IP address `%s'.\n"), | 362 | */ |
358 | inet_ntop (rh->af, | 363 | static void |
359 | (const void *) &rh[1], | 364 | process_requests () |
360 | buf, | 365 | { |
361 | sizeof(buf))); | 366 | struct GNUNET_RESOLVER_GetMessage *msg; |
362 | else | 367 | struct GNUNET_MQ_Envelope *env; |
363 | LOG (GNUNET_ERROR_TYPE_INFO, | 368 | struct GNUNET_RESOLVER_RequestHandle *rh = req_head; |
364 | _("Timeout trying to resolve hostname `%s'.\n"), | 369 | |
365 | (const char *) &rh[1]); | 370 | if (NULL == mq) |
366 | /* check if request was canceled */ | 371 | { |
367 | if (GNUNET_SYSERR != rh->was_transmitted) | ||
368 | { | ||
369 | if (NULL != rh->name_callback) | ||
370 | { | ||
371 | /* no reverse lookup was successful, return IP as string */ | ||
372 | if (GNUNET_NO == rh->received_response) | ||
373 | { | ||
374 | nret = no_resolve (rh->af, | ||
375 | &rh[1], | ||
376 | rh->data_len); | ||
377 | rh->name_callback (rh->cls, nret); | ||
378 | GNUNET_free (nret); | ||
379 | } | ||
380 | /* finally, make termination call */ | ||
381 | rh->name_callback (rh->cls, | ||
382 | NULL); | ||
383 | } | ||
384 | if (NULL != rh->addr_callback) | ||
385 | rh->addr_callback (rh->cls, | ||
386 | NULL, | ||
387 | 0); | ||
388 | } | ||
389 | rh->was_transmitted = GNUNET_NO; | ||
390 | GNUNET_RESOLVER_request_cancel (rh); | ||
391 | GNUNET_CLIENT_disconnect (client); | ||
392 | client = NULL; | ||
393 | reconnect (); | 372 | reconnect (); |
394 | return; | 373 | return; |
395 | } | 374 | } |
396 | if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type)) | 375 | if (NULL == rh) |
397 | { | 376 | { |
398 | GNUNET_break (0); | 377 | /* nothing to do, release socket really soon if there is nothing |
399 | GNUNET_CLIENT_disconnect (client); | 378 | * else happening... */ |
400 | client = NULL; | 379 | s_task = |
401 | reconnect (); | 380 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, |
381 | &shutdown_task, | ||
382 | NULL); | ||
402 | return; | 383 | return; |
403 | } | 384 | } |
385 | if (GNUNET_NO != rh->was_transmitted) | ||
386 | return; /* waiting for reply */ | ||
387 | env = GNUNET_MQ_msg_extra (msg, | ||
388 | rh->data_len, | ||
389 | GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST); | ||
390 | msg->direction = htonl (rh->direction); | ||
391 | msg->af = htonl (rh->af); | ||
392 | memcpy (&msg[1], | ||
393 | &rh[1], | ||
394 | rh->data_len); | ||
395 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
396 | "Transmitting DNS resolution request to DNS service\n"); | ||
397 | GNUNET_MQ_send (mq, | ||
398 | env); | ||
399 | rh->was_transmitted = GNUNET_YES; | ||
400 | } | ||
401 | |||
402 | |||
403 | /** | ||
404 | * Check validity of response with a hostname for a DNS lookup. | ||
405 | * | ||
406 | * @param cls NULL | ||
407 | * @param msg message with the hostname | ||
408 | */ | ||
409 | static int | ||
410 | check_response (void *cls, | ||
411 | const struct GNUNET_MessageHeader *msg) | ||
412 | { | ||
413 | /* implemented in #handle_response() for now */ | ||
414 | return GNUNET_OK; | ||
415 | } | ||
416 | |||
417 | |||
418 | /** | ||
419 | * Check validity of response with a hostname for a DNS lookup. | ||
420 | * NOTE: right now rather messy, might want to use different | ||
421 | * message types for different response formats in the future. | ||
422 | * | ||
423 | * @param cls NULL | ||
424 | * @param msg message with the response | ||
425 | */ | ||
426 | static void | ||
427 | handle_response (void *cls, | ||
428 | const struct GNUNET_MessageHeader *msg) | ||
429 | { | ||
430 | struct GNUNET_RESOLVER_RequestHandle *rh = req_head; | ||
431 | uint16_t size; | ||
432 | char *nret; | ||
433 | |||
404 | size = ntohs (msg->size); | 434 | size = ntohs (msg->size); |
405 | if (size == sizeof (struct GNUNET_MessageHeader)) | 435 | if (size == sizeof (struct GNUNET_MessageHeader)) |
406 | { | 436 | { |
@@ -449,8 +479,8 @@ handle_response (void *cls, | |||
449 | NULL); | 479 | NULL); |
450 | rh->was_transmitted = GNUNET_NO; | 480 | rh->was_transmitted = GNUNET_NO; |
451 | GNUNET_RESOLVER_request_cancel (rh); | 481 | GNUNET_RESOLVER_request_cancel (rh); |
452 | GNUNET_CLIENT_disconnect (client); | 482 | GNUNET_MQ_destroy (mq); |
453 | client = NULL; | 483 | mq = NULL; |
454 | reconnect (); | 484 | reconnect (); |
455 | return; | 485 | return; |
456 | } | 486 | } |
@@ -507,8 +537,8 @@ handle_response (void *cls, | |||
507 | 0); | 537 | 0); |
508 | rh->was_transmitted = GNUNET_NO; | 538 | rh->was_transmitted = GNUNET_NO; |
509 | GNUNET_RESOLVER_request_cancel (rh); | 539 | GNUNET_RESOLVER_request_cancel (rh); |
510 | GNUNET_CLIENT_disconnect (client); | 540 | GNUNET_MQ_destroy (mq); |
511 | client = NULL; | 541 | mq = NULL; |
512 | reconnect (); | 542 | reconnect (); |
513 | return; | 543 | return; |
514 | } | 544 | } |
@@ -519,10 +549,6 @@ handle_response (void *cls, | |||
519 | sa, | 549 | sa, |
520 | salen); | 550 | salen); |
521 | } | 551 | } |
522 | GNUNET_CLIENT_receive (client, | ||
523 | &handle_response, | ||
524 | rh, | ||
525 | GNUNET_TIME_absolute_get_remaining (rh->timeout)); | ||
526 | } | 552 | } |
527 | 553 | ||
528 | 554 | ||
@@ -652,75 +678,6 @@ loopback_resolution (void *cls) | |||
652 | 678 | ||
653 | 679 | ||
654 | /** | 680 | /** |
655 | * Task executed on system shutdown. | ||
656 | */ | ||
657 | static void | ||
658 | shutdown_task (void *cls) | ||
659 | { | ||
660 | s_task = NULL; | ||
661 | GNUNET_RESOLVER_disconnect (); | ||
662 | backoff = GNUNET_TIME_UNIT_MILLISECONDS; | ||
663 | } | ||
664 | |||
665 | |||
666 | /** | ||
667 | * Process pending requests to the resolver. | ||
668 | */ | ||
669 | static void | ||
670 | process_requests () | ||
671 | { | ||
672 | struct GNUNET_RESOLVER_GetMessage *msg; | ||
673 | char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; | ||
674 | struct GNUNET_RESOLVER_RequestHandle *rh; | ||
675 | |||
676 | if (NULL == client) | ||
677 | { | ||
678 | reconnect (); | ||
679 | return; | ||
680 | } | ||
681 | rh = req_head; | ||
682 | if (NULL == rh) | ||
683 | { | ||
684 | /* nothing to do, release socket really soon if there is nothing | ||
685 | * else happening... */ | ||
686 | s_task = | ||
687 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
688 | &shutdown_task, | ||
689 | NULL); | ||
690 | return; | ||
691 | } | ||
692 | if (GNUNET_NO != rh->was_transmitted) | ||
693 | return; /* waiting for reply */ | ||
694 | msg = (struct GNUNET_RESOLVER_GetMessage *) buf; | ||
695 | msg->header.size = | ||
696 | htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len); | ||
697 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST); | ||
698 | msg->direction = htonl (rh->direction); | ||
699 | msg->af = htonl (rh->af); | ||
700 | memcpy (&msg[1], | ||
701 | &rh[1], | ||
702 | rh->data_len); | ||
703 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
704 | "Transmitting DNS resolution request to DNS service\n"); | ||
705 | if (GNUNET_OK != | ||
706 | GNUNET_CLIENT_transmit_and_get_response (client, | ||
707 | &msg->header, | ||
708 | GNUNET_TIME_absolute_get_remaining (rh->timeout), | ||
709 | GNUNET_YES, | ||
710 | &handle_response, | ||
711 | rh)) | ||
712 | { | ||
713 | GNUNET_CLIENT_disconnect (client); | ||
714 | client = NULL; | ||
715 | GNUNET_break (0); | ||
716 | reconnect (); | ||
717 | return; | ||
718 | } | ||
719 | rh->was_transmitted = GNUNET_YES; | ||
720 | } | ||
721 | |||
722 | |||
723 | /** | ||
724 | * Now try to reconnect to the resolver service. | 681 | * Now try to reconnect to the resolver service. |
725 | * | 682 | * |
726 | * @param cls NULL | 683 | * @param cls NULL |
@@ -728,14 +685,25 @@ process_requests () | |||
728 | static void | 685 | static void |
729 | reconnect_task (void *cls) | 686 | reconnect_task (void *cls) |
730 | { | 687 | { |
688 | GNUNET_MQ_hd_var_size (response, | ||
689 | GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE, | ||
690 | struct GNUNET_MessageHeader); | ||
691 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
692 | make_response_handler (NULL), | ||
693 | GNUNET_MQ_handler_end () | ||
694 | }; | ||
695 | |||
731 | r_task = NULL; | 696 | r_task = NULL; |
732 | if (NULL == req_head) | 697 | if (NULL == req_head) |
733 | return; /* no work pending */ | 698 | return; /* no work pending */ |
734 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 699 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
735 | "Trying to connect to DNS service\n"); | 700 | "Trying to connect to DNS service\n"); |
736 | client = GNUNET_CLIENT_connect ("resolver", | 701 | mq = GNUNET_CLIENT_connecT (resolver_cfg, |
737 | resolver_cfg); | 702 | "resolver", |
738 | if (NULL == client) | 703 | handlers, |
704 | &mq_error_handler, | ||
705 | NULL); | ||
706 | if (NULL == mq) | ||
739 | { | 707 | { |
740 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 708 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
741 | "Failed to connect, will try again later\n"); | 709 | "Failed to connect, will try again later\n"); |
@@ -756,7 +724,7 @@ reconnect () | |||
756 | 724 | ||
757 | if (NULL != r_task) | 725 | if (NULL != r_task) |
758 | return; | 726 | return; |
759 | GNUNET_assert (NULL == client); | 727 | GNUNET_assert (NULL == mq); |
760 | if (NULL != (rh = req_head)) | 728 | if (NULL != (rh = req_head)) |
761 | { | 729 | { |
762 | switch (rh->was_transmitted) | 730 | switch (rh->was_transmitted) |
@@ -803,10 +771,45 @@ handle_lookup_timeout (void *cls) | |||
803 | struct GNUNET_RESOLVER_RequestHandle *rh = cls; | 771 | struct GNUNET_RESOLVER_RequestHandle *rh = cls; |
804 | 772 | ||
805 | rh->task = NULL; | 773 | rh->task = NULL; |
806 | rh->addr_callback (rh->cls, | 774 | if (GNUNET_NO == rh->direction) |
807 | NULL, | 775 | { |
808 | 0); | 776 | LOG (GNUNET_ERROR_TYPE_INFO, |
777 | _("Timeout trying to resolve hostname `%s'.\n"), | ||
778 | (const char *) &rh[1]); | ||
779 | if (NULL != rh->addr_callback) | ||
780 | rh->addr_callback (rh->cls, | ||
781 | NULL, | ||
782 | 0); | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | char buf[INET6_ADDRSTRLEN]; | ||
787 | |||
788 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
789 | _("Timeout trying to resolve IP address `%s'.\n"), | ||
790 | inet_ntop (rh->af, | ||
791 | (const void *) &rh[1], | ||
792 | buf, | ||
793 | sizeof(buf))); | ||
794 | if (GNUNET_NO == rh->received_response) | ||
795 | { | ||
796 | char *nret; | ||
797 | |||
798 | nret = no_resolve (rh->af, | ||
799 | &rh[1], | ||
800 | rh->data_len); | ||
801 | if (NULL != rh->name_callback) | ||
802 | rh->name_callback (rh->cls, nret); | ||
803 | GNUNET_free (nret); | ||
804 | } | ||
805 | /* finally, make termination call */ | ||
806 | if (NULL != rh->name_callback) | ||
807 | rh->name_callback (rh->cls, | ||
808 | NULL); | ||
809 | } | ||
810 | rh->was_transmitted = GNUNET_NO; | ||
809 | GNUNET_RESOLVER_request_cancel (rh); | 811 | GNUNET_RESOLVER_request_cancel (rh); |
812 | process_requests (); | ||
810 | } | 813 | } |
811 | 814 | ||
812 | 815 | ||
@@ -916,6 +919,11 @@ numeric_reverse (void *cls) | |||
916 | } | 919 | } |
917 | rh->name_callback (rh->cls, | 920 | rh->name_callback (rh->cls, |
918 | NULL); | 921 | NULL); |
922 | if (NULL != rh->task) | ||
923 | { | ||
924 | GNUNET_SCHEDULER_cancel (rh->task); | ||
925 | rh->task = NULL; | ||
926 | } | ||
919 | GNUNET_free (rh); | 927 | GNUNET_free (rh); |
920 | } | 928 | } |
921 | 929 | ||
@@ -972,15 +980,21 @@ GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, | |||
972 | rh->cls = cls; | 980 | rh->cls = cls; |
973 | rh->af = sa->sa_family; | 981 | rh->af = sa->sa_family; |
974 | rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 982 | rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
975 | memcpy (&rh[1], ip, ip_len); | 983 | memcpy (&rh[1], |
984 | ip, | ||
985 | ip_len); | ||
976 | rh->data_len = ip_len; | 986 | rh->data_len = ip_len; |
977 | rh->direction = GNUNET_YES; | 987 | rh->direction = GNUNET_YES; |
978 | rh->received_response = GNUNET_NO; | 988 | rh->received_response = GNUNET_NO; |
979 | if (GNUNET_NO == do_resolve) | 989 | if (GNUNET_NO == do_resolve) |
980 | { | 990 | { |
981 | rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh); | 991 | rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, |
992 | rh); | ||
982 | return rh; | 993 | return rh; |
983 | } | 994 | } |
995 | rh->task = GNUNET_SCHEDULER_add_delayed (timeout, | ||
996 | &handle_lookup_timeout, | ||
997 | rh); | ||
984 | GNUNET_CONTAINER_DLL_insert_tail (req_head, | 998 | GNUNET_CONTAINER_DLL_insert_tail (req_head, |
985 | req_tail, | 999 | req_tail, |
986 | rh); | 1000 | rh); |