X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Ftransport-testing.c;h=e3d4b7a9bdc9d34a07f3be7a94ac5157f8c74c4b;hb=ad1244d958b76cb249028c7ad87ff84df49293ff;hp=a2f91d761a35ea8f152e5223ef6cad03acc141ac;hpb=c0b81510ffe194dc662c3a6267d5e66a69873c4b;p=oweals%2Fgnunet.git diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c index a2f91d761..e3d4b7a9b 100644 --- a/src/transport/transport-testing.c +++ b/src/transport/transport-testing.c @@ -2,20 +2,18 @@ This file is part of GNUnet. Copyright (C) 2006, 2009, 2015, 2016 GNUnet e.V. - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ /** * @file transport-testing.c @@ -44,42 +42,117 @@ 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) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p1_c = GNUNET_YES; +} + + +static void +set_mq (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + struct GNUNET_MQ_Handle *mq = cls; + + cx->mq = mq; +} + + +static void +set_p2c (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p2_c = GNUNET_YES; +} + + +static void +clear_p1c (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p1_c = GNUNET_NO; +} + + +static void +clear_p2c (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p2_c = GNUNET_NO; +} + + +static void * notify_connect (void *cls, - const struct GNUNET_PeerIdentity *peer) + const struct GNUNET_PeerIdentity *peer, + struct GNUNET_MQ_Handle *mq) { 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; + int found; + void *ret; p2 = find_peer_context (p->tth, peer); if (NULL != p->nc) - p->nc (p->cb_cls, - peer); + ret = p->nc (p->cb_cls, + peer, + mq); + else + ret = NULL; - if (p2 != NULL) + if (NULL != p2) GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, @@ -94,45 +167,109 @@ 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) + /* update flags in connecting contexts */ + found = GNUNET_NO; + GNUNET_TRANSPORT_TESTING_find_connecting_context (p, + p2, + &set_p1c, + &found); + if (GNUNET_NO == found) + { + cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest); + cc->p1 = p; + cc->p2 = p2; 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) ) + GNUNET_CONTAINER_DLL_insert (tth->cc_head, + tth->cc_tail, + cc); + } + found = GNUNET_NO; + GNUNET_TRANSPORT_TESTING_find_connecting_context (p2, + p, + &set_p2c, + &found); + if (GNUNET_NO == found) { - cc->cb (cc->cb_cls); - GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc); + cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest); + cc->p1 = p2; + cc->p2 = p; + cc->p1_c = GNUNET_YES; + GNUNET_CONTAINER_DLL_insert (tth->cc_head, + tth->cc_tail, + cc); + } + GNUNET_TRANSPORT_TESTING_find_connecting_context (p, + p2, + &set_mq, + mq); + /* update set connected flag for all requests */ + for (cc = tth->cc_head; NULL != cc; cc = cc->next) + { + 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! */ + } } + return ret; } +/** + * 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) + const struct GNUNET_PeerIdentity *peer, + void *handler_cls) { 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; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; - if (NULL != p) - { - p2 = find_peer_context (p->tth, - peer); - no = p->no; - } - - if (p2 != NULL) + p2 = find_peer_context (p->tth, + peer); + no = p->no; + if (NULL != p2) GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, @@ -147,28 +284,47 @@ 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); -} - - -static void -notify_receive (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls; - - if (NULL == p) + peer, + handler_cls); + if (NULL == p2) return; - if (NULL != p->rec) - p->rec (p->cb_cls, - peer, - message); + /* clear MQ, it is now invalid */ + GNUNET_TRANSPORT_TESTING_find_connecting_context (p, + p2, + &set_mq, + NULL); + /* 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); + } + } } @@ -194,8 +350,7 @@ get_hello (void *cb_cls, "Peer %u (`%s') successfully started\n", p->no, GNUNET_i2s (&p->id)); - p->start_cb (p, - p->cb_cls); + p->start_cb (p->start_cb_cls); p->start_cb = NULL; } } @@ -206,26 +361,29 @@ get_hello (void *cb_cls, * @param tth the testing handle * @param cfgname configuration file * @param peer_id a unique number to identify the peer - * @param rec receive callback + * @param handlers functions for receiving messages * @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_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth, const char *cfgname, int peer_id, - GNUNET_TRANSPORT_ReceiveCallback rec, - GNUNET_TRANSPORT_NotifyConnect nc, - GNUNET_TRANSPORT_NotifyDisconnect nd, - GNUNET_TRANSPORT_TESTING_StartCallback start_cb, - void *cb_cls) + const struct GNUNET_MQ_MessageHandler *handlers, + GNUNET_TRANSPORT_NotifyConnecT nc, + GNUNET_TRANSPORT_NotifyDisconnecT nd, + void *cb_cls, + GNUNET_SCHEDULER_TaskCallback start_cb, + void *start_cb_cls) { char *emsg = NULL; struct GNUNET_TRANSPORT_TESTING_PeerContext *p; - struct GNUNET_PeerIdentity *dummy; + struct GNUNET_PeerIdentity dummy; + unsigned int i; if (GNUNET_NO == GNUNET_DISK_file_test (cfgname)) { @@ -239,12 +397,24 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth p->tth = tth; p->nc = nc; p->nd = nd; - p->rec = rec; - p->start_cb = start_cb; - if (cb_cls != NULL) + if (NULL != handlers) + { + for (i=0;NULL != handlers[i].cb;i++) ; + p->handlers = GNUNET_new_array (i + 1, + struct GNUNET_MQ_MessageHandler); + GNUNET_memcpy (p->handlers, + handlers, + i * sizeof (struct GNUNET_MQ_MessageHandler)); + } + if (NULL != cb_cls) p->cb_cls = cb_cls; else p->cb_cls = p; + p->start_cb = start_cb; + if (NULL != start_cb_cls) + p->start_cb_cls = start_cb_cls; + else + p->start_cb_cls = p; GNUNET_CONTAINER_DLL_insert (tth->p_head, tth->p_tail, p); @@ -311,14 +481,16 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth "Peer %u configured with identity `%s'\n", p->no, GNUNET_i2s_full (&p->id)); - - p->th = GNUNET_TRANSPORT_connect (p->cfg, - NULL, - p, - ¬ify_receive, - ¬ify_connect, - ¬ify_disconnect); - if (NULL == p->th) + p->tmh = GNUNET_TRANSPORT_manipulation_connect (p->cfg); + p->th = GNUNET_TRANSPORT_core_connect (p->cfg, + NULL, + handlers, + p, + ¬ify_connect, + ¬ify_disconnect, + NULL); + if ( (NULL == p->th) || + (NULL == p->tmh) ) { LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to transport service for peer `%s': `%s'\n", @@ -337,10 +509,11 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth GNUNET_TRANSPORT_TESTING_stop_peer (p); return NULL; } - p->ghh = GNUNET_TRANSPORT_get_hello (p->cfg, - &get_hello, + p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg, + GNUNET_TRANSPORT_AC_ANY, + &get_hello, p); - GNUNET_assert (p->ghh != NULL); + GNUNET_assert (NULL != p->ghh); return p; } @@ -350,14 +523,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) + GNUNET_SCHEDULER_TaskCallback restart_cb, + 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", @@ -365,14 +541,26 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_PeerConte GNUNET_i2s (&p->id)); if (NULL != p->ghh) { - GNUNET_TRANSPORT_get_hello_cancel (p->ghh); + GNUNET_TRANSPORT_hello_get_cancel (p->ghh); p->ghh = NULL; } if (NULL != p->th) { - GNUNET_TRANSPORT_disconnect (p->th); + GNUNET_TRANSPORT_core_disconnect (p->th); p->th = NULL; } + if (NULL != p->tmh) + { + GNUNET_TRANSPORT_manipulation_disconnect (p->tmh); + p->tmh = 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,17 +594,19 @@ 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->th = GNUNET_TRANSPORT_connect (p->cfg, - NULL, - p, - ¬ify_receive, - ¬ify_connect, - ¬ify_disconnect); + p->start_cb_cls = restart_cb_cls; + + p->th = GNUNET_TRANSPORT_core_connect (p->cfg, + NULL, + p->handlers, + p, + ¬ify_connect, + ¬ify_disconnect, + NULL); GNUNET_assert (NULL != p->th); p->ats = GNUNET_ATS_connectivity_init (p->cfg); - p->ghh = GNUNET_TRANSPORT_get_hello (p->cfg, + p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg, + GNUNET_TRANSPORT_AC_ANY, &get_hello, p); GNUNET_assert (NULL != p->ghh); @@ -433,15 +623,29 @@ 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); + GNUNET_TRANSPORT_hello_get_cancel (p->ghh); p->ghh = NULL; } + if (NULL != p->tmh) + { + GNUNET_TRANSPORT_manipulation_disconnect (p->tmh); + p->tmh = NULL; + } if (NULL != p->th) { - GNUNET_TRANSPORT_disconnect (p->th); + GNUNET_TRANSPORT_core_disconnect (p->th); p->th = NULL; } if (NULL != p->peer) @@ -472,6 +676,11 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext GNUNET_CONFIGURATION_destroy (p->cfg); p->cfg = NULL; } + if (NULL != p->handlers) + { + GNUNET_free (p->handlers); + p->handlers = NULL; + } GNUNET_CONTAINER_DLL_remove (tth->p_head, tth->p_tail, p); @@ -483,15 +692,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. @@ -564,6 +764,18 @@ GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_PeerCont { struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth; struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; + + ccn = NULL; + for (cc = tth->cc_head; NULL != cc; cc = cc->next) + { + if ( (cc->p1 == p1) && + (cc->p2 == p2) ) + { + ccn = cc; + break; + } + } cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest); cc->p1 = p1; @@ -573,6 +785,12 @@ GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_PeerCont cc->cb_cls = cls; else cc->cb_cls = cc; + if (NULL != ccn) + { + cc->p1_c = ccn->p1_c; + cc->p2_c = ccn->p2_c; + cc->connected = ccn->connected; + } GNUNET_CONTAINER_DLL_insert (tth->cc_head, tth->cc_tail, cc); @@ -637,6 +855,8 @@ GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth) struct GNUNET_TRANSPORT_TESTING_PeerContext *p; struct GNUNET_TRANSPORT_TESTING_PeerContext *t; + if (NULL == tth) + return; cc = tth->cc_head; while (NULL != cc) {