aboutsummaryrefslogtreecommitdiff
path: root/src/util/resolver_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/resolver_api.c')
-rw-r--r--src/util/resolver_api.c662
1 files changed, 316 insertions, 346 deletions
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c
index 3ff005263..ef48faf59 100644
--- a/src/util/resolver_api.c
+++ b/src/util/resolver_api.c
@@ -53,7 +53,7 @@ static const char *loopback[] = {
53 * Configuration. 53 * Configuration.
54 */ 54 */
55static const struct GNUNET_CONFIGURATION_Handle *cfg; 55static const struct GNUNET_CONFIGURATION_Handle *cfg;
56 56
57/** 57/**
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.
@@ -69,7 +69,7 @@ static struct GNUNET_RESOLVER_RequestHandle *req_head;
69 * Tail of DLL of requests. 69 * Tail of DLL of requests.
70 */ 70 */
71static struct GNUNET_RESOLVER_RequestHandle *req_tail; 71static struct GNUNET_RESOLVER_RequestHandle *req_tail;
72 72
73/** 73/**
74 * How long should we wait to reconnect? 74 * How long should we wait to reconnect?
75 */ 75 */
@@ -192,28 +192,27 @@ check_config (const struct GNUNET_CONFIGURATION_Handle *cfg)
192#endif 192#endif
193 if (GNUNET_OK != 193 if (GNUNET_OK !=
194 GNUNET_CONFIGURATION_get_value_string (cfg, 194 GNUNET_CONFIGURATION_get_value_string (cfg,
195 "resolver", 195 "resolver", "HOSTNAME", &hostname))
196 "HOSTNAME", &hostname)) 196 {
197 { 197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
198 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 198 _("Must specify `%s' for `%s' in configuration!\n"),
199 _("Must specify `%s' for `%s' in configuration!\n"), 199 "HOSTNAME", "resolver");
200 "HOSTNAME", "resolver"); 200 GNUNET_assert (0);
201 GNUNET_assert (0); 201 }
202 }
203 if ((1 != inet_pton (AF_INET, 202 if ((1 != inet_pton (AF_INET,
204 hostname, 203 hostname,
205 &v4)) || (1 != inet_pton (AF_INET6, hostname, &v6))) 204 &v4)) || (1 != inet_pton (AF_INET6, hostname, &v6)))
205 {
206 GNUNET_free (hostname);
207 return;
208 }
209 i = 0;
210 while (loopback[i] != NULL)
211 if (0 == strcasecmp (loopback[i++], hostname))
206 { 212 {
207 GNUNET_free (hostname); 213 GNUNET_free (hostname);
208 return; 214 return;
209 } 215 }
210 i = 0;
211 while (loopback[i] != NULL)
212 if (0 == strcasecmp (loopback[i++], hostname))
213 {
214 GNUNET_free (hostname);
215 return;
216 }
217 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 216 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
218 _ 217 _
219 ("Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n"), 218 ("Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n"),
@@ -247,24 +246,23 @@ GNUNET_RESOLVER_disconnect ()
247 GNUNET_assert (NULL == req_head); 246 GNUNET_assert (NULL == req_head);
248 GNUNET_assert (NULL == req_tail); 247 GNUNET_assert (NULL == req_tail);
249 if (NULL != client) 248 if (NULL != client)
250 { 249 {
251#if DEBUG_RESOLVER 250#if DEBUG_RESOLVER
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from DNS service\n");
253 "Disconnecting from DNS service\n");
254#endif 252#endif
255 GNUNET_CLIENT_disconnect (client, GNUNET_NO); 253 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
256 client = NULL; 254 client = NULL;
257 } 255 }
258 if (r_task != GNUNET_SCHEDULER_NO_TASK) 256 if (r_task != GNUNET_SCHEDULER_NO_TASK)
259 { 257 {
260 GNUNET_SCHEDULER_cancel (r_task); 258 GNUNET_SCHEDULER_cancel (r_task);
261 r_task = GNUNET_SCHEDULER_NO_TASK; 259 r_task = GNUNET_SCHEDULER_NO_TASK;
262 } 260 }
263 if (s_task != GNUNET_SCHEDULER_NO_TASK) 261 if (s_task != GNUNET_SCHEDULER_NO_TASK)
264 { 262 {
265 GNUNET_SCHEDULER_cancel (s_task); 263 GNUNET_SCHEDULER_cancel (s_task);
266 s_task = GNUNET_SCHEDULER_NO_TASK; 264 s_task = GNUNET_SCHEDULER_NO_TASK;
267 } 265 }
268} 266}
269 267
270 268
@@ -285,37 +283,37 @@ no_resolve (const struct sockaddr *sa, socklen_t salen)
285 if (salen < sizeof (struct sockaddr)) 283 if (salen < sizeof (struct sockaddr))
286 return NULL; 284 return NULL;
287 switch (sa->sa_family) 285 switch (sa->sa_family)
286 {
287 case AF_INET:
288 if (salen != sizeof (struct sockaddr_in))
289 return NULL;
290 if (NULL ==
291 inet_ntop (AF_INET,
292 &((struct sockaddr_in *) sa)->sin_addr,
293 inet4, INET_ADDRSTRLEN))
288 { 294 {
289 case AF_INET: 295 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
290 if (salen != sizeof (struct sockaddr_in)) 296 return NULL;
291 return NULL;
292 if (NULL ==
293 inet_ntop (AF_INET,
294 &((struct sockaddr_in *) sa)->sin_addr,
295 inet4, INET_ADDRSTRLEN))
296 {
297 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
298 return NULL;
299 }
300 ret = GNUNET_strdup (inet4);
301 break;
302 case AF_INET6:
303 if (salen != sizeof (struct sockaddr_in6))
304 return NULL;
305 if (NULL ==
306 inet_ntop (AF_INET6,
307 &((struct sockaddr_in6 *) sa)->sin6_addr,
308 inet6, INET6_ADDRSTRLEN))
309 {
310 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
311 return NULL;
312 }
313 ret = GNUNET_strdup (inet6);
314 break;
315 default:
316 ret = NULL;
317 break;
318 } 297 }
298 ret = GNUNET_strdup (inet4);
299 break;
300 case AF_INET6:
301 if (salen != sizeof (struct sockaddr_in6))
302 return NULL;
303 if (NULL ==
304 inet_ntop (AF_INET6,
305 &((struct sockaddr_in6 *) sa)->sin6_addr,
306 inet6, INET6_ADDRSTRLEN))
307 {
308 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
309 return NULL;
310 }
311 ret = GNUNET_strdup (inet6);
312 break;
313 default:
314 ret = NULL;
315 break;
316 }
319 return ret; 317 return ret;
320} 318}
321 319
@@ -323,8 +321,7 @@ no_resolve (const struct sockaddr *sa, socklen_t salen)
323/** 321/**
324 * Adjust exponential back-off and reconnect to the service. 322 * Adjust exponential back-off and reconnect to the service.
325 */ 323 */
326static void 324static void reconnect ();
327reconnect ();
328 325
329 326
330/** 327/**
@@ -332,8 +329,7 @@ reconnect ();
332 * 329 *
333 * @param h handle to the resolver 330 * @param h handle to the resolver
334 */ 331 */
335static void 332static void process_requests ();
336process_requests ();
337 333
338 334
339/** 335/**
@@ -343,8 +339,7 @@ process_requests ();
343 * @param msg message with the hostname, NULL on error 339 * @param msg message with the hostname, NULL on error
344 */ 340 */
345static void 341static void
346handle_response (void *cls, 342handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
347 const struct GNUNET_MessageHeader *msg)
348{ 343{
349 struct GNUNET_RESOLVER_RequestHandle *rh = cls; 344 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
350 uint16_t size; 345 uint16_t size;
@@ -353,138 +348,129 @@ handle_response (void *cls,
353 socklen_t salen; 348 socklen_t salen;
354 349
355#if DEBUG_RESOLVER 350#if DEBUG_RESOLVER
356 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving response from DNS service\n");
357 "Receiving response from DNS service\n");
358#endif 352#endif
359 if (msg == NULL) 353 if (msg == NULL)
354 {
355 if (NULL != rh->name_callback)
356 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
357 _("Timeout trying to resolve IP address `%s'.\n"),
358 GNUNET_a2s ((const void *) &rh[1], rh->data_len));
359 else
360 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
361 _("Timeout trying to resolve hostname `%s'.\n"),
362 (const char *) &rh[1]);
363 /* check if request was canceled */
364 if (rh->was_transmitted != GNUNET_SYSERR)
360 { 365 {
361 if (NULL != rh->name_callback) 366 if (NULL != rh->name_callback)
362 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 367 {
363 _("Timeout trying to resolve IP address `%s'.\n"), 368 /* no reverse lookup was successful, return ip as string */
364 GNUNET_a2s ((const void*) &rh[1], rh->data_len)); 369 if (rh->received_response == GNUNET_NO)
365 else 370 rh->name_callback (rh->cls,
366 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 371 no_resolve ((const struct sockaddr *) &rh[1],
367 _("Timeout trying to resolve hostname `%s'.\n"), 372 rh->data_len));
368 (const char *) &rh[1]); 373 /* at least one reverse lookup was successful */
369 /* check if request was canceled */ 374 else
370 if (rh->was_transmitted != GNUNET_SYSERR) 375 rh->name_callback (rh->cls, NULL);
371 { 376 }
372 if (NULL != rh->name_callback) 377 if (NULL != rh->addr_callback)
373 { 378 rh->addr_callback (rh->cls, NULL, 0);
374 /* no reverse lookup was successful, return ip as string */
375 if (rh->received_response == GNUNET_NO)
376 rh->name_callback (rh->cls,
377 no_resolve ((const struct sockaddr *) &rh[1], rh->data_len));
378 /* at least one reverse lookup was successful */
379 else
380 rh->name_callback (rh->cls, NULL);
381 }
382 if (NULL != rh->addr_callback)
383 rh->addr_callback (rh->cls, NULL, 0);
384 }
385 GNUNET_CONTAINER_DLL_remove (req_head,
386 req_tail,
387 rh);
388 GNUNET_free (rh);
389 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
390 client = NULL;
391 reconnect ();
392 return;
393 } 379 }
380 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
381 GNUNET_free (rh);
382 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
383 client = NULL;
384 reconnect ();
385 return;
386 }
394 if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type)) 387 if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type))
388 {
389 GNUNET_break (0);
390 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
391 client = NULL;
392 reconnect ();
393 return;
394 }
395 size = ntohs (msg->size);
396 /* message contains not data, just header */
397 if (size == sizeof (struct GNUNET_MessageHeader))
398 {
399 /* check if request was canceled */
400 if (rh->was_transmitted != GNUNET_SYSERR)
401 {
402 if (NULL != rh->name_callback)
403 rh->name_callback (rh->cls, NULL);
404 if (NULL != rh->addr_callback)
405 rh->addr_callback (rh->cls, NULL, 0);
406 }
407 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
408 GNUNET_free (rh);
409 process_requests ();
410 return;
411 }
412 /* return reverse lookup results to caller */
413 if (NULL != rh->name_callback)
414 {
415 hostname = (const char *) &msg[1];
416 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
395 { 417 {
396 GNUNET_break (0); 418 GNUNET_break (0);
419 if (rh->was_transmitted != GNUNET_SYSERR)
420 rh->name_callback (rh->cls, NULL);
421 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
422 GNUNET_free (rh);
397 GNUNET_CLIENT_disconnect (client, GNUNET_NO); 423 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
398 client = NULL; 424 client = NULL;
399 reconnect (); 425 reconnect ();
400 return; 426 return;
401 } 427 }
402 size = ntohs (msg->size); 428#if DEBUG_RESOLVER
403 /* message contains not data, just header */ 429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
404 if (size == sizeof (struct GNUNET_MessageHeader)) 430 _("Resolver returns `%s' for IP `%s'.\n"),
431 hostname, GNUNET_a2s ((const void *) &rh[1], rh->data_len));
432#endif
433 if (rh->was_transmitted != GNUNET_SYSERR)
434 rh->name_callback (rh->cls, hostname);
435 rh->received_response = GNUNET_YES;
436 GNUNET_CLIENT_receive (client,
437 &handle_response,
438 rh,
439 GNUNET_TIME_absolute_get_remaining (rh->timeout));
440 }
441 /* return lookup results to caller */
442 if (NULL != rh->addr_callback)
443 {
444 sa = (const struct sockaddr *) &msg[1];
445 salen = size - sizeof (struct GNUNET_MessageHeader);
446 if (salen < sizeof (struct sockaddr))
405 { 447 {
406 /* check if request was canceled */ 448 GNUNET_break (0);
407 if (rh->was_transmitted != GNUNET_SYSERR) 449 if (rh->was_transmitted != GNUNET_SYSERR)
408 { 450 rh->addr_callback (rh->cls, NULL, 0);
409 if (NULL != rh->name_callback) 451 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
410 rh->name_callback (rh->cls, NULL);
411 if (NULL != rh->addr_callback)
412 rh->addr_callback (rh->cls, NULL, 0);
413 }
414 GNUNET_CONTAINER_DLL_remove (req_head,
415 req_tail,
416 rh);
417 GNUNET_free (rh); 452 GNUNET_free (rh);
418 process_requests (); 453 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
454 client = NULL;
455 reconnect ();
419 return; 456 return;
420 } 457 }
421 /* return reverse lookup results to caller */
422 if (NULL != rh->name_callback)
423 {
424 hostname = (const char *) &msg[1];
425 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
426 {
427 GNUNET_break (0);
428 if (rh->was_transmitted != GNUNET_SYSERR)
429 rh->name_callback (rh->cls, NULL);
430 GNUNET_CONTAINER_DLL_remove (req_head,
431 req_tail,
432 rh);
433 GNUNET_free (rh);
434 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
435 client = NULL;
436 reconnect ();
437 return;
438 }
439#if DEBUG_RESOLVER 458#if DEBUG_RESOLVER
459 {
460 char *ips = no_resolve (sa, salen);
461
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
441 _("Resolver returns `%s' for IP `%s'.\n"), 463 "Resolver returns `%s' for `%s'.\n",
442 hostname, 464 ips, (const char *) &rh[1]);
443 GNUNET_a2s ((const void*) &rh[1], rh->data_len)); 465 GNUNET_free (ips);
444#endif
445 if (rh->was_transmitted != GNUNET_SYSERR)
446 rh->name_callback (rh->cls, hostname);
447 rh->received_response = GNUNET_YES;
448 GNUNET_CLIENT_receive (client,
449 &handle_response,
450 rh,
451 GNUNET_TIME_absolute_get_remaining (rh->timeout));
452 } 466 }
453 /* return lookup results to caller */
454 if (NULL != rh->addr_callback)
455 {
456 sa = (const struct sockaddr *) &msg[1];
457 salen = size - sizeof (struct GNUNET_MessageHeader);
458 if (salen < sizeof (struct sockaddr))
459 {
460 GNUNET_break (0);
461 if (rh->was_transmitted != GNUNET_SYSERR)
462 rh->addr_callback (rh->cls, NULL, 0);
463 GNUNET_CONTAINER_DLL_remove (req_head,
464 req_tail,
465 rh);
466 GNUNET_free (rh);
467 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
468 client = NULL;
469 reconnect ();
470 return;
471 }
472#if DEBUG_RESOLVER
473 {
474 char *ips = no_resolve (sa, salen);
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Resolver returns `%s' for `%s'.\n",
477 ips,
478 (const char*) &rh[1]);
479 GNUNET_free (ips);
480 }
481#endif 467#endif
482 rh->addr_callback (rh->cls, sa, salen); 468 rh->addr_callback (rh->cls, sa, salen);
483 GNUNET_CLIENT_receive (client, 469 GNUNET_CLIENT_receive (client,
484 &handle_response, 470 &handle_response,
485 rh, 471 rh,
486 GNUNET_TIME_absolute_get_remaining (rh->timeout)); 472 GNUNET_TIME_absolute_get_remaining (rh->timeout));
487 } 473 }
488} 474}
489 475
490 476
@@ -514,30 +500,29 @@ numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
514#if HAVE_SOCKADDR_IN_SIN_LEN 500#if HAVE_SOCKADDR_IN_SIN_LEN
515 v6.sin6_len = sizeof (v6); 501 v6.sin6_len = sizeof (v6);
516#endif 502#endif
517 hostname = (const char*) &rh[1]; 503 hostname = (const char *) &rh[1];
518 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET)) && 504 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET)) &&
519 (1 == inet_pton (AF_INET, hostname, &v4.sin_addr))) 505 (1 == inet_pton (AF_INET, hostname, &v4.sin_addr)))
506 {
507 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
508 if ((rh->domain == AF_UNSPEC) &&
509 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
520 { 510 {
521 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); 511 /* this can happen on some systems IF "hostname" is "localhost" */
522 if ((rh->domain == AF_UNSPEC) && 512 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
523 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
524 {
525 /* this can happen on some systems IF "hostname" is "localhost" */
526 rh->addr_callback (rh->cls,
527 (const struct sockaddr *) &v6, sizeof (v6));
528 }
529 rh->addr_callback (rh->cls, NULL, 0);
530 GNUNET_free (rh);
531 return;
532 } 513 }
514 rh->addr_callback (rh->cls, NULL, 0);
515 GNUNET_free (rh);
516 return;
517 }
533 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET6)) && 518 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET6)) &&
534 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr))) 519 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
535 { 520 {
536 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); 521 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
537 rh->addr_callback (rh->cls, NULL, 0); 522 rh->addr_callback (rh->cls, NULL, 0);
538 GNUNET_free (rh); 523 GNUNET_free (rh);
539 return; 524 return;
540 } 525 }
541 /* why are we here? this task should not have been scheduled! */ 526 /* why are we here? this task should not have been scheduled! */
542 GNUNET_assert (0); 527 GNUNET_assert (0);
543 GNUNET_free (rh); 528 GNUNET_free (rh);
@@ -572,21 +557,21 @@ loopback_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
572#endif 557#endif
573 v6.sin6_addr = in6addr_loopback; 558 v6.sin6_addr = in6addr_loopback;
574 switch (rh->domain) 559 switch (rh->domain)
575 { 560 {
576 case AF_INET: 561 case AF_INET:
577 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); 562 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
578 break; 563 break;
579 case AF_INET6: 564 case AF_INET6:
580 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); 565 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
581 break; 566 break;
582 case AF_UNSPEC: 567 case AF_UNSPEC:
583 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); 568 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
584 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); 569 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
585 break; 570 break;
586 default: 571 default:
587 GNUNET_break (0); 572 GNUNET_break (0);
588 break; 573 break;
589 } 574 }
590 rh->addr_callback (rh->cls, NULL, 0); 575 rh->addr_callback (rh->cls, NULL, 0);
591 GNUNET_free (rh); 576 GNUNET_free (rh);
592} 577}
@@ -614,46 +599,46 @@ process_requests ()
614 struct GNUNET_RESOLVER_GetMessage *msg; 599 struct GNUNET_RESOLVER_GetMessage *msg;
615 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; 600 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
616 struct GNUNET_RESOLVER_RequestHandle *rh; 601 struct GNUNET_RESOLVER_RequestHandle *rh;
617 602
618 if (NULL == client) 603 if (NULL == client)
619 { 604 {
620 reconnect (); 605 reconnect ();
621 return; 606 return;
622 } 607 }
623 rh = req_head; 608 rh = req_head;
624 if (NULL == rh) 609 if (NULL == rh)
625 { 610 {
626 /* nothing to do, release socket really soon if there is nothing 611 /* nothing to do, release socket really soon if there is nothing
627 else happening... */ 612 * else happening... */
628 s_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, 613 s_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
629 &shutdown_task, NULL); 614 &shutdown_task, NULL);
630 return; 615 return;
631 } 616 }
632 if (GNUNET_YES == rh->was_transmitted) 617 if (GNUNET_YES == rh->was_transmitted)
633 return; /* waiting for reply */ 618 return; /* waiting for reply */
634 msg = (struct GNUNET_RESOLVER_GetMessage *) buf; 619 msg = (struct GNUNET_RESOLVER_GetMessage *) buf;
635 msg->header.size = 620 msg->header.size =
636 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len); 621 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len);
637 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST); 622 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
638 msg->direction = htonl (rh->direction); 623 msg->direction = htonl (rh->direction);
639 msg->domain = htonl (rh->domain); 624 msg->domain = htonl (rh->domain);
640 memcpy (&msg[1], &rh[1], rh->data_len); 625 memcpy (&msg[1], &rh[1], rh->data_len);
641#if DEBUG_RESOLVER 626#if DEBUG_RESOLVER
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
643 "Transmitting DNS resolution request to DNS service\n"); 628 "Transmitting DNS resolution request to DNS service\n");
644#endif 629#endif
645 if (GNUNET_OK != 630 if (GNUNET_OK !=
646 GNUNET_CLIENT_transmit_and_get_response (client, 631 GNUNET_CLIENT_transmit_and_get_response (client,
647 &msg->header, 632 &msg->header,
648 GNUNET_TIME_absolute_get_remaining (rh->timeout), 633 GNUNET_TIME_absolute_get_remaining
649 GNUNET_YES, 634 (rh->timeout), GNUNET_YES,
650 &handle_response, rh)) 635 &handle_response, rh))
651 { 636 {
652 GNUNET_CLIENT_disconnect (client, GNUNET_NO); 637 GNUNET_CLIENT_disconnect (client, GNUNET_NO);
653 client = NULL; 638 client = NULL;
654 reconnect (); 639 reconnect ();
655 return; 640 return;
656 } 641 }
657 rh->was_transmitted = GNUNET_YES; 642 rh->was_transmitted = GNUNET_YES;
658} 643}
659 644
@@ -665,26 +650,24 @@ process_requests ()
665 * @param tc scheduler context 650 * @param tc scheduler context
666 */ 651 */
667static void 652static void
668reconnect_task (void *cls, 653reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
669 const struct GNUNET_SCHEDULER_TaskContext *tc)
670{ 654{
671 r_task = GNUNET_SCHEDULER_NO_TASK; 655 r_task = GNUNET_SCHEDULER_NO_TASK;
672 if (NULL == req_head) 656 if (NULL == req_head)
673 return; /* no work pending */ 657 return; /* no work pending */
674 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 658 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
675 return; 659 return;
676#if DEBUG_RESOLVER 660#if DEBUG_RESOLVER
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to connect to DNS service\n");
678 "Trying to connect to DNS service\n");
679#endif 662#endif
680 client = GNUNET_CLIENT_connect ("resolver", cfg); 663 client = GNUNET_CLIENT_connect ("resolver", cfg);
681 if (NULL == client) 664 if (NULL == client)
682 { 665 {
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
684 "Failed to connect, will try again later\n"); 667 "Failed to connect, will try again later\n");
685 reconnect (); 668 reconnect ();
686 return; 669 return;
687 } 670 }
688 process_requests (); 671 process_requests ();
689} 672}
690 673
@@ -701,37 +684,33 @@ reconnect ()
701 return; 684 return;
702 GNUNET_assert (NULL == client); 685 GNUNET_assert (NULL == client);
703 if (NULL != (rh = req_head)) 686 if (NULL != (rh = req_head))
687 {
688 switch (rh->was_transmitted)
704 { 689 {
705 switch (rh->was_transmitted) 690 case GNUNET_NO:
706 { 691 /* nothing more to do */
707 case GNUNET_NO: 692 break;
708 /* nothing more to do */ 693 case GNUNET_YES:
709 break; 694 /* disconnected, transmit again! */
710 case GNUNET_YES: 695 rh->was_transmitted = GNUNET_NO;
711 /* disconnected, transmit again! */ 696 break;
712 rh->was_transmitted = GNUNET_NO; 697 case GNUNET_SYSERR:
713 break; 698 /* request was cancelled, remove entirely */
714 case GNUNET_SYSERR: 699 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
715 /* request was cancelled, remove entirely */ 700 GNUNET_free (rh);
716 GNUNET_CONTAINER_DLL_remove (req_head, 701 break;
717 req_tail, 702 default:
718 rh); 703 GNUNET_assert (0);
719 GNUNET_free (rh); 704 break;
720 break;
721 default:
722 GNUNET_assert (0);
723 break;
724 }
725 } 705 }
706 }
726#if DEBUG_RESOLVER 707#if DEBUG_RESOLVER
727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
728 "Will try to connect to DNS service in %llu ms\n", 709 "Will try to connect to DNS service in %llu ms\n",
729 (unsigned long long) backoff.rel_value); 710 (unsigned long long) backoff.rel_value);
730#endif 711#endif
731 GNUNET_assert (NULL != cfg); 712 GNUNET_assert (NULL != cfg);
732 r_task = GNUNET_SCHEDULER_add_delayed (backoff, 713 r_task = GNUNET_SCHEDULER_add_delayed (backoff, &reconnect_task, NULL);
733 &reconnect_task,
734 NULL);
735 backoff = GNUNET_TIME_relative_multiply (backoff, 2); 714 backoff = GNUNET_TIME_relative_multiply (backoff, 2);
736} 715}
737 716
@@ -760,11 +739,12 @@ GNUNET_RESOLVER_ip_get (const char *hostname,
760 struct in6_addr v6; 739 struct in6_addr v6;
761 740
762 slen = strlen (hostname) + 1; 741 slen = strlen (hostname) + 1;
763 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 742 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >=
764 { 743 GNUNET_SERVER_MAX_MESSAGE_SIZE)
765 GNUNET_break (0); 744 {
766 return NULL; 745 GNUNET_break (0);
767 } 746 return NULL;
747 }
768 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen); 748 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
769 rh->domain = domain; 749 rh->domain = domain;
770 rh->addr_callback = callback; 750 rh->addr_callback = callback;
@@ -782,27 +762,25 @@ GNUNET_RESOLVER_ip_get (const char *hostname,
782 hostname, 762 hostname,
783 &v6)) && 763 &v6)) &&
784 ((domain == AF_INET6) || (domain == AF_UNSPEC)))) 764 ((domain == AF_INET6) || (domain == AF_UNSPEC))))
785 { 765 {
786 rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh); 766 rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh);
787 return rh; 767 return rh;
788 } 768 }
789 /* then, check if this is a loopback address */ 769 /* then, check if this is a loopback address */
790 i = 0; 770 i = 0;
791 while (loopback[i] != NULL) 771 while (loopback[i] != NULL)
792 if (0 == strcasecmp (loopback[i++], hostname)) 772 if (0 == strcasecmp (loopback[i++], hostname))
793 {
794 rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh);
795 return rh;
796 }
797 GNUNET_CONTAINER_DLL_insert_tail (req_head,
798 req_tail,
799 rh);
800 rh->was_queued = GNUNET_YES;
801 if (s_task != GNUNET_SCHEDULER_NO_TASK)
802 { 773 {
803 GNUNET_SCHEDULER_cancel (s_task); 774 rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh);
804 s_task = GNUNET_SCHEDULER_NO_TASK; 775 return rh;
805 } 776 }
777 GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh);
778 rh->was_queued = GNUNET_YES;
779 if (s_task != GNUNET_SCHEDULER_NO_TASK)
780 {
781 GNUNET_SCHEDULER_cancel (s_task);
782 s_task = GNUNET_SCHEDULER_NO_TASK;
783 }
806 process_requests (); 784 process_requests ();
807 return rh; 785 return rh;
808} 786}
@@ -816,8 +794,7 @@ GNUNET_RESOLVER_ip_get (const char *hostname,
816 * @param tc unused scheduler context 794 * @param tc unused scheduler context
817 */ 795 */
818static void 796static void
819numeric_reverse (void *cls, 797numeric_reverse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
820 const struct GNUNET_SCHEDULER_TaskContext *tc)
821{ 798{
822 struct GNUNET_RESOLVER_RequestHandle *rh = cls; 799 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
823 char *result; 800 char *result;
@@ -827,10 +804,10 @@ numeric_reverse (void *cls,
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver returns `%s'.\n"), result); 804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver returns `%s'.\n"), result);
828#endif 805#endif
829 if (result != NULL) 806 if (result != NULL)
830 { 807 {
831 rh->name_callback (rh->cls, result); 808 rh->name_callback (rh->cls, result);
832 GNUNET_free (result); 809 GNUNET_free (result);
833 } 810 }
834 rh->name_callback (rh->cls, NULL); 811 rh->name_callback (rh->cls, NULL);
835 GNUNET_free (rh); 812 GNUNET_free (rh);
836} 813}
@@ -868,25 +845,24 @@ GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
868 rh->direction = GNUNET_YES; 845 rh->direction = GNUNET_YES;
869 rh->received_response = GNUNET_NO; 846 rh->received_response = GNUNET_NO;
870 if (GNUNET_NO == do_resolve) 847 if (GNUNET_NO == do_resolve)
871 { 848 {
872 rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh); 849 rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh);
873 return rh; 850 return rh;
874 } 851 }
875 if (salen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 852 if (salen + sizeof (struct GNUNET_RESOLVER_GetMessage) >=
876 { 853 GNUNET_SERVER_MAX_MESSAGE_SIZE)
877 GNUNET_break (0); 854 {
878 GNUNET_free (rh); 855 GNUNET_break (0);
879 return NULL; 856 GNUNET_free (rh);
880 } 857 return NULL;
881 GNUNET_CONTAINER_DLL_insert_tail (req_head, 858 }
882 req_tail, 859 GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh);
883 rh);
884 rh->was_queued = GNUNET_YES; 860 rh->was_queued = GNUNET_YES;
885 if (s_task != GNUNET_SCHEDULER_NO_TASK) 861 if (s_task != GNUNET_SCHEDULER_NO_TASK)
886 { 862 {
887 GNUNET_SCHEDULER_cancel (s_task); 863 GNUNET_SCHEDULER_cancel (s_task);
888 s_task = GNUNET_SCHEDULER_NO_TASK; 864 s_task = GNUNET_SCHEDULER_NO_TASK;
889 } 865 }
890 process_requests (); 866 process_requests ();
891 return rh; 867 return rh;
892} 868}
@@ -901,26 +877,25 @@ char *
901GNUNET_RESOLVER_local_fqdn_get () 877GNUNET_RESOLVER_local_fqdn_get ()
902{ 878{
903 struct hostent *host; 879 struct hostent *host;
904 char hostname[GNUNET_OS_get_hostname_max_length() + 1]; 880 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
905 881
906 if (0 != gethostname (hostname, sizeof (hostname) - 1)) 882 if (0 != gethostname (hostname, sizeof (hostname) - 1))
907 { 883 {
908 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | 884 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR |
909 GNUNET_ERROR_TYPE_BULK, "gethostname"); 885 GNUNET_ERROR_TYPE_BULK, "gethostname");
910 return NULL; 886 return NULL;
911 } 887 }
912#if DEBUG_RESOLVER 888#if DEBUG_RESOLVER
913 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
914 _("Resolving our FQDN `%s'\n"), hostname); 890 _("Resolving our FQDN `%s'\n"), hostname);
915#endif 891#endif
916 host = gethostbyname (hostname); 892 host = gethostbyname (hostname);
917 if (NULL == host) 893 if (NULL == host)
918 { 894 {
919 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 895 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
920 _("Could not resolve our FQDN : %s\n"), 896 _("Could not resolve our FQDN : %s\n"), hstrerror (h_errno));
921 hstrerror (h_errno)); 897 return NULL;
922 return NULL; 898 }
923 }
924 return GNUNET_strdup (host->h_name); 899 return GNUNET_strdup (host->h_name);
925} 900}
926 901
@@ -940,22 +915,19 @@ GNUNET_RESOLVER_hostname_resolve (int domain,
940 GNUNET_RESOLVER_AddressCallback callback, 915 GNUNET_RESOLVER_AddressCallback callback,
941 void *cls) 916 void *cls)
942{ 917{
943 char hostname[GNUNET_OS_get_hostname_max_length() + 1]; 918 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
944 919
945 if (0 != gethostname (hostname, sizeof (hostname) - 1)) 920 if (0 != gethostname (hostname, sizeof (hostname) - 1))
946 { 921 {
947 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | 922 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR |
948 GNUNET_ERROR_TYPE_BULK, "gethostname"); 923 GNUNET_ERROR_TYPE_BULK, "gethostname");
949 return NULL; 924 return NULL;
950 } 925 }
951#if DEBUG_RESOLVER 926#if DEBUG_RESOLVER
952 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
953 _("Resolving our hostname `%s'\n"), hostname); 928 _("Resolving our hostname `%s'\n"), hostname);
954#endif 929#endif
955 return GNUNET_RESOLVER_ip_get (hostname, 930 return GNUNET_RESOLVER_ip_get (hostname, domain, timeout, callback, cls);
956 domain,
957 timeout,
958 callback, cls);
959} 931}
960 932
961 933
@@ -971,21 +943,19 @@ void
971GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh) 943GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh)
972{ 944{
973 if (rh->task != GNUNET_SCHEDULER_NO_TASK) 945 if (rh->task != GNUNET_SCHEDULER_NO_TASK)
974 { 946 {
975 GNUNET_SCHEDULER_cancel (rh->task); 947 GNUNET_SCHEDULER_cancel (rh->task);
976 rh->task = GNUNET_SCHEDULER_NO_TASK; 948 rh->task = GNUNET_SCHEDULER_NO_TASK;
977 } 949 }
978 if (rh->was_transmitted == GNUNET_NO) 950 if (rh->was_transmitted == GNUNET_NO)
979 { 951 {
980 if (rh->was_queued == GNUNET_YES) 952 if (rh->was_queued == GNUNET_YES)
981 GNUNET_CONTAINER_DLL_remove (req_head, 953 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
982 req_tail, 954 GNUNET_free (rh);
983 rh); 955 return;
984 GNUNET_free (rh); 956 }
985 return;
986 }
987 GNUNET_assert (rh->was_transmitted == GNUNET_YES); 957 GNUNET_assert (rh->was_transmitted == GNUNET_YES);
988 rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */ 958 rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
989} 959}
990 960
991 961