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