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