more work on new MST and service logic
[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->listen_socket = *ls;
1233       GNUNET_CONTAINER_DLL_insert (sh->slc_head,
1234                                    sh->slc_tail,
1235                                    slc);
1236     }
1237     GNUNET_free (lsocks);
1238   }
1239   else
1240   {
1241     struct sockaddr **addrs;
1242     socklen_t *addrlens;
1243     int num;
1244
1245     num = get_server_addresses (sh->service_name,
1246                                 sh->cfg,
1247                                 &addrs,
1248                                 &addrlens);
1249     if (GNUNET_SYSERR == num)
1250       return GNUNET_SYSERR;
1251
1252     for (int i = 0; i < num; i++)
1253     {
1254       struct ServiceListenContext *slc;
1255
1256       slc = GNUNET_new (struct ServiceListenContext);
1257       slc->listen_socket = open_listen_socket (addrs[i],
1258                                                addrlens[i]);
1259       GNUNET_break (NULL != slc->listen_socket);
1260       GNUNET_CONTAINER_DLL_insert (sh->slc_head,
1261                                    sh->slc_tail,
1262                                    slc);
1263     }
1264   }
1265
1266   sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1267   sh->match_uid =
1268       GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1269                                             sh->service_name,
1270                                             "UNIX_MATCH_UID");
1271   sh->match_gid =
1272       GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1273                                             sh->service_name,
1274                                             "UNIX_MATCH_GID");
1275   process_acl4 (&sh->v4_denied,
1276                 sh,
1277                 "REJECT_FROM");
1278   process_acl4 (&sh->v4_allowed,
1279                 sh,
1280                 "ACCEPT_FROM");
1281   process_acl6 (&sh->v6_denied,
1282                 sh,
1283                 "REJECT_FROM6");
1284   process_acl6 (&sh->v6_allowed,
1285                 sh,
1286                 "ACCEPT_FROM6");
1287   return GNUNET_OK;
1288 }
1289
1290
1291 /**
1292  * Get the name of the user that'll be used
1293  * to provide the service.
1294  *
1295  * @param sh service context
1296  * @return value of the 'USERNAME' option
1297  */
1298 static char *
1299 get_user_name (struct GNUNET_SERVICE_Handle *sh)
1300 {
1301   char *un;
1302
1303   if (GNUNET_OK !=
1304       GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1305                                                sh->service_name,
1306                                                "USERNAME",
1307                                                &un))
1308     return NULL;
1309   return un;
1310 }
1311
1312
1313 /**
1314  * Set user ID.
1315  *
1316  * @param sh service context
1317  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1318  */
1319 static int
1320 set_user_id (struct GNUNET_SERVICE_Handle *sh)
1321 {
1322   char *user;
1323
1324   if (NULL == (user = get_user_name (sh)))
1325     return GNUNET_OK;           /* keep */
1326 #ifndef MINGW
1327   struct passwd *pws;
1328
1329   errno = 0;
1330   pws = getpwnam (user);
1331   if (NULL == pws)
1332   {
1333     LOG (GNUNET_ERROR_TYPE_ERROR,
1334          _("Cannot obtain information about user `%s': %s\n"),
1335          user,
1336          errno == 0 ? _("No such user") : STRERROR (errno));
1337     GNUNET_free (user);
1338     return GNUNET_SYSERR;
1339   }
1340   if ( (0 != setgid (pws->pw_gid)) ||
1341        (0 != setegid (pws->pw_gid)) ||
1342 #if HAVE_INITGROUPS
1343        (0 != initgroups (user,
1344                          pws->pw_gid)) ||
1345 #endif
1346        (0 != setuid (pws->pw_uid)) ||
1347        (0 != seteuid (pws->pw_uid)))
1348   {
1349     if ((0 != setregid (pws->pw_gid,
1350                         pws->pw_gid)) ||
1351         (0 != setreuid (pws->pw_uid,
1352                         pws->pw_uid)))
1353     {
1354       LOG (GNUNET_ERROR_TYPE_ERROR,
1355            _("Cannot change user/group to `%s': %s\n"),
1356            user,
1357            STRERROR (errno));
1358       GNUNET_free (user);
1359       return GNUNET_SYSERR;
1360     }
1361   }
1362 #endif
1363   GNUNET_free (user);
1364   return GNUNET_OK;
1365 }
1366
1367
1368 /**
1369  * Get the name of the file where we will
1370  * write the PID of the service.
1371  *
1372  * @param sh service context
1373  * @return name of the file for the process ID
1374  */
1375 static char *
1376 get_pid_file_name (struct GNUNET_SERVICE_Handle *sh)
1377 {
1378   char *pif;
1379
1380   if (GNUNET_OK !=
1381       GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1382                                                sh->service_name,
1383                                                "PIDFILE",
1384                                                &pif))
1385     return NULL;
1386   return pif;
1387 }
1388
1389
1390 /**
1391  * Delete the PID file that was created by our parent.
1392  *
1393  * @param sh service context
1394  */
1395 static void
1396 pid_file_delete (struct GNUNET_SERVICE_Handle *sh)
1397 {
1398   char *pif = get_pid_file_name (sh);
1399
1400   if (NULL == pif)
1401     return;                     /* no PID file */
1402   if (0 != UNLINK (pif))
1403     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
1404                        "unlink",
1405                        pif);
1406   GNUNET_free (pif);
1407 }
1408
1409
1410 /**
1411  * Detach from terminal.
1412  *
1413  * @param sh service context
1414  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1415  */
1416 static int
1417 detach_terminal (struct GNUNET_SERVICE_Handle *sh)
1418 {
1419 #ifndef MINGW
1420   pid_t pid;
1421   int nullfd;
1422   int filedes[2];
1423
1424   if (0 != PIPE (filedes))
1425   {
1426     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1427                   "pipe");
1428     return GNUNET_SYSERR;
1429   }
1430   pid = fork ();
1431   if (pid < 0)
1432   {
1433     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1434                   "fork");
1435     return GNUNET_SYSERR;
1436   }
1437   if (0 != pid)
1438   {
1439     /* Parent */
1440     char c;
1441
1442     GNUNET_break (0 == CLOSE (filedes[1]));
1443     c = 'X';
1444     if (1 != READ (filedes[0],
1445                    &c,
1446                    sizeof (char)))
1447       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
1448                     "read");
1449     fflush (stdout);
1450     switch (c)
1451     {
1452     case '.':
1453       exit (0);
1454     case 'I':
1455       LOG (GNUNET_ERROR_TYPE_INFO,
1456            _("Service process failed to initialize\n"));
1457       break;
1458     case 'S':
1459       LOG (GNUNET_ERROR_TYPE_INFO,
1460            _("Service process could not initialize server function\n"));
1461       break;
1462     case 'X':
1463       LOG (GNUNET_ERROR_TYPE_INFO,
1464            _("Service process failed to report status\n"));
1465       break;
1466     }
1467     exit (1);                   /* child reported error */
1468   }
1469   GNUNET_break (0 == CLOSE (0));
1470   GNUNET_break (0 == CLOSE (1));
1471   GNUNET_break (0 == CLOSE (filedes[0]));
1472   nullfd = OPEN ("/dev/null",
1473                  O_RDWR | O_APPEND);
1474   if (nullfd < 0)
1475     return GNUNET_SYSERR;
1476   /* set stdin/stdout to /dev/null */
1477   if ( (dup2 (nullfd, 0) < 0) ||
1478        (dup2 (nullfd, 1) < 0) )
1479   {
1480     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1481                   "dup2");
1482     (void) CLOSE (nullfd);
1483     return GNUNET_SYSERR;
1484   }
1485   (void) CLOSE (nullfd);
1486   /* Detach from controlling terminal */
1487   pid = setsid ();
1488   if (-1 == pid)
1489     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1490                   "setsid");
1491   sh->ready_confirm_fd = filedes[1];
1492 #else
1493   /* FIXME: we probably need to do something else
1494    * elsewhere in order to fork the process itself... */
1495   FreeConsole ();
1496 #endif
1497   return GNUNET_OK;
1498 }
1499
1500
1501 /**
1502  * Creates the "main" function for a GNUnet service.  You
1503  * should almost always use the #GNUNET_SERVICE_MAIN macro
1504  * instead of calling this function directly (except
1505  * for ARM, which should call this function directly).
1506  *
1507  * The function will launch the service with the name @a service_name
1508  * using the @a service_options to configure its shutdown
1509  * behavior. Once the service is ready, the @a init_cb will be called
1510  * for service-specific initialization.  @a init_cb will be given the
1511  * service handler which can be used to control the service's
1512  * availability.  When clients connect or disconnect, the respective
1513  * @a connect_cb or @a disconnect_cb functions will be called. For
1514  * messages received from the clients, the respective @a handlers will
1515  * be invoked; for the closure of the handlers we use the return value
1516  * from the @a connect_cb invocation of the respective client.
1517  *
1518  * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1519  * message to receive further messages from this client.  If
1520  * #GNUNET_SERVICE_client_continue() is not called within a short
1521  * time, a warning will be logged. If delays are expected, services
1522  * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1523  * disable the warning.
1524  *
1525  * Clients sending invalid messages (based on @a handlers) will be
1526  * dropped. Additionally, clients can be dropped at any time using
1527  * #GNUNET_SERVICE_client_drop().
1528  *
1529  * @param argc number of command-line arguments in @a argv
1530  * @param argv array of command-line arguments
1531  * @param service_name name of the service to run
1532  * @param options options controlling shutdown of the service
1533  * @param service_init_cb function to call once the service is ready
1534  * @param connect_cb function to call whenever a client connects
1535  * @param disconnect_cb function to call whenever a client disconnects
1536  * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
1537  * @param handlers NULL-terminated array of message handlers for the service,
1538  *                 the closure will be set to the value returned by
1539  *                 the @a connect_cb for the respective connection
1540  * @return 0 on success, non-zero on error
1541  */
1542 int
1543 GNUNET_SERVICE_ruN_ (int argc,
1544                      char *const *argv,
1545                      const char *service_name,
1546                      enum GNUNET_SERVICE_Options options,
1547                      GNUNET_SERVICE_InitCallback service_init_cb,
1548                      GNUNET_SERVICE_ConnectHandler connect_cb,
1549                      GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1550                      void *cls,
1551                      const struct GNUNET_MQ_MessageHandler *handlers)
1552 {
1553   struct GNUNET_SERVICE_Handle sh;
1554   char *cfg_filename;
1555   char *opt_cfg_filename;
1556   char *loglev;
1557   const char *xdg;
1558   char *logfile;
1559   int do_daemonize;
1560   unsigned long long skew_offset;
1561   unsigned long long skew_variance;
1562   long long clock_offset;
1563   struct GNUNET_CONFIGURATION_Handle *cfg;
1564   int ret;
1565   int err;
1566
1567   struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1568     GNUNET_GETOPT_OPTION_CFG_FILE (&opt_cfg_filename),
1569     {'d', "daemonize", NULL,
1570      gettext_noop ("do daemonize (detach from terminal)"), 0,
1571      GNUNET_GETOPT_set_one, &do_daemonize},
1572     GNUNET_GETOPT_OPTION_HELP (NULL),
1573     GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
1574     GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
1575     GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION),
1576     GNUNET_GETOPT_OPTION_END
1577   };
1578
1579   xdg = getenv ("XDG_CONFIG_HOME");
1580   if (NULL != xdg)
1581     GNUNET_asprintf (&cfg_filename,
1582                      "%s%s%s",
1583                      xdg,
1584                      DIR_SEPARATOR_STR,
1585                      GNUNET_OS_project_data_get ()->config_file);
1586   else
1587     cfg_filename = GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
1588
1589   sh.options = options;
1590   sh.cfg = cfg = GNUNET_CONFIGURATION_create ();
1591   sh.service_init_cb = service_init_cb;
1592   sh.connect_cb = connect_cb;
1593   sh.disconnect_cb = disconnect_cb;
1594   sh.cb_cls = cls;
1595   sh.handlers = handlers;
1596
1597   /* setup subsystems */
1598   ret = GNUNET_GETOPT_run (service_name,
1599                            service_options,
1600                            argc,
1601                            argv);
1602   if (GNUNET_SYSERR == ret)
1603     goto shutdown;
1604   if (GNUNET_NO == ret)
1605   {
1606     err = 0;
1607     goto shutdown;
1608   }
1609   if (GNUNET_OK != GNUNET_log_setup (service_name,
1610                                      loglev,
1611                                      logfile))
1612   {
1613     GNUNET_break (0);
1614     goto shutdown;
1615   }
1616   if (NULL == opt_cfg_filename)
1617     opt_cfg_filename = GNUNET_strdup (cfg_filename);
1618   if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename))
1619   {
1620     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg,
1621                                                     opt_cfg_filename))
1622     {
1623       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1624                   _("Malformed configuration file `%s', exit ...\n"),
1625                   opt_cfg_filename);
1626       goto shutdown;
1627     }
1628   }
1629   else
1630   {
1631     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg,
1632                                                     NULL))
1633     {
1634       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1635                   _("Malformed configuration, exit ...\n"));
1636       goto shutdown;
1637     }
1638     if (0 != strcmp (opt_cfg_filename,
1639                      cfg_filename))
1640       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1641                   _("Could not access configuration file `%s'\n"),
1642                   opt_cfg_filename);
1643   }
1644   if (GNUNET_OK != setup_service (&sh))
1645     goto shutdown;
1646   if ( (1 == do_daemonize) &&
1647        (GNUNET_OK != detach_terminal (&sh)) )
1648   {
1649     GNUNET_break (0);
1650     goto shutdown;
1651   }
1652   if (GNUNET_OK != set_user_id (&sh))
1653     goto shutdown;
1654   LOG (GNUNET_ERROR_TYPE_DEBUG,
1655        "Service `%s' runs with configuration from `%s'\n",
1656        service_name,
1657        opt_cfg_filename);
1658   if ((GNUNET_OK ==
1659        GNUNET_CONFIGURATION_get_value_number (sh.cfg,
1660                                               "TESTING",
1661                                               "SKEW_OFFSET",
1662                                               &skew_offset)) &&
1663       (GNUNET_OK ==
1664        GNUNET_CONFIGURATION_get_value_number (sh.cfg,
1665                                               "TESTING",
1666                                               "SKEW_VARIANCE",
1667                                               &skew_variance)))
1668   {
1669     clock_offset = skew_offset - skew_variance;
1670     GNUNET_TIME_set_offset (clock_offset);
1671     LOG (GNUNET_ERROR_TYPE_DEBUG,
1672          "Skewing clock by %dll ms\n",
1673          clock_offset);
1674   }
1675   /* actually run service */
1676   err = 0;
1677   GNUNET_SCHEDULER_run (&service_main,
1678                         &sh);
1679   /* shutdown */
1680   if (1 == do_daemonize)
1681     pid_file_delete (&sh);
1682
1683 shutdown:
1684   if (-1 != sh.ready_confirm_fd)
1685   {
1686     if (1 != WRITE (sh.ready_confirm_fd, err ? "I" : "S", 1))
1687       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
1688     GNUNET_break (0 == CLOSE (sh.ready_confirm_fd));
1689   }
1690 #if HAVE_MALLINFO
1691   {
1692     char *counter;
1693
1694     if ( (GNUNET_YES ==
1695           GNUNET_CONFIGURATION_have_value (sh.cfg,
1696                                            service_name,
1697                                            "GAUGER_HEAP")) &&
1698          (GNUNET_OK ==
1699           GNUNET_CONFIGURATION_get_value_string (sh.cfg,
1700                                                  service_name,
1701                                                  "GAUGER_HEAP",
1702                                                  &counter)) )
1703     {
1704       struct mallinfo mi;
1705
1706       mi = mallinfo ();
1707       GAUGER (service_name,
1708               counter,
1709               mi.usmblks,
1710               "blocks");
1711       GNUNET_free (counter);
1712     }
1713   }
1714 #endif
1715   GNUNET_SPEEDUP_stop_ ();
1716   GNUNET_CONFIGURATION_destroy (cfg);
1717
1718   while (NULL != sh.slc_head)
1719   {
1720     struct ServiceListenContext *slc = sh.slc_head;
1721
1722     sh.slc_head = slc->next;
1723     if (NULL != slc->listen_task)
1724       GNUNET_SCHEDULER_cancel (slc->listen_task);
1725     GNUNET_break (GNUNET_OK ==
1726                   GNUNET_NETWORK_socket_close (slc->listen_socket));
1727     GNUNET_free (slc);
1728   }
1729
1730   GNUNET_free_non_null (logfile);
1731   GNUNET_free_non_null (loglev);
1732   GNUNET_free (cfg_filename);
1733   GNUNET_free_non_null (opt_cfg_filename);
1734   GNUNET_free_non_null (sh.v4_denied);
1735   GNUNET_free_non_null (sh.v6_denied);
1736   GNUNET_free_non_null (sh.v4_allowed);
1737   GNUNET_free_non_null (sh.v6_allowed);
1738
1739   return err ? GNUNET_SYSERR : sh.ret;
1740 }
1741
1742
1743 /**
1744  * Suspend accepting connections from the listen socket temporarily.
1745  * Resume activity using #GNUNET_SERVICE_resume.
1746  *
1747  * @param sh service to stop accepting connections.
1748  */
1749 void
1750 GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
1751 {
1752   struct ServiceListenContext *slc;
1753
1754   for (slc = sh->slc_head; NULL != slc; slc = slc->next)
1755   {
1756     if (NULL != slc->listen_task)
1757     {
1758       GNUNET_SCHEDULER_cancel (slc->listen_task);
1759       slc->listen_task = NULL;
1760     }
1761   }
1762 }
1763
1764
1765 /**
1766  * Signature of functions implementing the sending functionality of a
1767  * message queue.
1768  *
1769  * @param mq the message queue
1770  * @param msg the message to send
1771  * @param impl_state state of the implementation
1772  */
1773 static void
1774 service_mq_send (struct GNUNET_MQ_Handle *mq,
1775                  const struct GNUNET_MessageHeader *msg,
1776                  void *impl_state)
1777 {
1778   // struct GNUNET_SERVICE_Client *client = cls;
1779
1780   // FIXME 1: setup "client->send_task" for transmission.
1781   // FIXME 2: I seriously hope we do not need to make a copy of `msg`!
1782   // OPTIMIZATION: ideally, we'd like the ability to peak at the rest of
1783   //               the queue and transmit more than one message if possible.
1784 }
1785
1786
1787 /**
1788  * Implementation function that cancels the currently sent message.
1789  *
1790  * @param mq message queue
1791  * @param impl_state state specific to the implementation
1792  */
1793 static void
1794 service_mq_cancel (struct GNUNET_MQ_Handle *mq,
1795                    void *impl_state)
1796 {
1797   // struct GNUNET_SERVICE_Client *client = cls;
1798
1799   // FIXME: stop transmission! (must be possible, otherwise
1800   // we must have told MQ that the message was sent!)
1801 }
1802
1803
1804 /**
1805  * Generic error handler, called with the appropriate
1806  * error code and the same closure specified at the creation of
1807  * the message queue.
1808  * Not every message queue implementation supports an error handler.
1809  *
1810  * @param cls closure with our `struct GNUNET_SERVICE_Client`
1811  * @param error error code
1812  */
1813 static void
1814 service_mq_error_handler (void *cls,
1815                           enum GNUNET_MQ_Error error)
1816 {
1817   struct GNUNET_SERVICE_Client *client = cls;
1818   struct GNUNET_SERVICE_Handle *sh = client->sh;
1819
1820   if ( (GNUNET_MQ_ERROR_NO_MATCH == error) &&
1821        (GNUNET_NO == sh->require_found) )
1822     return; /* ignore error */
1823   GNUNET_SERVICE_client_drop (client);
1824 }
1825
1826
1827 /**
1828  * Task run to warn about missing calls to #GNUNET_SERVICE_client_continue().
1829  *
1830  * @param cls our `struct GNUNET_SERVICE_Client *` to process more requests from
1831  */
1832 static void
1833 warn_no_client_continue (void *cls)
1834 {
1835   struct GNUNET_SERVICE_Client *client = cls;
1836
1837   GNUNET_break (0 != client->warn_type); /* type should never be 0 here, as we don't use 0 */
1838   client->warn_task 
1839     = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
1840                                     &warn_no_client_continue,
1841                                     client);
1842   LOG (GNUNET_ERROR_TYPE_WARNING,
1843        _("Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
1844        (unsigned int) client->warn_type,
1845        GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (client->warn_start),
1846                                                GNUNET_YES));
1847 }
1848
1849
1850 /**
1851  * Functions with this signature are called whenever a
1852  * complete message is received by the tokenizer for a client.
1853  *
1854  * Do not call #GNUNET_MST_destroy() from within
1855  * the scope of this callback.
1856  *
1857  * @param cls closure with the `struct GNUNET_SERVICE_Client *`
1858  * @param message the actual message
1859  * @return #GNUNET_OK on success (always)
1860  */
1861 static int
1862 service_client_mst_cb (void *cls,
1863                        const struct GNUNET_MessageHeader *message)
1864 {
1865   struct GNUNET_SERVICE_Client *client = cls;
1866
1867   GNUNET_assert (GNUNET_NO == client->needs_continue);
1868   client->needs_continue = GNUNET_YES;
1869   client->warn_type = ntohs (message->type);
1870   client->warn_start = GNUNET_TIME_absolute_get ();
1871   client->warn_task
1872     = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
1873                                     &warn_no_client_continue,
1874                                     client);
1875   GNUNET_MQ_inject_message (client->mq,
1876                             message);
1877   return GNUNET_OK;
1878 }
1879
1880
1881 /**
1882  * A client sent us data. Receive and process it.  If we are done,
1883  * reschedule this task.
1884  *
1885  * @param cls the `struct GNUNET_SERVICE_Client` that sent us data.
1886  */
1887 static void
1888 service_client_recv (void *cls)
1889 {
1890   struct GNUNET_SERVICE_Client *client = cls;
1891   int ret;
1892
1893   client->recv_task = NULL;
1894   ret = GNUNET_MST_read (client->mst,
1895                          client->sock,
1896                          GNUNET_NO,
1897                          GNUNET_YES);
1898   if (GNUNET_SYSERR == ret)
1899   {
1900     GNUNET_break (0);
1901     GNUNET_SERVICE_client_drop (client);
1902     return;
1903   }
1904   if (GNUNET_NO == ret)
1905     return; /* more messages in buffer, wait for application
1906                to be done processing */
1907   GNUNET_assert (GNUNET_OK == ret);
1908   if (GNUNET_YES == client->needs_continue)
1909     return;
1910   /* MST needs more data, re-schedule read job */
1911   client->recv_task
1912     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1913                                      client->sock,
1914                                      &service_client_recv,
1915                                      client);
1916 }
1917
1918
1919 /**
1920  * We have successfully accepted a connection from a client.  Now
1921  * setup the client (with the scheduler) and tell the application.
1922  *
1923  * @param sh service that accepted the client
1924  * @param sock socket associated with the client
1925  */
1926 static void
1927 start_client (struct GNUNET_SERVICE_Handle *sh,
1928               struct GNUNET_NETWORK_Handle *csock)
1929 {
1930   struct GNUNET_SERVICE_Client *client;
1931
1932   client = GNUNET_new (struct GNUNET_SERVICE_Client);
1933   GNUNET_CONTAINER_DLL_insert (sh->clients_head,
1934                                sh->clients_tail,
1935                                client);
1936   client->sh = sh;
1937   client->sock = csock;
1938   client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send,
1939                                               NULL,
1940                                               &service_mq_cancel,
1941                                               client,
1942                                               sh->handlers,
1943                                               &service_mq_error_handler,
1944                                               client);
1945   client->mst = GNUNET_MST_create (&service_client_mst_cb,
1946                                    client);
1947   client->user_context = sh->connect_cb (sh->cb_cls,
1948                                          client,
1949                                          client->mq);
1950   GNUNET_MQ_set_handlers_closure (client->mq,
1951                                   client->user_context);
1952   client->recv_task
1953     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1954                                      client->sock,
1955                                      &service_client_recv,
1956                                      client);
1957 }
1958
1959
1960 /**
1961  * Check if the given IP address is in the list of IP addresses.
1962  *
1963  * @param list a list of networks
1964  * @param add the IP to check (in network byte order)
1965  * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
1966  */
1967 static int
1968 check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
1969                    const struct in_addr *add)
1970 {
1971   unsigned int i;
1972
1973   if (NULL == list)
1974     return GNUNET_NO;
1975   i = 0;
1976   while ( (0 != list[i].network.s_addr) ||
1977           (0 != list[i].netmask.s_addr) )
1978   {
1979     if ((add->s_addr & list[i].netmask.s_addr) ==
1980         (list[i].network.s_addr & list[i].netmask.s_addr))
1981       return GNUNET_YES;
1982     i++;
1983   }
1984   return GNUNET_NO;
1985 }
1986
1987
1988 /**
1989  * Check if the given IP address is in the list of IP addresses.
1990  *
1991  * @param list a list of networks
1992  * @param ip the IP to check (in network byte order)
1993  * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
1994  */
1995 static int
1996 check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
1997                    const struct in6_addr *ip)
1998 {
1999   unsigned int i;
2000   unsigned int j;
2001   struct in6_addr zero;
2002
2003   if (NULL == list)
2004     return GNUNET_NO;
2005   memset (&zero,
2006           0,
2007           sizeof (struct in6_addr));
2008   i = 0;
2009 NEXT:
2010   while (0 != memcmp (&zero,
2011                       &list[i].network,
2012                       sizeof (struct in6_addr)))
2013   {
2014     for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
2015       if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
2016           (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
2017       {
2018         i++;
2019         goto NEXT;
2020       }
2021     return GNUNET_YES;
2022   }
2023   return GNUNET_NO;
2024 }
2025
2026
2027 /**
2028  * We have a client. Accept the incoming socket(s) (and reschedule
2029  * the listen task).
2030  *
2031  * @param cls the `struct ServiceListenContext` of the ready listen socket
2032  */
2033 static void
2034 accept_client (void *cls)
2035 {
2036   struct ServiceListenContext *slc = cls;
2037   struct GNUNET_SERVICE_Handle *sh = slc->sh;
2038
2039   slc->listen_task = NULL;
2040   while (1)
2041   {
2042     struct GNUNET_NETWORK_Handle *sock;
2043     const struct sockaddr_in *v4;
2044     const struct sockaddr_in6 *v6;
2045     struct sockaddr_storage sa;
2046     socklen_t addrlen;
2047     int ok;
2048     
2049     addrlen = sizeof (sa);
2050     sock = GNUNET_NETWORK_socket_accept (slc->listen_socket,
2051                                          (struct sockaddr *) &sa,
2052                                          &addrlen);
2053     if (NULL == sock)
2054       break;
2055     switch (sa.ss_family)
2056     {
2057     case AF_INET:
2058       GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
2059       v4 = (const struct sockaddr_in *) &sa;
2060       ok = ( ( (NULL == sh->v4_allowed) ||
2061                (check_ipv4_listed (sh->v4_allowed,
2062                                    &v4->sin_addr))) &&
2063              ( (NULL == sh->v4_denied) ||
2064                (! check_ipv4_listed (sh->v4_denied,
2065                                      &v4->sin_addr)) ) );
2066       break;
2067     case AF_INET6:
2068       GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
2069       v6 = (const struct sockaddr_in6 *) &sa;
2070       ok = ( ( (NULL == sh->v6_allowed) ||
2071                (check_ipv6_listed (sh->v6_allowed,
2072                                    &v6->sin6_addr))) &&
2073              ( (NULL == sh->v6_denied) ||
2074                (! check_ipv6_listed (sh->v6_denied,
2075                                      &v6->sin6_addr)) ) );
2076       break;
2077 #ifndef WINDOWS
2078     case AF_UNIX:
2079       ok = GNUNET_OK;            /* controlled using file-system ACL now */
2080       break;
2081 #endif
2082     default:
2083       LOG (GNUNET_ERROR_TYPE_WARNING,
2084            _("Unknown address family %d\n"),
2085            sa.ss_family);
2086       return;
2087     }
2088     if (! ok)
2089     {
2090       LOG (GNUNET_ERROR_TYPE_DEBUG,
2091            "Service rejected incoming connection from %s due to policy.\n",
2092            GNUNET_a2s ((const struct sockaddr *) &sa,
2093                        addrlen));
2094       GNUNET_break (GNUNET_OK ==
2095                     GNUNET_NETWORK_socket_close (sock));
2096       continue;
2097     }
2098     LOG (GNUNET_ERROR_TYPE_DEBUG,
2099          "Service accepted incoming connection from %s.\n",
2100          GNUNET_a2s ((const struct sockaddr *) &sa,
2101                      addrlen));
2102     start_client (slc->sh,
2103                   sock);
2104   }
2105   slc->listen_task
2106     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2107                                      slc->listen_socket,
2108                                      &accept_client,
2109                                      slc);
2110 }
2111
2112
2113 /**
2114  * Resume accepting connections from the listen socket.
2115  *
2116  * @param sh service to resume accepting connections.
2117  */
2118 void
2119 GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
2120 {
2121   struct ServiceListenContext *slc;
2122
2123   for (slc = sh->slc_head; NULL != slc; slc = slc->next)
2124   {
2125     GNUNET_assert (NULL == slc->listen_task);
2126     slc->listen_task
2127       = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2128                                        slc->listen_socket,
2129                                        &accept_client,
2130                                        slc);
2131   }
2132 }
2133
2134
2135 /**
2136  * Task run to resume receiving data from the client after
2137  * the client called #GNUNET_SERVICE_client_continue().
2138  *
2139  * @param cls our `struct GNUNET_SERVICE_Client`
2140  */
2141 static void
2142 resume_client_receive (void *cls)
2143 {
2144   struct GNUNET_SERVICE_Client *c = cls;
2145   int ret;
2146
2147   c->recv_task = NULL;
2148   /* first, check if there is still something in the buffer */
2149   ret = GNUNET_MST_next (c->mst,
2150                          GNUNET_YES);
2151   if (GNUNET_SYSERR == ret)
2152   {
2153     GNUNET_break (0);
2154     GNUNET_SERVICE_client_drop (c);
2155     return;
2156   }
2157   if (GNUNET_NO == ret)
2158     return; /* done processing, wait for more later */
2159   GNUNET_assert (GNUNET_OK == ret);
2160   if (GNUNET_YES == c->needs_continue)
2161     return; /* #GNUNET_MST_next() did give a message to the client */
2162   /* need to receive more data from the network first */
2163   c->recv_task
2164     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2165                                      c->sock,
2166                                      &service_client_recv,
2167                                      c);  
2168 }
2169
2170
2171 /**
2172  * Continue receiving further messages from the given client.
2173  * Must be called after each message received.
2174  *
2175  * @param c the client to continue receiving from
2176  */
2177 void
2178 GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
2179 {
2180   GNUNET_assert (GNUNET_YES == c->needs_continue);
2181   GNUNET_assert (NULL == c->recv_task);
2182   c->needs_continue = GNUNET_NO;
2183   if (NULL != c->warn_task)
2184   {
2185     GNUNET_SCHEDULER_cancel (c->warn_task);
2186     c->warn_task = NULL;
2187   }
2188   c->recv_task = GNUNET_SCHEDULER_add_now (&resume_client_receive,
2189                                            c);
2190 }
2191
2192
2193 /**
2194  * Disable the warning the server issues if a message is not
2195  * acknowledged in a timely fashion.  Use this call if a client is
2196  * intentionally delayed for a while.  Only applies to the current
2197  * message.
2198  *
2199  * @param c client for which to disable the warning
2200  */
2201 void
2202 GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
2203 {
2204   GNUNET_break (NULL != c->warn_task);
2205   if (NULL != c->warn_task)
2206   {
2207     GNUNET_SCHEDULER_cancel (c->warn_task);
2208     c->warn_task = NULL;
2209   }
2210 }
2211
2212
2213 /**
2214  * Ask the server to disconnect from the given client.  This is the
2215  * same as returning #GNUNET_SYSERR within the check procedure when
2216  * handling a message, wexcept that it allows dropping of a client even
2217  * when not handling a message from that client.  The `disconnect_cb`
2218  * will be called on @a c even if the application closes the connection
2219  * using this function.
2220  *
2221  * @param c client to disconnect now
2222  */
2223 void
2224 GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2225 {
2226   struct GNUNET_SERVICE_Handle *sh = c->sh;
2227
2228   GNUNET_CONTAINER_DLL_remove (sh->clients_head,
2229                                sh->clients_tail,
2230                                c);
2231   sh->disconnect_cb (sh->cb_cls,
2232                      c,
2233                      c->user_context);
2234   if (NULL != c->warn_task)
2235   {
2236     GNUNET_SCHEDULER_cancel (c->warn_task);
2237     c->warn_task = NULL;
2238   }
2239   if (NULL != c->recv_task)
2240   {
2241     GNUNET_SCHEDULER_cancel (c->recv_task);
2242     c->recv_task = NULL;
2243   }
2244   if (NULL != c->send_task)
2245   {
2246     GNUNET_SCHEDULER_cancel (c->send_task);
2247     c->send_task = NULL;
2248   }
2249   GNUNET_MST_destroy (c->mst);
2250   GNUNET_MQ_destroy (c->mq);
2251   if (GNUNET_NO == c->persist)
2252   {
2253     GNUNET_break (GNUNET_OK ==
2254                   GNUNET_NETWORK_socket_close (c->sock));
2255   }
2256   else
2257   {
2258     GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
2259   }
2260   GNUNET_free (c);
2261   if ( (GNUNET_YES == sh->got_shutdown) &&
2262        (GNUNET_NO == have_non_monitor_clients (sh)) )
2263     GNUNET_SERVICE_shutdown (sh);
2264 }
2265
2266
2267 /**
2268  * Explicitly stops the service.
2269  *
2270  * @param sh server to shutdown
2271  */
2272 void
2273 GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
2274 {
2275   struct GNUNET_SERVICE_Client *client;
2276
2277   GNUNET_SERVICE_suspend (sh);
2278   sh->got_shutdown = GNUNET_NO;
2279   while (NULL != (client = sh->clients_head))
2280     GNUNET_SERVICE_client_drop (client);
2281 }
2282
2283
2284 /**
2285  * Set the 'monitor' flag on this client.  Clients which have been
2286  * marked as 'monitors' won't prevent the server from shutting down
2287  * once #GNUNET_SERVICE_stop_listening() has been invoked.  The idea is
2288  * that for "normal" clients we likely want to allow them to process
2289  * their requests; however, monitor-clients are likely to 'never'
2290  * disconnect during shutdown and thus will not be considered when
2291  * determining if the server should continue to exist after
2292  * shutdown has been triggered.
2293  *
2294  * @param c client to mark as a monitor
2295  */
2296 void
2297 GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
2298 {
2299   c->is_monitor = GNUNET_YES;
2300   if ( (GNUNET_YES == c->sh->got_shutdown) &&
2301        (GNUNET_NO == have_non_monitor_clients (c->sh)) )
2302     GNUNET_SERVICE_shutdown (c->sh);
2303 }
2304
2305
2306 /**
2307  * Set the persist option on this client.  Indicates that the
2308  * underlying socket or fd should never really be closed.  Used for
2309  * indicating process death.
2310  *
2311  * @param c client to persist the socket (never to be closed)
2312  */
2313 void
2314 GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
2315 {
2316   c->persist = GNUNET_YES;
2317 }
2318
2319
2320 /* end of service_new.c */