2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file util/service.c
23 * @brief functions related to starting services (redesign)
24 * @author Christian Grothoff
25 * @author Florian Dold
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_resolver_service.h"
40 #define LOG(kind, ...) GNUNET_log_from (kind, "util-service", __VA_ARGS__)
42 #define LOG_STRERROR(kind, syscall) \
43 GNUNET_log_from_strerror (kind, "util-service", syscall)
45 #define LOG_STRERROR_FILE(kind, syscall, filename) \
46 GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)
50 * Information the service tracks per listen operation.
52 struct ServiceListenContext
57 struct ServiceListenContext *next;
62 struct ServiceListenContext *prev;
65 * Service this listen context belongs to.
67 struct GNUNET_SERVICE_Handle *sh;
70 * Socket we are listening on.
72 struct GNUNET_NETWORK_Handle *listen_socket;
75 * Task scheduled to do the listening.
77 struct GNUNET_SCHEDULER_Task *listen_task;
82 * Reasons why we might be suspended.
87 * We are running normally.
89 SUSPEND_STATE_NONE = 0,
92 * Application requested it.
94 SUSPEND_STATE_APP = 1,
97 * OS ran out of file descriptors.
99 SUSPEND_STATE_EMFILE = 2,
102 * Both reasons, APP and EMFILE apply.
104 SUSPEND_STATE_APP_AND_EMFILE = 3,
107 * Suspension because service was permanently shutdown.
109 SUSPEND_STATE_SHUTDOWN = 4
114 * Handle to a service.
116 struct GNUNET_SERVICE_Handle
121 const struct GNUNET_CONFIGURATION_Handle *cfg;
124 * Name of our service.
126 const char *service_name;
129 * Main service-specific task to run.
131 GNUNET_SERVICE_InitCallback service_init_cb;
134 * Function to call when clients connect.
136 GNUNET_SERVICE_ConnectHandler connect_cb;
139 * Function to call when clients disconnect / are disconnected.
141 GNUNET_SERVICE_DisconnectHandler disconnect_cb;
144 * Closure for @e service_init_cb, @e connect_cb, @e disconnect_cb.
149 * DLL of listen sockets used to accept new connections.
151 struct ServiceListenContext *slc_head;
154 * DLL of listen sockets used to accept new connections.
156 struct ServiceListenContext *slc_tail;
159 * Our clients, kept in a DLL.
161 struct GNUNET_SERVICE_Client *clients_head;
164 * Our clients, kept in a DLL.
166 struct GNUNET_SERVICE_Client *clients_tail;
169 * Message handlers to use for all clients.
171 struct GNUNET_MQ_MessageHandler *handlers;
174 * Closure for @e task.
180 * IPv4 addresses that are not allowed to connect.
182 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
185 * IPv6 addresses that are not allowed to connect.
187 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
190 * IPv4 addresses that are allowed to connect (if not
191 * set, all are allowed).
193 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
196 * IPv6 addresses that are allowed to connect (if not
197 * set, all are allowed).
199 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
202 * Do we require a matching UID for UNIX domain socket connections?
203 * #GNUNET_NO means that the UID does not have to match (however,
204 * @e match_gid may still impose other access control checks).
209 * Do we require a matching GID for UNIX domain socket connections?
210 * Ignored if @e match_uid is #GNUNET_YES. Note that this is about
211 * checking that the client's UID is in our group OR that the
212 * client's GID is our GID. If both "match_gid" and @e match_uid are
213 * #GNUNET_NO, all users on the local system have access.
218 * Are we suspended, and if so, why?
220 enum SuspendReason suspend_state;
225 enum GNUNET_SERVICE_Options options;
228 * If we are daemonizing, this FD is set to the
229 * pipe to the parent. Send '.' if we started
230 * ok, '!' if not. -1 if we are not daemonizing.
232 int ready_confirm_fd;
235 * Overall success/failure of the service start.
240 * If #GNUNET_YES, consider unknown message types an error where the
241 * client is disconnected.
248 * Handle to a client that is connected to a service.
250 struct GNUNET_SERVICE_Client
255 struct GNUNET_SERVICE_Client *next;
260 struct GNUNET_SERVICE_Client *prev;
263 * Service that this client belongs to.
265 struct GNUNET_SERVICE_Handle *sh;
268 * Socket of this client.
270 struct GNUNET_NETWORK_Handle *sock;
273 * Message queue for the client.
275 struct GNUNET_MQ_Handle *mq;
278 * Tokenizer we use for processing incoming data.
280 struct GNUNET_MessageStreamTokenizer *mst;
283 * Task that warns about missing calls to
284 * #GNUNET_SERVICE_client_continue().
286 struct GNUNET_SCHEDULER_Task *warn_task;
289 * Task run to finish dropping the client after the stack has
292 struct GNUNET_SCHEDULER_Task *drop_task;
295 * Task that receives data from the client to
296 * pass it to the handlers.
298 struct GNUNET_SCHEDULER_Task *recv_task;
301 * Task that transmit data to the client.
303 struct GNUNET_SCHEDULER_Task *send_task;
306 * Pointer to the message to be transmitted by @e send_task.
308 const struct GNUNET_MessageHeader *msg;
311 * User context value, value returned from
312 * the connect callback.
317 * Time when we last gave a message from this client
318 * to the application.
320 struct GNUNET_TIME_Absolute warn_start;
323 * Current position in @e msg at which we are transmitting.
328 * Persist the file handle for this client no matter what happens,
329 * force the OS to close once the process actually dies. Should only
330 * be used in special cases!
335 * Is this client a 'monitor' client that should not be counted
336 * when deciding on destroying the server during soft shutdown?
337 * (see also #GNUNET_SERVICE_start)
342 * Are we waiting for the application to call #GNUNET_SERVICE_client_continue()?
347 * Type of last message processed (for warn_no_receive_done).
354 * Check if any of the clients we have left are unrelated to
357 * @param sh service to check clients for
358 * @return #GNUNET_YES if we have non-monitoring clients left
361 have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
363 for (struct GNUNET_SERVICE_Client *client = sh->clients_head; NULL != client;
364 client = client->next)
366 if (client->is_monitor)
375 * Suspend accepting connections from the listen socket temporarily.
376 * Resume activity using #do_resume.
378 * @param sh service to stop accepting connections.
379 * @param sr reason for suspending accepting connections
382 do_suspend (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
384 struct ServiceListenContext *slc;
386 GNUNET_assert (0 == (sh->suspend_state & sr));
387 sh->suspend_state |= sr;
388 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
390 if (NULL != slc->listen_task)
392 GNUNET_SCHEDULER_cancel (slc->listen_task);
393 slc->listen_task = NULL;
400 * Shutdown task triggered when a service should be terminated.
401 * This considers active clients and the service options to see
402 * how this specific service is to be terminated, and depending
403 * on this proceeds with the shutdown logic.
405 * @param cls our `struct GNUNET_SERVICE_Handle`
408 service_shutdown (void *cls)
410 struct GNUNET_SERVICE_Handle *sh = cls;
412 switch (sh->options & GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK)
414 case GNUNET_SERVICE_OPTION_NONE:
415 GNUNET_SERVICE_shutdown (sh);
417 case GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN:
418 /* This task should never be run if we are using
419 the manual shutdown. */
422 case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN:
423 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
424 do_suspend (sh, SUSPEND_STATE_SHUTDOWN);
425 if (GNUNET_NO == have_non_monitor_clients (sh))
426 GNUNET_SERVICE_shutdown (sh);
433 * Check if the given IP address is in the list of IP addresses.
435 * @param list a list of networks
436 * @param add the IP to check (in network byte order)
437 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
440 check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
441 const struct in_addr *add)
448 while ((0 != list[i].network.s_addr) || (0 != list[i].netmask.s_addr))
450 if ((add->s_addr & list[i].netmask.s_addr) ==
451 (list[i].network.s_addr & list[i].netmask.s_addr))
460 * Check if the given IP address is in the list of IP addresses.
462 * @param list a list of networks
463 * @param ip the IP to check (in network byte order)
464 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
467 check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
468 const struct in6_addr *ip)
477 while (0 != GNUNET_is_zero (&list[i].network))
479 for (j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
480 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
481 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
493 * Task run when we are ready to transmit data to the
496 * @param cls the `struct GNUNET_SERVICE_Client *` to send to
501 struct GNUNET_SERVICE_Client *client = cls;
506 LOG (GNUNET_ERROR_TYPE_DEBUG,
507 "service: sending message with type %u\n",
508 ntohs (client->msg->type));
509 client->send_task = NULL;
510 buf = (const char *) client->msg;
511 left = ntohs (client->msg->size) - client->msg_pos;
512 ret = GNUNET_NETWORK_socket_send (client->sock,
513 &buf[client->msg_pos],
515 GNUNET_assert (ret <= (ssize_t) left);
518 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
519 GNUNET_MQ_inject_error (client->mq, GNUNET_MQ_ERROR_WRITE);
524 if ((EAGAIN == errno) || (EINTR == errno))
532 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
533 LOG (GNUNET_ERROR_TYPE_DEBUG,
534 "socket send returned with error code %i",
536 GNUNET_MQ_inject_error (client->mq, GNUNET_MQ_ERROR_WRITE);
540 if (0 == client->msg_pos)
542 GNUNET_MQ_impl_send_in_flight (client->mq);
544 client->msg_pos += ret;
545 if (left > (size_t) ret)
547 GNUNET_assert (NULL == client->drop_task);
549 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
555 GNUNET_MQ_impl_send_continue (client->mq);
560 * Signature of functions implementing the sending functionality of a
563 * @param mq the message queue
564 * @param msg the message to send
565 * @param impl_state our `struct GNUNET_SERVICE_Client *`
568 service_mq_send (struct GNUNET_MQ_Handle *mq,
569 const struct GNUNET_MessageHeader *msg,
572 struct GNUNET_SERVICE_Client *client = impl_state;
575 if (NULL != client->drop_task)
576 return; /* we're going down right now, do not try to send */
577 GNUNET_assert (NULL == client->send_task);
578 LOG (GNUNET_ERROR_TYPE_DEBUG,
579 "Sending message of type %u and size %u to client\n",
584 client->send_task = GNUNET_SCHEDULER_add_now (&do_send,
590 * Implementation function that cancels the currently sent message.
592 * @param mq message queue
593 * @param impl_state state specific to the implementation
596 service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
598 struct GNUNET_SERVICE_Client *client = impl_state;
601 GNUNET_assert (0 == client->msg_pos);
603 GNUNET_SCHEDULER_cancel (client->send_task);
604 client->send_task = NULL;
609 * Generic error handler, called with the appropriate
610 * error code and the same closure specified at the creation of
612 * Not every message queue implementation supports an error handler.
614 * @param cls closure with our `struct GNUNET_SERVICE_Client`
615 * @param error error code
618 service_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
620 struct GNUNET_SERVICE_Client *client = cls;
621 struct GNUNET_SERVICE_Handle *sh = client->sh;
623 if ((GNUNET_MQ_ERROR_NO_MATCH == error) && (GNUNET_NO == sh->require_found))
625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
626 "No handler for message of type %u found\n",
627 (unsigned int) client->warn_type);
628 GNUNET_SERVICE_client_continue (client);
629 return; /* ignore error */
631 GNUNET_SERVICE_client_drop (client);
636 * Task run to warn about missing calls to #GNUNET_SERVICE_client_continue().
638 * @param cls our `struct GNUNET_SERVICE_Client *` to process more requests from
641 warn_no_client_continue (void *cls)
643 struct GNUNET_SERVICE_Client *client = cls;
647 client->warn_type); /* type should never be 0 here, as we don't use 0 */
648 client->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
649 &warn_no_client_continue,
652 GNUNET_ERROR_TYPE_WARNING,
654 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
655 (unsigned int) client->warn_type,
656 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (
663 * Functions with this signature are called whenever a
664 * complete message is received by the tokenizer for a client.
666 * Do not call #GNUNET_MST_destroy() from within
667 * the scope of this callback.
669 * @param cls closure with the `struct GNUNET_SERVICE_Client *`
670 * @param message the actual message
671 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the client was dropped
674 service_client_mst_cb (void *cls, const struct GNUNET_MessageHeader *message)
676 struct GNUNET_SERVICE_Client *client = cls;
678 LOG (GNUNET_ERROR_TYPE_DEBUG,
679 "Received message of type %u and size %u from client\n",
680 ntohs (message->type),
681 ntohs (message->size));
682 GNUNET_assert (GNUNET_NO == client->needs_continue);
683 client->needs_continue = GNUNET_YES;
684 client->warn_type = ntohs (message->type);
685 client->warn_start = GNUNET_TIME_absolute_get ();
686 GNUNET_assert (NULL == client->warn_task);
687 client->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
688 &warn_no_client_continue,
690 GNUNET_MQ_inject_message (client->mq, message);
691 if (NULL != client->drop_task)
692 return GNUNET_SYSERR;
698 * A client sent us data. Receive and process it. If we are done,
699 * reschedule this task.
701 * @param cls the `struct GNUNET_SERVICE_Client` that sent us data.
704 service_client_recv (void *cls)
706 struct GNUNET_SERVICE_Client *client = cls;
709 client->recv_task = NULL;
710 ret = GNUNET_MST_read (client->mst, client->sock, GNUNET_NO, GNUNET_YES);
711 if (GNUNET_SYSERR == ret)
713 /* client closed connection (or IO error) */
714 if (NULL == client->drop_task)
716 GNUNET_assert (GNUNET_NO == client->needs_continue);
717 GNUNET_SERVICE_client_drop (client);
721 if (GNUNET_NO == ret)
722 return; /* more messages in buffer, wait for application
723 to be done processing */
724 GNUNET_assert (GNUNET_OK == ret);
725 if (GNUNET_YES == client->needs_continue)
727 if (NULL != client->recv_task)
729 /* MST needs more data, re-schedule read job */
731 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
733 &service_client_recv,
739 * We have successfully accepted a connection from a client. Now
740 * setup the client (with the scheduler) and tell the application.
742 * @param sh service that accepted the client
743 * @param sock socket associated with the client
746 start_client (struct GNUNET_SERVICE_Handle *sh,
747 struct GNUNET_NETWORK_Handle *csock)
749 struct GNUNET_SERVICE_Client *client;
751 client = GNUNET_new (struct GNUNET_SERVICE_Client);
752 GNUNET_CONTAINER_DLL_insert (sh->clients_head, sh->clients_tail, client);
754 client->sock = csock;
755 client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send,
760 &service_mq_error_handler,
762 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
763 if (NULL != sh->connect_cb)
764 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
765 GNUNET_MQ_set_handlers_closure (client->mq, client->user_context);
767 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
769 &service_client_recv,
775 * We have a client. Accept the incoming socket(s) (and reschedule
778 * @param cls the `struct ServiceListenContext` of the ready listen socket
781 accept_client (void *cls)
783 struct ServiceListenContext *slc = cls;
784 struct GNUNET_SERVICE_Handle *sh = slc->sh;
786 slc->listen_task = NULL;
789 struct GNUNET_NETWORK_Handle *sock;
790 const struct sockaddr_in *v4;
791 const struct sockaddr_in6 *v6;
792 struct sockaddr_storage sa;
796 addrlen = sizeof(sa);
797 sock = GNUNET_NETWORK_socket_accept (slc->listen_socket,
798 (struct sockaddr *) &sa,
803 do_suspend (sh, SUSPEND_STATE_EMFILE);
804 else if (EAGAIN != errno)
805 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept");
808 switch (sa.ss_family)
811 GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
812 v4 = (const struct sockaddr_in *) &sa;
813 ok = (((NULL == sh->v4_allowed) ||
814 (check_ipv4_listed (sh->v4_allowed, &v4->sin_addr))) &&
815 ((NULL == sh->v4_denied) ||
816 (! check_ipv4_listed (sh->v4_denied, &v4->sin_addr))));
820 GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
821 v6 = (const struct sockaddr_in6 *) &sa;
822 ok = (((NULL == sh->v6_allowed) ||
823 (check_ipv6_listed (sh->v6_allowed, &v6->sin6_addr))) &&
824 ((NULL == sh->v6_denied) ||
825 (! check_ipv6_listed (sh->v6_denied, &v6->sin6_addr))));
829 ok = GNUNET_OK; /* controlled using file-system ACL now */
833 LOG (GNUNET_ERROR_TYPE_WARNING,
834 _ ("Unknown address family %d\n"),
840 LOG (GNUNET_ERROR_TYPE_DEBUG,
841 "Service rejected incoming connection from %s due to policy.\n",
842 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
843 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
846 LOG (GNUNET_ERROR_TYPE_DEBUG,
847 "Service accepted incoming connection from %s.\n",
848 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
849 start_client (slc->sh, sock);
851 if (0 != sh->suspend_state)
854 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
862 * Resume accepting connections from the listen socket.
864 * @param sh service to resume accepting connections.
865 * @param sr reason that is no longer causing the suspension,
866 * or #SUSPEND_STATE_NONE on first startup
869 do_resume (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
871 struct ServiceListenContext *slc;
873 GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
874 sh->suspend_state -= sr;
875 if (SUSPEND_STATE_NONE != sh->suspend_state)
877 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
879 GNUNET_assert (NULL == slc->listen_task);
881 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
890 * First task run by any service. Initializes our shutdown task,
891 * starts the listening operation on our listen sockets and launches
892 * the custom logic of the application service.
894 * @param cls our `struct GNUNET_SERVICE_Handle`
897 service_main (void *cls)
899 struct GNUNET_SERVICE_Handle *sh = cls;
901 if (GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN !=
902 (sh->options & GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK))
903 GNUNET_SCHEDULER_add_shutdown (&service_shutdown, sh);
904 do_resume (sh, SUSPEND_STATE_NONE);
906 if (-1 != sh->ready_confirm_fd)
908 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
909 GNUNET_break (0 == close (sh->ready_confirm_fd));
910 sh->ready_confirm_fd = -1;
913 if (NULL != sh->service_init_cb)
914 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
919 * Parse an IPv4 access control list.
921 * @param ret location where to write the ACL (set)
922 * @param sh service context to use to get the configuration
923 * @param option name of the ACL option to parse
924 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
928 process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret,
929 struct GNUNET_SERVICE_Handle *sh,
934 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
939 GNUNET_break (GNUNET_OK ==
940 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
944 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
946 LOG (GNUNET_ERROR_TYPE_WARNING,
947 _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
952 return GNUNET_SYSERR;
960 * Parse an IPv6 access control list.
962 * @param ret location where to write the ACL (set)
963 * @param sh service context to use to get the configuration
964 * @param option name of the ACL option to parse
965 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
969 process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret,
970 struct GNUNET_SERVICE_Handle *sh,
975 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
980 GNUNET_break (GNUNET_OK ==
981 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
985 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
987 LOG (GNUNET_ERROR_TYPE_WARNING,
988 _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
993 return GNUNET_SYSERR;
1001 * Add the given UNIX domain path as an address to the
1002 * list (as the first entry).
1004 * @param saddrs array to update
1005 * @param saddrlens where to store the address length
1006 * @param unixpath path to add
1009 add_unixpath (struct sockaddr **saddrs,
1010 socklen_t *saddrlens,
1011 const char *unixpath)
1014 struct sockaddr_un *un;
1016 un = GNUNET_new (struct sockaddr_un);
1017 un->sun_family = AF_UNIX;
1018 GNUNET_strlcpy (un->sun_path, unixpath, sizeof(un->sun_path));
1019 #if HAVE_SOCKADDR_UN_SUN_LEN
1020 un->sun_len = (u_char) sizeof(struct sockaddr_un);
1022 *saddrs = (struct sockaddr *) un;
1023 *saddrlens = sizeof(struct sockaddr_un);
1025 /* this function should never be called
1026 * unless AF_UNIX is defined! */
1033 * Get the list of addresses that a server for the given service
1036 * @param service_name name of the service
1037 * @param cfg configuration (which specifies the addresses)
1038 * @param addrs set (call by reference) to an array of pointers to the
1039 * addresses the server should bind to and listen on; the
1040 * array will be NULL-terminated (on success)
1041 * @param addr_lens set (call by reference) to an array of the lengths
1042 * of the respective `struct sockaddr` struct in the @a addrs
1043 * array (on success)
1044 * @return number of addresses found on success,
1045 * #GNUNET_SYSERR if the configuration
1046 * did not specify reasonable finding information or
1047 * if it specified a hostname that could not be resolved;
1048 * #GNUNET_NO if the number of addresses configured is
1049 * zero (in this case, `*addrs` and `*addr_lens` will be
1053 get_server_addresses (const char *service_name,
1054 const struct GNUNET_CONFIGURATION_Handle *cfg,
1055 struct sockaddr ***addrs,
1056 socklen_t **addr_lens)
1059 struct GNUNET_NETWORK_Handle *desc;
1060 unsigned long long port;
1062 struct addrinfo hints;
1063 struct addrinfo *res;
1064 struct addrinfo *pos;
1065 struct addrinfo *next;
1069 struct sockaddr **saddrs;
1070 socklen_t *saddrlens;
1076 disablev6 = GNUNET_NO;
1077 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
1079 GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
1080 disablev6 = GNUNET_YES;
1083 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
1085 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
1090 LOG (GNUNET_ERROR_TYPE_ERROR,
1091 _ ("Require valid port number for service `%s' in configuration!\n"),
1096 LOG (GNUNET_ERROR_TYPE_ERROR,
1097 _ ("Require valid port number for service `%s' in configuration!\n"),
1099 return GNUNET_SYSERR;
1103 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
1105 GNUNET_break (GNUNET_OK ==
1106 GNUNET_CONFIGURATION_get_value_string (cfg,
1117 GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
1118 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg,
1122 (0 < strlen (unixpath)))
1124 /* probe UNIX support */
1125 struct sockaddr_un s_un;
1127 if (strlen (unixpath) >= sizeof(s_un.sun_path))
1129 LOG (GNUNET_ERROR_TYPE_WARNING,
1130 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1132 (unsigned long long) sizeof(s_un.sun_path));
1133 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1134 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1136 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (unixpath))
1137 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mkdir", unixpath);
1139 if (NULL != unixpath)
1141 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1144 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1147 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
1148 GNUNET_free_non_null (hostname);
1149 GNUNET_free (unixpath);
1150 return GNUNET_SYSERR;
1152 LOG (GNUNET_ERROR_TYPE_INFO,
1154 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1157 GNUNET_free (unixpath);
1162 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
1168 if ((0 == port) && (NULL == unixpath))
1170 LOG (GNUNET_ERROR_TYPE_ERROR,
1172 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1174 GNUNET_free_non_null (hostname);
1175 return GNUNET_SYSERR;
1179 saddrs = GNUNET_new_array (2, struct sockaddr *);
1180 saddrlens = GNUNET_new_array (2, socklen_t);
1181 add_unixpath (saddrs, saddrlens, unixpath);
1182 GNUNET_free_non_null (unixpath);
1183 GNUNET_free_non_null (hostname);
1185 *addr_lens = saddrlens;
1189 if (NULL != hostname)
1191 LOG (GNUNET_ERROR_TYPE_DEBUG,
1192 "Resolving `%s' since that is where `%s' will bind to.\n",
1195 memset (&hints, 0, sizeof(struct addrinfo));
1197 hints.ai_family = AF_INET;
1198 hints.ai_protocol = IPPROTO_TCP;
1199 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1202 LOG (GNUNET_ERROR_TYPE_ERROR,
1203 _ ("Failed to resolve `%s': %s\n"),
1205 gai_strerror (ret));
1206 GNUNET_free (hostname);
1207 GNUNET_free_non_null (unixpath);
1208 return GNUNET_SYSERR;
1212 while (NULL != (pos = next))
1214 next = pos->ai_next;
1215 if ((disablev6) && (pos->ai_family == AF_INET6))
1221 LOG (GNUNET_ERROR_TYPE_ERROR,
1222 _ ("Failed to find %saddress for `%s'.\n"),
1223 disablev6 ? "IPv4 " : "",
1226 GNUNET_free (hostname);
1227 GNUNET_free_non_null (unixpath);
1228 return GNUNET_SYSERR;
1231 if (NULL != unixpath)
1233 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1234 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1236 if (NULL != unixpath)
1238 add_unixpath (saddrs, saddrlens, unixpath);
1242 while (NULL != (pos = next))
1244 next = pos->ai_next;
1245 if ((disablev6) && (AF_INET6 == pos->ai_family))
1247 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1248 continue; /* not TCP */
1249 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1250 continue; /* huh? */
1251 LOG (GNUNET_ERROR_TYPE_DEBUG,
1252 "Service `%s' will bind to `%s'\n",
1254 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1255 if (AF_INET == pos->ai_family)
1257 GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1258 saddrlens[i] = pos->ai_addrlen;
1259 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1260 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1261 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1265 GNUNET_assert (AF_INET6 == pos->ai_family);
1266 GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1267 saddrlens[i] = pos->ai_addrlen;
1268 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1269 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1270 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1274 GNUNET_free (hostname);
1280 /* will bind against everything, just set port */
1285 if (NULL != unixpath)
1288 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1289 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1290 if (NULL != unixpath)
1292 add_unixpath (saddrs, saddrlens, unixpath);
1295 saddrlens[i] = sizeof(struct sockaddr_in);
1296 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1297 #if HAVE_SOCKADDR_IN_SIN_LEN
1298 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1300 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1301 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1307 if (NULL != unixpath)
1309 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1310 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1312 if (NULL != unixpath)
1314 add_unixpath (saddrs, saddrlens, unixpath);
1317 saddrlens[i] = sizeof(struct sockaddr_in6);
1318 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1319 #if HAVE_SOCKADDR_IN_SIN_LEN
1320 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1322 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1323 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1325 saddrlens[i] = sizeof(struct sockaddr_in);
1326 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1327 #if HAVE_SOCKADDR_IN_SIN_LEN
1328 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1330 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1331 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1334 GNUNET_free_non_null (unixpath);
1336 *addr_lens = saddrlens;
1342 * Create and initialize a listen socket for the server.
1344 * @param server_addr address to listen on
1345 * @param socklen length of @a server_addr
1346 * @return NULL on error, otherwise the listen socket
1348 static struct GNUNET_NETWORK_Handle *
1349 open_listen_socket (const struct sockaddr *server_addr,
1352 struct GNUNET_NETWORK_Handle *sock;
1356 switch (server_addr->sa_family)
1359 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1362 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1372 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family,
1377 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1382 /* bind the socket */
1384 GNUNET_NETWORK_socket_bind (sock,
1389 if (EADDRINUSE != errno)
1391 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1392 * fail if we already took the port on IPv6; if both IPv4 and
1393 * IPv6 binds fail, then our caller will log using the
1394 * errno preserved in 'eno' */
1396 LOG (GNUNET_ERROR_TYPE_ERROR,
1397 _ ("`%s' failed for port %d (%s).\n"),
1400 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1402 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
1408 LOG (GNUNET_ERROR_TYPE_WARNING,
1409 _ ("`%s' failed for port %d (%s): address already in use\n"),
1412 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1413 else if (AF_UNIX == server_addr->sa_family)
1415 LOG (GNUNET_ERROR_TYPE_WARNING,
1416 _ ("`%s' failed for `%s': address already in use\n"),
1418 GNUNET_a2s (server_addr, socklen));
1421 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
1425 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1427 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "listen");
1428 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
1433 LOG (GNUNET_ERROR_TYPE_DEBUG,
1434 "Server starts to listen on port %u.\n",
1441 * Setup service handle
1443 * Configuration may specify:
1444 * - PORT (where to bind to for TCP)
1445 * - UNIXPATH (where to bind to for UNIX domain sockets)
1446 * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
1447 * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
1448 * - ACCEPT_FROM (only allow connections from specified IPv4 subnets)
1449 * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
1450 * - REJECT_FROM (disallow allow connections from specified IPv4 subnets)
1451 * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
1453 * @param sh service context to initialize
1454 * @return #GNUNET_OK if configuration succeeded
1457 setup_service (struct GNUNET_SERVICE_Handle *sh)
1460 struct GNUNET_NETWORK_Handle **csocks = NULL;
1461 struct GNUNET_NETWORK_Handle **lsocks;
1467 if (GNUNET_CONFIGURATION_have_value (sh->cfg,
1471 if (GNUNET_SYSERR ==
1472 (tolerant = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1476 LOG (GNUNET_ERROR_TYPE_ERROR,
1477 _ ("Specified value for `%s' of service `%s' is invalid\n"),
1480 return GNUNET_SYSERR;
1484 tolerant = GNUNET_NO;
1488 if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1489 (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1490 (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1492 lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
1495 flags = fcntl (3 + cnt, F_GETFD);
1496 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1497 (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1499 LOG (GNUNET_ERROR_TYPE_ERROR,
1501 "Could not access pre-bound socket %u, will try to bind myself\n"),
1502 (unsigned int) 3 + cnt);
1504 while (NULL != lsocks[cnt])
1505 GNUNET_break (GNUNET_OK ==
1506 GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1507 GNUNET_free (lsocks);
1512 unsetenv ("LISTEN_FDS");
1514 if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
1523 /* listen only on inherited sockets if we have any */
1524 for (struct GNUNET_NETWORK_Handle **ls = lsocks; NULL != *ls; ls++)
1526 struct ServiceListenContext *slc;
1528 slc = GNUNET_new (struct ServiceListenContext);
1530 slc->listen_socket = *ls;
1531 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1533 GNUNET_free (lsocks);
1537 struct sockaddr **addrs;
1538 socklen_t *addrlens;
1541 num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
1542 if (GNUNET_SYSERR == num)
1543 return GNUNET_SYSERR;
1545 for (int i = 0; i < num; i++)
1547 struct ServiceListenContext *slc;
1549 slc = GNUNET_new (struct ServiceListenContext);
1551 slc->listen_socket = open_listen_socket (addrs[i], addrlens[i]);
1552 GNUNET_free (addrs[i]);
1553 if (NULL == slc->listen_socket)
1555 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
1559 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1561 GNUNET_free_non_null (addrlens);
1562 GNUNET_free_non_null (addrs);
1563 if ((0 != num) && (NULL == sh->slc_head))
1565 /* All attempts to bind failed, hard failure */
1567 GNUNET_ERROR_TYPE_ERROR,
1569 "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1570 GNUNET_free_non_null (csocks);
1571 return GNUNET_SYSERR;
1576 /* close inherited sockets to signal parent that we are ready */
1577 for (struct GNUNET_NETWORK_Handle **ls = csocks; NULL != *ls; ls++)
1578 GNUNET_NETWORK_socket_close (*ls);
1579 GNUNET_free (csocks);
1581 sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1582 sh->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1585 sh->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1588 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1589 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1590 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1591 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1597 * Get the name of the user that'll be used
1598 * to provide the service.
1600 * @param sh service context
1601 * @return value of the 'USERNAME' option
1604 get_user_name (struct GNUNET_SERVICE_Handle *sh)
1608 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1620 * @param sh service context
1621 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1624 set_user_id (struct GNUNET_SERVICE_Handle *sh)
1628 if (NULL == (user = get_user_name (sh)))
1629 return GNUNET_OK; /* keep */
1634 pws = getpwnam (user);
1637 LOG (GNUNET_ERROR_TYPE_ERROR,
1638 _ ("Cannot obtain information about user `%s': %s\n"),
1640 errno == 0 ? _ ("No such user") : strerror (errno));
1642 return GNUNET_SYSERR;
1644 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1646 (0 != initgroups (user, pws->pw_gid)) ||
1648 (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1650 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1651 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1653 LOG (GNUNET_ERROR_TYPE_ERROR,
1654 _ ("Cannot change user/group to `%s': %s\n"),
1658 return GNUNET_SYSERR;
1668 * Get the name of the file where we will
1669 * write the PID of the service.
1671 * @param sh service context
1672 * @return name of the file for the process ID
1675 get_pid_file_name (struct GNUNET_SERVICE_Handle *sh)
1679 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1689 * Delete the PID file that was created by our parent.
1691 * @param sh service context
1694 pid_file_delete (struct GNUNET_SERVICE_Handle *sh)
1696 char *pif = get_pid_file_name (sh);
1699 return; /* no PID file */
1700 if (0 != unlink (pif))
1701 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", pif);
1707 * Detach from terminal.
1709 * @param sh service context
1710 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1713 detach_terminal (struct GNUNET_SERVICE_Handle *sh)
1719 if (0 != pipe (filedes))
1721 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe");
1722 return GNUNET_SYSERR;
1727 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
1728 return GNUNET_SYSERR;
1735 GNUNET_break (0 == close (filedes[1]));
1737 if (1 != read (filedes[0], &c, sizeof(char)))
1738 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "read");
1746 LOG (GNUNET_ERROR_TYPE_INFO,
1747 _ ("Service process failed to initialize\n"));
1751 LOG (GNUNET_ERROR_TYPE_INFO,
1752 _ ("Service process could not initialize server function\n"));
1756 LOG (GNUNET_ERROR_TYPE_INFO,
1757 _ ("Service process failed to report status\n"));
1760 exit (1); /* child reported error */
1762 GNUNET_break (0 == close (0));
1763 GNUNET_break (0 == close (1));
1764 GNUNET_break (0 == close (filedes[0]));
1765 nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1767 return GNUNET_SYSERR;
1768 /* set stdin/stdout to /dev/null */
1769 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1771 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
1772 (void) close (nullfd);
1773 return GNUNET_SYSERR;
1775 (void) close (nullfd);
1776 /* Detach from controlling terminal */
1779 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid");
1780 sh->ready_confirm_fd = filedes[1];
1787 * Tear down the service, closing the listen sockets and
1790 * @param sh handle to the service to tear down.
1793 teardown_service (struct GNUNET_SERVICE_Handle *sh)
1795 struct ServiceListenContext *slc;
1797 GNUNET_free_non_null (sh->v4_denied);
1798 GNUNET_free_non_null (sh->v6_denied);
1799 GNUNET_free_non_null (sh->v4_allowed);
1800 GNUNET_free_non_null (sh->v6_allowed);
1801 while (NULL != (slc = sh->slc_head))
1803 GNUNET_CONTAINER_DLL_remove (sh->slc_head, sh->slc_tail, slc);
1804 if (NULL != slc->listen_task)
1805 GNUNET_SCHEDULER_cancel (slc->listen_task);
1806 GNUNET_break (GNUNET_OK ==
1807 GNUNET_NETWORK_socket_close (slc->listen_socket));
1814 * Function to return link to AGPL source upon request.
1816 * @param cls closure with the identification of the client
1817 * @param msg AGPL request
1820 return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
1822 struct GNUNET_SERVICE_Client *client = cls;
1823 struct GNUNET_MQ_Handle *mq;
1824 struct GNUNET_MQ_Envelope *env;
1825 struct GNUNET_MessageHeader *res;
1829 slen = strlen (GNUNET_AGPL_URL) + 1;
1830 env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen);
1831 memcpy (&res[1], GNUNET_AGPL_URL, slen);
1832 mq = GNUNET_SERVICE_client_get_mq (client);
1833 GNUNET_MQ_send (mq, env);
1834 GNUNET_SERVICE_client_continue (client);
1839 * Low-level function to start a service if the scheduler
1840 * is already running. Should only be used directly in
1843 * The function will launch the service with the name @a service_name
1844 * using the @a service_options to configure its shutdown
1845 * behavior. When clients connect or disconnect, the respective
1846 * @a connect_cb or @a disconnect_cb functions will be called. For
1847 * messages received from the clients, the respective @a handlers will
1848 * be invoked; for the closure of the handlers we use the return value
1849 * from the @a connect_cb invocation of the respective client.
1851 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1852 * message to receive further messages from this client. If
1853 * #GNUNET_SERVICE_client_continue() is not called within a short
1854 * time, a warning will be logged. If delays are expected, services
1855 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1856 * disable the warning.
1858 * Clients sending invalid messages (based on @a handlers) will be
1859 * dropped. Additionally, clients can be dropped at any time using
1860 * #GNUNET_SERVICE_client_drop().
1862 * The service must be stopped using #GNUNET_SERVICE_stop().
1864 * @param service_name name of the service to run
1865 * @param cfg configuration to use
1866 * @param connect_cb function to call whenever a client connects
1867 * @param disconnect_cb function to call whenever a client disconnects
1868 * @param cls closure argument for @a connect_cb and @a disconnect_cb
1869 * @param handlers NULL-terminated array of message handlers for the service,
1870 * the closure will be set to the value returned by
1871 * the @a connect_cb for the respective connection
1872 * @return NULL on error
1874 struct GNUNET_SERVICE_Handle *
1875 GNUNET_SERVICE_start (const char *service_name,
1876 const struct GNUNET_CONFIGURATION_Handle *cfg,
1877 GNUNET_SERVICE_ConnectHandler connect_cb,
1878 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1880 const struct GNUNET_MQ_MessageHandler *handlers)
1882 struct GNUNET_SERVICE_Handle *sh;
1884 sh = GNUNET_new (struct GNUNET_SERVICE_Handle);
1885 sh->service_name = service_name;
1887 sh->connect_cb = connect_cb;
1888 sh->disconnect_cb = disconnect_cb;
1890 sh->handlers = GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
1891 if (GNUNET_OK != setup_service (sh))
1893 GNUNET_free_non_null (sh->handlers);
1897 do_resume (sh, SUSPEND_STATE_NONE);
1903 * Stops a service that was started with #GNUNET_SERVICE_start().
1905 * @param srv service to stop
1908 GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv)
1910 struct GNUNET_SERVICE_Client *client;
1912 GNUNET_SERVICE_suspend (srv);
1913 while (NULL != (client = srv->clients_head))
1914 GNUNET_SERVICE_client_drop (client);
1915 teardown_service (srv);
1916 GNUNET_free_non_null (srv->handlers);
1922 * Creates the "main" function for a GNUnet service. You
1923 * should almost always use the #GNUNET_SERVICE_MAIN macro
1924 * instead of calling this function directly (except
1925 * for ARM, which should call this function directly).
1927 * The function will launch the service with the name @a service_name
1928 * using the @a service_options to configure its shutdown
1929 * behavior. Once the service is ready, the @a init_cb will be called
1930 * for service-specific initialization. @a init_cb will be given the
1931 * service handler which can be used to control the service's
1932 * availability. When clients connect or disconnect, the respective
1933 * @a connect_cb or @a disconnect_cb functions will be called. For
1934 * messages received from the clients, the respective @a handlers will
1935 * be invoked; for the closure of the handlers we use the return value
1936 * from the @a connect_cb invocation of the respective client.
1938 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1939 * message to receive further messages from this client. If
1940 * #GNUNET_SERVICE_client_continue() is not called within a short
1941 * time, a warning will be logged. If delays are expected, services
1942 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1943 * disable the warning.
1945 * Clients sending invalid messages (based on @a handlers) will be
1946 * dropped. Additionally, clients can be dropped at any time using
1947 * #GNUNET_SERVICE_client_drop().
1949 * @param argc number of command-line arguments in @a argv
1950 * @param argv array of command-line arguments
1951 * @param service_name name of the service to run
1952 * @param options options controlling shutdown of the service
1953 * @param service_init_cb function to call once the service is ready
1954 * @param connect_cb function to call whenever a client connects
1955 * @param disconnect_cb function to call whenever a client disconnects
1956 * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
1957 * @param handlers NULL-terminated array of message handlers for the service,
1958 * the closure will be set to the value returned by
1959 * the @a connect_cb for the respective connection
1960 * @return 0 on success, non-zero on error
1963 GNUNET_SERVICE_run_ (int argc,
1965 const char *service_name,
1966 enum GNUNET_SERVICE_Options options,
1967 GNUNET_SERVICE_InitCallback service_init_cb,
1968 GNUNET_SERVICE_ConnectHandler connect_cb,
1969 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1971 const struct GNUNET_MQ_MessageHandler *handlers)
1973 struct GNUNET_SERVICE_Handle sh;
1979 char *opt_cfg_filename;
1984 unsigned long long skew_offset;
1985 unsigned long long skew_variance;
1986 long long clock_offset;
1987 struct GNUNET_CONFIGURATION_Handle *cfg;
1990 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
1991 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1992 GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
1993 GNUNET_GETOPT_option_flag ('d',
1996 "do daemonize (detach from terminal)"),
1998 GNUNET_GETOPT_option_help (NULL),
1999 GNUNET_GETOPT_option_loglevel (&loglev),
2000 GNUNET_GETOPT_option_logfile (&logfile),
2001 GNUNET_GETOPT_option_version (pd->version),
2002 GNUNET_GETOPT_OPTION_END
2006 memset (&sh, 0, sizeof(sh));
2007 xdg = getenv ("XDG_CONFIG_HOME");
2009 GNUNET_asprintf (&cfg_filename,
2015 cfg_filename = GNUNET_strdup (pd->user_config_file);
2016 sh.ready_confirm_fd = -1;
2017 sh.options = options;
2018 sh.cfg = cfg = GNUNET_CONFIGURATION_create ();
2019 sh.service_init_cb = service_init_cb;
2020 sh.connect_cb = connect_cb;
2021 sh.disconnect_cb = disconnect_cb;
2023 sh.handlers = GNUNET_MQ_copy_handlers (handlers);
2024 sh.service_name = service_name;
2026 /* setup subsystems */
2029 opt_cfg_filename = NULL;
2032 if (NULL != pd->gettext_domain)
2034 setlocale (LC_ALL, "");
2035 path = (NULL == pd->gettext_path) ?
2036 GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LOCALEDIR) :
2037 GNUNET_strdup (pd->gettext_path);
2040 bindtextdomain (pd->gettext_domain, path);
2043 textdomain (pd->gettext_domain);
2046 ret = GNUNET_GETOPT_run (service_name,
2050 if (GNUNET_SYSERR == ret)
2052 if (GNUNET_NO == ret)
2057 if (GNUNET_OK != GNUNET_log_setup (service_name,
2064 if (NULL != opt_cfg_filename)
2066 if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) ||
2067 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename)))
2069 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2070 _ ("Malformed configuration file `%s', exit ...\n"),
2077 if (GNUNET_YES == GNUNET_DISK_file_test (cfg_filename))
2079 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_filename))
2081 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2082 _ ("Malformed configuration file `%s', exit ...\n"),
2089 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL))
2091 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2092 _ ("Malformed configuration, exit ...\n"));
2097 if (GNUNET_OK != setup_service (&sh))
2099 if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sh)))
2104 if (GNUNET_OK != set_user_id (&sh))
2106 LOG (GNUNET_ERROR_TYPE_DEBUG,
2107 "Service `%s' runs with configuration from `%s'\n",
2109 (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename);
2110 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sh.cfg,
2114 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sh.cfg,
2119 clock_offset = skew_offset - skew_variance;
2120 GNUNET_TIME_set_offset (clock_offset);
2121 LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
2123 GNUNET_RESOLVER_connect (sh.cfg);
2125 /* actually run service */
2127 GNUNET_SCHEDULER_run (&service_main, &sh);
2129 if (1 == do_daemonize)
2130 pid_file_delete (&sh);
2133 if (-1 != sh.ready_confirm_fd)
2135 if (1 != write (sh.ready_confirm_fd, err ? "I" : "S", 1))
2136 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
2137 GNUNET_break (0 == close (sh.ready_confirm_fd));
2143 if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (sh.cfg,
2146 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (sh.cfg,
2154 GAUGER (service_name, counter, mi.usmblks, "blocks");
2155 GNUNET_free (counter);
2159 teardown_service (&sh);
2160 GNUNET_free_non_null (sh.handlers);
2161 GNUNET_SPEEDUP_stop_ ();
2162 GNUNET_CONFIGURATION_destroy (cfg);
2163 GNUNET_free_non_null (logfile);
2164 GNUNET_free_non_null (loglev);
2165 GNUNET_free (cfg_filename);
2166 GNUNET_free_non_null (opt_cfg_filename);
2168 return err ? GNUNET_SYSERR : sh.ret;
2173 * Suspend accepting connections from the listen socket temporarily.
2174 * Resume activity using #GNUNET_SERVICE_resume.
2176 * @param sh service to stop accepting connections.
2179 GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
2181 do_suspend (sh, SUSPEND_STATE_APP);
2186 * Resume accepting connections from the listen socket.
2188 * @param sh service to resume accepting connections.
2191 GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
2193 do_resume (sh, SUSPEND_STATE_APP);
2198 * Task run to resume receiving data from the client after
2199 * the client called #GNUNET_SERVICE_client_continue().
2201 * @param cls our `struct GNUNET_SERVICE_Client`
2204 resume_client_receive (void *cls)
2206 struct GNUNET_SERVICE_Client *c = cls;
2209 c->recv_task = NULL;
2210 /* first, check if there is still something in the buffer */
2211 ret = GNUNET_MST_next (c->mst, GNUNET_YES);
2212 if (GNUNET_SYSERR == ret)
2214 if (NULL == c->drop_task)
2215 GNUNET_SERVICE_client_drop (c);
2218 if (GNUNET_NO == ret)
2219 return; /* done processing, wait for more later */
2220 GNUNET_assert (GNUNET_OK == ret);
2221 if (GNUNET_YES == c->needs_continue)
2222 return; /* #GNUNET_MST_next() did give a message to the client */
2223 /* need to receive more data from the network first */
2224 if (NULL != c->recv_task)
2226 c->recv_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2228 &service_client_recv,
2234 * Continue receiving further messages from the given client.
2235 * Must be called after each message received.
2237 * @param c the client to continue receiving from
2240 GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
2242 GNUNET_assert (NULL == c->drop_task);
2243 GNUNET_assert (GNUNET_YES == c->needs_continue);
2244 GNUNET_assert (NULL == c->recv_task);
2245 c->needs_continue = GNUNET_NO;
2246 if (NULL != c->warn_task)
2248 GNUNET_SCHEDULER_cancel (c->warn_task);
2249 c->warn_task = NULL;
2251 c->recv_task = GNUNET_SCHEDULER_add_now (&resume_client_receive, c);
2256 * Disable the warning the server issues if a message is not
2257 * acknowledged in a timely fashion. Use this call if a client is
2258 * intentionally delayed for a while. Only applies to the current
2261 * @param c client for which to disable the warning
2264 GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
2266 GNUNET_break (NULL != c->warn_task);
2267 if (NULL != c->warn_task)
2269 GNUNET_SCHEDULER_cancel (c->warn_task);
2270 c->warn_task = NULL;
2276 * Asynchronously finish dropping the client.
2278 * @param cls the `struct GNUNET_SERVICE_Client`.
2281 finish_client_drop (void *cls)
2283 struct GNUNET_SERVICE_Client *c = cls;
2284 struct GNUNET_SERVICE_Handle *sh = c->sh;
2286 c->drop_task = NULL;
2287 GNUNET_assert (NULL == c->send_task);
2288 GNUNET_assert (NULL == c->recv_task);
2289 GNUNET_assert (NULL == c->warn_task);
2290 GNUNET_MST_destroy (c->mst);
2291 GNUNET_MQ_destroy (c->mq);
2292 if (GNUNET_NO == c->persist)
2294 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (c->sock));
2295 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
2296 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
2297 do_resume (sh, SUSPEND_STATE_EMFILE);
2301 GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
2304 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
2305 (GNUNET_NO == have_non_monitor_clients (sh)))
2306 GNUNET_SERVICE_shutdown (sh);
2311 * Ask the server to disconnect from the given client. This is the
2312 * same as returning #GNUNET_SYSERR within the check procedure when
2313 * handling a message, wexcept that it allows dropping of a client even
2314 * when not handling a message from that client. The `disconnect_cb`
2315 * will be called on @a c even if the application closes the connection
2316 * using this function.
2318 * @param c client to disconnect now
2321 GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2323 struct GNUNET_SERVICE_Handle *sh = c->sh;
2325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2326 "Client dropped: %p (MQ: %p)\n",
2331 void *backtrace_array[MAX_TRACE_DEPTH];
2332 int num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH);
2333 char **backtrace_strings =
2334 backtrace_symbols (backtrace_array, t->num_backtrace_strings);
2335 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2336 LOG (GNUNET_ERROR_TYPE_DEBUG,
2337 "client drop trace %u: %s\n",
2339 backtrace_strings[i]);
2342 if (NULL != c->drop_task)
2344 /* asked to drop twice! */
2348 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
2351 if (NULL != sh->disconnect_cb)
2352 sh->disconnect_cb (sh->cb_cls,
2355 if (NULL != c->warn_task)
2357 GNUNET_SCHEDULER_cancel (c->warn_task);
2358 c->warn_task = NULL;
2360 if (NULL != c->recv_task)
2362 GNUNET_SCHEDULER_cancel (c->recv_task);
2363 c->recv_task = NULL;
2365 if (NULL != c->send_task)
2367 GNUNET_SCHEDULER_cancel (c->send_task);
2368 c->send_task = NULL;
2370 c->drop_task = GNUNET_SCHEDULER_add_now (&finish_client_drop, c);
2375 * Explicitly stops the service.
2377 * @param sh server to shutdown
2380 GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
2382 struct GNUNET_SERVICE_Client *client;
2384 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
2385 do_suspend (sh, SUSPEND_STATE_SHUTDOWN);
2386 while (NULL != (client = sh->clients_head))
2387 GNUNET_SERVICE_client_drop (client);
2392 * Set the 'monitor' flag on this client. Clients which have been
2393 * marked as 'monitors' won't prevent the server from shutting down
2394 * once #GNUNET_SERVICE_stop_listening() has been invoked. The idea is
2395 * that for "normal" clients we likely want to allow them to process
2396 * their requests; however, monitor-clients are likely to 'never'
2397 * disconnect during shutdown and thus will not be considered when
2398 * determining if the server should continue to exist after
2399 * shutdown has been triggered.
2401 * @param c client to mark as a monitor
2404 GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
2406 c->is_monitor = GNUNET_YES;
2407 if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) &&
2408 (GNUNET_NO == have_non_monitor_clients (c->sh))))
2409 GNUNET_SERVICE_shutdown (c->sh);
2414 * Set the persist option on this client. Indicates that the
2415 * underlying socket or fd should never really be closed. Used for
2416 * indicating process death.
2418 * @param c client to persist the socket (never to be closed)
2421 GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
2423 c->persist = GNUNET_YES;
2428 * Obtain the message queue of @a c. Convenience function.
2430 * @param c the client to continue receiving from
2431 * @return the message queue of @a c
2433 struct GNUNET_MQ_Handle *
2434 GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c)
2440 /* end of service.c */