2 This file is part of GNUnet.
3 (C) 2012 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.
22 * @file testbed/gnunet-service-testbed.c
23 * @brief implementation of the TESTBED service
24 * @author Sree Harsha Totakura
28 #include "gnunet_service_lib.h"
29 #include "gnunet_server_lib.h"
33 #include "gnunet_testbed_service.h"
34 #include "testbed_api_hosts.h"
39 #define LOG(kind,...) \
40 GNUNET_log (kind, __VA_ARGS__)
45 #define LOG_DEBUG(...) \
46 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
49 #define LIST_GROW_STEP 10
54 * The client handle associated with this context
56 struct GNUNET_SERVER_Client *client;
59 * Event mask of event to be responded in this context
64 * Our host id according to this context
71 * The message queue for sending messages to clients
76 * The message to be sent
78 struct GNUNET_MessageHeader *msg;
81 * The client to send the message to
83 struct GNUNET_SERVER_Client *client;
86 * next pointer for DLL
88 struct MessageQueue *next;
91 * prev pointer for DLL
93 struct MessageQueue *prev;
98 * The structure for identifying a shared service
103 * The name of the shared service
108 * Number of shared peers per instance of the shared service
113 * Number of peers currently sharing the service
115 uint32_t num_sharing;
130 * The host destination is reachable thru
137 * Structure representing a connected(directly-linked) controller
142 * The controller process handle if we had started the controller
144 struct GNUNET_TESTBED_ControllerProc *controller_proc;
147 * The controller handle
149 struct GNUNET_TESTBED_Controller *controller;
152 * The id of the host this controller is running on
159 * States of LCFContext
164 * The Context has been initialized; Nothing has been done on it
169 * Delegated host has been registered at the forwarding controller
171 DELEGATED_HOST_REGISTERED,
174 * The context has been finished (may have error)
182 * Link controllers request forwarding context
187 * The serialized and compressed configuration
192 * The gateway which will pass the link message to delegated host
194 struct Slave *gateway;
197 * The host registration handle while registered hosts in this context
199 struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
202 * The size of the compressed serialized configuration
207 * The size of the uncompressed configuration
212 * Should the delegated host be started by the slave host?
217 * The state of this context
219 enum LCFContextState state;
224 uint32_t delegated_host_id;
231 * Structure of a queue entry in LCFContext request queue
233 struct LCFContextQueue
238 struct LCFContext *lcf;
243 struct LCFContextQueue *next;
248 struct LCFContextQueue *prev;
253 * The master context; generated with the first INIT message
255 static struct Context *master_context;
264 static struct GNUNET_DISK_FileHandle *fh;
267 * Current Transmit Handle; NULL if no notify transmit exists currently
269 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
276 * The head for the LCF queue
278 static struct LCFContextQueue *lcfq_head;
281 * The tail for the LCF queue
283 static struct LCFContextQueue *lcfq_tail;
286 * The message queue head
288 static struct MessageQueue *mq_head;
291 * The message queue tail
293 static struct MessageQueue *mq_tail;
298 static struct GNUNET_TESTBED_Host **host_list;
303 static struct Route **route_list;
306 * A list of directly linked neighbours
308 static struct Slave **slave_list;
311 * The hashmap of shared services
313 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
316 * The size of the host list
318 static uint32_t host_list_size;
321 * The size of the route list
323 static uint32_t route_list_size;
326 * The size of directly linked neighbours list
328 static uint32_t slave_list_size;
335 * The lcf_task handle
337 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
340 * The shutdown task handle
342 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
346 * Function called to notify a client about the connection begin ready to queue
347 * more data. "buf" will be NULL and "size" zero if the connection was closed
348 * for writing in the meantime.
351 * @param size number of bytes available in buf
352 * @param buf where the callee should write the message
353 * @return number of bytes written to buf
356 transmit_ready_notify (void *cls, size_t size, void *buf)
358 struct MessageQueue *mq_entry;
360 transmit_handle = NULL;
362 GNUNET_assert (NULL != mq_entry);
365 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
366 size = ntohs (mq_entry->msg->size);
367 memcpy (buf, mq_entry->msg, size);
368 GNUNET_free (mq_entry->msg);
369 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
370 GNUNET_free (mq_entry);
372 if (NULL != mq_entry)
374 GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
375 ntohs (mq_entry->msg->size),
376 GNUNET_TIME_UNIT_FOREVER_REL,
377 &transmit_ready_notify, NULL);
383 * Queues a message in send queue for sending to the service
385 * @param client the client to whom the queued message has to be sent
386 * @param msg the message to queue
389 queue_message (struct GNUNET_SERVER_Client *client,
390 struct GNUNET_MessageHeader *msg)
392 struct MessageQueue *mq_entry;
396 type = ntohs (msg->type);
397 size = ntohs (msg->size);
398 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
399 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
400 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
402 mq_entry->client = client;
403 LOG_DEBUG ( "Queueing message of type %u, size %u for sending\n", type,
405 GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
406 if (NULL == transmit_handle)
408 GNUNET_SERVER_notify_transmit_ready (client, size,
409 GNUNET_TIME_UNIT_FOREVER_REL,
410 &transmit_ready_notify, NULL);
415 * Function to add a host to the current list of known hosts
417 * @param host the host to add
418 * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
422 host_list_add (struct GNUNET_TESTBED_Host *host)
426 host_id = GNUNET_TESTBED_host_get_id_ (host);
427 if (host_list_size <= host_id)
429 host_list = GNUNET_realloc (host_list,
430 sizeof (struct GNUNET_TESTBED_Host *)
432 host_list_size += (host_id + 10);
434 if (NULL != host_list[host_id])
436 LOG_DEBUG ("A host with id: %u already exists\n", host_id);
437 return GNUNET_SYSERR;
439 host_list[host_id] = host;
445 * Adds a route to the route list
447 * @param route the route to add
450 route_list_add (struct Route *route)
452 if (route->dest > route_list_size)
454 route_list_size += LIST_GROW_STEP;
455 route_list = GNUNET_realloc (route_list, sizeof (struct Route *)
458 GNUNET_assert (NULL == route_list[route->dest]);
459 route_list[route->dest] = route;
464 * Routes message to a host given its host_id
466 * @param host_id the id of the destination host
467 * @param msg the message to be routed
470 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
477 * The Link Controller forwarding task
479 * @param cls the LCFContext
480 * @param tc the Task context from scheduler
483 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
487 * Completion callback for host registrations while forwarding Link Controller messages
489 * @param cls the LCFContext
490 * @param emsg the error message; NULL if host registration is successful
493 lcf_proc_cc (void *cls, const char *emsg)
495 struct LCFContext *lcf = cls;
498 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
504 LOG (GNUNET_ERROR_TYPE_WARNING,
505 "Host registration failed with message: %s\n", emsg);
506 lcf->state = FINISHED;
507 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
510 lcf->state = DELEGATED_HOST_REGISTERED;
511 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
514 GNUNET_assert (0); /* Shouldn't reach here */
520 * The Link Controller forwarding task
522 * @param cls the LCFContext
523 * @param tc the Task context from scheduler
526 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
528 struct LCFContext *lcf = cls;
529 struct LCFContextQueue *lcfq;
531 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
536 GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
537 lcf->gateway->controller))
540 GNUNET_TESTBED_register_host (lcf->gateway->controller,
541 host_list[lcf->delegated_host_id],
546 lcf->state = DELEGATED_HOST_REGISTERED;
547 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
550 case DELEGATED_HOST_REGISTERED:
551 GNUNET_TESTBED_controller_link_2 (lcf->gateway->controller,
552 host_list[lcf->delegated_host_id],
553 host_list[lcf->gateway->host_id],
554 lcf->sxcfg, lcf->sxcfg_size,
556 lcf->is_subordinate);
557 lcf->state = FINISHED;
560 GNUNET_assert (lcfq->lcf == lcf);
561 GNUNET_free (lcf->sxcfg);
563 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
565 if (NULL != lcfq_head)
567 GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
573 * Callback for event from slave controllers
575 * @param cls struct Slave *
576 * @param event information about the event
579 slave_event_callback(void *cls,
580 const struct GNUNET_TESTBED_EventInformation *event)
588 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
591 * @param client identification of the client
592 * @param message the actual message
595 handle_init (void *cls,
596 struct GNUNET_SERVER_Client *client,
597 const struct GNUNET_MessageHeader *message)
599 const struct GNUNET_TESTBED_InitMessage *msg;
600 struct GNUNET_TESTBED_Host *host;
602 if (NULL != master_context)
605 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
608 msg = (const struct GNUNET_TESTBED_InitMessage *) message;
609 master_context = GNUNET_malloc (sizeof (struct Context));
610 master_context->client = client;
611 master_context->host_id = ntohl (msg->host_id);
612 host = GNUNET_TESTBED_host_create_with_id (master_context->host_id,
614 host_list_add (host);
615 master_context->event_mask = GNUNET_ntohll (msg->event_mask);
616 GNUNET_SERVER_client_keep (client);
617 LOG_DEBUG ("Created master context with host ID: %u\n",
618 master_context->host_id);
619 GNUNET_SERVER_receive_done (client, GNUNET_OK);
624 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
627 * @param client identification of the client
628 * @param message the actual message
631 handle_add_host (void *cls,
632 struct GNUNET_SERVER_Client *client,
633 const struct GNUNET_MessageHeader *message)
635 struct GNUNET_TESTBED_Host *host;
636 const struct GNUNET_TESTBED_AddHostMessage *msg;
637 struct GNUNET_TESTBED_HostConfirmedMessage *reply;
642 uint16_t username_length;
643 uint16_t hostname_length;
646 msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
647 username_length = ntohs (msg->user_name_length);
648 username_length = (0 == username_length) ? 0 : username_length + 1;
649 username = (char *) &(msg[1]);
650 hostname = username + username_length;
651 if (ntohs (message->size) <=
652 (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length))
655 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
658 hostname_length = ntohs (message->size)
659 - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
660 if (strlen (hostname) != hostname_length)
663 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
666 host_id = ntohl (msg->host_id);
667 LOG_DEBUG ("Received ADDHOST message\n");
668 LOG_DEBUG ("-------host id: %u\n", host_id);
669 if (NULL != hostname) LOG_DEBUG ("-------hostname: %s\n", hostname);
670 if (NULL != username) LOG_DEBUG ("-------username: %s\n", username);
671 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
672 host = GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
673 ntohs (msg->ssh_port));
674 GNUNET_SERVER_receive_done (client, GNUNET_OK);
675 reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
676 if (GNUNET_OK != host_list_add (host))
678 /* We are unable to add a host */
679 emsg = "A host exists with given host-id";
680 LOG_DEBUG ("%s: %u", emsg, host_id);
681 GNUNET_TESTBED_host_destroy (host);
682 reply_size += strlen (emsg) + 1;
683 reply = GNUNET_malloc (reply_size);
684 memcpy (&reply[1], emsg, strlen (emsg) + 1);
687 reply = GNUNET_malloc (reply_size);
688 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
689 reply->header.size = htons (reply_size);
690 reply->host_id = htonl (host_id);
691 queue_message (client, (struct GNUNET_MessageHeader *) reply);
696 * Iterator over hash map entries.
699 * @param key current key code
700 * @param value value in the hash map
701 * @return GNUNET_YES if we should continue to
705 int ss_exists_iterator (void *cls,
706 const struct GNUNET_HashCode * key,
709 struct SharedService *queried_ss = cls;
710 struct SharedService *ss = value;
712 if (0 == strcmp (ss->name, queried_ss->name))
719 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
722 * @param client identification of the client
723 * @param message the actual message
726 handle_configure_shared_service (void *cls,
727 struct GNUNET_SERVER_Client *client,
728 const struct GNUNET_MessageHeader *message)
730 const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
731 struct SharedService *ss;
733 struct GNUNET_HashCode hash;
735 uint16_t service_name_size;
737 msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
738 msg_size = ntohs (message->size);
739 if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
742 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
745 service_name_size = msg_size -
746 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
747 service_name = (char *) &msg[1];
748 if ('\0' != service_name[service_name_size - 1])
751 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
754 LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
755 service_name, ntohl (msg->num_peers));
756 if (ntohl (msg->host_id) != master_context->host_id)
758 route_message (ntohl (msg->host_id), message);
759 GNUNET_SERVER_receive_done (client, GNUNET_OK);
762 GNUNET_SERVER_receive_done (client, GNUNET_OK);
763 ss = GNUNET_malloc (sizeof (struct SharedService));
764 ss->name = strdup (service_name);
765 ss->num_shared = ntohl (msg->num_peers);
766 GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
768 GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
769 &ss_exists_iterator, ss))
771 LOG (GNUNET_ERROR_TYPE_WARNING,
772 "Service %s already configured as a shared service. "
773 "Ignoring service sharing request \n", ss->name);
774 GNUNET_free (ss->name);
778 GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
779 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
784 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
787 * @param client identification of the client
788 * @param message the actual message
791 handle_link_controllers (void *cls,
792 struct GNUNET_SERVER_Client *client,
793 const struct GNUNET_MessageHeader *message)
795 const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
796 struct GNUNET_CONFIGURATION_Handle *cfg;
797 struct LCFContextQueue *lcfq;
799 struct Route *new_route;
803 uint32_t delegated_host_id;
804 uint32_t slave_host_id;
807 if (NULL == master_context)
810 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
813 msize = ntohs (message->size);
814 if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
817 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
820 msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
821 delegated_host_id = ntohl (msg->delegated_host_id);
822 if (delegated_host_id == master_context->host_id)
825 LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
826 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
829 if ((delegated_host_id >= host_list_size) ||
830 (NULL == host_list[delegated_host_id]))
832 LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host not registered with us\n");
833 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
836 slave_host_id = ntohl (msg->slave_host_id);
837 if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
839 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
840 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
843 if (slave_host_id == delegated_host_id)
845 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
846 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
849 msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
850 config_size = ntohs (msg->config_size);
852 if (slave_host_id == master_context->host_id) /* Link from us */
856 if ((delegated_host_id < slave_list_size) &&
857 (NULL != slave_list[delegated_host_id])) /* We have already added */
859 LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
861 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
864 config = GNUNET_malloc (config_size);
865 dest_size = (uLongf) config_size;
866 if (Z_OK != uncompress ((Bytef *) config, &dest_size,
867 (const Bytef *) &msg[1], (uLong) msize))
869 GNUNET_break (0); /* Compression error */
870 GNUNET_free (config);
871 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
874 if (config_size == dest_size)
876 LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
877 GNUNET_free (config);
878 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
880 cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
881 if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
884 GNUNET_break (0); /* Configuration parsing error */
885 GNUNET_free (config);
886 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
889 GNUNET_free (config);
890 if (delegated_host_id >= slave_list_size)
892 slave_list_size += LIST_GROW_STEP;
893 slave_list = GNUNET_realloc (slave_list,
894 sizeof (struct Slave *) * slave_list_size);
896 slave = GNUNET_malloc (sizeof (struct Slave));
897 slave->host_id = delegated_host_id;
898 slave_list[delegated_host_id] = slave;
899 if (1 == msg->is_subordinate)
901 slave->controller_proc =
902 GNUNET_TESTBED_controller_start (host_list[delegated_host_id]);
905 GNUNET_TESTBED_controller_connect (cfg, host_list[delegated_host_id],
906 master_context->event_mask,
907 &slave_event_callback, slave);
908 GNUNET_CONFIGURATION_destroy (cfg);
909 new_route = GNUNET_malloc (sizeof (struct Route));
910 new_route->dest = delegated_host_id;
911 new_route->thru = master_context->host_id;
912 route_list_add (new_route);
913 GNUNET_SERVER_receive_done (client, GNUNET_OK);
917 /* Route the request */
918 if (slave_host_id >= route_list_size)
920 LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
921 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
924 while (NULL != (route = route_list[slave_host_id]))
926 if (route->thru == master_context->host_id)
928 slave_host_id = route->thru;
930 GNUNET_assert (NULL != route); /* because we add routes carefully */
931 GNUNET_assert (route->dest < slave_list_size);
932 GNUNET_assert (NULL != slave_list[route->dest]);
933 lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
934 lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
935 lcfq->lcf->delegated_host_id = delegated_host_id;
936 lcfq->lcf->is_subordinate =
937 (1 == msg->is_subordinate) ? GNUNET_YES : GNUNET_NO;
938 lcfq->lcf->state = INIT;
939 lcfq->lcf->gateway = slave_list[route->dest];
940 lcfq->lcf->sxcfg_size = msize;
941 lcfq->lcf->sxcfg = GNUNET_malloc (msize);
942 lcfq->lcf->scfg_size = config_size;
943 (void) memcpy (lcfq->lcf->sxcfg, &msg[1], msize);
944 if (NULL == lcfq_head)
946 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
947 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
948 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq);
951 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
952 GNUNET_SERVER_receive_done (client, GNUNET_OK);
953 new_route = GNUNET_malloc (sizeof (struct Route));
954 new_route->dest = delegated_host_id;
955 new_route->thru = route->dest;
956 route_list_add (new_route);
961 * Iterator over hash map entries.
964 * @param key current key code
965 * @param value value in the hash map
966 * @return GNUNET_YES if we should continue to
971 ss_map_free_iterator (void *cls,
972 const struct GNUNET_HashCode * key, void *value)
974 struct SharedService *ss = value;
976 GNUNET_assert (GNUNET_YES ==
977 GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
978 GNUNET_free (ss->name);
985 * Task to clean up and shutdown nicely
988 * @param tc the TaskContext from scheduler
991 shutdown_task (void *cls,
992 const struct GNUNET_SCHEDULER_TaskContext *tc)
994 struct LCFContextQueue *lcfq;
997 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
998 GNUNET_SCHEDULER_shutdown ();
999 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
1000 (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
1002 GNUNET_CONTAINER_multihashmap_destroy (ss_map);
1005 GNUNET_DISK_file_close (fh);
1008 if (NULL != lcfq_head)
1010 if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
1012 GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
1013 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1015 if (NULL != lcfq_head->lcf->rhandle)
1016 GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
1018 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1019 for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
1021 GNUNET_free (lcfq->lcf->sxcfg);
1022 GNUNET_free (lcfq->lcf);
1023 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1026 /* Clear host list */
1027 for (id = 0; id < host_list_size; id++)
1028 if (NULL != host_list[id])
1029 GNUNET_TESTBED_host_destroy (host_list[id]);
1030 GNUNET_free_non_null (host_list);
1031 /* Clear route list */
1032 for (id = 0; id < route_list_size; id++)
1033 if (NULL != route_list[id])
1034 GNUNET_free (route_list[id]);
1035 GNUNET_free_non_null (route_list);
1036 /* Clear slave_list */
1037 for (id = 0; id < slave_list_size; id++)
1038 if (NULL != slave_list[id])
1040 GNUNET_assert (NULL != slave_list[id]->controller);
1041 GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
1042 if (NULL != slave_list[id]->controller_proc)
1043 GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
1045 GNUNET_free_non_null (master_context);
1050 * Callback for client disconnect
1053 * @param client the client which has disconnected
1056 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
1058 if (NULL == master_context)
1060 if (client == master_context->client)
1062 LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
1063 GNUNET_SERVER_client_drop (client);
1064 /* should not be needed as we're terminated by failure to read
1065 from stdin, but if stdin fails for some reason, this shouldn't
1066 hurt for now --- might need to revise this later if we ever
1067 decide that master connections might be temporarily down
1069 GNUNET_SCHEDULER_shutdown ();
1077 * @param cls closure
1078 * @param server the initialized server
1079 * @param cfg configuration to use
1082 testbed_run (void *cls,
1083 struct GNUNET_SERVER_Handle *server,
1084 const struct GNUNET_CONFIGURATION_Handle *cfg)
1086 static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
1088 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT,
1089 sizeof (struct GNUNET_TESTBED_InitMessage)},
1090 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
1091 {&handle_configure_shared_service, NULL,
1092 GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
1093 {&handle_link_controllers, NULL,
1094 GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
1098 GNUNET_SERVER_add_handlers (server,
1100 GNUNET_SERVER_disconnect_notify (server,
1101 &client_disconnect_cb,
1103 ss_map = GNUNET_CONTAINER_multihashmap_create (5);
1104 fh = GNUNET_DISK_get_handle_from_native (stdin);
1107 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1112 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1120 * The starting point of execution
1122 int main (int argc, char *const *argv)
1126 GNUNET_SERVICE_run (argc,
1129 GNUNET_SERVICE_OPTION_NONE,