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