getting service_new.c to compile, albeit it is not yet complete
[oweals/gnunet.git] / src / util / service_new.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2016 GNUnet e.V.
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file util/service_new.c
23  * @brief functions related to starting services (redesign)
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_constants.h"
30 #include "gnunet_resolver_service.h"
31 #include "speedup.h"
32
33 #if HAVE_MALLINFO
34 #include <malloc.h>
35 #include "gauger.h"
36 #endif
37
38
39 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
40
41 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
42
43 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
44
45
46 /**
47  * Information the service tracks per listen operation.
48  */
49 struct ServiceListenContext
50 {
51
52   /**
53    * Kept in a DLL.
54    */
55   struct ServiceListenContext *next;
56
57   /**
58    * Kept in a DLL.
59    */
60   struct ServiceListenContext *prev;
61
62   /**
63    * Service this listen context belongs to.
64    */
65   struct GNUNET_SERVICE_Handle *sh;
66
67   /**
68    * Socket we are listening on.
69    */
70   struct GNUNET_NETWORK_Handle *listen_socket;
71
72   /**
73    * Task scheduled to do the listening.
74    */
75   struct GNUNET_SCHEDULER_Task *listen_task;
76
77 };
78
79
80 /**
81  * Handle to a service.
82  */
83 struct GNUNET_SERVICE_Handle
84 {
85   /**
86    * Our configuration.
87    */
88   const struct GNUNET_CONFIGURATION_Handle *cfg;
89
90   /**
91    * Name of our service.
92    */
93   const char *service_name;
94
95   /**
96    * Main service-specific task to run.
97    */
98   GNUNET_SERVICE_InitCallback service_init_cb;
99
100   /**
101    * Function to call when clients connect.
102    */
103   GNUNET_SERVICE_ConnectHandler connect_cb;
104
105   /**
106    * Function to call when clients disconnect / are disconnected.
107    */
108   GNUNET_SERVICE_DisconnectHandler disconnect_cb;
109
110   /**
111    * Closure for @e service_init_cb, @e connect_cb, @e disconnect_cb.
112    */
113   void *cb_cls;
114
115   /**
116    * DLL of listen sockets used to accept new connections.
117    */
118   struct ServiceListenContext *slc_head;
119
120   /**
121    * DLL of listen sockets used to accept new connections.
122    */
123   struct ServiceListenContext *slc_tail;
124
125   /**
126    * Our clients, kept in a DLL.
127    */
128   struct GNUNET_SERVICE_Client *clients_head;
129
130   /**
131    * Our clients, kept in a DLL.
132    */
133   struct GNUNET_SERVICE_Client *clients_tail;
134
135   /**
136    * Message handlers to use for all clients.
137    */
138   const struct GNUNET_MQ_MessageHandler *handlers;
139
140   /**
141    * Closure for @e task.
142    */
143   void *task_cls;
144
145   /**
146    * IPv4 addresses that are not allowed to connect.
147    */
148   struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
149
150   /**
151    * IPv6 addresses that are not allowed to connect.
152    */
153   struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
154
155   /**
156    * IPv4 addresses that are allowed to connect (if not
157    * set, all are allowed).
158    */
159   struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
160
161   /**
162    * IPv6 addresses that are allowed to connect (if not
163    * set, all are allowed).
164    */
165   struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
166
167   /**
168    * Do we require a matching UID for UNIX domain socket connections?
169    * #GNUNET_NO means that the UID does not have to match (however,
170    * @e match_gid may still impose other access control checks).
171    */
172   int match_uid;
173
174   /**
175    * Do we require a matching GID for UNIX domain socket connections?
176    * Ignored if @e match_uid is #GNUNET_YES.  Note that this is about
177    * checking that the client's UID is in our group OR that the
178    * client's GID is our GID.  If both "match_gid" and @e match_uid are
179    * #GNUNET_NO, all users on the local system have access.
180    */
181   int match_gid;
182
183   /**
184    * Set to #GNUNET_YES if we got a shutdown signal and terminate
185    * the service if #have_non_monitor_clients() returns #GNUNET_YES.
186    */
187   int got_shutdown;
188
189   /**
190    * Our options.
191    */
192   enum GNUNET_SERVICE_Options options;
193
194   /**
195    * If we are daemonizing, this FD is set to the
196    * pipe to the parent.  Send '.' if we started
197    * ok, '!' if not.  -1 if we are not daemonizing.
198    */
199   int ready_confirm_fd;
200
201   /**
202    * Overall success/failure of the service start.
203    */
204   int ret;
205
206   /**
207    * If GNUNET_YES, consider unknown message types an error where the
208    * client is disconnected.
209    * FIXME: remove?
210    */
211   int require_found;
212 };
213
214
215 /**
216  * Handle to a client that is connected to a service.
217  */
218 struct GNUNET_SERVICE_Client
219 {
220
221   /**
222    * Kept in a DLL.
223    */
224   struct GNUNET_SERVICE_Client *next;
225
226   /**
227    * Kept in a DLL.
228    */
229   struct GNUNET_SERVICE_Client *prev;
230
231   /**
232    * Service that this client belongs to.
233    */
234   struct GNUNET_SERVICE_Handle *sh;
235
236   /**
237    * Socket of this client.
238    */
239   struct GNUNET_NETWORK_Handle *sock;
240
241   /**
242    * Message queue for the client.
243    */
244   struct GNUNET_MQ_Handle *mq;
245
246   /**
247    * Tokenizer we use for processing incoming data.
248    */
249   struct GNUNET_SERVER_MessageStreamTokenizer *mst;
250
251   /**
252    * Task that warns about missing calls to
253    * #GNUNET_SERVICE_client_continue().
254    */
255   struct GNUNET_SCHEDULER_Task *warn_task;
256
257   /**
258    * Task that receives data from the client to
259    * pass it to the handlers.
260    */
261   struct GNUNET_SCHEDULER_Task *recv_task;
262
263   /**
264    * Task that transmit data to the client.
265    */
266   struct GNUNET_SCHEDULER_Task *send_task;
267
268   /**
269    * User context value, value returned from
270    * the connect callback.
271    */
272   void *user_context;
273
274   /**
275    * Persist the file handle for this client no matter what happens,
276    * force the OS to close once the process actually dies.  Should only
277    * be used in special cases!
278    */
279   int persist;
280
281   /**
282    * Is this client a 'monitor' client that should not be counted
283    * when deciding on destroying the server during soft shutdown?
284    * (see also #GNUNET_SERVICE_start)
285    */
286   int is_monitor;
287
288   /**
289    * Type of last message processed (for warn_no_receive_done).
290    */
291   uint16_t warn_type;
292 };
293
294
295 /**
296  * Check if any of the clients we have left are unrelated to
297  * monitoring.
298  *
299  * @param sh service to check clients for
300  * @return #GNUNET_YES if we have non-monitoring clients left
301  */
302 static int
303 have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
304 {
305   struct GNUNET_SERVICE_Client *client;
306
307   for (client = sh->clients_head;NULL != client; client = client->next)
308   {
309     if (client->is_monitor)
310       continue;
311     return GNUNET_YES;
312   }
313   return GNUNET_NO;
314 }
315
316
317 /**
318  * Shutdown task triggered when a service should be terminated.
319  * This considers active clients and the service options to see
320  * how this specific service is to be terminated, and depending
321  * on this proceeds with the shutdown logic.
322  *
323  * @param cls our `struct GNUNET_SERVICE_Handle`
324  */
325 static void
326 service_shutdown (void *cls)
327 {
328   struct GNUNET_SERVICE_Handle *sh = cls;
329
330   switch (sh->options)
331   {
332   case GNUNET_SERVICE_OPTION_NONE:
333     GNUNET_SERVICE_shutdown (sh);
334     break;
335   case GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN:
336     /* This task should never be run if we are using
337        the manual shutdown. */
338     GNUNET_assert (0);
339     break;
340   case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN:
341     sh->got_shutdown = GNUNET_YES;
342     GNUNET_SERVICE_suspend (sh);
343     if (GNUNET_NO == have_non_monitor_clients (sh))
344       GNUNET_SERVICE_shutdown (sh);
345     break;
346   }
347 }
348
349
350 /**
351  * First task run by any service.  Initializes our shutdown task,
352  * starts the listening operation on our listen sockets and launches
353  * the custom logic of the application service.
354  *
355  * @param cls our `struct GNUNET_SERVICE_Handle`
356  */
357 static void
358 service_main (void *cls)
359 {
360   struct GNUNET_SERVICE_Handle *sh = cls;
361
362   if (GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN != sh->options)
363     GNUNET_SCHEDULER_add_shutdown (&service_shutdown,
364                                    sh);
365   GNUNET_SERVICE_resume (sh);
366   sh->service_init_cb (sh->cb_cls,
367                        sh->cfg,
368                        sh);
369 }
370
371
372 /**
373  * Parse an IPv4 access control list.
374  *
375  * @param ret location where to write the ACL (set)
376  * @param sh service context to use to get the configuration
377  * @param option name of the ACL option to parse
378  * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
379  *         no ACL configured)
380  */
381 static int
382 process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret,
383               struct GNUNET_SERVICE_Handle *sh,
384               const char *option)
385 {
386   char *opt;
387
388   if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
389   {
390     *ret = NULL;
391     return GNUNET_OK;
392   }
393   GNUNET_break (GNUNET_OK ==
394                 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
395                                                        sh->service_name,
396                                                        option, &opt));
397   if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
398   {
399     LOG (GNUNET_ERROR_TYPE_WARNING,
400          _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
401          opt,
402          sh->service_name,
403          option);
404     GNUNET_free (opt);
405     return GNUNET_SYSERR;
406   }
407   GNUNET_free (opt);
408   return GNUNET_OK;
409 }
410
411
412 /**
413  * Parse an IPv6 access control list.
414  *
415  * @param ret location where to write the ACL (set)
416  * @param sh service context to use to get the configuration
417  * @param option name of the ACL option to parse
418  * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
419  *         no ACL configured)
420  */
421 static int
422 process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret,
423               struct GNUNET_SERVICE_Handle *sh,
424               const char *option)
425 {
426   char *opt;
427
428   if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
429   {
430     *ret = NULL;
431     return GNUNET_OK;
432   }
433   GNUNET_break (GNUNET_OK ==
434                 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
435                                                        sh->service_name,
436                                                        option, &opt));
437   if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
438   {
439     LOG (GNUNET_ERROR_TYPE_WARNING,
440          _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
441          opt, sh->service_name, option);
442     GNUNET_free (opt);
443     return GNUNET_SYSERR;
444   }
445   GNUNET_free (opt);
446   return GNUNET_OK;
447 }
448
449
450 /**
451  * Add the given UNIX domain path as an address to the
452  * list (as the first entry).
453  *
454  * @param saddrs array to update
455  * @param saddrlens where to store the address length
456  * @param unixpath path to add
457  * @param abstract #GNUNET_YES to add an abstract UNIX domain socket.  This
458  *          parameter is ignore on systems other than LINUX
459  */
460 static void
461 add_unixpath (struct sockaddr **saddrs,
462               socklen_t *saddrlens,
463               const char *unixpath,
464               int abstract)
465 {
466 #ifdef AF_UNIX
467   struct sockaddr_un *un;
468
469   un = GNUNET_new (struct sockaddr_un);
470   un->sun_family = AF_UNIX;
471   strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
472 #ifdef LINUX
473   if (GNUNET_YES == abstract)
474     un->sun_path[0] = '\0';
475 #endif
476 #if HAVE_SOCKADDR_IN_SIN_LEN
477   un->sun_len = (u_char) sizeof (struct sockaddr_un);
478 #endif
479   *saddrs = (struct sockaddr *) un;
480   *saddrlens = sizeof (struct sockaddr_un);
481 #else
482   /* this function should never be called
483    * unless AF_UNIX is defined! */
484   GNUNET_assert (0);
485 #endif
486 }
487
488
489 /**
490  * Get the list of addresses that a server for the given service
491  * should bind to.
492  *
493  * @param service_name name of the service
494  * @param cfg configuration (which specifies the addresses)
495  * @param addrs set (call by reference) to an array of pointers to the
496  *              addresses the server should bind to and listen on; the
497  *              array will be NULL-terminated (on success)
498  * @param addr_lens set (call by reference) to an array of the lengths
499  *              of the respective `struct sockaddr` struct in the @a addrs
500  *              array (on success)
501  * @return number of addresses found on success,
502  *              #GNUNET_SYSERR if the configuration
503  *              did not specify reasonable finding information or
504  *              if it specified a hostname that could not be resolved;
505  *              #GNUNET_NO if the number of addresses configured is
506  *              zero (in this case, `*addrs` and `*addr_lens` will be
507  *              set to NULL).
508  */
509 static int
510 get_server_addresses (const char *service_name,
511                       const struct GNUNET_CONFIGURATION_Handle *cfg,
512                       struct sockaddr ***addrs,
513                       socklen_t **addr_lens)
514 {
515   int disablev6;
516   struct GNUNET_NETWORK_Handle *desc;
517   unsigned long long port;
518   char *unixpath;
519   struct addrinfo hints;
520   struct addrinfo *res;
521   struct addrinfo *pos;
522   struct addrinfo *next;
523   unsigned int i;
524   int resi;
525   int ret;
526   int abstract;
527   struct sockaddr **saddrs;
528   socklen_t *saddrlens;
529   char *hostname;
530
531   *addrs = NULL;
532   *addr_lens = NULL;
533   desc = NULL;
534   if (GNUNET_CONFIGURATION_have_value (cfg,
535                                        service_name,
536                                        "DISABLEV6"))
537   {
538     if (GNUNET_SYSERR ==
539         (disablev6 =
540          GNUNET_CONFIGURATION_get_value_yesno (cfg,
541                                                service_name,
542                                                "DISABLEV6")))
543       return GNUNET_SYSERR;
544   }
545   else
546     disablev6 = GNUNET_NO;
547
548   if (! disablev6)
549   {
550     /* probe IPv6 support */
551     desc = GNUNET_NETWORK_socket_create (PF_INET6,
552                                          SOCK_STREAM,
553                                          0);
554     if (NULL == desc)
555     {
556       if ((ENOBUFS == errno) ||
557           (ENOMEM == errno) ||
558           (ENFILE == errno) ||
559           (EACCES == errno))
560       {
561         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
562                       "socket");
563         return GNUNET_SYSERR;
564       }
565       LOG (GNUNET_ERROR_TYPE_INFO,
566            _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
567            service_name,
568            STRERROR (errno));
569       disablev6 = GNUNET_YES;
570     }
571     else
572     {
573       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
574       desc = NULL;
575     }
576   }
577
578   port = 0;
579   if (GNUNET_CONFIGURATION_have_value (cfg,
580                                        service_name,
581                                        "PORT"))
582   {
583     if (GNUNET_OK !=
584         GNUNET_CONFIGURATION_get_value_number (cfg,
585                                                service_name,
586                                                "PORT",
587                                                &port))
588     {
589       LOG (GNUNET_ERROR_TYPE_ERROR,
590            _("Require valid port number for service `%s' in configuration!\n"),
591            service_name);
592     }
593     if (port > 65535)
594     {
595       LOG (GNUNET_ERROR_TYPE_ERROR,
596            _("Require valid port number for service `%s' in configuration!\n"),
597            service_name);
598       return GNUNET_SYSERR;
599     }
600   }
601
602   if (GNUNET_CONFIGURATION_have_value (cfg,
603                                        service_name,
604                                        "BINDTO"))
605   {
606     GNUNET_break (GNUNET_OK ==
607                   GNUNET_CONFIGURATION_get_value_string (cfg,
608                                                          service_name,
609                                                          "BINDTO",
610                                                          &hostname));
611   }
612   else
613     hostname = NULL;
614
615   unixpath = NULL;
616   abstract = GNUNET_NO;
617 #ifdef AF_UNIX
618   if ((GNUNET_YES ==
619        GNUNET_CONFIGURATION_have_value (cfg,
620                                         service_name,
621                                         "UNIXPATH")) &&
622       (GNUNET_OK ==
623        GNUNET_CONFIGURATION_get_value_filename (cfg,
624                                                 service_name,
625                                                 "UNIXPATH",
626                                                 &unixpath)) &&
627       (0 < strlen (unixpath)))
628   {
629     /* probe UNIX support */
630     struct sockaddr_un s_un;
631
632     if (strlen (unixpath) >= sizeof (s_un.sun_path))
633     {
634       LOG (GNUNET_ERROR_TYPE_WARNING,
635            _("UNIXPATH `%s' too long, maximum length is %llu\n"),
636            unixpath,
637            (unsigned long long) sizeof (s_un.sun_path));
638       unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
639       LOG (GNUNET_ERROR_TYPE_INFO,
640            _("Using `%s' instead\n"),
641            unixpath);
642     }
643 #ifdef LINUX
644     abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
645                                                      "TESTING",
646                                                      "USE_ABSTRACT_SOCKETS");
647     if (GNUNET_SYSERR == abstract)
648       abstract = GNUNET_NO;
649 #endif
650     if ((GNUNET_YES != abstract)
651         && (GNUNET_OK !=
652             GNUNET_DISK_directory_create_for_file (unixpath)))
653       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
654                                 "mkdir",
655                                 unixpath);
656   }
657   if (NULL != unixpath)
658   {
659     desc = GNUNET_NETWORK_socket_create (AF_UNIX,
660                                          SOCK_STREAM,
661                                          0);
662     if (NULL == desc)
663     {
664       if ((ENOBUFS == errno) ||
665           (ENOMEM == errno) ||
666           (ENFILE == errno) ||
667           (EACCES == errno))
668       {
669         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
670                       "socket");
671         GNUNET_free_non_null (hostname);
672         GNUNET_free (unixpath);
673         return GNUNET_SYSERR;
674       }
675       LOG (GNUNET_ERROR_TYPE_INFO,
676            _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
677            service_name,
678            STRERROR (errno));
679       GNUNET_free (unixpath);
680       unixpath = NULL;
681     }
682     else
683     {
684       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
685       desc = NULL;
686     }
687   }
688 #endif
689
690   if ((0 == port) && (NULL == unixpath))
691   {
692     LOG (GNUNET_ERROR_TYPE_ERROR,
693          _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
694          service_name);
695     GNUNET_free_non_null (hostname);
696     return GNUNET_SYSERR;
697   }
698   if (0 == port)
699   {
700     saddrs = GNUNET_new_array (2,
701                                struct sockaddr *);
702     saddrlens = GNUNET_new_array (2,
703                                   socklen_t);
704     add_unixpath (saddrs,
705                   saddrlens,
706                   unixpath,
707                   abstract);
708     GNUNET_free_non_null (unixpath);
709     GNUNET_free_non_null (hostname);
710     *addrs = saddrs;
711     *addr_lens = saddrlens;
712     return 1;
713   }
714
715   if (NULL != hostname)
716   {
717     LOG (GNUNET_ERROR_TYPE_DEBUG,
718          "Resolving `%s' since that is where `%s' will bind to.\n",
719          hostname,
720          service_name);
721     memset (&hints,
722             0,
723             sizeof (struct addrinfo));
724     if (disablev6)
725       hints.ai_family = AF_INET;
726     hints.ai_protocol = IPPROTO_TCP;
727     if ((0 != (ret = getaddrinfo (hostname,
728                                   NULL,
729                                   &hints,
730                                   &res))) ||
731         (NULL == res))
732     {
733       LOG (GNUNET_ERROR_TYPE_ERROR,
734            _("Failed to resolve `%s': %s\n"),
735            hostname,
736            gai_strerror (ret));
737       GNUNET_free (hostname);
738       GNUNET_free_non_null (unixpath);
739       return GNUNET_SYSERR;
740     }
741     next = res;
742     i = 0;
743     while (NULL != (pos = next))
744     {
745       next = pos->ai_next;
746       if ( (disablev6) &&
747            (pos->ai_family == AF_INET6) )
748         continue;
749       i++;
750     }
751     if (0 == i)
752     {
753       LOG (GNUNET_ERROR_TYPE_ERROR,
754            _("Failed to find %saddress for `%s'.\n"),
755            disablev6 ? "IPv4 " : "",
756            hostname);
757       freeaddrinfo (res);
758       GNUNET_free (hostname);
759       GNUNET_free_non_null (unixpath);
760       return GNUNET_SYSERR;
761     }
762     resi = i;
763     if (NULL != unixpath)
764       resi++;
765     saddrs = GNUNET_new_array (resi + 1,
766                                struct sockaddr *);
767     saddrlens = GNUNET_new_array (resi + 1,
768                                   socklen_t);
769     i = 0;
770     if (NULL != unixpath)
771     {
772       add_unixpath (saddrs,
773                     saddrlens,
774                     unixpath,
775                     abstract);
776       i++;
777     }
778     next = res;
779     while (NULL != (pos = next))
780     {
781       next = pos->ai_next;
782       if ( (disablev6) &&
783            (AF_INET6 == pos->ai_family) )
784         continue;
785       if ( (IPPROTO_TCP != pos->ai_protocol) &&
786            (0 != pos->ai_protocol) )
787         continue;               /* not TCP */
788       if ( (SOCK_STREAM != pos->ai_socktype) &&
789            (0 != pos->ai_socktype) )
790         continue;               /* huh? */
791       LOG (GNUNET_ERROR_TYPE_DEBUG,
792            "Service `%s' will bind to `%s'\n",
793            service_name,
794            GNUNET_a2s (pos->ai_addr,
795                        pos->ai_addrlen));
796       if (AF_INET == pos->ai_family)
797       {
798         GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
799         saddrlens[i] = pos->ai_addrlen;
800         saddrs[i] = GNUNET_malloc (saddrlens[i]);
801         GNUNET_memcpy (saddrs[i],
802                        pos->ai_addr,
803                        saddrlens[i]);
804         ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
805       }
806       else
807       {
808         GNUNET_assert (AF_INET6 == pos->ai_family);
809         GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
810         saddrlens[i] = pos->ai_addrlen;
811         saddrs[i] = GNUNET_malloc (saddrlens[i]);
812         GNUNET_memcpy (saddrs[i],
813                        pos->ai_addr,
814                        saddrlens[i]);
815         ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
816       }
817       i++;
818     }
819     GNUNET_free (hostname);
820     freeaddrinfo (res);
821     resi = i;
822   }
823   else
824   {
825     /* will bind against everything, just set port */
826     if (disablev6)
827     {
828       /* V4-only */
829       resi = 1;
830       if (NULL != unixpath)
831         resi++;
832       i = 0;
833       saddrs = GNUNET_new_array (resi + 1,
834                                  struct sockaddr *);
835       saddrlens = GNUNET_new_array (resi + 1,
836                                     socklen_t);
837       if (NULL != unixpath)
838       {
839         add_unixpath (saddrs,
840                       saddrlens,
841                       unixpath,
842                       abstract);
843         i++;
844       }
845       saddrlens[i] = sizeof (struct sockaddr_in);
846       saddrs[i] = GNUNET_malloc (saddrlens[i]);
847 #if HAVE_SOCKADDR_IN_SIN_LEN
848       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
849 #endif
850       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
851       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
852     }
853     else
854     {
855       /* dual stack */
856       resi = 2;
857       if (NULL != unixpath)
858         resi++;
859       saddrs = GNUNET_new_array (resi + 1,
860                                  struct sockaddr *);
861       saddrlens = GNUNET_new_array (resi + 1,
862                                     socklen_t);
863       i = 0;
864       if (NULL != unixpath)
865       {
866         add_unixpath (saddrs,
867                       saddrlens,
868                       unixpath,
869                       abstract);
870         i++;
871       }
872       saddrlens[i] = sizeof (struct sockaddr_in6);
873       saddrs[i] = GNUNET_malloc (saddrlens[i]);
874 #if HAVE_SOCKADDR_IN_SIN_LEN
875       ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
876 #endif
877       ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
878       ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
879       i++;
880       saddrlens[i] = sizeof (struct sockaddr_in);
881       saddrs[i] = GNUNET_malloc (saddrlens[i]);
882 #if HAVE_SOCKADDR_IN_SIN_LEN
883       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
884 #endif
885       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
886       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
887     }
888   }
889   GNUNET_free_non_null (unixpath);
890   *addrs = saddrs;
891   *addr_lens = saddrlens;
892   return resi;
893 }
894
895
896 #ifdef MINGW
897 /**
898  * Read listen sockets from the parent process (ARM).
899  *
900  * @param sh service context to initialize
901  * @return NULL-terminated array of sockets on success,
902  *         NULL if not ok (must bind yourself)
903  */
904 static struct GNUNET_NETWORK_Handle **
905 receive_sockets_from_parent (struct GNUNET_SERVICE_Handle *sh)
906 {
907   static struct GNUNET_NETWORK_Handle **lsocks;
908   const char *env_buf;
909   int fail;
910   uint64_t count;
911   uint64_t i;
912   HANDLE lsocks_pipe;
913
914   env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
915   if ( (NULL == env_buf) ||
916        (strlen (env_buf) <= 0) )
917     return NULL;
918   /* Using W32 API directly here, because this pipe will
919    * never be used outside of this function, and it's just too much of a bother
920    * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
921    */
922   lsocks_pipe = (HANDLE) strtoul (env_buf,
923                                   NULL,
924                                   10);
925   if ( (0 == lsocks_pipe) ||
926        (INVALID_HANDLE_VALUE == lsocks_pipe))
927     return NULL;
928   fail = 1;
929   do
930   {
931     int ret;
932     int fail2;
933     DWORD rd;
934
935     ret = ReadFile (lsocks_pipe,
936                     &count,
937                     sizeof (count),
938                     &rd,
939                     NULL);
940     if ( (0 == ret) ||
941          (sizeof (count) != rd) ||
942          (0 == count) )
943       break;
944     lsocks = GNUNET_new_array (count + 1,
945                                struct GNUNET_NETWORK_Handle *);
946
947     fail2 = 1;
948     for (i = 0; i < count; i++)
949     {
950       WSAPROTOCOL_INFOA pi;
951       uint64_t size;
952       SOCKET s;
953
954       ret = ReadFile (lsocks_pipe,
955                       &size,
956                       sizeof (size),
957                       &rd,
958                       NULL);
959       if ( (0 == ret) ||
960            (sizeof (size) != rd) ||
961            (sizeof (pi) != size) )
962         break;
963       ret = ReadFile (lsocks_pipe,
964                       &pi,
965                       sizeof (pi),
966                       &rd,
967                       NULL);
968       if ( (0 == ret) ||
969            (sizeof (pi) != rd))
970         break;
971       s = WSASocketA (pi.iAddressFamily,
972                       pi.iSocketType,
973                       pi.iProtocol,
974                       &pi,
975                       0,
976                       WSA_FLAG_OVERLAPPED);
977       lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
978       if (NULL == lsocks[i])
979         break;
980       else if (i == count - 1)
981         fail2 = 0;
982     }
983     if (fail2)
984       break;
985     lsocks[count] = NULL;
986     fail = 0;
987   }
988   while (fail);
989   CloseHandle (lsocks_pipe);
990
991   if (fail)
992   {
993     LOG (GNUNET_ERROR_TYPE_ERROR,
994          _("Could not access a pre-bound socket, will try to bind myself\n"));
995     for (i = 0; (i < count) && (NULL != lsocks[i]); i++)
996       GNUNET_break (0 == GNUNET_NETWORK_socket_close (lsocks[i]));
997     GNUNET_free (lsocks);
998     return NULL;
999   }
1000   return lsocks;
1001 }
1002 #endif
1003
1004
1005 /**
1006  * Create and initialize a listen socket for the server.
1007  *
1008  * @param server_addr address to listen on
1009  * @param socklen length of @a server_addr
1010  * @return NULL on error, otherwise the listen socket
1011  */
1012 static struct GNUNET_NETWORK_Handle *
1013 open_listen_socket (const struct sockaddr *server_addr,
1014                     socklen_t socklen)
1015 {
1016   struct GNUNET_NETWORK_Handle *sock;
1017   uint16_t port;
1018   int eno;
1019
1020   switch (server_addr->sa_family)
1021   {
1022   case AF_INET:
1023     port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1024     break;
1025   case AF_INET6:
1026     port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1027     break;
1028   case AF_UNIX:
1029     port = 0;
1030     break;
1031   default:
1032     GNUNET_break (0);
1033     port = 0;
1034     break;
1035   }
1036   sock = GNUNET_NETWORK_socket_create (server_addr->sa_family,
1037                                        SOCK_STREAM,
1038                                        0);
1039   if (NULL == sock)
1040   {
1041     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1042                   "socket");
1043     errno = 0;
1044     return NULL;
1045   }
1046   /* bind the socket */
1047   if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock,
1048                                                server_addr,
1049                                                socklen))
1050   {
1051     eno = errno;
1052     if (EADDRINUSE != errno)
1053     {
1054       /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1055        * fail if we already took the port on IPv6; if both IPv4 and
1056        * IPv6 binds fail, then our caller will log using the
1057        * errno preserved in 'eno' */
1058       LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1059                     "bind");
1060       if (0 != port)
1061         LOG (GNUNET_ERROR_TYPE_ERROR,
1062              _("`%s' failed for port %d (%s).\n"),
1063              "bind",
1064              port,
1065              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1066       eno = 0;
1067     }
1068     else
1069     {
1070       if (0 != port)
1071         LOG (GNUNET_ERROR_TYPE_WARNING,
1072              _("`%s' failed for port %d (%s): address already in use\n"),
1073              "bind", port,
1074              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1075       else if (AF_UNIX == server_addr->sa_family)
1076       {
1077         LOG (GNUNET_ERROR_TYPE_WARNING,
1078              _("`%s' failed for `%s': address already in use\n"),
1079              "bind",
1080              GNUNET_a2s (server_addr, socklen));
1081       }
1082     }
1083     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
1084     errno = eno;
1085     return NULL;
1086   }
1087   if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock,
1088                                                  5))
1089   {
1090     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1091                   "listen");
1092     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
1093     errno = 0;
1094     return NULL;
1095   }
1096   if (0 != port)
1097     LOG (GNUNET_ERROR_TYPE_DEBUG,
1098          "Server starts to listen on port %u.\n",
1099          port);
1100   return sock;
1101 }
1102
1103
1104 /**
1105  * Setup service handle
1106  *
1107  * Configuration may specify:
1108  * - PORT (where to bind to for TCP)
1109  * - UNIXPATH (where to bind to for UNIX domain sockets)
1110  * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
1111  * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
1112  * - ACCEPT_FROM  (only allow connections from specified IPv4 subnets)
1113  * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
1114  * - REJECT_FROM  (disallow allow connections from specified IPv4 subnets)
1115  * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
1116  *
1117  * @param sh service context to initialize
1118  * @return #GNUNET_OK if configuration succeeded
1119  */
1120 static int
1121 setup_service (struct GNUNET_SERVICE_Handle *sh)
1122 {
1123   int tolerant;
1124   struct GNUNET_NETWORK_Handle **lsocks;
1125 #ifndef MINGW
1126   const char *nfds;
1127   unsigned int cnt;
1128   int flags;
1129 #endif
1130
1131   if (GNUNET_CONFIGURATION_have_value
1132       (sh->cfg,
1133        sh->service_name,
1134        "TOLERANT"))
1135   {
1136     if (GNUNET_SYSERR ==
1137         (tolerant =
1138          GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1139                                                sh->service_name,
1140                                                "TOLERANT")))
1141     {
1142       LOG (GNUNET_ERROR_TYPE_ERROR,
1143            _("Specified value for `%s' of service `%s' is invalid\n"),
1144            "TOLERANT",
1145            sh->service_name);
1146       return GNUNET_SYSERR;
1147     }
1148   }
1149   else
1150     tolerant = GNUNET_NO;
1151
1152   lsocks = NULL;
1153 #ifndef MINGW
1154   errno = 0;
1155   if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1156        (1 == SSCANF (nfds,
1157                      "%u",
1158                      &cnt)) &&
1159        (cnt > 0) &&
1160        (cnt < FD_SETSIZE) &&
1161        (cnt + 4 < FD_SETSIZE) )
1162   {
1163     lsocks = GNUNET_new_array (cnt + 1,
1164                                struct GNUNET_NETWORK_Handle *);
1165     while (0 < cnt--)
1166     {
1167       flags = fcntl (3 + cnt,
1168                      F_GETFD);
1169       if ( (flags < 0) ||
1170            (0 != (flags & FD_CLOEXEC)) ||
1171            (NULL ==
1172             (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1173       {
1174         LOG (GNUNET_ERROR_TYPE_ERROR,
1175              _("Could not access pre-bound socket %u, will try to bind myself\n"),
1176              (unsigned int) 3 + cnt);
1177         cnt++;
1178         while (NULL != lsocks[cnt])
1179           GNUNET_break (0 == GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1180         GNUNET_free (lsocks);
1181         lsocks = NULL;
1182         break;
1183       }
1184     }
1185     unsetenv ("LISTEN_FDS");
1186   }
1187 #else
1188   if (NULL != getenv ("GNUNET_OS_READ_LSOCKS"))
1189   {
1190     lsocks = receive_sockets_from_parent (sh);
1191     putenv ("GNUNET_OS_READ_LSOCKS=");
1192   }
1193 #endif
1194
1195   if (NULL != lsocks)
1196   {
1197     /* listen only on inherited sockets if we have any */
1198     struct GNUNET_NETWORK_Handle **ls;
1199     
1200     for (ls = lsocks; NULL != *ls; ls++)
1201     {
1202       struct ServiceListenContext *slc;
1203
1204       slc = GNUNET_new (struct ServiceListenContext);
1205       slc->listen_socket = *ls;
1206       GNUNET_CONTAINER_DLL_insert (sh->slc_head,
1207                                    sh->slc_tail,
1208                                    slc);
1209     }
1210     GNUNET_free (lsocks);
1211   }
1212   else
1213   {
1214     struct sockaddr **addrs;
1215     socklen_t *addrlens;
1216     int num;
1217
1218     num = get_server_addresses (sh->service_name,
1219                                 sh->cfg,
1220                                 &addrs,
1221                                 &addrlens);
1222     if (GNUNET_SYSERR == num)
1223       return GNUNET_SYSERR;
1224
1225     for (int i = 0; i < num; i++)
1226     {
1227       struct ServiceListenContext *slc;
1228
1229       slc = GNUNET_new (struct ServiceListenContext);
1230       slc->listen_socket = open_listen_socket (addrs[i],
1231                                                addrlens[i]);
1232       GNUNET_break (NULL != slc->listen_socket);
1233       GNUNET_CONTAINER_DLL_insert (sh->slc_head,
1234                                    sh->slc_tail,
1235                                    slc);
1236     }
1237   }
1238
1239   sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1240   sh->match_uid =
1241       GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1242                                             sh->service_name,
1243                                             "UNIX_MATCH_UID");
1244   sh->match_gid =
1245       GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1246                                             sh->service_name,
1247                                             "UNIX_MATCH_GID");
1248   process_acl4 (&sh->v4_denied,
1249                 sh,
1250                 "REJECT_FROM");
1251   process_acl4 (&sh->v4_allowed,
1252                 sh,
1253                 "ACCEPT_FROM");
1254   process_acl6 (&sh->v6_denied,
1255                 sh,
1256                 "REJECT_FROM6");
1257   process_acl6 (&sh->v6_allowed,
1258                 sh,
1259                 "ACCEPT_FROM6");
1260   return GNUNET_OK;
1261 }
1262
1263
1264 /**
1265  * Get the name of the user that'll be used
1266  * to provide the service.
1267  *
1268  * @param sh service context
1269  * @return value of the 'USERNAME' option
1270  */
1271 static char *
1272 get_user_name (struct GNUNET_SERVICE_Handle *sh)
1273 {
1274   char *un;
1275
1276   if (GNUNET_OK !=
1277       GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1278                                                sh->service_name,
1279                                                "USERNAME",
1280                                                &un))
1281     return NULL;
1282   return un;
1283 }
1284
1285
1286 /**
1287  * Set user ID.
1288  *
1289  * @param sh service context
1290  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1291  */
1292 static int
1293 set_user_id (struct GNUNET_SERVICE_Handle *sh)
1294 {
1295   char *user;
1296
1297   if (NULL == (user = get_user_name (sh)))
1298     return GNUNET_OK;           /* keep */
1299 #ifndef MINGW
1300   struct passwd *pws;
1301
1302   errno = 0;
1303   pws = getpwnam (user);
1304   if (NULL == pws)
1305   {
1306     LOG (GNUNET_ERROR_TYPE_ERROR,
1307          _("Cannot obtain information about user `%s': %s\n"),
1308          user,
1309          errno == 0 ? _("No such user") : STRERROR (errno));
1310     GNUNET_free (user);
1311     return GNUNET_SYSERR;
1312   }
1313   if ( (0 != setgid (pws->pw_gid)) ||
1314        (0 != setegid (pws->pw_gid)) ||
1315 #if HAVE_INITGROUPS
1316        (0 != initgroups (user,
1317                          pws->pw_gid)) ||
1318 #endif
1319        (0 != setuid (pws->pw_uid)) ||
1320        (0 != seteuid (pws->pw_uid)))
1321   {
1322     if ((0 != setregid (pws->pw_gid,
1323                         pws->pw_gid)) ||
1324         (0 != setreuid (pws->pw_uid,
1325                         pws->pw_uid)))
1326     {
1327       LOG (GNUNET_ERROR_TYPE_ERROR,
1328            _("Cannot change user/group to `%s': %s\n"),
1329            user,
1330            STRERROR (errno));
1331       GNUNET_free (user);
1332       return GNUNET_SYSERR;
1333     }
1334   }
1335 #endif
1336   GNUNET_free (user);
1337   return GNUNET_OK;
1338 }
1339
1340
1341 /**
1342  * Get the name of the file where we will
1343  * write the PID of the service.
1344  *
1345  * @param sh service context
1346  * @return name of the file for the process ID
1347  */
1348 static char *
1349 get_pid_file_name (struct GNUNET_SERVICE_Handle *sh)
1350 {
1351   char *pif;
1352
1353   if (GNUNET_OK !=
1354       GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1355                                                sh->service_name,
1356                                                "PIDFILE",
1357                                                &pif))
1358     return NULL;
1359   return pif;
1360 }
1361
1362
1363 /**
1364  * Delete the PID file that was created by our parent.
1365  *
1366  * @param sh service context
1367  */
1368 static void
1369 pid_file_delete (struct GNUNET_SERVICE_Handle *sh)
1370 {
1371   char *pif = get_pid_file_name (sh);
1372
1373   if (NULL == pif)
1374     return;                     /* no PID file */
1375   if (0 != UNLINK (pif))
1376     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
1377                        "unlink",
1378                        pif);
1379   GNUNET_free (pif);
1380 }
1381
1382
1383 /**
1384  * Detach from terminal.
1385  *
1386  * @param sh service context
1387  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1388  */
1389 static int
1390 detach_terminal (struct GNUNET_SERVICE_Handle *sh)
1391 {
1392 #ifndef MINGW
1393   pid_t pid;
1394   int nullfd;
1395   int filedes[2];
1396
1397   if (0 != PIPE (filedes))
1398   {
1399     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1400                   "pipe");
1401     return GNUNET_SYSERR;
1402   }
1403   pid = fork ();
1404   if (pid < 0)
1405   {
1406     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1407                   "fork");
1408     return GNUNET_SYSERR;
1409   }
1410   if (0 != pid)
1411   {
1412     /* Parent */
1413     char c;
1414
1415     GNUNET_break (0 == CLOSE (filedes[1]));
1416     c = 'X';
1417     if (1 != READ (filedes[0],
1418                    &c,
1419                    sizeof (char)))
1420       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
1421                     "read");
1422     fflush (stdout);
1423     switch (c)
1424     {
1425     case '.':
1426       exit (0);
1427     case 'I':
1428       LOG (GNUNET_ERROR_TYPE_INFO,
1429            _("Service process failed to initialize\n"));
1430       break;
1431     case 'S':
1432       LOG (GNUNET_ERROR_TYPE_INFO,
1433            _("Service process could not initialize server function\n"));
1434       break;
1435     case 'X':
1436       LOG (GNUNET_ERROR_TYPE_INFO,
1437            _("Service process failed to report status\n"));
1438       break;
1439     }
1440     exit (1);                   /* child reported error */
1441   }
1442   GNUNET_break (0 == CLOSE (0));
1443   GNUNET_break (0 == CLOSE (1));
1444   GNUNET_break (0 == CLOSE (filedes[0]));
1445   nullfd = OPEN ("/dev/null",
1446                  O_RDWR | O_APPEND);
1447   if (nullfd < 0)
1448     return GNUNET_SYSERR;
1449   /* set stdin/stdout to /dev/null */
1450   if ( (dup2 (nullfd, 0) < 0) ||
1451        (dup2 (nullfd, 1) < 0) )
1452   {
1453     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1454                   "dup2");
1455     (void) CLOSE (nullfd);
1456     return GNUNET_SYSERR;
1457   }
1458   (void) CLOSE (nullfd);
1459   /* Detach from controlling terminal */
1460   pid = setsid ();
1461   if (-1 == pid)
1462     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1463                   "setsid");
1464   sh->ready_confirm_fd = filedes[1];
1465 #else
1466   /* FIXME: we probably need to do something else
1467    * elsewhere in order to fork the process itself... */
1468   FreeConsole ();
1469 #endif
1470   return GNUNET_OK;
1471 }
1472
1473
1474 /**
1475  * Creates the "main" function for a GNUnet service.  You
1476  * should almost always use the #GNUNET_SERVICE_MAIN macro
1477  * instead of calling this function directly (except
1478  * for ARM, which should call this function directly).
1479  *
1480  * The function will launch the service with the name @a service_name
1481  * using the @a service_options to configure its shutdown
1482  * behavior. Once the service is ready, the @a init_cb will be called
1483  * for service-specific initialization.  @a init_cb will be given the
1484  * service handler which can be used to control the service's
1485  * availability.  When clients connect or disconnect, the respective
1486  * @a connect_cb or @a disconnect_cb functions will be called. For
1487  * messages received from the clients, the respective @a handlers will
1488  * be invoked; for the closure of the handlers we use the return value
1489  * from the @a connect_cb invocation of the respective client.
1490  *
1491  * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1492  * message to receive further messages from this client.  If
1493  * #GNUNET_SERVICE_client_continue() is not called within a short
1494  * time, a warning will be logged. If delays are expected, services
1495  * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1496  * disable the warning.
1497  *
1498  * Clients sending invalid messages (based on @a handlers) will be
1499  * dropped. Additionally, clients can be dropped at any time using
1500  * #GNUNET_SERVICE_client_drop().
1501  *
1502  * @param argc number of command-line arguments in @a argv
1503  * @param argv array of command-line arguments
1504  * @param service_name name of the service to run
1505  * @param options options controlling shutdown of the service
1506  * @param service_init_cb function to call once the service is ready
1507  * @param connect_cb function to call whenever a client connects
1508  * @param disconnect_cb function to call whenever a client disconnects
1509  * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
1510  * @param handlers NULL-terminated array of message handlers for the service,
1511  *                 the closure will be set to the value returned by
1512  *                 the @a connect_cb for the respective connection
1513  * @return 0 on success, non-zero on error
1514  */
1515 int
1516 GNUNET_SERVICE_ruN_ (int argc,
1517                      char *const *argv,
1518                      const char *service_name,
1519                      enum GNUNET_SERVICE_Options options,
1520                      GNUNET_SERVICE_InitCallback service_init_cb,
1521                      GNUNET_SERVICE_ConnectHandler connect_cb,
1522                      GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1523                      void *cls,
1524                      const struct GNUNET_MQ_MessageHandler *handlers)
1525 {
1526   struct GNUNET_SERVICE_Handle sh;
1527   char *cfg_filename;
1528   char *opt_cfg_filename;
1529   char *loglev;
1530   const char *xdg;
1531   char *logfile;
1532   int do_daemonize;
1533   unsigned long long skew_offset;
1534   unsigned long long skew_variance;
1535   long long clock_offset;
1536   struct GNUNET_CONFIGURATION_Handle *cfg;
1537   int ret;
1538   int err;
1539
1540   struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1541     GNUNET_GETOPT_OPTION_CFG_FILE (&opt_cfg_filename),
1542     {'d', "daemonize", NULL,
1543      gettext_noop ("do daemonize (detach from terminal)"), 0,
1544      GNUNET_GETOPT_set_one, &do_daemonize},
1545     GNUNET_GETOPT_OPTION_HELP (NULL),
1546     GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
1547     GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
1548     GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION),
1549     GNUNET_GETOPT_OPTION_END
1550   };
1551
1552   xdg = getenv ("XDG_CONFIG_HOME");
1553   if (NULL != xdg)
1554     GNUNET_asprintf (&cfg_filename,
1555                      "%s%s%s",
1556                      xdg,
1557                      DIR_SEPARATOR_STR,
1558                      GNUNET_OS_project_data_get ()->config_file);
1559   else
1560     cfg_filename = GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
1561
1562   sh.options = options;
1563   sh.cfg = cfg = GNUNET_CONFIGURATION_create ();
1564   sh.service_init_cb = service_init_cb;
1565   sh.connect_cb = connect_cb;
1566   sh.disconnect_cb = disconnect_cb;
1567   sh.cb_cls = cls;
1568   sh.handlers = handlers;
1569
1570   /* setup subsystems */
1571   ret = GNUNET_GETOPT_run (service_name,
1572                            service_options,
1573                            argc,
1574                            argv);
1575   if (GNUNET_SYSERR == ret)
1576     goto shutdown;
1577   if (GNUNET_NO == ret)
1578   {
1579     err = 0;
1580     goto shutdown;
1581   }
1582   if (GNUNET_OK != GNUNET_log_setup (service_name,
1583                                      loglev,
1584                                      logfile))
1585   {
1586     GNUNET_break (0);
1587     goto shutdown;
1588   }
1589   if (NULL == opt_cfg_filename)
1590     opt_cfg_filename = GNUNET_strdup (cfg_filename);
1591   if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename))
1592   {
1593     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg,
1594                                                     opt_cfg_filename))
1595     {
1596       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1597                   _("Malformed configuration file `%s', exit ...\n"),
1598                   opt_cfg_filename);
1599       goto shutdown;
1600     }
1601   }
1602   else
1603   {
1604     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg,
1605                                                     NULL))
1606     {
1607       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1608                   _("Malformed configuration, exit ...\n"));
1609       goto shutdown;
1610     }
1611     if (0 != strcmp (opt_cfg_filename,
1612                      cfg_filename))
1613       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1614                   _("Could not access configuration file `%s'\n"),
1615                   opt_cfg_filename);
1616   }
1617   if (GNUNET_OK != setup_service (&sh))
1618     goto shutdown;
1619   if ( (1 == do_daemonize) &&
1620        (GNUNET_OK != detach_terminal (&sh)) )
1621   {
1622     GNUNET_break (0);
1623     goto shutdown;
1624   }
1625   if (GNUNET_OK != set_user_id (&sh))
1626     goto shutdown;
1627   LOG (GNUNET_ERROR_TYPE_DEBUG,
1628        "Service `%s' runs with configuration from `%s'\n",
1629        service_name,
1630        opt_cfg_filename);
1631   if ((GNUNET_OK ==
1632        GNUNET_CONFIGURATION_get_value_number (sh.cfg,
1633                                               "TESTING",
1634                                               "SKEW_OFFSET",
1635                                               &skew_offset)) &&
1636       (GNUNET_OK ==
1637        GNUNET_CONFIGURATION_get_value_number (sh.cfg,
1638                                               "TESTING",
1639                                               "SKEW_VARIANCE",
1640                                               &skew_variance)))
1641   {
1642     clock_offset = skew_offset - skew_variance;
1643     GNUNET_TIME_set_offset (clock_offset);
1644     LOG (GNUNET_ERROR_TYPE_DEBUG,
1645          "Skewing clock by %dll ms\n",
1646          clock_offset);
1647   }
1648   /* actually run service */
1649   err = 0;
1650   GNUNET_SCHEDULER_run (&service_main,
1651                         &sh);
1652   /* shutdown */
1653   if (1 == do_daemonize)
1654     pid_file_delete (&sh);
1655
1656 shutdown:
1657   if (-1 != sh.ready_confirm_fd)
1658   {
1659     if (1 != WRITE (sh.ready_confirm_fd, err ? "I" : "S", 1))
1660       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
1661     GNUNET_break (0 == CLOSE (sh.ready_confirm_fd));
1662   }
1663 #if HAVE_MALLINFO
1664   {
1665     char *counter;
1666
1667     if ( (GNUNET_YES ==
1668           GNUNET_CONFIGURATION_have_value (sh.cfg,
1669                                            service_name,
1670                                            "GAUGER_HEAP")) &&
1671          (GNUNET_OK ==
1672           GNUNET_CONFIGURATION_get_value_string (sh.cfg,
1673                                                  service_name,
1674                                                  "GAUGER_HEAP",
1675                                                  &counter)) )
1676     {
1677       struct mallinfo mi;
1678
1679       mi = mallinfo ();
1680       GAUGER (service_name,
1681               counter,
1682               mi.usmblks,
1683               "blocks");
1684       GNUNET_free (counter);
1685     }
1686   }
1687 #endif
1688   GNUNET_SPEEDUP_stop_ ();
1689   GNUNET_CONFIGURATION_destroy (cfg);
1690
1691   while (NULL != sh.slc_head)
1692   {
1693     struct ServiceListenContext *slc = sh.slc_head;
1694
1695     sh.slc_head = slc->next;
1696     // FIXME: destroy slc
1697     GNUNET_free (slc);
1698   }
1699
1700   GNUNET_free_non_null (logfile);
1701   GNUNET_free_non_null (loglev);
1702   GNUNET_free (cfg_filename);
1703   GNUNET_free_non_null (opt_cfg_filename);
1704   GNUNET_free_non_null (sh.v4_denied);
1705   GNUNET_free_non_null (sh.v6_denied);
1706   GNUNET_free_non_null (sh.v4_allowed);
1707   GNUNET_free_non_null (sh.v6_allowed);
1708
1709   return err ? GNUNET_SYSERR : sh.ret;
1710 }
1711
1712
1713 /**
1714  * Suspend accepting connections from the listen socket temporarily.
1715  * Resume activity using #GNUNET_SERVICE_resume.
1716  *
1717  * @param sh service to stop accepting connections.
1718  */
1719 void
1720 GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
1721 {
1722   struct ServiceListenContext *slc;
1723
1724   for (slc = sh->slc_head; NULL != slc; slc = slc->next)
1725   {
1726     if (NULL != slc->listen_task)
1727     {
1728       GNUNET_SCHEDULER_cancel (slc->listen_task);
1729       slc->listen_task = NULL;
1730     }
1731   }
1732 }
1733
1734
1735 /**
1736  * Signature of functions implementing the sending functionality of a
1737  * message queue.
1738  *
1739  * @param mq the message queue
1740  * @param msg the message to send
1741  * @param impl_state state of the implementation
1742  */
1743 static void
1744 service_mq_send (struct GNUNET_MQ_Handle *mq,
1745                  const struct GNUNET_MessageHeader *msg,
1746                  void *impl_state)
1747 {
1748   // struct GNUNET_SERVICE_Client *client = cls;
1749
1750   // FIXME 1: setup "client->send_task" for transmission.
1751   // FIXME 2: I seriously hope we do not need to make a copy of `msg`!
1752   // OPTIMIZATION: ideally, we'd like the ability to peak at the rest of
1753   //               the queue and transmit more than one message if possible.
1754 }
1755
1756
1757 /**
1758  * Implementation function that cancels the currently sent message.
1759  *
1760  * @param mq message queue
1761  * @param impl_state state specific to the implementation
1762  */
1763 static void
1764 service_mq_cancel (struct GNUNET_MQ_Handle *mq,
1765                    void *impl_state)
1766 {
1767   // struct GNUNET_SERVICE_Client *client = cls;
1768
1769   // FIXME: stop transmission! (must be possible, otherwise
1770   // we must have told MQ that the message was sent!)
1771 }
1772
1773
1774 /**
1775  * Generic error handler, called with the appropriate
1776  * error code and the same closure specified at the creation of
1777  * the message queue.
1778  * Not every message queue implementation supports an error handler.
1779  *
1780  * @param cls closure
1781  * @param error error code
1782  */
1783 static void
1784 service_mq_error_handler (void *cls,
1785                           enum GNUNET_MQ_Error error)
1786 {
1787   struct GNUNET_SERVICE_Client *client = cls;
1788
1789   // FIXME!
1790 }
1791
1792
1793 /**
1794  * Functions with this signature are called whenever a
1795  * complete message is received by the tokenizer for a client.
1796  *
1797  * Do not call #GNUNET_SERVER_mst_destroy() from within
1798  * the scope of this callback.
1799  *
1800  * @param cls closure with the `struct GNUNET_SERVICE_Client *`
1801  * @param client_cls closure with the `struct GNUNET_SERVICE_Client *`
1802  * @param message the actual message
1803  * @return #GNUNET_OK on success (always)
1804  */
1805 static int
1806 service_client_mst_cb (void *cls,
1807                        void *client_cls,
1808                        const struct GNUNET_MessageHeader *message)
1809 {
1810   struct GNUNET_SERVICE_Client *client = cls;
1811
1812   GNUNET_MQ_inject_message (client->mq,
1813                             message);
1814   return GNUNET_OK;
1815 }
1816
1817
1818 /**
1819  * A client sent us data. Receive and process it.  If we are done,
1820  * reschedule this task.
1821  *
1822  * @param cls the `struct GNUNET_SERVICE_Client` that sent us data.
1823  */
1824 static void
1825 service_client_recv (void *cls)
1826 {
1827   struct GNUNET_SERVICE_Client *client = cls;
1828
1829   // FIXME: read into buffer, pass to MST, then client->mq inject!
1830   // FIXME: revise MST API to avoid the memcpy!
1831   // i.e.: GNUNET_MST_read (client->sock);
1832 }
1833
1834
1835 /**
1836  * We have successfully accepted a connection from a client.  Now
1837  * setup the client (with the scheduler) and tell the application.
1838  *
1839  * @param sh service that accepted the client
1840  * @param sock socket associated with the client
1841  */
1842 static void
1843 start_client (struct GNUNET_SERVICE_Handle *sh,
1844               struct GNUNET_NETWORK_Handle *csock)
1845 {
1846   struct GNUNET_SERVICE_Client *client;
1847
1848   client = GNUNET_new (struct GNUNET_SERVICE_Client);
1849   GNUNET_CONTAINER_DLL_insert (sh->clients_head,
1850                                sh->clients_tail,
1851                                client);
1852   client->sh = sh;
1853   client->sock = csock;
1854   client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send,
1855                                               NULL,
1856                                               &service_mq_cancel,
1857                                               client,
1858                                               sh->handlers,
1859                                               &service_mq_error_handler,
1860                                               client);
1861   client->mst = GNUNET_SERVER_mst_create (&service_client_mst_cb,
1862                                           client);
1863   client->user_context = sh->connect_cb (sh->cb_cls,
1864                                          client,
1865                                          client->mq);
1866   GNUNET_MQ_set_handlers_closure (client->mq,
1867                                   client->user_context);
1868   client->recv_task
1869     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1870                                      client->sock,
1871                                      &service_client_recv,
1872                                      client);
1873 }
1874
1875
1876 /**
1877  * Check if the given IP address is in the list of IP addresses.
1878  *
1879  * @param list a list of networks
1880  * @param add the IP to check (in network byte order)
1881  * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
1882  */
1883 static int
1884 check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
1885                    const struct in_addr *add)
1886 {
1887   unsigned int i;
1888
1889   if (NULL == list)
1890     return GNUNET_NO;
1891   i = 0;
1892   while ( (0 != list[i].network.s_addr) ||
1893           (0 != list[i].netmask.s_addr) )
1894   {
1895     if ((add->s_addr & list[i].netmask.s_addr) ==
1896         (list[i].network.s_addr & list[i].netmask.s_addr))
1897       return GNUNET_YES;
1898     i++;
1899   }
1900   return GNUNET_NO;
1901 }
1902
1903
1904 /**
1905  * Check if the given IP address is in the list of IP addresses.
1906  *
1907  * @param list a list of networks
1908  * @param ip the IP to check (in network byte order)
1909  * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
1910  */
1911 static int
1912 check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
1913                    const struct in6_addr *ip)
1914 {
1915   unsigned int i;
1916   unsigned int j;
1917   struct in6_addr zero;
1918
1919   if (NULL == list)
1920     return GNUNET_NO;
1921   memset (&zero,
1922           0,
1923           sizeof (struct in6_addr));
1924   i = 0;
1925 NEXT:
1926   while (0 != memcmp (&zero,
1927                       &list[i].network,
1928                       sizeof (struct in6_addr)))
1929   {
1930     for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
1931       if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
1932           (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
1933       {
1934         i++;
1935         goto NEXT;
1936       }
1937     return GNUNET_YES;
1938   }
1939   return GNUNET_NO;
1940 }
1941
1942
1943 /**
1944  * We have a client. Accept the incoming socket(s) (and reschedule
1945  * the listen task).
1946  *
1947  * @param cls the `struct ServiceListenContext` of the ready listen socket
1948  */
1949 static void
1950 accept_client (void *cls)
1951 {
1952   struct ServiceListenContext *slc = cls;
1953   struct GNUNET_SERVICE_Handle *sh = slc->sh;
1954
1955   slc->listen_task = NULL;
1956   while (1)
1957     {
1958       struct GNUNET_NETWORK_Handle *sock;
1959       const struct sockaddr_in *v4;
1960       const struct sockaddr_in6 *v6;
1961       struct sockaddr_storage sa;
1962       socklen_t addrlen;
1963       int ok;
1964
1965       addrlen = sizeof (sa);
1966       sock = GNUNET_NETWORK_socket_accept (slc->listen_socket,
1967                                            (struct sockaddr *) &sa,
1968                                            &addrlen);
1969       if (NULL == sock)
1970         break;
1971       switch (sa.ss_family)
1972       {
1973       case AF_INET:
1974         GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
1975         v4 = (const struct sockaddr_in *) &sa;
1976         ok = ( ( (NULL == sh->v4_allowed) ||
1977                  (check_ipv4_listed (sh->v4_allowed,
1978                                      &v4->sin_addr))) &&
1979                ( (NULL == sh->v4_denied) ||
1980                  (! check_ipv4_listed (sh->v4_denied,
1981                                        &v4->sin_addr)) ) );
1982         break;
1983       case AF_INET6:
1984         GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
1985         v6 = (const struct sockaddr_in6 *) &sa;
1986         ok = ( ( (NULL == sh->v6_allowed) ||
1987                  (check_ipv6_listed (sh->v6_allowed,
1988                                      &v6->sin6_addr))) &&
1989                ( (NULL == sh->v6_denied) ||
1990                  (! check_ipv6_listed (sh->v6_denied,
1991                                        &v6->sin6_addr)) ) );
1992         break;
1993 #ifndef WINDOWS
1994       case AF_UNIX:
1995         ok = GNUNET_OK;            /* controlled using file-system ACL now */
1996         break;
1997 #endif
1998       default:
1999         LOG (GNUNET_ERROR_TYPE_WARNING,
2000              _("Unknown address family %d\n"),
2001              sa.ss_family);
2002         return;
2003       }
2004       if (! ok)
2005         {
2006           LOG (GNUNET_ERROR_TYPE_DEBUG,
2007                "Service rejected incoming connection from %s due to policy.\n",
2008                GNUNET_a2s ((const struct sockaddr *) &sa,
2009                            addrlen));
2010           GNUNET_NETWORK_socket_close (sock);
2011           continue;
2012         }
2013       LOG (GNUNET_ERROR_TYPE_DEBUG,
2014            "Service accepted incoming connection from %s.\n",
2015            GNUNET_a2s ((const struct sockaddr *) &sa,
2016                        addrlen));
2017       start_client (slc->sh,
2018                     sock);
2019     }
2020   slc->listen_task
2021     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2022                                      slc->listen_socket,
2023                                      &accept_client,
2024                                      slc);
2025 }
2026
2027
2028 /**
2029  * Resume accepting connections from the listen socket.
2030  *
2031  * @param sh service to resume accepting connections.
2032  */
2033 void
2034 GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
2035 {
2036   struct ServiceListenContext *slc;
2037
2038   for (slc = sh->slc_head; NULL != slc; slc = slc->next)
2039   {
2040     GNUNET_assert (NULL == slc->listen_task);
2041     slc->listen_task
2042       = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2043                                        slc->listen_socket,
2044                                        &accept_client,
2045                                        slc);
2046   }
2047 }
2048
2049
2050 /**
2051  * Continue receiving further messages from the given client.
2052  * Must be called after each message received.
2053  *
2054  * @param c the client to continue receiving from
2055  */
2056 void
2057 GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
2058 {
2059   GNUNET_break (0); // not implemented
2060 }
2061
2062
2063 /**
2064  * Disable the warning the server issues if a message is not
2065  * acknowledged in a timely fashion.  Use this call if a client is
2066  * intentionally delayed for a while.  Only applies to the current
2067  * message.
2068  *
2069  * @param c client for which to disable the warning
2070  */
2071 void
2072 GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
2073 {
2074   GNUNET_break (NULL != c->warn_task);
2075   if (NULL != c->warn_task)
2076   {
2077     GNUNET_SCHEDULER_cancel (c->warn_task);
2078     c->warn_task = NULL;
2079   }
2080 }
2081
2082
2083 /**
2084  * Ask the server to disconnect from the given client.  This is the
2085  * same as returning #GNUNET_SYSERR within the check procedure when
2086  * handling a message, wexcept that it allows dropping of a client even
2087  * when not handling a message from that client.  The `disconnect_cb`
2088  * will be called on @a c even if the application closes the connection
2089  * using this function.
2090  *
2091  * @param c client to disconnect now
2092  */
2093 void
2094 GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2095 {
2096   struct GNUNET_SERVICE_Handle *sh = c->sh;
2097
2098   GNUNET_CONTAINER_DLL_remove (sh->clients_head,
2099                                sh->clients_tail,
2100                                c);
2101   sh->disconnect_cb (sh->cb_cls,
2102                      c,
2103                      c->user_context);
2104   if (NULL != c->warn_task)
2105   {
2106     GNUNET_SCHEDULER_cancel (c->warn_task);
2107     c->warn_task = NULL;
2108   }
2109   if (NULL != c->recv_task)
2110   {
2111     GNUNET_SCHEDULER_cancel (c->recv_task);
2112     c->recv_task = NULL;
2113   }
2114   if (NULL != c->send_task)
2115   {
2116     GNUNET_SCHEDULER_cancel (c->send_task);
2117     c->send_task = NULL;
2118   }
2119   GNUNET_SERVER_mst_destroy (c->mst);
2120   GNUNET_MQ_destroy (c->mq);
2121   if (GNUNET_NO == c->persist)
2122   {
2123     GNUNET_NETWORK_socket_close (c->sock);
2124   }
2125   else
2126   {
2127     GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
2128   }
2129   GNUNET_free (c);
2130   if ( (GNUNET_YES == sh->got_shutdown) &&
2131        (GNUNET_NO == have_non_monitor_clients (sh)) )
2132     GNUNET_SERVICE_shutdown (sh);
2133 }
2134
2135
2136 /**
2137  * Explicitly stops the service.
2138  *
2139  * @param sh server to shutdown
2140  */
2141 void
2142 GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
2143 {
2144   struct GNUNET_SERVICE_Client *client;
2145
2146   GNUNET_SERVICE_suspend (sh);
2147   sh->got_shutdown = GNUNET_NO;
2148   while (NULL != (client = sh->clients_head))
2149     GNUNET_SERVICE_client_drop (client);
2150 }
2151
2152
2153 /**
2154  * Set the 'monitor' flag on this client.  Clients which have been
2155  * marked as 'monitors' won't prevent the server from shutting down
2156  * once #GNUNET_SERVICE_stop_listening() has been invoked.  The idea is
2157  * that for "normal" clients we likely want to allow them to process
2158  * their requests; however, monitor-clients are likely to 'never'
2159  * disconnect during shutdown and thus will not be considered when
2160  * determining if the server should continue to exist after
2161  * shutdown has been triggered.
2162  *
2163  * @param c client to mark as a monitor
2164  */
2165 void
2166 GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
2167 {
2168   c->is_monitor = GNUNET_YES;
2169   if ( (GNUNET_YES == c->sh->got_shutdown) &&
2170        (GNUNET_NO == have_non_monitor_clients (c->sh)) )
2171     GNUNET_SERVICE_shutdown (c->sh);
2172 }
2173
2174
2175 /**
2176  * Set the persist option on this client.  Indicates that the
2177  * underlying socket or fd should never really be closed.  Used for
2178  * indicating process death.
2179  *
2180  * @param c client to persist the socket (never to be closed)
2181  */
2182 void
2183 GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
2184 {
2185   c->persist = GNUNET_YES;
2186 }
2187
2188
2189 /* end of service_new.c */