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