From 172ef59b934c067dd7ec8e72650e196c7ae2a04b Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Mon, 30 Nov 2020 18:08:25 +0900 Subject: -start TNG transport test logic --- src/transport/transport-testing2.c | 923 +++++++++++++++++++++++++++++++++++++ 1 file changed, 923 insertions(+) create mode 100644 src/transport/transport-testing2.c (limited to 'src/transport/transport-testing2.c') diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c new file mode 100644 index 000000000..ca338c52f --- /dev/null +++ b/src/transport/transport-testing2.c @@ -0,0 +1,923 @@ +/* + 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 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 + 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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @file transport-testing.c + * @brief testing lib for transport service + * @author Matthias Wachs + * @author Christian Grothoff + */ +#include "transport-testing2.h" + + +#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing", __VA_ARGS__) + + +static struct GNUNET_TRANSPORT_TESTING_PeerContext * +find_peer_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth, + const struct GNUNET_PeerIdentity *peer) +{ + struct GNUNET_TRANSPORT_TESTING_PeerContext *t; + + for (t = tth->p_head; NULL != t; t = t->next) + if (0 == memcmp (&t->id, + peer, + sizeof(struct GNUNET_PeerIdentity))) + return t; + return NULL; +} + + +/** + * 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 = ccn) + { + ccn = cc->next; + if ((cc->p1 == p1) && + (cc->p2 == p2)) + cb (cb_cls, + cc); + } +} + + +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, + 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) + ret = p->nc (p->cb_cls, + peer, + mq); + else + ret = NULL; + + if (NULL != p2) + GNUNET_asprintf (&p2_s, + "%u (`%s')", + p2->no, + GNUNET_i2s (&p2->id)); + else + GNUNET_asprintf (&p2_s, + "`%s'", + GNUNET_i2s (peer)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peers %s connected to peer %u (`%s')\n", + p2_s, + p->no, + GNUNET_i2s (&p->id)); + GNUNET_free (p2_s); + /* 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; + 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 = 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->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, + 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; + + p2 = find_peer_context (p->tth, + peer); + no = p->no; + if (NULL != p2) + GNUNET_asprintf (&p2_s, + "%u (`%s')", + p2->no, + GNUNET_i2s (&p2->id)); + else + GNUNET_asprintf (&p2_s, + "`%s'", + GNUNET_i2s (peer)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peers %s disconnected from peer %u (`%s')\n", + p2_s, + no, + GNUNET_i2s (&p->id)); + GNUNET_free (p2_s); + /* notify about disconnect */ + if (NULL != p->nd) + p->nd (p->cb_cls, + peer, + handler_cls); + if (NULL == p2) + return; + /* 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) + 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); + } + } +} + + +static void +hello_iter_cb (void *cb_cls, + const struct GNUNET_PEERSTORE_Record *record, + const char *emsg) +{ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls; + //Check record type et al? + p->hello = GNUNET_malloc (record->value_size); + memcpy (p->hello, record->value, record->value_size); + + GNUNET_PEERSTORE_iterate_cancel (p->pic); + if (NULL != p->start_cb) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer %u (`%s') successfully started\n", + p->no, + GNUNET_i2s (&p->id)); + p->start_cb (p->start_cb_cls); + p->start_cb = NULL; + } +} + + +/** + * Start a peer with the given configuration + * @param tth the testing handle + * @param cfgname configuration file + * @param peer_id a unique number to identify the peer + * @param handlers functions for receiving messages + * @param nc connect callback + * @param nd disconnect 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, + 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; + unsigned int i; + + if (GNUNET_NO == GNUNET_DISK_file_test (cfgname)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "File not found: `%s'\n", + cfgname); + return NULL; + } + + p = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_PeerContext); + p->tth = tth; + p->nc = nc; + p->nd = nd; + 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); + + /* Create configuration and call testing lib to modify it */ + p->cfg = GNUNET_CONFIGURATION_create (); + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_load (p->cfg, cfgname)); + if (GNUNET_SYSERR == + GNUNET_TESTING_configuration_create (tth->tl_system, + p->cfg)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s'\n", + cfgname); + GNUNET_CONFIGURATION_destroy (p->cfg); + GNUNET_free (p); + return NULL; + } + + p->no = peer_id; + /* Configure peer with configuration */ + p->peer = GNUNET_TESTING_peer_configure (tth->tl_system, + p->cfg, + p->no, + NULL, + &emsg); + if (NULL == p->peer) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s': `%s'\n", + cfgname, + emsg); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + GNUNET_free (emsg); + return NULL; + } + GNUNET_free (emsg); + if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s'\n", + cfgname); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + + memset (&dummy, + '\0', + sizeof(dummy)); + GNUNET_TESTING_peer_get_identity (p->peer, + &p->id); + if (0 == memcmp (&dummy, + &p->id, + sizeof(struct GNUNET_PeerIdentity))) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to obtain peer identity for peer %u\n", + p->no); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer %u configured with identity `%s'\n", + p->no, + GNUNET_i2s_full (&p->id)); + p->tmh = GNUNET_TRANSPORT_manipulation_connect (p->cfg); + p->th = GNUNET_TRANSPORT_core_connect (p->cfg, + NULL, + handlers, + p, + ¬ify_connect, + ¬ify_disconnect); + if ((NULL == p->th) || + (NULL == p->tmh)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to transport service for peer `%s': `%s'\n", + cfgname, + emsg); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + p->ats = GNUNET_ATS_connectivity_init (p->cfg); + if (NULL == p->ats) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to ATS service for peer `%s': `%s'\n", + cfgname, + emsg); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + p->pic = GNUNET_PEERSTORE_iterate (p->ph, + "transport", + &p->id, + GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY, + hello_iter_cb, + p); + GNUNET_assert (NULL != p->pic); + + return p; +} + + +/** + * Stops and restarts the given peer, sleeping (!) for 5s in between. + * + * @param p the peer + * @param restart_cb callback to call when restarted + * @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_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", + p->no, + GNUNET_i2s (&p->id)); + if (NULL != p->pic) + { + GNUNET_PEERSTORE_iterate_cancel (p->pic); + p->pic = NULL; + } + if (NULL != 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); + p->ats = NULL; + } + if (GNUNET_SYSERR == + GNUNET_TESTING_peer_stop (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to stop peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + return GNUNET_SYSERR; + } + + sleep (5); // YUCK! + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Restarting peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + /* restart */ + if (GNUNET_SYSERR == GNUNET_TESTING_peer_start (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to restart peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + return GNUNET_SYSERR; + } + + GNUNET_assert (NULL == p->start_cb); + p->start_cb = restart_cb; + p->start_cb_cls = restart_cb_cls; + + p->th = GNUNET_TRANSPORT_core_connect (p->cfg, + NULL, + p->handlers, + p, + ¬ify_connect, + ¬ify_disconnect); + GNUNET_assert (NULL != p->th); + p->ats = GNUNET_ATS_connectivity_init (p->cfg); + p->pic = GNUNET_PEERSTORE_iterate (p->ph, + "transport", + &p->id, + GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY, + hello_iter_cb, + p); + GNUNET_assert (NULL != p->pic); + return GNUNET_OK; +} + + +/** + * Shutdown the given peer + * + * @param p the peer + */ +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->pic) + { + GNUNET_PEERSTORE_iterate_cancel (p->pic); + p->pic = NULL; + } + if (NULL != p->tmh) + { + GNUNET_TRANSPORT_manipulation_disconnect (p->tmh); + p->tmh = NULL; + } + if (NULL != p->th) + { + GNUNET_TRANSPORT_core_disconnect (p->th); + p->th = NULL; + } + if (NULL != p->peer) + { + if (GNUNET_OK != + GNUNET_TESTING_peer_stop (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Testing lib failed to stop peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + } + GNUNET_TESTING_peer_destroy (p->peer); + p->peer = NULL; + } + if (NULL != p->ats) + { + GNUNET_ATS_connectivity_done (p->ats); + p->ats = NULL; + } + if (NULL != p->hello) + { + GNUNET_free (p->hello); + p->hello = NULL; + } + if (NULL != p->cfg) + { + 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); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer %u (`%s') stopped\n", + p->no, + GNUNET_i2s (&p->id)); + GNUNET_free (p); +} + + +/** + * Function called after the HELLO was passed to the + * transport service. + * FIXME maybe schedule the application_validate somehow + */ +/* +static void +hello_offered (void *cls) +{ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls; + + cc->oh = NULL; + cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + &offer_hello, + cc); +}*/ + + +/** + * Offer the current HELLO of P2 to P1. + * + * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest` + */ +static void +offer_hello (void *cls) +{ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p1 = cc->p1; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = cc->p2; + struct GNUNET_TIME_Absolute t; + enum GNUNET_NetworkType nt; + char *addr; + + cc->tct = NULL; + { + char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id)); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %s\n", + p1->no, + GNUNET_i2s (&p1->id), + p2->no, + p2_s, + cc->p2->hello); + GNUNET_free (p2_s); + } + + addr = GNUNET_HELLO_extract_address (cc->p2->hello, + cc->p2->hello_size, + &cc->p2->id, + &nt, + &t); + GNUNET_assert (NULL == addr); + GNUNET_TRANSPORT_application_validate (cc->p1->ah, + &cc->p2->id, + nt, + addr); + GNUNET_free (addr); +} + + +/** + * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message + * + * Remarks: start_peer's notify_connect callback can be called before. + * + * @param tth transport testing handle + * @param p1 peer 1 + * @param p2 peer 2 + * @param cb the callback to call when both peers notified that they are connected + * @param cls callback cls + * @return a connect request handle + */ +struct GNUNET_TRANSPORT_TESTING_ConnectRequest * +GNUNET_TRANSPORT_TESTING_connect_peers (struct + GNUNET_TRANSPORT_TESTING_PeerContext *p1, + struct + GNUNET_TRANSPORT_TESTING_PeerContext *p2, + GNUNET_SCHEDULER_TaskCallback cb, + void *cls) +{ + 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; + cc->p2 = p2; + cc->cb = cb; + if (NULL != cls) + 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); + cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello, + cc); + cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats, + &p2->id, + 1); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "New connect request %p\n", + cc); + return cc; +} + + +/** + * Cancel the request to connect two peers + * Tou MUST cancel the request if you stop the peers before the peers connected succesfully + * + * @param tth transport testing handle + * @param cc a connect request handle + */ +void +GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct + GNUNET_TRANSPORT_TESTING_ConnectRequest + *cc) +{ + struct GNUNET_TRANSPORT_TESTING_Handle *tth = cc->p1->tth; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Canceling connect request!\n"); + if (NULL != cc->tct) + { + GNUNET_SCHEDULER_cancel (cc->tct); + cc->tct = NULL; + } + if (NULL != cc->ats_sh) + { + GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh); + cc->ats_sh = NULL; + } + GNUNET_CONTAINER_DLL_remove (tth->cc_head, + tth->cc_tail, + cc); + GNUNET_free (cc); +} + + +/** + * Clean up the transport testing + * + * @param tth transport testing handle + */ +void +GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth) +{ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ct; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p; + struct GNUNET_TRANSPORT_TESTING_PeerContext *t; + + if (NULL == tth) + return; + cc = tth->cc_head; + while (NULL != cc) + { + ct = cc->next; + LOG (GNUNET_ERROR_TYPE_ERROR, + "Developer forgot to cancel connect request!\n"); + GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc); + cc = ct; + } + p = tth->p_head; + while (NULL != p) + { + t = p->next; + LOG (GNUNET_ERROR_TYPE_ERROR, + "Developer forgot to stop peer!\n"); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + p = t; + } + GNUNET_TESTING_system_destroy (tth->tl_system, + GNUNET_YES); + + GNUNET_free (tth); +} + + +/** + * Initialize the transport testing + * + * @return transport testing handle + */ +struct GNUNET_TRANSPORT_TESTING_Handle * +GNUNET_TRANSPORT_TESTING_init () +{ + struct GNUNET_TRANSPORT_TESTING_Handle *tth; + + tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_Handle); + tth->tl_system = GNUNET_TESTING_system_create ("transport-testing", + NULL, + NULL, + NULL); + if (NULL == tth->tl_system) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to initialize testing library!\n"); + GNUNET_free (tth); + return NULL; + } + return tth; +} + + +/* end of transport-testing.c */ -- cgit v1.2.3