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