make service_new (almost) compile
[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_main (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  * Parse an IPv4 access control list.
348  *
349  * @param ret location where to write the ACL (set)
350  * @param sh service context to use to get the configuration
351  * @param option name of the ACL option to parse
352  * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
353  *         no ACL configured)
354  */
355 static int
356 process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret,
357               struct GNUNET_SERVICE_Handle *sh,
358               const char *option)
359 {
360   char *opt;
361
362   if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
363   {
364     *ret = NULL;
365     return GNUNET_OK;
366   }
367   GNUNET_break (GNUNET_OK ==
368                 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
369                                                        sh->service_name,
370                                                        option, &opt));
371   if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
372   {
373     LOG (GNUNET_ERROR_TYPE_WARNING,
374          _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
375          opt, sh->service_name, option);
376     GNUNET_free (opt);
377     return GNUNET_SYSERR;
378   }
379   GNUNET_free (opt);
380   return GNUNET_OK;
381 }
382
383
384 /**
385  * Parse an IPv6 access control list.
386  *
387  * @param ret location where to write the ACL (set)
388  * @param sh service context to use to get the configuration
389  * @param option name of the ACL option to parse
390  * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
391  *         no ACL configured)
392  */
393 static int
394 process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret,
395               struct GNUNET_SERVICE_Handle *sh,
396               const char *option)
397 {
398   char *opt;
399
400   if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
401   {
402     *ret = NULL;
403     return GNUNET_OK;
404   }
405   GNUNET_break (GNUNET_OK ==
406                 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
407                                                        sh->service_name,
408                                                        option, &opt));
409   if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
410   {
411     LOG (GNUNET_ERROR_TYPE_WARNING,
412          _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
413          opt, sh->service_name, option);
414     GNUNET_free (opt);
415     return GNUNET_SYSERR;
416   }
417   GNUNET_free (opt);
418   return GNUNET_OK;
419 }
420
421
422 /**
423  * Get the list of addresses that a server for the given service
424  * should bind to.
425  *
426  * @param service_name name of the service
427  * @param cfg configuration (which specifies the addresses)
428  * @param addrs set (call by reference) to an array of pointers to the
429  *              addresses the server should bind to and listen on; the
430  *              array will be NULL-terminated (on success)
431  * @param addr_lens set (call by reference) to an array of the lengths
432  *              of the respective `struct sockaddr` struct in the @a addrs
433  *              array (on success)
434  * @return number of addresses found on success,
435  *              #GNUNET_SYSERR if the configuration
436  *              did not specify reasonable finding information or
437  *              if it specified a hostname that could not be resolved;
438  *              #GNUNET_NO if the number of addresses configured is
439  *              zero (in this case, `*addrs` and `*addr_lens` will be
440  *              set to NULL).
441  */
442 static int
443 get_server_addresses (const char *service_name,
444                                      const struct GNUNET_CONFIGURATION_Handle *cfg,
445                                      struct sockaddr ***addrs,
446                                      socklen_t ** addr_lens)
447 {
448   int disablev6;
449   struct GNUNET_NETWORK_Handle *desc;
450   unsigned long long port;
451   char *unixpath;
452   struct addrinfo hints;
453   struct addrinfo *res;
454   struct addrinfo *pos;
455   struct addrinfo *next;
456   unsigned int i;
457   int resi;
458   int ret;
459   int abstract;
460   struct sockaddr **saddrs;
461   socklen_t *saddrlens;
462   char *hostname;
463
464   *addrs = NULL;
465   *addr_lens = NULL;
466   desc = NULL;
467   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
468   {
469     if (GNUNET_SYSERR ==
470         (disablev6 =
471          GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
472       return GNUNET_SYSERR;
473   }
474   else
475     disablev6 = GNUNET_NO;
476
477   if (! disablev6)
478   {
479     /* probe IPv6 support */
480     desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
481     if (NULL == desc)
482     {
483       if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
484           (EACCES == errno))
485       {
486         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
487         return GNUNET_SYSERR;
488       }
489       LOG (GNUNET_ERROR_TYPE_INFO,
490            _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
491            service_name, STRERROR (errno));
492       disablev6 = GNUNET_YES;
493     }
494     else
495     {
496       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
497       desc = NULL;
498     }
499   }
500
501   port = 0;
502   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
503   {
504     if (GNUNET_OK !=
505         GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
506                                                "PORT", &port))
507     {
508       LOG (GNUNET_ERROR_TYPE_ERROR,
509            _("Require valid port number for service `%s' in configuration!\n"),
510            service_name);
511     }
512     if (port > 65535)
513     {
514       LOG (GNUNET_ERROR_TYPE_ERROR,
515            _("Require valid port number for service `%s' in configuration!\n"),
516            service_name);
517       return GNUNET_SYSERR;
518     }
519   }
520
521   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
522   {
523     GNUNET_break (GNUNET_OK ==
524                   GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
525                                                          "BINDTO", &hostname));
526   }
527   else
528     hostname = NULL;
529
530   unixpath = NULL;
531   abstract = GNUNET_NO;
532 #ifdef AF_UNIX
533   if ((GNUNET_YES ==
534        GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
535       (GNUNET_OK ==
536        GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
537                                               &unixpath)) &&
538       (0 < strlen (unixpath)))
539   {
540     /* probe UNIX support */
541     struct sockaddr_un s_un;
542
543     if (strlen (unixpath) >= sizeof (s_un.sun_path))
544     {
545       LOG (GNUNET_ERROR_TYPE_WARNING,
546            _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
547            (unsigned long long) sizeof (s_un.sun_path));
548       unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
549       LOG (GNUNET_ERROR_TYPE_INFO,
550            _("Using `%s' instead\n"),
551            unixpath);
552     }
553 #ifdef LINUX
554     abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
555                                                      "TESTING",
556                                                      "USE_ABSTRACT_SOCKETS");
557     if (GNUNET_SYSERR == abstract)
558       abstract = GNUNET_NO;
559 #endif
560     if ((GNUNET_YES != abstract)
561         && (GNUNET_OK !=
562             GNUNET_DISK_directory_create_for_file (unixpath)))
563       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
564                                 "mkdir",
565                                 unixpath);
566   }
567   if (NULL != unixpath)
568   {
569     desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
570     if (NULL == desc)
571     {
572       if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
573           (EACCES == errno))
574       {
575         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
576         GNUNET_free_non_null (hostname);
577         GNUNET_free (unixpath);
578         return GNUNET_SYSERR;
579       }
580       LOG (GNUNET_ERROR_TYPE_INFO,
581            _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
582            service_name,
583            STRERROR (errno));
584       GNUNET_free (unixpath);
585       unixpath = NULL;
586     }
587     else
588     {
589       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
590       desc = NULL;
591     }
592   }
593 #endif
594
595   if ((0 == port) && (NULL == unixpath))
596   {
597     LOG (GNUNET_ERROR_TYPE_ERROR,
598          _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
599          service_name);
600     GNUNET_free_non_null (hostname);
601     return GNUNET_SYSERR;
602   }
603   if (0 == port)
604   {
605     saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
606     saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
607     add_unixpath (saddrs, saddrlens, unixpath, abstract);
608     GNUNET_free_non_null (unixpath);
609     GNUNET_free_non_null (hostname);
610     *addrs = saddrs;
611     *addr_lens = saddrlens;
612     return 1;
613   }
614
615   if (NULL != hostname)
616   {
617     LOG (GNUNET_ERROR_TYPE_DEBUG,
618          "Resolving `%s' since that is where `%s' will bind to.\n",
619          hostname,
620          service_name);
621     memset (&hints, 0, sizeof (struct addrinfo));
622     if (disablev6)
623       hints.ai_family = AF_INET;
624     hints.ai_protocol = IPPROTO_TCP;
625     if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
626         (NULL == res))
627     {
628       LOG (GNUNET_ERROR_TYPE_ERROR,
629            _("Failed to resolve `%s': %s\n"),
630            hostname,
631            gai_strerror (ret));
632       GNUNET_free (hostname);
633       GNUNET_free_non_null (unixpath);
634       return GNUNET_SYSERR;
635     }
636     next = res;
637     i = 0;
638     while (NULL != (pos = next))
639     {
640       next = pos->ai_next;
641       if ((disablev6) && (pos->ai_family == AF_INET6))
642         continue;
643       i++;
644     }
645     if (0 == i)
646     {
647       LOG (GNUNET_ERROR_TYPE_ERROR,
648            _("Failed to find %saddress for `%s'.\n"),
649            disablev6 ? "IPv4 " : "",
650            hostname);
651       freeaddrinfo (res);
652       GNUNET_free (hostname);
653       GNUNET_free_non_null (unixpath);
654       return GNUNET_SYSERR;
655     }
656     resi = i;
657     if (NULL != unixpath)
658       resi++;
659     saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
660     saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
661     i = 0;
662     if (NULL != unixpath)
663     {
664       add_unixpath (saddrs, saddrlens, unixpath, abstract);
665       i++;
666     }
667     next = res;
668     while (NULL != (pos = next))
669     {
670       next = pos->ai_next;
671       if ((disablev6) && (AF_INET6 == pos->ai_family))
672         continue;
673       if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
674         continue;               /* not TCP */
675       if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
676         continue;               /* huh? */
677       LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
678            service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
679       if (AF_INET == pos->ai_family)
680       {
681         GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
682         saddrlens[i] = pos->ai_addrlen;
683         saddrs[i] = GNUNET_malloc (saddrlens[i]);
684         GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
685         ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
686       }
687       else
688       {
689         GNUNET_assert (AF_INET6 == pos->ai_family);
690         GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
691         saddrlens[i] = pos->ai_addrlen;
692         saddrs[i] = GNUNET_malloc (saddrlens[i]);
693         GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
694         ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
695       }
696       i++;
697     }
698     GNUNET_free (hostname);
699     freeaddrinfo (res);
700     resi = i;
701   }
702   else
703   {
704     /* will bind against everything, just set port */
705     if (disablev6)
706     {
707       /* V4-only */
708       resi = 1;
709       if (NULL != unixpath)
710         resi++;
711       i = 0;
712       saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
713       saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
714       if (NULL != unixpath)
715       {
716         add_unixpath (saddrs, saddrlens, unixpath, abstract);
717         i++;
718       }
719       saddrlens[i] = sizeof (struct sockaddr_in);
720       saddrs[i] = GNUNET_malloc (saddrlens[i]);
721 #if HAVE_SOCKADDR_IN_SIN_LEN
722       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
723 #endif
724       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
725       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
726     }
727     else
728     {
729       /* dual stack */
730       resi = 2;
731       if (NULL != unixpath)
732         resi++;
733       saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
734       saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
735       i = 0;
736       if (NULL != unixpath)
737       {
738         add_unixpath (saddrs, saddrlens, unixpath, abstract);
739         i++;
740       }
741       saddrlens[i] = sizeof (struct sockaddr_in6);
742       saddrs[i] = GNUNET_malloc (saddrlens[i]);
743 #if HAVE_SOCKADDR_IN_SIN_LEN
744       ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
745 #endif
746       ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
747       ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
748       i++;
749       saddrlens[i] = sizeof (struct sockaddr_in);
750       saddrs[i] = GNUNET_malloc (saddrlens[i]);
751 #if HAVE_SOCKADDR_IN_SIN_LEN
752       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
753 #endif
754       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
755       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
756     }
757   }
758   GNUNET_free_non_null (unixpath);
759   *addrs = saddrs;
760   *addr_lens = saddrlens;
761   return resi;
762 }
763
764
765 #ifdef MINGW
766 /**
767  * Read listen sockets from the parent process (ARM).
768  *
769  * @param sh service context to initialize
770  * @return #GNUNET_YES if ok, #GNUNET_NO if not ok (must bind yourself),
771  * and #GNUNET_SYSERR on error.
772  */
773 static int
774 receive_sockets_from_parent (struct GNUNET_SERVICE_Handle *sh)
775 {
776   const char *env_buf;
777   int fail;
778   uint64_t count;
779   uint64_t i;
780   HANDLE lsocks_pipe;
781
782   env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
783   if ((NULL == env_buf) || (strlen (env_buf) <= 0))
784     return GNUNET_NO;
785   /* Using W32 API directly here, because this pipe will
786    * never be used outside of this function, and it's just too much of a bother
787    * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
788    */
789   lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
790   if ( (0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
791     return GNUNET_NO;
792   fail = 1;
793   do
794   {
795     int ret;
796     int fail2;
797     DWORD rd;
798
799     ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
800     if ((0 == ret) || (sizeof (count) != rd) || (0 == count))
801       break;
802     sh->lsocks =
803         GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1));
804
805     fail2 = 1;
806     for (i = 0; i < count; i++)
807     {
808       WSAPROTOCOL_INFOA pi;
809       uint64_t size;
810       SOCKET s;
811
812       ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
813       if ( (0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size) )
814         break;
815       ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
816       if ( (0 == ret) || (sizeof (pi) != rd))
817         break;
818       s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED);
819       sh->lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
820       if (NULL == sh->lsocks[i])
821         break;
822       else if (i == count - 1)
823         fail2 = 0;
824     }
825     if (fail2)
826       break;
827     sh->lsocks[count] = NULL;
828     fail = 0;
829   }
830   while (fail);
831
832   CloseHandle (lsocks_pipe);
833
834   if (fail)
835   {
836     LOG (GNUNET_ERROR_TYPE_ERROR,
837          _("Could not access a pre-bound socket, will try to bind myself\n"));
838     for (i = 0; (i < count) && (NULL != sh->lsocks[i]); i++)
839       GNUNET_break (0 == GNUNET_NETWORK_socket_close (sh->lsocks[i]));
840     GNUNET_free_non_null (sh->lsocks);
841     sh->lsocks = NULL;
842     return GNUNET_NO;
843   }
844   return GNUNET_YES;
845 }
846 #endif
847
848
849 /**
850  * Create and initialize a listen socket for the server.
851  *
852  * @param server_addr address to listen on
853  * @param socklen length of @a server_addr
854  * @return NULL on error, otherwise the listen socket
855  */
856 static struct GNUNET_NETWORK_Handle *
857 open_listen_socket (const struct sockaddr *server_addr,
858                     socklen_t socklen)
859 {
860   struct GNUNET_NETWORK_Handle *sock;
861   uint16_t port;
862   int eno;
863
864   switch (server_addr->sa_family)
865   {
866   case AF_INET:
867     port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
868     break;
869   case AF_INET6:
870     port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
871     break;
872   case AF_UNIX:
873     port = 0;
874     break;
875   default:
876     GNUNET_break (0);
877     port = 0;
878     break;
879   }
880   sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0);
881   if (NULL == sock)
882   {
883     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
884     errno = 0;
885     return NULL;
886   }
887   /* bind the socket */
888   if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen))
889   {
890     eno = errno;
891     if (EADDRINUSE != errno)
892     {
893       /* we don't log 'EADDRINUSE' here since an IPv4 bind may
894        * fail if we already took the port on IPv6; if both IPv4 and
895        * IPv6 binds fail, then our caller will log using the
896        * errno preserved in 'eno' */
897       LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
898                     "bind");
899       if (0 != port)
900         LOG (GNUNET_ERROR_TYPE_ERROR,
901              _("`%s' failed for port %d (%s).\n"),
902              "bind",
903              port,
904              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
905       eno = 0;
906     }
907     else
908     {
909       if (0 != port)
910         LOG (GNUNET_ERROR_TYPE_WARNING,
911              _("`%s' failed for port %d (%s): address already in use\n"),
912              "bind", port,
913              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
914       else if (AF_UNIX == server_addr->sa_family)
915       {
916         LOG (GNUNET_ERROR_TYPE_WARNING,
917              _("`%s' failed for `%s': address already in use\n"),
918              "bind",
919              GNUNET_a2s (server_addr, socklen));
920       }
921     }
922     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
923     errno = eno;
924     return NULL;
925   }
926   if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
927   {
928     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
929                   "listen");
930     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
931     errno = 0;
932     return NULL;
933   }
934   if (0 != port)
935     LOG (GNUNET_ERROR_TYPE_DEBUG,
936          "Server starts to listen on port %u.\n",
937          port);
938   return sock;
939 }
940
941
942
943
944 /**
945  * Setup service handle
946  *
947  * Configuration may specify:
948  * - PORT (where to bind to for TCP)
949  * - UNIXPATH (where to bind to for UNIX domain sockets)
950  * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
951  * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
952  * - ACCEPT_FROM  (only allow connections from specified IPv4 subnets)
953  * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
954  * - REJECT_FROM  (disallow allow connections from specified IPv4 subnets)
955  * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
956  *
957  * @param sh service context to initialize
958  * @return #GNUNET_OK if configuration succeeded
959  */
960 static int
961 setup_service (struct GNUNET_SERVICE_Handle *sh)
962 {
963   struct GNUNET_TIME_Relative idleout;
964   int tolerant;
965
966 #ifndef MINGW
967   const char *nfds;
968   unsigned int cnt;
969   int flags;
970 #endif
971
972   if (GNUNET_CONFIGURATION_have_value
973       (sh->cfg, sh->service_name, "TOLERANT"))
974   {
975     if (GNUNET_SYSERR ==
976         (tolerant =
977          GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, sh->service_name,
978                                                "TOLERANT")))
979     {
980       LOG (GNUNET_ERROR_TYPE_ERROR,
981            _("Specified value for `%s' of service `%s' is invalid\n"),
982            "TOLERANT", sh->service_name);
983       return GNUNET_SYSERR;
984     }
985   }
986   else
987     tolerant = GNUNET_NO;
988
989 #ifndef MINGW
990   errno = 0;
991   if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
992       (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
993       (cnt + 4 < FD_SETSIZE))
994   {
995     sh->lsocks =
996         GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (cnt + 1));
997     while (0 < cnt--)
998     {
999       flags = fcntl (3 + cnt, F_GETFD);
1000       if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1001           (NULL ==
1002            (sh->lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1003       {
1004         LOG (GNUNET_ERROR_TYPE_ERROR,
1005              _
1006              ("Could not access pre-bound socket %u, will try to bind myself\n"),
1007              (unsigned int) 3 + cnt);
1008         cnt++;
1009         while (sh->lsocks[cnt] != NULL)
1010           GNUNET_break (0 == GNUNET_NETWORK_socket_close (sh->lsocks[cnt++]));
1011         GNUNET_free (sh->lsocks);
1012         sh->lsocks = NULL;
1013         break;
1014       }
1015     }
1016     unsetenv ("LISTEN_FDS");
1017   }
1018 #else
1019   if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL)
1020   {
1021     receive_sockets_from_parent (sh);
1022     putenv ("GNUNET_OS_READ_LSOCKS=");
1023   }
1024 #endif
1025
1026   if (NULL != sh->lsocks)
1027   {
1028     /* listen only on inherited sockets if we have any */
1029     struct GNUNET_NETWORK_Handle **ls = sh->lsocks;
1030     for (; NULL != *ls; ls++)
1031     {
1032       struct ServiceListenContext *slc;
1033
1034       slc = GNUNET_new (struct ServiceListenContext);
1035       slc->listen_socket = *ls;
1036       GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1037     }
1038     GNUNET_free_non_null (sh->lsocks);
1039   }
1040   else
1041   {
1042     struct sockaddr **addrs;
1043     socklen_t *addrlens;
1044     int num;
1045
1046     num = get_server_addresses (sh->service_name, sh->cfg,
1047                                                &addrs, &addrlens);
1048     if (GNUNET_SYSERR == num)
1049       return GNUNET_SYSERR;
1050
1051     for (int i = 0; i < num; i++)
1052     {
1053       struct ServiceListenContext *slc;
1054
1055       slc = GNUNET_new (struct ServiceListenContext);
1056       slc->listen_socket = open_listen_socket (addrs[i], addrlens[i]);
1057       GNUNET_break (NULL != slc->listen_socket);
1058       GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1059     }
1060   }
1061
1062   sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1063   sh->match_uid =
1064       GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, sh->service_name,
1065                                             "UNIX_MATCH_UID");
1066   sh->match_gid =
1067       GNUNET_CONFIGURATION_get_value_yesno (sh->cfg, sh->service_name,
1068                                             "UNIX_MATCH_GID");
1069   process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1070   process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1071   process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1072   process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1073
1074   return GNUNET_OK;
1075 }
1076
1077
1078 /**
1079  * Creates the "main" function for a GNUnet service.  You
1080  * should almost always use the #GNUNET_SERVICE_MAIN macro
1081  * instead of calling this function directly (except
1082  * for ARM, which should call this function directly).
1083  *
1084  * The function will launch the service with the name @a service_name
1085  * using the @a service_options to configure its shutdown
1086  * behavior. Once the service is ready, the @a init_cb will be called
1087  * for service-specific initialization.  @a init_cb will be given the
1088  * service handler which can be used to control the service's
1089  * availability.  When clients connect or disconnect, the respective
1090  * @a connect_cb or @a disconnect_cb functions will be called. For
1091  * messages received from the clients, the respective @a handlers will
1092  * be invoked; for the closure of the handlers we use the return value
1093  * from the @a connect_cb invocation of the respective client.
1094  *
1095  * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1096  * message to receive further messages from this client.  If
1097  * #GNUNET_SERVICE_client_continue() is not called within a short
1098  * time, a warning will be logged. If delays are expected, services
1099  * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1100  * disable the warning.
1101  *
1102  * Clients sending invalid messages (based on @a handlers) will be
1103  * dropped. Additionally, clients can be dropped at any time using
1104  * #GNUNET_SERVICE_client_drop().
1105  *
1106  * @param argc number of command-line arguments in @a argv
1107  * @param argv array of command-line arguments
1108  * @param service_name name of the service to run
1109  * @param options options controlling shutdown of the service
1110  * @param service_init_cb function to call once the service is ready
1111  * @param connect_cb function to call whenever a client connects
1112  * @param disconnect_cb function to call whenever a client disconnects
1113  * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
1114  * @param handlers NULL-terminated array of message handlers for the service,
1115  *                 the closure will be set to the value returned by
1116  *                 the @a connect_cb for the respective connection
1117  * @return 0 on success, non-zero on error
1118  */
1119 int
1120 GNUNET_SERVICE_ruN_ (int argc,
1121                      char *const *argv,
1122                      const char *service_name,
1123                      enum GNUNET_SERVICE_Options options,
1124                      GNUNET_SERVICE_InitCallback service_init_cb,
1125                      GNUNET_SERVICE_ConnectHandler connect_cb,
1126                      GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1127                      void *cls,
1128                      const struct GNUNET_MQ_MessageHandler *handlers)
1129 {
1130   struct GNUNET_SERVICE_Handle sh;
1131   char *cfg_filename;
1132   char *opt_cfg_filename;
1133   char *loglev;
1134   const char *xdg;
1135   char *logfile;
1136   int do_daemonize;
1137   unsigned int i;
1138   unsigned long long skew_offset;
1139   unsigned long long skew_variance;
1140   long long clock_offset;
1141   struct GNUNET_CONFIGURATION_Handle *cfg;
1142   int ret;
1143   int err;
1144
1145   struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1146     GNUNET_GETOPT_OPTION_CFG_FILE (&opt_cfg_filename),
1147     {'d', "daemonize", NULL,
1148      gettext_noop ("do daemonize (detach from terminal)"), 0,
1149      GNUNET_GETOPT_set_one, &do_daemonize},
1150     GNUNET_GETOPT_OPTION_HELP (NULL),
1151     GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
1152     GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
1153     GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION),
1154     GNUNET_GETOPT_OPTION_END
1155   };
1156
1157   xdg = getenv ("XDG_CONFIG_HOME");
1158   if (NULL != xdg)
1159     GNUNET_asprintf (&cfg_filename,
1160                      "%s%s%s",
1161                      xdg,
1162                      DIR_SEPARATOR_STR,
1163                      GNUNET_OS_project_data_get ()->config_file);
1164   else
1165     cfg_filename = GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
1166
1167   sh.options = options;
1168   sh.cfg = cfg = GNUNET_CONFIGURATION_create ();
1169   sh.service_init_cb = service_init_cb;
1170   sh.connect_cb = connect_cb;
1171   sh.disconnect_cb = disconnect_cb;
1172   sh.cb_cls = cls;
1173   sh.handlers = handlers;
1174
1175   /* setup subsystems */
1176   ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv);
1177   if (GNUNET_SYSERR == ret)
1178     goto shutdown;
1179   if (GNUNET_NO == ret)
1180   {
1181     err = 0;
1182     goto shutdown;
1183   }
1184   if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
1185   {
1186     GNUNET_break (0);
1187     goto shutdown;
1188   }
1189   if (NULL == opt_cfg_filename)
1190     opt_cfg_filename = GNUNET_strdup (cfg_filename);
1191   if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename))
1192   {
1193     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename))
1194     {
1195       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1196                   _("Malformed configuration file `%s', exit ...\n"),
1197                   opt_cfg_filename);
1198       goto shutdown;
1199     }
1200   }
1201   else
1202   {
1203     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL))
1204     {
1205       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1206                   _("Malformed configuration, exit ...\n"));
1207       goto shutdown;
1208     }
1209     if (0 != strcmp (opt_cfg_filename, cfg_filename))
1210       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1211                   _("Could not access configuration file `%s'\n"),
1212                   opt_cfg_filename);
1213   }
1214   if (GNUNET_OK != setup_service (&sh))
1215     goto shutdown;
1216   if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sh)))
1217   {
1218     GNUNET_break (0);
1219     goto shutdown;
1220   }
1221   if (GNUNET_OK != set_user_id (&sh))
1222     goto shutdown;
1223   LOG (GNUNET_ERROR_TYPE_DEBUG,
1224        "Service `%s' runs with configuration from `%s'\n",
1225        service_name,
1226        opt_cfg_filename);
1227   if ((GNUNET_OK ==
1228        GNUNET_CONFIGURATION_get_value_number (sh.cfg, "TESTING",
1229                                               "SKEW_OFFSET", &skew_offset)) &&
1230       (GNUNET_OK ==
1231        GNUNET_CONFIGURATION_get_value_number (sh.cfg, "TESTING",
1232                                               "SKEW_VARIANCE", &skew_variance)))
1233   {
1234     clock_offset = skew_offset - skew_variance;
1235     GNUNET_TIME_set_offset (clock_offset);
1236     LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
1237   }
1238   /* actually run service */
1239   err = 0;
1240   GNUNET_SCHEDULER_run (&service_main, &sh);
1241   /* shutdown */
1242   if (1 == do_daemonize)
1243     pid_file_delete (&sh);
1244
1245 shutdown:
1246   if (-1 != sh.ready_confirm_fd)
1247   {
1248     if (1 != WRITE (sh.ready_confirm_fd, err ? "I" : "S", 1))
1249       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
1250     GNUNET_break (0 == CLOSE (sh.ready_confirm_fd));
1251   }
1252 #if HAVE_MALLINFO
1253   {
1254     char *counter;
1255
1256     if ( (GNUNET_YES ==
1257           GNUNET_CONFIGURATION_have_value (sh.cfg, service_name,
1258                                            "GAUGER_HEAP")) &&
1259          (GNUNET_OK ==
1260           GNUNET_CONFIGURATION_get_value_string (sh.cfg, service_name,
1261                                                  "GAUGER_HEAP",
1262                                                  &counter)) )
1263     {
1264       struct mallinfo mi;
1265
1266       mi = mallinfo ();
1267       GAUGER (service_name, counter, mi.usmblks, "blocks");
1268       GNUNET_free (counter);
1269     }
1270   }
1271 #endif
1272   GNUNET_SPEEDUP_stop_ ();
1273   GNUNET_CONFIGURATION_destroy (cfg);
1274
1275   while (NULL != sh.slc_head)
1276   {
1277     struct ServiceListenContext *slc = sh.slc_head;
1278     sh.slc_head = slc->next;
1279     // FIXME: destroy slc
1280     GNUNET_free (slc);
1281   }
1282
1283   GNUNET_free_non_null (logfile);
1284   GNUNET_free_non_null (loglev);
1285   GNUNET_free (cfg_filename);
1286   GNUNET_free_non_null (opt_cfg_filename);
1287   GNUNET_free_non_null (sh.v4_denied);
1288   GNUNET_free_non_null (sh.v6_denied);
1289   GNUNET_free_non_null (sh.v4_allowed);
1290   GNUNET_free_non_null (sh.v6_allowed);
1291
1292   return err ? GNUNET_SYSERR : sh.ret;
1293 }
1294
1295
1296 /**
1297  * Suspend accepting connections from the listen socket temporarily.
1298  * Resume activity using #GNUNET_SERVICE_resume.
1299  *
1300  * @param sh service to stop accepting connections.
1301  */
1302 void
1303 GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
1304 {
1305   struct ServiceListenContext *slc;
1306
1307   for (slc = sh->slc_head; NULL != slc; slc = slc->next)
1308   {
1309     if (NULL != slc->listen_task)
1310       {
1311         GNUNET_SCHEDULER_cancel (slc->listen_task);
1312         slc->listen_task = NULL;
1313       }
1314   }
1315 }
1316
1317
1318 /**
1319  * Signature of functions implementing the sending functionality of a
1320  * message queue.
1321  *
1322  * @param mq the message queue
1323  * @param msg the message to send
1324  * @param impl_state state of the implementation
1325  */
1326 static void
1327 service_mq_send (struct GNUNET_MQ_Handle *mq,
1328                  const struct GNUNET_MessageHeader *msg,
1329                  void *impl_state)
1330 {
1331   // struct GNUNET_SERVICE_Client *client = cls;
1332
1333   // FIXME 1: setup "client->send_task" for transmission.
1334   // FIXME 2: I seriously hope we do not need to make a copy of `msg`!
1335   // OPTIMIZATION: ideally, we'd like the ability to peak at the rest of
1336   //               the queue and transmit more than one message if possible.
1337 }
1338
1339
1340 /**
1341  * Implementation function that cancels the currently sent message.
1342  *
1343  * @param mq message queue
1344  * @param impl_state state specific to the implementation
1345  */
1346 static void
1347 service_mq_cancel (struct GNUNET_MQ_Handle *mq,
1348                    void *impl_state)
1349 {
1350   // struct GNUNET_SERVICE_Client *client = cls;
1351
1352   // FIXME: stop transmission! (must be possible, otherwise
1353   // we must have told MQ that the message was sent!)
1354 }
1355
1356
1357 /**
1358  * Generic error handler, called with the appropriate
1359  * error code and the same closure specified at the creation of
1360  * the message queue.
1361  * Not every message queue implementation supports an error handler.
1362  *
1363  * @param cls closure
1364  * @param error error code
1365  */
1366 static void
1367 service_mq_error_handler (void *cls,
1368                           enum GNUNET_MQ_Error error)
1369 {
1370   struct GNUNET_SERVICE_Client *client = cls;
1371
1372   // FIXME!
1373 }
1374
1375
1376 /**
1377  * Functions with this signature are called whenever a
1378  * complete message is received by the tokenizer for a client.
1379  *
1380  * Do not call #GNUNET_SERVER_mst_destroy() from within
1381  * the scope of this callback.
1382  *
1383  * @param cls closure with the `struct GNUNET_SERVICE_Client *`
1384  * @param client_cls closure with the `struct GNUNET_SERVICE_Client *`
1385  * @param message the actual message
1386  * @return #GNUNET_OK on success (always)
1387  */
1388 static int
1389 service_client_mst_cb (void *cls,
1390                        void *client_cls,
1391                        const struct GNUNET_MessageHeader *message)
1392 {
1393   struct GNUNET_SERVICE_Client *client = cls;
1394
1395   GNUNET_MQ_inject_message (client->mq,
1396                             message);
1397   return GNUNET_OK;
1398 }
1399
1400
1401 /**
1402  * A client sent us data. Receive and process it.  If we are done,
1403  * reschedule this task.
1404  *
1405  * @param cls the `struct GNUNET_SERVICE_Client` that sent us data.
1406  */
1407 static void
1408 service_client_recv (void *cls)
1409 {
1410   struct GNUNET_SERVICE_Client *client = cls;
1411
1412   // FIXME: read into buffer, pass to MST, then client->mq inject!
1413   // FIXME: revise MST API to avoid the memcpy!
1414   // i.e.: GNUNET_MST_read (client->sock);
1415 }
1416
1417
1418 /**
1419  * We have successfully accepted a connection from a client.  Now
1420  * setup the client (with the scheduler) and tell the application.
1421  *
1422  * @param sh service that accepted the client
1423  * @param sock socket associated with the client
1424  */
1425 static void
1426 start_client (struct GNUNET_SERVICE_Handle *sh,
1427               struct GNUNET_NETWORK_Handle *csock)
1428 {
1429   struct GNUNET_SERVICE_Client *client;
1430
1431   client = GNUNET_new (struct GNUNET_SERVICE_Client);
1432   GNUNET_CONTAINER_DLL_insert (sh->clients_head,
1433                                sh->clients_tail,
1434                                client);
1435   client->sh = sh;
1436   client->sock = csock;
1437   client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send,
1438                                               NULL,
1439                                               &service_mq_cancel,
1440                                               client,
1441                                               sh->handlers,
1442                                               &service_mq_error_handler,
1443                                               client);
1444   client->mst = GNUNET_SERVER_mst_create (&service_client_mst_cb,
1445                                           client);
1446   client->user_context = sh->connect_cb (sh->cb_cls,
1447                                          client,
1448                                          client->mq);
1449   GNUNET_MQ_set_handlers_closure (client->mq,
1450                                   client->user_context);
1451   client->recv_task = GNUNET_SCHEDULER_add_read (client->sock,
1452                                                  &service_client_recv,
1453                                                  client);
1454 }
1455
1456
1457 /**
1458  * We have a client. Accept the incoming socket(s) (and reschedule
1459  * the listen task).
1460  *
1461  * @param cls the `struct ServiceListenContext` of the ready listen socket
1462  */
1463 static void
1464 accept_client (void *cls)
1465 {
1466   struct ServiceListenContext *slc = cls;
1467   struct GNUNET_SERVICE_Handle *sh = slc->sh;
1468
1469   slc->listen_task = NULL;
1470   while (1)
1471     {
1472       struct GNUNET_NETWORK_Handle *sock;
1473       struct sockaddr_in *v4;
1474       struct sockaddr_in6 *v6;
1475       struct sockaddr_storage sa;
1476       socklen_t addrlen;
1477       int ok;
1478
1479       addrlen = sizeof (sa);
1480       sock = GNUNET_NETWORK_socket_accept (slc->listen_socket,
1481                                            (struct sockaddr *) &sa,
1482                                            &addrlen);
1483       if (NULL == sock)
1484         break;
1485       switch (sa.ss_family)
1486       {
1487       case AF_INET:
1488         GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
1489         v4 = (const struct sockaddr_in *) &sa;
1490         ok = ( ( (NULL == sh->v4_allowed) ||
1491                  (check_ipv4_listed (sh->v4_allowed,
1492                                      &v4->sin_addr))) &&
1493                ( (NULL == sh->v4_denied) ||
1494                  (! check_ipv4_listed (sh->v4_denied,
1495                                        &v4->sin_addr)) ) );
1496         break;
1497       case AF_INET6:
1498         GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
1499         v6 = (const struct sockaddr_in6 *) &sa;
1500         ok = ( ( (NULL == sh->v6_allowed) ||
1501                  (check_ipv6_listed (sh->v6_allowed,
1502                                      &v6->sin6_addr))) &&
1503                ( (NULL == sh->v6_denied) ||
1504                  (! check_ipv6_listed (sh->v6_denied,
1505                                        &v6->sin6_addr)) ) );
1506         break;
1507 #ifndef WINDOWS
1508       case AF_UNIX:
1509         ok = GNUNET_OK;            /* controlled using file-system ACL now */
1510         break;
1511 #endif
1512       default:
1513         LOG (GNUNET_ERROR_TYPE_WARNING,
1514              _("Unknown address family %d\n"),
1515              sa.ss_family);
1516         return GNUNET_SYSERR;
1517       }
1518       if (! ok)
1519         {
1520           LOG (GNUNET_ERROR_TYPE_DEBUG,
1521                "Service rejected incoming connection from %s due to policy.\n",
1522                GNUNET_a2s ((const struct sockaddr *) &sa,
1523                            addrlen));
1524           GNUNET_NETWORK_socket_close (sock);
1525           continue;
1526         }
1527       LOG (GNUNET_ERROR_TYPE_DEBUG,
1528            "Service accepted incoming connection from %s.\n",
1529            GNUNET_a2s ((const struct sockaddr *) &sa,
1530                        addrlen));
1531       start_client (slc->sh,
1532                     sock);
1533     }
1534   slc->listen_task = GNUNET_SCHEDULER_add_read (slc->listen_socket,
1535                                                 &accept_client,
1536                                                 slc);
1537 }
1538
1539
1540 /**
1541  * Resume accepting connections from the listen socket.
1542  *
1543  * @param sh service to resume accepting connections.
1544  */
1545 void
1546 GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
1547 {
1548   struct ServiceListenContext *slc;
1549
1550   for (slc = sh->slc_head; NULL != slc; slc = slc->next)
1551   {
1552     GNUNET_assert (NULL == slc->listen_task);
1553     slc->listen_task = GNUNET_SCHEDULER_add_read (slc->listen_socket,
1554                                                   &accept_client,
1555                                                   slc);
1556   }
1557 }
1558
1559
1560 /**
1561  * Continue receiving further messages from the given client.
1562  * Must be called after each message received.
1563  *
1564  * @param c the client to continue receiving from
1565  */
1566 void
1567 GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
1568 {
1569   GNUNET_break (0); // not implemented
1570 }
1571
1572
1573 /**
1574  * Disable the warning the server issues if a message is not
1575  * acknowledged in a timely fashion.  Use this call if a client is
1576  * intentionally delayed for a while.  Only applies to the current
1577  * message.
1578  *
1579  * @param c client for which to disable the warning
1580  */
1581 void
1582 GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
1583 {
1584   GNUNET_break (NULL != c->warn_task);
1585   if (NULL != c->warn_task)
1586   {
1587     GNUNET_SCHEDULER_cancel (c->warn_task);
1588     c->warn_task = NULL;
1589   }
1590 }
1591
1592
1593 /**
1594  * Ask the server to disconnect from the given client.  This is the
1595  * same as returning #GNUNET_SYSERR within the check procedure when
1596  * handling a message, wexcept that it allows dropping of a client even
1597  * when not handling a message from that client.  The `disconnect_cb`
1598  * will be called on @a c even if the application closes the connection
1599  * using this function.
1600  *
1601  * @param c client to disconnect now
1602  */
1603 void
1604 GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
1605 {
1606   struct GNUNET_SERVICE_Handle *sh = c->sh;
1607
1608   GNUNET_CONTAINER_DLL_remove (sh->clients_head,
1609                                sh->clients_tail,
1610                                c);
1611   sh->disconnect_cb (sh->cb_cls,
1612                      c,
1613                      c->user_context);
1614   if (NULL != c->warn_task)
1615   {
1616     GNUNET_SCHEDULER_cancel (c->warn_task);
1617     c->warn_task = NULL;
1618   }
1619   if (NULL != c->recv_task)
1620   {
1621     GNUNET_SCHEDULER_cancel (c->recv_task);
1622     c->recv_task = NULL;
1623   }
1624   if (NULL != c->send_task)
1625   {
1626     GNUNET_SCHEDULER_cancel (c->send_task);
1627     c->send_task = NULL;
1628   }
1629   GNUNET_SERVER_mst_destroy (c->mst);
1630   GNUNET_MQ_destroy (c->mq);
1631   if (GNUNET_NO == c->persist)
1632   {
1633     GNUNET_NETWORK_socket_close (c->sock);
1634   }
1635   else
1636   {
1637     GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
1638   }
1639   GNUNET_free (c);
1640   if ( (GNUNET_YES == sh->got_shutdown) &&
1641        (GNUNET_NO == have_non_monitor_clients (sh)) )
1642     GNUNET_SERVICE_shutdown (sh);
1643 }
1644
1645
1646 /**
1647  * Explicitly stops the service.
1648  *
1649  * @param sh server to shutdown
1650  */
1651 void
1652 GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
1653 {
1654   struct GNUNET_SERVICE_Client *client;
1655
1656   GNUNET_SERVICE_suspend (sh);
1657   sh->got_shutdown = GNUNET_NO;
1658   while (NULL != (client = sh->clients_head))
1659     GNUNET_SERVICE_client_drop (client);
1660 }
1661
1662
1663 /**
1664  * Set the 'monitor' flag on this client.  Clients which have been
1665  * marked as 'monitors' won't prevent the server from shutting down
1666  * once #GNUNET_SERVICE_stop_listening() has been invoked.  The idea is
1667  * that for "normal" clients we likely want to allow them to process
1668  * their requests; however, monitor-clients are likely to 'never'
1669  * disconnect during shutdown and thus will not be considered when
1670  * determining if the server should continue to exist after
1671  * shutdown has been triggered.
1672  *
1673  * @param c client to mark as a monitor
1674  */
1675 void
1676 GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
1677 {
1678   c->is_monitor = GNUNET_YES;
1679   if ( (GNUNET_YES == c->sh->got_shutdown) &&
1680        (GNUNET_NO == have_non_monitor_clients (c->sh)) )
1681     GNUNET_SERVICE_shutdown (c->sh);
1682 }
1683
1684
1685 /**
1686  * Set the persist option on this client.  Indicates that the
1687  * underlying socket or fd should never really be closed.  Used for
1688  * indicating process death.
1689  *
1690  * @param c client to persist the socket (never to be closed)
1691  */
1692 void
1693 GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
1694 {
1695   c->persist = GNUNET_YES;
1696 }
1697
1698
1699 /* end of service_new.c */