* The TESTING system handle for starting peers locally
*/
struct GNUNET_TESTING_System *system;
-
- /**
- * Event mask of event to be responded in this context
- */
- uint64_t event_mask;
-
+
/**
* Our host id according to this context
*/
struct GNUNET_TESTBED_Controller *controller;
/**
- * The configuration of the slave. Will be NULL for slave which we didn't
- * directly start
+ * The configuration of the slave. Cannot be NULL
*/
struct GNUNET_CONFIGURATION_Handle *cfg;
/**
- * A locally started peer
+ * A peer
*/
struct Peer
{
*/
struct GNUNET_TESTBED_Controller *controller;
+ /**
+ * The id of the remote host this peer is running on
+ */
+ uint32_t remote_host_id;
+
} remote;
} details;
};
+/**
+ * Context information to used during operations which forward the overlay
+ * connect message
+ */
+struct ForwardedOverlayConnectContext
+{
+ /**
+ * The gateway controller to which this operation is forwarded to
+ */
+ struct GNUNET_TESTBED_Controller *gateway;
+
+ /**
+ * The gateway controller through which peer2's controller can be reached
+ */
+ struct GNUNET_TESTBED_Controller *gateway2;
+
+ /**
+ * Handle for sub-operations
+ */
+ struct GNUNET_TESTBED_Operation *sub_op;
+
+ /**
+ * The client which initiated the link controller operation
+ */
+ struct GNUNET_SERVER_Client *client;
+
+ /**
+ * A copy of the original overlay connect message
+ */
+ struct GNUNET_MessageHeader *orig_msg;
+
+ /**
+ * The host registration handle while registered hosts in this context
+ */
+ struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
+
+ /**
+ * The id of the operation which created this context information
+ */
+ uint64_t operation_id;
+
+ /**
+ * Enumeration of states for this context
+ */
+ enum FOCCState {
+
+ /**
+ * The initial state
+ */
+ FOCC_INIT = 0,
+
+ /**
+ * State where we attempt to register peer2's controller with peer1's controller
+ */
+ FOCC_REGISTER,
+
+ /**
+ * State where we attempt to get peer2's controller configuration
+ */
+ FOCC_GET_CFG,
+
+ /**
+ * State where we attempt to link the controller of peer 1 to the controller
+ * of peer2
+ */
+ FOCC_LINK,
+
+ /**
+ * State where we attempt to do the overlay connection again
+ */
+ FOCC_OL_CONNECT
+
+ } state;
+
+ /**
+ * the id of peer 1
+ */
+ uint32_t peer1;
+
+ /**
+ * The id of peer 2
+ */
+ uint32_t peer2;
+
+ /**
+ * Id of the host where peer2 is running
+ */
+ uint32_t peer2_host_id;
+};
+
+
/**
* The master context; generated with the first INIT message
*/
static char *hostname;
+
/***********/
/* Handles */
/***********/
+/**
+ * Our configuration
+ */
+static struct GNUNET_CONFIGURATION_Handle *our_config;
+
/**
* Current Transmit Handle; NULL if no notify transmit exists currently
*/
static struct MessageQueue *mq_tail;
/**
- * Array of host list
+ * Array of hosts
*/
static struct GNUNET_TESTBED_Host **host_list;
static struct Slave **slave_list;
/**
- * A list of peers we own locally
+ * A list of peers we know about
*/
static struct Peer **peer_list;
*/
static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
+/**
+ * The event mask for the events we listen from sub-controllers
+ */
+static uint64_t event_mask;
+
/**
* The size of the host list
*/
{
struct Route *route;
+ if (route_list_size <= host_id)
+ return NULL;
while (NULL != (route = route_list[host_id]))
{
if (route->thru == master_context->host_id)
}
+/**
+ * Callback to be called when forwarded overlay connection operation has a reply
+ * from the sub-controller successfull. We have to relay the reply msg back to
+ * the client
+ *
+ * @param cls ForwardedOperationContext
+ * @param msg the peer create success message
+ */
+static void
+forwarded_overlay_connect_listener (void *cls,
+ const struct GNUNET_MessageHeader *msg);
+
+
+/**
+ * Cleans up ForwardedOverlayConnectContext
+ *
+ * @param focc the ForwardedOverlayConnectContext to cleanup
+ */
+static void
+cleanup_focc (struct ForwardedOverlayConnectContext *focc)
+{
+ if (NULL != focc->sub_op)
+ GNUNET_TESTBED_operation_done (focc->sub_op);
+ if (NULL != focc->client)
+ GNUNET_SERVER_client_drop (focc->client);
+ GNUNET_free_non_null (focc->orig_msg);
+ GNUNET_free (focc);
+}
+
/**
* Callback for event from slave controllers
*
slave_event_callback (void *cls,
const struct GNUNET_TESTBED_EventInformation *event)
{
- GNUNET_break (0);
+ struct ForwardedOverlayConnectContext *focc;
+ struct ForwardedOperationContext *fopc;
+ struct GNUNET_CONFIGURATION_Handle *slave_cfg;
+ struct GNUNET_TESTBED_Operation *old_op;
+ char *emsg;
+
+ /* We currently only get here when doing overlay connect operations and that
+ too while trying out sub operations */
+ GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
+ focc = event->details.operation_finished.op_cls;
+ LOG_DEBUG ("Operation successful\n");
+ if (NULL != event->details.operation_finished.emsg)
+ {
+ GNUNET_asprintf (&emsg, "Failure executing suboperation: %s",
+ event->details.operation_finished.emsg);
+ send_operation_fail_msg (focc->client, focc->operation_id,
+ emsg);
+ GNUNET_free (emsg);
+ cleanup_focc (focc);
+ return;
+ }
+ switch (focc->state)
+ {
+ case FOCC_GET_CFG:
+ slave_cfg = event->details.operation_finished.generic;
+ old_op = focc->sub_op;
+ focc->state = FOCC_LINK;
+ focc->sub_op = GNUNET_TESTBED_controller_link_ (focc,
+ focc->gateway,
+ focc->peer2_host_id,
+ peer_list[focc->peer1]->details.remote.remote_host_id,
+ slave_cfg,
+ GNUNET_NO);
+ GNUNET_TESTBED_operation_done (old_op);
+ break;
+ case FOCC_LINK:
+ LOG_DEBUG ("OL: Linking controllers successfull\n");
+ GNUNET_TESTBED_operation_done (focc->sub_op);
+ focc->sub_op = NULL;
+ focc->state = FOCC_OL_CONNECT;
+ fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fopc->client = focc->client;
+ focc->client = NULL;
+ fopc->operation_id = focc->operation_id;
+ fopc->cls = NULL;
+ fopc->opc =
+ GNUNET_TESTBED_forward_operation_msg_ (focc->gateway,
+ focc->operation_id, focc->orig_msg,
+ &forwarded_operation_reply_relay,
+ fopc);
+ GNUNET_free (focc->orig_msg);
+ focc->orig_msg = NULL;
+ fopc->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
+ fopc);
+ cleanup_focc (focc);
+ break;
+ default:
+ GNUNET_assert (0);
+ }
+ return;
}
}
slave->controller =
GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
- master_context->event_mask,
+ event_mask,
&slave_event_callback, slave);
if (NULL != slave->controller)
{
master_context->system =
GNUNET_TESTING_system_create ("testbed", master_context->master_ip, hostname);
host =
- GNUNET_TESTBED_host_create_with_id (master_context->host_id, NULL, NULL,
+ GNUNET_TESTBED_host_create_with_id (master_context->host_id,
+ master_context->master_ip,
+ NULL,
0);
host_list_add (host);
- master_context->event_mask = GNUNET_ntohll (msg->event_mask);
GNUNET_SERVER_client_keep (client);
LOG_DEBUG ("Created master context with host ID: %u\n",
master_context->host_id);
msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
msize = ntohs (msg->header.size);
- username = (char *) &(msg[1]);
+ username = (char *) &msg[1];
username_length = ntohs (msg->user_name_length);
- GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length + 1)); /* msg must contain hostname */
if (0 != username_length)
- GNUNET_assert ('\0' == username[username_length]);
- username_length = (0 == username_length) ? 0 : username_length + 1;
+ username_length++;
+ /* msg must contain hostname */
+ GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
+ username_length + 1));
+ if (0 != username_length)
+ GNUNET_assert ('\0' == username[username_length - 1]);
hostname = username + username_length;
hostname_length =
msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
slave_host_id = ntohl (msg->slave_host_id);
if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
{
- LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
+ LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
+ slave_host_id);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
{
LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
delegated_host_id);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
config = GNUNET_malloc (config_size);
{
slave->controller =
GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
- master_context->event_mask,
+ event_mask,
&slave_event_callback, slave);
- GNUNET_CONFIGURATION_destroy (cfg);
+ slave->cfg = cfg;
if (NULL != slave->controller)
send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
else
struct ForwardedOperationContext *fo_ctxt = cls;
/* send error msg to client */
+ GNUNET_free (fo_ctxt->cls);
send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, "Timedout");
GNUNET_SERVER_client_drop (fo_ctxt->client);
GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);
struct ForwardedOperationContext *fo_ctxt = cls;
const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *success_msg;
struct GNUNET_MessageHeader *dup_msg;
- struct Peer *peer;
+ struct Peer *remote_peer;
uint16_t msize;
GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
{
success_msg =
(const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *) msg;
- peer = GNUNET_malloc (sizeof (struct Peer));
- peer->is_remote = GNUNET_YES;
- peer->id = ntohl (success_msg->peer_id);
GNUNET_assert (NULL != fo_ctxt->cls);
- peer->details.remote.controller = fo_ctxt->cls;
- peer_list_add (peer);
+ remote_peer = fo_ctxt->cls;
+ GNUNET_assert (remote_peer->details.remote.remote_host_id
+ == ntohl (success_msg->peer_id));
+ peer_list_add (remote_peer);
}
msize = ntohs (msg->size);
dup_msg = GNUNET_malloc (msize);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
+
+ peer = GNUNET_malloc (sizeof (struct Peer));
+ peer->is_remote = GNUNET_YES;
+ peer->id = peer_id;
+ peer->details.remote.controller = slave_list[route->dest]->controller;
+ peer->details.remote.remote_host_id = host_id;
fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
GNUNET_SERVER_client_keep (client);
fo_ctxt->client = client;
fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
- fo_ctxt->cls = slave_list[route->dest]->controller;
+ fo_ctxt->cls = peer; //slave_list[route->dest]->controller;
fo_ctxt->opc =
- GNUNET_TESTBED_forward_operation_msg_ (slave_list
- [route->dest]->controller,
+ GNUNET_TESTBED_forward_operation_msg_ (slave_list [route->dest]->controller,
fo_ctxt->operation_id,
&msg->header,
peer_create_success_cb, fo_ctxt);
fo_ctxt->timeout_task =
GNUNET_SCHEDULER_add_delayed (TIMEOUT, &peer_create_forward_timeout,
fo_ctxt);
-
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
peer = peer_list[peer_id];
if (GNUNET_YES == peer->is_remote)
{
- /* FIXME: forward to sub controller */
- GNUNET_break (0);
+ struct ForwardedOperationContext *fopc;
+
+ fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ GNUNET_SERVER_client_keep (client);
+ fopc->client = client;
+ fopc->operation_id = GNUNET_ntohll (msg->operation_id);
+ fopc->opc =
+ GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
+ fopc->operation_id, &msg->header,
+ &forwarded_operation_reply_relay,
+ fopc);
+ fopc->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
+ fopc);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
}
+/**
+ * This callback is a part of overlay connect operation. This will be run when
+ * the registration operation of peer2's controller is completed at peer1's
+ * controller
+ *
+ * @param cls the ForwardedOverlayConnectContext
+ * @param emsg the error message in case of any failure; NULL if host
+ * registration is successfull.
+ */
+static void
+focc_reg_completion_cc (void *cls, const char *emsg)
+{
+ struct ForwardedOverlayConnectContext *focc = cls;
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ GNUNET_assert (FOCC_REGISTER == focc->state);
+ focc->rhandle = NULL;
+ GNUNET_assert (NULL == focc->sub_op);
+ LOG_DEBUG ("Registering peer2's host successful\n");
+ if ((NULL == focc->gateway2)
+ || ((focc->peer2_host_id < slave_list_size) /* Check if we have the needed config */
+ && (NULL != slave_list[focc->peer2_host_id])))
+ {
+ focc->state = FOCC_LINK;
+ cfg = (NULL == focc->gateway2) ?
+ our_config : slave_list[focc->peer2_host_id]->cfg;
+ focc->sub_op =
+ GNUNET_TESTBED_controller_link_ (focc,
+ focc->gateway,
+ focc->peer2_host_id,
+ peer_list[focc->peer1]->details.remote.remote_host_id,
+ cfg,
+ GNUNET_NO);
+ return;
+ }
+ focc->state = FOCC_GET_CFG;
+ focc->sub_op = GNUNET_TESTBED_get_slave_config_ (focc, focc->gateway2,
+ focc->peer2_host_id);
+}
+
+
+/**
+ * Callback to be called when forwarded overlay connection operation has a reply
+ * from the sub-controller successfull. We have to relay the reply msg back to
+ * the client
+ *
+ * @param cls ForwardedOperationContext
+ * @param msg the peer create success message
+ */
+static void
+forwarded_overlay_connect_listener (void *cls,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct ForwardedOperationContext *fopc = cls;
+ struct ForwardedOverlayConnectContext *focc;
+
+ focc = fopc->cls;
+ if (NULL == focc)
+ {
+ forwarded_operation_reply_relay (cls, msg);
+ return;
+ }
+ switch (focc->state)
+ {
+ case FOCC_INIT:
+ if (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG != ntohs (msg->type))
+ {
+ GNUNET_break (0); /* Something failed; you may check output of
+ sub-controllers */
+ cleanup_focc (focc);
+ forwarded_operation_reply_relay (cls, msg);
+ return;
+ }
+ LOG_DEBUG ("Registering peer2's host\n");
+ focc->state = FOCC_REGISTER;
+ focc->rhandle =
+ GNUNET_TESTBED_register_host (focc->gateway,
+ host_list[focc->peer2_host_id],
+ focc_reg_completion_cc, focc);
+ break;
+ default:
+ GNUNET_assert (0);
+ }
+ GNUNET_SERVER_client_drop (fopc->client);
+ GNUNET_SCHEDULER_cancel (fopc->timeout_task);
+ fopc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_free (fopc);
+}
+
+
/**
* Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
*
struct Peer *peer;
uint64_t operation_id;
uint32_t p1;
- uint32_t p2;
+ uint32_t p2;
+ uint32_t peer2_host_id;
msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
p1 = ntohl (msg->peer1);
p2 = ntohl (msg->peer2);
+ peer2_host_id = ntohl (msg->peer2_host_id);
GNUNET_assert (p1 < peer_list_size);
GNUNET_assert (NULL != peer_list[p1]);
peer = peer_list[p1];
- operation_id = GNUNET_ntohll (msg->operation_id);
+ operation_id = GNUNET_ntohll (msg->operation_id);
if (GNUNET_YES == peer->is_remote)
{
struct ForwardedOperationContext *fopc;
+ struct Route *route_to_peer2_host;
+ struct Route *route_to_peer1_host;
- fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ LOG_DEBUG ("Forwarding overlay connect\n");
GNUNET_SERVER_client_keep (client);
+ fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
fopc->client = client;
fopc->operation_id = operation_id;
- LOG_DEBUG ("Forwarding overlay connect\n");
+ route_to_peer2_host = NULL;
+ route_to_peer1_host = NULL;
+ route_to_peer2_host = find_dest_route (peer2_host_id);
+ if ((NULL != route_to_peer2_host)
+ || (peer2_host_id == master_context->host_id))
+ {
+ route_to_peer1_host =
+ find_dest_route (peer_list[p1]->details.remote.remote_host_id);
+ GNUNET_assert (NULL != route_to_peer1_host);
+ if ((peer2_host_id == master_context->host_id)
+ || (route_to_peer2_host->dest != route_to_peer1_host->dest))
+ {
+ struct ForwardedOverlayConnectContext *focc;
+ uint16_t msize;
+
+ msize = sizeof (struct GNUNET_TESTBED_OverlayConnectMessage);
+ focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
+ focc->gateway = peer->details.remote.controller;
+ focc->gateway2 = (NULL == route_to_peer2_host) ? NULL :
+ slave_list[route_to_peer2_host->dest]->controller;
+ focc->peer1 = p1;
+ focc->peer2 = p2;
+ focc->peer2_host_id = peer2_host_id;
+ focc->state = FOCC_INIT;
+ focc->orig_msg = GNUNET_malloc (msize);
+ (void) memcpy (focc->orig_msg, message, msize);
+ GNUNET_SERVER_client_keep (client);
+ focc->client = client;
+ focc->operation_id = operation_id;
+ fopc->cls = focc;
+ }
+ }
fopc->opc =
GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
operation_id, message,
- &forwarded_operation_reply_relay,
+ &forwarded_overlay_connect_listener,
fopc);
fopc->timeout_task =
GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
occ->peer_id = p1;
occ->other_peer_id = p2;
occ->peer = peer_list[p1];
- occ->op_id = GNUNET_ntohll (msg->operation_id);
+ occ->op_id = GNUNET_ntohll (msg->operation_id);
if ((p2 >= peer_list_size) || (NULL == peer_list[p2]))
- {
- uint32_t peer2_host_id;
-
- peer2_host_id = ntohl (msg->peer2_host_id);
+ {
if ((peer2_host_id >= slave_list_size)
|| (NULL ==slave_list[peer2_host_id]))
{
- GNUNET_break (0);
- GNUNET_SERVER_client_drop (client);
+ struct GNUNET_TESTBED_NeedControllerConfig *reply;
+
GNUNET_free (occ);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ reply = GNUNET_malloc (sizeof (struct
+ GNUNET_TESTBED_NeedControllerConfig));
+ reply->header.size = htons (sizeof (struct
+ GNUNET_TESTBED_NeedControllerConfig));
+ reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG);
+ reply->controller_host_id = msg->peer2_host_id;
+ reply->operation_id = msg->operation_id;
+ queue_message (client, &reply->header);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- occ->peer2_controller = slave_list[peer2_host_id]->controller;
- if (NULL == occ->peer2_controller)
+ else
{
- GNUNET_break (0);
- GNUNET_SERVER_client_drop (client);
- GNUNET_free (occ);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
+ occ->peer2_controller = slave_list[peer2_host_id]->controller;
+ if (NULL == occ->peer2_controller)
+ {
+ GNUNET_break (0); /* What's going on? */
+ GNUNET_SERVER_client_drop (client);
+ GNUNET_free (occ);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ }
}
else
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- if (GNUNET_NO != peer->is_remote)
+ if (GNUNET_YES == peer->is_remote)
{
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ struct GNUNET_MessageHeader *msg2;
+
+ msg2 = GNUNET_malloc (msize);
+ (void) memcpy (msg2, message, msize);
+ GNUNET_TESTBED_queue_message_ (peer->details.remote.controller, msg2);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
rocc = GNUNET_malloc (sizeof (struct RequestOverlayConnectContext));
sizeof (struct GNUNET_PeerIdentity));
rocc->hello = GNUNET_malloc (hsize);
memcpy (rocc->hello, msg->hello, hsize);
- /* GNUNET_TRANSPORT_offer_hello (th, msg->hello, NULL, NULL); */
- /* GNUNET_TRANSPORT_try_connect (th, &msg->peer_identity); */
rocc->attempt_connect_task_id =
GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
rocc->timeout_rocc_task_id =
master_context = NULL;
}
GNUNET_free_non_null (hostname);
+ GNUNET_CONFIGURATION_destroy (our_config);
}
GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string
(cfg, "testbed", "HOSTNAME", &hostname));
+ our_config = GNUNET_CONFIGURATION_dup (cfg);
GNUNET_SERVER_add_handlers (server, message_handlers);
GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
- ss_map = GNUNET_CONTAINER_multihashmap_create (5);
+ ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
shutdown_task_id =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
&shutdown_task, NULL);
LOG_DEBUG ("Testbed startup complete\n");
+ event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
}