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"
31 #include "gnunet_core_service.h"
32 #include "gnunet_hello_lib.h"
35 #include "gnunet_testbed_service.h"
37 #include "testbed_api.h"
38 #include "testbed_api_hosts.h"
39 #include "gnunet_testing_lib-new.h"
44 #define LOG(kind,...) \
45 GNUNET_log (kind, __VA_ARGS__)
50 #define LOG_DEBUG(...) \
51 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
54 * By how much should the arrays lists grow
56 #define LIST_GROW_STEP 10
59 * Default timeout for operations which may take some time
61 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
64 * The main context information associated with the client which started us
69 * The client handle associated with this context
71 struct GNUNET_SERVER_Client *client;
74 * The network address of the master controller
79 * The TESTING system handle for starting peers locally
81 struct GNUNET_TESTING_System *system;
84 * Our host id according to this context
91 * The message queue for sending messages to clients
96 * The message to be sent
98 struct GNUNET_MessageHeader *msg;
101 * The client to send the message to
103 struct GNUNET_SERVER_Client *client;
106 * next pointer for DLL
108 struct MessageQueue *next;
111 * prev pointer for DLL
113 struct MessageQueue *prev;
118 * The structure for identifying a shared service
123 * The name of the shared service
128 * Number of shared peers per instance of the shared service
133 * Number of peers currently sharing the service
135 uint32_t num_sharing;
150 * The destination host is reachable thru
157 * Context information used while linking controllers
159 struct LinkControllersContext;
163 * A DLL of host registrations to be made
165 struct HostRegistration
168 * next registration in the DLL
170 struct HostRegistration *next;
173 * previous registration in the DLL
175 struct HostRegistration *prev;
178 * The callback to call after this registration's status is available
180 GNUNET_TESTBED_HostRegistrationCompletion cb;
183 * The closure for the above callback
188 * The host that has to be registered
190 struct GNUNET_TESTBED_Host *host;
195 * Structure representing a connected(directly-linked) controller
200 * The controller process handle if we had started the controller
202 struct GNUNET_TESTBED_ControllerProc *controller_proc;
205 * The controller handle
207 struct GNUNET_TESTBED_Controller *controller;
210 * The configuration of the slave. Cannot be NULL
212 struct GNUNET_CONFIGURATION_Handle *cfg;
215 * handle to lcc which is associated with this slave startup. Should be set to
216 * NULL when the slave has successfully started up
218 struct LinkControllersContext *lcc;
221 * Head of the host registration DLL
223 struct HostRegistration *hr_dll_head;
226 * Tail of the host registration DLL
228 struct HostRegistration *hr_dll_tail;
231 * The current host registration handle
233 struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
236 * The id of the host this controller is running on
244 * States of LCFContext
249 * The Context has been initialized; Nothing has been done on it
254 * Delegated host has been registered at the forwarding controller
256 DELEGATED_HOST_REGISTERED,
259 * The slave host has been registred at the forwarding controller
261 SLAVE_HOST_REGISTERED,
264 * The context has been finished (may have error)
271 * Link controllers request forwarding context
276 * The gateway which will pass the link message to delegated host
278 struct Slave *gateway;
281 * The controller link message that has to be forwarded to
283 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
286 * The client which has asked to perform this operation
288 struct GNUNET_SERVER_Client *client;
291 * The id of the operation which created this context
293 uint64_t operation_id;
296 * The state of this context
298 enum LCFContextState state;
303 uint32_t delegated_host_id;
308 uint32_t slave_host_id;
314 * Structure of a queue entry in LCFContext request queue
316 struct LCFContextQueue
321 struct LCFContext *lcf;
326 struct LCFContextQueue *next;
331 struct LCFContextQueue *prev;
345 * The peer handle from testing API
347 struct GNUNET_TESTING_Peer *peer;
350 * The modified (by GNUNET_TESTING_peer_configure) configuration this
351 * peer is configured with
353 struct GNUNET_CONFIGURATION_Handle *cfg;
356 * Is the peer running
365 * The slave this peer is started through
370 * The id of the remote host this peer is running on
372 uint32_t remote_host_id;
379 * Is this peer locally created?
384 * Our local reference id for this peer
392 * Context information for connecting 2 peers in overlay
394 struct OverlayConnectContext
397 * The client which has requested for overlay connection
399 struct GNUNET_SERVER_Client *client;
402 * the peer which has to connect to the other peer
407 * Transport handle of the first peer to get its HELLO
409 struct GNUNET_TRANSPORT_Handle *p1th;
412 * Transport handle of other peer to offer first peer's HELLO
414 struct GNUNET_TRANSPORT_Handle *p2th;
417 * Core handles of the first peer; used to notify when second peer connects to it
419 struct GNUNET_CORE_Handle *ch;
422 * HELLO of the other peer
424 struct GNUNET_MessageHeader *hello;
427 * Get hello handle to acquire HELLO of first peer
429 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
432 * The error message we send if this overlay connect operation has timed out
437 * Operation context for suboperations
439 struct OperationContext *opc;
442 * Controller of peer 2; NULL if the peer is local
444 struct GNUNET_TESTBED_Controller *peer2_controller;
447 * The peer identity of the first peer
449 struct GNUNET_PeerIdentity peer_identity;
452 * The peer identity of the other peer
454 struct GNUNET_PeerIdentity other_peer_identity;
457 * The id of the operation responsible for creating this context
462 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
465 GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
468 * The id of the overlay connect timeout task
470 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
480 uint32_t other_peer_id;
483 * Number of times we tried to send hello; used to increase delay in offering
491 * Context information for RequestOverlayConnect
492 * operations. RequestOverlayConnect is used when peers A, B reside on different
493 * hosts and the host controller for peer B is asked by the host controller of
494 * peer A to make peer B connect to peer A
496 struct RequestOverlayConnectContext
499 * The transport handle of peer B
501 struct GNUNET_TRANSPORT_Handle *th;
506 struct GNUNET_MessageHeader *hello;
509 * The peer identity of peer A
511 struct GNUNET_PeerIdentity a_id;
514 * Task for offering HELLO of A to B and doing try_connect
516 GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
519 * Task to timeout RequestOverlayConnect
521 GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
524 * Number of times we tried to send hello; used to increase delay in offering
533 * Context information for operations forwarded to subcontrollers
535 struct ForwardedOperationContext
538 * The generated operation context
540 struct OperationContext *opc;
543 * The client to which we have to reply
545 struct GNUNET_SERVER_Client *client;
553 * Task ID for the timeout task
555 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
558 * The id of the operation that has been forwarded
560 uint64_t operation_id;
566 * Context information used while linking controllers
568 struct LinkControllersContext
571 * The client which initiated the link controller operation
573 struct GNUNET_SERVER_Client *client;
576 * The ID of the operation
578 uint64_t operation_id;
584 * Context information to used during operations which forward the overlay
587 struct ForwardedOverlayConnectContext
590 * The gateway to which this operation is forwarded to
592 struct Slave *gateway;
595 * The gateway through which peer2's controller can be reached
597 struct Slave *gateway2;
600 * Handle for sub-operations
602 struct GNUNET_TESTBED_Operation *sub_op;
605 * The client which initiated the link controller operation
607 struct GNUNET_SERVER_Client *client;
610 * A copy of the original overlay connect message
612 struct GNUNET_MessageHeader *orig_msg;
615 * The id of the operation which created this context information
617 uint64_t operation_id;
620 * Id of the timeout task;
622 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
625 * Enumeration of states for this context
635 * State where we attempt to register peer2's controller with peer1's controller
640 * State where we attempt to get peer2's controller configuration
645 * State where we attempt to link the controller of peer 1 to the controller
651 * State where we attempt to do the overlay connection again
668 * Id of the host where peer2 is running
670 uint32_t peer2_host_id;
676 * The master context; generated with the first INIT message
678 static struct Context *master_context;
681 * Our hostname; we give this to all the peers we start
683 static char *hostname;
693 static struct GNUNET_CONFIGURATION_Handle *our_config;
696 * Current Transmit Handle; NULL if no notify transmit exists currently
698 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
705 * The head for the LCF queue
707 static struct LCFContextQueue *lcfq_head;
710 * The tail for the LCF queue
712 static struct LCFContextQueue *lcfq_tail;
715 * The message queue head
717 static struct MessageQueue *mq_head;
720 * The message queue tail
722 static struct MessageQueue *mq_tail;
727 static struct GNUNET_TESTBED_Host **host_list;
732 static struct Route **route_list;
735 * A list of directly linked neighbours
737 static struct Slave **slave_list;
740 * A list of peers we know about
742 static struct Peer **peer_list;
745 * The hashmap of shared services
747 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
750 * The event mask for the events we listen from sub-controllers
752 static uint64_t event_mask;
755 * The size of the host list
757 static uint32_t host_list_size;
760 * The size of the route list
762 static uint32_t route_list_size;
765 * The size of directly linked neighbours list
767 static uint32_t slave_list_size;
770 * The size of the peer list
772 static uint32_t peer_list_size;
779 * The lcf_task handle
781 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
784 * The shutdown task handle
786 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
790 * Function called to notify a client about the connection begin ready to queue
791 * more data. "buf" will be NULL and "size" zero if the connection was closed
792 * for writing in the meantime.
795 * @param size number of bytes available in buf
796 * @param buf where the callee should write the message
797 * @return number of bytes written to buf
800 transmit_ready_notify (void *cls, size_t size, void *buf)
802 struct MessageQueue *mq_entry;
804 transmit_handle = NULL;
806 GNUNET_assert (NULL != mq_entry);
809 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
810 size = ntohs (mq_entry->msg->size);
811 memcpy (buf, mq_entry->msg, size);
812 GNUNET_free (mq_entry->msg);
813 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
814 GNUNET_free (mq_entry);
816 if (NULL != mq_entry)
818 GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
819 ntohs (mq_entry->msg->size),
820 GNUNET_TIME_UNIT_FOREVER_REL,
821 &transmit_ready_notify, NULL);
827 * Queues a message in send queue for sending to the service
829 * @param client the client to whom the queued message has to be sent
830 * @param msg the message to queue
833 queue_message (struct GNUNET_SERVER_Client *client,
834 struct GNUNET_MessageHeader *msg)
836 struct MessageQueue *mq_entry;
840 type = ntohs (msg->type);
841 size = ntohs (msg->size);
842 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
843 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
844 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
846 mq_entry->client = client;
847 LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type,
849 GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
850 if (NULL == transmit_handle)
852 GNUNET_SERVER_notify_transmit_ready (client, size,
853 GNUNET_TIME_UNIT_FOREVER_REL,
854 &transmit_ready_notify, NULL);
859 * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
861 * @param ptr the memory block to realloc
862 * @param size the size of ptr
863 * @param new_size the size to which ptr has to be realloc'ed
864 * @return the newly reallocated memory block
867 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
869 ptr = GNUNET_realloc (ptr, new_size);
871 (void) memset (ptr + size, 0, new_size - size);
877 * Function to add a host to the current list of known hosts
879 * @param host the host to add
880 * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
884 host_list_add (struct GNUNET_TESTBED_Host *host)
889 host_id = GNUNET_TESTBED_host_get_id_ (host);
890 orig_size = host_list_size;
891 if (host_list_size <= host_id)
893 while (host_list_size <= host_id)
894 host_list_size += LIST_GROW_STEP;
896 TESTBED_realloc (host_list,
897 sizeof (struct GNUNET_TESTBED_Host *) * orig_size,
898 sizeof (struct GNUNET_TESTBED_Host *)
901 if (NULL != host_list[host_id])
903 LOG_DEBUG ("A host with id: %u already exists\n", host_id);
904 return GNUNET_SYSERR;
906 host_list[host_id] = host;
912 * Adds a route to the route list
914 * @param route the route to add
917 route_list_add (struct Route *route)
921 orig_size = route_list_size;
922 if (route->dest >= route_list_size)
924 while (route->dest >= route_list_size)
925 route_list_size += LIST_GROW_STEP;
927 TESTBED_realloc (route_list,
928 sizeof (struct Route *) * orig_size,
929 sizeof (struct Route *) * route_list_size);
931 GNUNET_assert (NULL == route_list[route->dest]);
932 route_list[route->dest] = route;
937 * Adds a slave to the slave array
939 * @param slave the slave controller to add
942 slave_list_add (struct Slave *slave)
944 if (slave->host_id >= slave_list_size)
947 TESTBED_realloc (slave_list, sizeof (struct Slave *) * slave_list_size,
948 sizeof (struct Slave *) * (slave_list_size +
950 slave_list_size += LIST_GROW_STEP;
952 GNUNET_assert (NULL == slave_list[slave->host_id]);
953 slave_list[slave->host_id] = slave;
958 * Adds a peer to the peer array
960 * @param peer the peer to add
963 peer_list_add (struct Peer *peer)
967 orig_size = peer_list_size;
968 if (peer->id >= peer_list_size)
970 while (peer->id >= peer_list_size)
971 peer_list_size += LIST_GROW_STEP;
973 TESTBED_realloc (peer_list, sizeof (struct Peer *) * orig_size,
974 sizeof (struct Peer *) * peer_list_size);
976 GNUNET_assert (NULL == peer_list[peer->id]);
977 peer_list[peer->id] = peer;
982 * Removes a the give peer from the peer array
984 * @param peer the peer to be removed
987 peer_list_remove (struct Peer *peer)
992 peer_list[peer->id] = NULL;
993 orig_size = peer_list_size;
994 while (peer_list_size >= LIST_GROW_STEP)
996 for (id = peer_list_size - 1;
997 (id >= peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); id--)
998 if (NULL != peer_list[id])
1000 if (id != ((peer_list_size - LIST_GROW_STEP) - 1))
1002 peer_list_size -= LIST_GROW_STEP;
1004 if (orig_size == peer_list_size)
1007 GNUNET_realloc (peer_list, sizeof (struct Peer *) * peer_list_size);
1012 * Finds the route with directly connected host as destination through which
1013 * the destination host can be reached
1015 * @param host_id the id of the destination host
1016 * @return the route with directly connected destination host; NULL if no route
1019 static struct Route *
1020 find_dest_route (uint32_t host_id)
1022 struct Route *route;
1024 if (route_list_size <= host_id)
1026 while (NULL != (route = route_list[host_id]))
1028 if (route->thru == master_context->host_id)
1030 host_id = route->thru;
1037 * Routes message to a host given its host_id
1039 * @param host_id the id of the destination host
1040 * @param msg the message to be routed
1043 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
1050 * Send operation failure message to client
1052 * @param client the client to which the failure message has to be sent to
1053 * @param operation_id the id of the failed operation
1054 * @param emsg the error message; can be NULL
1057 send_operation_fail_msg (struct GNUNET_SERVER_Client *client,
1058 uint64_t operation_id, const char *emsg)
1060 struct GNUNET_TESTBED_OperationFailureEventMessage *msg;
1064 msize = sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
1065 emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1;
1067 msg = GNUNET_malloc (msize);
1068 msg->header.size = htons (msize);
1069 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT);
1070 msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1071 msg->operation_id = GNUNET_htonll (operation_id);
1073 memcpy (&msg[1], emsg, emsg_len);
1074 queue_message (client, &msg->header);
1079 * Function to send generic operation success message to given client
1081 * @param client the client to send the message to
1082 * @param operation_id the id of the operation which was successful
1085 send_operation_success_msg (struct GNUNET_SERVER_Client *client,
1086 uint64_t operation_id)
1088 struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg;
1091 msize = sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1092 msg = GNUNET_malloc (msize);
1093 msg->header.size = htons (msize);
1094 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1095 msg->operation_id = GNUNET_htonll (operation_id);
1096 msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1097 queue_message (client, &msg->header);
1102 * Callback which will be called to after a host registration succeeded or failed
1104 * @param cls the handle to the slave at which the registration is completed
1105 * @param emsg the error message; NULL if host registration is successful
1108 hr_completion (void *cls, const char *emsg);
1112 * Attempts to register the next host in the host registration queue
1114 * @param slave the slave controller whose host registration queue is checked
1115 * for host registrations
1118 register_next_host (struct Slave *slave)
1120 struct HostRegistration *hr;
1122 hr = slave->hr_dll_head;
1123 GNUNET_assert (NULL != hr);
1124 GNUNET_assert (NULL == slave->rhandle);
1125 slave->rhandle = GNUNET_TESTBED_register_host (slave->controller,
1133 * Callback which will be called to after a host registration succeeded or failed
1135 * @param cls the handle to the slave at which the registration is completed
1136 * @param emsg the error message; NULL if host registration is successful
1139 hr_completion (void *cls, const char *emsg)
1141 struct Slave *slave = cls;
1142 struct HostRegistration *hr;
1144 slave->rhandle = NULL;
1145 hr = slave->hr_dll_head;
1146 GNUNET_assert (NULL != hr);
1147 GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head,
1151 hr->cb (hr->cb_cls, emsg);
1153 if ((NULL == slave->rhandle) && (NULL != slave->hr_dll_head))
1154 register_next_host (slave);
1159 * Adds a host registration's request to a slave's registration queue
1161 * @param slave the slave controller at which the given host has to be
1163 * @param cb the host registration completion callback
1164 * @param cb_cls the closure for the host registration completion callback
1165 * @param host the host which has to be registered
1168 queue_host_registration (struct Slave *slave,
1169 GNUNET_TESTBED_HostRegistrationCompletion cb,
1171 struct GNUNET_TESTBED_Host *host)
1173 struct HostRegistration *hr;
1176 hr = GNUNET_malloc (sizeof (struct HostRegistration));
1178 hr->cb_cls = cb_cls;
1180 call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO;
1181 GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head,
1184 if (GNUNET_YES == call_register)
1185 register_next_host (slave);
1190 * The Link Controller forwarding task
1192 * @param cls the LCFContext
1193 * @param tc the Task context from scheduler
1196 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1200 * Completion callback for host registrations while forwarding Link Controller messages
1202 * @param cls the LCFContext
1203 * @param emsg the error message; NULL if host registration is successful
1206 lcf_proc_cc (void *cls, const char *emsg)
1208 struct LCFContext *lcf = cls;
1210 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1215 goto registration_error;
1216 lcf->state = DELEGATED_HOST_REGISTERED;
1217 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1219 case DELEGATED_HOST_REGISTERED:
1221 goto registration_error;
1222 lcf->state = SLAVE_HOST_REGISTERED;
1223 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1226 GNUNET_assert (0); /* Shouldn't reach here */
1231 LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n",
1233 lcf->state = FINISHED;
1234 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1239 * Callback to be called when forwarded link controllers operation is
1240 * successfull. We have to relay the reply msg back to the client
1242 * @param cls ForwardedOperationContext
1243 * @param msg the peer create success message
1246 forwarded_operation_reply_relay (void *cls,
1247 const struct GNUNET_MessageHeader *msg)
1249 struct ForwardedOperationContext *fopc = cls;
1250 struct GNUNET_MessageHeader *dup_msg;
1253 msize = ntohs (msg->size);
1254 LOG_DEBUG ("Relaying message with type: %u, size: %u\n", ntohs (msg->type),
1256 dup_msg = GNUNET_malloc (msize);
1257 (void) memcpy (dup_msg, msg, msize);
1258 queue_message (fopc->client, dup_msg);
1259 GNUNET_SERVER_client_drop (fopc->client);
1260 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
1266 * Task to free resources when forwarded link controllers has been timedout
1268 * @param cls the ForwardedOperationContext
1269 * @param tc the task context from scheduler
1272 forwarded_operation_timeout (void *cls,
1273 const struct GNUNET_SCHEDULER_TaskContext *tc)
1275 struct ForwardedOperationContext *fopc = cls;
1277 GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
1278 LOG (GNUNET_ERROR_TYPE_WARNING, "A forwarded operation has timed out\n");
1279 send_operation_fail_msg (fopc->client, fopc->operation_id, "Timeout");
1280 GNUNET_SERVER_client_drop (fopc->client);
1286 * The Link Controller forwarding task
1288 * @param cls the LCFContext
1289 * @param tc the Task context from scheduler
1292 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1294 struct LCFContext *lcf = cls;
1295 struct LCFContextQueue *lcfq;
1296 struct ForwardedOperationContext *fopc;
1298 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1303 GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
1304 lcf->gateway->controller))
1306 queue_host_registration (lcf->gateway,
1308 host_list[lcf->delegated_host_id]);
1312 lcf->state = DELEGATED_HOST_REGISTERED;
1313 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1316 case DELEGATED_HOST_REGISTERED:
1318 GNUNET_TESTBED_is_host_registered_ (host_list[lcf->slave_host_id],
1319 lcf->gateway->controller))
1321 queue_host_registration (lcf->gateway,
1323 host_list[lcf->slave_host_id]);
1327 lcf->state = SLAVE_HOST_REGISTERED;
1328 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1331 case SLAVE_HOST_REGISTERED:
1332 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1333 fopc->client = lcf->client;
1334 fopc->operation_id = lcf->operation_id;
1336 GNUNET_TESTBED_forward_operation_msg_ (lcf->gateway->controller,
1339 &forwarded_operation_reply_relay,
1341 fopc->timeout_task =
1342 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
1344 lcf->state = FINISHED;
1345 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1349 GNUNET_assert (lcfq->lcf == lcf);
1350 GNUNET_free (lcf->msg);
1352 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1354 if (NULL != lcfq_head)
1356 GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
1362 * Callback to be called when forwarded overlay connection operation has a reply
1363 * from the sub-controller successfull. We have to relay the reply msg back to
1366 * @param cls ForwardedOperationContext
1367 * @param msg the peer create success message
1370 forwarded_overlay_connect_listener (void *cls,
1371 const struct GNUNET_MessageHeader *msg);
1375 * Cleans up ForwardedOverlayConnectContext
1377 * @param focc the ForwardedOverlayConnectContext to cleanup
1380 cleanup_focc (struct ForwardedOverlayConnectContext *focc)
1382 if (GNUNET_SCHEDULER_NO_TASK != focc->timeout_task)
1383 GNUNET_SCHEDULER_cancel (focc->timeout_task);
1384 if (NULL != focc->sub_op)
1385 GNUNET_TESTBED_operation_done (focc->sub_op);
1386 if (NULL != focc->client)
1387 GNUNET_SERVER_client_drop (focc->client);
1388 GNUNET_free_non_null (focc->orig_msg);
1393 * Callback for event from slave controllers
1395 * @param cls struct Slave *
1396 * @param event information about the event
1399 slave_event_callback (void *cls,
1400 const struct GNUNET_TESTBED_EventInformation *event)
1402 struct ForwardedOverlayConnectContext *focc;
1403 struct ForwardedOperationContext *fopc;
1404 struct GNUNET_CONFIGURATION_Handle *slave_cfg;
1405 struct GNUNET_TESTBED_Operation *old_op;
1408 /* We currently only get here when doing overlay connect operations and that
1409 too while trying out sub operations */
1410 GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
1411 focc = event->details.operation_finished.op_cls;
1412 LOG_DEBUG ("Operation successful\n");
1413 if (NULL != event->details.operation_finished.emsg)
1415 GNUNET_asprintf (&emsg, "Failure executing suboperation: %s",
1416 event->details.operation_finished.emsg);
1417 send_operation_fail_msg (focc->client, focc->operation_id,
1420 cleanup_focc (focc);
1423 switch (focc->state)
1426 slave_cfg = event->details.operation_finished.generic;
1427 old_op = focc->sub_op;
1428 focc->state = FOCC_LINK;
1429 focc->sub_op = GNUNET_TESTBED_controller_link_ (focc,
1430 focc->gateway->controller,
1431 focc->peer2_host_id,
1432 peer_list[focc->peer1]->details.remote.remote_host_id,
1435 GNUNET_TESTBED_operation_done (old_op);
1438 LOG_DEBUG ("OL: Linking controllers successfull\n");
1439 GNUNET_TESTBED_operation_done (focc->sub_op);
1440 focc->sub_op = NULL;
1441 focc->state = FOCC_OL_CONNECT;
1442 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1443 fopc->client = focc->client;
1444 focc->client = NULL;
1445 fopc->operation_id = focc->operation_id;
1448 GNUNET_TESTBED_forward_operation_msg_ (focc->gateway->controller,
1449 focc->operation_id, focc->orig_msg,
1450 &forwarded_operation_reply_relay,
1452 GNUNET_free (focc->orig_msg);
1453 focc->orig_msg = NULL;
1454 fopc->timeout_task =
1455 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
1457 cleanup_focc (focc);
1467 * Callback to signal successfull startup of the controller process
1469 * @param cls the handle to the slave whose status is to be found here
1470 * @param cfg the configuration with which the controller has been started;
1471 * NULL if status is not GNUNET_OK
1472 * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
1473 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
1476 slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
1479 struct Slave *slave = cls;
1480 struct LinkControllersContext *lcc;
1483 if (GNUNET_SYSERR == status)
1485 slave->controller_proc = NULL;
1486 slave_list[slave->host_id] = NULL;
1487 if (NULL != slave->cfg)
1488 GNUNET_CONFIGURATION_destroy (slave->cfg);
1489 GNUNET_free (slave);
1491 LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
1492 GNUNET_SCHEDULER_shutdown (); /* We too shutdown */
1496 GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1498 &slave_event_callback, slave);
1499 if (NULL != slave->controller)
1501 send_operation_success_msg (lcc->client, lcc->operation_id);
1502 slave->cfg = GNUNET_CONFIGURATION_dup (cfg);
1506 send_operation_fail_msg (lcc->client, lcc->operation_id,
1507 "Could not connect to delegated controller");
1508 GNUNET_TESTBED_controller_stop (slave->controller_proc);
1509 slave_list[slave->host_id] = NULL;
1510 GNUNET_free (slave);
1517 if (NULL != lcc->client)
1519 GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK);
1520 GNUNET_SERVER_client_drop (lcc->client);
1531 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
1534 * @param client identification of the client
1535 * @param message the actual message
1538 handle_init (void *cls, struct GNUNET_SERVER_Client *client,
1539 const struct GNUNET_MessageHeader *message)
1541 const struct GNUNET_TESTBED_InitMessage *msg;
1542 struct GNUNET_TESTBED_Host *host;
1543 const char *controller_hostname;
1546 if (NULL != master_context)
1548 LOG_DEBUG ("We are being connected to laterally\n");
1549 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1552 msg = (const struct GNUNET_TESTBED_InitMessage *) message;
1553 msize = ntohs (message->size);
1554 if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage))
1557 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1560 msize -= sizeof (struct GNUNET_TESTBED_InitMessage);
1561 controller_hostname = (const char *) &msg[1];
1562 if ('\0' != controller_hostname[msize - 1])
1565 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1568 master_context = GNUNET_malloc (sizeof (struct Context));
1569 master_context->client = client;
1570 master_context->host_id = ntohl (msg->host_id);
1571 master_context->master_ip = GNUNET_strdup (controller_hostname);
1572 LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
1573 master_context->system =
1574 GNUNET_TESTING_system_create ("testbed", master_context->master_ip, hostname);
1576 GNUNET_TESTBED_host_create_with_id (master_context->host_id,
1577 master_context->master_ip,
1580 host_list_add (host);
1581 GNUNET_SERVER_client_keep (client);
1582 LOG_DEBUG ("Created master context with host ID: %u\n",
1583 master_context->host_id);
1584 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1589 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1592 * @param client identification of the client
1593 * @param message the actual message
1596 handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
1597 const struct GNUNET_MessageHeader *message)
1599 struct GNUNET_TESTBED_Host *host;
1600 const struct GNUNET_TESTBED_AddHostMessage *msg;
1601 struct GNUNET_TESTBED_HostConfirmedMessage *reply;
1606 uint16_t username_length;
1607 uint16_t hostname_length;
1608 uint16_t reply_size;
1611 msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
1612 msize = ntohs (msg->header.size);
1613 username = (char *) &msg[1];
1614 username_length = ntohs (msg->user_name_length);
1615 if (0 != username_length)
1617 /* msg must contain hostname */
1618 GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1619 username_length + 1));
1620 if (0 != username_length)
1621 GNUNET_assert ('\0' == username[username_length - 1]);
1622 hostname = username + username_length;
1624 msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
1625 GNUNET_assert ('\0' == hostname[hostname_length - 1]);
1626 GNUNET_assert (strlen (hostname) == hostname_length - 1);
1627 host_id = ntohl (msg->host_id);
1628 LOG_DEBUG ("Received ADDHOST %u message\n", host_id);
1629 LOG_DEBUG ("-------host id: %u\n", host_id);
1630 LOG_DEBUG ("-------hostname: %s\n", hostname);
1631 if (0 != username_length)
1632 LOG_DEBUG ("-------username: %s\n", username);
1635 LOG_DEBUG ("-------username: NULL\n");
1638 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
1640 GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
1641 ntohs (msg->ssh_port));
1642 GNUNET_assert (NULL != host);
1643 reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
1644 if (GNUNET_OK != host_list_add (host))
1646 /* We are unable to add a host */
1647 emsg = "A host exists with given host-id";
1648 LOG_DEBUG ("%s: %u", emsg, host_id);
1649 GNUNET_TESTBED_host_destroy (host);
1650 reply_size += strlen (emsg) + 1;
1651 reply = GNUNET_malloc (reply_size);
1652 memcpy (&reply[1], emsg, strlen (emsg) + 1);
1656 LOG_DEBUG ("Added host %u at %u\n",
1657 host_id, master_context->host_id);
1658 reply = GNUNET_malloc (reply_size);
1660 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
1661 reply->header.size = htons (reply_size);
1662 reply->host_id = htonl (host_id);
1663 queue_message (client, &reply->header);
1664 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1669 * Iterator over hash map entries.
1671 * @param cls closure
1672 * @param key current key code
1673 * @param value value in the hash map
1674 * @return GNUNET_YES if we should continue to
1679 ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
1681 struct SharedService *queried_ss = cls;
1682 struct SharedService *ss = value;
1684 if (0 == strcmp (ss->name, queried_ss->name))
1692 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1695 * @param client identification of the client
1696 * @param message the actual message
1699 handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
1700 const struct GNUNET_MessageHeader *message)
1702 const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1703 struct SharedService *ss;
1705 struct GNUNET_HashCode hash;
1707 uint16_t service_name_size;
1709 msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1710 msg_size = ntohs (message->size);
1711 if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1714 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1718 msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1719 service_name = (char *) &msg[1];
1720 if ('\0' != service_name[service_name_size - 1])
1723 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1726 LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1727 service_name, ntohl (msg->num_peers));
1728 if (ntohl (msg->host_id) != master_context->host_id)
1730 route_message (ntohl (msg->host_id), message);
1731 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1734 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1735 ss = GNUNET_malloc (sizeof (struct SharedService));
1736 ss->name = strdup (service_name);
1737 ss->num_shared = ntohl (msg->num_peers);
1738 GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1739 if (GNUNET_SYSERR ==
1740 GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1741 &ss_exists_iterator, ss))
1743 LOG (GNUNET_ERROR_TYPE_WARNING,
1744 "Service %s already configured as a shared service. "
1745 "Ignoring service sharing request \n", ss->name);
1746 GNUNET_free (ss->name);
1750 GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1751 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1756 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1759 * @param client identification of the client
1760 * @param message the actual message
1763 handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
1764 const struct GNUNET_MessageHeader *message)
1766 const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1767 struct GNUNET_CONFIGURATION_Handle *cfg;
1768 struct LCFContextQueue *lcfq;
1769 struct Route *route;
1770 struct Route *new_route;
1774 uint32_t delegated_host_id;
1775 uint32_t slave_host_id;
1778 if (NULL == master_context)
1781 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1784 msize = ntohs (message->size);
1785 if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1788 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1791 msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1792 delegated_host_id = ntohl (msg->delegated_host_id);
1793 if (delegated_host_id == master_context->host_id)
1796 LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1797 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1800 if ((delegated_host_id >= host_list_size) ||
1801 (NULL == host_list[delegated_host_id]))
1803 LOG (GNUNET_ERROR_TYPE_WARNING,
1804 "Delegated host %u not registered with us\n", delegated_host_id);
1805 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1808 slave_host_id = ntohl (msg->slave_host_id);
1809 if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1811 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
1813 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1816 if (slave_host_id == delegated_host_id)
1818 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1819 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1823 if (slave_host_id == master_context->host_id) /* Link from us */
1825 struct Slave *slave;
1826 struct LinkControllersContext *lcc;
1828 msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1829 config_size = ntohs (msg->config_size);
1830 if ((delegated_host_id < slave_list_size) && (NULL != slave_list[delegated_host_id])) /* We have already added */
1832 LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1834 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1837 config = GNUNET_malloc (config_size);
1838 dest_size = (uLongf) config_size;
1840 uncompress ((Bytef *) config, &dest_size, (const Bytef *) &msg[1],
1843 GNUNET_break (0); /* Compression error */
1844 GNUNET_free (config);
1845 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1848 if (config_size != dest_size)
1850 LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1851 GNUNET_free (config);
1852 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1855 cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
1857 GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
1859 GNUNET_break (0); /* Configuration parsing error */
1860 GNUNET_free (config);
1861 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1864 GNUNET_free (config);
1865 if ((delegated_host_id < slave_list_size) &&
1866 (NULL != slave_list[delegated_host_id]))
1868 GNUNET_break (0); /* Configuration parsing error */
1869 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1872 slave = GNUNET_malloc (sizeof (struct Slave));
1873 slave->host_id = delegated_host_id;
1874 slave_list_add (slave);
1875 if (1 != msg->is_subordinate)
1878 GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1880 &slave_event_callback, slave);
1882 if (NULL != slave->controller)
1883 send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
1885 send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1886 "Could not connect to delegated controller");
1887 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1890 lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
1891 lcc->operation_id = GNUNET_ntohll (msg->operation_id);
1892 GNUNET_SERVER_client_keep (client);
1893 lcc->client = client;
1895 slave->controller_proc =
1896 GNUNET_TESTBED_controller_start (master_context->master_ip,
1897 host_list[slave->host_id], cfg,
1898 &slave_status_callback, slave);
1899 GNUNET_CONFIGURATION_destroy (cfg);
1900 new_route = GNUNET_malloc (sizeof (struct Route));
1901 new_route->dest = delegated_host_id;
1902 new_route->thru = master_context->host_id;
1903 route_list_add (new_route);
1907 /* Route the request */
1908 if (slave_host_id >= route_list_size)
1910 LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1911 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1914 lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1915 lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1916 lcfq->lcf->delegated_host_id = delegated_host_id;
1917 lcfq->lcf->slave_host_id = slave_host_id;
1918 route = find_dest_route (slave_host_id);
1919 GNUNET_assert (NULL != route); /* because we add routes carefully */
1920 GNUNET_assert (route->dest < slave_list_size);
1921 GNUNET_assert (NULL != slave_list[route->dest]);
1922 lcfq->lcf->state = INIT;
1923 lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
1924 lcfq->lcf->gateway = slave_list[route->dest];
1925 lcfq->lcf->msg = GNUNET_malloc (msize);
1926 (void) memcpy (lcfq->lcf->msg, msg, msize);
1927 GNUNET_SERVER_client_keep (client);
1928 lcfq->lcf->client = client;
1929 if (NULL == lcfq_head)
1931 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1932 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1933 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
1936 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1937 /* FIXME: Adding a new route should happen after the controllers are linked
1939 if (1 != msg->is_subordinate)
1941 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1944 if ((delegated_host_id < route_list_size)
1945 && (NULL != route_list[delegated_host_id]))
1947 GNUNET_break_op (0); /* Are you trying to link delegated host twice
1948 with is subordinate flag set to GNUNET_YES? */
1949 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1952 new_route = GNUNET_malloc (sizeof (struct Route));
1953 new_route->dest = delegated_host_id;
1954 new_route->thru = route->dest;
1955 route_list_add (new_route);
1956 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1961 * The task to be executed if the forwarded peer create operation has been
1964 * @param cls the FowardedOperationContext
1965 * @param tc the TaskContext from the scheduler
1968 peer_create_forward_timeout (void *cls,
1969 const struct GNUNET_SCHEDULER_TaskContext *tc)
1971 struct ForwardedOperationContext *fo_ctxt = cls;
1973 /* send error msg to client */
1974 GNUNET_free (fo_ctxt->cls);
1975 send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, "Timedout");
1976 GNUNET_SERVER_client_drop (fo_ctxt->client);
1977 GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);
1978 GNUNET_free (fo_ctxt);
1983 * Callback to be called when forwarded peer create operation is
1984 * successfull. We have to relay the reply msg back to the client
1986 * @param cls ForwardedOperationContext
1987 * @param msg the peer create success message
1990 peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
1992 struct ForwardedOperationContext *fo_ctxt = cls;
1993 struct GNUNET_MessageHeader *dup_msg;
1994 struct Peer *remote_peer;
1997 GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
1998 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS)
2000 GNUNET_assert (NULL != fo_ctxt->cls);
2001 remote_peer = fo_ctxt->cls;
2002 peer_list_add (remote_peer);
2004 msize = ntohs (msg->size);
2005 dup_msg = GNUNET_malloc (msize);
2006 (void) memcpy (dup_msg, msg, msize);
2007 queue_message (fo_ctxt->client, dup_msg);
2008 GNUNET_SERVER_client_drop (fo_ctxt->client);
2009 GNUNET_free (fo_ctxt);
2015 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
2018 * @param client identification of the client
2019 * @param message the actual message
2022 handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
2023 const struct GNUNET_MessageHeader *message)
2025 const struct GNUNET_TESTBED_PeerCreateMessage *msg;
2026 struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
2027 struct GNUNET_CONFIGURATION_Handle *cfg;
2028 struct ForwardedOperationContext *fo_ctxt;
2029 struct Route *route;
2034 uint32_t config_size;
2040 msize = ntohs (message->size);
2041 if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
2043 GNUNET_break (0); /* We need configuration */
2044 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2047 msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
2048 host_id = ntohl (msg->host_id);
2049 peer_id = ntohl (msg->peer_id);
2050 if (UINT32_MAX == peer_id)
2052 send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2053 "Cannot create peer with given ID");
2054 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2057 if (host_id == master_context->host_id)
2061 /* We are responsible for this peer */
2062 msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
2063 config_size = ntohl (msg->config_size);
2064 config = GNUNET_malloc (config_size);
2065 dest_size = config_size;
2068 uncompress ((Bytef *) config, (uLongf *) & dest_size,
2069 (const Bytef *) &msg[1], (uLong) msize)))
2071 GNUNET_break (0); /* uncompression error */
2072 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2075 if (config_size != dest_size)
2077 GNUNET_break (0); /* Uncompressed config size mismatch */
2078 GNUNET_free (config);
2079 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2082 cfg = GNUNET_CONFIGURATION_create ();
2084 GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
2086 GNUNET_break (0); /* Configuration parsing error */
2087 GNUNET_free (config);
2088 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2091 GNUNET_free (config);
2092 peer = GNUNET_malloc (sizeof (struct Peer));
2093 peer->is_remote = GNUNET_NO;
2094 peer->details.local.cfg = cfg;
2096 LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
2097 peer->details.local.peer =
2098 GNUNET_TESTING_peer_configure (master_context->system,
2099 peer->details.local.cfg, peer->id,
2100 NULL /* Peer id */ ,
2102 if (NULL == peer->details.local.peer)
2104 LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
2108 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2111 peer->details.local.is_running = GNUNET_NO;
2112 peer_list_add (peer);
2114 GNUNET_malloc (sizeof
2115 (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
2116 reply->header.size =
2117 htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
2118 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
2119 reply->peer_id = msg->peer_id;
2120 reply->operation_id = msg->operation_id;
2121 queue_message (client, &reply->header);
2122 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2126 /* Forward peer create request */
2127 route = find_dest_route (host_id);
2131 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2135 peer = GNUNET_malloc (sizeof (struct Peer));
2136 peer->is_remote = GNUNET_YES;
2138 peer->details.remote.slave = slave_list[route->dest];
2139 peer->details.remote.remote_host_id = host_id;
2140 fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2141 GNUNET_SERVER_client_keep (client);
2142 fo_ctxt->client = client;
2143 fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
2144 fo_ctxt->cls = peer; //slave_list[route->dest]->controller;
2146 GNUNET_TESTBED_forward_operation_msg_ (slave_list [route->dest]->controller,
2147 fo_ctxt->operation_id,
2149 peer_create_success_cb, fo_ctxt);
2150 fo_ctxt->timeout_task =
2151 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &peer_create_forward_timeout,
2153 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2158 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2161 * @param client identification of the client
2162 * @param message the actual message
2165 handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2166 const struct GNUNET_MessageHeader *message)
2168 const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
2169 struct ForwardedOperationContext *fopc;
2173 msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
2174 peer_id = ntohl (msg->peer_id);
2175 LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
2176 peer_id, GNUNET_ntohll (msg->operation_id));
2177 if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
2179 LOG (GNUNET_ERROR_TYPE_ERROR,
2180 "Asked to destroy a non existent peer with id: %u\n", peer_id);
2181 send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2182 "Peer doesn't exist");
2183 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2186 peer = peer_list[peer_id];
2187 if (GNUNET_YES == peer->is_remote)
2189 /* Forward the destory message to sub controller */
2190 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2191 GNUNET_SERVER_client_keep (client);
2192 fopc->client = client;
2193 fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2195 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2196 fopc->operation_id, &msg->header,
2197 &forwarded_operation_reply_relay,
2199 fopc->timeout_task =
2200 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2202 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2205 GNUNET_TESTING_peer_destroy (peer->details.local.peer);
2206 GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
2207 peer_list_remove (peer);
2209 send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
2210 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2215 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2218 * @param client identification of the client
2219 * @param message the actual message
2222 handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
2223 const struct GNUNET_MessageHeader *message)
2225 const struct GNUNET_TESTBED_PeerStartMessage *msg;
2226 struct GNUNET_TESTBED_PeerEventMessage *reply;
2227 struct ForwardedOperationContext *fopc;
2231 msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
2232 peer_id = ntohl (msg->peer_id);
2233 if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2236 LOG (GNUNET_ERROR_TYPE_ERROR,
2237 "Asked to start a non existent peer with id: %u\n", peer_id);
2238 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2241 peer = peer_list[peer_id];
2242 if (GNUNET_YES == peer->is_remote)
2244 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2245 GNUNET_SERVER_client_keep (client);
2246 fopc->client = client;
2247 fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2249 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2250 fopc->operation_id, &msg->header,
2251 &forwarded_operation_reply_relay,
2253 fopc->timeout_task =
2254 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2256 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2259 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer))
2261 send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2263 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2266 peer->details.local.is_running = GNUNET_YES;
2267 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2268 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2269 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2270 reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
2271 reply->host_id = htonl (master_context->host_id);
2272 reply->peer_id = msg->peer_id;
2273 reply->operation_id = msg->operation_id;
2274 queue_message (client, &reply->header);
2275 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2280 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2283 * @param client identification of the client
2284 * @param message the actual message
2287 handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
2288 const struct GNUNET_MessageHeader *message)
2290 const struct GNUNET_TESTBED_PeerStopMessage *msg;
2291 struct GNUNET_TESTBED_PeerEventMessage *reply;
2292 struct ForwardedOperationContext *fopc;
2296 msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
2297 peer_id = ntohl (msg->peer_id);
2298 if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2300 send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2302 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2305 peer = peer_list[peer_id];
2306 if (GNUNET_YES == peer->is_remote)
2308 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2309 GNUNET_SERVER_client_keep (client);
2310 fopc->client = client;
2311 fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2313 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2314 fopc->operation_id, &msg->header,
2315 &forwarded_operation_reply_relay,
2317 fopc->timeout_task =
2318 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2320 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2323 if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer->details.local.peer))
2325 send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2326 "Peer not running");
2327 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2330 peer->details.local.is_running = GNUNET_NO;
2331 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2332 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2333 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2334 reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
2335 reply->host_id = htonl (master_context->host_id);
2336 reply->peer_id = msg->peer_id;
2337 reply->operation_id = msg->operation_id;
2338 queue_message (client, &reply->header);
2339 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2344 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
2347 * @param client identification of the client
2348 * @param message the actual message
2351 handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
2352 const struct GNUNET_MessageHeader *message)
2354 const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
2355 struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
2364 msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
2365 peer_id = ntohl (msg->peer_id);
2366 if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2368 send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2370 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2373 peer = peer_list[peer_id];
2374 if (GNUNET_YES == peer->is_remote)
2376 struct ForwardedOperationContext *fopc;
2378 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2379 GNUNET_SERVER_client_keep (client);
2380 fopc->client = client;
2381 fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2383 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2384 fopc->operation_id, &msg->header,
2385 &forwarded_operation_reply_relay,
2387 fopc->timeout_task =
2388 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2390 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2394 GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->details.local.cfg,
2396 xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
2397 GNUNET_free (config);
2400 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2401 reply = GNUNET_realloc (xconfig, msize);
2402 (void) memmove (&reply[1], reply, xc_size);
2403 reply->header.size = htons (msize);
2404 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
2405 reply->peer_id = msg->peer_id;
2406 reply->operation_id = msg->operation_id;
2407 GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->details.local.peer,
2408 &reply->peer_identity);
2409 reply->config_size = htons ((uint16_t) c_size);
2410 queue_message (client, &reply->header);
2411 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2416 * Task for cleaing up overlay connect context structure
2418 * @param cls the overlay connect context
2419 * @param tc the task context
2422 occ_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2424 struct OverlayConnectContext *occ = cls;
2426 LOG_DEBUG ("Cleaning up occ\n");
2427 GNUNET_free_non_null (occ->emsg);
2428 GNUNET_free_non_null (occ->hello);
2429 GNUNET_SERVER_client_drop (occ->client);
2430 if (NULL != occ->opc)
2431 GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
2432 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2433 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2434 if (NULL != occ->ch)
2435 GNUNET_CORE_disconnect (occ->ch);
2436 if (NULL != occ->ghh)
2437 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2438 if (NULL != occ->p1th)
2439 GNUNET_TRANSPORT_disconnect (occ->p1th);
2440 if (NULL != occ->p2th)
2441 GNUNET_TRANSPORT_disconnect (occ->p2th);
2447 * Task which will be run when overlay connect request has been timed out
2449 * @param cls the OverlayConnectContext
2450 * @param tc the TaskContext
2453 timeout_overlay_connect (void *cls,
2454 const struct GNUNET_SCHEDULER_TaskContext *tc)
2456 struct OverlayConnectContext *occ = cls;
2458 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2459 LOG (GNUNET_ERROR_TYPE_WARNING,
2460 "Timeout while connecting peers %u and %u\n",
2461 occ->peer_id, occ->other_peer_id);
2462 send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
2463 occ_cleanup (occ, tc);
2469 * Function called to notify transport users that another
2470 * peer connected to us.
2472 * @param cls closure
2473 * @param new_peer the peer that connected
2474 * @param ats performance data
2475 * @param ats_count number of entries in ats (excluding 0-termination)
2478 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
2479 const struct GNUNET_ATS_Information *ats,
2480 unsigned int ats_count)
2482 struct OverlayConnectContext *occ = cls;
2483 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
2485 char *other_peer_str;
2487 LOG_DEBUG ("Overlay connect notify\n");
2489 memcmp (new_peer, &occ->peer_identity,
2490 sizeof (struct GNUNET_PeerIdentity)))
2492 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
2493 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2495 memcmp (new_peer, &occ->other_peer_identity,
2496 sizeof (struct GNUNET_PeerIdentity)))
2498 LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n",
2499 new_peer_str, other_peer_str);
2500 GNUNET_free (new_peer_str);
2501 GNUNET_free (other_peer_str);
2504 GNUNET_free (new_peer_str);
2505 LOG_DEBUG ("Peer %4s connected to peer %4s\n", other_peer_str,
2506 GNUNET_i2s (&occ->peer_identity));
2507 GNUNET_free (other_peer_str);
2508 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2510 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2511 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2513 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
2514 GNUNET_SCHEDULER_cancel (occ->timeout_task);
2515 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2516 GNUNET_free_non_null (occ->emsg);
2518 if (NULL != occ->p2th)
2519 GNUNET_TRANSPORT_disconnect (occ->p2th);
2521 LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
2522 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2524 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2525 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
2526 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
2527 msg->peer1 = htonl (occ->peer_id);
2528 msg->peer2 = htonl (occ->other_peer_id);
2529 msg->operation_id = GNUNET_htonll (occ->op_id);
2530 queue_message (occ->client, &msg->header);
2531 GNUNET_SCHEDULER_add_now (&occ_cleanup, occ);
2536 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
2539 * @param cls the OverlayConnectContext
2540 * @param tc the TaskContext from scheduler
2543 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2545 struct OverlayConnectContext *occ = cls;
2546 char *other_peer_str;
2548 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2549 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2551 GNUNET_assert (NULL != occ->hello);
2552 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2553 if (NULL != occ->peer2_controller)
2555 struct GNUNET_TESTBED_RequestConnectMessage *msg;
2557 uint16_t hello_size;
2559 LOG_DEBUG ("Offering HELLO of %s to %s via Remote Overlay Request\n",
2560 GNUNET_i2s (&occ->peer_identity), other_peer_str);
2561 hello_size = ntohs (occ->hello->size);
2562 msize = sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hello_size;
2563 msg = GNUNET_malloc (msize);
2564 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT);
2565 msg->header.size = htons (msize);
2566 msg->peer = htonl (occ->other_peer_id);
2567 msg->operation_id = GNUNET_htonll (occ->op_id);
2568 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
2569 sizeof (struct GNUNET_PeerIdentity));
2570 memcpy (msg->hello, occ->hello, hello_size);
2571 GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
2575 LOG_DEBUG ("Offering HELLO of %s to %s\n",
2576 GNUNET_i2s (&occ->peer_identity), other_peer_str);
2577 GNUNET_TRANSPORT_offer_hello (occ->p2th, occ->hello, NULL, NULL);
2578 GNUNET_TRANSPORT_try_connect (occ->p2th, &occ->peer_identity);
2579 occ->send_hello_task =
2580 GNUNET_SCHEDULER_add_delayed
2581 (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
2582 100 * (pow (2, occ->retries++))),
2585 GNUNET_free (other_peer_str);
2589 * Test for checking whether HELLO message is empty
2591 * @param cls empty flag to set
2592 * @param address the HELLO
2593 * @param expiration expiration of the HELLO
2597 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
2598 struct GNUNET_TIME_Absolute expiration)
2608 * Function called whenever there is an update to the HELLO of peers in the
2609 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
2610 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
2612 * @param cls closure
2613 * @param hello our updated HELLO
2616 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
2618 struct OverlayConnectContext *occ = cls;
2622 msize = ntohs (hello->size);
2624 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
2625 hello, GNUNET_NO, &test_address,
2627 if (GNUNET_YES == empty)
2629 LOG_DEBUG ("HELLO of %s is empty\n", GNUNET_i2s (&occ->peer_identity));
2632 LOG_DEBUG ("Received HELLO of %s\n", GNUNET_i2s (&occ->peer_identity));
2633 occ->hello = GNUNET_malloc (msize);
2634 memcpy (occ->hello, hello, msize);
2635 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2637 GNUNET_TRANSPORT_disconnect (occ->p1th);
2639 GNUNET_free_non_null (occ->emsg);
2640 if (NULL == occ->peer2_controller)
2643 GNUNET_TRANSPORT_connect (peer_list[occ->other_peer_id]->details.local.cfg,
2644 &occ->other_peer_identity, NULL, NULL, NULL,
2646 if (NULL == occ->p2th)
2648 GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of %s\n",
2649 GNUNET_i2s (&occ->other_peer_identity));
2650 GNUNET_SCHEDULER_cancel (occ->timeout_task);
2651 occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2655 occ->emsg = GNUNET_strdup ("Timeout while offering HELLO to other peer");
2656 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
2661 * Function called after GNUNET_CORE_connect has succeeded (or failed
2662 * for good). Note that the private key of the peer is intentionally
2663 * not exposed here; if you need it, your process should try to read
2664 * the private key file directly (which should work if you are
2667 * @param cls closure
2668 * @param server handle to the server, NULL if we failed
2669 * @param my_identity ID of this peer, NULL if we failed
2672 core_startup_cb (void *cls, struct GNUNET_CORE_Handle *server,
2673 const struct GNUNET_PeerIdentity *my_identity)
2675 struct OverlayConnectContext *occ = cls;
2677 GNUNET_free_non_null (occ->emsg);
2678 occ->emsg = GNUNET_strdup ("Failed to connect to CORE\n");
2679 if ((NULL == server) || (NULL == my_identity))
2681 GNUNET_free (occ->emsg);
2684 memcpy (&occ->peer_identity, my_identity,
2685 sizeof (struct GNUNET_PeerIdentity));
2687 GNUNET_TRANSPORT_connect (occ->peer->details.local.cfg,
2688 &occ->peer_identity, NULL, NULL, NULL, NULL);
2689 if (NULL == occ->p1th)
2691 GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of peers %4s",
2692 GNUNET_i2s (&occ->peer_identity));
2695 LOG_DEBUG ("Acquiring HELLO of peer %s\n", GNUNET_i2s (&occ->peer_identity));
2696 occ->emsg = GNUNET_strdup ("Timeout while acquiring HELLO message");
2697 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th, &hello_update_cb, occ);
2701 GNUNET_SCHEDULER_cancel (occ->timeout_task);
2702 occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2708 * Callback to be called when forwarded get peer config operation as part of
2709 * overlay connect is successfull. Connection to Peer 1's core is made and is
2710 * checked for new connection from peer 2
2712 * @param cls ForwardedOperationContext
2713 * @param msg the peer create success message
2716 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
2718 struct OverlayConnectContext *occ = cls;
2719 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
2720 const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2725 if (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG != ntohs (msg->type))
2727 cmsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
2729 memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
2730 sizeof (struct GNUNET_PeerIdentity));
2731 GNUNET_free_non_null (occ->emsg);
2732 occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
2734 GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
2735 &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
2736 GNUNET_NO, no_handlers);
2737 if (NULL == occ->ch)
2742 GNUNET_SCHEDULER_cancel (occ->timeout_task);
2744 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2749 * This callback is a part of overlay connect operation. This will be run when
2750 * the registration operation of peer2's controller is completed at peer1's
2753 * @param cls the ForwardedOverlayConnectContext
2754 * @param emsg the error message in case of any failure; NULL if host
2755 * registration is successfull.
2758 focc_reg_completion_cc (void *cls, const char *emsg)
2760 struct ForwardedOverlayConnectContext *focc = cls;
2761 struct GNUNET_CONFIGURATION_Handle *cfg;
2763 GNUNET_assert (FOCC_REGISTER == focc->state);
2764 GNUNET_assert (NULL == focc->sub_op);
2765 LOG_DEBUG ("[%u -> %u] Registering peer2's host successful\n",
2766 focc->peer1, focc->peer2);
2767 if ((NULL == focc->gateway2)
2768 || ((focc->peer2_host_id < slave_list_size) /* Check if we have the needed config */
2769 && (NULL != slave_list[focc->peer2_host_id])))
2771 focc->state = FOCC_LINK;
2772 cfg = (NULL == focc->gateway2) ?
2773 our_config : slave_list[focc->peer2_host_id]->cfg;
2775 GNUNET_TESTBED_controller_link_ (focc,
2776 focc->gateway->controller,
2777 focc->peer2_host_id,
2778 peer_list[focc->peer1]->details.remote.remote_host_id,
2783 focc->state = FOCC_GET_CFG;
2784 focc->sub_op = GNUNET_TESTBED_get_slave_config_ (focc, focc->gateway2->controller,
2785 focc->peer2_host_id);
2790 * Callback to be called when forwarded overlay connection operation has a reply
2791 * from the sub-controller successfull. We have to relay the reply msg back to
2794 * @param cls ForwardedOperationContext
2795 * @param msg the peer create success message
2798 forwarded_overlay_connect_listener (void *cls,
2799 const struct GNUNET_MessageHeader *msg)
2801 struct ForwardedOperationContext *fopc = cls;
2802 struct ForwardedOverlayConnectContext *focc;
2807 forwarded_operation_reply_relay (cls, msg);
2810 switch (focc->state)
2813 if (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG != ntohs (msg->type))
2815 GNUNET_break (0); /* Something failed; you may check output of
2817 cleanup_focc (focc);
2818 forwarded_operation_reply_relay (cls, msg);
2821 LOG_DEBUG ("[%u -> %u] Registering peer2's host %u at %u\n",
2822 focc->peer1, focc->peer2, focc->peer2_host_id,
2823 peer_list[focc->peer1]->details.remote.remote_host_id);
2824 focc->state = FOCC_REGISTER;
2825 queue_host_registration (focc->gateway,
2826 focc_reg_completion_cc,
2828 host_list[focc->peer2_host_id]);
2833 GNUNET_SERVER_client_drop (fopc->client);
2834 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
2835 fopc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2841 * Timeout task for cancelling a forwarded overlay connect connect
2843 * @param cls the ForwardedOverlayConnectContext
2844 * @param tc the task context from the scheduler
2847 forwarded_overlay_connect_timeout (void *cls,
2848 const struct GNUNET_SCHEDULER_TaskContext
2851 struct ForwardedOverlayConnectContext *focc = cls;
2853 focc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2854 LOG_DEBUG ("Overlay linking between peers %u and %u failed during state %u\n",
2855 focc->peer1, focc->peer2, focc->state);
2856 send_operation_fail_msg (focc->client, focc->operation_id, "Timeout");
2857 cleanup_focc (focc);
2862 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
2865 * @param client identification of the client
2866 * @param message the actual message
2869 handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
2870 const struct GNUNET_MessageHeader *message)
2872 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
2873 struct OverlayConnectContext *occ;
2874 const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2878 uint64_t operation_id;
2881 uint32_t peer2_host_id;
2883 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
2884 p1 = ntohl (msg->peer1);
2885 p2 = ntohl (msg->peer2);
2886 peer2_host_id = ntohl (msg->peer2_host_id);
2887 GNUNET_assert (p1 < peer_list_size);
2888 GNUNET_assert (NULL != peer_list[p1]);
2889 peer = peer_list[p1];
2890 operation_id = GNUNET_ntohll (msg->operation_id);
2891 LOG_DEBUG ("Received overlay connect for peers %u and %u with op id: 0x%lx\n",
2892 p1, p2, operation_id);
2893 if (GNUNET_YES == peer->is_remote)
2895 struct ForwardedOperationContext *fopc;
2896 struct Route *route_to_peer2_host;
2897 struct Route *route_to_peer1_host;
2899 LOG_DEBUG ("Forwarding overlay connect\n");
2900 GNUNET_SERVER_client_keep (client);
2901 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2902 fopc->client = client;
2903 fopc->operation_id = operation_id;
2904 route_to_peer2_host = NULL;
2905 route_to_peer1_host = NULL;
2906 route_to_peer2_host = find_dest_route (peer2_host_id);
2907 if ((NULL != route_to_peer2_host)
2908 || (peer2_host_id == master_context->host_id))
2910 route_to_peer1_host =
2911 find_dest_route (peer_list[p1]->details.remote.remote_host_id);
2912 GNUNET_assert (NULL != route_to_peer1_host);
2913 if ((peer2_host_id == master_context->host_id)
2914 || (route_to_peer2_host->dest != route_to_peer1_host->dest))
2916 struct ForwardedOverlayConnectContext *focc;
2919 msize = sizeof (struct GNUNET_TESTBED_OverlayConnectMessage);
2920 focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
2921 focc->gateway = peer->details.remote.slave;
2922 focc->gateway2 = (NULL == route_to_peer2_host) ? NULL :
2923 slave_list[route_to_peer2_host->dest];
2926 focc->peer2_host_id = peer2_host_id;
2927 focc->state = FOCC_INIT;
2928 focc->orig_msg = GNUNET_malloc (msize);
2929 (void) memcpy (focc->orig_msg, message, msize);
2930 GNUNET_SERVER_client_keep (client);
2931 focc->client = client;
2932 focc->operation_id = operation_id;
2934 focc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
2935 &forwarded_overlay_connect_timeout,
2940 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2941 operation_id, message,
2942 &forwarded_overlay_connect_listener,
2944 fopc->timeout_task =
2945 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2947 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2950 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
2951 GNUNET_SERVER_client_keep (client);
2952 occ->client = client;
2954 occ->other_peer_id = p2;
2955 occ->peer = peer_list[p1];
2956 occ->op_id = GNUNET_ntohll (msg->operation_id);
2957 if ((p2 >= peer_list_size) || (NULL == peer_list[p2]))
2959 if ((peer2_host_id >= slave_list_size)
2960 || (NULL ==slave_list[peer2_host_id]))
2962 struct GNUNET_TESTBED_NeedControllerConfig *reply;
2964 LOG_DEBUG ("Need controller configuration for connecting peers %u and %u\n",
2965 occ->peer_id, occ->other_peer_id);
2967 reply = GNUNET_malloc (sizeof (struct
2968 GNUNET_TESTBED_NeedControllerConfig));
2969 reply->header.size = htons (sizeof (struct
2970 GNUNET_TESTBED_NeedControllerConfig));
2971 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG);
2972 reply->controller_host_id = msg->peer2_host_id;
2973 reply->operation_id = msg->operation_id;
2974 queue_message (client, &reply->header);
2975 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2980 occ->peer2_controller = slave_list[peer2_host_id]->controller;
2981 if (NULL == occ->peer2_controller)
2983 GNUNET_break (0); /* What's going on? */
2984 GNUNET_SERVER_client_drop (client);
2986 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2993 if (GNUNET_YES == peer_list[occ->other_peer_id]->is_remote)
2994 occ->peer2_controller = peer_list[occ->other_peer_id]->details.remote.slave->controller;
2996 /* Get the identity of the second peer */
2997 if (NULL != occ->peer2_controller)
2999 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
3002 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
3003 cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG);
3004 cmsg.peer_id = msg->peer2;
3005 cmsg.operation_id = msg->operation_id;
3007 GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
3008 occ->op_id, &cmsg.header,
3009 &overlay_connect_get_config,
3012 GNUNET_strdup ("Timeout while getting peer identity of peer B\n");
3014 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
3015 (GNUNET_TIME_UNIT_SECONDS, 30),
3016 &timeout_overlay_connect, occ);
3017 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3020 GNUNET_TESTING_peer_get_identity (peer_list[occ->other_peer_id]->details.local.peer,
3021 &occ->other_peer_identity);
3022 /* Connect to the core of 1st peer and wait for the 2nd peer to connect */
3023 occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
3025 GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
3026 &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
3027 GNUNET_NO, no_handlers);
3028 if (NULL == occ->ch)
3030 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
3033 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
3034 (GNUNET_TIME_UNIT_SECONDS, 30),
3035 &timeout_overlay_connect, occ);
3036 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3041 * Function to cleanup RequestOverlayConnectContext and any associated tasks
3044 * @param rocc the RequestOverlayConnectContext
3047 cleanup_rocc (struct RequestOverlayConnectContext *rocc)
3049 if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
3050 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
3051 if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
3052 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
3053 GNUNET_TRANSPORT_disconnect (rocc->th);
3054 GNUNET_free_non_null (rocc->hello);
3060 * Task to timeout rocc and cleanit up
3062 * @param cls the RequestOverlayConnectContext
3063 * @param tc the TaskContext from scheduler
3066 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3068 struct RequestOverlayConnectContext *rocc = cls;
3070 rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
3071 cleanup_rocc (rocc);
3076 * Function called to notify transport users that another
3077 * peer connected to us.
3079 * @param cls closure
3080 * @param new_peer the peer that connected
3081 * @param ats performance data
3082 * @param ats_count number of entries in ats (excluding 0-termination)
3085 transport_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
3086 const struct GNUNET_ATS_Information * ats,
3089 struct RequestOverlayConnectContext *rocc = cls;
3091 LOG_DEBUG ("Request Overlay connect notify\n");
3092 if (0 != memcmp (new_peer, &rocc->a_id, sizeof (struct GNUNET_PeerIdentity)))
3094 LOG_DEBUG ("Peer %4s connected\n", GNUNET_i2s (&rocc->a_id));
3095 cleanup_rocc (rocc);
3100 * Task to offer the HELLO message to the peer and ask it to connect to the peer
3101 * whose identity is in RequestOverlayConnectContext
3103 * @param cls the RequestOverlayConnectContext
3104 * @param tc the TaskContext from scheduler
3107 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3109 struct RequestOverlayConnectContext *rocc = cls;
3111 rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
3112 GNUNET_TRANSPORT_offer_hello (rocc->th, rocc->hello, NULL, NULL);
3113 GNUNET_TRANSPORT_try_connect (rocc->th, &rocc->a_id);
3114 rocc->attempt_connect_task_id =
3115 GNUNET_SCHEDULER_add_delayed
3116 (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
3117 100 * (pow (2, rocc->retries++))),
3118 &attempt_connect_task, rocc);
3123 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
3126 * @param client identification of the client
3127 * @param message the actual message
3130 handle_overlay_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
3131 const struct GNUNET_MessageHeader *message)
3133 const struct GNUNET_TESTBED_RequestConnectMessage *msg;
3134 struct RequestOverlayConnectContext *rocc;
3140 msize = ntohs (message->size);
3141 if (sizeof (struct GNUNET_TESTBED_RequestConnectMessage) >= msize)
3144 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3147 msg = (const struct GNUNET_TESTBED_RequestConnectMessage *) message;
3148 if ((NULL == msg->hello) ||
3149 (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))
3152 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3155 hsize = ntohs (msg->hello->size);
3156 if ((sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hsize) != msize)
3159 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3162 peer_id = ntohl (msg->peer);
3163 if ((peer_id >= peer_list_size) || (NULL == (peer = peer_list[peer_id])))
3165 GNUNET_break_op (0);
3166 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3169 if (GNUNET_YES == peer->is_remote)
3171 struct GNUNET_MessageHeader *msg2;
3173 msg2 = GNUNET_malloc (msize);
3174 (void) memcpy (msg2, message, msize);
3175 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, msg2);
3176 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3179 rocc = GNUNET_malloc (sizeof (struct RequestOverlayConnectContext));
3180 rocc->th = GNUNET_TRANSPORT_connect (peer->details.local.cfg, NULL, rocc,
3181 NULL, &transport_connect_notify, NULL);
3182 if (NULL == rocc->th)
3186 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3189 memcpy (&rocc->a_id, &msg->peer_identity,
3190 sizeof (struct GNUNET_PeerIdentity));
3191 rocc->hello = GNUNET_malloc (hsize);
3192 memcpy (rocc->hello, msg->hello, hsize);
3193 rocc->attempt_connect_task_id =
3194 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
3195 rocc->timeout_rocc_task_id =
3196 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_rocc_task, rocc);
3197 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3202 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
3205 * @param client identification of the client
3206 * @param message the actual message
3209 handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
3210 const struct GNUNET_MessageHeader *message)
3212 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
3213 struct Slave *slave;
3214 struct GNUNET_TESTBED_SlaveConfiguration *reply;
3218 size_t xconfig_size;
3223 msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message;
3224 slave_id = ntohl (msg->slave_id);
3225 op_id = GNUNET_ntohll (msg->operation_id);
3226 if ((slave_list_size <= slave_id) || (NULL == slave_list[slave_id]))
3228 send_operation_fail_msg (client, op_id, "Slave not found");
3229 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3232 slave = slave_list[slave_id];
3233 if (NULL == slave->cfg)
3235 send_operation_fail_msg (client, op_id,
3236 "Configuration not found (slave not started by me)");
3237 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3240 config = GNUNET_CONFIGURATION_serialize (slave->cfg, &config_size);
3241 xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size,
3243 GNUNET_free (config);
3244 reply_size = xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
3245 GNUNET_break (reply_size <= UINT16_MAX);
3246 GNUNET_break (config_size <= UINT16_MAX);
3247 reply = GNUNET_realloc (xconfig, reply_size);
3248 (void) memmove (&reply[1], reply, xconfig_size);
3249 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG);
3250 reply->header.size = htons ((uint16_t) reply_size);
3251 reply->slave_id = msg->slave_id;
3252 reply->operation_id = msg->operation_id;
3253 reply->config_size = htons ((uint16_t) config_size);
3254 queue_message (client, &reply->header);
3255 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3260 * Iterator over hash map entries.
3262 * @param cls closure
3263 * @param key current key code
3264 * @param value value in the hash map
3265 * @return GNUNET_YES if we should continue to
3270 ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
3272 struct SharedService *ss = value;
3274 GNUNET_assert (GNUNET_YES ==
3275 GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
3276 GNUNET_free (ss->name);
3283 * Task to clean up and shutdown nicely
3286 * @param tc the TaskContext from scheduler
3289 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3291 struct LCFContextQueue *lcfq;
3294 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
3295 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
3296 (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
3298 GNUNET_CONTAINER_multihashmap_destroy (ss_map);
3299 if (NULL != lcfq_head)
3301 if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
3303 GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
3304 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
3307 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
3308 for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
3310 GNUNET_free (lcfq->lcf->msg);
3311 GNUNET_free (lcfq->lcf);
3312 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
3315 /* Clear peer list */
3316 for (id = 0; id < peer_list_size; id++)
3317 if (NULL != peer_list[id])
3319 if (GNUNET_NO == peer_list[id]->is_remote)
3321 if (GNUNET_YES == peer_list[id]->details.local.is_running)
3322 GNUNET_TESTING_peer_stop (peer_list[id]->details.local.peer);
3323 GNUNET_TESTING_peer_destroy (peer_list[id]->details.local.peer);
3324 GNUNET_CONFIGURATION_destroy (peer_list[id]->details.local.cfg);
3326 GNUNET_free (peer_list[id]);
3328 GNUNET_free_non_null (peer_list);
3329 /* Clear host list */
3330 for (id = 0; id < host_list_size; id++)
3331 if (NULL != host_list[id])
3332 GNUNET_TESTBED_host_destroy (host_list[id]);
3333 GNUNET_free_non_null (host_list);
3334 /* Clear route list */
3335 for (id = 0; id < route_list_size; id++)
3336 if (NULL != route_list[id])
3337 GNUNET_free (route_list[id]);
3338 GNUNET_free_non_null (route_list);
3339 /* Clear slave_list */
3340 for (id = 0; id < slave_list_size; id++)
3341 if (NULL != slave_list[id])
3343 struct HostRegistration *hr_entry;
3345 while (NULL != (hr_entry = slave_list[id]->hr_dll_head))
3347 GNUNET_CONTAINER_DLL_remove (slave_list[id]->hr_dll_head,
3348 slave_list[id]->hr_dll_tail,
3350 GNUNET_free (hr_entry);
3352 if (NULL != slave_list[id]->rhandle)
3353 GNUNET_TESTBED_cancel_registration (slave_list[id]->rhandle);
3354 if (NULL != slave_list[id]->cfg)
3355 GNUNET_CONFIGURATION_destroy (slave_list[id]->cfg);
3356 if (NULL != slave_list[id]->controller)
3357 GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
3358 if (NULL != slave_list[id]->controller_proc)
3359 GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
3360 GNUNET_free (slave_list[id]);
3362 GNUNET_free_non_null (slave_list);
3363 if (NULL != master_context)
3365 GNUNET_free_non_null (master_context->master_ip);
3366 if (NULL != master_context->system)
3367 GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
3368 GNUNET_free (master_context);
3369 master_context = NULL;
3371 GNUNET_free_non_null (hostname);
3372 GNUNET_CONFIGURATION_destroy (our_config);
3377 * Callback for client disconnect
3380 * @param client the client which has disconnected
3383 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
3385 if (NULL == master_context)
3387 if (client == master_context->client)
3389 LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
3390 GNUNET_SERVER_client_drop (client);
3391 /* should not be needed as we're terminated by failure to read
3392 * from stdin, but if stdin fails for some reason, this shouldn't
3393 * hurt for now --- might need to revise this later if we ever
3394 * decide that master connections might be temporarily down
3395 * for some reason */
3396 //GNUNET_SCHEDULER_shutdown ();
3404 * @param cls closure
3405 * @param server the initialized server
3406 * @param cfg configuration to use
3409 testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
3410 const struct GNUNET_CONFIGURATION_Handle *cfg)
3412 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
3413 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
3414 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
3415 {&handle_configure_shared_service, NULL,
3416 GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
3417 {&handle_link_controllers, NULL,
3418 GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
3419 {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
3420 {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
3421 sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
3422 {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
3423 sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
3424 {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
3425 sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
3426 {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
3427 sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
3428 {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
3429 sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
3430 {&handle_overlay_request_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT,
3432 {handle_slave_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG,
3433 sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
3437 GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string
3438 (cfg, "testbed", "HOSTNAME", &hostname));
3439 our_config = GNUNET_CONFIGURATION_dup (cfg);
3440 GNUNET_SERVER_add_handlers (server, message_handlers);
3441 GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
3442 ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
3444 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
3445 &shutdown_task, NULL);
3446 LOG_DEBUG ("Testbed startup complete\n");
3447 event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
3452 * The starting point of execution
3455 main (int argc, char *const *argv)
3457 //sleep (15); /* Debugging */
3458 return (GNUNET_OK ==
3459 GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
3460 &testbed_run, NULL)) ? 0 : 1;
3463 /* end of gnunet-service-testbed.c */