diff options
Diffstat (limited to 'src/lib/util/service.c')
-rw-r--r-- | src/lib/util/service.c | 596 |
1 files changed, 280 insertions, 316 deletions
diff --git a/src/lib/util/service.c b/src/lib/util/service.c index 7aeabf687..363210c61 100644 --- a/src/lib/util/service.c +++ b/src/lib/util/service.c | |||
@@ -24,7 +24,6 @@ | |||
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * @author Florian Dold | 25 | * @author Florian Dold |
26 | */ | 26 | */ |
27 | |||
28 | #include "platform.h" | 27 | #include "platform.h" |
29 | #include "gnunet_util_lib.h" | 28 | #include "gnunet_util_lib.h" |
30 | #include "gnunet_protocols.h" | 29 | #include "gnunet_protocols.h" |
@@ -233,15 +232,10 @@ struct GNUNET_SERVICE_Handle | |||
233 | int ready_confirm_fd; | 232 | int ready_confirm_fd; |
234 | 233 | ||
235 | /** | 234 | /** |
236 | * Overall success/failure of the service start. | 235 | * If true, consider unknown message types an error where the |
237 | */ | ||
238 | int ret; | ||
239 | |||
240 | /** | ||
241 | * If #GNUNET_YES, consider unknown message types an error where the | ||
242 | * client is disconnected. | 236 | * client is disconnected. |
243 | */ | 237 | */ |
244 | int require_found; | 238 | bool require_found; |
245 | }; | 239 | }; |
246 | 240 | ||
247 | 241 | ||
@@ -330,19 +324,19 @@ struct GNUNET_SERVICE_Client | |||
330 | * force the OS to close once the process actually dies. Should only | 324 | * force the OS to close once the process actually dies. Should only |
331 | * be used in special cases! | 325 | * be used in special cases! |
332 | */ | 326 | */ |
333 | int persist; | 327 | bool persist; |
334 | 328 | ||
335 | /** | 329 | /** |
336 | * Is this client a 'monitor' client that should not be counted | 330 | * Is this client a 'monitor' client that should not be counted |
337 | * when deciding on destroying the server during soft shutdown? | 331 | * when deciding on destroying the server during soft shutdown? |
338 | * (see also #GNUNET_SERVICE_start) | 332 | * (see also #GNUNET_SERVICE_start) |
339 | */ | 333 | */ |
340 | int is_monitor; | 334 | bool is_monitor; |
341 | 335 | ||
342 | /** | 336 | /** |
343 | * Are we waiting for the application to call #GNUNET_SERVICE_client_continue()? | 337 | * Are we waiting for the application to call #GNUNET_SERVICE_client_continue()? |
344 | */ | 338 | */ |
345 | int needs_continue; | 339 | bool needs_continue; |
346 | 340 | ||
347 | /** | 341 | /** |
348 | * Type of last message processed (for warn_no_receive_done). | 342 | * Type of last message processed (for warn_no_receive_done). |
@@ -356,19 +350,22 @@ struct GNUNET_SERVICE_Client | |||
356 | * monitoring. | 350 | * monitoring. |
357 | * | 351 | * |
358 | * @param sh service to check clients for | 352 | * @param sh service to check clients for |
359 | * @return #GNUNET_YES if we have non-monitoring clients left | 353 | * @return true if we have non-monitoring clients left |
360 | */ | 354 | */ |
361 | static int | 355 | static enum GNUNET_GenericReturnValue |
362 | have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh) | 356 | have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh) |
363 | { | 357 | { |
364 | for (struct GNUNET_SERVICE_Client *client = sh->clients_head; NULL != client; | 358 | for (struct GNUNET_SERVICE_Client *client = sh->clients_head; |
359 | NULL != client; | ||
365 | client = client->next) | 360 | client = client->next) |
366 | { | 361 | { |
362 | if (NULL != client->drop_task) | ||
363 | continue; | ||
367 | if (client->is_monitor) | 364 | if (client->is_monitor) |
368 | continue; | 365 | continue; |
369 | return GNUNET_YES; | 366 | return true; |
370 | } | 367 | } |
371 | return GNUNET_NO; | 368 | return false; |
372 | } | 369 | } |
373 | 370 | ||
374 | 371 | ||
@@ -380,13 +377,14 @@ have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh) | |||
380 | * @param sr reason for suspending accepting connections | 377 | * @param sr reason for suspending accepting connections |
381 | */ | 378 | */ |
382 | static void | 379 | static void |
383 | do_suspend (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr) | 380 | do_suspend (struct GNUNET_SERVICE_Handle *sh, |
381 | enum SuspendReason sr) | ||
384 | { | 382 | { |
385 | struct ServiceListenContext *slc; | ||
386 | |||
387 | GNUNET_assert (0 == (sh->suspend_state & sr)); | 383 | GNUNET_assert (0 == (sh->suspend_state & sr)); |
388 | sh->suspend_state |= sr; | 384 | sh->suspend_state |= sr; |
389 | for (slc = sh->slc_head; NULL != slc; slc = slc->next) | 385 | for (struct ServiceListenContext *slc = sh->slc_head; |
386 | NULL != slc; | ||
387 | slc = slc->next) | ||
390 | { | 388 | { |
391 | if (NULL != slc->listen_task) | 389 | if (NULL != slc->listen_task) |
392 | { | 390 | { |
@@ -423,7 +421,7 @@ service_shutdown (void *cls) | |||
423 | case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN: | 421 | case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN: |
424 | if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN)) | 422 | if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN)) |
425 | do_suspend (sh, SUSPEND_STATE_SHUTDOWN); | 423 | do_suspend (sh, SUSPEND_STATE_SHUTDOWN); |
426 | if (GNUNET_NO == have_non_monitor_clients (sh)) | 424 | if (! have_non_monitor_clients (sh)) |
427 | GNUNET_SERVICE_shutdown (sh); | 425 | GNUNET_SERVICE_shutdown (sh); |
428 | break; | 426 | break; |
429 | } | 427 | } |
@@ -435,25 +433,21 @@ service_shutdown (void *cls) | |||
435 | * | 433 | * |
436 | * @param list a list of networks | 434 | * @param list a list of networks |
437 | * @param add the IP to check (in network byte order) | 435 | * @param add the IP to check (in network byte order) |
438 | * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is | 436 | * @return false if the IP is not in the list, true if it it is |
439 | */ | 437 | */ |
440 | static int | 438 | static bool |
441 | check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, | 439 | check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, |
442 | const struct in_addr *add) | 440 | const struct in_addr *add) |
443 | { | 441 | { |
444 | unsigned int i; | 442 | for (unsigned int i = 0; |
445 | 443 | 0 != list[i].network.s_addr; | |
446 | if (NULL == list) | 444 | i++) |
447 | return GNUNET_NO; | ||
448 | i = 0; | ||
449 | while ((0 != list[i].network.s_addr) || (0 != list[i].netmask.s_addr)) | ||
450 | { | 445 | { |
451 | if ((add->s_addr & list[i].netmask.s_addr) == | 446 | if ( (add->s_addr & list[i].netmask.s_addr) == |
452 | (list[i].network.s_addr & list[i].netmask.s_addr)) | 447 | (list[i].network.s_addr & list[i].netmask.s_addr) ) |
453 | return GNUNET_YES; | 448 | return true; |
454 | i++; | ||
455 | } | 449 | } |
456 | return GNUNET_NO; | 450 | return false; |
457 | } | 451 | } |
458 | 452 | ||
459 | 453 | ||
@@ -462,30 +456,29 @@ check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, | |||
462 | * | 456 | * |
463 | * @param list a list of networks | 457 | * @param list a list of networks |
464 | * @param ip the IP to check (in network byte order) | 458 | * @param ip the IP to check (in network byte order) |
465 | * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is | 459 | * @return false if the IP is not in the list, true if it it is |
466 | */ | 460 | */ |
467 | static int | 461 | static bool |
468 | check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, | 462 | check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, |
469 | const struct in6_addr *ip) | 463 | const struct in6_addr *ip) |
470 | { | 464 | { |
471 | unsigned int i; | 465 | for (unsigned int i = 0; |
472 | 466 | ! GNUNET_is_zero (&list[i].network); | |
473 | if (NULL == list) | 467 | i++) |
474 | return GNUNET_NO; | ||
475 | i = 0; | ||
476 | NEXT: | ||
477 | while (GNUNET_NO == GNUNET_is_zero (&list[i].network)) | ||
478 | { | 468 | { |
469 | bool match = true; | ||
470 | |||
479 | for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++) | 471 | for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++) |
480 | if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) != | 472 | if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) != |
481 | (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j])) | 473 | (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j])) |
482 | { | 474 | { |
483 | i++; | 475 | match = false; |
484 | goto NEXT; | 476 | break; |
485 | } | 477 | } |
486 | return GNUNET_YES; | 478 | if (match) |
479 | return true; | ||
487 | } | 480 | } |
488 | return GNUNET_NO; | 481 | return false; |
489 | } | 482 | } |
490 | 483 | ||
491 | 484 | ||
@@ -593,7 +586,8 @@ service_mq_send (struct GNUNET_MQ_Handle *mq, | |||
593 | * @param impl_state state specific to the implementation | 586 | * @param impl_state state specific to the implementation |
594 | */ | 587 | */ |
595 | static void | 588 | static void |
596 | service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state) | 589 | service_mq_cancel (struct GNUNET_MQ_Handle *mq, |
590 | void *impl_state) | ||
597 | { | 591 | { |
598 | struct GNUNET_SERVICE_Client *client = impl_state; | 592 | struct GNUNET_SERVICE_Client *client = impl_state; |
599 | 593 | ||
@@ -615,12 +609,14 @@ service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state) | |||
615 | * @param error error code | 609 | * @param error error code |
616 | */ | 610 | */ |
617 | static void | 611 | static void |
618 | service_mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | 612 | service_mq_error_handler (void *cls, |
613 | enum GNUNET_MQ_Error error) | ||
619 | { | 614 | { |
620 | struct GNUNET_SERVICE_Client *client = cls; | 615 | struct GNUNET_SERVICE_Client *client = cls; |
621 | struct GNUNET_SERVICE_Handle *sh = client->sh; | 616 | struct GNUNET_SERVICE_Handle *sh = client->sh; |
622 | 617 | ||
623 | if ((GNUNET_MQ_ERROR_NO_MATCH == error) && (GNUNET_NO == sh->require_found)) | 618 | if ( (GNUNET_MQ_ERROR_NO_MATCH == error) && |
619 | (! sh->require_found) ) | ||
624 | { | 620 | { |
625 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 621 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
626 | "No handler for message of type %u found\n", | 622 | "No handler for message of type %u found\n", |
@@ -680,8 +676,8 @@ service_client_mst_cb (void *cls, | |||
680 | "Received message of type %u and size %u from client\n", | 676 | "Received message of type %u and size %u from client\n", |
681 | ntohs (message->type), | 677 | ntohs (message->type), |
682 | ntohs (message->size)); | 678 | ntohs (message->size)); |
683 | GNUNET_assert (GNUNET_NO == client->needs_continue); | 679 | GNUNET_assert (! client->needs_continue); |
684 | client->needs_continue = GNUNET_YES; | 680 | client->needs_continue = true; |
685 | client->warn_type = ntohs (message->type); | 681 | client->warn_type = ntohs (message->type); |
686 | client->warn_start = GNUNET_TIME_absolute_get (); | 682 | client->warn_start = GNUNET_TIME_absolute_get (); |
687 | GNUNET_assert (NULL == client->warn_task); | 683 | GNUNET_assert (NULL == client->warn_task); |
@@ -717,7 +713,7 @@ service_client_recv (void *cls) | |||
717 | /* client closed connection (or IO error) */ | 713 | /* client closed connection (or IO error) */ |
718 | if (NULL == client->drop_task) | 714 | if (NULL == client->drop_task) |
719 | { | 715 | { |
720 | GNUNET_assert (GNUNET_NO == client->needs_continue); | 716 | GNUNET_assert (! client->needs_continue); |
721 | GNUNET_SERVICE_client_drop (client); | 717 | GNUNET_SERVICE_client_drop (client); |
722 | } | 718 | } |
723 | return; | 719 | return; |
@@ -726,7 +722,7 @@ service_client_recv (void *cls) | |||
726 | return; /* more messages in buffer, wait for application | 722 | return; /* more messages in buffer, wait for application |
727 | to be done processing */ | 723 | to be done processing */ |
728 | GNUNET_assert (GNUNET_OK == ret); | 724 | GNUNET_assert (GNUNET_OK == ret); |
729 | if (GNUNET_YES == client->needs_continue) | 725 | if (client->needs_continue) |
730 | return; | 726 | return; |
731 | if (NULL != client->recv_task) | 727 | if (NULL != client->recv_task) |
732 | return; | 728 | return; |
@@ -753,7 +749,9 @@ start_client (struct GNUNET_SERVICE_Handle *sh, | |||
753 | struct GNUNET_SERVICE_Client *client; | 749 | struct GNUNET_SERVICE_Client *client; |
754 | 750 | ||
755 | client = GNUNET_new (struct GNUNET_SERVICE_Client); | 751 | client = GNUNET_new (struct GNUNET_SERVICE_Client); |
756 | GNUNET_CONTAINER_DLL_insert (sh->clients_head, sh->clients_tail, client); | 752 | GNUNET_CONTAINER_DLL_insert (sh->clients_head, |
753 | sh->clients_tail, | ||
754 | client); | ||
757 | client->sh = sh; | 755 | client->sh = sh; |
758 | client->sock = csock; | 756 | client->sock = csock; |
759 | client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send, | 757 | client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send, |
@@ -806,7 +804,8 @@ accept_client (void *cls) | |||
806 | if (EMFILE == errno) | 804 | if (EMFILE == errno) |
807 | do_suspend (sh, SUSPEND_STATE_EMFILE); | 805 | do_suspend (sh, SUSPEND_STATE_EMFILE); |
808 | else if (EAGAIN != errno) | 806 | else if (EAGAIN != errno) |
809 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept"); | 807 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, |
808 | "accept"); | ||
810 | break; | 809 | break; |
811 | } | 810 | } |
812 | switch (sa.ss_family) | 811 | switch (sa.ss_family) |
@@ -815,18 +814,22 @@ accept_client (void *cls) | |||
815 | GNUNET_assert (addrlen == sizeof(struct sockaddr_in)); | 814 | GNUNET_assert (addrlen == sizeof(struct sockaddr_in)); |
816 | v4 = (const struct sockaddr_in *) &sa; | 815 | v4 = (const struct sockaddr_in *) &sa; |
817 | ok = (((NULL == sh->v4_allowed) || | 816 | ok = (((NULL == sh->v4_allowed) || |
818 | (check_ipv4_listed (sh->v4_allowed, &v4->sin_addr))) && | 817 | (check_ipv4_listed (sh->v4_allowed, |
818 | &v4->sin_addr))) && | ||
819 | ((NULL == sh->v4_denied) || | 819 | ((NULL == sh->v4_denied) || |
820 | (! check_ipv4_listed (sh->v4_denied, &v4->sin_addr)))); | 820 | (! check_ipv4_listed (sh->v4_denied, |
821 | &v4->sin_addr)))); | ||
821 | break; | 822 | break; |
822 | 823 | ||
823 | case AF_INET6: | 824 | case AF_INET6: |
824 | GNUNET_assert (addrlen == sizeof(struct sockaddr_in6)); | 825 | GNUNET_assert (addrlen == sizeof(struct sockaddr_in6)); |
825 | v6 = (const struct sockaddr_in6 *) &sa; | 826 | v6 = (const struct sockaddr_in6 *) &sa; |
826 | ok = (((NULL == sh->v6_allowed) || | 827 | ok = (((NULL == sh->v6_allowed) || |
827 | (check_ipv6_listed (sh->v6_allowed, &v6->sin6_addr))) && | 828 | (check_ipv6_listed (sh->v6_allowed, |
829 | &v6->sin6_addr))) && | ||
828 | ((NULL == sh->v6_denied) || | 830 | ((NULL == sh->v6_denied) || |
829 | (! check_ipv6_listed (sh->v6_denied, &v6->sin6_addr)))); | 831 | (! check_ipv6_listed (sh->v6_denied, |
832 | &v6->sin6_addr)))); | ||
830 | break; | 833 | break; |
831 | 834 | ||
832 | case AF_UNIX: | 835 | case AF_UNIX: |
@@ -850,7 +853,8 @@ accept_client (void *cls) | |||
850 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 853 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
851 | "Service accepted incoming connection from %s.\n", | 854 | "Service accepted incoming connection from %s.\n", |
852 | GNUNET_a2s ((const struct sockaddr *) &sa, addrlen)); | 855 | GNUNET_a2s ((const struct sockaddr *) &sa, addrlen)); |
853 | start_client (slc->sh, sock); | 856 | start_client (slc->sh, |
857 | sock); | ||
854 | } | 858 | } |
855 | if (0 != sh->suspend_state) | 859 | if (0 != sh->suspend_state) |
856 | return; | 860 | return; |
@@ -870,15 +874,16 @@ accept_client (void *cls) | |||
870 | * or #SUSPEND_STATE_NONE on first startup | 874 | * or #SUSPEND_STATE_NONE on first startup |
871 | */ | 875 | */ |
872 | static void | 876 | static void |
873 | do_resume (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr) | 877 | do_resume (struct GNUNET_SERVICE_Handle *sh, |
878 | enum SuspendReason sr) | ||
874 | { | 879 | { |
875 | struct ServiceListenContext *slc; | ||
876 | |||
877 | GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr))); | 880 | GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr))); |
878 | sh->suspend_state -= sr; | 881 | sh->suspend_state -= sr; |
879 | if (SUSPEND_STATE_NONE != sh->suspend_state) | 882 | if (SUSPEND_STATE_NONE != sh->suspend_state) |
880 | return; | 883 | return; |
881 | for (slc = sh->slc_head; NULL != slc; slc = slc->next) | 884 | for (struct ServiceListenContext *slc = sh->slc_head; |
885 | NULL != slc; | ||
886 | slc = slc->next) | ||
882 | { | 887 | { |
883 | GNUNET_assert (NULL == slc->listen_task); | 888 | GNUNET_assert (NULL == slc->listen_task); |
884 | slc->listen_task = | 889 | slc->listen_task = |
@@ -928,7 +933,7 @@ service_main (void *cls) | |||
928 | * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including | 933 | * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including |
929 | * no ACL configured) | 934 | * no ACL configured) |
930 | */ | 935 | */ |
931 | static int | 936 | static enum GNUNET_GenericReturnValue |
932 | process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, | 937 | process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, |
933 | struct GNUNET_SERVICE_Handle *sh, | 938 | struct GNUNET_SERVICE_Handle *sh, |
934 | const char *option) | 939 | const char *option) |
@@ -969,7 +974,7 @@ process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, | |||
969 | * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including | 974 | * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including |
970 | * no ACL configured) | 975 | * no ACL configured) |
971 | */ | 976 | */ |
972 | static int | 977 | static enum GNUNET_GenericReturnValue |
973 | process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, | 978 | process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, |
974 | struct GNUNET_SERVICE_Handle *sh, | 979 | struct GNUNET_SERVICE_Handle *sh, |
975 | const char *option) | 980 | const char *option) |
@@ -1457,7 +1462,7 @@ open_listen_socket (const struct sockaddr *server_addr, | |||
1457 | * @param sh service context to initialize | 1462 | * @param sh service context to initialize |
1458 | * @return #GNUNET_OK if configuration succeeded | 1463 | * @return #GNUNET_OK if configuration succeeded |
1459 | */ | 1464 | */ |
1460 | static int | 1465 | static enum GNUNET_GenericReturnValue |
1461 | setup_service (struct GNUNET_SERVICE_Handle *sh) | 1466 | setup_service (struct GNUNET_SERVICE_Handle *sh) |
1462 | { | 1467 | { |
1463 | int tolerant; | 1468 | int tolerant; |
@@ -1489,8 +1494,8 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1489 | 1494 | ||
1490 | lsocks = NULL; | 1495 | lsocks = NULL; |
1491 | errno = 0; | 1496 | errno = 0; |
1492 | if ((NULL != (nfds = getenv ("LISTEN_FDS"))) && | 1497 | if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) && |
1493 | (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) && | 1498 | (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) && |
1494 | (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE)) | 1499 | (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE)) |
1495 | { | 1500 | { |
1496 | lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *); | 1501 | lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *); |
@@ -1532,7 +1537,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1532 | slc = GNUNET_new (struct ServiceListenContext); | 1537 | slc = GNUNET_new (struct ServiceListenContext); |
1533 | slc->sh = sh; | 1538 | slc->sh = sh; |
1534 | slc->listen_socket = *ls; | 1539 | slc->listen_socket = *ls; |
1535 | GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc); | 1540 | GNUNET_CONTAINER_DLL_insert (sh->slc_head, |
1541 | sh->slc_tail, | ||
1542 | slc); | ||
1536 | } | 1543 | } |
1537 | GNUNET_free (lsocks); | 1544 | GNUNET_free (lsocks); |
1538 | } | 1545 | } |
@@ -1552,7 +1559,8 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1552 | 1559 | ||
1553 | slc = GNUNET_new (struct ServiceListenContext); | 1560 | slc = GNUNET_new (struct ServiceListenContext); |
1554 | slc->sh = sh; | 1561 | slc->sh = sh; |
1555 | slc->listen_socket = open_listen_socket (addrs[i], addrlens[i]); | 1562 | slc->listen_socket = open_listen_socket (addrs[i], |
1563 | addrlens[i]); | ||
1556 | GNUNET_free (addrs[i]); | 1564 | GNUNET_free (addrs[i]); |
1557 | if (NULL == slc->listen_socket) | 1565 | if (NULL == slc->listen_socket) |
1558 | { | 1566 | { |
@@ -1560,7 +1568,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1560 | GNUNET_free (slc); | 1568 | GNUNET_free (slc); |
1561 | continue; | 1569 | continue; |
1562 | } | 1570 | } |
1563 | GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc); | 1571 | GNUNET_CONTAINER_DLL_insert (sh->slc_head, |
1572 | sh->slc_tail, | ||
1573 | slc); | ||
1564 | } | 1574 | } |
1565 | GNUNET_free (addrlens); | 1575 | GNUNET_free (addrlens); |
1566 | GNUNET_free (addrs); | 1576 | GNUNET_free (addrs); |
@@ -1582,7 +1592,7 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1582 | GNUNET_NETWORK_socket_close (*ls); | 1592 | GNUNET_NETWORK_socket_close (*ls); |
1583 | GNUNET_free (csocks); | 1593 | GNUNET_free (csocks); |
1584 | } | 1594 | } |
1585 | sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES; | 1595 | sh->require_found = (GNUNET_NO == tolerant); |
1586 | sh->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, | 1596 | sh->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, |
1587 | sh->service_name, | 1597 | sh->service_name, |
1588 | "UNIX_MATCH_UID"); | 1598 | "UNIX_MATCH_UID"); |
@@ -1609,10 +1619,11 @@ get_user_name (struct GNUNET_SERVICE_Handle *sh) | |||
1609 | { | 1619 | { |
1610 | char *un; | 1620 | char *un; |
1611 | 1621 | ||
1612 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sh->cfg, | 1622 | if (GNUNET_OK != |
1613 | sh->service_name, | 1623 | GNUNET_CONFIGURATION_get_value_filename (sh->cfg, |
1614 | "USERNAME", | 1624 | sh->service_name, |
1615 | &un)) | 1625 | "USERNAME", |
1626 | &un)) | ||
1616 | return NULL; | 1627 | return NULL; |
1617 | return un; | 1628 | return un; |
1618 | } | 1629 | } |
@@ -1624,16 +1635,14 @@ get_user_name (struct GNUNET_SERVICE_Handle *sh) | |||
1624 | * @param sh service context | 1635 | * @param sh service context |
1625 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | 1636 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error |
1626 | */ | 1637 | */ |
1627 | static int | 1638 | static enum GNUNET_GenericReturnValue |
1628 | set_user_id (struct GNUNET_SERVICE_Handle *sh) | 1639 | set_user_id (struct GNUNET_SERVICE_Handle *sh) |
1629 | { | 1640 | { |
1630 | char *user; | 1641 | char *user; |
1642 | struct passwd *pws; | ||
1631 | 1643 | ||
1632 | if (NULL == (user = get_user_name (sh))) | 1644 | if (NULL == (user = get_user_name (sh))) |
1633 | return GNUNET_OK; /* keep */ | 1645 | return GNUNET_OK; /* keep */ |
1634 | |||
1635 | struct passwd *pws; | ||
1636 | |||
1637 | errno = 0; | 1646 | errno = 0; |
1638 | pws = getpwnam (user); | 1647 | pws = getpwnam (user); |
1639 | if (NULL == pws) | 1648 | if (NULL == pws) |
@@ -1649,7 +1658,8 @@ set_user_id (struct GNUNET_SERVICE_Handle *sh) | |||
1649 | #if HAVE_INITGROUPS | 1658 | #if HAVE_INITGROUPS |
1650 | (0 != initgroups (user, pws->pw_gid)) || | 1659 | (0 != initgroups (user, pws->pw_gid)) || |
1651 | #endif | 1660 | #endif |
1652 | (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid))) | 1661 | (0 != setuid (pws->pw_uid)) || |
1662 | (0 != seteuid (pws->pw_uid))) | ||
1653 | { | 1663 | { |
1654 | if ((0 != setregid (pws->pw_gid, pws->pw_gid)) || | 1664 | if ((0 != setregid (pws->pw_gid, pws->pw_gid)) || |
1655 | (0 != setreuid (pws->pw_uid, pws->pw_uid))) | 1665 | (0 != setreuid (pws->pw_uid, pws->pw_uid))) |
@@ -1680,10 +1690,11 @@ get_pid_file_name (struct GNUNET_SERVICE_Handle *sh) | |||
1680 | { | 1690 | { |
1681 | char *pif; | 1691 | char *pif; |
1682 | 1692 | ||
1683 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sh->cfg, | 1693 | if (GNUNET_OK != |
1684 | sh->service_name, | 1694 | GNUNET_CONFIGURATION_get_value_filename (sh->cfg, |
1685 | "PIDFILE", | 1695 | sh->service_name, |
1686 | &pif)) | 1696 | "PIDFILE", |
1697 | &pif)) | ||
1687 | return NULL; | 1698 | return NULL; |
1688 | return pif; | 1699 | return pif; |
1689 | } | 1700 | } |
@@ -1702,7 +1713,9 @@ pid_file_delete (struct GNUNET_SERVICE_Handle *sh) | |||
1702 | if (NULL == pif) | 1713 | if (NULL == pif) |
1703 | return; /* no PID file */ | 1714 | return; /* no PID file */ |
1704 | if (0 != unlink (pif)) | 1715 | if (0 != unlink (pif)) |
1705 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", pif); | 1716 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, |
1717 | "unlink", | ||
1718 | pif); | ||
1706 | GNUNET_free (pif); | 1719 | GNUNET_free (pif); |
1707 | } | 1720 | } |
1708 | 1721 | ||
@@ -1713,7 +1726,7 @@ pid_file_delete (struct GNUNET_SERVICE_Handle *sh) | |||
1713 | * @param sh service context | 1726 | * @param sh service context |
1714 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | 1727 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error |
1715 | */ | 1728 | */ |
1716 | static int | 1729 | static enum GNUNET_GenericReturnValue |
1717 | detach_terminal (struct GNUNET_SERVICE_Handle *sh) | 1730 | detach_terminal (struct GNUNET_SERVICE_Handle *sh) |
1718 | { | 1731 | { |
1719 | pid_t pid; | 1732 | pid_t pid; |
@@ -1722,13 +1735,15 @@ detach_terminal (struct GNUNET_SERVICE_Handle *sh) | |||
1722 | 1735 | ||
1723 | if (0 != pipe (filedes)) | 1736 | if (0 != pipe (filedes)) |
1724 | { | 1737 | { |
1725 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe"); | 1738 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, |
1739 | "pipe"); | ||
1726 | return GNUNET_SYSERR; | 1740 | return GNUNET_SYSERR; |
1727 | } | 1741 | } |
1728 | pid = fork (); | 1742 | pid = fork (); |
1729 | if (pid < 0) | 1743 | if (pid < 0) |
1730 | { | 1744 | { |
1731 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); | 1745 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, |
1746 | "fork"); | ||
1732 | return GNUNET_SYSERR; | 1747 | return GNUNET_SYSERR; |
1733 | } | 1748 | } |
1734 | if (0 != pid) | 1749 | if (0 != pid) |
@@ -1739,7 +1754,8 @@ detach_terminal (struct GNUNET_SERVICE_Handle *sh) | |||
1739 | GNUNET_break (0 == close (filedes[1])); | 1754 | GNUNET_break (0 == close (filedes[1])); |
1740 | c = 'X'; | 1755 | c = 'X'; |
1741 | if (1 != read (filedes[0], &c, sizeof(char))) | 1756 | if (1 != read (filedes[0], &c, sizeof(char))) |
1742 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "read"); | 1757 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, |
1758 | "read"); | ||
1743 | fflush (stdout); | 1759 | fflush (stdout); |
1744 | switch (c) | 1760 | switch (c) |
1745 | { | 1761 | { |
@@ -1780,7 +1796,8 @@ detach_terminal (struct GNUNET_SERVICE_Handle *sh) | |||
1780 | /* Detach from controlling terminal */ | 1796 | /* Detach from controlling terminal */ |
1781 | pid = setsid (); | 1797 | pid = setsid (); |
1782 | if (-1 == pid) | 1798 | if (-1 == pid) |
1783 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid"); | 1799 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, |
1800 | "setsid"); | ||
1784 | sh->ready_confirm_fd = filedes[1]; | 1801 | sh->ready_confirm_fd = filedes[1]; |
1785 | 1802 | ||
1786 | return GNUNET_OK; | 1803 | return GNUNET_OK; |
@@ -1804,7 +1821,9 @@ teardown_service (struct GNUNET_SERVICE_Handle *sh) | |||
1804 | GNUNET_free (sh->v6_allowed); | 1821 | GNUNET_free (sh->v6_allowed); |
1805 | while (NULL != (slc = sh->slc_head)) | 1822 | while (NULL != (slc = sh->slc_head)) |
1806 | { | 1823 | { |
1807 | GNUNET_CONTAINER_DLL_remove (sh->slc_head, sh->slc_tail, slc); | 1824 | GNUNET_CONTAINER_DLL_remove (sh->slc_head, |
1825 | sh->slc_tail, | ||
1826 | slc); | ||
1808 | if (NULL != slc->listen_task) | 1827 | if (NULL != slc->listen_task) |
1809 | GNUNET_SCHEDULER_cancel (slc->listen_task); | 1828 | GNUNET_SCHEDULER_cancel (slc->listen_task); |
1810 | GNUNET_break (GNUNET_OK == | 1829 | GNUNET_break (GNUNET_OK == |
@@ -1821,7 +1840,8 @@ teardown_service (struct GNUNET_SERVICE_Handle *sh) | |||
1821 | * @param msg AGPL request | 1840 | * @param msg AGPL request |
1822 | */ | 1841 | */ |
1823 | static void | 1842 | static void |
1824 | return_agpl (void *cls, const struct GNUNET_MessageHeader *msg) | 1843 | return_agpl (void *cls, |
1844 | const struct GNUNET_MessageHeader *msg) | ||
1825 | { | 1845 | { |
1826 | struct GNUNET_SERVICE_Client *client = cls; | 1846 | struct GNUNET_SERVICE_Client *client = cls; |
1827 | struct GNUNET_MQ_Handle *mq; | 1847 | struct GNUNET_MQ_Handle *mq; |
@@ -1832,50 +1852,17 @@ return_agpl (void *cls, const struct GNUNET_MessageHeader *msg) | |||
1832 | 1852 | ||
1833 | (void) msg; | 1853 | (void) msg; |
1834 | slen = strlen (pd->agpl_url) + 1; | 1854 | slen = strlen (pd->agpl_url) + 1; |
1835 | env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen); | 1855 | env = GNUNET_MQ_msg_extra (res, |
1836 | memcpy (&res[1], GNUNET_AGPL_URL, slen); | 1856 | GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen); |
1857 | memcpy (&res[1], | ||
1858 | GNUNET_AGPL_URL, | ||
1859 | slen); | ||
1837 | mq = GNUNET_SERVICE_client_get_mq (client); | 1860 | mq = GNUNET_SERVICE_client_get_mq (client); |
1838 | GNUNET_MQ_send (mq, env); | 1861 | GNUNET_MQ_send (mq, env); |
1839 | GNUNET_SERVICE_client_continue (client); | 1862 | GNUNET_SERVICE_client_continue (client); |
1840 | } | 1863 | } |
1841 | 1864 | ||
1842 | 1865 | ||
1843 | /** | ||
1844 | * Low-level function to start a service if the scheduler | ||
1845 | * is already running. Should only be used directly in | ||
1846 | * special cases. | ||
1847 | * | ||
1848 | * The function will launch the service with the name @a service_name | ||
1849 | * using the @a service_options to configure its shutdown | ||
1850 | * behavior. When clients connect or disconnect, the respective | ||
1851 | * @a connect_cb or @a disconnect_cb functions will be called. For | ||
1852 | * messages received from the clients, the respective @a handlers will | ||
1853 | * be invoked; for the closure of the handlers we use the return value | ||
1854 | * from the @a connect_cb invocation of the respective client. | ||
1855 | * | ||
1856 | * Each handler MUST call #GNUNET_SERVICE_client_continue() after each | ||
1857 | * message to receive further messages from this client. If | ||
1858 | * #GNUNET_SERVICE_client_continue() is not called within a short | ||
1859 | * time, a warning will be logged. If delays are expected, services | ||
1860 | * should call #GNUNET_SERVICE_client_disable_continue_warning() to | ||
1861 | * disable the warning. | ||
1862 | * | ||
1863 | * Clients sending invalid messages (based on @a handlers) will be | ||
1864 | * dropped. Additionally, clients can be dropped at any time using | ||
1865 | * #GNUNET_SERVICE_client_drop(). | ||
1866 | * | ||
1867 | * The service must be stopped using #GNUNET_SERVICE_stop(). | ||
1868 | * | ||
1869 | * @param service_name name of the service to run | ||
1870 | * @param cfg configuration to use | ||
1871 | * @param connect_cb function to call whenever a client connects | ||
1872 | * @param disconnect_cb function to call whenever a client disconnects | ||
1873 | * @param cls closure argument for @a connect_cb and @a disconnect_cb | ||
1874 | * @param handlers NULL-terminated array of message handlers for the service, | ||
1875 | * the closure will be set to the value returned by | ||
1876 | * the @a connect_cb for the respective connection | ||
1877 | * @return NULL on error | ||
1878 | */ | ||
1879 | struct GNUNET_SERVICE_Handle * | 1866 | struct GNUNET_SERVICE_Handle * |
1880 | GNUNET_SERVICE_start (const char *service_name, | 1867 | GNUNET_SERVICE_start (const char *service_name, |
1881 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 1868 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
@@ -1892,23 +1879,61 @@ GNUNET_SERVICE_start (const char *service_name, | |||
1892 | sh->connect_cb = connect_cb; | 1879 | sh->connect_cb = connect_cb; |
1893 | sh->disconnect_cb = disconnect_cb; | 1880 | sh->disconnect_cb = disconnect_cb; |
1894 | sh->cb_cls = cls; | 1881 | sh->cb_cls = cls; |
1895 | sh->handlers = GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL); | 1882 | sh->handlers = GNUNET_MQ_copy_handlers2 (handlers, |
1883 | &return_agpl, | ||
1884 | NULL); | ||
1896 | if (GNUNET_OK != setup_service (sh)) | 1885 | if (GNUNET_OK != setup_service (sh)) |
1897 | { | 1886 | { |
1898 | GNUNET_free (sh->handlers); | 1887 | GNUNET_free (sh->handlers); |
1899 | GNUNET_free (sh); | 1888 | GNUNET_free (sh); |
1900 | return NULL; | 1889 | return NULL; |
1901 | } | 1890 | } |
1902 | do_resume (sh, SUSPEND_STATE_NONE); | 1891 | do_resume (sh, |
1892 | SUSPEND_STATE_NONE); | ||
1903 | return sh; | 1893 | return sh; |
1904 | } | 1894 | } |
1905 | 1895 | ||
1906 | 1896 | ||
1907 | /** | 1897 | /** |
1908 | * Stops a service that was started with #GNUNET_SERVICE_start(). | 1898 | * Asynchronously finish dropping the client. |
1909 | * | 1899 | * |
1910 | * @param srv service to stop | 1900 | * @param cls the `struct GNUNET_SERVICE_Client`. |
1911 | */ | 1901 | */ |
1902 | static void | ||
1903 | finish_client_drop (void *cls) | ||
1904 | { | ||
1905 | struct GNUNET_SERVICE_Client *c = cls; | ||
1906 | struct GNUNET_SERVICE_Handle *sh = c->sh; | ||
1907 | |||
1908 | c->drop_task = NULL; | ||
1909 | GNUNET_CONTAINER_DLL_remove (sh->clients_head, | ||
1910 | sh->clients_tail, | ||
1911 | c); | ||
1912 | GNUNET_assert (NULL == c->send_task); | ||
1913 | GNUNET_assert (NULL == c->recv_task); | ||
1914 | GNUNET_assert (NULL == c->warn_task); | ||
1915 | GNUNET_MST_destroy (c->mst); | ||
1916 | GNUNET_MQ_destroy (c->mq); | ||
1917 | if (! c->persist) | ||
1918 | { | ||
1919 | GNUNET_break (GNUNET_OK == | ||
1920 | GNUNET_NETWORK_socket_close (c->sock)); | ||
1921 | if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) && | ||
1922 | (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state))) | ||
1923 | do_resume (sh, | ||
1924 | SUSPEND_STATE_EMFILE); | ||
1925 | } | ||
1926 | else | ||
1927 | { | ||
1928 | GNUNET_NETWORK_socket_free_memory_only_ (c->sock); | ||
1929 | } | ||
1930 | GNUNET_free (c); | ||
1931 | if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) && | ||
1932 | (! have_non_monitor_clients (sh))) | ||
1933 | GNUNET_SERVICE_shutdown (sh); | ||
1934 | } | ||
1935 | |||
1936 | |||
1912 | void | 1937 | void |
1913 | GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv) | 1938 | GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv) |
1914 | { | 1939 | { |
@@ -1916,7 +1941,12 @@ GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv) | |||
1916 | 1941 | ||
1917 | GNUNET_SERVICE_suspend (srv); | 1942 | GNUNET_SERVICE_suspend (srv); |
1918 | while (NULL != (client = srv->clients_head)) | 1943 | while (NULL != (client = srv->clients_head)) |
1919 | GNUNET_SERVICE_client_drop (client); | 1944 | { |
1945 | if (NULL == client->drop_task) | ||
1946 | GNUNET_SERVICE_client_drop (client); | ||
1947 | GNUNET_SCHEDULER_cancel (client->drop_task); | ||
1948 | finish_client_drop (client); | ||
1949 | } | ||
1920 | teardown_service (srv); | 1950 | teardown_service (srv); |
1921 | GNUNET_free (srv->handlers); | 1951 | GNUNET_free (srv->handlers); |
1922 | GNUNET_free (srv); | 1952 | GNUNET_free (srv); |
@@ -1988,7 +2018,6 @@ GNUNET_SERVICE_run_ (int argc, | |||
1988 | ? GNUNET_MQ_copy_handlers (handlers) | 2018 | ? GNUNET_MQ_copy_handlers (handlers) |
1989 | : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL); | 2019 | : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL); |
1990 | sh.service_name = service_name; | 2020 | sh.service_name = service_name; |
1991 | sh.ret = 0; | ||
1992 | /* setup subsystems */ | 2021 | /* setup subsystems */ |
1993 | loglev = NULL; | 2022 | loglev = NULL; |
1994 | logfile = NULL; | 2023 | logfile = NULL; |
@@ -2040,9 +2069,12 @@ GNUNET_SERVICE_run_ (int argc, | |||
2040 | } | 2069 | } |
2041 | else | 2070 | else |
2042 | { | 2071 | { |
2043 | if (GNUNET_YES == GNUNET_DISK_file_test (cfg_filename)) | 2072 | if (GNUNET_YES == |
2073 | GNUNET_DISK_file_test (cfg_filename)) | ||
2044 | { | 2074 | { |
2045 | if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_filename)) | 2075 | if (GNUNET_SYSERR == |
2076 | GNUNET_CONFIGURATION_load (cfg, | ||
2077 | cfg_filename)) | ||
2046 | { | 2078 | { |
2047 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2079 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2048 | _ ("Malformed configuration file `%s', exit ...\n"), | 2080 | _ ("Malformed configuration file `%s', exit ...\n"), |
@@ -2052,7 +2084,9 @@ GNUNET_SERVICE_run_ (int argc, | |||
2052 | } | 2084 | } |
2053 | else | 2085 | else |
2054 | { | 2086 | { |
2055 | if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL)) | 2087 | if (GNUNET_SYSERR == |
2088 | GNUNET_CONFIGURATION_load (cfg, | ||
2089 | NULL)) | ||
2056 | { | 2090 | { |
2057 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2091 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2058 | _ ("Malformed configuration, exit ...\n")); | 2092 | _ ("Malformed configuration, exit ...\n")); |
@@ -2062,7 +2096,8 @@ GNUNET_SERVICE_run_ (int argc, | |||
2062 | } | 2096 | } |
2063 | if (GNUNET_OK != setup_service (&sh)) | 2097 | if (GNUNET_OK != setup_service (&sh)) |
2064 | goto shutdown; | 2098 | goto shutdown; |
2065 | if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sh))) | 2099 | if ( (1 == do_daemonize) && |
2100 | (GNUNET_OK != detach_terminal (&sh)) ) | ||
2066 | { | 2101 | { |
2067 | GNUNET_break (0); | 2102 | GNUNET_break (0); |
2068 | goto shutdown; | 2103 | goto shutdown; |
@@ -2073,14 +2108,16 @@ GNUNET_SERVICE_run_ (int argc, | |||
2073 | "Service `%s' runs with configuration from `%s'\n", | 2108 | "Service `%s' runs with configuration from `%s'\n", |
2074 | service_name, | 2109 | service_name, |
2075 | (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename); | 2110 | (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename); |
2076 | if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sh.cfg, | 2111 | if ( (GNUNET_OK == |
2077 | "TESTING", | 2112 | GNUNET_CONFIGURATION_get_value_number (sh.cfg, |
2078 | "SKEW_OFFSET", | 2113 | "TESTING", |
2079 | &skew_offset)) && | 2114 | "SKEW_OFFSET", |
2080 | (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sh.cfg, | 2115 | &skew_offset)) && |
2081 | "TESTING", | 2116 | (GNUNET_OK == |
2082 | "SKEW_VARIANCE", | 2117 | GNUNET_CONFIGURATION_get_value_number (sh.cfg, |
2083 | &skew_variance))) | 2118 | "TESTING", |
2119 | "SKEW_VARIANCE", | ||
2120 | &skew_variance)) ) | ||
2084 | { | 2121 | { |
2085 | clock_offset = skew_offset - skew_variance; | 2122 | clock_offset = skew_offset - skew_variance; |
2086 | GNUNET_TIME_set_offset (clock_offset); | 2123 | GNUNET_TIME_set_offset (clock_offset); |
@@ -2108,18 +2145,23 @@ shutdown: | |||
2108 | { | 2145 | { |
2109 | char *counter; | 2146 | char *counter; |
2110 | 2147 | ||
2111 | if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (sh.cfg, | 2148 | if ( (GNUNET_YES == |
2112 | service_name, | 2149 | GNUNET_CONFIGURATION_have_value (sh.cfg, |
2113 | "GAUGER_HEAP")) && | 2150 | service_name, |
2114 | (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (sh.cfg, | 2151 | "GAUGER_HEAP")) && |
2115 | service_name, | 2152 | (GNUNET_OK == |
2116 | "GAUGER_HEAP", | 2153 | GNUNET_CONFIGURATION_get_value_string (sh.cfg, |
2117 | &counter))) | 2154 | service_name, |
2155 | "GAUGER_HEAP", | ||
2156 | &counter))) | ||
2118 | { | 2157 | { |
2119 | struct mallinfo2 mi; | 2158 | struct mallinfo2 mi; |
2120 | 2159 | ||
2121 | mi = mallinfo2 (); | 2160 | mi = mallinfo2 (); |
2122 | GAUGER (service_name, counter, mi.usmblks, "blocks"); | 2161 | GAUGER (service_name, |
2162 | counter, | ||
2163 | mi.usmblks, | ||
2164 | "blocks"); | ||
2123 | GNUNET_free (counter); | 2165 | GNUNET_free (counter); |
2124 | } | 2166 | } |
2125 | } | 2167 | } |
@@ -2133,11 +2175,12 @@ shutdown: | |||
2133 | GNUNET_free (cfg_filename); | 2175 | GNUNET_free (cfg_filename); |
2134 | GNUNET_free (opt_cfg_filename); | 2176 | GNUNET_free (opt_cfg_filename); |
2135 | 2177 | ||
2136 | return err ? GNUNET_SYSERR : sh.ret; | 2178 | return err ? GNUNET_SYSERR : 0; |
2137 | } | 2179 | } |
2138 | 2180 | ||
2139 | 2181 | ||
2140 | /* A list of service to be launched when GNUNET_SERVICE_main() | 2182 | /** |
2183 | * A list of service to be launched when GNUNET_SERVICE_main() | ||
2141 | * is called | 2184 | * is called |
2142 | */ | 2185 | */ |
2143 | struct ServiceHandleList | 2186 | struct ServiceHandleList |
@@ -2153,10 +2196,11 @@ struct ServiceHandleList | |||
2153 | }; | 2196 | }; |
2154 | 2197 | ||
2155 | /* The service list */ | 2198 | /* The service list */ |
2156 | static struct ServiceHandleList *hll_head = NULL; | 2199 | static struct ServiceHandleList *hll_head; |
2157 | 2200 | ||
2158 | /* The service list */ | 2201 | /* The service list */ |
2159 | static struct ServiceHandleList *hll_tail = NULL; | 2202 | static struct ServiceHandleList *hll_tail; |
2203 | |||
2160 | 2204 | ||
2161 | int | 2205 | int |
2162 | GNUNET_SERVICE_register_ (const char *service_name, | 2206 | GNUNET_SERVICE_register_ (const char *service_name, |
@@ -2181,30 +2225,34 @@ GNUNET_SERVICE_register_ (const char *service_name, | |||
2181 | ? GNUNET_MQ_copy_handlers (handlers) | 2225 | ? GNUNET_MQ_copy_handlers (handlers) |
2182 | : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL); | 2226 | : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL); |
2183 | sh->service_name = service_name; | 2227 | sh->service_name = service_name; |
2184 | sh->ret = 0; | ||
2185 | hle = GNUNET_new (struct ServiceHandleList); | 2228 | hle = GNUNET_new (struct ServiceHandleList); |
2186 | hle->sh = sh; | 2229 | hle->sh = sh; |
2187 | GNUNET_CONTAINER_DLL_insert (hll_head, hll_tail, hle); | 2230 | GNUNET_CONTAINER_DLL_insert (hll_head, |
2188 | return GNUNET_OK; | 2231 | hll_tail, |
2232 | hle); | ||
2233 | return 0; | ||
2189 | } | 2234 | } |
2190 | 2235 | ||
2191 | 2236 | ||
2192 | static void | 2237 | static void |
2193 | do_registered_services_shutdown (void *cls) | 2238 | do_registered_services_shutdown (void *cls) |
2194 | { | 2239 | { |
2195 | struct GNUNET_SERVICE_Handle *sh; | 2240 | while (NULL != hll_head) |
2196 | struct ServiceHandleList *shl; | ||
2197 | |||
2198 | for (shl = hll_head; NULL != shl;) | ||
2199 | { | 2241 | { |
2200 | sh = shl->sh; | 2242 | struct ServiceHandleList *shl = hll_head; |
2201 | GNUNET_CONTAINER_DLL_remove (hll_head, hll_tail, shl); | 2243 | struct GNUNET_SERVICE_Handle *sh = shl->sh; |
2244 | |||
2245 | GNUNET_CONTAINER_DLL_remove (hll_head, | ||
2246 | hll_tail, | ||
2247 | shl); | ||
2202 | GNUNET_free (shl); | 2248 | GNUNET_free (shl); |
2203 | if (-1 != sh->ready_confirm_fd) | 2249 | if (-1 != sh->ready_confirm_fd) |
2204 | { | 2250 | { |
2205 | if (1 != write (sh->ready_confirm_fd, "S", 1)) | 2251 | if (1 != write (sh->ready_confirm_fd, "S", 1)) |
2206 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write"); | 2252 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, |
2207 | GNUNET_break (0 == close (sh->ready_confirm_fd)); | 2253 | "write"); |
2254 | GNUNET_break (0 == | ||
2255 | close (sh->ready_confirm_fd)); | ||
2208 | } | 2256 | } |
2209 | teardown_service (sh); | 2257 | teardown_service (sh); |
2210 | GNUNET_free (sh->handlers); | 2258 | GNUNET_free (sh->handlers); |
@@ -2216,20 +2264,22 @@ do_registered_services_shutdown (void *cls) | |||
2216 | static void | 2264 | static void |
2217 | launch_registered_services (void *cls) | 2265 | launch_registered_services (void *cls) |
2218 | { | 2266 | { |
2219 | struct ServiceHandleList *shl; | ||
2220 | struct GNUNET_CONFIGURATION_Handle *cfg = cls; | 2267 | struct GNUNET_CONFIGURATION_Handle *cfg = cls; |
2221 | 2268 | ||
2222 | for (shl = hll_head; NULL != shl; shl = shl->next) | 2269 | for (struct ServiceHandleList *shl = hll_head; |
2270 | NULL != shl; | ||
2271 | shl = shl->next) | ||
2223 | { | 2272 | { |
2224 | shl->sh->cfg = cfg; | 2273 | shl->sh->cfg = cfg; |
2225 | if (GNUNET_OK != setup_service (shl->sh)) | 2274 | if (GNUNET_OK != setup_service (shl->sh)) |
2226 | continue; | 2275 | continue; |
2227 | if (GNUNET_OK != set_user_id (shl->sh)) | 2276 | if (GNUNET_OK != set_user_id (shl->sh)) |
2228 | continue; | 2277 | continue; |
2229 | 2278 | GNUNET_SCHEDULER_add_now (&service_main, | |
2230 | GNUNET_SCHEDULER_add_now (&service_main, shl->sh); | 2279 | shl->sh); |
2231 | } | 2280 | } |
2232 | GNUNET_SCHEDULER_add_shutdown (&do_registered_services_shutdown, NULL); | 2281 | GNUNET_SCHEDULER_add_shutdown (&do_registered_services_shutdown, |
2282 | NULL); | ||
2233 | } | 2283 | } |
2234 | 2284 | ||
2235 | 2285 | ||
@@ -2246,7 +2296,6 @@ GNUNET_SERVICE_main (int argc, | |||
2246 | int ret; | 2296 | int ret; |
2247 | struct GNUNET_CONFIGURATION_Handle *cfg; | 2297 | struct GNUNET_CONFIGURATION_Handle *cfg; |
2248 | const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); | 2298 | const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); |
2249 | |||
2250 | struct GNUNET_GETOPT_CommandLineOption service_options[] = { | 2299 | struct GNUNET_GETOPT_CommandLineOption service_options[] = { |
2251 | GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename), | 2300 | GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename), |
2252 | GNUNET_GETOPT_option_flag ('d', | 2301 | GNUNET_GETOPT_option_flag ('d', |
@@ -2260,6 +2309,7 @@ GNUNET_SERVICE_main (int argc, | |||
2260 | GNUNET_GETOPT_option_version (pd->version), | 2309 | GNUNET_GETOPT_option_version (pd->version), |
2261 | GNUNET_GETOPT_OPTION_END | 2310 | GNUNET_GETOPT_OPTION_END |
2262 | }; | 2311 | }; |
2312 | |||
2263 | xdg = getenv ("XDG_CONFIG_HOME"); | 2313 | xdg = getenv ("XDG_CONFIG_HOME"); |
2264 | if (NULL != xdg) | 2314 | if (NULL != xdg) |
2265 | GNUNET_asprintf (&cfg_filename, | 2315 | GNUNET_asprintf (&cfg_filename, |
@@ -2282,17 +2332,22 @@ GNUNET_SERVICE_main (int argc, | |||
2282 | goto shutdown; | 2332 | goto shutdown; |
2283 | } | 2333 | } |
2284 | // FIXME we need to set this up for each service! | 2334 | // FIXME we need to set this up for each service! |
2285 | if (GNUNET_OK != GNUNET_log_setup ("libgnunet", | 2335 | // NOTE: that was not the idea. What are you proposing? -CG |
2286 | loglev, | 2336 | if (GNUNET_OK != |
2287 | logfile)) | 2337 | GNUNET_log_setup ("libgnunet", |
2338 | loglev, | ||
2339 | logfile)) | ||
2288 | { | 2340 | { |
2289 | GNUNET_break (0); | 2341 | GNUNET_break (0); |
2290 | goto shutdown; | 2342 | goto shutdown; |
2291 | } | 2343 | } |
2292 | if (NULL != opt_cfg_filename) | 2344 | if (NULL != opt_cfg_filename) |
2293 | { | 2345 | { |
2294 | if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) || | 2346 | if ( (GNUNET_YES != |
2295 | (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename))) | 2347 | GNUNET_DISK_file_test (opt_cfg_filename)) || |
2348 | (GNUNET_SYSERR == | ||
2349 | GNUNET_CONFIGURATION_load (cfg, | ||
2350 | opt_cfg_filename)) ) | ||
2296 | { | 2351 | { |
2297 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2352 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2298 | _ ("Malformed configuration file `%s', exit ...\n"), | 2353 | _ ("Malformed configuration file `%s', exit ...\n"), |
@@ -2302,9 +2357,12 @@ GNUNET_SERVICE_main (int argc, | |||
2302 | } | 2357 | } |
2303 | else | 2358 | else |
2304 | { | 2359 | { |
2305 | if (GNUNET_YES == GNUNET_DISK_file_test (cfg_filename)) | 2360 | if (GNUNET_YES == |
2361 | GNUNET_DISK_file_test (cfg_filename)) | ||
2306 | { | 2362 | { |
2307 | if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_filename)) | 2363 | if (GNUNET_SYSERR == |
2364 | GNUNET_CONFIGURATION_load (cfg, | ||
2365 | cfg_filename)) | ||
2308 | { | 2366 | { |
2309 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2367 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2310 | _ ("Malformed configuration file `%s', exit ...\n"), | 2368 | _ ("Malformed configuration file `%s', exit ...\n"), |
@@ -2315,7 +2373,9 @@ GNUNET_SERVICE_main (int argc, | |||
2315 | } | 2373 | } |
2316 | else | 2374 | else |
2317 | { | 2375 | { |
2318 | if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL)) | 2376 | if (GNUNET_SYSERR == |
2377 | GNUNET_CONFIGURATION_load (cfg, | ||
2378 | NULL)) | ||
2319 | { | 2379 | { |
2320 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2380 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2321 | _ ("Malformed configuration, exit ...\n")); | 2381 | _ ("Malformed configuration, exit ...\n")); |
@@ -2326,7 +2386,8 @@ GNUNET_SERVICE_main (int argc, | |||
2326 | } | 2386 | } |
2327 | GNUNET_RESOLVER_connect (cfg); | 2387 | GNUNET_RESOLVER_connect (cfg); |
2328 | 2388 | ||
2329 | GNUNET_SCHEDULER_run (&launch_registered_services, cfg); | 2389 | GNUNET_SCHEDULER_run (&launch_registered_services, |
2390 | cfg); | ||
2330 | shutdown: | 2391 | shutdown: |
2331 | GNUNET_SPEEDUP_stop_ (); | 2392 | GNUNET_SPEEDUP_stop_ (); |
2332 | GNUNET_CONFIGURATION_destroy (cfg); | 2393 | GNUNET_CONFIGURATION_destroy (cfg); |
@@ -2337,28 +2398,19 @@ shutdown: | |||
2337 | } | 2398 | } |
2338 | 2399 | ||
2339 | 2400 | ||
2340 | /** | ||
2341 | * Suspend accepting connections from the listen socket temporarily. | ||
2342 | * Resume activity using #GNUNET_SERVICE_resume. | ||
2343 | * | ||
2344 | * @param sh service to stop accepting connections. | ||
2345 | */ | ||
2346 | void | 2401 | void |
2347 | GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh) | 2402 | GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh) |
2348 | { | 2403 | { |
2349 | do_suspend (sh, SUSPEND_STATE_APP); | 2404 | do_suspend (sh, |
2405 | SUSPEND_STATE_APP); | ||
2350 | } | 2406 | } |
2351 | 2407 | ||
2352 | 2408 | ||
2353 | /** | ||
2354 | * Resume accepting connections from the listen socket. | ||
2355 | * | ||
2356 | * @param sh service to resume accepting connections. | ||
2357 | */ | ||
2358 | void | 2409 | void |
2359 | GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh) | 2410 | GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh) |
2360 | { | 2411 | { |
2361 | do_resume (sh, SUSPEND_STATE_APP); | 2412 | do_resume (sh, |
2413 | SUSPEND_STATE_APP); | ||
2362 | } | 2414 | } |
2363 | 2415 | ||
2364 | 2416 | ||
@@ -2376,7 +2428,8 @@ resume_client_receive (void *cls) | |||
2376 | 2428 | ||
2377 | c->recv_task = NULL; | 2429 | c->recv_task = NULL; |
2378 | /* first, check if there is still something in the buffer */ | 2430 | /* first, check if there is still something in the buffer */ |
2379 | ret = GNUNET_MST_next (c->mst, GNUNET_YES); | 2431 | ret = GNUNET_MST_next (c->mst, |
2432 | GNUNET_YES); | ||
2380 | if (GNUNET_SYSERR == ret) | 2433 | if (GNUNET_SYSERR == ret) |
2381 | { | 2434 | { |
2382 | if (NULL == c->drop_task) | 2435 | if (NULL == c->drop_task) |
@@ -2386,7 +2439,7 @@ resume_client_receive (void *cls) | |||
2386 | if (GNUNET_NO == ret) | 2439 | if (GNUNET_NO == ret) |
2387 | return; /* done processing, wait for more later */ | 2440 | return; /* done processing, wait for more later */ |
2388 | GNUNET_assert (GNUNET_OK == ret); | 2441 | GNUNET_assert (GNUNET_OK == ret); |
2389 | if (GNUNET_YES == c->needs_continue) | 2442 | if (c->needs_continue) |
2390 | return; /* #GNUNET_MST_next() did give a message to the client */ | 2443 | return; /* #GNUNET_MST_next() did give a message to the client */ |
2391 | /* need to receive more data from the network first */ | 2444 | /* need to receive more data from the network first */ |
2392 | if (NULL != c->recv_task) | 2445 | if (NULL != c->recv_task) |
@@ -2398,36 +2451,23 @@ resume_client_receive (void *cls) | |||
2398 | } | 2451 | } |
2399 | 2452 | ||
2400 | 2453 | ||
2401 | /** | ||
2402 | * Continue receiving further messages from the given client. | ||
2403 | * Must be called after each message received. | ||
2404 | * | ||
2405 | * @param c the client to continue receiving from | ||
2406 | */ | ||
2407 | void | 2454 | void |
2408 | GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c) | 2455 | GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c) |
2409 | { | 2456 | { |
2410 | GNUNET_assert (NULL == c->drop_task); | 2457 | GNUNET_assert (NULL == c->drop_task); |
2411 | GNUNET_assert (GNUNET_YES == c->needs_continue); | 2458 | GNUNET_assert (c->needs_continue); |
2412 | GNUNET_assert (NULL == c->recv_task); | 2459 | GNUNET_assert (NULL == c->recv_task); |
2413 | c->needs_continue = GNUNET_NO; | 2460 | c->needs_continue = false; |
2414 | if (NULL != c->warn_task) | 2461 | if (NULL != c->warn_task) |
2415 | { | 2462 | { |
2416 | GNUNET_SCHEDULER_cancel (c->warn_task); | 2463 | GNUNET_SCHEDULER_cancel (c->warn_task); |
2417 | c->warn_task = NULL; | 2464 | c->warn_task = NULL; |
2418 | } | 2465 | } |
2419 | c->recv_task = GNUNET_SCHEDULER_add_now (&resume_client_receive, c); | 2466 | c->recv_task = GNUNET_SCHEDULER_add_now (&resume_client_receive, |
2467 | c); | ||
2420 | } | 2468 | } |
2421 | 2469 | ||
2422 | 2470 | ||
2423 | /** | ||
2424 | * Disable the warning the server issues if a message is not | ||
2425 | * acknowledged in a timely fashion. Use this call if a client is | ||
2426 | * intentionally delayed for a while. Only applies to the current | ||
2427 | * message. | ||
2428 | * | ||
2429 | * @param c client for which to disable the warning | ||
2430 | */ | ||
2431 | void | 2471 | void |
2432 | GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c) | 2472 | GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c) |
2433 | { | 2473 | { |
@@ -2440,51 +2480,6 @@ GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c) | |||
2440 | } | 2480 | } |
2441 | 2481 | ||
2442 | 2482 | ||
2443 | /** | ||
2444 | * Asynchronously finish dropping the client. | ||
2445 | * | ||
2446 | * @param cls the `struct GNUNET_SERVICE_Client`. | ||
2447 | */ | ||
2448 | static void | ||
2449 | finish_client_drop (void *cls) | ||
2450 | { | ||
2451 | struct GNUNET_SERVICE_Client *c = cls; | ||
2452 | struct GNUNET_SERVICE_Handle *sh = c->sh; | ||
2453 | |||
2454 | c->drop_task = NULL; | ||
2455 | GNUNET_assert (NULL == c->send_task); | ||
2456 | GNUNET_assert (NULL == c->recv_task); | ||
2457 | GNUNET_assert (NULL == c->warn_task); | ||
2458 | GNUNET_MST_destroy (c->mst); | ||
2459 | GNUNET_MQ_destroy (c->mq); | ||
2460 | if (GNUNET_NO == c->persist) | ||
2461 | { | ||
2462 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (c->sock)); | ||
2463 | if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) && | ||
2464 | (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state))) | ||
2465 | do_resume (sh, SUSPEND_STATE_EMFILE); | ||
2466 | } | ||
2467 | else | ||
2468 | { | ||
2469 | GNUNET_NETWORK_socket_free_memory_only_ (c->sock); | ||
2470 | } | ||
2471 | GNUNET_free (c); | ||
2472 | if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) && | ||
2473 | (GNUNET_NO == have_non_monitor_clients (sh))) | ||
2474 | GNUNET_SERVICE_shutdown (sh); | ||
2475 | } | ||
2476 | |||
2477 | |||
2478 | /** | ||
2479 | * Ask the server to disconnect from the given client. This is the | ||
2480 | * same as returning #GNUNET_SYSERR within the check procedure when | ||
2481 | * handling a message, wexcept that it allows dropping of a client even | ||
2482 | * when not handling a message from that client. The `disconnect_cb` | ||
2483 | * will be called on @a c even if the application closes the connection | ||
2484 | * using this function. | ||
2485 | * | ||
2486 | * @param c client to disconnect now | ||
2487 | */ | ||
2488 | void | 2483 | void |
2489 | GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c) | 2484 | GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c) |
2490 | { | 2485 | { |
@@ -2497,9 +2492,11 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c) | |||
2497 | #if EXECINFO | 2492 | #if EXECINFO |
2498 | { | 2493 | { |
2499 | void *backtrace_array[MAX_TRACE_DEPTH]; | 2494 | void *backtrace_array[MAX_TRACE_DEPTH]; |
2500 | int num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH); | 2495 | int num_backtrace_strings = backtrace (backtrace_array, |
2496 | MAX_TRACE_DEPTH); | ||
2501 | char **backtrace_strings = | 2497 | char **backtrace_strings = |
2502 | backtrace_symbols (backtrace_array, t->num_backtrace_strings); | 2498 | backtrace_symbols (backtrace_array, |
2499 | t->num_backtrace_strings); | ||
2503 | for (unsigned int i = 0; i < num_backtrace_strings; i++) | 2500 | for (unsigned int i = 0; i < num_backtrace_strings; i++) |
2504 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2501 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2505 | "client drop trace %u: %s\n", | 2502 | "client drop trace %u: %s\n", |
@@ -2507,15 +2504,7 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c) | |||
2507 | backtrace_strings[i]); | 2504 | backtrace_strings[i]); |
2508 | } | 2505 | } |
2509 | #endif | 2506 | #endif |
2510 | if (NULL != c->drop_task) | 2507 | GNUNET_assert (NULL == c->drop_task); |
2511 | { | ||
2512 | /* asked to drop twice! */ | ||
2513 | GNUNET_assert (0); | ||
2514 | return; | ||
2515 | } | ||
2516 | GNUNET_CONTAINER_DLL_remove (sh->clients_head, | ||
2517 | sh->clients_tail, | ||
2518 | c); | ||
2519 | if (NULL != sh->disconnect_cb) | 2508 | if (NULL != sh->disconnect_cb) |
2520 | sh->disconnect_cb (sh->cb_cls, | 2509 | sh->disconnect_cb (sh->cb_cls, |
2521 | c, | 2510 | c, |
@@ -2535,69 +2524,44 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c) | |||
2535 | GNUNET_SCHEDULER_cancel (c->send_task); | 2524 | GNUNET_SCHEDULER_cancel (c->send_task); |
2536 | c->send_task = NULL; | 2525 | c->send_task = NULL; |
2537 | } | 2526 | } |
2538 | c->drop_task = GNUNET_SCHEDULER_add_now (&finish_client_drop, c); | 2527 | c->drop_task = GNUNET_SCHEDULER_add_now (&finish_client_drop, |
2528 | c); | ||
2539 | } | 2529 | } |
2540 | 2530 | ||
2541 | 2531 | ||
2542 | /** | ||
2543 | * Explicitly stops the service. | ||
2544 | * | ||
2545 | * @param sh server to shutdown | ||
2546 | */ | ||
2547 | void | 2532 | void |
2548 | GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh) | 2533 | GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh) |
2549 | { | 2534 | { |
2550 | struct GNUNET_SERVICE_Client *client; | ||
2551 | |||
2552 | if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN)) | 2535 | if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN)) |
2553 | do_suspend (sh, SUSPEND_STATE_SHUTDOWN); | 2536 | do_suspend (sh, |
2554 | while (NULL != (client = sh->clients_head)) | 2537 | SUSPEND_STATE_SHUTDOWN); |
2555 | GNUNET_SERVICE_client_drop (client); | 2538 | for (struct GNUNET_SERVICE_Client *client = sh->clients_head; |
2539 | NULL != client; | ||
2540 | client = client->next) | ||
2541 | { | ||
2542 | if (NULL == client->drop_task) | ||
2543 | GNUNET_SERVICE_client_drop (client); | ||
2544 | } | ||
2556 | } | 2545 | } |
2557 | 2546 | ||
2558 | 2547 | ||
2559 | /** | ||
2560 | * Set the 'monitor' flag on this client. Clients which have been | ||
2561 | * marked as 'monitors' won't prevent the server from shutting down | ||
2562 | * once #GNUNET_SERVICE_stop_listening() has been invoked. The idea is | ||
2563 | * that for "normal" clients we likely want to allow them to process | ||
2564 | * their requests; however, monitor-clients are likely to 'never' | ||
2565 | * disconnect during shutdown and thus will not be considered when | ||
2566 | * determining if the server should continue to exist after | ||
2567 | * shutdown has been triggered. | ||
2568 | * | ||
2569 | * @param c client to mark as a monitor | ||
2570 | */ | ||
2571 | void | 2548 | void |
2572 | GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c) | 2549 | GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c) |
2573 | { | 2550 | { |
2574 | c->is_monitor = GNUNET_YES; | 2551 | c->is_monitor = true; |
2575 | if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) && | 2552 | if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) && |
2576 | (GNUNET_NO == have_non_monitor_clients (c->sh)))) | 2553 | (! have_non_monitor_clients (c->sh)))) |
2577 | GNUNET_SERVICE_shutdown (c->sh); | 2554 | GNUNET_SERVICE_shutdown (c->sh); |
2578 | } | 2555 | } |
2579 | 2556 | ||
2580 | 2557 | ||
2581 | /** | ||
2582 | * Set the persist option on this client. Indicates that the | ||
2583 | * underlying socket or fd should never really be closed. Used for | ||
2584 | * indicating process death. | ||
2585 | * | ||
2586 | * @param c client to persist the socket (never to be closed) | ||
2587 | */ | ||
2588 | void | 2558 | void |
2589 | GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c) | 2559 | GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c) |
2590 | { | 2560 | { |
2591 | c->persist = GNUNET_YES; | 2561 | c->persist = true; |
2592 | } | 2562 | } |
2593 | 2563 | ||
2594 | 2564 | ||
2595 | /** | ||
2596 | * Obtain the message queue of @a c. Convenience function. | ||
2597 | * | ||
2598 | * @param c the client to continue receiving from | ||
2599 | * @return the message queue of @a c | ||
2600 | */ | ||
2601 | struct GNUNET_MQ_Handle * | 2565 | struct GNUNET_MQ_Handle * |
2602 | GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c) | 2566 | GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c) |
2603 | { | 2567 | { |