towards handling suboperations during overlay connect
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed.c
index 0736f59979b32869969b95560686b3e7a565c8b2..05d296fee451ef07d68dd7175a5608ce56a30b8c 100644 (file)
  */
 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
 
-/**
- * Timeout of Transport try_connect requests
- */
-#define TRANSPORT_TRY_CONNECT_TIMEOUT                                   \
-  GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100)
-
 /**
  * The main context information associated with the client which started us
  */
@@ -85,7 +79,7 @@ struct Context
    * The TESTING system handle for starting peers locally
    */
   struct GNUNET_TESTING_System *system;
-
+  
   /**
    * Event mask of event to be responded in this context
    */
@@ -186,8 +180,7 @@ struct Slave
   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;
 
@@ -302,7 +295,7 @@ struct LCFContextQueue
 
 
 /**
- * A locally started peer
+ * A peer
  */
 struct Peer
 {
@@ -442,6 +435,12 @@ struct OverlayConnectContext
    * The id of peer B
    */
   uint32_t other_peer_id;
+
+  /**
+   * Number of times we tried to send hello; used to increase delay in offering
+   * hellos
+   */
+  uint16_t retries;
 };
 
 
@@ -478,6 +477,12 @@ struct RequestOverlayConnectContext
    */
   GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
   
+  /**
+   * Number of times we tried to send hello; used to increase delay in offering
+   * hellos
+   */
+  uint16_t retries;
+  
 };
 
 
@@ -592,7 +597,7 @@ static struct Route **route_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;
 
@@ -1540,7 +1545,7 @@ handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
           GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
                                              master_context->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
@@ -2036,8 +2041,20 @@ handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
   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;
   }
@@ -2225,8 +2242,10 @@ send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_TRANSPORT_offer_hello (occ->p2th, occ->hello, NULL, NULL);
     GNUNET_TRANSPORT_try_connect (occ->p2th, &occ->peer_identity);
     occ->send_hello_task =
-        GNUNET_SCHEDULER_add_delayed (TRANSPORT_TRY_CONNECT_TIMEOUT,
-                                      &send_hello, occ);
+        GNUNET_SCHEDULER_add_delayed
+        (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                        100 * (pow (2, occ->retries++))),
+         &send_hello, occ);
   }
   GNUNET_free (other_peer_str);  
 }
@@ -2445,7 +2464,7 @@ handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
   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;
@@ -2454,21 +2473,32 @@ handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
     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
   {
@@ -2594,8 +2624,10 @@ attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   GNUNET_TRANSPORT_offer_hello (rocc->th, rocc->hello, NULL, NULL);
   GNUNET_TRANSPORT_try_connect (rocc->th, &rocc->a_id);
   rocc->attempt_connect_task_id = 
-      GNUNET_SCHEDULER_add_delayed (TRANSPORT_TRY_CONNECT_TIMEOUT,
-                                    &attempt_connect_task, rocc);
+      GNUNET_SCHEDULER_add_delayed 
+      (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                      100 * (pow (2, rocc->retries++))),
+       &attempt_connect_task, rocc);
 }
 
 
@@ -2646,10 +2678,14 @@ handle_overlay_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
     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));
@@ -2666,8 +2702,6 @@ handle_overlay_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
           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 =
@@ -2906,7 +2940,7 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
                 (cfg, "testbed", "HOSTNAME", &hostname));
   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);