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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file util/service_new.c
23 * @brief functions related to starting services (redesign)
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_constants.h"
30 #include "gnunet_resolver_service.h"
34 * Information the service tracks per listen operation.
36 struct ServiceListenContext
42 struct ServiceListenContext *next;
47 struct ServiceListenContext *prev;
50 * Service this listen context belongs to.
52 struct GNUNET_SERVICE_Handle *sh;
55 * Socket we are listening on.
57 struct GNUNET_NETWORK_Handle *listen_socket;
60 * Task scheduled to do the listening.
62 struct GNUNET_SCHEDULER_Task *listen_task;
68 * Handle to a service.
70 struct GNUNET_SERVICE_Handle
75 const struct GNUNET_CONFIGURATION_Handle *cfg;
78 * Name of our service.
80 const char *service_name;
83 * Main service-specific task to run.
85 GNUNET_SERVICE_InitCallback service_init_cb;
88 * Function to call when clients connect.
90 GNUNET_SERVICE_ConnectHandler connect_cb;
93 * Function to call when clients disconnect / are disconnected.
95 GNUNET_SERVICE_DisconnectHandler disconnect_cb;
98 * Closure for @e service_init_cb, @e connect_cb, @e disconnect_cb.
103 * DLL of listen sockets used to accept new connections.
105 struct ServiceListenContext *slc_head;
108 * DLL of listen sockets used to accept new connections.
110 struct ServiceListenContext *slc_tail;
113 * Our clients, kept in a DLL.
115 struct GNUNET_SERVICE_Client *clients_head;
118 * Our clients, kept in a DLL.
120 struct GNUNET_SERVICE_Client *clients_tail;
123 * Message handlers to use for all clients.
125 const struct GNUNET_MQ_MessageHandler *handlers;
128 * Closure for @e task.
133 * IPv4 addresses that are not allowed to connect.
135 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
138 * IPv6 addresses that are not allowed to connect.
140 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
143 * IPv4 addresses that are allowed to connect (if not
144 * set, all are allowed).
146 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
149 * IPv6 addresses that are allowed to connect (if not
150 * set, all are allowed).
152 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
155 * Do we require a matching UID for UNIX domain socket connections?
156 * #GNUNET_NO means that the UID does not have to match (however,
157 * @e match_gid may still impose other access control checks).
162 * Do we require a matching GID for UNIX domain socket connections?
163 * Ignored if @e match_uid is #GNUNET_YES. Note that this is about
164 * checking that the client's UID is in our group OR that the
165 * client's GID is our GID. If both "match_gid" and @e match_uid are
166 * #GNUNET_NO, all users on the local system have access.
171 * Set to #GNUNET_YES if we got a shutdown signal and terminate
172 * the service if #have_non_monitor_clients() returns #GNUNET_YES.
179 enum GNUNET_SERVICE_Options options;
182 * If we are daemonizing, this FD is set to the
183 * pipe to the parent. Send '.' if we started
184 * ok, '!' if not. -1 if we are not daemonizing.
186 int ready_confirm_fd;
189 * Overall success/failure of the service start.
194 * Inherited listening sockets, only
195 * used during initialization.
196 * FIXME: remove from struct
198 struct GNUNET_NETWORK_Handle **lsocks;
201 * If GNUNET_YES, consider unknown message types an error where the
202 * client is disconnected.
210 * Handle to a client that is connected to a service.
212 struct GNUNET_SERVICE_Client
218 struct GNUNET_SERVICE_Client *next;
223 struct GNUNET_SERVICE_Client *prev;
226 * Service that this client belongs to.
228 struct GNUNET_SERVICE_Handle *sh;
231 * Socket of this client.
233 struct GNUNET_NETWORK_Handle *sock;
236 * Message queue for the client.
238 struct GNUNET_MQ_Handle *mq;
241 * Tokenizer we use for processing incoming data.
243 struct GNUNET_SERVER_MessageStreamTokenizer *mst;
246 * Task that warns about missing calls to
247 * #GNUNET_SERVICE_client_continue().
249 struct GNUNET_SCHEDULER_Task *warn_task;
252 * Task that receives data from the client to
253 * pass it to the handlers.
255 struct GNUNET_SCHEDULER_Task *recv_task;
258 * Task that transmit data to the client.
260 struct GNUNET_SCHEDULER_Task *send_task;
263 * User context value, value returned from
264 * the connect callback.
269 * Persist the file handle for this client no matter what happens,
270 * force the OS to close once the process actually dies. Should only
271 * be used in special cases!
276 * Is this client a 'monitor' client that should not be counted
277 * when deciding on destroying the server during soft shutdown?
278 * (see also #GNUNET_SERVICE_start)
283 * Type of last message processed (for warn_no_receive_done).
290 * Check if any of the clients we have left are unrelated to
293 * @param sh service to check clients for
294 * @return #GNUNET_YES if we have non-monitoring clients left
297 have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
299 struct GNUNET_SERVICE_Client *client;
301 for (client = sh->clients_head;NULL != client; client = client->next)
303 if (client->is_monitor)
312 * Shutdown task triggered when a service should be terminated.
313 * This considers active clients and the service options to see
314 * how this specific service is to be terminated, and depending
315 * on this proceeds with the shutdown logic.
317 * @param cls our `struct GNUNET_SERVICE_Handle`
320 service_shutdown (void *cls)
322 struct GNUNET_SERVICE_Handle *sh = cls;
323 struct GNUNET_SERVICE_Client *client;
328 case GNUNET_SERVICE_OPTION_NONE:
329 GNUNET_SERVICE_shutdown (sh);
331 case GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN:
332 /* This task should never be run if we are using
333 the manual shutdown. */
336 case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN:
337 sh->got_shutdown = GNUNET_YES;
338 GNUNET_SERVICE_suspend (sh);
339 if (GNUNET_NO == have_non_monitor_clients (sh))
340 GNUNET_SERVICE_shutdown (sh);
347 * First task run by any service. Initializes our shutdown task,
348 * starts the listening operation on our listen sockets and launches
349 * the custom logic of the application service.
351 * @param cls our `struct GNUNET_SERVICE_Handle`
354 service_main (void *cls)
356 struct GNUNET_SERVICE_Handle *sh = cls;
358 if (GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN != sh->options)
359 GNUNET_SCHEDULER_add_shutdown (&service_shutdown,
361 GNUNET_SERVICE_resume (sh);
362 sh->service_init_cb (sh->cb_cls,
369 * Parse an IPv4 access control list.
371 * @param ret location where to write the ACL (set)
372 * @param sh service context to use to get the configuration
373 * @param option name of the ACL option to parse
374 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
378 process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret,
379 struct GNUNET_SERVICE_Handle *sh,
384 if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
389 GNUNET_break (GNUNET_OK ==
390 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
393 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
395 LOG (GNUNET_ERROR_TYPE_WARNING,
396 _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
397 opt, sh->service_name, option);
399 return GNUNET_SYSERR;
407 * Parse an IPv6 access control list.
409 * @param ret location where to write the ACL (set)
410 * @param sh service context to use to get the configuration
411 * @param option name of the ACL option to parse
412 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
416 process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret,
417 struct GNUNET_SERVICE_Handle *sh,
422 if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
427 GNUNET_break (GNUNET_OK ==
428 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
431 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
433 LOG (GNUNET_ERROR_TYPE_WARNING,
434 _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
435 opt, sh->service_name, option);
437 return GNUNET_SYSERR;
445 * Get the list of addresses that a server for the given service
448 * @param service_name name of the service
449 * @param cfg configuration (which specifies the addresses)
450 * @param addrs set (call by reference) to an array of pointers to the
451 * addresses the server should bind to and listen on; the
452 * array will be NULL-terminated (on success)
453 * @param addr_lens set (call by reference) to an array of the lengths
454 * of the respective `struct sockaddr` struct in the @a addrs
456 * @return number of addresses found on success,
457 * #GNUNET_SYSERR if the configuration
458 * did not specify reasonable finding information or
459 * if it specified a hostname that could not be resolved;
460 * #GNUNET_NO if the number of addresses configured is
461 * zero (in this case, `*addrs` and `*addr_lens` will be
465 get_server_addresses (const char *service_name,
466 const struct GNUNET_CONFIGURATION_Handle *cfg,
467 struct sockaddr ***addrs,
468 socklen_t ** addr_lens)
471 struct GNUNET_NETWORK_Handle *desc;
472 unsigned long long port;
474 struct addrinfo hints;
475 struct addrinfo *res;
476 struct addrinfo *pos;
477 struct addrinfo *next;
482 struct sockaddr **saddrs;
483 socklen_t *saddrlens;
489 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
493 GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
494 return GNUNET_SYSERR;
497 disablev6 = GNUNET_NO;
501 /* probe IPv6 support */
502 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
505 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
508 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
509 return GNUNET_SYSERR;
511 LOG (GNUNET_ERROR_TYPE_INFO,
512 _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
513 service_name, STRERROR (errno));
514 disablev6 = GNUNET_YES;
518 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
524 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
527 GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
530 LOG (GNUNET_ERROR_TYPE_ERROR,
531 _("Require valid port number for service `%s' in configuration!\n"),
536 LOG (GNUNET_ERROR_TYPE_ERROR,
537 _("Require valid port number for service `%s' in configuration!\n"),
539 return GNUNET_SYSERR;
543 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
545 GNUNET_break (GNUNET_OK ==
546 GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
547 "BINDTO", &hostname));
553 abstract = GNUNET_NO;
556 GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
558 GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
560 (0 < strlen (unixpath)))
562 /* probe UNIX support */
563 struct sockaddr_un s_un;
565 if (strlen (unixpath) >= sizeof (s_un.sun_path))
567 LOG (GNUNET_ERROR_TYPE_WARNING,
568 _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
569 (unsigned long long) sizeof (s_un.sun_path));
570 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
571 LOG (GNUNET_ERROR_TYPE_INFO,
572 _("Using `%s' instead\n"),
576 abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
578 "USE_ABSTRACT_SOCKETS");
579 if (GNUNET_SYSERR == abstract)
580 abstract = GNUNET_NO;
582 if ((GNUNET_YES != abstract)
584 GNUNET_DISK_directory_create_for_file (unixpath)))
585 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
589 if (NULL != unixpath)
591 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
594 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
597 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
598 GNUNET_free_non_null (hostname);
599 GNUNET_free (unixpath);
600 return GNUNET_SYSERR;
602 LOG (GNUNET_ERROR_TYPE_INFO,
603 _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
606 GNUNET_free (unixpath);
611 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
617 if ((0 == port) && (NULL == unixpath))
619 LOG (GNUNET_ERROR_TYPE_ERROR,
620 _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
622 GNUNET_free_non_null (hostname);
623 return GNUNET_SYSERR;
627 saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
628 saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
629 add_unixpath (saddrs, saddrlens, unixpath, abstract);
630 GNUNET_free_non_null (unixpath);
631 GNUNET_free_non_null (hostname);
633 *addr_lens = saddrlens;
637 if (NULL != hostname)
639 LOG (GNUNET_ERROR_TYPE_DEBUG,
640 "Resolving `%s' since that is where `%s' will bind to.\n",
643 memset (&hints, 0, sizeof (struct addrinfo));
645 hints.ai_family = AF_INET;
646 hints.ai_protocol = IPPROTO_TCP;
647 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
650 LOG (GNUNET_ERROR_TYPE_ERROR,
651 _("Failed to resolve `%s': %s\n"),
654 GNUNET_free (hostname);
655 GNUNET_free_non_null (unixpath);
656 return GNUNET_SYSERR;
660 while (NULL != (pos = next))
663 if ((disablev6) && (pos->ai_family == AF_INET6))
669 LOG (GNUNET_ERROR_TYPE_ERROR,
670 _("Failed to find %saddress for `%s'.\n"),
671 disablev6 ? "IPv4 " : "",
674 GNUNET_free (hostname);
675 GNUNET_free_non_null (unixpath);
676 return GNUNET_SYSERR;
679 if (NULL != unixpath)
681 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
682 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
684 if (NULL != unixpath)
686 add_unixpath (saddrs, saddrlens, unixpath, abstract);
690 while (NULL != (pos = next))
693 if ((disablev6) && (AF_INET6 == pos->ai_family))
695 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
696 continue; /* not TCP */
697 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
699 LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
700 service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
701 if (AF_INET == pos->ai_family)
703 GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
704 saddrlens[i] = pos->ai_addrlen;
705 saddrs[i] = GNUNET_malloc (saddrlens[i]);
706 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
707 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
711 GNUNET_assert (AF_INET6 == pos->ai_family);
712 GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
713 saddrlens[i] = pos->ai_addrlen;
714 saddrs[i] = GNUNET_malloc (saddrlens[i]);
715 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
716 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
720 GNUNET_free (hostname);
726 /* will bind against everything, just set port */
731 if (NULL != unixpath)
734 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
735 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
736 if (NULL != unixpath)
738 add_unixpath (saddrs, saddrlens, unixpath, abstract);
741 saddrlens[i] = sizeof (struct sockaddr_in);
742 saddrs[i] = GNUNET_malloc (saddrlens[i]);
743 #if HAVE_SOCKADDR_IN_SIN_LEN
744 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
746 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
747 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
753 if (NULL != unixpath)
755 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
756 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
758 if (NULL != unixpath)
760 add_unixpath (saddrs, saddrlens, unixpath, abstract);
763 saddrlens[i] = sizeof (struct sockaddr_in6);
764 saddrs[i] = GNUNET_malloc (saddrlens[i]);
765 #if HAVE_SOCKADDR_IN_SIN_LEN
766 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
768 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
769 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
771 saddrlens[i] = sizeof (struct sockaddr_in);
772 saddrs[i] = GNUNET_malloc (saddrlens[i]);
773 #if HAVE_SOCKADDR_IN_SIN_LEN
774 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
776 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
777 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
780 GNUNET_free_non_null (unixpath);
782 *addr_lens = saddrlens;
789 * Read listen sockets from the parent process (ARM).
791 * @param sh service context to initialize
792 * @return #GNUNET_YES if ok, #GNUNET_NO if not ok (must bind yourself),
793 * and #GNUNET_SYSERR on error.
796 receive_sockets_from_parent (struct GNUNET_SERVICE_Handle *sh)
804 env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
805 if ((NULL == env_buf) || (strlen (env_buf) <= 0))
807 /* Using W32 API directly here, because this pipe will
808 * never be used outside of this function, and it's just too much of a bother
809 * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
811 lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
812 if ( (0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
821 ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
822 if ((0 == ret) || (sizeof (count) != rd) || (0 == count))
825 GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1));
828 for (i = 0; i < count; i++)
830 WSAPROTOCOL_INFOA pi;
834 ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
835 if ( (0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size) )
837 ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
838 if ( (0 == ret) || (sizeof (pi) != rd))
840 s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED);
841 sh->lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
842 if (NULL == sh->lsocks[i])
844 else if (i == count - 1)
849 sh->lsocks[count] = NULL;
854 CloseHandle (lsocks_pipe);
858 LOG (GNUNET_ERROR_TYPE_ERROR,
859 _("Could not access a pre-bound socket, will try to bind myself\n"));
860 for (i = 0; (i < count) && (NULL != sh->lsocks[i]); i++)
861 GNUNET_break (0 == GNUNET_NETWORK_socket_close (sh->lsocks[i]));
862 GNUNET_free_non_null (sh->lsocks);
872 * Create and initialize a listen socket for the server.
874 * @param server_addr address to listen on
875 * @param socklen length of @a server_addr
876 * @return NULL on error, otherwise the listen socket
878 static struct GNUNET_NETWORK_Handle *
879 open_listen_socket (const struct sockaddr *server_addr,
882 struct GNUNET_NETWORK_Handle *sock;
886 switch (server_addr->sa_family)
889 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
892 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
902 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0);
905 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
909 /* bind the socket */
910 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen))
913 if (EADDRINUSE != errno)
915 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
916 * fail if we already took the port on IPv6; if both IPv4 and
917 * IPv6 binds fail, then our caller will log using the
918 * errno preserved in 'eno' */
919 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
922 LOG (GNUNET_ERROR_TYPE_ERROR,
923 _("`%s' failed for port %d (%s).\n"),
926 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
932 LOG (GNUNET_ERROR_TYPE_WARNING,
933 _("`%s' failed for port %d (%s): address already in use\n"),
935 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
936 else if (AF_UNIX == server_addr->sa_family)
938 LOG (GNUNET_ERROR_TYPE_WARNING,
939 _("`%s' failed for `%s': address already in use\n"),
941 GNUNET_a2s (server_addr, socklen));
944 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
948 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
950 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
952 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
957 LOG (GNUNET_ERROR_TYPE_DEBUG,
958 "Server starts to listen on port %u.\n",
967 * Setup service handle
969 * Configuration may specify:
970 * - PORT (where to bind to for TCP)
971 * - UNIXPATH (where to bind to for UNIX domain sockets)
972 * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
973 * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
974 * - ACCEPT_FROM (only allow connections from specified IPv4 subnets)
975 * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
976 * - REJECT_FROM (disallow allow connections from specified IPv4 subnets)
977 * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
979 * @param sh service context to initialize
980 * @return #GNUNET_OK if configuration succeeded
983 setup_service (struct GNUNET_SERVICE_Handle *sh)
985 struct GNUNET_TIME_Relative idleout;
994 if (GNUNET_CONFIGURATION_have_value
995 (sh->cfg, sh->service_name, "TOLERANT"))
999 GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, sh->service_name,
1002 LOG (GNUNET_ERROR_TYPE_ERROR,
1003 _("Specified value for `%s' of service `%s' is invalid\n"),
1004 "TOLERANT", sh->service_name);
1005 return GNUNET_SYSERR;
1009 tolerant = GNUNET_NO;
1013 if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1014 (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
1015 (cnt + 4 < FD_SETSIZE))
1018 GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (cnt + 1));
1021 flags = fcntl (3 + cnt, F_GETFD);
1022 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1024 (sh->lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1026 LOG (GNUNET_ERROR_TYPE_ERROR,
1028 ("Could not access pre-bound socket %u, will try to bind myself\n"),
1029 (unsigned int) 3 + cnt);
1031 while (sh->lsocks[cnt] != NULL)
1032 GNUNET_break (0 == GNUNET_NETWORK_socket_close (sh->lsocks[cnt++]));
1033 GNUNET_free (sh->lsocks);
1038 unsetenv ("LISTEN_FDS");
1041 if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL)
1043 receive_sockets_from_parent (sh);
1044 putenv ("GNUNET_OS_READ_LSOCKS=");
1048 if (NULL != sh->lsocks)
1050 /* listen only on inherited sockets if we have any */
1051 struct GNUNET_NETWORK_Handle **ls = sh->lsocks;
1052 for (; NULL != *ls; ls++)
1054 struct ServiceListenContext *slc;
1056 slc = GNUNET_new (struct ServiceListenContext);
1057 slc->listen_socket = *ls;
1058 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1060 GNUNET_free_non_null (sh->lsocks);
1064 struct sockaddr **addrs;
1065 socklen_t *addrlens;
1068 num = get_server_addresses (sh->service_name, sh->cfg,
1070 if (GNUNET_SYSERR == num)
1071 return GNUNET_SYSERR;
1073 for (int i = 0; i < num; i++)
1075 struct ServiceListenContext *slc;
1077 slc = GNUNET_new (struct ServiceListenContext);
1078 slc->listen_socket = open_listen_socket (addrs[i], addrlens[i]);
1079 GNUNET_break (NULL != slc->listen_socket);
1080 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1084 sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1086 GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, sh->service_name,
1089 GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, sh->service_name,
1091 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1092 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1093 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1094 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1101 * Creates the "main" function for a GNUnet service. You
1102 * should almost always use the #GNUNET_SERVICE_MAIN macro
1103 * instead of calling this function directly (except
1104 * for ARM, which should call this function directly).
1106 * The function will launch the service with the name @a service_name
1107 * using the @a service_options to configure its shutdown
1108 * behavior. Once the service is ready, the @a init_cb will be called
1109 * for service-specific initialization. @a init_cb will be given the
1110 * service handler which can be used to control the service's
1111 * availability. When clients connect or disconnect, the respective
1112 * @a connect_cb or @a disconnect_cb functions will be called. For
1113 * messages received from the clients, the respective @a handlers will
1114 * be invoked; for the closure of the handlers we use the return value
1115 * from the @a connect_cb invocation of the respective client.
1117 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1118 * message to receive further messages from this client. If
1119 * #GNUNET_SERVICE_client_continue() is not called within a short
1120 * time, a warning will be logged. If delays are expected, services
1121 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1122 * disable the warning.
1124 * Clients sending invalid messages (based on @a handlers) will be
1125 * dropped. Additionally, clients can be dropped at any time using
1126 * #GNUNET_SERVICE_client_drop().
1128 * @param argc number of command-line arguments in @a argv
1129 * @param argv array of command-line arguments
1130 * @param service_name name of the service to run
1131 * @param options options controlling shutdown of the service
1132 * @param service_init_cb function to call once the service is ready
1133 * @param connect_cb function to call whenever a client connects
1134 * @param disconnect_cb function to call whenever a client disconnects
1135 * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
1136 * @param handlers NULL-terminated array of message handlers for the service,
1137 * the closure will be set to the value returned by
1138 * the @a connect_cb for the respective connection
1139 * @return 0 on success, non-zero on error
1142 GNUNET_SERVICE_ruN_ (int argc,
1144 const char *service_name,
1145 enum GNUNET_SERVICE_Options options,
1146 GNUNET_SERVICE_InitCallback service_init_cb,
1147 GNUNET_SERVICE_ConnectHandler connect_cb,
1148 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1150 const struct GNUNET_MQ_MessageHandler *handlers)
1152 struct GNUNET_SERVICE_Handle sh;
1154 char *opt_cfg_filename;
1160 unsigned long long skew_offset;
1161 unsigned long long skew_variance;
1162 long long clock_offset;
1163 struct GNUNET_CONFIGURATION_Handle *cfg;
1167 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1168 GNUNET_GETOPT_OPTION_CFG_FILE (&opt_cfg_filename),
1169 {'d', "daemonize", NULL,
1170 gettext_noop ("do daemonize (detach from terminal)"), 0,
1171 GNUNET_GETOPT_set_one, &do_daemonize},
1172 GNUNET_GETOPT_OPTION_HELP (NULL),
1173 GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
1174 GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
1175 GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION),
1176 GNUNET_GETOPT_OPTION_END
1179 xdg = getenv ("XDG_CONFIG_HOME");
1181 GNUNET_asprintf (&cfg_filename,
1185 GNUNET_OS_project_data_get ()->config_file);
1187 cfg_filename = GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
1189 sh.options = options;
1190 sh.cfg = cfg = GNUNET_CONFIGURATION_create ();
1191 sh.service_init_cb = service_init_cb;
1192 sh.connect_cb = connect_cb;
1193 sh.disconnect_cb = disconnect_cb;
1195 sh.handlers = handlers;
1197 /* setup subsystems */
1198 ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv);
1199 if (GNUNET_SYSERR == ret)
1201 if (GNUNET_NO == ret)
1206 if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
1211 if (NULL == opt_cfg_filename)
1212 opt_cfg_filename = GNUNET_strdup (cfg_filename);
1213 if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename))
1215 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename))
1217 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1218 _("Malformed configuration file `%s', exit ...\n"),
1225 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL))
1227 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1228 _("Malformed configuration, exit ...\n"));
1231 if (0 != strcmp (opt_cfg_filename, cfg_filename))
1232 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1233 _("Could not access configuration file `%s'\n"),
1236 if (GNUNET_OK != setup_service (&sh))
1238 if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sh)))
1243 if (GNUNET_OK != set_user_id (&sh))
1245 LOG (GNUNET_ERROR_TYPE_DEBUG,
1246 "Service `%s' runs with configuration from `%s'\n",
1250 GNUNET_CONFIGURATION_get_value_number (sh.cfg, "TESTING",
1251 "SKEW_OFFSET", &skew_offset)) &&
1253 GNUNET_CONFIGURATION_get_value_number (sh.cfg, "TESTING",
1254 "SKEW_VARIANCE", &skew_variance)))
1256 clock_offset = skew_offset - skew_variance;
1257 GNUNET_TIME_set_offset (clock_offset);
1258 LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
1260 /* actually run service */
1262 GNUNET_SCHEDULER_run (&service_main, &sh);
1264 if (1 == do_daemonize)
1265 pid_file_delete (&sh);
1268 if (-1 != sh.ready_confirm_fd)
1270 if (1 != WRITE (sh.ready_confirm_fd, err ? "I" : "S", 1))
1271 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
1272 GNUNET_break (0 == CLOSE (sh.ready_confirm_fd));
1279 GNUNET_CONFIGURATION_have_value (sh.cfg, service_name,
1282 GNUNET_CONFIGURATION_get_value_string (sh.cfg, service_name,
1289 GAUGER (service_name, counter, mi.usmblks, "blocks");
1290 GNUNET_free (counter);
1294 GNUNET_SPEEDUP_stop_ ();
1295 GNUNET_CONFIGURATION_destroy (cfg);
1297 while (NULL != sh.slc_head)
1299 struct ServiceListenContext *slc = sh.slc_head;
1300 sh.slc_head = slc->next;
1301 // FIXME: destroy slc
1305 GNUNET_free_non_null (logfile);
1306 GNUNET_free_non_null (loglev);
1307 GNUNET_free (cfg_filename);
1308 GNUNET_free_non_null (opt_cfg_filename);
1309 GNUNET_free_non_null (sh.v4_denied);
1310 GNUNET_free_non_null (sh.v6_denied);
1311 GNUNET_free_non_null (sh.v4_allowed);
1312 GNUNET_free_non_null (sh.v6_allowed);
1314 return err ? GNUNET_SYSERR : sh.ret;
1319 * Suspend accepting connections from the listen socket temporarily.
1320 * Resume activity using #GNUNET_SERVICE_resume.
1322 * @param sh service to stop accepting connections.
1325 GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
1327 struct ServiceListenContext *slc;
1329 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
1331 if (NULL != slc->listen_task)
1333 GNUNET_SCHEDULER_cancel (slc->listen_task);
1334 slc->listen_task = NULL;
1341 * Signature of functions implementing the sending functionality of a
1344 * @param mq the message queue
1345 * @param msg the message to send
1346 * @param impl_state state of the implementation
1349 service_mq_send (struct GNUNET_MQ_Handle *mq,
1350 const struct GNUNET_MessageHeader *msg,
1353 // struct GNUNET_SERVICE_Client *client = cls;
1355 // FIXME 1: setup "client->send_task" for transmission.
1356 // FIXME 2: I seriously hope we do not need to make a copy of `msg`!
1357 // OPTIMIZATION: ideally, we'd like the ability to peak at the rest of
1358 // the queue and transmit more than one message if possible.
1363 * Implementation function that cancels the currently sent message.
1365 * @param mq message queue
1366 * @param impl_state state specific to the implementation
1369 service_mq_cancel (struct GNUNET_MQ_Handle *mq,
1372 // struct GNUNET_SERVICE_Client *client = cls;
1374 // FIXME: stop transmission! (must be possible, otherwise
1375 // we must have told MQ that the message was sent!)
1380 * Generic error handler, called with the appropriate
1381 * error code and the same closure specified at the creation of
1382 * the message queue.
1383 * Not every message queue implementation supports an error handler.
1385 * @param cls closure
1386 * @param error error code
1389 service_mq_error_handler (void *cls,
1390 enum GNUNET_MQ_Error error)
1392 struct GNUNET_SERVICE_Client *client = cls;
1399 * Functions with this signature are called whenever a
1400 * complete message is received by the tokenizer for a client.
1402 * Do not call #GNUNET_SERVER_mst_destroy() from within
1403 * the scope of this callback.
1405 * @param cls closure with the `struct GNUNET_SERVICE_Client *`
1406 * @param client_cls closure with the `struct GNUNET_SERVICE_Client *`
1407 * @param message the actual message
1408 * @return #GNUNET_OK on success (always)
1411 service_client_mst_cb (void *cls,
1413 const struct GNUNET_MessageHeader *message)
1415 struct GNUNET_SERVICE_Client *client = cls;
1417 GNUNET_MQ_inject_message (client->mq,
1424 * A client sent us data. Receive and process it. If we are done,
1425 * reschedule this task.
1427 * @param cls the `struct GNUNET_SERVICE_Client` that sent us data.
1430 service_client_recv (void *cls)
1432 struct GNUNET_SERVICE_Client *client = cls;
1434 // FIXME: read into buffer, pass to MST, then client->mq inject!
1435 // FIXME: revise MST API to avoid the memcpy!
1436 // i.e.: GNUNET_MST_read (client->sock);
1441 * We have successfully accepted a connection from a client. Now
1442 * setup the client (with the scheduler) and tell the application.
1444 * @param sh service that accepted the client
1445 * @param sock socket associated with the client
1448 start_client (struct GNUNET_SERVICE_Handle *sh,
1449 struct GNUNET_NETWORK_Handle *csock)
1451 struct GNUNET_SERVICE_Client *client;
1453 client = GNUNET_new (struct GNUNET_SERVICE_Client);
1454 GNUNET_CONTAINER_DLL_insert (sh->clients_head,
1458 client->sock = csock;
1459 client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send,
1464 &service_mq_error_handler,
1466 client->mst = GNUNET_SERVER_mst_create (&service_client_mst_cb,
1468 client->user_context = sh->connect_cb (sh->cb_cls,
1471 GNUNET_MQ_set_handlers_closure (client->mq,
1472 client->user_context);
1473 client->recv_task = GNUNET_SCHEDULER_add_read (client->sock,
1474 &service_client_recv,
1480 * We have a client. Accept the incoming socket(s) (and reschedule
1483 * @param cls the `struct ServiceListenContext` of the ready listen socket
1486 accept_client (void *cls)
1488 struct ServiceListenContext *slc = cls;
1489 struct GNUNET_SERVICE_Handle *sh = slc->sh;
1491 slc->listen_task = NULL;
1494 struct GNUNET_NETWORK_Handle *sock;
1495 struct sockaddr_in *v4;
1496 struct sockaddr_in6 *v6;
1497 struct sockaddr_storage sa;
1501 addrlen = sizeof (sa);
1502 sock = GNUNET_NETWORK_socket_accept (slc->listen_socket,
1503 (struct sockaddr *) &sa,
1507 switch (sa.ss_family)
1510 GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
1511 v4 = (const struct sockaddr_in *) &sa;
1512 ok = ( ( (NULL == sh->v4_allowed) ||
1513 (check_ipv4_listed (sh->v4_allowed,
1515 ( (NULL == sh->v4_denied) ||
1516 (! check_ipv4_listed (sh->v4_denied,
1517 &v4->sin_addr)) ) );
1520 GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
1521 v6 = (const struct sockaddr_in6 *) &sa;
1522 ok = ( ( (NULL == sh->v6_allowed) ||
1523 (check_ipv6_listed (sh->v6_allowed,
1524 &v6->sin6_addr))) &&
1525 ( (NULL == sh->v6_denied) ||
1526 (! check_ipv6_listed (sh->v6_denied,
1527 &v6->sin6_addr)) ) );
1531 ok = GNUNET_OK; /* controlled using file-system ACL now */
1535 LOG (GNUNET_ERROR_TYPE_WARNING,
1536 _("Unknown address family %d\n"),
1538 return GNUNET_SYSERR;
1542 LOG (GNUNET_ERROR_TYPE_DEBUG,
1543 "Service rejected incoming connection from %s due to policy.\n",
1544 GNUNET_a2s ((const struct sockaddr *) &sa,
1546 GNUNET_NETWORK_socket_close (sock);
1549 LOG (GNUNET_ERROR_TYPE_DEBUG,
1550 "Service accepted incoming connection from %s.\n",
1551 GNUNET_a2s ((const struct sockaddr *) &sa,
1553 start_client (slc->sh,
1556 slc->listen_task = GNUNET_SCHEDULER_add_read (slc->listen_socket,
1563 * Resume accepting connections from the listen socket.
1565 * @param sh service to resume accepting connections.
1568 GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
1570 struct ServiceListenContext *slc;
1572 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
1574 GNUNET_assert (NULL == slc->listen_task);
1575 slc->listen_task = GNUNET_SCHEDULER_add_read (slc->listen_socket,
1583 * Continue receiving further messages from the given client.
1584 * Must be called after each message received.
1586 * @param c the client to continue receiving from
1589 GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
1591 GNUNET_break (0); // not implemented
1596 * Disable the warning the server issues if a message is not
1597 * acknowledged in a timely fashion. Use this call if a client is
1598 * intentionally delayed for a while. Only applies to the current
1601 * @param c client for which to disable the warning
1604 GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
1606 GNUNET_break (NULL != c->warn_task);
1607 if (NULL != c->warn_task)
1609 GNUNET_SCHEDULER_cancel (c->warn_task);
1610 c->warn_task = NULL;
1616 * Ask the server to disconnect from the given client. This is the
1617 * same as returning #GNUNET_SYSERR within the check procedure when
1618 * handling a message, wexcept that it allows dropping of a client even
1619 * when not handling a message from that client. The `disconnect_cb`
1620 * will be called on @a c even if the application closes the connection
1621 * using this function.
1623 * @param c client to disconnect now
1626 GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
1628 struct GNUNET_SERVICE_Handle *sh = c->sh;
1630 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
1633 sh->disconnect_cb (sh->cb_cls,
1636 if (NULL != c->warn_task)
1638 GNUNET_SCHEDULER_cancel (c->warn_task);
1639 c->warn_task = NULL;
1641 if (NULL != c->recv_task)
1643 GNUNET_SCHEDULER_cancel (c->recv_task);
1644 c->recv_task = NULL;
1646 if (NULL != c->send_task)
1648 GNUNET_SCHEDULER_cancel (c->send_task);
1649 c->send_task = NULL;
1651 GNUNET_SERVER_mst_destroy (c->mst);
1652 GNUNET_MQ_destroy (c->mq);
1653 if (GNUNET_NO == c->persist)
1655 GNUNET_NETWORK_socket_close (c->sock);
1659 GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
1662 if ( (GNUNET_YES == sh->got_shutdown) &&
1663 (GNUNET_NO == have_non_monitor_clients (sh)) )
1664 GNUNET_SERVICE_shutdown (sh);
1669 * Explicitly stops the service.
1671 * @param sh server to shutdown
1674 GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
1676 struct GNUNET_SERVICE_Client *client;
1678 GNUNET_SERVICE_suspend (sh);
1679 sh->got_shutdown = GNUNET_NO;
1680 while (NULL != (client = sh->clients_head))
1681 GNUNET_SERVICE_client_drop (client);
1686 * Set the 'monitor' flag on this client. Clients which have been
1687 * marked as 'monitors' won't prevent the server from shutting down
1688 * once #GNUNET_SERVICE_stop_listening() has been invoked. The idea is
1689 * that for "normal" clients we likely want to allow them to process
1690 * their requests; however, monitor-clients are likely to 'never'
1691 * disconnect during shutdown and thus will not be considered when
1692 * determining if the server should continue to exist after
1693 * shutdown has been triggered.
1695 * @param c client to mark as a monitor
1698 GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
1700 c->is_monitor = GNUNET_YES;
1701 if ( (GNUNET_YES == c->sh->got_shutdown) &&
1702 (GNUNET_NO == have_non_monitor_clients (c->sh)) )
1703 GNUNET_SERVICE_shutdown (c->sh);
1708 * Set the persist option on this client. Indicates that the
1709 * underlying socket or fd should never really be closed. Used for
1710 * indicating process death.
1712 * @param c client to persist the socket (never to be closed)
1715 GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
1717 c->persist = GNUNET_YES;
1721 /* end of service_new.c */