aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-06-16 10:09:47 +0000
committerChristian Grothoff <christian@grothoff.org>2011-06-16 10:09:47 +0000
commit007b8443b0cb0d67bf8b176a1a175ad4bc37f1f3 (patch)
treeb42d56110ae349eb2977673690c072dcf75b32a4 /src/util
parent94c41ff98d293d8c041c4bbbe8d19dbf8ccd6f3f (diff)
downloadgnunet-007b8443b0cb0d67bf8b176a1a175ad4bc37f1f3.tar.gz
gnunet-007b8443b0cb0d67bf8b176a1a175ad4bc37f1f3.zip
resolver API change
Diffstat (limited to 'src/util')
-rw-r--r--src/util/client.c6
-rw-r--r--src/util/connection.c3
-rw-r--r--src/util/gnunet-resolver.c3
-rw-r--r--src/util/program.c5
-rw-r--r--src/util/resolver_api.c630
5 files changed, 416 insertions, 231 deletions
diff --git a/src/util/client.c b/src/util/client.c
index 9458cc94b..7461a0fe2 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -151,9 +151,8 @@ struct GNUNET_CLIENT_Connection
151 151
152 /** 152 /**
153 * Our configuration. 153 * Our configuration.
154 * FIXME: why do we DUP the configuration? Avoid this!
155 */ 154 */
156 struct GNUNET_CONFIGURATION_Handle *cfg; 155 const struct GNUNET_CONFIGURATION_Handle *cfg;
157 156
158 /** 157 /**
159 * Name of the service we interact with. 158 * Name of the service we interact with.
@@ -377,7 +376,7 @@ GNUNET_CLIENT_connect (const char *service_name,
377 ret->attempts = 1; 376 ret->attempts = 1;
378 ret->sock = sock; 377 ret->sock = sock;
379 ret->service_name = GNUNET_strdup (service_name); 378 ret->service_name = GNUNET_strdup (service_name);
380 ret->cfg = GNUNET_CONFIGURATION_dup (cfg); 379 ret->cfg = cfg;
381 ret->back_off = GNUNET_TIME_UNIT_MILLISECONDS; 380 ret->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
382 return ret; 381 return ret;
383} 382}
@@ -447,7 +446,6 @@ GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *sock,
447 } 446 }
448 GNUNET_array_grow (sock->received_buf, sock->received_size, 0); 447 GNUNET_array_grow (sock->received_buf, sock->received_size, 0);
449 GNUNET_free (sock->service_name); 448 GNUNET_free (sock->service_name);
450 GNUNET_CONFIGURATION_destroy (sock->cfg);
451 GNUNET_free (sock); 449 GNUNET_free (sock);
452} 450}
453 451
diff --git a/src/util/connection.c b/src/util/connection.c
index dae049eeb..b28c7c3e6 100644
--- a/src/util/connection.c
+++ b/src/util/connection.c
@@ -901,8 +901,7 @@ GNUNET_CONNECTION_create_from_connect (const struct
901 ret->write_buffer = GNUNET_malloc(ret->write_buffer_size); 901 ret->write_buffer = GNUNET_malloc(ret->write_buffer_size);
902 ret->port = port; 902 ret->port = port;
903 ret->hostname = GNUNET_strdup (hostname); 903 ret->hostname = GNUNET_strdup (hostname);
904 ret->dns_active = GNUNET_RESOLVER_ip_get (cfg, 904 ret->dns_active = GNUNET_RESOLVER_ip_get (ret->hostname,
905 ret->hostname,
906 AF_UNSPEC, 905 AF_UNSPEC,
907 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT, 906 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
908 &try_connect_using_address, ret); 907 &try_connect_using_address, ret);
diff --git a/src/util/gnunet-resolver.c b/src/util/gnunet-resolver.c
index 18ce232f2..85aedcacf 100644
--- a/src/util/gnunet-resolver.c
+++ b/src/util/gnunet-resolver.c
@@ -61,8 +61,7 @@ run (void *cls,
61{ 61{
62 if (args[0] == NULL) 62 if (args[0] == NULL)
63 return; 63 return;
64 GNUNET_RESOLVER_ip_get (cfg, 64 GNUNET_RESOLVER_ip_get (args[0],
65 args[0],
66 AF_UNSPEC, 65 AF_UNSPEC,
67 GET_TIMEOUT, 66 GET_TIMEOUT,
68 &printer, 67 &printer,
diff --git a/src/util/program.c b/src/util/program.c
index 6f8467837..8fd77637f 100644
--- a/src/util/program.c
+++ b/src/util/program.c
@@ -32,6 +32,7 @@
32#include "gnunet_getopt_lib.h" 32#include "gnunet_getopt_lib.h"
33#include "gnunet_os_lib.h" 33#include "gnunet_os_lib.h"
34#include "gnunet_program_lib.h" 34#include "gnunet_program_lib.h"
35#include "gnunet_resolver_service.h"
35#include "gnunet_scheduler_lib.h" 36#include "gnunet_scheduler_lib.h"
36#include <gcrypt.h> 37#include <gcrypt.h>
37 38
@@ -77,6 +78,7 @@ program_main (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
77{ 78{
78 struct CommandContext *cc = cls; 79 struct CommandContext *cc = cls;
79 80
81 GNUNET_RESOLVER_connect (cc->cfg);
80 cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg); 82 cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg);
81} 83}
82 84
@@ -212,7 +214,6 @@ GNUNET_PROGRAM_run (int argc,
212 loglev, 214 loglev,
213 logfile)) || 215 logfile)) ||
214 (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cc.cfgfile)))) 216 (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cc.cfgfile))))
215
216 { 217 {
217 GNUNET_CONFIGURATION_destroy (cfg); 218 GNUNET_CONFIGURATION_destroy (cfg);
218 GNUNET_free_non_null (cc.cfgfile); 219 GNUNET_free_non_null (cc.cfgfile);
@@ -221,7 +222,7 @@ GNUNET_PROGRAM_run (int argc,
221 return GNUNET_SYSERR; 222 return GNUNET_SYSERR;
222 } 223 }
223 GNUNET_free (allopts); 224 GNUNET_free (allopts);
224 225
225 /* run */ 226 /* run */
226 cc.args = &argv[ret]; 227 cc.args = &argv[ret];
227 GNUNET_SCHEDULER_run (&program_main, &cc); 228 GNUNET_SCHEDULER_run (&program_main, &cc);
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c
index 7daaaf1cc..5c0973f86 100644
--- a/src/util/resolver_api.c
+++ b/src/util/resolver_api.c
@@ -27,6 +27,7 @@
27#include "gnunet_getopt_lib.h" 27#include "gnunet_getopt_lib.h"
28#include "gnunet_os_lib.h" 28#include "gnunet_os_lib.h"
29#include "gnunet_client_lib.h" 29#include "gnunet_client_lib.h"
30#include "gnunet_container_lib.h"
30#include "gnunet_protocols.h" 31#include "gnunet_protocols.h"
31#include "gnunet_resolver_service.h" 32#include "gnunet_resolver_service.h"
32#include "gnunet_server_lib.h" 33#include "gnunet_server_lib.h"
@@ -50,6 +51,44 @@ static const char *loopback[] = {
50 51
51 52
52/** 53/**
54 * Configuration.
55 */
56static const struct GNUNET_CONFIGURATION_Handle *cfg;
57
58/**
59 * Our connection to the resolver service, created on-demand, but then
60 * persists until error or shutdown.
61 */
62static struct GNUNET_CLIENT_Connection *client;
63
64/**
65 * Head of DLL of requests.
66 */
67static struct GNUNET_RESOLVER_RequestHandle *req_head;
68
69/**
70 * Tail of DLL of requests.
71 */
72static struct GNUNET_RESOLVER_RequestHandle *req_tail;
73
74/**
75 * How long should we wait to reconnect?
76 */
77static struct GNUNET_TIME_Relative backoff;
78
79/**
80 * Task for reconnecting.
81 */
82static GNUNET_SCHEDULER_TaskIdentifier r_task;
83
84/**
85 * Task ID of shutdown task; only present while we have a
86 * connection to the resolver service.
87 */
88static GNUNET_SCHEDULER_TaskIdentifier s_task;
89
90
91/**
53 * Handle to a request given to the resolver. Can be used to cancel 92 * Handle to a request given to the resolver. Can be used to cancel
54 * the request prior to the timeout or successful execution. Also 93 * the request prior to the timeout or successful execution. Also
55 * used to track our internal state for the request. 94 * used to track our internal state for the request.
@@ -58,6 +97,16 @@ struct GNUNET_RESOLVER_RequestHandle
58{ 97{
59 98
60 /** 99 /**
100 * Next entry in DLL of requests.
101 */
102 struct GNUNET_RESOLVER_RequestHandle *next;
103
104 /**
105 * Previous entry in DLL of requests.
106 */
107 struct GNUNET_RESOLVER_RequestHandle *prev;
108
109 /**
61 * Callback if this is an name resolution request, 110 * Callback if this is an name resolution request,
62 * otherwise NULL. 111 * otherwise NULL.
63 */ 112 */
@@ -75,16 +124,6 @@ struct GNUNET_RESOLVER_RequestHandle
75 void *cls; 124 void *cls;
76 125
77 /** 126 /**
78 * Our connection to the resolver service.
79 */
80 struct GNUNET_CLIENT_Connection *client;
81
82 /**
83 * Name of the host that we are resolving.
84 */
85 const char *hostname;
86
87 /**
88 * When should this request time out? 127 * When should this request time out?
89 */ 128 */
90 struct GNUNET_TIME_Absolute timeout; 129 struct GNUNET_TIME_Absolute timeout;
@@ -100,10 +139,24 @@ struct GNUNET_RESOLVER_RequestHandle
100 int domain; 139 int domain;
101 140
102 /** 141 /**
103 * Length of the "struct sockaddr" that follows this 142 * Has this request been transmitted to the service?
104 * struct (only for reverse lookup).
105 */ 143 */
106 socklen_t salen; 144 int was_transmitted;
145
146 /**
147 * Did we add this request to the queue?
148 */
149 int was_queued;
150
151 /**
152 * Desired direction (IP to name or name to IP)
153 */
154 int direction;
155
156 /**
157 * Length of the data that follows this struct.
158 */
159 size_t data_len;
107}; 160};
108 161
109 162
@@ -164,6 +217,45 @@ check_config (const struct GNUNET_CONFIGURATION_Handle *cfg)
164 217
165 218
166/** 219/**
220 * Create the connection to the resolver service.
221 *
222 * @param c configuration to use
223 */
224void
225GNUNET_RESOLVER_connect (const struct GNUNET_CONFIGURATION_Handle *c)
226{
227 check_config (c);
228 cfg = c;
229}
230
231
232/**
233 * Destroy the connection to the resolver service.
234 */
235void
236GNUNET_RESOLVER_disconnect ()
237{
238 GNUNET_assert (NULL == req_head);
239 GNUNET_assert (NULL == req_tail);
240 if (NULL != client)
241 {
242 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
243 client = NULL;
244 }
245 if (r_task != GNUNET_SCHEDULER_NO_TASK)
246 {
247 GNUNET_SCHEDULER_cancel (r_task);
248 r_task = GNUNET_SCHEDULER_NO_TASK;
249 }
250 if (s_task != GNUNET_SCHEDULER_NO_TASK)
251 {
252 GNUNET_SCHEDULER_cancel (s_task);
253 s_task = GNUNET_SCHEDULER_NO_TASK;
254 }
255}
256
257
258/**
167 * Convert IP address to string without DNS resolution. 259 * Convert IP address to string without DNS resolution.
168 * 260 *
169 * @param sa the address 261 * @param sa the address
@@ -216,76 +308,146 @@ no_resolve (const struct sockaddr *sa, socklen_t salen)
216 308
217 309
218/** 310/**
219 * Process the reply from the resolver (which is presumably 311 * Adjust exponential back-off and reconnect to the service.
220 * the numeric IP address for a name resolution request). 312 */
313static void
314reconnect ();
315
316
317/**
318 * Process pending requests to the resolver.
221 * 319 *
222 * @param cls the "GNUNET_RESOLVER_RequestHandle" for which this is a reply 320 * @param h handle to the resolver
223 * @param msg reply from the resolver or NULL on error 321 */
322static void
323process_requests ();
324
325
326/**
327 * Process response with a hostname for a DNS lookup.
328 *
329 * @param cls our "struct GNUNET_RESOLVER_RequestHandle" context
330 * @param msg message with the hostname, NULL on error
224 */ 331 */
225static void 332static void
226handle_address_response (void *cls, const struct GNUNET_MessageHeader *msg) 333handle_response (void *cls,
334 const struct GNUNET_MessageHeader *msg)
227{ 335{
228 struct GNUNET_RESOLVER_RequestHandle *rh = cls; 336 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
229 uint16_t size; 337 uint16_t size;
338 const char *hostname;
230 const struct sockaddr *sa; 339 const struct sockaddr *sa;
231 socklen_t salen; 340 socklen_t salen;
232 341
233 if (msg == NULL) 342 if (msg == NULL)
234 { 343 {
235 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 344 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
236 _("Timeout trying to resolve hostname `%s'.\n"), 345 _("Timeout trying to resolve IP address `%s'.\n"),
237 rh->hostname); 346 GNUNET_a2s ((const void*) &rh[1], rh->data_len));
238 rh->addr_callback (rh->cls, NULL, 0); 347 if (rh->was_transmitted != GNUNET_SYSERR)
239 GNUNET_CLIENT_disconnect (rh->client, GNUNET_NO); 348 {
349 if (NULL != rh->name_callback)
350 rh->name_callback (rh->cls, NULL);
351 if (NULL != rh->addr_callback)
352 rh->addr_callback (rh->cls, NULL, 0);
353 }
354 GNUNET_CONTAINER_DLL_remove (req_head,
355 req_tail,
356 rh);
240 GNUNET_free (rh); 357 GNUNET_free (rh);
358 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
359 client = NULL;
360 reconnect ();
241 return; 361 return;
242 } 362 }
243 if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type)) 363 if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type))
244 { 364 {
245 GNUNET_break (0); 365 GNUNET_break (0);
246 rh->addr_callback (rh->cls, NULL, 0); 366 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
247 GNUNET_CLIENT_disconnect (rh->client, GNUNET_NO); 367 client = NULL;
248 GNUNET_free (rh); 368 reconnect ();
249 return; 369 return;
250 } 370 }
251
252 size = ntohs (msg->size); 371 size = ntohs (msg->size);
253 if (size == sizeof (struct GNUNET_MessageHeader)) 372 if (size == sizeof (struct GNUNET_MessageHeader))
254 { 373 {
255#if DEBUG_RESOLVER 374 if (rh->was_transmitted != GNUNET_SYSERR)
256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 375 {
257 _("Received end message resolving hostname `%s'.\n"), 376 if (NULL != rh->name_callback)
258 rh->hostname); 377 rh->name_callback (rh->cls, NULL);
259#endif 378 if (NULL != rh->addr_callback)
260 rh->addr_callback (rh->cls, NULL, 0); 379 rh->addr_callback (rh->cls, NULL, 0);
261 GNUNET_CLIENT_disconnect (rh->client, GNUNET_NO); 380 }
381 GNUNET_CONTAINER_DLL_remove (req_head,
382 req_tail,
383 rh);
262 GNUNET_free (rh); 384 GNUNET_free (rh);
385 process_requests ();
263 return; 386 return;
264 } 387 }
265 sa = (const struct sockaddr *) &msg[1]; 388 if (NULL != rh->name_callback)
266 salen = size - sizeof (struct GNUNET_MessageHeader);
267 if (salen < sizeof (struct sockaddr))
268 { 389 {
269 GNUNET_break (0); 390 hostname = (const char *) &msg[1];
270 rh->addr_callback (rh->cls, NULL, 0); 391 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
271 GNUNET_CLIENT_disconnect (rh->client, GNUNET_NO); 392 {
272 GNUNET_free (rh); 393 GNUNET_break (0);
273 return; 394 if (rh->was_transmitted != GNUNET_SYSERR)
395 rh->name_callback (rh->cls, NULL);
396 GNUNET_CONTAINER_DLL_remove (req_head,
397 req_tail,
398 rh);
399 GNUNET_free (rh);
400 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
401 client = NULL;
402 reconnect ();
403 return;
404 }
405#if DEBUG_RESOLVER
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
407 _("Resolver returns `%s' for IP `%s'.\n"),
408 hostname,
409 GNUNET_a2s ((const void*) &rh[1], rh->data_len));
410#endif
411 if (rh->was_transmitted != GNUNET_SYSERR)
412 rh->name_callback (rh->cls, hostname);
413 GNUNET_CLIENT_receive (client,
414 &handle_response,
415 rh,
416 GNUNET_TIME_absolute_get_remaining (rh->timeout));
274 } 417 }
418 if (NULL != rh->addr_callback)
419 {
420 sa = (const struct sockaddr *) &msg[1];
421 salen = size - sizeof (struct GNUNET_MessageHeader);
422 if (salen < sizeof (struct sockaddr))
423 {
424 GNUNET_break (0);
425 if (rh->was_transmitted != GNUNET_SYSERR)
426 rh->addr_callback (rh->cls, NULL, 0);
427 GNUNET_CONTAINER_DLL_remove (req_head,
428 req_tail,
429 rh);
430 GNUNET_free (rh);
431 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
432 client = NULL;
433 reconnect ();
434 return;
435 }
275#if DEBUG_RESOLVER 436#if DEBUG_RESOLVER
276 { 437 {
277 char *ips = no_resolve (sa, salen); 438 char *ips = no_resolve (sa, salen);
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
279 "Resolver returns `%s' for `%s'.\n", ips, 440 "Resolver returns `%s' for `%s'.\n", ips,
280 rh->hostname); 441 rh->hostname);
281 GNUNET_free (ips); 442 GNUNET_free (ips);
282 } 443 }
283#endif 444#endif
284 rh->addr_callback (rh->cls, sa, salen); 445 rh->addr_callback (rh->cls, sa, salen);
285 GNUNET_CLIENT_receive (rh->client, 446 GNUNET_CLIENT_receive (client,
286 &handle_address_response, 447 &handle_response,
287 rh, 448 rh,
288 GNUNET_TIME_absolute_get_remaining (rh->timeout)); 449 GNUNET_TIME_absolute_get_remaining (rh->timeout));
450 }
289} 451}
290 452
291 453
@@ -303,6 +465,7 @@ numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
303 struct GNUNET_RESOLVER_RequestHandle *rh = cls; 465 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
304 struct sockaddr_in v4; 466 struct sockaddr_in v4;
305 struct sockaddr_in6 v6; 467 struct sockaddr_in6 v6;
468 const char *hostname;
306 469
307 memset (&v4, 0, sizeof (v4)); 470 memset (&v4, 0, sizeof (v4));
308 v4.sin_family = AF_INET; 471 v4.sin_family = AF_INET;
@@ -314,13 +477,13 @@ numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
314#if HAVE_SOCKADDR_IN_SIN_LEN 477#if HAVE_SOCKADDR_IN_SIN_LEN
315 v6.sin6_len = sizeof (v6); 478 v6.sin6_len = sizeof (v6);
316#endif 479#endif
317 480 hostname = (const char*) &rh[1];
318 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET)) && 481 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET)) &&
319 (1 == inet_pton (AF_INET, rh->hostname, &v4.sin_addr))) 482 (1 == inet_pton (AF_INET, hostname, &v4.sin_addr)))
320 { 483 {
321 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); 484 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
322 if ((rh->domain == AF_UNSPEC) && 485 if ((rh->domain == AF_UNSPEC) &&
323 (1 == inet_pton (AF_INET6, rh->hostname, &v6.sin6_addr))) 486 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
324 { 487 {
325 /* this can happen on some systems IF "hostname" is "localhost" */ 488 /* this can happen on some systems IF "hostname" is "localhost" */
326 rh->addr_callback (rh->cls, 489 rh->addr_callback (rh->cls,
@@ -331,7 +494,7 @@ numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
331 return; 494 return;
332 } 495 }
333 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET6)) && 496 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET6)) &&
334 (1 == inet_pton (AF_INET6, rh->hostname, &v6.sin6_addr))) 497 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
335 { 498 {
336 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); 499 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
337 rh->addr_callback (rh->cls, NULL, 0); 500 rh->addr_callback (rh->cls, NULL, 0);
@@ -344,7 +507,6 @@ numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
344} 507}
345 508
346 509
347
348/** 510/**
349 * We've been asked to lookup the address for a hostname and were 511 * We've been asked to lookup the address for a hostname and were
350 * given a variant of "loopback". Perform the callbacks for the 512 * given a variant of "loopback". Perform the callbacks for the
@@ -394,9 +556,138 @@ loopback_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
394 556
395 557
396/** 558/**
559 * Task executed on system shutdown.
560 */
561static void
562shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
563{
564 s_task = GNUNET_SCHEDULER_NO_TASK;
565 GNUNET_RESOLVER_disconnect ();
566}
567
568
569/**
570 * Process pending requests to the resolver.
571 *
572 * @param h handle to the resolver
573 */
574static void
575process_requests ()
576{
577 struct GNUNET_RESOLVER_GetMessage *msg;
578 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
579 struct GNUNET_RESOLVER_RequestHandle *rh;
580
581 if (NULL == client)
582 {
583 reconnect ();
584 return;
585 }
586 rh = req_head;
587 if (NULL == rh)
588 {
589 /* nothing to do, release socket really soon if there is nothing
590 else happening... */
591 s_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
592 &shutdown_task, NULL);
593 return;
594 }
595 if (GNUNET_YES == rh->was_transmitted)
596 return; /* waiting for reply */
597 msg = (struct GNUNET_RESOLVER_GetMessage *) buf;
598 msg->header.size =
599 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len);
600 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
601 msg->direction = htonl (rh->direction);
602 msg->domain = htonl (rh->domain);
603 memcpy (&msg[1], &rh[1], rh->data_len);
604
605 if (GNUNET_OK !=
606 GNUNET_CLIENT_transmit_and_get_response (client,
607 &msg->header,
608 GNUNET_TIME_absolute_get_remaining (rh->timeout),
609 GNUNET_YES,
610 &handle_response, rh))
611 {
612 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
613 client = NULL;
614 reconnect ();
615 return;
616 }
617 rh->was_transmitted = GNUNET_YES;
618}
619
620
621/**
622 * Now try to reconnect to the resolver service.
623 *
624 * @param cls NULL
625 * @param tc scheduler context
626 */
627static void
628reconnect_task (void *cls,
629 const struct GNUNET_SCHEDULER_TaskContext *tc)
630{
631 r_task = GNUNET_SCHEDULER_NO_TASK;
632 if (NULL == req_head)
633 return; /* no work pending */
634 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
635 return;
636 client = GNUNET_CLIENT_connect ("resolver", cfg);
637 if (NULL == client)
638 {
639 reconnect ();
640 return;
641 }
642 process_requests ();
643}
644
645
646/**
647 * Adjust exponential back-off and reconnect to the service.
648 */
649static void
650reconnect ()
651{
652 struct GNUNET_RESOLVER_RequestHandle *rh;
653
654 if (GNUNET_SCHEDULER_NO_TASK != r_task)
655 return;
656 GNUNET_assert (NULL == client);
657 if (NULL != (rh = req_head))
658 {
659 switch (rh->was_transmitted)
660 {
661 case GNUNET_NO:
662 /* nothing more to do */
663 break;
664 case GNUNET_YES:
665 /* disconnected, transmit again! */
666 rh->was_transmitted = GNUNET_NO;
667 break;
668 case GNUNET_SYSERR:
669 /* request was cancelled, remove entirely */
670 GNUNET_CONTAINER_DLL_remove (req_head,
671 req_tail,
672 rh);
673 GNUNET_free (rh);
674 break;
675 default:
676 GNUNET_assert (0);
677 break;
678 }
679 }
680 r_task = GNUNET_SCHEDULER_add_delayed (backoff,
681 &reconnect_task,
682 NULL);
683 backoff = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_SECONDS,
684 GNUNET_TIME_relative_multiply (backoff, 2));
685}
686
687
688/**
397 * Convert a string to one or more IP addresses. 689 * Convert a string to one or more IP addresses.
398 * 690 *
399 * @param cfg configuration to use
400 * @param hostname the hostname to resolve 691 * @param hostname the hostname to resolve
401 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any" 692 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any"
402 * @param callback function to call with addresses 693 * @param callback function to call with addresses
@@ -405,23 +696,18 @@ loopback_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
405 * @return handle that can be used to cancel the request, NULL on error 696 * @return handle that can be used to cancel the request, NULL on error
406 */ 697 */
407struct GNUNET_RESOLVER_RequestHandle * 698struct GNUNET_RESOLVER_RequestHandle *
408GNUNET_RESOLVER_ip_get (const struct GNUNET_CONFIGURATION_Handle *cfg, 699GNUNET_RESOLVER_ip_get (const char *hostname,
409 const char *hostname,
410 int domain, 700 int domain,
411 struct GNUNET_TIME_Relative timeout, 701 struct GNUNET_TIME_Relative timeout,
412 GNUNET_RESOLVER_AddressCallback callback, 702 GNUNET_RESOLVER_AddressCallback callback,
413 void *callback_cls) 703 void *callback_cls)
414{ 704{
415 struct GNUNET_CLIENT_Connection *client;
416 struct GNUNET_RESOLVER_GetMessage *msg;
417 struct GNUNET_RESOLVER_RequestHandle *rh; 705 struct GNUNET_RESOLVER_RequestHandle *rh;
418 size_t slen; 706 size_t slen;
419 unsigned int i; 707 unsigned int i;
420 struct in_addr v4; 708 struct in_addr v4;
421 struct in6_addr v6; 709 struct in6_addr v6;
422 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
423 710
424 check_config (cfg);
425 slen = strlen (hostname) + 1; 711 slen = strlen (hostname) + 1;
426 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 712 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
427 { 713 {
@@ -433,9 +719,9 @@ GNUNET_RESOLVER_ip_get (const struct GNUNET_CONFIGURATION_Handle *cfg,
433 rh->addr_callback = callback; 719 rh->addr_callback = callback;
434 rh->cls = callback_cls; 720 rh->cls = callback_cls;
435 memcpy (&rh[1], hostname, slen); 721 memcpy (&rh[1], hostname, slen);
436 rh->hostname = (const char *) &rh[1]; 722 rh->data_len = slen;
437 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); 723 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
438 724 rh->direction = GNUNET_NO;
439 /* first, check if this is a numeric address */ 725 /* first, check if this is a numeric address */
440 if (((1 == inet_pton (AF_INET, 726 if (((1 == inet_pton (AF_INET,
441 hostname, 727 hostname,
@@ -457,104 +743,21 @@ GNUNET_RESOLVER_ip_get (const struct GNUNET_CONFIGURATION_Handle *cfg,
457 rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh); 743 rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh);
458 return rh; 744 return rh;
459 } 745 }
460 746 GNUNET_CONTAINER_DLL_insert_tail (req_head,
461 client = GNUNET_CLIENT_connect ("resolver", cfg); 747 req_tail,
462 if (client == NULL) 748 rh);
463 { 749 rh->was_queued = GNUNET_YES;
464 GNUNET_free (rh); 750 if (s_task != GNUNET_SCHEDULER_NO_TASK)
465 return NULL;
466 }
467 rh->client = client;
468
469 msg = (struct GNUNET_RESOLVER_GetMessage *) buf;
470 msg->header.size =
471 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + slen);
472 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
473 msg->direction = htonl (GNUNET_NO);
474 msg->domain = htonl (domain);
475 memcpy (&msg[1], hostname, slen);
476
477#if DEBUG_RESOLVER
478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
479 _("Resolver requests DNS resolution of hostname `%s'.\n"),
480 hostname);
481#endif
482 if (GNUNET_OK !=
483 GNUNET_CLIENT_transmit_and_get_response (client,
484 &msg->header,
485 timeout,
486 GNUNET_YES,
487 &handle_address_response, rh))
488 { 751 {
489 GNUNET_free (rh); 752 GNUNET_SCHEDULER_cancel (s_task);
490 GNUNET_CLIENT_disconnect (client, GNUNET_NO); 753 s_task = GNUNET_SCHEDULER_NO_TASK;
491 return NULL;
492 } 754 }
755 process_requests ();
493 return rh; 756 return rh;
494} 757}
495 758
496 759
497/** 760/**
498 * Process response with a hostname for a reverse DNS lookup.
499 *
500 * @param cls our "struct GNUNET_RESOLVER_RequestHandle" context
501 * @param msg message with the hostname, NULL on error
502 */
503static void
504handle_hostname_response (void *cls, const struct GNUNET_MessageHeader *msg)
505{
506 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
507 uint16_t size;
508 const char *hostname;
509
510 if (msg == NULL)
511 {
512 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
513 _("Timeout trying to resolve IP address `%s'.\n"),
514 GNUNET_a2s ((const void*) &rh[1], rh->salen));
515 rh->name_callback (rh->cls, NULL);
516 GNUNET_CLIENT_disconnect (rh->client, GNUNET_NO);
517 GNUNET_free (rh);
518 return;
519 }
520 size = ntohs (msg->size);
521 if (size == sizeof (struct GNUNET_MessageHeader))
522 {
523#if DEBUG_RESOLVER
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
525 _("Received end message resolving IP address `%s'.\n"),
526 GNUNET_a2s ((const void*) &rh[1], rh->salen));
527#endif
528 rh->name_callback (rh->cls, NULL);
529 GNUNET_CLIENT_disconnect (rh->client, GNUNET_NO);
530 GNUNET_free (rh);
531 return;
532 }
533 hostname = (const char *) &msg[1];
534 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
535 {
536 GNUNET_break (0);
537 rh->name_callback (rh->cls, NULL);
538 GNUNET_CLIENT_disconnect (rh->client, GNUNET_NO);
539 GNUNET_free (rh);
540 return;
541 }
542#if DEBUG_RESOLVER
543 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
544 _("Resolver returns `%s' for IP `%s'.\n"),
545 hostname,
546 GNUNET_a2s ((const void*) &rh[1], rh->salen));
547#endif
548 rh->name_callback (rh->cls, hostname);
549 GNUNET_CLIENT_receive (rh->client,
550 &handle_hostname_response,
551 rh,
552 GNUNET_TIME_absolute_get_remaining (rh->timeout));
553}
554
555
556
557/**
558 * We've been asked to convert an address to a string without 761 * We've been asked to convert an address to a string without
559 * a reverse lookup. Do it. 762 * a reverse lookup. Do it.
560 * 763 *
@@ -562,12 +765,13 @@ handle_hostname_response (void *cls, const struct GNUNET_MessageHeader *msg)
562 * @param tc unused scheduler context 765 * @param tc unused scheduler context
563 */ 766 */
564static void 767static void
565numeric_reverse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 768numeric_reverse (void *cls,
769 const struct GNUNET_SCHEDULER_TaskContext *tc)
566{ 770{
567 struct GNUNET_RESOLVER_RequestHandle *rh = cls; 771 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
568 char *result; 772 char *result;
569 773
570 result = no_resolve ((const struct sockaddr *) &rh[1], rh->salen); 774 result = no_resolve ((const struct sockaddr *) &rh[1], rh->data_len);
571#if DEBUG_RESOLVER 775#if DEBUG_RESOLVER
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver returns `%s'.\n"), result); 776 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver returns `%s'.\n"), result);
573#endif 777#endif
@@ -581,11 +785,9 @@ numeric_reverse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
581} 785}
582 786
583 787
584
585/** 788/**
586 * Get an IP address as a string. 789 * Get an IP address as a string.
587 * 790 *
588 * @param cfg configuration to use
589 * @param sa host address 791 * @param sa host address
590 * @param salen length of host address 792 * @param salen length of host address
591 * @param do_resolve use GNUNET_NO to return numeric hostname 793 * @param do_resolve use GNUNET_NO to return numeric hostname
@@ -595,27 +797,23 @@ numeric_reverse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
595 * @return handle that can be used to cancel the request 797 * @return handle that can be used to cancel the request
596 */ 798 */
597struct GNUNET_RESOLVER_RequestHandle * 799struct GNUNET_RESOLVER_RequestHandle *
598GNUNET_RESOLVER_hostname_get (const struct GNUNET_CONFIGURATION_Handle *cfg, 800GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
599 const struct sockaddr *sa,
600 socklen_t salen, 801 socklen_t salen,
601 int do_resolve, 802 int do_resolve,
602 struct GNUNET_TIME_Relative timeout, 803 struct GNUNET_TIME_Relative timeout,
603 GNUNET_RESOLVER_HostnameCallback callback, 804 GNUNET_RESOLVER_HostnameCallback callback,
604 void *cls) 805 void *cls)
605{ 806{
606 struct GNUNET_CLIENT_Connection *client;
607 struct GNUNET_RESOLVER_GetMessage *msg;
608 struct GNUNET_RESOLVER_RequestHandle *rh; 807 struct GNUNET_RESOLVER_RequestHandle *rh;
609 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
610 808
611 check_config (cfg); 809 check_config (cfg);
612 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen); 810 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen);
613 rh->name_callback = callback; 811 rh->name_callback = callback;
614 rh->cls = cls; 812 rh->cls = cls;
615 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); 813 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
616 rh->salen = salen;
617 memcpy (&rh[1], sa, salen); 814 memcpy (&rh[1], sa, salen);
618 815 rh->data_len = salen;
816 rh->direction = GNUNET_YES;
619 if (GNUNET_NO == do_resolve) 817 if (GNUNET_NO == do_resolve)
620 { 818 {
621 rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh); 819 rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh);
@@ -627,51 +825,31 @@ GNUNET_RESOLVER_hostname_get (const struct GNUNET_CONFIGURATION_Handle *cfg,
627 GNUNET_free (rh); 825 GNUNET_free (rh);
628 return NULL; 826 return NULL;
629 } 827 }
630 client = GNUNET_CLIENT_connect ("resolver", cfg); 828 GNUNET_CONTAINER_DLL_insert_tail (req_head,
631 if (client == NULL) 829 req_tail,
830 rh);
831 rh->was_queued = GNUNET_YES;
832 if (s_task != GNUNET_SCHEDULER_NO_TASK)
632 { 833 {
633 GNUNET_free (rh); 834 GNUNET_SCHEDULER_cancel (s_task);
634 return NULL; 835 s_task = GNUNET_SCHEDULER_NO_TASK;
635 }
636 rh->client = client;
637
638 msg = (struct GNUNET_RESOLVER_GetMessage *) buf;
639 msg->header.size =
640 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + salen);
641 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
642 msg->direction = htonl (GNUNET_YES);
643 msg->domain = htonl (sa->sa_family);
644 memcpy (&msg[1], sa, salen);
645#if DEBUG_RESOLVER
646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
647 _("Resolver requests DNS resolution of IP address.\n"));
648#endif
649 if (GNUNET_OK !=
650 GNUNET_CLIENT_transmit_and_get_response (client,
651 &msg->header,
652 timeout,
653 GNUNET_YES,
654 &handle_hostname_response, rh))
655 {
656 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
657 GNUNET_free (rh);
658 return NULL;
659 } 836 }
837 process_requests ();
660 return rh; 838 return rh;
661} 839}
662 840
663 841
664/** 842/**
665 * Get local fully qualified domain name 843 * Get local fully qualified domain name
844 *
666 * @return fqdn 845 * @return fqdn
667 */ 846 */
668char * 847char *
669GNUNET_RESOLVER_local_fqdn_get ( void ) 848GNUNET_RESOLVER_local_fqdn_get ()
670{ 849{
671 struct hostent *host; 850 struct hostent *host;
672 char hostname[GNUNET_OS_get_hostname_max_length() + 1]; 851 char hostname[GNUNET_OS_get_hostname_max_length() + 1];
673 852
674
675 if (0 != gethostname (hostname, sizeof (hostname) - 1)) 853 if (0 != gethostname (hostname, sizeof (hostname) - 1))
676 { 854 {
677 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | 855 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR |
@@ -682,21 +860,21 @@ GNUNET_RESOLVER_local_fqdn_get ( void )
682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
683 _("Resolving our FQDN `%s'\n"), hostname); 861 _("Resolving our FQDN `%s'\n"), hostname);
684#endif 862#endif
685 host = gethostbyname ( hostname ); 863 host = gethostbyname (hostname);
686 if ( NULL == host) 864 if (NULL == host)
687 { 865 {
688 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 866 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
689 _("Could not resolve our FQDN : %s\n"), 867 _("Could not resolve our FQDN : %s\n"),
690 hstrerror (h_errno)); 868 hstrerror (h_errno));
691 return NULL; 869 return NULL;
692 } 870 }
693 return GNUNET_strdup (host->h_name); 871 return GNUNET_strdup (host->h_name);
694} 872}
695 873
874
696/** 875/**
697 * Looking our own hostname. 876 * Looking our own hostname.
698 * 877 *
699 * @param cfg configuration to use
700 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any" 878 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any"
701 * @param callback function to call with addresses 879 * @param callback function to call with addresses
702 * @param cls closure for callback 880 * @param cls closure for callback
@@ -704,15 +882,13 @@ GNUNET_RESOLVER_local_fqdn_get ( void )
704 * @return handle that can be used to cancel the request, NULL on error 882 * @return handle that can be used to cancel the request, NULL on error
705 */ 883 */
706struct GNUNET_RESOLVER_RequestHandle * 884struct GNUNET_RESOLVER_RequestHandle *
707GNUNET_RESOLVER_hostname_resolve (const struct GNUNET_CONFIGURATION_Handle 885GNUNET_RESOLVER_hostname_resolve (int domain,
708 *cfg, int domain,
709 struct GNUNET_TIME_Relative timeout, 886 struct GNUNET_TIME_Relative timeout,
710 GNUNET_RESOLVER_AddressCallback callback, 887 GNUNET_RESOLVER_AddressCallback callback,
711 void *cls) 888 void *cls)
712{ 889{
713 char hostname[GNUNET_OS_get_hostname_max_length() + 1]; 890 char hostname[GNUNET_OS_get_hostname_max_length() + 1];
714 891
715 check_config (cfg);
716 if (0 != gethostname (hostname, sizeof (hostname) - 1)) 892 if (0 != gethostname (hostname, sizeof (hostname) - 1))
717 { 893 {
718 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | 894 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR |
@@ -723,8 +899,10 @@ GNUNET_RESOLVER_hostname_resolve (const struct GNUNET_CONFIGURATION_Handle
723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
724 _("Resolving our hostname `%s'\n"), hostname); 900 _("Resolving our hostname `%s'\n"), hostname);
725#endif 901#endif
726 return GNUNET_RESOLVER_ip_get (cfg, hostname, domain, timeout, callback, 902 return GNUNET_RESOLVER_ip_get (hostname,
727 cls); 903 domain,
904 timeout,
905 callback, cls);
728} 906}
729 907
730 908
@@ -734,18 +912,28 @@ GNUNET_RESOLVER_hostname_resolve (const struct GNUNET_CONFIGURATION_Handle
734 * been completed (i.e, the callback has been called to 912 * been completed (i.e, the callback has been called to
735 * signal timeout or the final result). 913 * signal timeout or the final result).
736 * 914 *
737 * @param h handle of request to cancel 915 * @param rh handle of request to cancel
738 */ 916 */
739void 917void
740GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *h) 918GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh)
741{ 919{
742 if (h->client != NULL) 920 if (rh->task != GNUNET_SCHEDULER_NO_TASK)
743 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); 921 {
744 if (h->task != GNUNET_SCHEDULER_NO_TASK) 922 GNUNET_SCHEDULER_cancel (rh->task);
745 GNUNET_SCHEDULER_cancel (h->task); 923 rh->task = GNUNET_SCHEDULER_NO_TASK;
746 GNUNET_free (h); 924 }
925 if (rh->was_transmitted == GNUNET_NO)
926 {
927 if (rh->was_queued == GNUNET_YES)
928 GNUNET_CONTAINER_DLL_remove (req_head,
929 req_tail,
930 rh);
931 GNUNET_free (rh);
932 return;
933 }
934 GNUNET_assert (rh->was_transmitted == GNUNET_YES);
935 rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
747} 936}
748 937
749 938
750
751/* end of resolver_api.c */ 939/* end of resolver_api.c */