}
-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;
}
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);
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,
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);
+ }
+ }
}
p->no,
GNUNET_i2s (&p->id));
p->start_cb (p,
- p->cb_cls);
+ p->start_cb_cls);
p->start_cb = NULL;
}
}
* @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 *
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;
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);
*
* @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",
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);
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,
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);
}
-/**
- * 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.