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 * Context information for connecting 2 peers in overlay
301 struct OverlayConnectContext
314 * Transport handle of peer1
316 struct GNUNET_TRANSPORT_Handle *peer1_transport;
319 * Transport handle of peer2
321 struct GNUNET_TRANSPORT_Handle *peer2_transport;
326 struct GNUNET_MessageHeader *peer1_hello;
331 struct GNUNET_MessageHeader *peer2_hello;
334 * Get hello handle for peer1
336 struct GNUNET_TRANSPORT_GetHelloHandle *peer1_ghh;
339 * Get hello handle for peer2
341 struct GNUNET_TRANSPORT_GetHelloHandle *peer2_ghh;
346 * The master context; generated with the first INIT message
348 static struct Context *master_context;
355 * Current Transmit Handle; NULL if no notify transmit exists currently
357 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
364 * The head for the LCF queue
366 static struct LCFContextQueue *lcfq_head;
369 * The tail for the LCF queue
371 static struct LCFContextQueue *lcfq_tail;
374 * The message queue head
376 static struct MessageQueue *mq_head;
379 * The message queue tail
381 static struct MessageQueue *mq_tail;
386 static struct GNUNET_TESTBED_Host **host_list;
391 static struct Route **route_list;
394 * A list of directly linked neighbours
396 static struct Slave **slave_list;
399 * A list of peers we own locally
401 static struct Peer **peer_list;
404 * The hashmap of shared services
406 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
409 * The size of the host list
411 static uint32_t host_list_size;
414 * The size of the route list
416 static uint32_t route_list_size;
419 * The size of directly linked neighbours list
421 static uint32_t slave_list_size;
424 * The size of the peer list
426 static uint32_t peer_list_size;
433 * The lcf_task handle
435 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
438 * The shutdown task handle
440 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
444 * Function called to notify a client about the connection begin ready to queue
445 * more data. "buf" will be NULL and "size" zero if the connection was closed
446 * for writing in the meantime.
449 * @param size number of bytes available in buf
450 * @param buf where the callee should write the message
451 * @return number of bytes written to buf
454 transmit_ready_notify (void *cls, size_t size, void *buf)
456 struct MessageQueue *mq_entry;
458 transmit_handle = NULL;
460 GNUNET_assert (NULL != mq_entry);
463 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
464 size = ntohs (mq_entry->msg->size);
465 memcpy (buf, mq_entry->msg, size);
466 GNUNET_free (mq_entry->msg);
467 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
468 GNUNET_free (mq_entry);
470 if (NULL != mq_entry)
472 GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
473 ntohs (mq_entry->msg->size),
474 GNUNET_TIME_UNIT_FOREVER_REL,
475 &transmit_ready_notify, NULL);
481 * Queues a message in send queue for sending to the service
483 * @param client the client to whom the queued message has to be sent
484 * @param msg the message to queue
487 queue_message (struct GNUNET_SERVER_Client *client,
488 struct GNUNET_MessageHeader *msg)
490 struct MessageQueue *mq_entry;
494 type = ntohs (msg->type);
495 size = ntohs (msg->size);
496 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
497 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
498 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
500 mq_entry->client = client;
501 LOG_DEBUG ( "Queueing message of type %u, size %u for sending\n", type,
503 GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
504 if (NULL == transmit_handle)
506 GNUNET_SERVER_notify_transmit_ready (client, size,
507 GNUNET_TIME_UNIT_FOREVER_REL,
508 &transmit_ready_notify, NULL);
513 * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
515 * @param ptr the memory block to realloc
516 * @param size the size of ptr
517 * @param new_size the size to which ptr has to be realloc'ed
518 * @return the newly reallocated memory block
521 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
523 ptr = GNUNET_realloc (ptr, new_size);
525 ptr = memset (ptr + size, 0, new_size - size);
531 * Function to add a host to the current list of known hosts
533 * @param host the host to add
534 * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
538 host_list_add (struct GNUNET_TESTBED_Host *host)
542 host_id = GNUNET_TESTBED_host_get_id_ (host);
543 if (host_list_size <= host_id)
546 TESTBED_realloc (host_list,
547 sizeof (struct GNUNET_TESTBED_Host *) * host_list_size,
548 sizeof (struct GNUNET_TESTBED_Host *) *
549 (host_list_size + LIST_GROW_STEP));
550 host_list_size += LIST_GROW_STEP;
552 if (NULL != host_list[host_id])
554 LOG_DEBUG ("A host with id: %u already exists\n", host_id);
555 return GNUNET_SYSERR;
557 host_list[host_id] = host;
563 * Adds a route to the route list
565 * @param route the route to add
568 route_list_add (struct Route *route)
570 if (route->dest >= route_list_size)
573 TESTBED_realloc (route_list,
574 sizeof (struct Route *) * route_list_size,
575 sizeof (struct Route *) *
576 (route_list_size + LIST_GROW_STEP));
577 route_list_size += LIST_GROW_STEP;
579 GNUNET_assert (NULL == route_list[route->dest]);
580 route_list[route->dest] = route;
585 * Adds a slave to the slave array
587 * @param slave the slave controller to add
590 slave_list_add (struct Slave *slave)
592 if (slave->host_id >= slave_list_size)
594 slave_list = TESTBED_realloc (slave_list,
595 sizeof (struct Slave *) *slave_list_size,
596 sizeof (struct Slave *) *
597 (slave_list_size + LIST_GROW_STEP));
598 slave_list_size += LIST_GROW_STEP;
600 GNUNET_assert (NULL == slave_list[slave->host_id]);
601 slave_list[slave->host_id] = slave;
606 * Adds a peer to the peer array
608 * @param peer the peer to add
611 peer_list_add (struct Peer *peer)
613 if (peer->id >= peer_list_size)
615 peer_list = TESTBED_realloc (peer_list,
616 sizeof (struct Peer *) * peer_list_size,
617 sizeof (struct Peer *) *
618 (peer_list_size + LIST_GROW_STEP));
619 peer_list_size += LIST_GROW_STEP;
621 GNUNET_assert (NULL == peer_list[peer->id]);
622 peer_list[peer->id] = peer;
627 * Routes message to a host given its host_id
629 * @param host_id the id of the destination host
630 * @param msg the message to be routed
633 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
640 * The Link Controller forwarding task
642 * @param cls the LCFContext
643 * @param tc the Task context from scheduler
646 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
650 * Completion callback for host registrations while forwarding Link Controller messages
652 * @param cls the LCFContext
653 * @param emsg the error message; NULL if host registration is successful
656 lcf_proc_cc (void *cls, const char *emsg)
658 struct LCFContext *lcf = cls;
661 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
666 goto registration_error;
667 lcf->state = DELEGATED_HOST_REGISTERED;
668 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
670 case DELEGATED_HOST_REGISTERED:
672 goto registration_error;
673 lcf->state = SLAVE_HOST_REGISTERED;
674 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
677 GNUNET_assert (0); /* Shouldn't reach here */
682 LOG (GNUNET_ERROR_TYPE_WARNING,
683 "Host registration failed with message: %s\n", emsg);
684 lcf->state = FINISHED;
685 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
690 * The Link Controller forwarding task
692 * @param cls the LCFContext
693 * @param tc the Task context from scheduler
696 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
698 struct LCFContext *lcf = cls;
699 struct LCFContextQueue *lcfq;
701 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
706 GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
707 lcf->gateway->controller))
710 GNUNET_TESTBED_register_host (lcf->gateway->controller,
711 host_list[lcf->delegated_host_id],
716 lcf->state = DELEGATED_HOST_REGISTERED;
717 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
720 case DELEGATED_HOST_REGISTERED:
722 GNUNET_TESTBED_is_host_registered_ (host_list[lcf->slave_host_id],
723 lcf->gateway->controller))
726 GNUNET_TESTBED_register_host (lcf->gateway->controller,
727 host_list[lcf->slave_host_id],
732 lcf->state = SLAVE_HOST_REGISTERED;
733 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
736 case SLAVE_HOST_REGISTERED:
737 GNUNET_TESTBED_controller_link_2 (lcf->gateway->controller,
738 host_list[lcf->delegated_host_id],
739 host_list[lcf->slave_host_id],
740 lcf->sxcfg, lcf->sxcfg_size,
742 lcf->is_subordinate);
743 lcf->state = FINISHED;
744 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
748 GNUNET_assert (lcfq->lcf == lcf);
749 GNUNET_free (lcf->sxcfg);
751 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
753 if (NULL != lcfq_head)
755 GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
761 * Callback for event from slave controllers
763 * @param cls struct Slave *
764 * @param event information about the event
767 slave_event_callback(void *cls,
768 const struct GNUNET_TESTBED_EventInformation *event)
775 * Callback to signal successfull startup of the controller process
777 * @param cls the closure from GNUNET_TESTBED_controller_start()
778 * @param cfg the configuration with which the controller has been started;
779 * NULL if status is not GNUNET_OK
780 * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
781 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
784 slave_status_callback (void *cls,
785 const struct GNUNET_CONFIGURATION_Handle *cfg,
788 struct Slave *slave = cls;
790 if (GNUNET_SYSERR == status)
792 slave->controller_proc = NULL;
793 LOG (GNUNET_ERROR_TYPE_WARNING,
794 "Unexpected slave shutdown\n");
795 GNUNET_SCHEDULER_shutdown (); /* We too shutdown */
799 GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
800 master_context->event_mask,
801 &slave_event_callback, slave);
806 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
809 * @param client identification of the client
810 * @param message the actual message
813 handle_init (void *cls,
814 struct GNUNET_SERVER_Client *client,
815 const struct GNUNET_MessageHeader *message)
817 const struct GNUNET_TESTBED_InitMessage *msg;
818 struct GNUNET_TESTBED_Host *host;
822 if (NULL != master_context)
825 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
828 msg = (const struct GNUNET_TESTBED_InitMessage *) message;
829 master_context = GNUNET_malloc (sizeof (struct Context));
830 master_context->client = client;
831 master_context->host_id = ntohl (msg->host_id);
832 GNUNET_assert (GNUNET_OK ==
833 GNUNET_SERVER_client_get_address (client, &addr, &addrlen));
834 master_context->master_ip = GNUNET_malloc (NI_MAXHOST);
835 if (0 != getnameinfo (addr, addrlen, master_context->master_ip, NI_MAXHOST,
836 NULL, 0, NI_NUMERICHOST))
838 LOG (GNUNET_ERROR_TYPE_WARNING,
839 "Cannot determine the ip of master controller: %s\n", STRERROR (errno));
841 GNUNET_free (master_context->master_ip);
845 if (0 == strcasecmp (master_context->master_ip, "localhost"))
846 { /* Hack for connections via unix sockets */
847 LOG_DEBUG ("May be using local sockets - assuming loopback for master ip\n");
848 GNUNET_free (master_context->master_ip);
849 master_context->master_ip = strdup ("127.0.0.1");
851 LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
852 master_context->system =
853 GNUNET_TESTING_system_create ("testbed", master_context->master_ip);
854 host = GNUNET_TESTBED_host_create_with_id (master_context->host_id,
856 host_list_add (host);
857 master_context->event_mask = GNUNET_ntohll (msg->event_mask);
858 GNUNET_SERVER_client_keep (client);
859 LOG_DEBUG ("Created master context with host ID: %u\n",
860 master_context->host_id);
861 GNUNET_SERVER_receive_done (client, GNUNET_OK);
866 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
869 * @param client identification of the client
870 * @param message the actual message
873 handle_add_host (void *cls,
874 struct GNUNET_SERVER_Client *client,
875 const struct GNUNET_MessageHeader *message)
877 struct GNUNET_TESTBED_Host *host;
878 const struct GNUNET_TESTBED_AddHostMessage *msg;
879 struct GNUNET_TESTBED_HostConfirmedMessage *reply;
884 uint16_t username_length;
885 uint16_t hostname_length;
889 msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
890 msize = ntohs (msg->header.size);
891 username = (char *) &(msg[1]);
892 username_length = ntohs (msg->user_name_length);
893 GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage)
894 + username_length + 1)); /* msg must contain hostname */
895 if (0 != username_length)
896 GNUNET_assert ('\0' == username[username_length]);
897 username_length = (0 == username_length) ? 0 : username_length + 1;
898 hostname = username + username_length;
899 hostname_length = msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage)
901 GNUNET_assert ('\0' == hostname[hostname_length - 1]);
902 GNUNET_assert (strlen (hostname) == hostname_length - 1);
903 host_id = ntohl (msg->host_id);
904 LOG_DEBUG ("Received ADDHOST message\n");
905 LOG_DEBUG ("-------host id: %u\n", host_id);
906 if (NULL != hostname) LOG_DEBUG ("-------hostname: %s\n", hostname);
907 if (0 != username_length) LOG_DEBUG ("-------username: %s\n", username);
908 else LOG_DEBUG ("-------username: NULL\n");
909 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
910 host = GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
911 ntohs (msg->ssh_port));
912 GNUNET_SERVER_receive_done (client, GNUNET_OK);
913 reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
914 if (GNUNET_OK != host_list_add (host))
916 /* We are unable to add a host */
917 emsg = "A host exists with given host-id";
918 LOG_DEBUG ("%s: %u", emsg, host_id);
919 GNUNET_TESTBED_host_destroy (host);
920 reply_size += strlen (emsg) + 1;
921 reply = GNUNET_malloc (reply_size);
922 memcpy (&reply[1], emsg, strlen (emsg) + 1);
925 reply = GNUNET_malloc (reply_size);
926 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
927 reply->header.size = htons (reply_size);
928 reply->host_id = htonl (host_id);
929 queue_message (client, (struct GNUNET_MessageHeader *) reply);
934 * Iterator over hash map entries.
937 * @param key current key code
938 * @param value value in the hash map
939 * @return GNUNET_YES if we should continue to
943 int ss_exists_iterator (void *cls,
944 const struct GNUNET_HashCode * key,
947 struct SharedService *queried_ss = cls;
948 struct SharedService *ss = value;
950 if (0 == strcmp (ss->name, queried_ss->name))
958 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
961 * @param client identification of the client
962 * @param message the actual message
965 handle_configure_shared_service (void *cls,
966 struct GNUNET_SERVER_Client *client,
967 const struct GNUNET_MessageHeader *message)
969 const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
970 struct SharedService *ss;
972 struct GNUNET_HashCode hash;
974 uint16_t service_name_size;
976 msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
977 msg_size = ntohs (message->size);
978 if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
981 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
984 service_name_size = msg_size -
985 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
986 service_name = (char *) &msg[1];
987 if ('\0' != service_name[service_name_size - 1])
990 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
993 LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
994 service_name, ntohl (msg->num_peers));
995 if (ntohl (msg->host_id) != master_context->host_id)
997 route_message (ntohl (msg->host_id), message);
998 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1001 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1002 ss = GNUNET_malloc (sizeof (struct SharedService));
1003 ss->name = strdup (service_name);
1004 ss->num_shared = ntohl (msg->num_peers);
1005 GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1006 if (GNUNET_SYSERR ==
1007 GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1008 &ss_exists_iterator, ss))
1010 LOG (GNUNET_ERROR_TYPE_WARNING,
1011 "Service %s already configured as a shared service. "
1012 "Ignoring service sharing request \n", ss->name);
1013 GNUNET_free (ss->name);
1017 GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1018 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1023 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1026 * @param client identification of the client
1027 * @param message the actual message
1030 handle_link_controllers (void *cls,
1031 struct GNUNET_SERVER_Client *client,
1032 const struct GNUNET_MessageHeader *message)
1034 const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1035 struct GNUNET_CONFIGURATION_Handle *cfg;
1036 struct LCFContextQueue *lcfq;
1037 struct Route *route;
1038 struct Route *new_route;
1042 uint32_t delegated_host_id;
1043 uint32_t slave_host_id;
1046 if (NULL == master_context)
1049 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1052 msize = ntohs (message->size);
1053 if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1056 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1059 msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1060 delegated_host_id = ntohl (msg->delegated_host_id);
1061 if (delegated_host_id == master_context->host_id)
1064 LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1065 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1068 if ((delegated_host_id >= host_list_size) ||
1069 (NULL == host_list[delegated_host_id]))
1071 LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host not registered with us\n");
1072 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1075 slave_host_id = ntohl (msg->slave_host_id);
1076 if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1078 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
1079 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1082 if (slave_host_id == delegated_host_id)
1084 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1085 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1088 msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1089 config_size = ntohs (msg->config_size);
1091 if (slave_host_id == master_context->host_id) /* Link from us */
1093 struct Slave *slave;
1095 if ((delegated_host_id < slave_list_size) &&
1096 (NULL != slave_list[delegated_host_id])) /* We have already added */
1098 LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1100 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1103 config = GNUNET_malloc (config_size);
1104 dest_size = (uLongf) config_size;
1105 if (Z_OK != uncompress ((Bytef *) config, &dest_size,
1106 (const Bytef *) &msg[1], (uLong) msize))
1108 GNUNET_break (0); /* Compression error */
1109 GNUNET_free (config);
1110 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1113 if (config_size == dest_size)
1115 LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1116 GNUNET_free (config);
1117 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1120 cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
1121 if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1124 GNUNET_break (0); /* Configuration parsing error */
1125 GNUNET_free (config);
1126 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1129 GNUNET_free (config);
1130 if ((delegated_host_id < slave_list_size) &&
1131 (NULL != slave_list[delegated_host_id]))
1133 GNUNET_break (0); /* Configuration parsing error */
1134 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1137 slave = GNUNET_malloc (sizeof (struct Slave));
1138 slave->host_id = delegated_host_id;
1139 slave_list_add (slave);
1140 if (1 == msg->is_subordinate)
1142 slave->controller_proc =
1143 GNUNET_TESTBED_controller_start (master_context->master_ip,
1144 host_list[slave->host_id],
1145 cfg, &slave_status_callback,
1150 GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1151 master_context->event_mask,
1152 &slave_event_callback, slave);
1154 GNUNET_CONFIGURATION_destroy (cfg);
1155 new_route = GNUNET_malloc (sizeof (struct Route));
1156 new_route->dest = delegated_host_id;
1157 new_route->thru = master_context->host_id;
1158 route_list_add (new_route);
1159 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1163 /* Route the request */
1164 if (slave_host_id >= route_list_size)
1166 LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1167 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1170 lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1171 lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1172 lcfq->lcf->delegated_host_id = delegated_host_id;
1173 lcfq->lcf->slave_host_id = slave_host_id;
1174 while (NULL != (route = route_list[slave_host_id]))
1176 if (route->thru == master_context->host_id)
1178 slave_host_id = route->thru;
1180 GNUNET_assert (NULL != route); /* because we add routes carefully */
1181 GNUNET_assert (route->dest < slave_list_size);
1182 GNUNET_assert (NULL != slave_list[route->dest]);
1183 lcfq->lcf->is_subordinate =
1184 (1 == msg->is_subordinate) ? GNUNET_YES : GNUNET_NO;
1185 lcfq->lcf->state = INIT;
1186 lcfq->lcf->gateway = slave_list[route->dest];
1187 lcfq->lcf->sxcfg_size = msize;
1188 lcfq->lcf->sxcfg = GNUNET_malloc (msize);
1189 lcfq->lcf->scfg_size = config_size;
1190 (void) memcpy (lcfq->lcf->sxcfg, &msg[1], msize);
1191 if (NULL == lcfq_head)
1193 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1194 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1195 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq);
1198 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1199 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1200 new_route = GNUNET_malloc (sizeof (struct Route));
1201 new_route->dest = delegated_host_id;
1202 new_route->thru = route->dest;
1203 route_list_add (new_route);
1208 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
1211 * @param client identification of the client
1212 * @param message the actual message
1215 handle_peer_create (void *cls,
1216 struct GNUNET_SERVER_Client *client,
1217 const struct GNUNET_MessageHeader *message)
1219 const struct GNUNET_TESTBED_PeerCreateMessage *msg;
1220 struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
1221 struct GNUNET_CONFIGURATION_Handle *cfg;
1225 uint32_t config_size;
1229 msize = ntohs (message->size);
1230 if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
1232 GNUNET_break (0); /* We need configuration */
1233 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1236 msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
1237 if (ntohl (msg->host_id) == master_context->host_id)
1242 /* We are responsible for this peer */
1243 msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1244 config_size = ntohl (msg->config_size);
1245 config = GNUNET_malloc (config_size);
1246 dest_size = config_size;
1247 if (Z_OK != (ret = uncompress ((Bytef *) config, (uLongf *) &dest_size,
1248 (const Bytef *) &msg[1], (uLong) msize)))
1250 GNUNET_break (0); /* uncompression error */
1251 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1254 if (config_size != dest_size)
1256 GNUNET_break (0);/* Uncompressed config size mismatch */
1257 GNUNET_free (config);
1258 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1261 cfg = GNUNET_CONFIGURATION_create ();
1262 if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1265 GNUNET_break (0); /* Configuration parsing error */
1266 GNUNET_free (config);
1267 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1270 GNUNET_free (config);
1271 peer = GNUNET_malloc (sizeof (struct Peer));
1273 peer->id = ntohl (msg->peer_id);
1274 LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
1275 peer->peer = GNUNET_TESTING_peer_configure (master_context->system, peer->cfg,
1279 if (NULL == peer->peer)
1281 LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
1285 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1288 peer_list_add (peer);
1289 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1290 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1291 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
1292 reply->peer_id = msg->peer_id;
1293 reply->operation_id = msg->operation_id;
1294 queue_message (client, &reply->header);
1295 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1299 /* FIXME: Forward the peer to other host */
1301 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1306 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1309 * @param client identification of the client
1310 * @param message the actual message
1313 handle_peer_destroy (void *cls,
1314 struct GNUNET_SERVER_Client *client,
1315 const struct GNUNET_MessageHeader *message)
1317 const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
1318 struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *reply;
1321 uint16_t reply_size;
1323 msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
1324 peer_id = ntohl (msg->peer_id);
1325 LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
1326 peer_id, GNUNET_ntohll (msg->operation_id));
1327 if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
1330 /* FIXME: Reply with failure event message or forward to slave controller */
1331 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1334 GNUNET_TESTING_peer_destroy (peer_list[peer_id]->peer);
1335 GNUNET_CONFIGURATION_destroy (peer_list[peer_id]->cfg);
1336 GNUNET_free (peer_list[peer_id]);
1337 peer_list[peer_id] = NULL;
1338 for (id = 0; id < LIST_GROW_STEP; id++)
1340 if (((peer_id + id >= peer_list_size) ||
1341 (NULL != peer_list[peer_id])))
1344 if (LIST_GROW_STEP == id)
1346 peer_list_size -= LIST_GROW_STEP;
1347 peer_list = GNUNET_realloc (peer_list, peer_list_size);
1350 sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1351 reply = GNUNET_malloc (reply_size);
1352 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1353 reply->header.size = htons (reply_size);
1354 reply->operation_id = msg->operation_id;
1355 reply->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1356 queue_message (client, &reply->header);
1357 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1362 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1365 * @param client identification of the client
1366 * @param message the actual message
1369 handle_peer_start (void *cls,
1370 struct GNUNET_SERVER_Client *client,
1371 const struct GNUNET_MessageHeader *message)
1373 const struct GNUNET_TESTBED_PeerStartMessage *msg;
1374 struct GNUNET_TESTBED_PeerEventMessage *reply;
1377 msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
1378 peer_id = ntohl (msg->peer_id);
1379 if ((peer_id >= peer_list_size)
1380 || (NULL == peer_list[peer_id]))
1383 /* FIXME: reply with failure message or forward to slave controller */
1384 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1387 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer_list[peer_id]->peer))
1389 /* FIXME: return FAILURE message */
1391 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1394 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1395 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1396 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1397 reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
1398 reply->host_id = htonl (master_context->host_id);
1399 reply->peer_id = msg->peer_id;
1400 reply->operation_id = msg->operation_id;
1401 queue_message (client, &reply->header);
1402 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1407 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1410 * @param client identification of the client
1411 * @param message the actual message
1414 handle_peer_stop (void *cls,
1415 struct GNUNET_SERVER_Client *client,
1416 const struct GNUNET_MessageHeader *message)
1418 const struct GNUNET_TESTBED_PeerStopMessage *msg;
1419 struct GNUNET_TESTBED_PeerEventMessage *reply;
1422 msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
1423 peer_id = ntohl (msg->peer_id);
1424 if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1426 GNUNET_break (0); /* FIXME: route to slave? */
1427 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1430 if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer_list[peer_id]->peer))
1432 /* FIXME: return FAILURE message */
1434 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1437 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1438 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1439 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1440 reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
1441 reply->host_id = htonl (master_context->host_id);
1442 reply->peer_id = msg->peer_id;
1443 reply->operation_id = msg->operation_id;
1444 queue_message (client, &reply->header);
1445 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1450 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
1453 * @param client identification of the client
1454 * @param message the actual message
1457 handle_peer_get_config (void *cls,
1458 struct GNUNET_SERVER_Client *client,
1459 const struct GNUNET_MessageHeader *message)
1461 const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
1462 struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
1470 msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
1471 peer_id = ntohl (msg->peer_id);
1472 if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1474 /* FIXME: return FAILURE message */
1476 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1478 config = GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->cfg,
1480 xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
1481 GNUNET_free (config);
1482 msize = xc_size + sizeof (struct
1483 GNUNET_TESTBED_PeerConfigurationInformationMessage);
1484 reply = GNUNET_realloc (xconfig, msize);
1485 (void) memmove (&reply[1], reply, xc_size);
1486 reply->header.size = htons (msize);
1487 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
1488 reply->peer_id = msg->peer_id;
1489 reply->operation_id = msg->operation_id;
1490 GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->peer,
1491 &reply->peer_identity);
1492 reply->config_size = htons ((uint16_t) c_size);
1493 queue_message (client, &reply->header);
1494 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1500 * Function called whenever there is an update to the
1501 * HELLO of this peer.
1503 * @param cls closure
1504 * @param hello our updated HELLO
1507 hello_update_cb (void *cls,
1508 const struct GNUNET_MessageHeader *hello)
1515 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1518 * @param client identification of the client
1519 * @param message the actual message
1522 handle_overlay_connect (void *cls,
1523 struct GNUNET_SERVER_Client *client,
1524 const struct GNUNET_MessageHeader *message)
1526 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1527 struct OverlayConnectContext *occ;
1531 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1532 p1 = ntohl (msg->peer1);
1533 p2 = ntohl (msg->peer2);
1534 GNUNET_assert (p1 < peer_list_size);
1535 GNUNET_assert (NULL != peer_list[p1]);
1536 GNUNET_assert (p2 < peer_list_size);
1537 GNUNET_assert (NULL != peer_list[p2]);
1538 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1539 occ->peer1 = peer_list[p1];
1540 occ->peer2 = peer_list[p2];
1541 occ->peer1_transport = GNUNET_TRANSPORT_connect (occ->peer1->cfg, NULL, occ,
1543 occ->peer2_transport = GNUNET_TRANSPORT_connect (occ->peer2->cfg, NULL, occ,
1545 occ->peer1_ghh = GNUNET_TRANSPORT_get_hello (occ->peer1_transport, &hello_update_cb, occ);
1546 occ->peer2_ghh = GNUNET_TRANSPORT_get_hello (occ->peer2_transport, &hello_update_cb, occ);
1551 * Iterator over hash map entries.
1553 * @param cls closure
1554 * @param key current key code
1555 * @param value value in the hash map
1556 * @return GNUNET_YES if we should continue to
1561 ss_map_free_iterator (void *cls,
1562 const struct GNUNET_HashCode * key, void *value)
1564 struct SharedService *ss = value;
1566 GNUNET_assert (GNUNET_YES ==
1567 GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
1568 GNUNET_free (ss->name);
1575 * Task to clean up and shutdown nicely
1578 * @param tc the TaskContext from scheduler
1581 shutdown_task (void *cls,
1582 const struct GNUNET_SCHEDULER_TaskContext *tc)
1584 struct LCFContextQueue *lcfq;
1587 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
1588 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
1589 (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
1591 GNUNET_CONTAINER_multihashmap_destroy (ss_map);
1592 if (NULL != lcfq_head)
1594 if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
1596 GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
1597 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1599 if (NULL != lcfq_head->lcf->rhandle)
1600 GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
1602 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1603 for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
1605 GNUNET_free (lcfq->lcf->sxcfg);
1606 GNUNET_free (lcfq->lcf);
1607 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1610 /* Clear peer list */
1611 for (id = 0; id < peer_list_size; id++)
1612 if (NULL != peer_list[id])
1614 GNUNET_TESTING_peer_destroy (peer_list[id]->peer);
1615 GNUNET_CONFIGURATION_destroy (peer_list[id]->cfg);
1616 GNUNET_free (peer_list[id]);
1618 GNUNET_free_non_null (peer_list);
1619 /* Clear host list */
1620 for (id = 0; id < host_list_size; id++)
1621 if (NULL != host_list[id])
1622 GNUNET_TESTBED_host_destroy (host_list[id]);
1623 GNUNET_free_non_null (host_list);
1624 /* Clear route list */
1625 for (id = 0; id < route_list_size; id++)
1626 if (NULL != route_list[id])
1627 GNUNET_free (route_list[id]);
1628 GNUNET_free_non_null (route_list);
1629 /* Clear slave_list */
1630 for (id = 0; id < slave_list_size; id++)
1631 if (NULL != slave_list[id])
1633 GNUNET_assert (NULL != slave_list[id]->controller);
1634 GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
1635 if (NULL != slave_list[id]->controller_proc)
1636 GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
1638 if (NULL != master_context)
1640 GNUNET_free_non_null (master_context->master_ip);
1641 if (NULL != master_context->system)
1642 GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
1643 GNUNET_free (master_context);
1644 master_context = NULL;
1650 * Callback for client disconnect
1653 * @param client the client which has disconnected
1656 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
1658 if (NULL == master_context)
1660 if (client == master_context->client)
1662 LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
1663 GNUNET_SERVER_client_drop (client);
1664 /* should not be needed as we're terminated by failure to read
1665 from stdin, but if stdin fails for some reason, this shouldn't
1666 hurt for now --- might need to revise this later if we ever
1667 decide that master connections might be temporarily down
1669 //GNUNET_SCHEDULER_shutdown ();
1677 * @param cls closure
1678 * @param server the initialized server
1679 * @param cfg configuration to use
1682 testbed_run (void *cls,
1683 struct GNUNET_SERVER_Handle *server,
1684 const struct GNUNET_CONFIGURATION_Handle *cfg)
1686 static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
1688 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT,
1689 sizeof (struct GNUNET_TESTBED_InitMessage)},
1690 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
1691 {&handle_configure_shared_service, NULL,
1692 GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
1693 {&handle_link_controllers, NULL,
1694 GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
1695 {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
1696 {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
1697 sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
1698 {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
1699 sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
1700 {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
1701 sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
1702 {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
1703 sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
1704 {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
1705 sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
1709 GNUNET_SERVER_add_handlers (server,
1711 GNUNET_SERVER_disconnect_notify (server,
1712 &client_disconnect_cb,
1714 ss_map = GNUNET_CONTAINER_multihashmap_create (5);
1716 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1719 LOG_DEBUG ("Testbed startup complete\n");
1724 * The starting point of execution
1726 int main (int argc, char *const *argv)
1730 GNUNET_SERVICE_run (argc,
1733 GNUNET_SERVICE_OPTION_NONE,