migrate more tests to new transmission API
[oweals/gnunet.git] / src / transport / transport-testing.c
index 95f4eb6710e6ba766ebf2e882748fab8148b505f..50c297389126da68b1d3165a796ed25117b8b3e9 100644 (file)
@@ -44,23 +44,64 @@ find_peer_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
 }
 
 
-static struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
-find_connecting_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
-                         struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
-                         struct GNUNET_TRANSPORT_TESTING_PeerContext *p2)
+/**
+ * Find any connecting context matching the given pair of peers.
+ *
+ * @param p1 first peer
+ * @param p2 second peer
+ * @param cb function to call 
+ * @param cb_cls closure for @a cb
+ */
+void
+GNUNET_TRANSPORT_TESTING_find_connecting_context (struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
+                                                 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
+                                                 GNUNET_TRANSPORT_TESTING_ConnectContextCallback cb,
+                                                 void *cb_cls)
 {
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
 
-  for (cc = tth->cc_head; NULL != cc; cc = cc->next)
+  for (cc = tth->cc_head; NULL != cc; cc = ccn)
   {
+    ccn = cc->next;
     if ( (cc->p1 == p1) &&
-         (cc->p2 == p2) )
-      return cc;
-    if ( (cc->p1 == p2) &&
-         (cc->p2 == p1) )
-      return cc;
+        (cc->p2 == p2) ) 
+      cb (cb_cls,
+         cc);
   }
-  return NULL;
+}
+
+
+static void
+set_p1c (void *cls,   
+        struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  cx->p1_c = GNUNET_YES;
+}
+
+
+static void
+set_p2c (void *cls,   
+        struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  cx->p2_c = GNUNET_YES;
+}
+
+
+static void
+clear_p1c (void *cls,   
+          struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  cx->p1_c = GNUNET_NO;
+}
+
+
+static void
+clear_p2c (void *cls,   
+        struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  cx->p2_c = GNUNET_NO;
 }
 
 
@@ -69,9 +110,11 @@ notify_connect (void *cls,
                 const struct GNUNET_PeerIdentity *peer)
 {
   struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
   char *p2_s;
   struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
 
   p2 = find_peer_context (p->tth,
                           peer);
@@ -94,45 +137,83 @@ notify_connect (void *cls,
        p->no,
        GNUNET_i2s (&p->id));
   GNUNET_free (p2_s);
-
-  /* Find ConnectingContext */
-  cc = find_connecting_context (p->tth,
-                                p,
-                                p2);
-  if (NULL == cc)
-    return;
-  if (p == cc->p1)
-    cc->p1_c = GNUNET_YES;
-  if (p == cc->p2)
-    cc->p2_c = GNUNET_YES;
-
-  if ( (cc->p1_c == GNUNET_YES) &&
-       (cc->p2_c == GNUNET_YES) )
+  /* update flags in connecting contexts */
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
+                                                   p2,
+                                                   &set_p1c,
+                                                   NULL);
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
+                                                   p,
+                                                   &set_p2c,
+                                                   NULL);
+  /* update set connected flag for all requests */
+  for (cc = tth->cc_head; NULL != cc; cc = cc->next)
   {
-    cc->cb (cc->cb_cls);
-    GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
+    if (GNUNET_YES == cc->connected)
+      continue;
+    if ( (GNUNET_YES == cc->p1_c) &&
+         (GNUNET_YES == cc->p2_c) )
+    {
+      cc->connected = GNUNET_YES;
+      /* stop trying to connect */
+      if (NULL != cc->tct)
+      {
+       GNUNET_SCHEDULER_cancel (cc->tct);
+       cc->tct = NULL;
+      }
+      if (NULL != cc->oh)
+      {
+       GNUNET_TRANSPORT_offer_hello_cancel (cc->oh);
+       cc->oh = NULL;
+      }
+      if (NULL != cc->ats_sh)
+      {
+       GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh);
+       cc->ats_sh = NULL;
+      }
+    }
+  }
+  /* then notify application */
+  for (cc = tth->cc_head; NULL != cc; cc = ccn)
+  {
+    ccn = cc->next;
+    if ( (GNUNET_YES == cc->connected) &&
+         (NULL != cc->cb) )
+    {
+      cc->cb (cc->cb_cls);
+      cc->cb = NULL; /* only notify once! */
+    }
   }
 }
 
 
+/**
+ * Offer the current HELLO of P2 to P1.
+ *
+ * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
+ */
+static void
+offer_hello (void *cls);
+
+
 static void
 notify_disconnect (void *cls,
                    const struct GNUNET_PeerIdentity *peer)
 {
   struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
   char *p2_s;
   /* Find PeerContext */
   int no = 0;
   struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL;
-
-  if (NULL != p)
-  {
-    p2 = find_peer_context (p->tth,
-                            peer);
-    no = p->no;
-  }
-
-  if (p2 != NULL)
+  struct TRANSPORT_TESTING_SendJob *sj;
+  struct TRANSPORT_TESTING_SendJob *sjn;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  
+  p2 = find_peer_context (p->tth,
+                         peer);
+  no = p->no;
+  if (NULL != p2)
     GNUNET_asprintf (&p2_s,
                      "%u (`%s')",
                      p2->no,
@@ -147,12 +228,57 @@ notify_disconnect (void *cls,
        no,
        GNUNET_i2s (&p->id));
   GNUNET_free (p2_s);
-
-  if (NULL == p)
-    return;
+  /* notify about disconnect */
   if (NULL != p->nd)
     p->nd (p->cb_cls,
            peer);
+  if (NULL == p2)
+    return;
+  /* abort all transmissions this disconnected pair is involved in */
+  for (sj = tth->sj_head; NULL != sj; sj = sjn)
+  {
+    sjn = sj->next;
+    if ( ( (sj->sender == p2) &&
+          (sj->receiver == p) ) ||
+        ( (sj->receiver == p2) &&
+          (sj->sender == p) ) )
+    {
+      GNUNET_CONTAINER_DLL_remove (tth->sj_head,
+                                  tth->sj_tail,
+                                  sj);
+      GNUNET_TRANSPORT_notify_transmit_ready_cancel (sj->th);
+      GNUNET_free (sj);
+    }
+  }
+  /* update set connected flags for all requests */
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
+                                                   p2,
+                                                   &clear_p1c,
+                                                   NULL);
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
+                                                   p,
+                                                   &clear_p2c,
+                                                   NULL);
+  /* resume connectivity requests as necessary */
+  for (cc = tth->cc_head; NULL != cc; cc = cc->next)
+  {
+    if (GNUNET_NO == cc->connected)
+      continue;
+    if ( (GNUNET_YES != cc->p1_c) ||
+         (GNUNET_YES != cc->p2_c) )
+    {
+      cc->connected = GNUNET_NO;
+      /* start trying to connect */
+      if ( (NULL == cc->tct) &&
+          (NULL == cc->oh) )
+       cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
+                                           cc);
+      if (NULL == cc->ats_sh)
+       cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats,
+                                                     &p2->id,
+                                                     1);
+    }
+  }
 }
 
 
@@ -195,7 +321,7 @@ get_hello (void *cb_cls,
          p->no,
          GNUNET_i2s (&p->id));
     p->start_cb (p,
-                 p->cb_cls);
+                 p->start_cb_cls);
     p->start_cb = NULL;
   }
 }
@@ -209,8 +335,9 @@ get_hello (void *cb_cls,
  * @param rec receive callback
  * @param nc connect callback
  * @param nd disconnect callback
- * @param start_cb start callback
  * @param cb_cls closure for callback
+ * @param start_cb start callback
+ * @param start_cb_cls closure for callback
  * @return the peer context
  */
 struct GNUNET_TRANSPORT_TESTING_PeerContext *
@@ -220,8 +347,9 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth
                                      GNUNET_TRANSPORT_ReceiveCallback rec,
                                      GNUNET_TRANSPORT_NotifyConnect nc,
                                      GNUNET_TRANSPORT_NotifyDisconnect nd,
+                                    void *cb_cls,
                                      GNUNET_TRANSPORT_TESTING_StartCallback start_cb,
-                                     void *cb_cls)
+                                     void *start_cb_cls)
 {
   char *emsg = NULL;
   struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
@@ -240,11 +368,12 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth
   p->nc = nc;
   p->nd = nd;
   p->rec = rec;
-  p->start_cb = start_cb;
-  if (cb_cls != NULL)
+  if (NULL != cb_cls)
     p->cb_cls = cb_cls;
   else
     p->cb_cls = p;
+  p->start_cb = start_cb;
+  p->start_cb_cls = start_cb_cls;
   GNUNET_CONTAINER_DLL_insert (tth->p_head,
                                tth->p_tail,
                                p);
@@ -350,14 +479,17 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth
  *
  * @param p the peer
  * @param restart_cb callback to call when restarted
- * @param cb_cls callback closure
+ * @param restart_cb_cls callback closure
  * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR
  */
 int
 GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext *p,
                                        GNUNET_TRANSPORT_TESTING_StartCallback restart_cb,
-                                       void *cb_cls)
+                                       void *restart_cb_cls)
 {
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
   /* shutdown */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Stopping peer %u (`%s')\n",
@@ -373,6 +505,13 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_PeerConte
     GNUNET_TRANSPORT_disconnect (p->th);
     p->th = NULL;
   }
+  for (cc = p->tth->cc_head; NULL != cc; cc = ccn)
+  {
+    ccn = cc->next;
+    if ( (cc->p1 == p) ||
+         (cc->p2 == p) )
+      GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
+  }
   if (NULL != p->ats)
   {
     GNUNET_ATS_connectivity_done (p->ats);
@@ -406,7 +545,7 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_PeerConte
 
   GNUNET_assert (NULL == p->start_cb);
   p->start_cb = restart_cb;
-  p->cb_cls = cb_cls;
+  p->start_cb_cls = restart_cb_cls;
 
   p->th = GNUNET_TRANSPORT_connect (p->cfg,
                                     NULL,
@@ -433,7 +572,16 @@ void
 GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext *p)
 {
   struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
 
+  for (cc = tth->cc_head; NULL != cc; cc = ccn)
+  {
+    ccn = cc->next;
+    if ( (cc->p1 == p) ||
+         (cc->p2 == p) )
+      GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
+  }
   if (NULL != p->ghh)
   {
     GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
@@ -483,15 +631,6 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext
 }
 
 
-/**
- * Offer the current HELLO of P2 to P1.
- *
- * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
- */
-static void
-offer_hello (void *cls);
-
-
 /**
  * Function called after the HELLO was passed to the
  * transport service.