2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
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 2, or (at your
8 option) any later version.
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.
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file arm/gnunet-service-manager.c
22 * @brief listen to incoming connections from clients to services,
23 * start services for which incoming an incoming connection occur,
24 * and relay communication between the client and the service for
25 * that first incoming connection.
27 * @author Safey Abdel Halim
28 * @author Christian Grothoff
32 #include "gnunet_service_lib.h"
33 #include "gnunet_configuration_lib.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_client_lib.h"
36 #include "gnunet_container_lib.h"
37 #include "gnunet_service_arm_.h"
40 #define DEBUG_SERVICE_MANAGER GNUNET_NO
42 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
44 #define BUFFER_SIZE (64 * 1024)
47 * Problem forwarding from client to service.
49 #define REASON_CLIENT_TO_SERVICE 1
52 * Problem forwarding from service to client.
54 #define REASON_SERVICE_TO_CLIENT 2
57 * Problem in both directions.
59 #define REASON_ERROR 3
65 struct ServiceListeningInfo
68 * This is a linked list.
70 struct ServiceListeningInfo *next;
73 * This is a linked list.
75 struct ServiceListeningInfo *prev;
78 * Name of the service being forwarded.
85 struct sockaddr *service_addr;
90 socklen_t service_addr_len;
93 * Our listening socket.
95 struct GNUNET_NETWORK_Handle *listeningSocket;
98 * Task doing the accepting.
100 GNUNET_SCHEDULER_TaskIdentifier acceptTask;
104 * Information of the connection: client-arm-service
106 struct ForwardedConnection
111 struct GNUNET_NETWORK_Handle *armClientSocket;
116 struct GNUNET_NETWORK_Handle *armServiceSocket;
121 struct ServiceListeningInfo *listen_info;
126 char service_to_client_buffer[BUFFER_SIZE];
131 char client_to_service_buffer[BUFFER_SIZE];
136 char client_addr[32];
141 const char *client_to_service_bufferPos;
146 const char *service_to_client_bufferPos;
149 * Timeout for forwarding.
151 struct GNUNET_TIME_Absolute timeout;
154 * Current back-off value.
156 struct GNUNET_TIME_Relative back_off;
161 GNUNET_SCHEDULER_TaskIdentifier client_to_service_task;
166 GNUNET_SCHEDULER_TaskIdentifier service_to_client_task;
171 ssize_t client_to_service_bufferDataLength;
176 ssize_t service_to_client_bufferDataLength;
181 socklen_t client_addr_len;
187 * Array with the names of the services started by default.
189 static char **defaultServicesList;
192 * Size of the defaultServicesList array.
194 static unsigned int numDefaultServices;
199 static const struct GNUNET_CONFIGURATION_Handle *cfg;
204 static struct GNUNET_SCHEDULER_Handle *scheduler;
209 static struct ServiceListeningInfo *serviceListeningInfoList_head;
214 static struct ServiceListeningInfo *serviceListeningInfoList_tail;
218 * Put the default services represented by a space separated string into an array of strings
220 * @param services space separated string of default services
223 addDefaultServicesToList (const char *services)
229 if (strlen (services) == 0)
231 s = GNUNET_strdup (services);
232 token = strtok (s, " ");
233 while (NULL != token)
235 numDefaultServices++;
236 token = strtok (NULL, " ");
240 defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *));
242 s = GNUNET_strdup (services);
243 token = strtok (s, " ");
244 while (NULL != token)
246 defaultServicesList[i++] = GNUNET_strdup (token);
247 token = strtok (NULL, " ");
250 GNUNET_assert (i == numDefaultServices);
254 * Checks whether the serviceName is in the list of default services
256 * @param serviceName string to check its existance in the list
257 * @return GNUNET_YES if the service is started by default
260 isInDefaultList (const char *serviceName)
263 for (i = 0; i < numDefaultServices; i++)
264 if (strcmp (serviceName, defaultServicesList[i]) == 0)
271 * Close forwarded connection (partial or full).
273 * @param fc connection to close
274 * @param reason which direction to close
277 closeClientAndServiceSockets (struct ForwardedConnection *fc,
280 if (0 != (REASON_SERVICE_TO_CLIENT & reason))
282 #if DEBUG_SERVICE_MANAGER
283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
284 "Stopping forwarding from service to client\n",
285 fc->listen_info->serviceName);
287 if (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK)
289 GNUNET_SCHEDULER_cancel (scheduler, fc->service_to_client_task);
290 fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
292 if (fc->armClientSocket != NULL)
293 GNUNET_NETWORK_socket_shutdown (fc->armClientSocket,
295 if (fc->armServiceSocket != NULL)
296 GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket,
299 if (0 != (REASON_CLIENT_TO_SERVICE & reason))
301 #if DEBUG_SERVICE_MANAGER
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
303 "Stopping forwarding from client to service\n",
304 fc->listen_info->serviceName);
306 if (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK)
308 GNUNET_SCHEDULER_cancel (scheduler,
309 fc->client_to_service_task);
310 fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
312 if (fc->armClientSocket != NULL)
313 GNUNET_NETWORK_socket_shutdown (fc->armClientSocket,
315 if (fc->armServiceSocket != NULL)
316 GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket,
319 if ( (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK) ||
320 (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK) )
322 #if DEBUG_SERVICE_MANAGER
323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
324 "Closing forwarding connection (done with both directions)\n");
326 if ( (NULL != fc->armClientSocket) &&
328 GNUNET_NETWORK_socket_close (fc->armClientSocket)) )
329 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
330 if ( (NULL != fc->armServiceSocket) &&
332 GNUNET_NETWORK_socket_close (fc->armServiceSocket)) )
333 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
334 GNUNET_free (fc->listen_info->serviceName);
335 GNUNET_free (fc->listen_info->service_addr);
336 GNUNET_free (fc->listen_info);
345 receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
352 receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
356 * Forward messages sent from service to client
358 * @param cls callback data, struct ForwardedConnection for the communication between client and service
362 forwardToClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
364 struct ForwardedConnection *fc = cls;
365 ssize_t numberOfBytesSent;
367 fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
368 if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->write_ready,
369 fc->armClientSocket))
371 fc->service_to_client_task =
372 GNUNET_SCHEDULER_add_write_net (scheduler,
373 GNUNET_TIME_UNIT_FOREVER_REL,
375 &forwardToClient, fc);
378 /* Forwarding service response to client */
380 GNUNET_NETWORK_socket_send (fc->armClientSocket,
381 fc->service_to_client_bufferPos,
382 fc->service_to_client_bufferDataLength);
383 if (numberOfBytesSent <= 0)
385 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
386 "Failed to forward data to client: %s\n",
388 closeClientAndServiceSockets (fc,
389 REASON_SERVICE_TO_CLIENT);
392 #if DEBUG_SERVICE_MANAGER
393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
394 "Forwarded %d bytes to client\n",
397 if (numberOfBytesSent < fc->service_to_client_bufferDataLength)
399 fc->service_to_client_bufferPos += numberOfBytesSent;
400 fc->service_to_client_bufferDataLength -= numberOfBytesSent;
401 fc->service_to_client_task =
402 GNUNET_SCHEDULER_add_write_net (scheduler,
403 GNUNET_TIME_UNIT_FOREVER_REL,
409 fc->service_to_client_task =
410 GNUNET_SCHEDULER_add_read_net (scheduler,
411 GNUNET_TIME_UNIT_FOREVER_REL,
412 fc->armServiceSocket,
419 * Receive service messages sent by the service and forward it to client
421 * @param cls callback data, struct ForwardedConnection for the communication between client and service
422 * @param tc scheduler context
425 receiveFromService (void *cls,
426 const struct GNUNET_SCHEDULER_TaskContext *tc)
428 struct ForwardedConnection *fc = cls;
430 fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
431 if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->read_ready,
432 fc->armServiceSocket))
434 fc->service_to_client_task =
435 GNUNET_SCHEDULER_add_read_net (scheduler,
436 GNUNET_TIME_UNIT_FOREVER_REL,
437 fc->armServiceSocket,
438 &receiveFromService, fc);
441 fc->service_to_client_bufferPos = fc->service_to_client_buffer;
442 fc->service_to_client_bufferDataLength =
443 GNUNET_NETWORK_socket_recv (fc->armServiceSocket,
444 fc->service_to_client_buffer,
446 if (fc->service_to_client_bufferDataLength <= 0)
448 if (fc->service_to_client_bufferDataLength == 0)
450 #if DEBUG_SERVICE_MANAGER
451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
452 "Service `%s' stopped sending data.\n",
453 fc->listen_info->serviceName);
458 #if DEBUG_SERVICE_MANAGER
459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
460 "Error receiving from service: %s\n",
464 closeClientAndServiceSockets (fc, REASON_SERVICE_TO_CLIENT);
467 #if DEBUG_SERVICE_MANAGER
468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
469 "Received %d bytes for client\n",
470 fc->service_to_client_bufferDataLength);
472 fc->service_to_client_task =
473 GNUNET_SCHEDULER_add_write_net (scheduler,
474 GNUNET_TIME_UNIT_FOREVER_REL,
476 &forwardToClient, fc);
481 * Forward client message to service
483 * @param cls callback data, struct ForwardedConnection for the communication between client and service
484 * @param tc scheduler context
487 forwardToService (void *cls,
488 const struct GNUNET_SCHEDULER_TaskContext *tc)
490 struct ForwardedConnection *fc = cls;
491 ssize_t numberOfBytesSent;
493 fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
494 if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->write_ready,
495 fc->armServiceSocket))
497 fc->client_to_service_task =
498 GNUNET_SCHEDULER_add_write_net (scheduler,
499 GNUNET_TIME_UNIT_FOREVER_REL,
500 fc->armServiceSocket,
501 &forwardToService, fc);
505 GNUNET_NETWORK_socket_send (fc->armServiceSocket,
506 fc->client_to_service_bufferPos,
507 fc->client_to_service_bufferDataLength);
508 if (numberOfBytesSent <= 0)
510 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
511 "Failed to forward data to service: %s\n",
513 closeClientAndServiceSockets (fc,
514 REASON_CLIENT_TO_SERVICE);
517 #if DEBUG_SERVICE_MANAGER
518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
519 "Forwarded %d bytes to service\n",
522 if (numberOfBytesSent < fc->client_to_service_bufferDataLength)
524 fc->client_to_service_bufferPos += numberOfBytesSent;
525 fc->client_to_service_bufferDataLength -= numberOfBytesSent;
526 fc->client_to_service_task =
527 GNUNET_SCHEDULER_add_write_net (scheduler,
528 GNUNET_TIME_UNIT_FOREVER_REL,
529 fc->armServiceSocket,
530 &forwardToService, fc);
533 fc->client_to_service_task =
534 GNUNET_SCHEDULER_add_read_net (scheduler,
535 GNUNET_TIME_UNIT_FOREVER_REL,
537 &receiveFromClient, fc);
542 * Read data from the client and then forward it to the service.
544 * @param cls callback data, struct ForwardedConnection for the communication between client and service
548 receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
550 struct ForwardedConnection *fc = cls;
552 fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
553 if (GNUNET_YES != GNUNET_NETWORK_fdset_isset (tc->read_ready,
554 fc->armClientSocket))
556 fc->client_to_service_task =
557 GNUNET_SCHEDULER_add_read_net (scheduler,
558 GNUNET_TIME_UNIT_FOREVER_REL,
560 &receiveFromClient, fc);
563 fc->client_to_service_bufferPos = fc->client_to_service_buffer;
564 fc->client_to_service_bufferDataLength =
565 GNUNET_NETWORK_socket_recv (fc->armClientSocket,
566 fc->client_to_service_buffer,
568 if (fc->client_to_service_bufferDataLength <= 0)
570 if (fc->client_to_service_bufferDataLength == 0)
572 #if DEBUG_SERVICE_MANAGER
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
574 "Client closed connection with service `%s'\n",
575 fc->listen_info->serviceName);
580 #if DEBUG_SERVICE_MANAGER
581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
582 "Error receiving from client: %s\n",
586 closeClientAndServiceSockets (fc, REASON_CLIENT_TO_SERVICE);
589 #if DEBUG_SERVICE_MANAGER
590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
591 "Received %d bytes for service\n",
592 fc->client_to_service_bufferDataLength);
594 fc->client_to_service_task =
595 GNUNET_SCHEDULER_add_write_net (scheduler,
596 GNUNET_TIME_UNIT_FOREVER_REL,
597 fc->armServiceSocket,
598 &forwardToService, fc);
606 start_forwarding (void *cls,
607 const struct GNUNET_SCHEDULER_TaskContext *tc)
609 struct ForwardedConnection *fc = cls;
610 struct GNUNET_TIME_Relative rem;
613 (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) )
615 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
616 _("Unable to forward to service `%s': shutdown\n"),
617 fc->listen_info->serviceName);
618 closeClientAndServiceSockets (fc, REASON_ERROR);
621 rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
622 fc->armServiceSocket =
623 GNUNET_NETWORK_socket_create (fc->listen_info->service_addr->sa_family,
625 if (NULL == fc->armServiceSocket)
627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
628 _ ("Unable to start service `%s': %s\n"),
629 fc->listen_info->serviceName,
631 closeClientAndServiceSockets (fc, REASON_ERROR);
634 if ((GNUNET_SYSERR ==
635 GNUNET_NETWORK_socket_connect (fc->armServiceSocket,
636 fc->listen_info->service_addr,
637 fc->listen_info->service_addr_len)) &&
638 (EINPROGRESS != errno) )
642 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
643 _("Unable to forward to service `%s': timeout before connect\n"),
644 fc->listen_info->serviceName);
645 closeClientAndServiceSockets (fc, REASON_ERROR);
648 fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
649 GNUNET_SCHEDULER_add_delayed (scheduler,
650 GNUNET_TIME_relative_min (fc->back_off,
655 #if DEBUG_SERVICE_MANAGER
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
657 "Connected to service, now starting forwarding\n");
659 fc->client_to_service_task =
660 GNUNET_SCHEDULER_add_read_net (scheduler,
661 GNUNET_TIME_UNIT_FOREVER_REL,
663 &receiveFromClient, fc);
664 fc->service_to_client_task =
665 GNUNET_SCHEDULER_add_read_net (scheduler,
666 GNUNET_TIME_UNIT_FOREVER_REL,
667 fc->armServiceSocket,
668 &receiveFromService, fc);
673 * ARM connects to the just created service,
674 * starts the processes for relaying messages between the client and the service
676 * @param cls callback data, struct ForwardedConnection for the communication between client and service
680 connectToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
682 struct ForwardedConnection *fc = cls;
684 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
686 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
687 _("Unable to start service `%s': shutdown\n"),
688 fc->listen_info->serviceName);
689 closeClientAndServiceSockets (fc,
690 (REASON_CLIENT_TO_SERVICE & REASON_SERVICE_TO_CLIENT));
693 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
695 /* Service is not up. Unable to proceed */
696 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
697 _("Unable to start service `%s': timeout\n"),
698 fc->listen_info->serviceName);
699 closeClientAndServiceSockets (fc,
700 (REASON_CLIENT_TO_SERVICE & REASON_SERVICE_TO_CLIENT));
703 GNUNET_break (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE));
704 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
705 _("Service `%s' started\n"),
706 fc->listen_info->serviceName);
707 fc->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_SERVICE_TIMEOUT);
708 fc->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
709 start_forwarding (fc, NULL);
717 stop_listening (const char *serviceName)
719 struct ServiceListeningInfo *pos;
720 struct ServiceListeningInfo *next;
724 next = serviceListeningInfoList_head;
725 while (NULL != (pos = next))
728 if ( (serviceName != NULL) &&
729 (strcmp (pos->serviceName, serviceName) != 0) )
731 GNUNET_SCHEDULER_cancel (scheduler, pos->acceptTask);
732 GNUNET_break (GNUNET_OK ==
733 GNUNET_NETWORK_socket_close (pos->listeningSocket));
734 GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
735 serviceListeningInfoList_tail,
737 GNUNET_free (pos->serviceName);
738 GNUNET_free (pos->service_addr);
747 * First connection has come to the listening socket associated with the service,
748 * create the service in order to relay the incoming connection to it
750 * @param cls callback data, struct ServiceListeningInfo describing a listen socket
754 acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
756 struct ServiceListeningInfo *serviceListeningInfo = cls;
757 struct ForwardedConnection *fc;
759 serviceListeningInfo->acceptTask = GNUNET_SCHEDULER_NO_TASK;
760 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
762 fc = GNUNET_malloc (sizeof (struct ForwardedConnection));
763 fc->listen_info = serviceListeningInfo;
764 fc->service_to_client_bufferPos = fc->service_to_client_buffer;
765 fc->client_to_service_bufferPos = fc->client_to_service_buffer;
766 fc->client_addr_len = sizeof (fc->client_addr);
767 fc->armClientSocket = GNUNET_NETWORK_socket_accept (serviceListeningInfo->listeningSocket,
768 (struct sockaddr*) fc->client_addr,
769 &fc->client_addr_len);
770 if (NULL == fc->armClientSocket)
772 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
773 _("Unable to accept connection for service `%s': %s\n"),
774 serviceListeningInfo->serviceName,
777 serviceListeningInfo->acceptTask =
778 GNUNET_SCHEDULER_add_read_net (scheduler,
779 GNUNET_TIME_UNIT_FOREVER_REL,
780 serviceListeningInfo->listeningSocket,
782 serviceListeningInfo);
785 GNUNET_break (GNUNET_OK ==
786 GNUNET_NETWORK_socket_close (serviceListeningInfo->listeningSocket));
787 GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
788 serviceListeningInfoList_tail,
789 serviceListeningInfo);
790 start_service (NULL, serviceListeningInfo->serviceName);
791 GNUNET_CLIENT_service_test (scheduler,
792 serviceListeningInfo->serviceName,
801 * Creating a listening socket for each of the service's addresses and
802 * wait for the first incoming connection to it
804 * @param sa address associated with the service
805 * @param addr_len length of sa
806 * @param serviceName the name of the service in question
809 createListeningSocket (struct sockaddr *sa,
811 const char *serviceName)
813 const static int on = 1;
814 struct GNUNET_NETWORK_Handle *sock;
815 struct ServiceListeningInfo *serviceListeningInfo;
817 switch (sa->sa_family)
820 sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
823 sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
831 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
832 _("Unable to create socket for service `%s'"),
837 if (GNUNET_NETWORK_socket_setsockopt
838 (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
839 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
842 if ( (sa->sa_family == AF_INET6) &&
843 (GNUNET_NETWORK_socket_setsockopt
844 (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK))
845 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
849 if (GNUNET_NETWORK_socket_bind
850 (sock, (const struct sockaddr *) sa, addr_len) != GNUNET_OK)
852 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
853 _("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
855 GNUNET_a2s (sa, addr_len),
857 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
861 if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK)
863 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
865 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
869 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
870 _("ARM now monitors connections to service `%s' at `%s'\n"),
872 GNUNET_a2s (sa, addr_len));
873 serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
874 serviceListeningInfo->serviceName = GNUNET_strdup (serviceName);
875 serviceListeningInfo->service_addr = sa;
876 serviceListeningInfo->service_addr_len = addr_len;
877 serviceListeningInfo->listeningSocket = sock;
878 serviceListeningInfo->acceptTask =
879 GNUNET_SCHEDULER_add_read_net (scheduler,
880 GNUNET_TIME_UNIT_FOREVER_REL, sock,
882 serviceListeningInfo);
883 GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head,
884 serviceListeningInfoList_tail,
885 serviceListeningInfo);
890 * Callback function, checks whether the current tokens are representing a service,
891 * gets its addresses and create listening socket for it.
893 * @param cls callback data, not used
894 * @param section configuration section
895 * @param option configuration option
896 * @param value the option's value
899 checkPortNumberCB (void *cls,
904 struct sockaddr **addrs;
905 socklen_t *addr_lens;
909 if ( (strcasecmp (section, "arm") == 0) ||
910 (strcasecmp (option, "AUTOSTART") != 0) ||
911 (strcasecmp (value, "YES") != 0) ||
912 (isInDefaultList (section) == GNUNET_YES) )
914 if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs,
917 /* this will free (or capture) addrs[i] for i in 0..ret */
918 for (i = 0; i < ret; i++)
919 createListeningSocket (addrs[i], addr_lens[i], section);
921 GNUNET_free (addr_lens);
926 * Entry point to the Service Manager
928 * @param configurationHandle configuration to use to get services
929 * @param sched scheduler to handle clients and services communications
932 prepareServices (const struct GNUNET_CONFIGURATION_Handle
933 *configurationHandle, struct GNUNET_SCHEDULER_Handle *sched)
935 char *defaultServicesString;
938 cfg = configurationHandle;
939 /* Split the default services into a list */
941 GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES",
942 &defaultServicesString))
944 addDefaultServicesToList (defaultServicesString);
945 GNUNET_free (defaultServicesString);
947 /* Spot the services from the configuration and create a listening
949 GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL);
952 /* end of gnunet-service-manager.c */