summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-01-15 16:36:30 +0000
committerChristian Grothoff <christian@grothoff.org>2010-01-15 16:36:30 +0000
commit2ea6ea66581947fce7820357f9a260896ffd4199 (patch)
tree18f2cb95bdc77b2978cc8e53de10a186aa37ab72
parenta257f028184102b04995c6774f065200919a3dff (diff)
downloadgnunet-2ea6ea66581947fce7820357f9a260896ffd4199.tar.gz
gnunet-2ea6ea66581947fce7820357f9a260896ffd4199.zip
making code work better with dual-stack, preparing for triple-stack
-rw-r--r--src/util/server.c165
-rw-r--r--src/util/service.c179
-rw-r--r--src/util/test_client.c10
-rw-r--r--src/util/test_server.c10
-rw-r--r--src/util/test_server_disconnect.c10
-rw-r--r--src/util/test_server_with_client.c10
-rw-r--r--src/util/test_service.c3
7 files changed, 262 insertions, 125 deletions
diff --git a/src/util/server.c b/src/util/server.c
index 72eceac44..036c8a441 100644
--- a/src/util/server.c
+++ b/src/util/server.c
@@ -112,6 +112,12 @@ struct GNUNET_SERVER_Handle
112 void *access_cls; 112 void *access_cls;
113 113
114 /** 114 /**
115 * NULL-terminated array of sockets used to listen for new
116 * connections.
117 */
118 struct GNUNET_NETWORK_Handle **listen_sockets;
119
120 /**
115 * After how long should an idle connection time 121 * After how long should an idle connection time
116 * out (on write). 122 * out (on write).
117 */ 123 */
@@ -123,12 +129,6 @@ struct GNUNET_SERVER_Handle
123 size_t maxbuf; 129 size_t maxbuf;
124 130
125 /** 131 /**
126 * Socket used to listen for new connections. Set to
127 * "-1" by GNUNET_SERVER_destroy to initiate shutdown.
128 */
129 struct GNUNET_NETWORK_Handle *listen_socket;
130
131 /**
132 * Task scheduled to do the listening. 132 * Task scheduled to do the listening.
133 */ 133 */
134 GNUNET_SCHEDULER_TaskIdentifier listen_task; 134 GNUNET_SCHEDULER_TaskIdentifier listen_task;
@@ -265,8 +265,7 @@ struct GNUNET_SERVER_Client
265 265
266 266
267/** 267/**
268 * Scheduler says our listen socket is ready. 268 * Scheduler says our listen socket is ready. Process it!
269 * Process it!
270 * 269 *
271 * @param cls handle to our server for which we are processing the listen 270 * @param cls handle to our server for which we are processing the listen
272 * socket 271 * socket
@@ -280,10 +279,13 @@ process_listen_socket (void *cls,
280 struct GNUNET_CONNECTION_Handle *sock; 279 struct GNUNET_CONNECTION_Handle *sock;
281 struct GNUNET_SERVER_Client *client; 280 struct GNUNET_SERVER_Client *client;
282 struct GNUNET_NETWORK_FDSet *r; 281 struct GNUNET_NETWORK_FDSet *r;
282 unsigned int i;
283 283
284 server->listen_task = GNUNET_SCHEDULER_NO_TASK; 284 server->listen_task = GNUNET_SCHEDULER_NO_TASK;
285 r = GNUNET_NETWORK_fdset_create (); 285 r = GNUNET_NETWORK_fdset_create ();
286 GNUNET_NETWORK_fdset_set (r, server->listen_socket); 286 i = 0;
287 while (NULL != server->listen_sockets[i])
288 GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
287 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 289 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
288 { 290 {
289 /* ignore shutdown, someone else will take care of it! */ 291 /* ignore shutdown, someone else will take care of it! */
@@ -297,27 +299,33 @@ process_listen_socket (void *cls,
297 GNUNET_NETWORK_fdset_destroy (r); 299 GNUNET_NETWORK_fdset_destroy (r);
298 return; 300 return;
299 } 301 }
300 GNUNET_assert (GNUNET_NETWORK_fdset_isset 302 i = 0;
301 (tc->read_ready, server->listen_socket)); 303 while (NULL != server->listen_sockets[i])
302 sock =
303 GNUNET_CONNECTION_create_from_accept (tc->sched, server->access,
304 server->access_cls,
305 server->listen_socket,
306 server->maxbuf);
307 if (sock != NULL)
308 { 304 {
305 if (GNUNET_NETWORK_fdset_isset (tc->read_ready, server->listen_sockets[i]))
306 {
307 sock =
308 GNUNET_CONNECTION_create_from_accept (tc->sched, server->access,
309 server->access_cls,
310 server->listen_sockets[i],
311 server->maxbuf);
312 if (sock != NULL)
313 {
309#if DEBUG_SERVER 314#if DEBUG_SERVER
310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
311 "Server accepted incoming connection.\n"); 316 "Server accepted incoming connection.\n");
312#endif 317#endif
313 client = GNUNET_SERVER_connect_socket (server, sock); 318 client = GNUNET_SERVER_connect_socket (server, sock);
314 GNUNET_CONNECTION_ignore_shutdown (sock, server->clients_ignore_shutdown); 319 GNUNET_CONNECTION_ignore_shutdown (sock, server->clients_ignore_shutdown);
315 /* decrement reference count, we don't keep "client" alive */ 320 /* decrement reference count, we don't keep "client" alive */
316 GNUNET_SERVER_client_drop (client); 321 GNUNET_SERVER_client_drop (client);
317 } 322 }
323 }
324 i++;
325 }
318 /* listen for more! */ 326 /* listen for more! */
319 server->listen_task = GNUNET_SCHEDULER_add_select (server->sched, 327 server->listen_task = GNUNET_SCHEDULER_add_select (server->sched,
320 GNUNET_SCHEDULER_PRIORITY_HIGH, 328 GNUNET_SCHEDULER_PRIORITY_HIGH,
321 GNUNET_SCHEDULER_NO_TASK, 329 GNUNET_SCHEDULER_NO_TASK,
322 GNUNET_TIME_UNIT_FOREVER_REL, 330 GNUNET_TIME_UNIT_FOREVER_REL,
323 r, NULL, 331 r, NULL,
@@ -338,6 +346,7 @@ open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
338 const static int on = 1; 346 const static int on = 1;
339 struct GNUNET_NETWORK_Handle *sock; 347 struct GNUNET_NETWORK_Handle *sock;
340 uint16_t port; 348 uint16_t port;
349 int eno;
341 350
342 switch (serverAddr->sa_family) 351 switch (serverAddr->sa_family)
343 { 352 {
@@ -348,39 +357,55 @@ open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
348 port = ntohs (((const struct sockaddr_in6 *) serverAddr)->sin6_port); 357 port = ntohs (((const struct sockaddr_in6 *) serverAddr)->sin6_port);
349 break; 358 break;
350 default: 359 default:
351 GNUNET_break (0); 360 port = 0;
352 return NULL; 361 break;
353 } 362 }
354 sock = GNUNET_NETWORK_socket_create (serverAddr->sa_family, SOCK_STREAM, 0); 363 sock = GNUNET_NETWORK_socket_create (serverAddr->sa_family, SOCK_STREAM, 0);
355 if (NULL == sock) 364 if (NULL == sock)
356 { 365 {
357 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); 366 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
367 errno = 0;
358 return NULL; 368 return NULL;
359 } 369 }
360 if (GNUNET_NETWORK_socket_setsockopt 370 if ( (port != 0) &&
361 (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) 371 (GNUNET_NETWORK_socket_setsockopt
372 (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK))
362 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 373 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
363 "setsockopt"); 374 "setsockopt");
364 /* bind the socket */ 375 /* bind the socket */
365 if (GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen) != GNUNET_OK) 376 if (GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen) != GNUNET_OK)
366 { 377 {
367 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); 378 eno = errno;
368 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 379 if (errno != EADDRINUSE)
369 _ 380 {
370 ("`%s' failed for port %d. Is the service already running?\n"), 381 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
371 "bind", port); 382 fail if we already took the port on IPv6; if both IPv4 and
383 IPv6 binds fail, then our caller will log using the
384 errno preserved in 'eno' */
385 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
386 if (port != 0)
387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
388 _
389 ("`%s' failed for port %d (%s).\n"),
390 "bind", port,
391 (serverAddr->sa_family == AF_INET) ? "IPv4" : "IPv6");
392 eno = 0;
393 }
372 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); 394 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
395 errno = eno;
373 return NULL; 396 return NULL;
374 } 397 }
375 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5)) 398 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
376 { 399 {
377 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); 400 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
378 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); 401 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
402 errno = 0;
379 return NULL; 403 return NULL;
380 } 404 }
381#if DEBUG_SERVER 405#if DEBUG_SERVER
382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 406 if (port != 0)
383 "Server starts to listen on port %u.\n", port); 407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 "Server starts to listen on port %u.\n", port);
384#endif 409#endif
385 return sock; 410 return sock;
386} 411}
@@ -392,8 +417,7 @@ open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
392 * @param sched scheduler to use 417 * @param sched scheduler to use
393 * @param access function for access control 418 * @param access function for access control
394 * @param access_cls closure for access 419 * @param access_cls closure for access
395 * @param serverAddr address to listen on (including port), use NULL 420 * @param serverAddr address to listen on (including port), NULL terminated array
396 * for internal server (no listening)
397 * @param socklen length of serverAddr 421 * @param socklen length of serverAddr
398 * @param maxbuf maximum write buffer size for accepted sockets 422 * @param maxbuf maximum write buffer size for accepted sockets
399 * @param idle_timeout after how long should we timeout idle connections? 423 * @param idle_timeout after how long should we timeout idle connections?
@@ -406,35 +430,61 @@ struct GNUNET_SERVER_Handle *
406GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched, 430GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
407 GNUNET_CONNECTION_AccessCheck access, 431 GNUNET_CONNECTION_AccessCheck access,
408 void *access_cls, 432 void *access_cls,
409 const struct sockaddr *serverAddr, 433 struct sockaddr *const *serverAddr,
410 socklen_t socklen, 434 const socklen_t *socklen,
411 size_t maxbuf, 435 size_t maxbuf,
412 struct GNUNET_TIME_Relative 436 struct GNUNET_TIME_Relative
413 idle_timeout, int require_found) 437 idle_timeout,
438 int require_found)
414{ 439{
415 struct GNUNET_SERVER_Handle *ret; 440 struct GNUNET_SERVER_Handle *ret;
416 struct GNUNET_NETWORK_Handle *lsock; 441 struct GNUNET_NETWORK_Handle **lsocks;
417 struct GNUNET_NETWORK_FDSet *r; 442 struct GNUNET_NETWORK_FDSet *r;
443 unsigned int i;
444 unsigned int j;
418 445
419 lsock = NULL; 446 i = 0;
420 if (serverAddr != NULL) 447 while (serverAddr[i] != NULL)
448 i++;
449 if (i > 0)
450 {
451 lsocks = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle*) * (i+1));
452 i = 0;
453 j = 0;
454 while (serverAddr[i] != NULL)
455 {
456 lsocks[j] = open_listen_socket (serverAddr[i], socklen[i]);
457 if (lsocks[j] != NULL)
458 j++;
459 i++;
460 }
461 if (j == 0)
462 {
463 if (errno != 0)
464 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
465 GNUNET_free (lsocks);
466 lsocks = NULL;
467 }
468 }
469 else
421 { 470 {
422 lsock = open_listen_socket (serverAddr, socklen); 471 lsocks = NULL;
423 if (lsock == NULL)
424 return NULL;
425 } 472 }
426 ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle)); 473 ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
427 ret->sched = sched; 474 ret->sched = sched;
428 ret->maxbuf = maxbuf; 475 ret->maxbuf = maxbuf;
429 ret->idle_timeout = idle_timeout; 476 ret->idle_timeout = idle_timeout;
430 ret->listen_socket = lsock; 477 ret->listen_sockets = lsocks;
431 ret->access = access; 478 ret->access = access;
432 ret->access_cls = access_cls; 479 ret->access_cls = access_cls;
433 ret->require_found = require_found; 480 ret->require_found = require_found;
434 if (lsock != NULL) 481 if (lsocks != NULL)
435 { 482 {
483
436 r = GNUNET_NETWORK_fdset_create (); 484 r = GNUNET_NETWORK_fdset_create ();
437 GNUNET_NETWORK_fdset_set (r, ret->listen_socket); 485 i = 0;
486 while (NULL != ret->listen_sockets[i])
487 GNUNET_NETWORK_fdset_set (r, ret->listen_sockets[i++]);
438 ret->listen_task = GNUNET_SCHEDULER_add_select (sched, 488 ret->listen_task = GNUNET_SCHEDULER_add_select (sched,
439 GNUNET_SCHEDULER_PRIORITY_HIGH, 489 GNUNET_SCHEDULER_PRIORITY_HIGH,
440 GNUNET_SCHEDULER_NO_TASK, 490 GNUNET_SCHEDULER_NO_TASK,
@@ -457,6 +507,7 @@ GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
457 struct GNUNET_SERVER_Client *pos; 507 struct GNUNET_SERVER_Client *pos;
458 struct HandlerList *hpos; 508 struct HandlerList *hpos;
459 struct NotifyList *npos; 509 struct NotifyList *npos;
510 unsigned int i;
460 511
461#if DEBUG_SERVER 512#if DEBUG_SERVER
462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n"); 513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n");
@@ -466,8 +517,14 @@ GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
466 GNUNET_SCHEDULER_cancel (s->sched, s->listen_task); 517 GNUNET_SCHEDULER_cancel (s->sched, s->listen_task);
467 s->listen_task = GNUNET_SCHEDULER_NO_TASK; 518 s->listen_task = GNUNET_SCHEDULER_NO_TASK;
468 } 519 }
469 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s->listen_socket)); 520 if (s->listen_sockets != NULL)
470 s->listen_socket = NULL; 521 {
522 i = 0;
523 while (s->listen_sockets[i] != NULL)
524 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s->listen_sockets[i++]));
525 GNUNET_free (s->listen_sockets);
526 s->listen_sockets = NULL;
527 }
471 while (s->clients != NULL) 528 while (s->clients != NULL)
472 { 529 {
473 pos = s->clients; 530 pos = s->clients;
diff --git a/src/util/service.c b/src/util/service.c
index 034cff170..af17a7f3e 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -35,6 +35,8 @@
35#include "gnunet_server_lib.h" 35#include "gnunet_server_lib.h"
36#include "gnunet_service_lib.h" 36#include "gnunet_service_lib.h"
37 37
38#define DEBUG_SERVICE GNUNET_NO
39
38/* ******************* access control ******************** */ 40/* ******************* access control ******************** */
39 41
40/** 42/**
@@ -433,9 +435,9 @@ struct GNUNET_SERVICE_Context
433 struct GNUNET_SCHEDULER_Handle *sched; 435 struct GNUNET_SCHEDULER_Handle *sched;
434 436
435 /** 437 /**
436 * Address to bind to. 438 * NULL-terminated array of addresses to bind to.
437 */ 439 */
438 struct sockaddr *addr; 440 struct sockaddr **addrs;
439 441
440 /** 442 /**
441 * Name of our service. 443 * Name of our service.
@@ -519,9 +521,9 @@ struct GNUNET_SERVICE_Context
519 enum GNUNET_SERVICE_Options options; 521 enum GNUNET_SERVICE_Options options;
520 522
521 /** 523 /**
522 * Length of addr. 524 * Array of the lengths of the entries in addrs.
523 */ 525 */
524 socklen_t addrlen; 526 socklen_t * addrlens;
525 527
526}; 528};
527 529
@@ -766,8 +768,10 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
766 struct addrinfo hints; 768 struct addrinfo hints;
767 struct addrinfo *res; 769 struct addrinfo *res;
768 struct addrinfo *pos; 770 struct addrinfo *pos;
771 struct addrinfo *next;
769 int ret; 772 int ret;
770 int tolerant; 773 int tolerant;
774 unsigned int i;
771 struct GNUNET_NETWORK_Handle *desc; 775 struct GNUNET_NETWORK_Handle *desc;
772 776
773 if (GNUNET_CONFIGURATION_have_value (sctx->cfg, 777 if (GNUNET_CONFIGURATION_have_value (sctx->cfg,
@@ -884,6 +888,12 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
884 888
885 if (hostname != NULL) 889 if (hostname != NULL)
886 { 890 {
891#if DEBUG_SERVICE
892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
893 "Resolving `%s' since that is where `%s' will bind to.\n",
894 hostname,
895 sctx->serviceName);
896#endif
887 memset (&hints, 0, sizeof (struct addrinfo)); 897 memset (&hints, 0, sizeof (struct addrinfo));
888 if (disablev6) 898 if (disablev6)
889 hints.ai_family = AF_INET; 899 hints.ai_family = AF_INET;
@@ -896,13 +906,16 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
896 GNUNET_free (hostname); 906 GNUNET_free (hostname);
897 return GNUNET_SYSERR; 907 return GNUNET_SYSERR;
898 } 908 }
899 pos = res; 909 next = res;
900 while ((NULL != pos) && 910 i = 0;
901 (((disablev6) && 911 while (NULL != (pos = next))
902 (pos->ai_family != AF_INET)) || 912 {
903 ((pos->ai_family != AF_INET) && (pos->ai_family != AF_INET6)))) 913 next = pos->ai_next;
904 pos = pos->ai_next; 914 if ( (disablev6) && (pos->ai_family == AF_INET6))
905 if (pos == NULL) 915 continue;
916 i++;
917 }
918 if (0 == i)
906 { 919 {
907 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 920 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
908 _("Failed to find %saddress for `%s'.\n"), 921 _("Failed to find %saddress for `%s'.\n"),
@@ -911,32 +924,42 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
911 GNUNET_free (hostname); 924 GNUNET_free (hostname);
912 return GNUNET_SYSERR; 925 return GNUNET_SYSERR;
913 } 926 }
927 sctx->addrs = GNUNET_malloc ((i+1) * sizeof(struct sockaddr*));
928 sctx->addrlens = GNUNET_malloc ((i+1) * sizeof (socklen_t));
929 i = 0;
930 next = res;
931 while (NULL != (pos = next))
932 {
933 next = pos->ai_next;
934 if ( (disablev6) && (pos->ai_family == AF_INET6))
935 continue;
936#if DEBUG_SERVICE
937 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
938 "Service `%s' will bind to `%s'\n",
939 sctx->serviceName,
940 GNUNET_a2s (pos->ai_addr,
941 pos->ai_addrlen));
942#endif
943 if (pos->ai_family == AF_INET)
944 {
945 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in));
946 sctx->addrlens[i] = pos->ai_addrlen;
947 sctx->addrs[i] = GNUNET_malloc (sctx->addrlens[i]);
948 memcpy (sctx->addrs[i], pos->ai_addr, sctx->addrlens[i]);
949 ((struct sockaddr_in *) sctx->addrs[i])->sin_port = htons (port);
950 }
951 else
952 {
953 GNUNET_assert (pos->ai_family == AF_INET6);
954 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6));
955 sctx->addrlens[i] = pos->ai_addrlen;
956 sctx->addrs[i] = GNUNET_malloc (sctx->addrlens[i]);
957 memcpy (sctx->addrs[i], pos->ai_addr, sctx->addrlens[i]);
958 ((struct sockaddr_in6 *) sctx->addrs[i])->sin6_port = htons (port);
959 }
960 i++;
961 }
914 GNUNET_free (hostname); 962 GNUNET_free (hostname);
915 if (pos->ai_family == AF_INET)
916 {
917 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in));
918 sctx->addrlen = pos->ai_addrlen;
919 sctx->addr = GNUNET_malloc (sctx->addrlen);
920 memcpy (sctx->addr, res->ai_addr, sctx->addrlen);
921 ((struct sockaddr_in *) sctx->addr)->sin_port = htons (port);
922 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
923 _
924 ("Configured to bind to %s address; %s connections to this service will fail!\n"),
925 "IPv4", "IPv6");
926 }
927 else
928 {
929 GNUNET_assert (pos->ai_family == AF_INET6);
930 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6));
931 sctx->addrlen = pos->ai_addrlen;
932 sctx->addr = GNUNET_malloc (sctx->addrlen);
933 memcpy (sctx->addr, res->ai_addr, sctx->addrlen);
934 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
935 _
936 ("Configured to bind to %s address; %s connections to this service will fail!\n"),
937 "IPv6", "IPv4");
938 ((struct sockaddr_in6 *) sctx->addr)->sin6_port = htons (port);
939 }
940 freeaddrinfo (res); 963 freeaddrinfo (res);
941 } 964 }
942 else 965 else
@@ -945,28 +968,38 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
945 if (disablev6) 968 if (disablev6)
946 { 969 {
947 /* V4-only */ 970 /* V4-only */
948 sctx->addrlen = sizeof (struct sockaddr_in); 971 sctx->addrs = GNUNET_malloc (2 * sizeof(struct sockaddr*));
949 sctx->addr = GNUNET_malloc (sctx->addrlen); 972 sctx->addrlens = GNUNET_malloc (2 * sizeof (socklen_t));
973 sctx->addrlens[0] = sizeof (struct sockaddr_in);
974 sctx->addrs[0] = GNUNET_malloc (sctx->addrlens[0]);
950#if HAVE_SOCKADDR_IN_SIN_LEN 975#if HAVE_SOCKADDR_IN_SIN_LEN
951 ((struct sockaddr_in *) sctx->addr)->sin_len = sctx->addrlen; 976 ((struct sockaddr_in *) sctx->addrs[0])->sin_len = sctx->addrlens[0];
952#endif 977#endif
953 ((struct sockaddr_in *) sctx->addr)->sin_family = AF_INET; 978 ((struct sockaddr_in *) sctx->addrs[0])->sin_family = AF_INET;
954 ((struct sockaddr_in *) sctx->addr)->sin_port = htons (port); 979 ((struct sockaddr_in *) sctx->addrs[0])->sin_port = htons (port);
955 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
956 _
957 ("Configured to bind to %s address; %s connections to this service will fail!\n"),
958 "IPv4", "IPv6");
959 } 980 }
960 else 981 else
961 { 982 {
962 /* dual stack */ 983 /* dual stack */
963 sctx->addrlen = sizeof (struct sockaddr_in6); 984 sctx->addrs = GNUNET_malloc (3 * sizeof(struct sockaddr*));
964 sctx->addr = GNUNET_malloc (sctx->addrlen); 985 sctx->addrlens = GNUNET_malloc (3 * sizeof (socklen_t));
986
987 sctx->addrlens[0] = sizeof (struct sockaddr_in6);
988 sctx->addrs[0] = GNUNET_malloc (sctx->addrlens[0]);
989#if HAVE_SOCKADDR_IN_SIN_LEN
990 ((struct sockaddr_in6 *) sctx->addrs[0])->sin6_len = sctx->addrlen[0];
991#endif
992 ((struct sockaddr_in6 *) sctx->addrs[0])->sin6_family = AF_INET6;
993 ((struct sockaddr_in6 *) sctx->addrs[0])->sin6_port = htons (port);
994
995 sctx->addrlens[1] = sizeof (struct sockaddr_in);
996 sctx->addrs[1] = GNUNET_malloc (sctx->addrlens[1]);
965#if HAVE_SOCKADDR_IN_SIN_LEN 997#if HAVE_SOCKADDR_IN_SIN_LEN
966 ((struct sockaddr_in6 *) sctx->addr)->sin6_len = sctx->addrlen; 998 ((struct sockaddr_in *) sctx->addrs[1])->sin_len = sctx->addrlens[1];
967#endif 999#endif
968 ((struct sockaddr_in6 *) sctx->addr)->sin6_family = AF_INET6; 1000 ((struct sockaddr_in *) sctx->addrs[1])->sin_family = AF_INET;
969 ((struct sockaddr_in6 *) sctx->addr)->sin6_port = htons (port); 1001 ((struct sockaddr_in *) sctx->addrs[1])->sin_port = htons (port);
1002
970 } 1003 }
971 } 1004 }
972 sctx->maxbuf = (size_t) maxbuf; 1005 sctx->maxbuf = (size_t) maxbuf;
@@ -1090,15 +1123,21 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1090 sctx->server = GNUNET_SERVER_create (tc->sched, 1123 sctx->server = GNUNET_SERVER_create (tc->sched,
1091 &check_access, 1124 &check_access,
1092 sctx, 1125 sctx,
1093 sctx->addr, 1126 sctx->addrs,
1094 sctx->addrlen, 1127 sctx->addrlens,
1095 sctx->maxbuf, 1128 sctx->maxbuf,
1096 sctx->timeout, sctx->require_found); 1129 sctx->timeout, sctx->require_found);
1097 if (sctx->server == NULL) 1130 if (sctx->server == NULL)
1098 { 1131 {
1099 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1132 i = 0;
1100 _("Failed to start `%s' at `%s'\n"), 1133 while (sctx->addrs[i] != NULL)
1101 sctx->serviceName, GNUNET_a2s (sctx->addr, sctx->addrlen)); 1134 {
1135 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1136 _("Failed to start `%s' at `%s'\n"),
1137 sctx->serviceName,
1138 GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1139 i++;
1140 }
1102 sctx->ret = GNUNET_SYSERR; 1141 sctx->ret = GNUNET_SYSERR;
1103 return; 1142 return;
1104 } 1143 }
@@ -1123,9 +1162,15 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1123 sctx->ready_confirm_fd = -1; 1162 sctx->ready_confirm_fd = -1;
1124 write_pid_file (sctx, getpid ()); 1163 write_pid_file (sctx, getpid ());
1125 } 1164 }
1126 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1165 i = 0;
1127 _("Service `%s' runs at %s\n"), 1166 while (sctx->addrs[i] != NULL)
1128 sctx->serviceName, GNUNET_a2s (sctx->addr, sctx->addrlen)); 1167 {
1168 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1169 _("Service `%s' runs at %s\n"),
1170 sctx->serviceName,
1171 GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1172 i++;
1173 }
1129 sctx->task (sctx->task_cls, tc->sched, sctx->server, sctx->cfg); 1174 sctx->task (sctx->task_cls, tc->sched, sctx->server, sctx->cfg);
1130} 1175}
1131 1176
@@ -1295,6 +1340,7 @@ GNUNET_SERVICE_run (int argc,
1295 char *loglev; 1340 char *loglev;
1296 char *logfile; 1341 char *logfile;
1297 int do_daemonize; 1342 int do_daemonize;
1343 unsigned int i;
1298 struct GNUNET_SERVICE_Context sctx; 1344 struct GNUNET_SERVICE_Context sctx;
1299 struct GNUNET_CONFIGURATION_Handle *cfg; 1345 struct GNUNET_CONFIGURATION_Handle *cfg;
1300 struct GNUNET_GETOPT_CommandLineOption service_options[] = { 1346 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
@@ -1358,7 +1404,11 @@ shutdown:
1358 } 1404 }
1359 1405
1360 GNUNET_CONFIGURATION_destroy (cfg); 1406 GNUNET_CONFIGURATION_destroy (cfg);
1361 GNUNET_free_non_null (sctx.addr); 1407 i = 0;
1408 while (sctx.addrs[i] != NULL)
1409 GNUNET_free (sctx.addrs[i++]);
1410 GNUNET_free_non_null (sctx.addrs);
1411 GNUNET_free_non_null (sctx.addrlens);
1362 GNUNET_free_non_null (logfile); 1412 GNUNET_free_non_null (logfile);
1363 GNUNET_free (loglev); 1413 GNUNET_free (loglev);
1364 GNUNET_free (cfg_fn); 1414 GNUNET_free (cfg_fn);
@@ -1402,8 +1452,8 @@ GNUNET_SERVICE_start (const char *serviceName,
1402 (NULL == (sctx->server = GNUNET_SERVER_create (sched, 1452 (NULL == (sctx->server = GNUNET_SERVER_create (sched,
1403 &check_access, 1453 &check_access,
1404 sctx, 1454 sctx,
1405 sctx->addr, 1455 sctx->addrs,
1406 sctx->addrlen, 1456 sctx->addrlens,
1407 sctx->maxbuf, 1457 sctx->maxbuf,
1408 sctx->timeout, 1458 sctx->timeout,
1409 sctx->require_found)))) 1459 sctx->require_found))))
@@ -1442,10 +1492,15 @@ GNUNET_SERVICE_get_server (struct GNUNET_SERVICE_Context *ctx)
1442void 1492void
1443GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx) 1493GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx)
1444{ 1494{
1495 unsigned int i;
1445 if (NULL != sctx->server) 1496 if (NULL != sctx->server)
1446 GNUNET_SERVER_destroy (sctx->server); 1497 GNUNET_SERVER_destroy (sctx->server);
1447 GNUNET_free_non_null (sctx->my_handlers); 1498 GNUNET_free_non_null (sctx->my_handlers);
1448 GNUNET_free_non_null (sctx->addr); 1499 i = 0;
1500 while (sctx->addrs[i] != NULL)
1501 GNUNET_free (sctx->addrs[i++]);
1502 GNUNET_free_non_null (sctx->addrs);
1503 GNUNET_free_non_null (sctx->addrlens);
1449 GNUNET_free_non_null (sctx->v4_denied); 1504 GNUNET_free_non_null (sctx->v4_denied);
1450 GNUNET_free_non_null (sctx->v6_denied); 1505 GNUNET_free_non_null (sctx->v6_denied);
1451 GNUNET_free_non_null (sctx->v4_allowed); 1506 GNUNET_free_non_null (sctx->v4_allowed);
diff --git a/src/util/test_client.c b/src/util/test_client.c
index 4811e8776..aa8b93a82 100644
--- a/src/util/test_client.c
+++ b/src/util/test_client.c
@@ -137,7 +137,13 @@ static void
137task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 137task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
138{ 138{
139 struct sockaddr_in sa; 139 struct sockaddr_in sa;
140 struct sockaddr * sap[2];
141 socklen_t slens[2];
140 142
143 sap[0] = (struct sockaddr*) &sa;
144 slens[0] = sizeof (sa);
145 sap[1] = NULL;
146 slens[1] = 0;
141 memset (&sa, 0, sizeof (sa)); 147 memset (&sa, 0, sizeof (sa));
142#if HAVE_SOCKADDR_IN_SIN_LEN 148#if HAVE_SOCKADDR_IN_SIN_LEN
143 sa.sin_len = sizeof (sa); 149 sa.sin_len = sizeof (sa);
@@ -147,8 +153,8 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
147 server = GNUNET_SERVER_create (tc->sched, 153 server = GNUNET_SERVER_create (tc->sched,
148 NULL, 154 NULL,
149 NULL, 155 NULL,
150 (const struct sockaddr *) &sa, 156 sap,
151 sizeof (sa), 157 slens,
152 1024, 158 1024,
153 GNUNET_TIME_relative_multiply 159 GNUNET_TIME_relative_multiply
154 (GNUNET_TIME_UNIT_MILLISECONDS, 10000), 160 (GNUNET_TIME_UNIT_MILLISECONDS, 10000),
diff --git a/src/util/test_server.c b/src/util/test_server.c
index 95206c0f1..901b78a08 100644
--- a/src/util/test_server.c
+++ b/src/util/test_server.c
@@ -232,7 +232,13 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
232{ 232{
233 struct sockaddr_in sa; 233 struct sockaddr_in sa;
234 struct GNUNET_MessageHeader msg; 234 struct GNUNET_MessageHeader msg;
235 struct sockaddr * sap[2];
236 socklen_t slens[2];
235 237
238 sap[0] = (struct sockaddr*) &sa;
239 slens[0] = sizeof (sa);
240 sap[1] = NULL;
241 slens[1] = 0;
236 sched = tc->sched; 242 sched = tc->sched;
237 memset (&sa, 0, sizeof (sa)); 243 memset (&sa, 0, sizeof (sa));
238#if HAVE_SOCKADDR_IN_SIN_LEN 244#if HAVE_SOCKADDR_IN_SIN_LEN
@@ -243,8 +249,8 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
243 server = GNUNET_SERVER_create (tc->sched, 249 server = GNUNET_SERVER_create (tc->sched,
244 NULL, 250 NULL,
245 NULL, 251 NULL,
246 (const struct sockaddr *) &sa, 252 sap,
247 sizeof (sa), 253 slens,
248 1024, 254 1024,
249 GNUNET_TIME_relative_multiply 255 GNUNET_TIME_relative_multiply
250 (GNUNET_TIME_UNIT_MILLISECONDS, 250), 256 (GNUNET_TIME_UNIT_MILLISECONDS, 250),
diff --git a/src/util/test_server_disconnect.c b/src/util/test_server_disconnect.c
index 7b35647ea..76a73d348 100644
--- a/src/util/test_server_disconnect.c
+++ b/src/util/test_server_disconnect.c
@@ -174,7 +174,13 @@ static void
174task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 174task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
175{ 175{
176 struct sockaddr_in sa; 176 struct sockaddr_in sa;
177 struct sockaddr * sap[2];
178 socklen_t slens[2];
177 179
180 sap[0] = (struct sockaddr*) &sa;
181 slens[0] = sizeof (sa);
182 sap[1] = NULL;
183 slens[1] = 0;
178 sched = tc->sched; 184 sched = tc->sched;
179 memset (&sa, 0, sizeof (sa)); 185 memset (&sa, 0, sizeof (sa));
180#if HAVE_SOCKADDR_IN_SIN_LEN 186#if HAVE_SOCKADDR_IN_SIN_LEN
@@ -185,8 +191,8 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
185 server = GNUNET_SERVER_create (tc->sched, 191 server = GNUNET_SERVER_create (tc->sched,
186 NULL, 192 NULL,
187 NULL, 193 NULL,
188 (const struct sockaddr *) &sa, 194 sap,
189 sizeof (sa), 195 slens,
190 1024, 196 1024,
191 GNUNET_TIME_relative_multiply 197 GNUNET_TIME_relative_multiply
192 (GNUNET_TIME_UNIT_MILLISECONDS, 250), 198 (GNUNET_TIME_UNIT_MILLISECONDS, 250),
diff --git a/src/util/test_server_with_client.c b/src/util/test_server_with_client.c
index f22c15300..68b842ef8 100644
--- a/src/util/test_server_with_client.c
+++ b/src/util/test_server_with_client.c
@@ -158,7 +158,13 @@ static void
158task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 158task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
159{ 159{
160 struct sockaddr_in sa; 160 struct sockaddr_in sa;
161 struct sockaddr * sap[2];
162 socklen_t slens[2];
161 163
164 sap[0] = (struct sockaddr*) &sa;
165 slens[0] = sizeof (sa);
166 sap[1] = NULL;
167 slens[1] = 0;
162 sched = tc->sched; 168 sched = tc->sched;
163 memset (&sa, 0, sizeof (sa)); 169 memset (&sa, 0, sizeof (sa));
164#if HAVE_SOCKADDR_IN_SIN_LEN 170#if HAVE_SOCKADDR_IN_SIN_LEN
@@ -169,8 +175,8 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
169 server = GNUNET_SERVER_create (tc->sched, 175 server = GNUNET_SERVER_create (tc->sched,
170 NULL, 176 NULL,
171 NULL, 177 NULL,
172 (const struct sockaddr *) &sa, 178 sap,
173 sizeof (sa), 179 slens,
174 1024, 180 1024,
175 GNUNET_TIME_relative_multiply 181 GNUNET_TIME_relative_multiply
176 (GNUNET_TIME_UNIT_MILLISECONDS, 250), 182 (GNUNET_TIME_UNIT_MILLISECONDS, 250),
diff --git a/src/util/test_service.c b/src/util/test_service.c
index dce66d398..a40630c64 100644
--- a/src/util/test_service.c
+++ b/src/util/test_service.c
@@ -76,15 +76,16 @@ build_msg (void *cls, size_t size, void *buf)
76 return sizeof (struct GNUNET_MessageHeader); 76 return sizeof (struct GNUNET_MessageHeader);
77} 77}
78 78
79
79static void 80static void
80ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 81ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
81{ 82{
82 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 83 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
83 struct GNUNET_CLIENT_Connection *client; 84 struct GNUNET_CLIENT_Connection *client;
84 85
86 GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE));
85 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service confirmed running\n"); 87 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service confirmed running\n");
86 sched = tc->sched; 88 sched = tc->sched;
87 GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE));
88 client = GNUNET_CLIENT_connect (tc->sched, "test_service", cfg); 89 client = GNUNET_CLIENT_connect (tc->sched, "test_service", cfg);
89 GNUNET_assert (client != NULL); 90 GNUNET_assert (client != NULL);
90 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 91 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,