aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/service.c')
-rw-r--r--src/lib/util/service.c596
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 */
361static int 355static enum GNUNET_GenericReturnValue
362have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh) 356have_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 */
382static void 379static void
383do_suspend (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr) 380do_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 */
440static int 438static bool
441check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, 439check_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 */
467static int 461static bool
468check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, 462check_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;
476NEXT:
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 */
595static void 588static void
596service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state) 589service_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 */
617static void 611static void
618service_mq_error_handler (void *cls, enum GNUNET_MQ_Error error) 612service_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 */
872static void 876static void
873do_resume (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr) 877do_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 */
931static int 936static enum GNUNET_GenericReturnValue
932process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, 937process_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 */
972static int 977static enum GNUNET_GenericReturnValue
973process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, 978process_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 */
1460static int 1465static enum GNUNET_GenericReturnValue
1461setup_service (struct GNUNET_SERVICE_Handle *sh) 1466setup_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 */
1627static int 1638static enum GNUNET_GenericReturnValue
1628set_user_id (struct GNUNET_SERVICE_Handle *sh) 1639set_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 */
1716static int 1729static enum GNUNET_GenericReturnValue
1717detach_terminal (struct GNUNET_SERVICE_Handle *sh) 1730detach_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 */
1823static void 1842static void
1824return_agpl (void *cls, const struct GNUNET_MessageHeader *msg) 1843return_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 */
1879struct GNUNET_SERVICE_Handle * 1866struct GNUNET_SERVICE_Handle *
1880GNUNET_SERVICE_start (const char *service_name, 1867GNUNET_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 */
1902static void
1903finish_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
1912void 1937void
1913GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv) 1938GNUNET_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 */
2143struct ServiceHandleList 2186struct ServiceHandleList
@@ -2153,10 +2196,11 @@ struct ServiceHandleList
2153}; 2196};
2154 2197
2155/* The service list */ 2198/* The service list */
2156static struct ServiceHandleList *hll_head = NULL; 2199static struct ServiceHandleList *hll_head;
2157 2200
2158/* The service list */ 2201/* The service list */
2159static struct ServiceHandleList *hll_tail = NULL; 2202static struct ServiceHandleList *hll_tail;
2203
2160 2204
2161int 2205int
2162GNUNET_SERVICE_register_ (const char *service_name, 2206GNUNET_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
2192static void 2237static void
2193do_registered_services_shutdown (void *cls) 2238do_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)
2216static void 2264static void
2217launch_registered_services (void *cls) 2265launch_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);
2330shutdown: 2391shutdown:
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 */
2346void 2401void
2347GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh) 2402GNUNET_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 */
2358void 2409void
2359GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh) 2410GNUNET_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 */
2407void 2454void
2408GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c) 2455GNUNET_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 */
2431void 2471void
2432GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c) 2472GNUNET_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 */
2448static void
2449finish_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 */
2488void 2483void
2489GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c) 2484GNUNET_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 */
2547void 2532void
2548GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh) 2533GNUNET_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 */
2571void 2548void
2572GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c) 2549GNUNET_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 */
2588void 2558void
2589GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c) 2559GNUNET_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 */
2601struct GNUNET_MQ_Handle * 2565struct GNUNET_MQ_Handle *
2602GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c) 2566GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c)
2603{ 2567{