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"
30 #include "gnunet_transport_service.h"
33 #include "gnunet_testbed_service.h"
35 #include "testbed_api.h"
36 #include "testbed_api_hosts.h"
37 #include "gnunet_testing_lib-new.h"
42 #define LOG(kind,...) \
43 GNUNET_log (kind, __VA_ARGS__)
48 #define LOG_DEBUG(...) \
49 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
52 #define LIST_GROW_STEP 10
57 * The client handle associated with this context
59 struct GNUNET_SERVER_Client *client;
62 * The network address of the master controller
67 * The TESTING system handle for starting peers locally
69 struct GNUNET_TESTING_System *system;
72 * Event mask of event to be responded in this context
77 * Our host id according to this context
84 * The message queue for sending messages to clients
89 * The message to be sent
91 struct GNUNET_MessageHeader *msg;
94 * The client to send the message to
96 struct GNUNET_SERVER_Client *client;
99 * next pointer for DLL
101 struct MessageQueue *next;
104 * prev pointer for DLL
106 struct MessageQueue *prev;
111 * The structure for identifying a shared service
116 * The name of the shared service
121 * Number of shared peers per instance of the shared service
126 * Number of peers currently sharing the service
128 uint32_t num_sharing;
143 * The host destination is reachable thru
150 * Structure representing a connected(directly-linked) controller
155 * The controller process handle if we had started the controller
157 struct GNUNET_TESTBED_ControllerProc *controller_proc;
160 * The controller handle
162 struct GNUNET_TESTBED_Controller *controller;
165 * The id of the host this controller is running on
172 * States of LCFContext
177 * The Context has been initialized; Nothing has been done on it
182 * Delegated host has been registered at the forwarding controller
184 DELEGATED_HOST_REGISTERED,
187 * The slave host has been registred at the forwarding controller
189 SLAVE_HOST_REGISTERED,
192 * The context has been finished (may have error)
200 * Link controllers request forwarding context
205 * The serialized and compressed configuration
210 * The gateway which will pass the link message to delegated host
212 struct Slave *gateway;
215 * The host registration handle while registered hosts in this context
217 struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
220 * The size of the compressed serialized configuration
225 * The size of the uncompressed configuration
230 * Should the delegated host be started by the slave host?
235 * The state of this context
237 enum LCFContextState state;
242 uint32_t delegated_host_id;
247 uint32_t slave_host_id;
253 * Structure of a queue entry in LCFContext request queue
255 struct LCFContextQueue
260 struct LCFContext *lcf;
265 struct LCFContextQueue *next;
270 struct LCFContextQueue *prev;
275 * A locally started peer
280 * The peer handle from testing API
282 struct GNUNET_TESTING_Peer *peer;
285 * The modified (by GNUNET_TESTING_peer_configure) configuration this peer is
288 struct GNUNET_CONFIGURATION_Handle *cfg;
291 * Our local reference id for this peer
299 * State information for overlay connect context
309 * Peer 1 has connected to peer0
311 OCC_STATE_PEER0_SUCCESS,
314 * Peer 2 has connected to peer1
316 OCC_STATE_PEER1_SUCCESS,
322 * Context information for connecting 2 peers in overlay
324 struct OverlayConnectContext
327 * The client which has requested for overlay connection
329 struct GNUNET_SERVER_Client *client;
334 struct Peer * peers[2];
337 * Transport handle of peers
339 struct GNUNET_TRANSPORT_Handle *peers_transport[2];
344 struct GNUNET_MessageHeader *peers_hello[2];
347 * Get hello handle for peers
349 struct GNUNET_TRANSPORT_GetHelloHandle *peers_ghh[2];
352 * The peer identity of peers
354 struct GNUNET_PeerIdentity peers_identity[2];
357 * The id of the operation responsible for creating this context
362 * State information for determining whose HELLOs have been successfully
371 * Wrapper around OverlayConnectContext
373 struct OverlayConnectContextWrapper
376 * The overlay connect context
378 struct OverlayConnectContext *occ;
381 * The peer number in reference; should be 0 or 1
388 * The master context; generated with the first INIT message
390 static struct Context *master_context;
397 * Current Transmit Handle; NULL if no notify transmit exists currently
399 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
406 * The head for the LCF queue
408 static struct LCFContextQueue *lcfq_head;
411 * The tail for the LCF queue
413 static struct LCFContextQueue *lcfq_tail;
416 * The message queue head
418 static struct MessageQueue *mq_head;
421 * The message queue tail
423 static struct MessageQueue *mq_tail;
428 static struct GNUNET_TESTBED_Host **host_list;
433 static struct Route **route_list;
436 * A list of directly linked neighbours
438 static struct Slave **slave_list;
441 * A list of peers we own locally
443 static struct Peer **peer_list;
446 * The hashmap of shared services
448 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
451 * The size of the host list
453 static uint32_t host_list_size;
456 * The size of the route list
458 static uint32_t route_list_size;
461 * The size of directly linked neighbours list
463 static uint32_t slave_list_size;
466 * The size of the peer list
468 static uint32_t peer_list_size;
475 * The lcf_task handle
477 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
480 * The shutdown task handle
482 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
486 * Function called to notify a client about the connection begin ready to queue
487 * more data. "buf" will be NULL and "size" zero if the connection was closed
488 * for writing in the meantime.
491 * @param size number of bytes available in buf
492 * @param buf where the callee should write the message
493 * @return number of bytes written to buf
496 transmit_ready_notify (void *cls, size_t size, void *buf)
498 struct MessageQueue *mq_entry;
500 transmit_handle = NULL;
502 GNUNET_assert (NULL != mq_entry);
505 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
506 size = ntohs (mq_entry->msg->size);
507 memcpy (buf, mq_entry->msg, size);
508 GNUNET_free (mq_entry->msg);
509 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
510 GNUNET_free (mq_entry);
512 if (NULL != mq_entry)
514 GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
515 ntohs (mq_entry->msg->size),
516 GNUNET_TIME_UNIT_FOREVER_REL,
517 &transmit_ready_notify, NULL);
523 * Queues a message in send queue for sending to the service
525 * @param client the client to whom the queued message has to be sent
526 * @param msg the message to queue
529 queue_message (struct GNUNET_SERVER_Client *client,
530 struct GNUNET_MessageHeader *msg)
532 struct MessageQueue *mq_entry;
536 type = ntohs (msg->type);
537 size = ntohs (msg->size);
538 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
539 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
540 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
542 mq_entry->client = client;
543 LOG_DEBUG ( "Queueing message of type %u, size %u for sending\n", type,
545 GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
546 if (NULL == transmit_handle)
548 GNUNET_SERVER_notify_transmit_ready (client, size,
549 GNUNET_TIME_UNIT_FOREVER_REL,
550 &transmit_ready_notify, NULL);
555 * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
557 * @param ptr the memory block to realloc
558 * @param size the size of ptr
559 * @param new_size the size to which ptr has to be realloc'ed
560 * @return the newly reallocated memory block
563 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
565 ptr = GNUNET_realloc (ptr, new_size);
567 ptr = memset (ptr + size, 0, new_size - size);
573 * Function to add a host to the current list of known hosts
575 * @param host the host to add
576 * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
580 host_list_add (struct GNUNET_TESTBED_Host *host)
584 host_id = GNUNET_TESTBED_host_get_id_ (host);
585 if (host_list_size <= host_id)
588 TESTBED_realloc (host_list,
589 sizeof (struct GNUNET_TESTBED_Host *) * host_list_size,
590 sizeof (struct GNUNET_TESTBED_Host *) *
591 (host_list_size + LIST_GROW_STEP));
592 host_list_size += LIST_GROW_STEP;
594 if (NULL != host_list[host_id])
596 LOG_DEBUG ("A host with id: %u already exists\n", host_id);
597 return GNUNET_SYSERR;
599 host_list[host_id] = host;
605 * Adds a route to the route list
607 * @param route the route to add
610 route_list_add (struct Route *route)
612 if (route->dest >= route_list_size)
615 TESTBED_realloc (route_list,
616 sizeof (struct Route *) * route_list_size,
617 sizeof (struct Route *) *
618 (route_list_size + LIST_GROW_STEP));
619 route_list_size += LIST_GROW_STEP;
621 GNUNET_assert (NULL == route_list[route->dest]);
622 route_list[route->dest] = route;
627 * Adds a slave to the slave array
629 * @param slave the slave controller to add
632 slave_list_add (struct Slave *slave)
634 if (slave->host_id >= slave_list_size)
636 slave_list = TESTBED_realloc (slave_list,
637 sizeof (struct Slave *) *slave_list_size,
638 sizeof (struct Slave *) *
639 (slave_list_size + LIST_GROW_STEP));
640 slave_list_size += LIST_GROW_STEP;
642 GNUNET_assert (NULL == slave_list[slave->host_id]);
643 slave_list[slave->host_id] = slave;
648 * Adds a peer to the peer array
650 * @param peer the peer to add
653 peer_list_add (struct Peer *peer)
655 if (peer->id >= peer_list_size)
657 peer_list = TESTBED_realloc (peer_list,
658 sizeof (struct Peer *) * peer_list_size,
659 sizeof (struct Peer *) *
660 (peer_list_size + LIST_GROW_STEP));
661 peer_list_size += LIST_GROW_STEP;
663 GNUNET_assert (NULL == peer_list[peer->id]);
664 peer_list[peer->id] = peer;
669 * Routes message to a host given its host_id
671 * @param host_id the id of the destination host
672 * @param msg the message to be routed
675 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
682 * The Link Controller forwarding task
684 * @param cls the LCFContext
685 * @param tc the Task context from scheduler
688 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
692 * Completion callback for host registrations while forwarding Link Controller messages
694 * @param cls the LCFContext
695 * @param emsg the error message; NULL if host registration is successful
698 lcf_proc_cc (void *cls, const char *emsg)
700 struct LCFContext *lcf = cls;
703 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
708 goto registration_error;
709 lcf->state = DELEGATED_HOST_REGISTERED;
710 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
712 case DELEGATED_HOST_REGISTERED:
714 goto registration_error;
715 lcf->state = SLAVE_HOST_REGISTERED;
716 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
719 GNUNET_assert (0); /* Shouldn't reach here */
724 LOG (GNUNET_ERROR_TYPE_WARNING,
725 "Host registration failed with message: %s\n", emsg);
726 lcf->state = FINISHED;
727 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
732 * The Link Controller forwarding task
734 * @param cls the LCFContext
735 * @param tc the Task context from scheduler
738 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
740 struct LCFContext *lcf = cls;
741 struct LCFContextQueue *lcfq;
743 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
748 GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
749 lcf->gateway->controller))
752 GNUNET_TESTBED_register_host (lcf->gateway->controller,
753 host_list[lcf->delegated_host_id],
758 lcf->state = DELEGATED_HOST_REGISTERED;
759 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
762 case DELEGATED_HOST_REGISTERED:
764 GNUNET_TESTBED_is_host_registered_ (host_list[lcf->slave_host_id],
765 lcf->gateway->controller))
768 GNUNET_TESTBED_register_host (lcf->gateway->controller,
769 host_list[lcf->slave_host_id],
774 lcf->state = SLAVE_HOST_REGISTERED;
775 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
778 case SLAVE_HOST_REGISTERED:
779 GNUNET_TESTBED_controller_link_2 (lcf->gateway->controller,
780 host_list[lcf->delegated_host_id],
781 host_list[lcf->slave_host_id],
782 lcf->sxcfg, lcf->sxcfg_size,
784 lcf->is_subordinate);
785 lcf->state = FINISHED;
786 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
790 GNUNET_assert (lcfq->lcf == lcf);
791 GNUNET_free (lcf->sxcfg);
793 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
795 if (NULL != lcfq_head)
797 GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
803 * Callback for event from slave controllers
805 * @param cls struct Slave *
806 * @param event information about the event
809 slave_event_callback(void *cls,
810 const struct GNUNET_TESTBED_EventInformation *event)
817 * Callback to signal successfull startup of the controller process
819 * @param cls the closure from GNUNET_TESTBED_controller_start()
820 * @param cfg the configuration with which the controller has been started;
821 * NULL if status is not GNUNET_OK
822 * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
823 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
826 slave_status_callback (void *cls,
827 const struct GNUNET_CONFIGURATION_Handle *cfg,
830 struct Slave *slave = cls;
832 if (GNUNET_SYSERR == status)
834 slave->controller_proc = NULL;
835 LOG (GNUNET_ERROR_TYPE_WARNING,
836 "Unexpected slave shutdown\n");
837 GNUNET_SCHEDULER_shutdown (); /* We too shutdown */
841 GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
842 master_context->event_mask,
843 &slave_event_callback, slave);
848 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
851 * @param client identification of the client
852 * @param message the actual message
855 handle_init (void *cls,
856 struct GNUNET_SERVER_Client *client,
857 const struct GNUNET_MessageHeader *message)
859 const struct GNUNET_TESTBED_InitMessage *msg;
860 struct GNUNET_TESTBED_Host *host;
864 if (NULL != master_context)
867 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
870 msg = (const struct GNUNET_TESTBED_InitMessage *) message;
871 master_context = GNUNET_malloc (sizeof (struct Context));
872 master_context->client = client;
873 master_context->host_id = ntohl (msg->host_id);
874 GNUNET_assert (GNUNET_OK ==
875 GNUNET_SERVER_client_get_address (client, &addr, &addrlen));
876 master_context->master_ip = GNUNET_malloc (NI_MAXHOST);
877 if (0 != getnameinfo (addr, addrlen, master_context->master_ip, NI_MAXHOST,
878 NULL, 0, NI_NUMERICHOST))
880 LOG (GNUNET_ERROR_TYPE_WARNING,
881 "Cannot determine the ip of master controller: %s\n", STRERROR (errno));
883 GNUNET_free (master_context->master_ip);
887 if (0 == strcasecmp (master_context->master_ip, "localhost"))
888 { /* Hack for connections via unix sockets */
889 LOG_DEBUG ("May be using local sockets - assuming loopback for master ip\n");
890 GNUNET_free (master_context->master_ip);
891 master_context->master_ip = strdup ("127.0.0.1");
893 LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
894 master_context->system =
895 GNUNET_TESTING_system_create ("testbed", master_context->master_ip);
896 host = GNUNET_TESTBED_host_create_with_id (master_context->host_id,
898 host_list_add (host);
899 master_context->event_mask = GNUNET_ntohll (msg->event_mask);
900 GNUNET_SERVER_client_keep (client);
901 LOG_DEBUG ("Created master context with host ID: %u\n",
902 master_context->host_id);
903 GNUNET_SERVER_receive_done (client, GNUNET_OK);
908 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
911 * @param client identification of the client
912 * @param message the actual message
915 handle_add_host (void *cls,
916 struct GNUNET_SERVER_Client *client,
917 const struct GNUNET_MessageHeader *message)
919 struct GNUNET_TESTBED_Host *host;
920 const struct GNUNET_TESTBED_AddHostMessage *msg;
921 struct GNUNET_TESTBED_HostConfirmedMessage *reply;
926 uint16_t username_length;
927 uint16_t hostname_length;
931 msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
932 msize = ntohs (msg->header.size);
933 username = (char *) &(msg[1]);
934 username_length = ntohs (msg->user_name_length);
935 GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage)
936 + username_length + 1)); /* msg must contain hostname */
937 if (0 != username_length)
938 GNUNET_assert ('\0' == username[username_length]);
939 username_length = (0 == username_length) ? 0 : username_length + 1;
940 hostname = username + username_length;
941 hostname_length = msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage)
943 GNUNET_assert ('\0' == hostname[hostname_length - 1]);
944 GNUNET_assert (strlen (hostname) == hostname_length - 1);
945 host_id = ntohl (msg->host_id);
946 LOG_DEBUG ("Received ADDHOST message\n");
947 LOG_DEBUG ("-------host id: %u\n", host_id);
948 if (NULL != hostname) LOG_DEBUG ("-------hostname: %s\n", hostname);
949 if (0 != username_length) LOG_DEBUG ("-------username: %s\n", username);
950 else LOG_DEBUG ("-------username: NULL\n");
951 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
952 host = GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
953 ntohs (msg->ssh_port));
954 GNUNET_SERVER_receive_done (client, GNUNET_OK);
955 reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
956 if (GNUNET_OK != host_list_add (host))
958 /* We are unable to add a host */
959 emsg = "A host exists with given host-id";
960 LOG_DEBUG ("%s: %u", emsg, host_id);
961 GNUNET_TESTBED_host_destroy (host);
962 reply_size += strlen (emsg) + 1;
963 reply = GNUNET_malloc (reply_size);
964 memcpy (&reply[1], emsg, strlen (emsg) + 1);
967 reply = GNUNET_malloc (reply_size);
968 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
969 reply->header.size = htons (reply_size);
970 reply->host_id = htonl (host_id);
971 queue_message (client, (struct GNUNET_MessageHeader *) reply);
976 * Iterator over hash map entries.
979 * @param key current key code
980 * @param value value in the hash map
981 * @return GNUNET_YES if we should continue to
985 int ss_exists_iterator (void *cls,
986 const struct GNUNET_HashCode * key,
989 struct SharedService *queried_ss = cls;
990 struct SharedService *ss = value;
992 if (0 == strcmp (ss->name, queried_ss->name))
1000 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1003 * @param client identification of the client
1004 * @param message the actual message
1007 handle_configure_shared_service (void *cls,
1008 struct GNUNET_SERVER_Client *client,
1009 const struct GNUNET_MessageHeader *message)
1011 const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1012 struct SharedService *ss;
1014 struct GNUNET_HashCode hash;
1016 uint16_t service_name_size;
1018 msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1019 msg_size = ntohs (message->size);
1020 if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1023 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1026 service_name_size = msg_size -
1027 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1028 service_name = (char *) &msg[1];
1029 if ('\0' != service_name[service_name_size - 1])
1032 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1035 LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1036 service_name, ntohl (msg->num_peers));
1037 if (ntohl (msg->host_id) != master_context->host_id)
1039 route_message (ntohl (msg->host_id), message);
1040 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1043 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1044 ss = GNUNET_malloc (sizeof (struct SharedService));
1045 ss->name = strdup (service_name);
1046 ss->num_shared = ntohl (msg->num_peers);
1047 GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1048 if (GNUNET_SYSERR ==
1049 GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1050 &ss_exists_iterator, ss))
1052 LOG (GNUNET_ERROR_TYPE_WARNING,
1053 "Service %s already configured as a shared service. "
1054 "Ignoring service sharing request \n", ss->name);
1055 GNUNET_free (ss->name);
1059 GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1060 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1065 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1068 * @param client identification of the client
1069 * @param message the actual message
1072 handle_link_controllers (void *cls,
1073 struct GNUNET_SERVER_Client *client,
1074 const struct GNUNET_MessageHeader *message)
1076 const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1077 struct GNUNET_CONFIGURATION_Handle *cfg;
1078 struct LCFContextQueue *lcfq;
1079 struct Route *route;
1080 struct Route *new_route;
1084 uint32_t delegated_host_id;
1085 uint32_t slave_host_id;
1088 if (NULL == master_context)
1091 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1094 msize = ntohs (message->size);
1095 if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1098 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1101 msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1102 delegated_host_id = ntohl (msg->delegated_host_id);
1103 if (delegated_host_id == master_context->host_id)
1106 LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1107 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1110 if ((delegated_host_id >= host_list_size) ||
1111 (NULL == host_list[delegated_host_id]))
1113 LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host not registered with us\n");
1114 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1117 slave_host_id = ntohl (msg->slave_host_id);
1118 if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1120 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
1121 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1124 if (slave_host_id == delegated_host_id)
1126 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1127 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1130 msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1131 config_size = ntohs (msg->config_size);
1133 if (slave_host_id == master_context->host_id) /* Link from us */
1135 struct Slave *slave;
1137 if ((delegated_host_id < slave_list_size) &&
1138 (NULL != slave_list[delegated_host_id])) /* We have already added */
1140 LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1142 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1145 config = GNUNET_malloc (config_size);
1146 dest_size = (uLongf) config_size;
1147 if (Z_OK != uncompress ((Bytef *) config, &dest_size,
1148 (const Bytef *) &msg[1], (uLong) msize))
1150 GNUNET_break (0); /* Compression error */
1151 GNUNET_free (config);
1152 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1155 if (config_size == dest_size)
1157 LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1158 GNUNET_free (config);
1159 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1162 cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
1163 if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1166 GNUNET_break (0); /* Configuration parsing error */
1167 GNUNET_free (config);
1168 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1171 GNUNET_free (config);
1172 if ((delegated_host_id < slave_list_size) &&
1173 (NULL != slave_list[delegated_host_id]))
1175 GNUNET_break (0); /* Configuration parsing error */
1176 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1179 slave = GNUNET_malloc (sizeof (struct Slave));
1180 slave->host_id = delegated_host_id;
1181 slave_list_add (slave);
1182 if (1 == msg->is_subordinate)
1184 slave->controller_proc =
1185 GNUNET_TESTBED_controller_start (master_context->master_ip,
1186 host_list[slave->host_id],
1187 cfg, &slave_status_callback,
1192 GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1193 master_context->event_mask,
1194 &slave_event_callback, slave);
1196 GNUNET_CONFIGURATION_destroy (cfg);
1197 new_route = GNUNET_malloc (sizeof (struct Route));
1198 new_route->dest = delegated_host_id;
1199 new_route->thru = master_context->host_id;
1200 route_list_add (new_route);
1201 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1205 /* Route the request */
1206 if (slave_host_id >= route_list_size)
1208 LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1209 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1212 lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1213 lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1214 lcfq->lcf->delegated_host_id = delegated_host_id;
1215 lcfq->lcf->slave_host_id = slave_host_id;
1216 while (NULL != (route = route_list[slave_host_id]))
1218 if (route->thru == master_context->host_id)
1220 slave_host_id = route->thru;
1222 GNUNET_assert (NULL != route); /* because we add routes carefully */
1223 GNUNET_assert (route->dest < slave_list_size);
1224 GNUNET_assert (NULL != slave_list[route->dest]);
1225 lcfq->lcf->is_subordinate =
1226 (1 == msg->is_subordinate) ? GNUNET_YES : GNUNET_NO;
1227 lcfq->lcf->state = INIT;
1228 lcfq->lcf->gateway = slave_list[route->dest];
1229 lcfq->lcf->sxcfg_size = msize;
1230 lcfq->lcf->sxcfg = GNUNET_malloc (msize);
1231 lcfq->lcf->scfg_size = config_size;
1232 (void) memcpy (lcfq->lcf->sxcfg, &msg[1], msize);
1233 if (NULL == lcfq_head)
1235 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1236 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1237 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq);
1240 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1241 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1242 new_route = GNUNET_malloc (sizeof (struct Route));
1243 new_route->dest = delegated_host_id;
1244 new_route->thru = route->dest;
1245 route_list_add (new_route);
1250 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
1253 * @param client identification of the client
1254 * @param message the actual message
1257 handle_peer_create (void *cls,
1258 struct GNUNET_SERVER_Client *client,
1259 const struct GNUNET_MessageHeader *message)
1261 const struct GNUNET_TESTBED_PeerCreateMessage *msg;
1262 struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
1263 struct GNUNET_CONFIGURATION_Handle *cfg;
1267 uint32_t config_size;
1271 msize = ntohs (message->size);
1272 if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
1274 GNUNET_break (0); /* We need configuration */
1275 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1278 msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
1279 if (ntohl (msg->host_id) == master_context->host_id)
1284 /* We are responsible for this peer */
1285 msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1286 config_size = ntohl (msg->config_size);
1287 config = GNUNET_malloc (config_size);
1288 dest_size = config_size;
1289 if (Z_OK != (ret = uncompress ((Bytef *) config, (uLongf *) &dest_size,
1290 (const Bytef *) &msg[1], (uLong) msize)))
1292 GNUNET_break (0); /* uncompression error */
1293 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1296 if (config_size != dest_size)
1298 GNUNET_break (0);/* Uncompressed config size mismatch */
1299 GNUNET_free (config);
1300 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1303 cfg = GNUNET_CONFIGURATION_create ();
1304 if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1307 GNUNET_break (0); /* Configuration parsing error */
1308 GNUNET_free (config);
1309 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1312 GNUNET_free (config);
1313 peer = GNUNET_malloc (sizeof (struct Peer));
1315 peer->id = ntohl (msg->peer_id);
1316 LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
1317 peer->peer = GNUNET_TESTING_peer_configure (master_context->system, peer->cfg,
1321 if (NULL == peer->peer)
1323 LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
1327 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1330 peer_list_add (peer);
1331 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1332 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1333 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
1334 reply->peer_id = msg->peer_id;
1335 reply->operation_id = msg->operation_id;
1336 queue_message (client, &reply->header);
1337 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1341 /* FIXME: Forward the peer to other host */
1343 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1348 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1351 * @param client identification of the client
1352 * @param message the actual message
1355 handle_peer_destroy (void *cls,
1356 struct GNUNET_SERVER_Client *client,
1357 const struct GNUNET_MessageHeader *message)
1359 const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
1360 struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *reply;
1363 uint16_t reply_size;
1365 msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
1366 peer_id = ntohl (msg->peer_id);
1367 LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
1368 peer_id, GNUNET_ntohll (msg->operation_id));
1369 if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
1372 /* FIXME: Reply with failure event message or forward to slave controller */
1373 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1376 GNUNET_TESTING_peer_destroy (peer_list[peer_id]->peer);
1377 GNUNET_CONFIGURATION_destroy (peer_list[peer_id]->cfg);
1378 GNUNET_free (peer_list[peer_id]);
1379 peer_list[peer_id] = NULL;
1380 for (id = 0; id < LIST_GROW_STEP; id++)
1382 if (((peer_id + id >= peer_list_size) ||
1383 (NULL != peer_list[peer_id])))
1386 if (LIST_GROW_STEP == id)
1388 peer_list_size -= LIST_GROW_STEP;
1389 peer_list = GNUNET_realloc (peer_list, peer_list_size);
1392 sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1393 reply = GNUNET_malloc (reply_size);
1394 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1395 reply->header.size = htons (reply_size);
1396 reply->operation_id = msg->operation_id;
1397 reply->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1398 queue_message (client, &reply->header);
1399 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1404 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1407 * @param client identification of the client
1408 * @param message the actual message
1411 handle_peer_start (void *cls,
1412 struct GNUNET_SERVER_Client *client,
1413 const struct GNUNET_MessageHeader *message)
1415 const struct GNUNET_TESTBED_PeerStartMessage *msg;
1416 struct GNUNET_TESTBED_PeerEventMessage *reply;
1419 msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
1420 peer_id = ntohl (msg->peer_id);
1421 if ((peer_id >= peer_list_size)
1422 || (NULL == peer_list[peer_id]))
1425 /* FIXME: reply with failure message or forward to slave controller */
1426 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1429 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer_list[peer_id]->peer))
1431 /* FIXME: return FAILURE message */
1433 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1436 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1437 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1438 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1439 reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
1440 reply->host_id = htonl (master_context->host_id);
1441 reply->peer_id = msg->peer_id;
1442 reply->operation_id = msg->operation_id;
1443 queue_message (client, &reply->header);
1444 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1449 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1452 * @param client identification of the client
1453 * @param message the actual message
1456 handle_peer_stop (void *cls,
1457 struct GNUNET_SERVER_Client *client,
1458 const struct GNUNET_MessageHeader *message)
1460 const struct GNUNET_TESTBED_PeerStopMessage *msg;
1461 struct GNUNET_TESTBED_PeerEventMessage *reply;
1464 msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
1465 peer_id = ntohl (msg->peer_id);
1466 if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1468 GNUNET_break (0); /* FIXME: route to slave? */
1469 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1472 if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer_list[peer_id]->peer))
1474 /* FIXME: return FAILURE message */
1476 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1479 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1480 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1481 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1482 reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
1483 reply->host_id = htonl (master_context->host_id);
1484 reply->peer_id = msg->peer_id;
1485 reply->operation_id = msg->operation_id;
1486 queue_message (client, &reply->header);
1487 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1492 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
1495 * @param client identification of the client
1496 * @param message the actual message
1499 handle_peer_get_config (void *cls,
1500 struct GNUNET_SERVER_Client *client,
1501 const struct GNUNET_MessageHeader *message)
1503 const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
1504 struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
1512 msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
1513 peer_id = ntohl (msg->peer_id);
1514 if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1516 /* FIXME: return FAILURE message */
1518 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1520 config = GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->cfg,
1522 xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
1523 GNUNET_free (config);
1524 msize = xc_size + sizeof (struct
1525 GNUNET_TESTBED_PeerConfigurationInformationMessage);
1526 reply = GNUNET_realloc (xconfig, msize);
1527 (void) memmove (&reply[1], reply, xc_size);
1528 reply->header.size = htons (msize);
1529 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
1530 reply->peer_id = msg->peer_id;
1531 reply->operation_id = msg->operation_id;
1532 GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->peer,
1533 &reply->peer_identity);
1534 reply->config_size = htons ((uint16_t) c_size);
1535 queue_message (client, &reply->header);
1536 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1541 * Exchanges HELLO of peers among them
1543 * @param occ the OverlayConnectContext to look into for HELLO messages
1546 exchange_hellos (struct OverlayConnectContext *occ)
1550 GNUNET_assert (NULL != occ->peers_hello[0]);
1551 GNUNET_assert (NULL != occ->peers_hello[1]);
1552 LOG_DEBUG ("Exchanging hellos\n");
1553 for (peer = 0; peer < 2; peer++)
1555 GNUNET_TRANSPORT_offer_hello (occ->peers_transport[peer],
1556 occ->peers_hello[peer ^ 1],
1558 GNUNET_TRANSPORT_try_connect (occ->peers_transport[peer],
1559 &occ->peers_identity[peer ^ 1]);
1560 GNUNET_free (occ->peers_hello[peer ^ 1]);
1566 * Function called whenever there is an update to the
1567 * HELLO of peers in the OverlayConnectClosure
1569 * @param cls closure
1570 * @param hello our updated HELLO
1573 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
1575 struct OverlayConnectContextWrapper *occw = cls;
1576 struct OverlayConnectContext *occ;
1580 msize = ntohs (hello->size);
1582 GNUNET_assert (peer <= 1);
1584 occ->peers_hello[peer] = GNUNET_malloc (msize);
1585 memcpy (occ->peers_hello[peer], hello, msize);
1586 GNUNET_TRANSPORT_get_hello_cancel (occ->peers_ghh[peer]);
1587 occ->peers_ghh[peer] = NULL;
1588 if (NULL != occ->peers_hello[peer ^ 1])
1589 exchange_hellos (occ);
1594 * Function called to notify transport users that another
1595 * peer connected to us.
1597 * @param cls closure
1598 * @param new_peer the peer that connected
1599 * @param ats performance data
1600 * @param ats_count number of entries in ats (excluding 0-termination)
1603 overlay_connect_notify (void *cls,
1604 const struct GNUNET_PeerIdentity * new_peer,
1605 const struct GNUNET_ATS_Information * ats,
1608 struct OverlayConnectContextWrapper *occw = cls;
1609 struct OverlayConnectContext *occ;
1610 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
1615 if (0 != memcmp (new_peer, &occ->peers_identity[peer ^ 1],
1616 sizeof (struct GNUNET_PeerIdentity)))
1618 LOG_DEBUG ("Unexpected peer %4s connected to peer %4s\n",
1619 GNUNET_i2s (new_peer),
1620 GNUNET_i2s (&occ->peers_identity[peer ^ 1]));
1624 LOG_DEBUG ("Peer %4s connected to peer %4s\n", GNUNET_i2s (new_peer),
1625 GNUNET_i2s (&occ->peers_identity[peer ^ 1]));
1626 GNUNET_TRANSPORT_disconnect (occ->peers_transport[peer]);
1627 occ->peers_transport[peer] = NULL;
1628 if (NULL != occ->peers_transport[peer ^ 1])
1630 /* Peers are connected - now send overlay connect success message */
1631 LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
1632 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1633 msg->header.size = htons (sizeof (struct
1634 GNUNET_TESTBED_ConnectionEventMessage));
1635 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
1636 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
1637 msg->peer1 = occ->peers[0]->id;
1638 msg->peer2 = occ->peers[1]->id;
1639 msg->operation_id = GNUNET_htonll (occ->op_id);
1640 queue_message (occ->client, &msg->header);
1641 GNUNET_SERVER_client_drop (occ->client);
1647 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1650 * @param client identification of the client
1651 * @param message the actual message
1654 handle_overlay_connect (void *cls,
1655 struct GNUNET_SERVER_Client *client,
1656 const struct GNUNET_MessageHeader *message)
1658 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1659 struct OverlayConnectContext *occ;
1660 struct OverlayConnectContextWrapper *occw;
1665 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1666 p1 = ntohl (msg->peer1);
1667 p2 = ntohl (msg->peer2);
1668 GNUNET_assert (p1 < peer_list_size);
1669 GNUNET_assert (NULL != peer_list[p1]);
1670 GNUNET_assert (p2 < peer_list_size);
1671 GNUNET_assert (NULL != peer_list[p2]);
1672 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1673 GNUNET_SERVER_client_keep (client);
1674 occ->client = client;
1675 occ->state = OCC_STATE_INIT;
1676 occ->peers[0] = peer_list[p1];
1677 occ->peers[1] = peer_list[p2];
1678 occ->op_id = GNUNET_ntohll (msg->operation_id);
1679 for (peer = 0; peer < 2; peer++)
1681 occw = GNUNET_malloc (sizeof (struct OverlayConnectContextWrapper));
1684 GNUNET_TESTING_peer_get_identity (occ->peers[peer]->peer,
1685 &occ->peers_identity[peer]);
1686 occ->peers_transport[peer] =
1687 GNUNET_TRANSPORT_connect (occ->peers[peer]->cfg,
1688 &occ->peers_identity[peer], occw, NULL,
1689 &overlay_connect_notify, NULL);
1690 occ->peers_ghh[peer] =
1691 GNUNET_TRANSPORT_get_hello (occ->peers_transport[peer],
1692 &hello_update_cb, occw);
1694 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1699 * Iterator over hash map entries.
1701 * @param cls closure
1702 * @param key current key code
1703 * @param value value in the hash map
1704 * @return GNUNET_YES if we should continue to
1709 ss_map_free_iterator (void *cls,
1710 const struct GNUNET_HashCode * key, void *value)
1712 struct SharedService *ss = value;
1714 GNUNET_assert (GNUNET_YES ==
1715 GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
1716 GNUNET_free (ss->name);
1723 * Task to clean up and shutdown nicely
1726 * @param tc the TaskContext from scheduler
1729 shutdown_task (void *cls,
1730 const struct GNUNET_SCHEDULER_TaskContext *tc)
1732 struct LCFContextQueue *lcfq;
1735 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
1736 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
1737 (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
1739 GNUNET_CONTAINER_multihashmap_destroy (ss_map);
1740 if (NULL != lcfq_head)
1742 if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
1744 GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
1745 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1747 if (NULL != lcfq_head->lcf->rhandle)
1748 GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
1750 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1751 for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
1753 GNUNET_free (lcfq->lcf->sxcfg);
1754 GNUNET_free (lcfq->lcf);
1755 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1758 /* Clear peer list */
1759 for (id = 0; id < peer_list_size; id++)
1760 if (NULL != peer_list[id])
1762 GNUNET_TESTING_peer_destroy (peer_list[id]->peer);
1763 GNUNET_CONFIGURATION_destroy (peer_list[id]->cfg);
1764 GNUNET_free (peer_list[id]);
1766 GNUNET_free_non_null (peer_list);
1767 /* Clear host list */
1768 for (id = 0; id < host_list_size; id++)
1769 if (NULL != host_list[id])
1770 GNUNET_TESTBED_host_destroy (host_list[id]);
1771 GNUNET_free_non_null (host_list);
1772 /* Clear route list */
1773 for (id = 0; id < route_list_size; id++)
1774 if (NULL != route_list[id])
1775 GNUNET_free (route_list[id]);
1776 GNUNET_free_non_null (route_list);
1777 /* Clear slave_list */
1778 for (id = 0; id < slave_list_size; id++)
1779 if (NULL != slave_list[id])
1781 GNUNET_assert (NULL != slave_list[id]->controller);
1782 GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
1783 if (NULL != slave_list[id]->controller_proc)
1784 GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
1786 if (NULL != master_context)
1788 GNUNET_free_non_null (master_context->master_ip);
1789 if (NULL != master_context->system)
1790 GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
1791 GNUNET_free (master_context);
1792 master_context = NULL;
1798 * Callback for client disconnect
1801 * @param client the client which has disconnected
1804 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
1806 if (NULL == master_context)
1808 if (client == master_context->client)
1810 LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
1811 GNUNET_SERVER_client_drop (client);
1812 /* should not be needed as we're terminated by failure to read
1813 from stdin, but if stdin fails for some reason, this shouldn't
1814 hurt for now --- might need to revise this later if we ever
1815 decide that master connections might be temporarily down
1817 //GNUNET_SCHEDULER_shutdown ();
1825 * @param cls closure
1826 * @param server the initialized server
1827 * @param cfg configuration to use
1830 testbed_run (void *cls,
1831 struct GNUNET_SERVER_Handle *server,
1832 const struct GNUNET_CONFIGURATION_Handle *cfg)
1834 static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
1836 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT,
1837 sizeof (struct GNUNET_TESTBED_InitMessage)},
1838 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
1839 {&handle_configure_shared_service, NULL,
1840 GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
1841 {&handle_link_controllers, NULL,
1842 GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
1843 {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
1844 {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
1845 sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
1846 {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
1847 sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
1848 {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
1849 sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
1850 {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
1851 sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
1852 {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
1853 sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
1857 GNUNET_SERVER_add_handlers (server,
1859 GNUNET_SERVER_disconnect_notify (server,
1860 &client_disconnect_cb,
1862 ss_map = GNUNET_CONTAINER_multihashmap_create (5);
1864 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1867 LOG_DEBUG ("Testbed startup complete\n");
1872 * The starting point of execution
1874 int main (int argc, char *const *argv)
1878 GNUNET_SERVICE_run (argc,
1881 GNUNET_SERVICE_OPTION_NONE,