This file is part of GNUnet.
Copyright (C) 2011, 2017 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.
+ 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 <http://www.gnu.org/licenses/>.
- 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.
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @file cadet/test_cadet.c
*/
#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
+/**
+ * How fast do we send messages?
+ */
+#define SEND_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10)
+
/**
* DIFFERENT TESTS TO RUN
*/
#define SPEED_ACK 4
#define SPEED_REL 8
#define P2P_SIGNAL 10
+#define REOPEN 11
/**
* Which test are we running?
*/
static struct GNUNET_SCHEDULER_Task *disconnect_task;
+/**
+ * Task called to reconnect peers.
+ */
+static struct GNUNET_SCHEDULER_Task *reconnect_task;
+
/**
* Task To perform tests
*/
end_time = GNUNET_TIME_absolute_get ();
total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
- FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
- FPRINTF (stderr, "Test time %s\n",
+ FPRINTF (stderr,
+ "\nResults of test \"%s\"\n",
+ test_name);
+ FPRINTF (stderr,
+ "Test time %s\n",
GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
- FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
- FPRINTF (stderr, "Test throughput: %f packets/s\n\n", total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
- GAUGER ("CADET", test_name,
+ FPRINTF (stderr,
+ "Test bandwidth: %f kb/s\n",
+ 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
+ FPRINTF (stderr,
+ "Test throughput: %f packets/s\n\n",
+ total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
+ GAUGER ("CADET",
+ test_name,
total_packets * 1000.0 / (total_time.rel_value_us / 1000),
"packets/s");
}
disconnect_cadet_peers (void *cls)
{
long line = (long) cls;
- unsigned int i;
disconnect_task = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"disconnecting cadet service of peers, called from line %ld\n",
line);
- for (i = 0; i < 2; i++)
+ for (unsigned int i = 0; i < 2; i++)
{
GNUNET_TESTBED_operation_done (t_op[i]);
}
static void
shutdown_task (void *cls)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Ending test.\n");
if (NULL != send_next_msg_task)
{
GNUNET_SCHEDULER_cancel (send_next_msg_task);
{
GNUNET_SCHEDULER_cancel (disconnect_task);
disconnect_task =
- GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__);
+ GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+ (void *) __LINE__);
}
}
* operation has executed successfully.
*/
static void
-stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
+stats_cont (void *cls,
+ struct GNUNET_TESTBED_Operation *op,
+ const char *emsg)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n",
- ka_sent, ka_received);
- if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1)))
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KA sent: %u, KA received: %u\n",
+ ka_sent,
+ ka_received);
+ if ((KEEPALIVE == test || REOPEN == test) &&
+ ((ka_sent < 2) || (ka_sent > ka_received + 1)))
{
GNUNET_break (0);
ok--;
if (NULL != disconnect_task)
GNUNET_SCHEDULER_cancel (disconnect_task);
- disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls);
+ disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+ cls);
}
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
static int
-stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer,
- const char *subsystem, const char *name, uint64_t value,
+stats_iterator (void *cls,
+ const struct GNUNET_TESTBED_Peer *peer,
+ const char *subsystem,
+ const char *name,
+ uint64_t value,
int is_persistent)
{
static const char *s_sent = "# keepalives sent";
}
+/**
+ * Send a message on the channel with the appropriate size and payload.
+ *
+ * Update the appropriate *_sent counter.
+ *
+ * @param channel Channel to send the message on.
+ */
+static void
+send_test_message (struct GNUNET_CADET_Channel *channel);
+
+/**
+ * Check if payload is sane (size contains payload).
+ *
+ * @param cls should match #ch
+ * @param message The actual message.
+ * @return #GNUNET_OK to keep the channel open,
+ * #GNUNET_SYSERR to close it (signal serious error).
+ */
+static int
+check_data (void *cls,
+ const struct GNUNET_MessageHeader *message);
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect(), peer number)
+ * @param message the actual message
+ */
+static void
+handle_data (void *cls,
+ const struct GNUNET_MessageHeader *message);
+
+/**
+ * Function called whenever an MQ-channel is destroyed, even if the destruction
+ * was requested by #GNUNET_CADET_channel_destroy.
+ * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
+ *
+ * It should clean up any associated state, including cancelling any pending
+ * transmission on this channel.
+ *
+ * @param cls Channel closure (channel wrapper).
+ * @param channel Connection to the other end (henceforth invalid).
+ */
+static void
+disconnect_handler (void *cls,
+ const struct GNUNET_CADET_Channel *channel);
+
+
+/**
+ * Task to reconnect to other peer.
+ *
+ * @param cls Closure (line from which the task was scheduled).
+ */
+static void
+reconnect_op (void *cls)
+{
+ struct GNUNET_MQ_MessageHandler handlers[] = {
+ GNUNET_MQ_hd_var_size (data,
+ GNUNET_MESSAGE_TYPE_DUMMY,
+ struct GNUNET_MessageHeader,
+ NULL),
+ GNUNET_MQ_handler_end ()
+ };
+ long l = (long) cls;
+ struct CadetTestChannelWrapper *ch;
+ enum GNUNET_CADET_ChannelOption flags;
+
+ reconnect_task = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "reconnecting from line %ld\n",
+ l);
+ if (NULL != outgoing_ch)
+ {
+ GNUNET_CADET_channel_destroy (outgoing_ch);
+ outgoing_ch = NULL;
+ }
+ flags = GNUNET_CADET_OPTION_DEFAULT;
+ ch = GNUNET_new (struct CadetTestChannelWrapper);
+ outgoing_ch = GNUNET_CADET_channel_create (h1,
+ ch,
+ p_id[1],
+ &port,
+ flags,
+ NULL,
+ &disconnect_handler,
+ handlers);
+ ch->ch = outgoing_ch;
+ send_test_message (outgoing_ch);
+}
+
+/**
+ * Function called whenever an MQ-channel is destroyed, even if the destruction
+ * was requested by #GNUNET_CADET_channel_destroy.
+ * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
+ *
+ * It should clean up any associated state, including cancelling any pending
+ * transmission on this channel.
+ *
+ * @param cls Channel closure (channel wrapper).
+ * @param channel Connection to the other end (henceforth invalid).
+ */
+static void
+disconnect_handler (void *cls,
+ const struct GNUNET_CADET_Channel *channel)
+{
+ struct CadetTestChannelWrapper *ch_w = cls;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Channel disconnected at %d\n",
+ ok);
+ GNUNET_assert (ch_w->ch == channel);
+ if (channel == incoming_ch)
+ {
+ ok++;
+ incoming_ch = NULL;
+ }
+ else if (outgoing_ch == channel)
+ {
+ if (P2P_SIGNAL == test)
+ {
+ ok++;
+ }
+ outgoing_ch = NULL;
+ }
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Unknown channel! %p\n",
+ channel);
+ if (NULL != disconnect_task && REOPEN != test)
+ {
+ GNUNET_SCHEDULER_cancel (disconnect_task);
+ disconnect_task =
+ GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
+ (void *) __LINE__);
+ }
+ else if (NULL != reconnect_task && REOPEN == test)
+ {
+ GNUNET_SCHEDULER_cancel (reconnect_task);
+ reconnect_task =
+ GNUNET_SCHEDULER_add_now (&reconnect_op,
+ (void *) __LINE__);
+ }
+ GNUNET_free (ch_w);
+}
+
/**
* Abort test: schedule disconnect and shutdown immediately
if (NULL != disconnect_task)
{
GNUNET_SCHEDULER_cancel (disconnect_task);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Aborting test from %ld\n",
+ line);
disconnect_task =
- GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line);
+ GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+ (void *) line);
}
}
{
payload = data_sent;
}
+ else if (REOPEN == test)
+ {
+ payload = data_sent;
+ data_sent++;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending DATA %u [%d bytes]\n",
+ data_sent, size);
+ }
else
{
GNUNET_assert (0);
GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
}
+
/**
* Task to request a new data transmission in a SPEED test, without waiting
* for previous messages to be sent/arrrive.
struct GNUNET_CADET_Channel *channel;
send_next_msg_task = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending next message: %d\n",
+ data_sent);
channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
GNUNET_assert (NULL != channel);
"Scheduling message %d\n",
data_sent + 1);
send_next_msg_task =
- GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS,
- &send_next_msg,
- NULL);
+ GNUNET_SCHEDULER_add_delayed (SEND_INTERVAL,
+ &send_next_msg,
+ NULL);
}
}
if (NULL != disconnect_task)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- " reschedule timeout every 10 messages\n");
+ "reschedule timeout every 10 messages\n");
GNUNET_SCHEDULER_cancel (disconnect_task);
disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
&gather_stats_and_exit,
* #GNUNET_SYSERR to close it (signal serious error).
*/
static int
-check_data (void *cls, const struct GNUNET_MessageHeader *message)
+check_data (void *cls,
+ const struct GNUNET_MessageHeader *message)
{
- if (sizeof (struct GNUNET_MessageHeader) >= ntohs (message->size))
- return GNUNET_SYSERR;
return GNUNET_OK; /* all is well-formed */
}
* @param message the actual message
*/
static void
-handle_data (void *cls, const struct GNUNET_MessageHeader *message)
+handle_data (void *cls,
+ const struct GNUNET_MessageHeader *message)
{
struct CadetTestChannelWrapper *ch = cls;
struct GNUNET_CADET_Channel *channel = ch->ch;
if (channel == outgoing_ch)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message.\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Root client got a message.\n");
}
else if (channel == incoming_ch)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client got a message.\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Leaf client got a message.\n");
}
else
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown channel %p.\n", channel);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unknown channel %p.\n",
+ channel);
GNUNET_assert (0);
}
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ " ok: (%d/%d)\n",
+ ok,
+ ok_goal);
data = (uint32_t *) &message[1];
payload = ntohl (*data);
if (payload == *counter)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ " payload as expected: %u\n",
+ payload);
}
else
{
if (SPEED == test)
{
GNUNET_assert (incoming_ch == channel);
- send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL);
+ send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg,
+ NULL);
return;
}
}
* received on the @a channel.
*/
static void *
-connect_handler (void *cls, struct GNUNET_CADET_Channel *channel,
+connect_handler (void *cls,
+ struct GNUNET_CADET_Channel *channel,
const struct GNUNET_PeerIdentity *source)
{
struct CadetTestChannelWrapper *ch;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Incoming channel from %s to %ld: %p\n",
- GNUNET_i2s (source), peer, channel);
+ GNUNET_i2s (source),
+ peer,
+ channel);
ok++;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ " ok: %d\n",
+ ok);
if (peer == peers_requested - 1)
{
if (NULL != incoming_ch)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Duplicate incoming channel for client %lu\n", (long) cls);
+ "Duplicate incoming channel for client %lu\n",
+ (long) cls);
GNUNET_assert (0);
}
incoming_ch = channel;
else
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Incoming channel for unexpected peer #%lu\n", (long) cls);
+ "Incoming channel for unexpected peer #%lu\n",
+ (long) cls);
GNUNET_assert (0);
}
- if (NULL != disconnect_task)
+ if (NULL != disconnect_task && REOPEN != test)
{
GNUNET_SCHEDULER_cancel (disconnect_task);
disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
&gather_stats_and_exit,
(void *) __LINE__);
}
+ else if ((NULL != disconnect_task) && (REOPEN == test))
+ {
+ GNUNET_SCHEDULER_cancel (disconnect_task);
+ disconnect_task = GNUNET_SCHEDULER_add_delayed (
+ GNUNET_TIME_relative_multiply (short_time, 2),
+ &gather_stats_and_exit,
+ (void *) __LINE__);
+ }
+
+ if ((NULL != reconnect_task) && (REOPEN == test))
+ {
+ GNUNET_SCHEDULER_cancel (reconnect_task);
+ reconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
+ &reconnect_op,
+ (void *) __LINE__);
+ }
/* TODO: cannot return channel as-is, in order to unify the data handlers */
ch = GNUNET_new (struct CadetTestChannelWrapper);
}
-/**
- * Function called whenever an MQ-channel is destroyed, even if the destruction
- * was requested by #GNUNET_CADET_channel_destroy.
- * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
- *
- * It should clean up any associated state, including cancelling any pending
- * transmission on this channel.
- *
- * @param cls Channel closure (channel wrapper).
- * @param channel Connection to the other end (henceforth invalid).
- */
-static void
-disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel)
-{
- struct CadetTestChannelWrapper *ch_w = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel disconnected\n");
- GNUNET_assert (ch_w->ch == channel);
- if (channel == incoming_ch)
- {
- ok++;
- incoming_ch = NULL;
- }
- else if (outgoing_ch == channel
- )
- {
- if (P2P_SIGNAL == test)
- {
- ok++;
- }
- outgoing_ch = NULL;
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown channel! %p\n", channel);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-
- if (NULL != disconnect_task)
- {
- GNUNET_SCHEDULER_cancel (disconnect_task);
- disconnect_task =
- GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__);
- }
-}
-
-
/**
* START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
*
enum GNUNET_CADET_ChannelOption flags;
test_task = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test: %s\n", test_name);
if (NULL != disconnect_task)
{
GNUNET_SCHEDULER_cancel (disconnect_task);
if (KEEPALIVE == test)
return; /* Don't send any data. */
-
data_received = 0;
data_sent = 0;
ack_received = 0;
"Sending data initializer on channel %p...\n",
outgoing_ch);
send_test_message (outgoing_ch);
+ if (REOPEN == test)
+ {
+ reconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
+ &reconnect_op,
+ (void *) __LINE__);
+ GNUNET_SCHEDULER_cancel (disconnect_task);
+ disconnect_task = GNUNET_SCHEDULER_add_delayed (
+ GNUNET_TIME_relative_multiply (short_time, 2),
+ &gather_stats_and_exit,
+ (void *) __LINE__);
+ }
+
}
* NULL if the operation is successfull
*/
static void
-pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
- const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg)
+pi_cb (void *cls,
+ struct GNUNET_TESTBED_Operation *op,
+ const struct GNUNET_TESTBED_PeerInformation *pinfo,
+ const char *emsg)
{
long i = (long) cls;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i);
-
- if ((NULL == pinfo) || (NULL != emsg))
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ID callback for %ld\n",
+ i);
+ if ( (NULL == pinfo) ||
+ (NULL != emsg) )
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "pi_cb: %s\n",
+ emsg);
abort_test (__LINE__);
return;
}
p_id[i] = pinfo->result.id;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i]));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "id: %s\n",
+ GNUNET_i2s (p_id[i]));
p_ids++;
if (p_ids < 2)
return;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got all IDs, starting test\n");
test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
}
disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
&disconnect_cadet_peers,
(void *) __LINE__);
- GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
GNUNET_TESTBED_PIT_IDENTITY,
&pi_cb,
"short_time",
gettext_noop ("set short timeout"),
&short_time),
-
GNUNET_GETOPT_option_uint ('m',
"messages",
"NUM_MESSAGES",
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "5 PEER LINE\n");
peers_requested = 5;
}
+ else if (strstr (argv[0], "_6_") != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "6 PEER LINE\n");
+ peers_requested = 6;
+ }
else
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SIZE UNKNOWN, USING 2\n");
*/
ok_goal = 2;
}
+ else if (strstr (argv[0], "_reopen") != NULL)
+ {
+ test = REOPEN;
+ test_name = "reopen";
+ ///* Test is supposed to generate the following callbacks:
+ // * 1 incoming channel (@dest)
+ // * [wait]
+ // * 1 received channel destroy (@dest)
+ // */
+ ok_goal = 7;
+ }
else
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");