if (NULL != GNUNET_CONTAINER_multihashmap_get (h->peers,
&peer->hashPubKey))
- return NULL; /* Already connected, means callback should have happened already! */
-
+ {
+#if DEBUG_CORE
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peers are already connected!\n");
+#endif
+ return NULL;
+ }
cm = GNUNET_malloc (sizeof (struct ControlMessage) +
sizeof (struct ConnectMessage));
msg = (struct GNUNET_MessageHeader *)buf;
msg->size = htons (msize);
- msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS);
if (peer != NULL)
- memcpy(&msg[1], peer, sizeof(struct GNUNET_PeerIdentity));
+ {
+ msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED);
+ memcpy(&msg[1], peer, sizeof(struct GNUNET_PeerIdentity));
+ }
+ else
+ msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS);
return msize;
}
GNUNET_YES,
&transmit_request,
peer);
-
+ GNUNET_assert(request_context->th != NULL);
GNUNET_CLIENT_receive(client, &receive_info, request_context, GNUNET_TIME_relative_get_forever());
return GNUNET_OK;
}
{
struct GNUNET_MessageHeader done_msg;
struct GNUNET_SERVER_TransmitContext *tc;
- struct GNUNET_PeerIdentity *peer;
int msize;
/* notify new client about existing neighbours */
tc = GNUNET_SERVER_transmit_context_create (client);
if (msize == sizeof(struct GNUNET_MessageHeader))
GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, tc);
- else if (msize == sizeof(struct GNUNET_MessageHeader) + sizeof(struct GNUNET_PeerIdentity))
- {
- peer = (struct GNUNET_PeerIdentity *)&message[1];
- GNUNET_CONTAINER_multihashmap_get_multiple(neighbours, &peer->hashPubKey, &queue_connect_message, tc);
- }
else
GNUNET_break(0);
GNUNET_TIME_UNIT_FOREVER_REL);
}
+/**
+ * Handle CORE_ITERATE_PEERS request.
+ *
+ * @param cls unused
+ * @param client client sending the iteration request
+ * @param message iteration request message
+ */
+static void
+handle_client_have_peer (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+
+{
+ struct GNUNET_MessageHeader done_msg;
+ struct GNUNET_SERVER_TransmitContext *tc;
+ struct GNUNET_PeerIdentity *peer;
+ int msize;
+ /* notify new client about existing neighbours */
+
+ msize = ntohs(message->size);
+ tc = GNUNET_SERVER_transmit_context_create (client);
+
+ peer = (struct GNUNET_PeerIdentity *)&message[1];
+ GNUNET_CONTAINER_multihashmap_get_multiple(neighbours, &peer->hashPubKey, &queue_connect_message, tc);
+
+ done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+ done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
+ GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
+ GNUNET_SERVER_transmit_context_run (tc,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
/**
* Handle REQUEST_INFO request.
if ( (GNUNET_YES == n->is_connected) ||
(n->th != NULL) )
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Core received `%s' request for `%4s', already connected!\n",
- "REQUEST_CONNECT",
- GNUNET_i2s (&cm->peer));
if (GNUNET_YES == n->is_connected)
GNUNET_STATISTICS_update (stats,
gettext_noop ("# connection requests ignored (already connected)"),
1,
GNUNET_NO);
+#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Core received `%s' request for `%4s', will try to establish connection\n",
"REQUEST_CONNECT",
GNUNET_i2s (&cm->peer));
+#endif
/* ask transport to connect to the peer */
n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
{&handle_client_iterate_peers, NULL,
GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
sizeof (struct GNUNET_MessageHeader)},
+ {&handle_client_have_peer, NULL,
+ GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED,
+ sizeof (struct GNUNET_MessageHeader) + sizeof(struct GNUNET_PeerIdentity)},
{&handle_client_request_info, NULL,
GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
sizeof (struct RequestInfoMessage)},
#include "gnunet_dht_service.h"
#include "dhtlog.h"
#include "dht.h"
+#include "gauger.h"
/* Specific DEBUG hack, do not use normally (may leak memory, segfault, or eat children.) */
-#define ONLY_TESTING GNUNET_YES
+#define ONLY_TESTING GNUNET_NO
/* DEFINES */
#define VERBOSE GNUNET_NO
*/
static unsigned long long gets_completed;
+/**
+ * Total number of items to attempt to get.
+ */
+static unsigned long long cumulative_num_gets;
+
+/**
+ * How many gets are done?
+ */
+static unsigned long long cumulative_successful_gets;
+
/**
* How many gets failed?
*/
{
timeout = GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime);
}
- GNUNET_TESTING_daemons_connect(d1, d2, timeout, DEFAULT_RECONNECT_ATTEMPTS, NULL, NULL);
+ GNUNET_TESTING_daemons_connect(d1, d2, timeout, DEFAULT_RECONNECT_ATTEMPTS, GNUNET_YES, NULL, NULL);
}
if (GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime).rel_value > 0)
return GNUNET_YES;
if (tc->reason == GNUNET_SCHEDULER_REASON_TIMEOUT)
gets_failed++;
+ else
+ cumulative_successful_gets++;
+
GNUNET_assert(test_get->get_handle != NULL);
GNUNET_DHT_get_stop(test_get->get_handle);
test_get->get_handle = NULL;
GNUNET_assert(test_get->dht_handle != NULL);
outstanding_gets++;
+ cumulative_num_gets++;
/* Insert the data at the first peer */
test_get->get_handle = GNUNET_DHT_get_start(test_get->dht_handle,
get_delay,
(second_daemon == repeat_connect_peer2))
{
if (emsg != NULL) /* Peers failed to connect again! */
- return;
+ {
+ GNUNET_assert(repeat_connect_task == GNUNET_SCHEDULER_NO_TASK);
+ repeat_connect_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 60), &repeat_connect, NULL);
+ return;
+ }
else /* Repeat peers actually connected! */
{
if (repeat_connect_task != GNUNET_SCHEDULER_NO_TASK)
}
#endif
}
-#if ONLY_TESTING
- else if (repeat_connect_mode == GNUNET_YES)
- {
- repeat_connect_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 60), &repeat_connect, NULL);
- }
-#endif
if (emsg == NULL)
{
}
#if ONLY_TESTING
- if (repeat_connect_mode == GNUNET_YES)
+ if ((repeat_connect_mode == GNUNET_YES) )
return;
#endif
dhtlog_handle->insert_topology(expected_connections);
}
+
+ total_duration = GNUNET_TIME_absolute_get_difference (connect_start_time,
+ GNUNET_TIME_absolute_get()).rel_value / 1000;
+ failed_conns_per_sec_total = (double)failed_connections / total_duration;
+ conns_per_sec_total = (double)total_connections / total_duration;
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Overall connection info --- Total: %u, Total Failed %u/s\n",
+ total_connections, failed_connections);
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Overall connection info --- Total: %.2f/s, Total Failed %.2f/s\n",
+ conns_per_sec_total, failed_conns_per_sec_total);
+ /** Comment out until gauger is ready */
+ /**
+ GNUNET_asprintf(&temp_conn_string, "dht_peer_connection_speed");
+ GNUNET_asprintf(&temp_failed_conn_string, "dht_peer_failed_connection_speed");
+
+ GAUGER_COUNTER(temp_conn_string, conns_per_sec_total, trial_to_run, DATE);
+ GAUGER_COUNTER(temp_failed_conn_string, failed_conns_per_sec_total, trial_to_run, DATE);
+
+ GNUNET_free(temp_conn_string);
+ GNUNET_free(temp_failed_conn_string);
+ */
+
GNUNET_SCHEDULER_cancel (die_task);
if ((GNUNET_YES == dhtlog_minimal) && (NULL != dhtlog_handle))
if (GNUNET_YES == consider_peer (&new_peer))
{
increment_stats (STAT_HELLOS_PROVIDED);
- GNUNET_TRANSPORT_offer_hello (transport_handle, hello_msg);
+ GNUNET_TRANSPORT_offer_hello (transport_handle, hello_msg, NULL, NULL);
GNUNET_CORE_peer_request_connect (coreAPI,
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 5),
if (GNUNET_YES == consider_peer (&peer_id))
{
increment_stats (STAT_HELLOS_PROVIDED);
- GNUNET_TRANSPORT_offer_hello (transport_handle, other_hello);
+ GNUNET_TRANSPORT_offer_hello (transport_handle, other_hello, NULL, NULL);
GNUNET_CORE_peer_request_connect (coreAPI,
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 5),
daemon2->daemon,
timeout,
CONNECT_ATTEMPTS,
+ GNUNET_YES,
¬ify_connection,
ncc);
}
1,
GNUNET_NO);
stat_hellos_obtained++;
- GNUNET_TRANSPORT_offer_hello (transport, msg);
+ GNUNET_TRANSPORT_offer_hello (transport, msg, NULL, NULL);
}
else
{
*/
#define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END 79
+/**
+ * Check whether a given peer is currently connected to CORE.
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED 80
+
/**
* Session key exchange between peers.
*/
-#define GNUNET_MESSAGE_TYPE_CORE_SET_KEY 80
+#define GNUNET_MESSAGE_TYPE_CORE_SET_KEY 81
/**
* Encapsulation for an encrypted message between peers.
*/
-#define GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE 81
+#define GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE 82
/**
* Check that other peer is alive (challenge).
*/
-#define GNUNET_MESSAGE_TYPE_CORE_PING 82
+#define GNUNET_MESSAGE_TYPE_CORE_PING 83
/**
* Confirmation that other peer is alive.
*/
-#define GNUNET_MESSAGE_TYPE_CORE_PONG 83
+#define GNUNET_MESSAGE_TYPE_CORE_PONG 84
/**
* Request by the other peer to terminate the connection.
*/
-#define GNUNET_MESSAGE_TYPE_CORE_HANGUP 84
+#define GNUNET_MESSAGE_TYPE_CORE_HANGUP 85
/**
* Message sent by datastore client on join.
*/
SP_START_CORE,
+ /**
+ * CORE is up, now make sure we get the HELLO for this peer.
+ */
+ SP_GET_HELLO,
+
/**
* Core has notified us that we've established a connection to the service.
* The main FSM halts here and waits to be moved to UPDATE or CLEANUP.
* allowed to take?
* @param max_connect_attempts how many times should we try to reconnect
* (within timeout)
+ * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume
+ * the HELLO has already been exchanged
* @param cb function to call at the end
* @param cb_cls closure for cb
*/
-void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
- struct GNUNET_TESTING_Daemon *d2,
- struct GNUNET_TIME_Relative timeout,
- unsigned int max_connect_attempts,
- GNUNET_TESTING_NotifyConnection cb,
- void *cb_cls);
+void
+GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
+ struct GNUNET_TESTING_Daemon *d2,
+ struct GNUNET_TIME_Relative timeout,
+ unsigned int max_connect_attempts,
+ int send_hello,
+ GNUNET_TESTING_NotifyConnection cb,
+ void *cb_cls);
/**
* Offer the transport service the HELLO of another peer. Note that
* the transport service may just ignore this message if the HELLO is
- * malformed or useless due to our local configuration. If the HELLO
- * is working, we should add it to PEERINFO.
+ * malformed or useless due to our local configuration.
*
* @param handle connection to transport service
* @param hello the hello message
+ * @param cont continuation to call when HELLO has been sent
+ * @param cls closure for continuation
+ *
*/
void
GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle,
- const struct GNUNET_MessageHeader *hello);
+ const struct GNUNET_MessageHeader *hello,
+ GNUNET_SCHEDULER_Task cont,
+ void *cls);
/**
char *connect_topology_option_str;
char *connect_topology_option_modifier_string;
unsigned long long temp_settle;
+ unsigned long long max_outstanding_connections;
ok = 1;
dotOutFile = fopen (dotOutFileName, "w");
return;
}
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "max_outstanding_connections",
+ &max_outstanding_connections))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", "testing", "max_outstanding_connections");
+ return;
+ }
+
if (GNUNET_SYSERR ==
GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
&num_peers))
GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
pg = GNUNET_TESTING_daemons_start (cfg,
peers_left,
- peers_left / 2,
+ max_outstanding_connections,
peers_left,
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
#include "gnunet_hello_lib.h"
#define DEBUG_TESTING GNUNET_NO
-#define DEBUG_TESTING_RECONNECT GNUNET_NO
+#define DEBUG_TESTING_RECONNECT GNUNET_YES
/**
* How long do we wait after starting gnunet-service-arm
process_hello (void *cls, const struct GNUNET_MessageHeader *message)
{
struct GNUNET_TESTING_Daemon *daemon = cls;
+ GNUNET_TESTING_NotifyDaemonRunning cb;
+
int msize;
if (daemon == NULL)
return;
+ GNUNET_assert (daemon->phase == SP_GET_HELLO);
+
+ cb = daemon->cb;
+ daemon->cb = NULL;
+ if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */
+ GNUNET_SCHEDULER_cancel(daemon->task);
+
if (daemon->server != NULL)
{
#if DEBUG_TESTING
GNUNET_TRANSPORT_disconnect (daemon->th);
daemon->th = NULL;
}
+ daemon->phase = SP_START_DONE;
+ if (NULL != cb) /* FIXME: what happens when this callback calls GNUNET_TESTING_daemon_stop? */
+ cb (daemon->cb_cls, &daemon->id, daemon->cfg, daemon, NULL);
}
+static void
+start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
/**
* Function called after GNUNET_CORE_connect has succeeded
* (or failed for good). Note that the private key of the
const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
{
struct GNUNET_TESTING_Daemon *d = cls;
- GNUNET_TESTING_NotifyDaemonRunning cb;
GNUNET_assert (d->phase == SP_START_CORE);
- d->phase = SP_START_DONE;
- cb = d->cb;
- d->cb = NULL;
+ d->phase = SP_GET_HELLO;
+
if (server == NULL)
{
d->server = NULL;
GNUNET_TIME_absolute_get_remaining
(d->max_timeout), d->dead_cb,
d->dead_cb_cls, GNUNET_YES, GNUNET_NO);
- else if (NULL != cb)
- cb (d->cb_cls, NULL, d->cfg, d,
+ else if (NULL != d->cb)
+ d->cb (d->cb_cls, NULL, d->cfg, d,
_("Failed to connect to core service\n"));
return;
}
d->server = server;
d->running = GNUNET_YES;
- if (NULL != cb) /* FIXME: what happens when this callback calls GNUNET_TESTING_daemon_stop? */
- cb (d->cb_cls, my_identity, d->cfg, d, NULL);
-
if (GNUNET_NO == d->running)
{
#if DEBUG_TESTING
#endif
GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d);
+ /* wait some more */
+ if (d->task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel(d->task);
+ d->task
+ = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT,
+ &start_fsm, d);
}
(NULL == d->hostname)
? _("`gnunet-arm' does not seem to terminate.\n")
: _("`ssh' does not seem to terminate.\n"));
+ GNUNET_CONFIGURATION_destroy (d->cfg);
+ GNUNET_free (d->cfgfile);
+ GNUNET_free_non_null (d->hostname);
+ GNUNET_free_non_null (d->username);
GNUNET_free(d->proc);
+ GNUNET_free(d);
return;
}
/* wait some more */
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Calling CORE_connect\n");
#endif
+ /* Fall through */
+ case SP_START_CORE:
+ if (d->server != NULL)
+ GNUNET_CORE_disconnect(d->server);
+
+ if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value ==
+ 0)
+ {
+ cb = d->cb;
+ d->cb = NULL;
+ if (NULL != cb)
+ cb (d->cb_cls,
+ NULL,
+ d->cfg,
+ d,
+ _("Unable to connect to CORE service for peer!\n"));
+ GNUNET_CONFIGURATION_destroy (d->cfg);
+ GNUNET_free (d->cfgfile);
+ GNUNET_free_non_null (d->hostname);
+ GNUNET_free_non_null (d->username);
+ GNUNET_free (d);
+ return;
+ }
d->server = GNUNET_CORE_connect (d->cfg, 1,
-#if NO_MORE_TIMEOUT_FIXME
- ARM_START_WAIT,
-#endif
d,
&testing_init,
NULL, NULL, NULL,
NULL, GNUNET_NO,
NULL, GNUNET_NO, no_handlers);
+ d->task
+ = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_CONSTANTS_SERVICE_RETRY, 2),
+ &start_fsm, d);
break;
- case SP_START_CORE:
- GNUNET_break (0);
+ case SP_GET_HELLO:
+ if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value ==
+ 0)
+ {
+ if (d->server != NULL)
+ GNUNET_CORE_disconnect(d->server);
+ if (d->th != NULL)
+ GNUNET_TRANSPORT_disconnect(d->th);
+ cb = d->cb;
+ d->cb = NULL;
+ if (NULL != cb)
+ cb (d->cb_cls,
+ NULL,
+ d->cfg,
+ d,
+ _("Unable to get HELLO for peer!\n"));
+ GNUNET_CONFIGURATION_destroy (d->cfg);
+ GNUNET_free (d->cfgfile);
+ GNUNET_free_non_null (d->hostname);
+ GNUNET_free_non_null (d->username);
+ GNUNET_free (d);
+ return;
+ }
+ if (d->hello != NULL)
+ return;
+ GNUNET_assert(d->task == GNUNET_SCHEDULER_NO_TASK);
+ d->task
+ = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_CONSTANTS_SERVICE_RETRY, 2),
+ &start_fsm, d);
break;
case SP_START_DONE:
GNUNET_break (0);
*/
void *cb_cls;
- /**
- * When should this operation be complete (or we must trigger
- * a timeout).
- */
- struct GNUNET_TIME_Absolute timeout;
-
/**
* The relative timeout from whence this connect attempt was
* started. Allows for reconnect attempts.
* Maximum number of connect attempts, will retry connection
* this number of times on failures.
*/
- unsigned int max_connect_attempts;
+ unsigned int connect_attempts;
/**
* Hello timeout task
*/
int connected;
+ /**
+ * When connecting, do we need to send the HELLO?
+ */
+ int send_hello;
+
/**
* The distance between the two connected peers
*/
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct ConnectContext *ctx = cls;
- struct GNUNET_TIME_Relative remaining;
-
ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_CORE_peer_request_connect_cancel (ctx->connect_request_handle);
ctx->connect_request_handle = NULL;
}
+
if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
{
if (ctx->d1th != NULL)
ctx->d2core = NULL;
#endif
ctx->d1core = NULL;
-
GNUNET_free (ctx);
return;
}
- remaining = GNUNET_TIME_absolute_get_remaining (ctx->timeout);
+ if (ctx->d1th != NULL)
+ GNUNET_TRANSPORT_disconnect (ctx->d1th);
+ ctx->d1th = NULL;
+ if (ctx->d1core != NULL)
+ GNUNET_CORE_disconnect (ctx->d1core);
+ ctx->d1core = NULL;
if (ctx->connected == GNUNET_YES)
{
ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2, NULL);
}
}
- else if (remaining.rel_value > 0)
+ else if (ctx->connect_attempts > 0)
{
- if (ctx->d1core != NULL)
- {
- GNUNET_CORE_disconnect (ctx->d1core);
- ctx->d1core = NULL;
- }
ctx->d1core_ready = GNUNET_NO;
#if CONNECT_CORE2
if (ctx->d2core != NULL)
ctx->d2core = NULL;
}
#endif
-
- if (ctx->d1th != NULL)
- {
- GNUNET_TRANSPORT_disconnect (ctx->d1th);
- ctx->d1th = NULL;
- }
GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx);
return;
}
}
}
- if (ctx->d1th != NULL)
- GNUNET_TRANSPORT_disconnect (ctx->d1th);
- ctx->d1th = NULL;
- if (ctx->d1core != NULL)
- GNUNET_CORE_disconnect (ctx->d1core);
- ctx->d1core = NULL;
GNUNET_free (ctx);
}
{
struct ConnectContext *ctx = cls;
+#if DEBUG_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Connected peer %s to peer %s\n",
+ ctx->d1->shortname, GNUNET_i2s(peer));
+#endif
+
if (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))
{
+
ctx->connected = GNUNET_YES;
ctx->distance = 0; /* FIXME: distance */
if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
{
hello = GNUNET_HELLO_get_header (ctx->d2->hello);
GNUNET_assert (hello != NULL);
- GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello);
+ GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello, NULL, NULL);
GNUNET_assert (ctx->d1core != NULL);
ctx->connect_request_handle =
GNUNET_CORE_peer_request_connect (ctx->d1core,
- GNUNET_TIME_relative_divide
- (ctx->relative_timeout,
- ctx->max_connect_attempts + 1),
- &ctx->d2->id,
- &core_connect_request_cont, ctx);
+ ctx->relative_timeout,
+ &ctx->d2->id,
+ &core_connect_request_cont, ctx);
+
#if DEBUG_TESTING
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Sending connect request to CORE of %s for peer %s\n",
GNUNET_i2s (&ctx->d1->id),
GNUNET_h2s (&ctx->d2->id.hashPubKey));
{
struct ConnectContext *connect_ctx = cls;
connect_ctx->d1core_ready = GNUNET_YES;
+
+ if (connect_ctx->send_hello == GNUNET_NO)
+ {
+ connect_ctx->connect_request_handle =
+ GNUNET_CORE_peer_request_connect (connect_ctx->d1core,
+ connect_ctx->relative_timeout,
+ &connect_ctx->d2->id,
+ &core_connect_request_cont, connect_ctx);
+ GNUNET_assert(connect_ctx->connect_request_handle != NULL);
+#if DEBUG_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending connect request to CORE of %s for peer %s\n",
+ connect_ctx->d1->shortname,
+ connect_ctx->d2->shortname);
+#endif
+ }
+
+}
+
+
+static void
+reattempt_daemons_connect (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ConnectContext *ctx = cls;
+ if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ {
+ GNUNET_free(ctx);
+ return;
+ }
+#if DEBUG_TESTING_RECONNECT
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "re-attempting connect of peer %s to peer %s\n",
+ ctx->d1->shortname, ctx->d2->shortname);
+#endif
+ ctx->connect_attempts--;
+ GNUNET_assert (ctx->d1core == NULL);
+ ctx->d1core_ready = GNUNET_NO;
+ ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
+ ctx,
+ &core_init_notify,
+ &connect_notify, NULL, NULL,
+ NULL, GNUNET_NO,
+ NULL, GNUNET_NO, no_handlers);
+ if (ctx->d1core == NULL)
+ {
+ if (NULL != ctx->cb)
+ ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+ ctx->d2->cfg, ctx->d1, ctx->d2,
+ _("Failed to connect to core service of first peer!\n"));
+ GNUNET_free (ctx);
+ return;
+ }
+
+ if (ctx->send_hello == GNUNET_YES)
+ {
+ ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
+ &ctx->d1->id,
+ ctx->d1, NULL, NULL, NULL);
+ if (ctx->d1th == NULL)
+ {
+ GNUNET_CORE_disconnect (ctx->d1core);
+ GNUNET_free (ctx);
+ if (NULL != ctx->cb)
+ ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+ ctx->d2->cfg, ctx->d1, ctx->d2,
+ _("Failed to connect to transport service!\n"));
+ return;
+ }
+ ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
+ }
+ else
+ {
+ ctx->connect_request_handle =
+ GNUNET_CORE_peer_request_connect (ctx->d1core,
+ ctx->relative_timeout,
+ &ctx->d2->id,
+ &core_connect_request_cont, ctx);
+ }
+ ctx->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
+ ¬ify_connect_result, ctx);
}
/**
ctx->distance = 0; /* FIXME: distance */
return;
}
- else if (peer == NULL) /* Peer not already connected, need to schedule connect request! */
+ else if (peer == NULL) /* End of iteration over peers */
{
if (ctx->connected == GNUNET_YES)
{
return;
}
- ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
- ctx,
- &core_init_notify,
- &connect_notify, NULL, NULL,
- NULL, GNUNET_NO,
- NULL, GNUNET_NO, no_handlers);
+ /* Peer not already connected, need to schedule connect request! */
+ if (ctx->d1core == NULL)
+ {
+#if DEBUG_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Peers are NOT connected, connecting to core!\n");
+#endif
+ ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
+ ctx,
+ &core_init_notify,
+ &connect_notify, NULL, NULL,
+ NULL, GNUNET_NO,
+ NULL, GNUNET_NO, no_handlers);
+ }
+
if (ctx->d1core == NULL)
{
GNUNET_free (ctx);
return;
}
-#if DEBUG_TESTING > 2
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Asked to connect peer %s to peer %s\n",
- ctx->d1->shortname, ctx->d2->shortname);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connecting to transport service of peer %s\n", ctx->d2->shortname);
-
-#endif
-
- ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
- &ctx->d1->id, ctx->d1, NULL, NULL, NULL);
- if (ctx->d1th == NULL)
+ if (ctx->send_hello == GNUNET_YES)
{
- GNUNET_CORE_disconnect (ctx->d1core);
- GNUNET_free (ctx);
- if (NULL != ctx->cb)
- ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2,
- _("Failed to connect to transport service!\n"));
- return;
+ ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
+ &ctx->d1->id, ctx->d1, NULL, NULL, NULL);
+ if (ctx->d1th == NULL)
+ {
+ GNUNET_CORE_disconnect (ctx->d1core);
+ GNUNET_free (ctx);
+ if (NULL != ctx->cb)
+ ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2,
+ _("Failed to connect to transport service!\n"));
+ return;
+ }
+ ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
}
ctx->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
- (ctx->relative_timeout,
- ctx->max_connect_attempts),
- ¬ify_connect_result, ctx);
-
- ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
+ GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
+ ¬ify_connect_result, ctx);
}
}
* allowed to take?
* @param max_connect_attempts how many times should we try to reconnect
* (within timeout)
+ * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume
+ * the HELLO has already been exchanged
* @param cb function to call at the end
* @param cb_cls closure for cb
*/
struct GNUNET_TESTING_Daemon *d2,
struct GNUNET_TIME_Relative timeout,
unsigned int max_connect_attempts,
+ int send_hello,
GNUNET_TESTING_NotifyConnection cb,
void *cb_cls)
{
_("Peers are not fully running yet, can not connect!\n"));
return;
}
+
ctx = GNUNET_malloc (sizeof (struct ConnectContext));
ctx->d1 = d1;
ctx->d2 = d2;
- ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
ctx->timeout_hello =
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500);
- ctx->relative_timeout = timeout;
+ ctx->relative_timeout = GNUNET_TIME_relative_divide(timeout, max_connect_attempts);
ctx->cb = cb;
ctx->cb_cls = cb_cls;
- ctx->max_connect_attempts = max_connect_attempts;
+ ctx->connect_attempts = max_connect_attempts;
ctx->connected = GNUNET_NO;
+ ctx->send_hello = send_hello;
#if DEBUG_TESTING
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Asked to connect peer %s to peer %s\n",
#endif
/* Core is up! Iterate over all _known_ peers first to check if we are already connected to the peer! */
- GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id, &core_initial_iteration, ctx);
- /* GNUNET_CORE_iterate_peers(ctx->d1->cfg, &core_initial_iteration, ctx); */
-
-}
-
-static void
-reattempt_daemons_connect (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
- struct ConnectContext *ctx = cls;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
- {
- return;
- }
-#if DEBUG_TESTING_RECONNECT
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "re-attempting connect of peer %s to peer %s\n",
- ctx->d1->shortname, ctx->d2->shortname);
-#endif
-
- GNUNET_assert (ctx->d1core == NULL);
- ctx->d1core_ready = GNUNET_NO;
- ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
- ctx,
- &core_init_notify,
- &connect_notify, NULL, NULL,
- NULL, GNUNET_NO,
- NULL, GNUNET_NO, no_handlers);
- if (ctx->d1core == NULL)
- {
- if (NULL != ctx->cb)
- ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
- ctx->d2->cfg, ctx->d1, ctx->d2,
- _("Failed to connect to core service of first peer!\n"));
- GNUNET_free (ctx);
- return;
- }
-
- ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
- &ctx->d1->id,
- ctx->d1, NULL, NULL, NULL);
- if (ctx->d1th == NULL)
- {
- GNUNET_CORE_disconnect (ctx->d1core);
- GNUNET_free (ctx);
- if (NULL != ctx->cb)
- ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
- ctx->d2->cfg, ctx->d1, ctx->d2,
- _("Failed to connect to transport service!\n"));
- return;
- }
-
- ctx->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
- (ctx->relative_timeout,
- ctx->max_connect_attempts),
- ¬ify_connect_result, ctx);
-
- ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
+ GNUNET_assert(GNUNET_OK == GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id, &core_initial_iteration, ctx));
+ /*GNUNET_assert(GNUNET_OK == GNUNET_CORE_iterate_peers (ctx->d1->cfg, &core_initial_iteration, ctx));*/
}
/* end of testing.c */
#include "gnunet_testing_lib.h"
#include "gnunet_core_service.h"
-#define VERBOSE_TESTING GNUNET_YES
+#define VERBOSE_TESTING GNUNET_NO
#define VERBOSE_TOPOLOGY GNUNET_YES
#define OLD 1
+#define USE_SEND_HELLOS GNUNET_NO
+
/**
* Lowest port used for GNUnet testing. Should be high enough to not
* conflict with other applications running on the hosts but be low
};
+struct SendHelloContext
+{
+ /**
+ * Global handle to the peer group.
+ */
+ struct GNUNET_TESTING_PeerGroup *pg;
+
+ /**
+ * The data about this specific peer.
+ */
+ struct PeerData *peer;
+
+ /**
+ * The next HELLO that needs sent to this peer.
+ */
+ struct PeerConnection *peer_pos;
+
+ /**
+ * Are we connected to CORE yet?
+ */
+ unsigned int core_ready;
+
+ /**
+ * How many attempts should we make for failed connections?
+ */
+ unsigned int connect_attempts;
+
+ /**
+ * Task for scheduling core connect requests to be sent.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier core_connect_task;
+};
+
+
struct ShutdownContext
{
struct GNUNET_TESTING_PeerGroup *pg;
struct GNUNET_STATISTICS_GetHandle *stats_get_handle;
};
+
+struct ConnectTopologyContext
+{
+ /**
+ * How many connections are left to create.
+ */
+ unsigned int remaining_connections;
+
+ /**
+ * Handle to group of peers.
+ */
+ struct GNUNET_TESTING_PeerGroup *pg;
+
+ /**
+ * How long to try this connection before timing out.
+ */
+ struct GNUNET_TIME_Relative connect_timeout;
+
+ /**
+ * How many times to retry connecting the two peers.
+ */
+ unsigned int connect_attempts;
+
+ /**
+ * Temp value set for each iteration.
+ */
+ //struct PeerData *first;
+
+ /**
+ * Notification that all peers are connected.
+ */
+ GNUNET_TESTING_NotifyCompletion notify_connections_done;
+
+ /**
+ * Closure for notify.
+ */
+ void *notify_cls;
+};
+
+
/**
* Handle to a group of GNUnet peers.
*/
*/
unsigned int outstanding_connects;
+ /**
+ * Number of HELLOs we have yet to send.
+ */
+ unsigned int remaining_hellos;
+
/**
* How many connects have already been scheduled?
*/
* Stop scheduling peers connecting.
*/
unsigned int stop_connects;
-};
-
-struct UpdateContext
-{
- struct GNUNET_CONFIGURATION_Handle *ret;
- const struct GNUNET_CONFIGURATION_Handle *orig;
- const char *hostname;
- unsigned int nport;
- unsigned int upnum;
- unsigned int fdnum;
-};
-
-struct ConnectTopologyContext
-{
- /**
- * How many connections are left to create.
- */
- unsigned int remaining_connections;
/**
- * How many more connections do we need to schedule?
+ * Connection context for peer group.
*/
- unsigned int remaining_connects_to_schedule;
+ struct ConnectTopologyContext ct_ctx;
+};
+struct UpdateContext
+{
/**
- * Handle to group of peers.
+ * The altered configuration.
*/
- struct GNUNET_TESTING_PeerGroup *pg;
+ struct GNUNET_CONFIGURATION_Handle *ret;
/**
- * How long to try this connection before timing out.
+ * The original configuration to alter.
*/
- struct GNUNET_TIME_Relative connect_timeout;
+ const struct GNUNET_CONFIGURATION_Handle *orig;
/**
- * How many times to retry connecting the two peers.
+ * The hostname that this peer will run on.
*/
- unsigned int connect_attempts;
+ const char *hostname;
/**
- * Temp value set for each iteration.
+ * The next possible port to assign.
*/
- //struct PeerData *first;
+ unsigned int nport;
/**
- * Notification that all peers are connected.
+ * Unique number for unix domain sockets.
*/
- GNUNET_TESTING_NotifyCompletion notify_connections_done;
+ unsigned int upnum;
/**
- * Closure for notify.
+ * Unique number for this peer/host to offset
+ * things that are grouped by host.
*/
- void *notify_cls;
+ unsigned int fdnum;
};
+
struct ConnectContext
{
/**
- * Peer to connect second to.
+ * Index of peer to connect second to.
*/
- struct GNUNET_TESTING_Daemon *first;
+ uint32_t first_index;
/**
- * Peer to connect first to.
+ * Index of peer to connect first to.
*/
- struct GNUNET_TESTING_Daemon *second;
+ uint32_t second_index;
/**
* Higher level topology connection context.
}
#endif
+#if USE_SEND_HELLOS
+static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
+#endif
+
/**
* Get a topology from a string input.
*
char *per_host_variable;
unsigned long long num_per_host;
+ GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
+ GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
+
if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
{
- GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
- if ((ival != 0)
- && (GNUNET_YES !=
+ if ((ival != 0) &&
+ (GNUNET_YES !=
GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
single_variable)))
{
GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
value = cval;
}
-
- GNUNET_free (single_variable);
+ else if ((ival != 0) &&
+ (GNUNET_YES ==
+ GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
+ single_variable)) &&
+ GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing",
+ per_host_variable,
+ &num_per_host))
+ {
+ GNUNET_snprintf (cval, sizeof (cval), "%u", ival + ctx->fdnum % num_per_host);
+ value = cval;
+ }
}
if (0 == strcmp (option, "UNIXPATH"))
{
- GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
- GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
if (GNUNET_YES !=
GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
single_variable))
section, ctx->fdnum % num_per_host);
value = uval;
}
- GNUNET_free (single_variable);
- GNUNET_free (per_host_variable);
}
if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL))
{
value = ctx->hostname;
}
-
+ GNUNET_free (single_variable);
+ GNUNET_free (per_host_variable);
GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value);
}
make_config (const struct GNUNET_CONFIGURATION_Handle *cfg,
uint32_t off,
uint16_t * port,
- uint32_t * upnum, const char *hostname, uint32_t * fdnum)
+ uint32_t * upnum, const char *hostname,
+ uint32_t * fdnum)
{
struct UpdateContext uc;
uint16_t orig;
char *control_host;
char *allowed_hosts;
- unsigned long long temp_port;
orig = *port;
uc.nport = *port;
GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "UNIXPATH", "");
GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "UNIXPATH", "");
-
- if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(uc.orig, "statistics", "port", &temp_port) &&
- (temp_port != 0) &&
- (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (uc.orig, "testing",
- "single_statistics_per_host")))
- {
- GNUNET_CONFIGURATION_set_value_number (uc.ret, "statistics", "port", temp_port + off);
- }
-
GNUNET_free_non_null (control_host);
GNUNET_free (allowed_hosts);
}
new_first = GNUNET_malloc (sizeof (struct PeerConnection));
new_first->index = second;
GNUNET_CONTAINER_DLL_insert(*first_list, *first_tail, new_first);
- /*
- new_first->next = *first_list;
- *first_list = new_first;*/
#else
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (pg->
new_second = GNUNET_malloc (sizeof (struct PeerConnection));
new_second->index = first;
GNUNET_CONTAINER_DLL_insert(*second_list, *second_tail, new_second);
- /*
- new_second->next = *second_list;
- *second_list = new_second;
- *second_list */
#else
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (pg->
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
_("Copying file with command cp %s %s\n"), mytemp, arg);
#endif
-
+ ret = GNUNET_OS_process_wait(procarr[pg_iter]); /* FIXME: schedule this, throttle! */
+ GNUNET_OS_process_close (procarr[pg_iter]);
GNUNET_free (arg);
}
else /* Remote, scp the file to the correct place */
*
* @param ct_ctx the overall connection context
*/
-static void preschedule_connect(struct ConnectTopologyContext *ct_ctx)
+static void preschedule_connect(struct GNUNET_TESTING_PeerGroup *pg)
{
- struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg;
+ struct ConnectTopologyContext *ct_ctx = &pg->ct_ctx;
struct PeerConnection *connection_iter;
struct ConnectContext *connect_context;
uint32_t random_peer;
- if (ct_ctx->remaining_connects_to_schedule == 0)
+ if (ct_ctx->remaining_connections == 0)
return;
random_peer = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
while (pg->peers[random_peer].connect_peers_head == NULL)
random_peer = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
connection_iter = pg->peers[random_peer].connect_peers_head;
-#if DEBUG_TESTING
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Scheduling connection between %d and %d\n", random_peer, connection_iter->index);
-#endif
connect_context = GNUNET_malloc (sizeof (struct ConnectContext));
- connect_context->first = pg->peers[random_peer].daemon;
- connect_context->second = pg->peers[connection_iter->index].daemon;
+ connect_context->first_index = random_peer;
+ connect_context->second_index = connection_iter->index;
connect_context->ct_ctx = ct_ctx;
GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
GNUNET_CONTAINER_DLL_remove(pg->peers[random_peer].connect_peers_head, pg->peers[random_peer].connect_peers_tail, connection_iter);
- ct_ctx->remaining_connects_to_schedule--;
+ GNUNET_free(connection_iter);
+ ct_ctx->remaining_connections--;
+}
+
+#if USE_SEND_HELLOS
+/* Forward declaration */
+static void schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Close connections and free the hello context.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+free_hello_context (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SendHelloContext *send_hello_context = cls;
+ if (send_hello_context->peer->daemon->server != NULL)
+ {
+ GNUNET_CORE_disconnect(send_hello_context->peer->daemon->server);
+ send_hello_context->peer->daemon->server = NULL;
+ }
+ if (send_hello_context->peer->daemon->th != NULL)
+ {
+ GNUNET_TRANSPORT_disconnect(send_hello_context->peer->daemon->th);
+ send_hello_context->peer->daemon->th = NULL;
+ }
+ if (send_hello_context->core_connect_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel(send_hello_context->core_connect_task);
+ send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ send_hello_context->pg->outstanding_connects--;
+ GNUNET_free(send_hello_context);
+}
+
+/**
+ * For peers that haven't yet connected, notify
+ * the caller that they have failed (timeout).
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+notify_remaining_connections_failed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SendHelloContext *send_hello_context = cls;
+ struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+ struct PeerConnection *connection;
+
+ GNUNET_CORE_disconnect(send_hello_context->peer->daemon->server);
+ send_hello_context->peer->daemon->server = NULL;
+
+ connection = send_hello_context->peer->connect_peers_head;
+
+ while (connection != NULL)
+ {
+ if (pg->notify_connection != NULL)
+ {
+ pg->notify_connection(pg->notify_connection_cls,
+ &send_hello_context->peer->daemon->id,
+ &pg->peers[connection->index].daemon->id,
+ 0, /* FIXME */
+ send_hello_context->peer->daemon->cfg,
+ pg->peers[connection->index].daemon->cfg,
+ send_hello_context->peer->daemon,
+ pg->peers[connection->index].daemon,
+ "Peers failed to connect (timeout)");
+ }
+ GNUNET_CONTAINER_DLL_remove(send_hello_context->peer->connect_peers_head, send_hello_context->peer->connect_peers_tail, connection);
+ GNUNET_free(connection);
+ connection = connection->next;
+ }
+ GNUNET_SCHEDULER_add_now(&free_hello_context, send_hello_context);
+#if BAD
+ other_peer = &pg->peers[connection->index];
+#endif
}
+/**
+ * For peers that haven't yet connected, send
+ * CORE connect requests.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+send_core_connect_requests (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SendHelloContext *send_hello_context = cls;
+ struct PeerConnection *conn;
+ GNUNET_assert(send_hello_context->peer->daemon->server != NULL);
+
+ send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
+
+ send_hello_context->connect_attempts++;
+ if (send_hello_context->connect_attempts < send_hello_context->pg->ct_ctx.connect_attempts)
+ {
+ conn = send_hello_context->peer->connect_peers_head;
+ while (conn != NULL)
+ {
+ GNUNET_CORE_peer_request_connect(send_hello_context->peer->daemon->server,
+ GNUNET_TIME_relative_get_forever(),
+ &send_hello_context->pg->peers[conn->index].daemon->id,
+ NULL,
+ NULL);
+ conn = conn->next;
+ }
+ send_hello_context->core_connect_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_divide(send_hello_context->pg->ct_ctx.connect_timeout, send_hello_context->pg->ct_ctx.connect_attempts) ,
+ &send_core_connect_requests,
+ send_hello_context);
+ }
+ else
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Timeout before all connections created, marking rest as failed!\n");
+ GNUNET_SCHEDULER_add_now(¬ify_remaining_connections_failed, send_hello_context);
+ }
+
+}
+
+
+/**
+ * Success, connection is up. Signal client our success.
+ *
+ * @param cls our "struct SendHelloContext"
+ * @param peer identity of the peer that has connected
+ * @param atsi performance information
+ *
+ * FIXME: remove peers from BOTH lists, call notify twice, should
+ * double the speed of connections as long as the list iteration
+ * doesn't take too long!
+ */
+static void
+core_connect_notify (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+ struct SendHelloContext *send_hello_context = cls;
+ struct PeerConnection *connection;
+ struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+#if BAD
+ struct PeerData *other_peer;
+#endif
+#if DEBUG_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Connected peer %s to peer %s\n",
+ ctx->d1->shortname, GNUNET_i2s(peer));
+#endif
+
+ if (0 == memcmp(&send_hello_context->peer->daemon->id, peer, sizeof(struct GNUNET_PeerIdentity)))
+ return;
+
+ connection = send_hello_context->peer->connect_peers_head;
+#if BAD
+ other_peer = NULL;
+#endif
+
+ while ((connection != NULL) &&
+ (0 != memcmp(&pg->peers[connection->index].daemon->id, peer, sizeof(struct GNUNET_PeerIdentity))))
+ {
+ connection = connection->next;
+ }
+
+ if (connection == NULL)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Connected peer %s to %s, not in list (no problem(?))\n", GNUNET_i2s(peer), send_hello_context->peer->daemon->shortname);
+ }
+ else
+ {
+#if BAD
+ other_peer = &pg->peers[connection->index];
+#endif
+ if (pg->notify_connection != NULL)
+ {
+ pg->notify_connection(pg->notify_connection_cls,
+ &send_hello_context->peer->daemon->id,
+ peer,
+ 0, /* FIXME */
+ send_hello_context->peer->daemon->cfg,
+ pg->peers[connection->index].daemon->cfg,
+ send_hello_context->peer->daemon,
+ pg->peers[connection->index].daemon,
+ NULL);
+ }
+ GNUNET_CONTAINER_DLL_remove(send_hello_context->peer->connect_peers_head, send_hello_context->peer->connect_peers_tail, connection);
+ GNUNET_free(connection);
+ }
+
+#if BAD
+ /* Notify of reverse connection and remove from other peers list of outstanding */
+ if (other_peer != NULL)
+ {
+ connection = other_peer->connect_peers_head;
+ while ((connection != NULL) &&
+ (0 != memcmp(&send_hello_context->peer->daemon->id, &pg->peers[connection->index].daemon->id, sizeof(struct GNUNET_PeerIdentity))))
+ {
+ connection = connection->next;
+ }
+ if (connection != NULL)
+ {
+ if (pg->notify_connection != NULL)
+ {
+ pg->notify_connection(pg->notify_connection_cls,
+ peer,
+ &send_hello_context->peer->daemon->id,
+ 0, /* FIXME */
+ pg->peers[connection->index].daemon->cfg,
+ send_hello_context->peer->daemon->cfg,
+ pg->peers[connection->index].daemon,
+ send_hello_context->peer->daemon,
+ NULL);
+ }
+
+ GNUNET_CONTAINER_DLL_remove(other_peer->connect_peers_head, other_peer->connect_peers_tail, connection);
+ GNUNET_free(connection);
+ }
+ }
+#endif
+
+ if (send_hello_context->peer->connect_peers_head == NULL)
+ {
+ GNUNET_SCHEDULER_add_now(&free_hello_context, send_hello_context);
+ }
+}
+
+/**
+ * Notify of a successful connection to the core service.
+ *
+ * @param cls a struct SendHelloContext *
+ * @param server handle to the core service
+ * @param my_identity the peer identity of this peer
+ * @param publicKey the public key of the peer
+ */
+void
+core_init (void *cls,
+ struct GNUNET_CORE_Handle * server,
+ const struct GNUNET_PeerIdentity *
+ my_identity,
+ const struct
+ GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
+ publicKey)
+{
+ struct SendHelloContext *send_hello_context = cls;
+ send_hello_context->core_ready = GNUNET_YES;
+}
+
+
+/**
+ * Function called once a hello has been sent
+ * to the transport, move on to the next one
+ * or go away forever.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+hello_sent_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SendHelloContext *send_hello_context = cls;
+ //unsigned int pg_iter;
+ if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ {
+ GNUNET_free(send_hello_context);
+ return;
+ }
+
+ send_hello_context->pg->remaining_hellos--;
+#if DEBUG_TESTING
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sent HELLO, have %d remaining!\n", send_hello_context->pg->remaining_hellos);
+#endif
+ if (send_hello_context->peer_pos == NULL) /* All HELLOs (for this peer!) have been transmitted! */
+ {
+#if DEBUG_TESTING
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "All hellos for this peer sent, disconnecting transport!\n");
+#endif
+ GNUNET_assert(send_hello_context->peer->daemon->th != NULL);
+ GNUNET_TRANSPORT_disconnect(send_hello_context->peer->daemon->th);
+ send_hello_context->peer->daemon->th = NULL;
+
+ /*if (send_hello_context->pg->remaining_hellos == 0)
+ {
+ for (pg_iter = 0; pg_iter < send_hello_context->pg->max_outstanding_connections; pg_iter++)
+ {
+ preschedule_connect(&send_hello_context->pg->ct_ctx);
+ }
+ }
+ */
+ GNUNET_assert (send_hello_context->peer->daemon->server == NULL);
+ send_hello_context->peer->daemon->server = GNUNET_CORE_connect(send_hello_context->peer->cfg,
+ 1,
+ send_hello_context,
+ &core_init,
+ &core_connect_notify,
+ NULL,
+ NULL,
+ NULL, GNUNET_NO,
+ NULL, GNUNET_NO,
+ no_handlers);
+
+ send_hello_context->core_connect_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_divide(send_hello_context->pg->ct_ctx.connect_timeout, send_hello_context->pg->ct_ctx.connect_attempts),
+ &send_core_connect_requests,
+ send_hello_context);
+ }
+ else
+ GNUNET_SCHEDULER_add_now(&schedule_send_hellos, send_hello_context);
+}
+
+
+/**
+ * Connect to a peer, give it all the HELLO's of those peers
+ * we will later ask it to connect to.
+ *
+ * @param ct_ctx the overall connection context
+ */
+static void schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SendHelloContext *send_hello_context = cls;
+ struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+
+ if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ {
+ GNUNET_free(send_hello_context);
+ return;
+ }
+
+ GNUNET_assert(send_hello_context->peer_pos != NULL); /* All of the HELLO sends to be scheduled have been scheduled! */
+
+ if (((send_hello_context->peer->daemon->th == NULL) &&
+ (pg->outstanding_connects > pg->max_outstanding_connections)) ||
+ (pg->stop_connects == GNUNET_YES))
+ {
+#if VERBOSE_TESTING > 2
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _
+ ("Delaying connect, we have too many outstanding connections!\n"));
+#endif
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+ (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+ &schedule_send_hellos, send_hello_context);
+ }
+ else
+ {
+#if VERBOSE_TESTING > 2
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Creating connection, outstanding_connections is %d\n"),
+ outstanding_connects);
+#endif
+ if (send_hello_context->peer->daemon->th == NULL)
+ {
+ pg->outstanding_connects++; /* Actual TRANSPORT, CORE connections! */
+ send_hello_context->peer->daemon->th = GNUNET_TRANSPORT_connect(send_hello_context->peer->cfg,
+ NULL,
+ send_hello_context,
+ NULL,
+ NULL,
+ NULL);
+ }
+#if DEBUG_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Offering Hello of peer %s to peer %s\n"),
+ send_hello_context->peer->daemon->shortname, pg->peers[send_hello_context->peer_pos->index].daemon->shortname);
+#endif
+ GNUNET_TRANSPORT_offer_hello(send_hello_context->peer->daemon->th,
+ (const struct GNUNET_MessageHeader *)pg->peers[send_hello_context->peer_pos->index].daemon->hello,
+ &hello_sent_callback,
+ send_hello_context);
+ send_hello_context->peer_pos = send_hello_context->peer_pos->next;
+ GNUNET_assert(send_hello_context->peer->daemon->th != NULL);
+ }
+}
+#endif
+
+
/**
* Internal notification of a connection, kept so that we can ensure some connections
* happen instead of flooding all testing daemons with requests to connect.
struct GNUNET_TESTING_Daemon *second_daemon,
const char *emsg)
{
- struct ConnectTopologyContext *ct_ctx = cls;
+ struct ConnectContext *connect_ctx = cls;
+ struct ConnectTopologyContext *ct_ctx = connect_ctx->ct_ctx;
struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg;
+ struct PeerConnection *connection;
pg->outstanding_connects--;
- ct_ctx->remaining_connections--;
+
+ /*
+ * Check whether the inverse connection has been scheduled yet,
+ * if not, we can remove it from the other peers list and avoid
+ * even trying to connect them again!
+ */
+ connection = pg->peers[connect_ctx->second_index].connect_peers_head;
+#if BAD
+ other_peer = NULL;
+#endif
+
+ while ((connection != NULL) &&
+ (0 != memcmp(first, &pg->peers[connection->index].daemon->id, sizeof(struct GNUNET_PeerIdentity))))
+ {
+ connection = connection->next;
+ }
+
+ if (connection != NULL) /* Can safely remove! */
+ {
+ ct_ctx->remaining_connections--;
+ if (pg->notify_connection != NULL) /* Notify of reverse connection */
+ pg->notify_connection (pg->notify_connection_cls, second, first, distance,
+ second_cfg, first_cfg, second_daemon, first_daemon,
+ emsg);
+
+ GNUNET_CONTAINER_DLL_remove(pg->peers[connect_ctx->second_index].connect_peers_head, pg->peers[connect_ctx->second_index].connect_peers_tail, connection);
+ GNUNET_free(connection);
+ }
+
if (ct_ctx->remaining_connections == 0)
{
if (ct_ctx->notify_connections_done != NULL)
ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL);
- GNUNET_free (ct_ctx);
}
else
- preschedule_connect(ct_ctx);
+ preschedule_connect(pg);
if (pg->notify_connection != NULL)
pg->notify_connection (pg->notify_connection_cls, first, second, distance,
first_cfg, second_cfg, first_daemon, second_daemon,
emsg);
+
+ GNUNET_free(connect_ctx);
}
if ((pg->outstanding_connects > pg->max_outstanding_connections) || (pg->stop_connects == GNUNET_YES))
{
-#if VERBOSE_TESTING > 2
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+#if VERBOSE_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_
("Delaying connect, we have too many outstanding connections!\n"));
#endif
}
else
{
-#if VERBOSE_TESTING > 2
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- _("Creating connection, outstanding_connections is %d\n"),
- outstanding_connects);
+#if VERBOSE_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Creating connection, outstanding_connections is %d (max %d)\n"),
+ pg->outstanding_connects, pg->max_outstanding_connections);
#endif
pg->outstanding_connects++;
pg->total_connects_scheduled++;
- GNUNET_TESTING_daemons_connect (connect_context->first,
- connect_context->second,
+ GNUNET_TESTING_daemons_connect (pg->peers[connect_context->first_index].daemon,
+ pg->peers[connect_context->second_index].daemon,
connect_context->ct_ctx->connect_timeout,
connect_context->ct_ctx->connect_attempts,
+#if USE_SEND_HELLOS
+ GNUNET_NO,
+#else
+ GNUNET_YES,
+#endif
&internal_connect_notify,
- connect_context->ct_ctx);
- GNUNET_free (connect_context);
+ connect_context); /* FIXME: free connect context! */
}
}
{
unsigned int pg_iter;
unsigned int total;
- struct ConnectTopologyContext *ct_ctx;
+
#if OLD
struct PeerConnection *connection_iter;
#endif
+#if USE_SEND_HELLOS
+ struct SendHelloContext *send_hello_context
+#endif
total = 0;
- ct_ctx = GNUNET_malloc (sizeof (struct ConnectTopologyContext));
- ct_ctx->notify_connections_done = notify_callback;
- ct_ctx->notify_cls = notify_cls;
- ct_ctx->pg = pg;
+ pg->ct_ctx.notify_connections_done = notify_callback;
+ pg->ct_ctx.notify_cls = notify_cls;
+ pg->ct_ctx.pg = pg;
for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
{
}
if (total == 0)
+ return total;
+
+ pg->ct_ctx.connect_timeout = connect_timeout;
+ pg->ct_ctx.connect_attempts = connect_attempts;
+ pg->ct_ctx.remaining_connections = total;
+
+#if USE_SEND_HELLOS
+ /* First give all peers the HELLO's of other peers (connect to first peer's transport service, give HELLO's of other peers, continue...) */
+ pg->remaining_hellos = total;
+ for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
{
- GNUNET_free (ct_ctx);
- return total;
+ send_hello_context = GNUNET_malloc(sizeof(struct SendHelloContext));
+ send_hello_context->peer = &pg->peers[pg_iter];
+ send_hello_context->peer_pos = pg->peers[pg_iter].connect_peers_head;
+ send_hello_context->pg = pg;
+ GNUNET_SCHEDULER_add_now(&schedule_send_hellos, send_hello_context);
}
- ct_ctx->connect_timeout = connect_timeout;
- ct_ctx->connect_attempts = connect_attempts;
- ct_ctx->remaining_connections = total;
- ct_ctx->remaining_connects_to_schedule = total;
-
+#else
for (pg_iter = 0; pg_iter < pg->max_outstanding_connections; pg_iter++)
- {
- preschedule_connect(ct_ctx);
- }
+ {
+ preschedule_connect(pg);
+ }
+#endif
return total;
}
}
if (transport != NULL)
GNUNET_TRANSPORT_offer_hello (transport,
- message);
+ message, NULL, NULL);
return GNUNET_OK;
}
#if DEBUG_CLIENT
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected to unixpath `%s'!\n", unixpath);
#endif
+ GNUNET_free(unixpath);
return sock;
}
}