*
*/
#include "platform.h"
+#include "gnunet_constants.h"
#include "gnunet_arm_service.h"
#include "gnunet_testing_lib.h"
#include "gnunet_core_service.h"
#define DEBUG_CHURN GNUNET_NO
+#define USE_START_HELPER GNUNET_YES
+
#define OLD 1
+/* Before connecting peers, send all of the HELLOs */
#define USE_SEND_HELLOS GNUNET_NO
#define TOPOLOGY_HACK GNUNET_YES
-#define AVOID_CONN_MALLOC GNUNET_YES
/**
* Lowest port used for GNUnet testing. Should be high enough to not
* Connection context for peer group.
*/
struct ConnectTopologyContext ct_ctx;
-
-#if AVOID_CONN_MALLOC
- struct PeerConnection working_peer_connections[200000];
-
- unsigned int current_peer_connection;
-#endif
};
struct UpdateContext
added = 0;
if (add_first)
{
-#if AVOID_CONN_MALLOC
- new_first = &pg->working_peer_connections[pg->current_peer_connection];
- pg->current_peer_connection++;
-#else
new_first = GNUNET_malloc (sizeof (struct PeerConnection));
-#endif
new_first->index = second;
GNUNET_CONTAINER_DLL_insert(*first_list, *first_tail, new_first);
pg->peers[first].num_connections++;
if (add_second)
{
-#if AVOID_CONN_MALLOC
- new_second = &pg->working_peer_connections[pg->current_peer_connection];
- pg->current_peer_connection++;
-#else
new_second = GNUNET_malloc (sizeof (struct PeerConnection));
-#endif
new_second->index = first;
GNUNET_CONTAINER_DLL_insert(*second_list, *second_tail, new_second);
pg->peers[second].num_connections++;
connect_attempts = 0;
conn_meter = create_meter ((((pg->total * pg->total) + pg->total) / 2)
- - pg->total, "Create Clique ", GNUNET_YES);
+ - pg->total, "Create Clique ", GNUNET_NO);
for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
{
for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
update_meter (conn_meter);
}
}
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Meter has %d left\n",
- conn_meter->total - conn_meter->completed);
reset_meter (conn_meter);
free_meter (conn_meter);
return connect_attempts;
}
}
-#if 0
- /* Connect each peer to the next highest numbered peer */
- for (count = 0; count < pg->total - 1; count++)
- {
-#if VERBOSE_TESTING
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connecting peer %d to peer %d\n", first_peer_index, second_peer_index);
-#endif
- connect_attempts += proc (pg, first_peer_index, second_peer_index);
- }
-#endif
return connect_attempts;
}
GNUNET_asprintf (&arg, "%s/friends", temp_service_path);
procarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "mv", "mv",
mytemp, arg, NULL);
+ GNUNET_assert(procarr[pg_iter] != NULL);
#if VERBOSE_TESTING
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
_("Copying file with command cp %s %s\n"), mytemp, arg);
temp_service_path);
procarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp", "scp",
mytemp, arg, NULL);
-
+ GNUNET_assert(procarr[pg_iter] != NULL);
ret = GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: schedule this, throttle! */
GNUNET_OS_process_close (procarr[pg_iter]);
if (ret != GNUNET_OK)
temp_service_path);
procarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp", "scp",
mytemp, arg, NULL);
-
+ GNUNET_assert(procarr[pg_iter] != NULL);
GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: add scheduled blacklist file copy that parallelizes file copying! */
#if VERBOSE_TESTING
{
struct SendHelloContext *send_hello_context = cls;
//unsigned int pg_iter;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
{
GNUNET_free(send_hello_context);
return;
struct SendHelloContext *send_hello_context = cls;
struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
{
GNUNET_free(send_hello_context);
return;
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);
+ 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,
struct ConnectContext *connect_context = cls;
struct GNUNET_TESTING_PeerGroup *pg = connect_context->ct_ctx->pg;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
return;
if ((pg->outstanding_connects > pg->max_outstanding_connections)
connect_context->ct_ctx->connect_timeout,
connect_context->ct_ctx->connect_attempts,
#if USE_SEND_HELLOS
- GNUNET_NO,
+ GNUNET_NO,
#else
GNUNET_YES,
#endif
"Creating connection between %d and %d\n", pg_iter,
iter->index);
total += add_connections (pg, pg_iter, iter->index, CONNECT,
- GNUNET_NO);
+ GNUNET_YES);
//total += add_actual_connections(pg, pg_iter, iter->index);
iter = iter->next;
}
struct PeerConnection *connection_iter;
#endif
#if USE_SEND_HELLOS
- struct SendHelloContext *send_hello_context
+ struct SendHelloContext *send_hello_context;
#endif
total = 0;
if ((restrict_topology != GNUNET_TESTING_TOPOLOGY_NONE) && (restrict_topology
!= GNUNET_TESTING_TOPOLOGY_FROM_FILE))
create_clique (pg, &add_connections, BLACKLIST, GNUNET_NO);
+ else
+ return num_connections;
unblacklisted_connections = 0;
/* Un-blacklist connections as per the topology specified */
struct CoreContext *core_context = cls;
struct TopologyIterateContext *topology_context =
(struct TopologyIterateContext *) core_context->iter_context;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
return;
if (topology_context->connected
struct StatsIterateContext *stats_context =
(struct StatsIterateContext *) core_context->iter_context;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
return;
if (stats_context->connected > stats_context->pg->max_outstanding_connections)
{
struct InternalStartContext *internal_context = cls;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
{
return;
}
}
}
+
static void
internal_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct InternalStartContext *internal_context = cls;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
{
return;
}
internal_context->peer->daemon
= GNUNET_TESTING_daemon_start (internal_context->peer->cfg,
internal_context->timeout,
+ GNUNET_NO,
internal_context->hostname,
internal_context->username,
internal_context->sshport,
&internal_start, internal_context);
}
}
+#if USE_START_HELPER
+
+struct PeerStartHelperContext
+{
+ struct GNUNET_TESTING_PeerGroup *pg;
+
+ struct HostData *host;
+
+ struct GNUNET_OS_Process *proc;
+};
+
+static void
+check_peers_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct PeerStartHelperContext *helper = cls;
+ enum GNUNET_OS_ProcessStatusType type;
+ unsigned long code;
+ unsigned int i;
+ GNUNET_TESTING_NotifyDaemonRunning cb;
+
+ if (GNUNET_NO == GNUNET_OS_process_status (helper->proc, &type, &code)) /* Still running, wait some more! */
+ {
+ GNUNET_SCHEDULER_add_delayed(GNUNET_CONSTANTS_EXEC_WAIT, &check_peers_started, helper);
+ return;
+ }
+
+ helper->pg->starting--;
+ if (helper->pg->starting == 0) /* All peers have finished starting! */
+ {
+ /* Call the peer started callback for each peer, set proper FSM state (?) */
+ for (i = 0; i < helper->pg->total; i++)
+ {
+ cb = helper->pg->peers[i].daemon->cb;
+ helper->pg->peers[i].daemon->cb = NULL;
+ helper->pg->peers[i].daemon->running = GNUNET_YES;
+ helper->pg->peers[i].daemon->phase = SP_START_DONE;
+ if (NULL != cb)
+ {
+ if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
+ cb (helper->pg->peers[i].daemon->cb_cls,
+ &helper->pg->peers[i].daemon->id,
+ helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon,
+ "Failed to execute peerStartHelper.pl, or return code bad!");
+ else
+ cb (helper->pg->peers[i].daemon->cb_cls,
+ &helper->pg->peers[i].daemon->id,
+ helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon,
+ NULL);
+
+ }
+
+ }
+ }
+ GNUNET_OS_process_close(helper->proc);
+}
+
+static void
+start_peer_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct PeerStartHelperContext *helper = cls;
+ char *baseservicehome;
+ char *tempdir;
+ char *arg;
+ /* ssh user@host peerStartHelper /path/to/basedirectory */
+ GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (helper->pg->cfg, "PATHS", "SERVICEHOME",
+ &baseservicehome));
+ GNUNET_asprintf(&tempdir, "%s/%s/", baseservicehome, helper->host->hostname);
+ if (NULL != helper->host->username)
+ GNUNET_asprintf (&arg, "%s@%s", helper->host->username, helper->host->hostname);
+ else
+ GNUNET_asprintf (&arg, "%s", helper->host->hostname);
+
+ /* FIXME: Doesn't support ssh_port option! */
+ helper->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh", arg,
+ "peerStartHelper.pl", tempdir, NULL);
+ GNUNET_assert(helper->proc != NULL);
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "starting peers with cmd ssh %s %s %s\n", arg, "peerStartHelper.pl", tempdir);
+ GNUNET_SCHEDULER_add_now (&check_peers_started, helper);
+ GNUNET_free (tempdir);
+ GNUNET_free (baseservicehome);
+ GNUNET_free (arg);
+}
+#endif
/**
* Function which continues a peer group starting up
{
unsigned int i;
+#if USE_START_HELPER
+ if ((pg->num_hosts > 0) && (pg->hostkey_data != NULL))
+ {
+ struct PeerStartHelperContext *helper;
+ pg->starting = pg->num_hosts;
+ for (i = 0; i < pg->num_hosts; i++)
+ {
+ helper = GNUNET_malloc(sizeof(struct PeerStartHelperContext));
+ helper->pg = pg;
+ helper->host = &pg->hosts[i];
+ GNUNET_SCHEDULER_add_now(&start_peer_helper, helper);
+ }
+ }
+ else
+ {
+ pg->starting = 0;
+ for (i = 0; i < pg->total; i++)
+ {
+ GNUNET_SCHEDULER_add_now (&internal_continue_startup,
+ &pg->peers[i].internal_context);
+ }
+ }
+#else
pg->starting = 0;
for (i = 0; i < pg->total; i++)
{
GNUNET_SCHEDULER_add_now (&internal_continue_startup,
&pg->peers[i].internal_context);
- //GNUNET_TESTING_daemon_continue_startup(pg->peers[i].daemon);
}
+#endif
}
+#if USE_START_HELPER
+static void
+call_hostkey_callbacks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_TESTING_PeerGroup *pg = cls;
+ unsigned int i;
+ for (i = 0; i < pg->total; i++)
+ {
+ if (pg->peers[i].internal_context.hostkey_callback != NULL)
+ pg->peers[i].internal_context.hostkey_callback (pg->peers[i].internal_context.hostkey_cls,
+ &pg->peers[i].daemon->id,
+ pg->peers[i].daemon,
+ NULL);
+ }
+
+ if (pg->peers[0].internal_context.hostkey_callback == NULL)
+ GNUNET_TESTING_daemons_continue_startup (pg);
+}
+#endif
+
/**
* Start count gnunet instances with the same set of transports and
* applications. The port numbers (any option called "PORT") will be
* @return NULL on error, otherwise handle to control peer group
*/
struct GNUNET_TESTING_PeerGroup *
-GNUNET_TESTING_daemons_start(
- const struct GNUNET_CONFIGURATION_Handle *cfg,
+GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
unsigned int total,
unsigned int max_concurrent_connections,
unsigned int max_concurrent_ssh,
{
struct GNUNET_TESTING_PeerGroup *pg;
const struct GNUNET_TESTING_Host *hostpos;
-#if 0
- char *pos;
- const char *rpos;
- char *start;
-#endif
const char *hostname;
const char *username;
char *baseservicehome;
uint64_t total_hostkeys;
struct GNUNET_OS_Process *proc;
+ username = NULL;
if (0 == total)
{
GNUNET_break (0);
hostcnt = off;
minport = 0;
pg->num_hosts = off;
-
-#if NO_LL
- off = 2;
- /* skip leading spaces */
- while ((0 != *hostnames) && (isspace ((unsigned char) *hostnames)))
- hostnames++;
- rpos = hostnames;
- while ('\0' != *rpos)
- {
- if (isspace ((unsigned char) *rpos))
- off++;
- rpos++;
- }
- pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
- off = 0;
- start = GNUNET_strdup (hostnames);
- pos = start;
- while ('\0' != *pos)
- {
- if (isspace ((unsigned char) *pos))
- {
- *pos = '\0';
- if (strlen (start) > 0)
- {
- pg->hosts[off].minport = LOW_PORT;
- pg->hosts[off++].hostname = start;
- }
- start = pos + 1;
- }
- pos++;
- }
- if (strlen (start) > 0)
- {
- pg->hosts[off].minport = LOW_PORT;
- pg->hosts[off++].hostname = start;
- }
- if (off == 0)
- {
- GNUNET_free (start);
- GNUNET_free (pg->hosts);
- pg->hosts = NULL;
- }
- hostcnt = off;
- minport = 0; /* make gcc happy */
-#endif
}
else
{
else
proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh", arg,
"mkdir -p", tmpdir, NULL);
+ GNUNET_assert(proc != NULL);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Creating remote dir with command ssh %s %s %s\n", arg,
" mkdir -p ", tmpdir);
fs = 0;
GNUNET_log (
- GNUNET_ERROR_TYPE_WARNING,
+ GNUNET_ERROR_TYPE_DEBUG,
"Found file size %llu for hostkeys, expect hostkeys to be size %d\n",
fs, HOSTKEYFILESIZE);
else
{
total_hostkeys = fs / HOSTKEYFILESIZE;
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Will read %llu hostkeys from file\n", total_hostkeys);
pg->hostkey_data = GNUNET_malloc_large (fs);
GNUNET_assert (fs == GNUNET_DISK_file_read (fd, pg->hostkey_data, fs));
GNUNET_asprintf (&newservicehome, "%s/%s/%d/", baseservicehome, hostname, off);
else
GNUNET_asprintf (&newservicehome, "%s/%d/", baseservicehome, off);
+#if !USE_START_HELPER
GNUNET_free (baseservicehome);
+#endif
}
else
{
newservicehome);
GNUNET_free (newservicehome);
pg->peers[off].cfg = pcfg;
-#if DEFER
- /* Can we do this later? */
- pg->peers[off].allowed_peers =
- GNUNET_CONTAINER_multihashmap_create (total);
- pg->peers[off].connect_peers =
- GNUNET_CONTAINER_multihashmap_create (total);
- pg->peers[off].blacklisted_peers =
- GNUNET_CONTAINER_multihashmap_create (total);
-
-#endif
pg->peers[off].pg = pg;
pg->peers[off].internal_context.peer = &pg->peers[off];
pg->peers[off].internal_context.timeout = timeout;
pg->peers[off].internal_context.hostkey_cls = hostkey_cls;
pg->peers[off].internal_context.start_cb = cb;
pg->peers[off].internal_context.start_cb_cls = cb_cls;
-
+#if !USE_START_HELPER
GNUNET_SCHEDULER_add_now (&internal_start,
&pg->peers[off].internal_context);
+#else
+ if ((pg->hostkey_data != NULL) && (hostcnt > 0))
+ {
+ pg->peers[off].daemon = GNUNET_TESTING_daemon_start (pcfg,
+ timeout,
+ GNUNET_YES,
+ hostname,
+ username,
+ sshport,
+ pg->peers[off].internal_context.hostkey,
+ &internal_hostkey_callback,
+ &pg->peers[off].internal_context,
+ &internal_startup_callback,
+ &pg->peers[off].internal_context);
+ /**
+ * At this point, given that we had a hostkeyfile,
+ * we can call the hostkey callback!
+ * But first, we should copy (rsync) all of the configs
+ * and hostkeys to the remote peers. Then let topology
+ * creation happen, then call the peer start helper processes,
+ * then set pg->whatever_phase for each peer and let them
+ * enter the fsm to get the HELLO's for peers and start connecting.
+ */
+ }
+ else
+ {
+ GNUNET_SCHEDULER_add_now (&internal_start,
+ &pg->peers[off].internal_context);
+ }
+#endif
}
+
+#if USE_START_HELPER /* Now the peergroup has been set up, hostkeys and configs written to files. */
+ if ((pg->hostkey_data != NULL) && (hostcnt > 0))
+ {
+ for (off = 0; off < hostcnt; off++)
+ {
+ GNUNET_asprintf(&newservicehome, "%s/%s/", baseservicehome, pg->hosts[off].hostname);
+
+ if (NULL != username)
+ GNUNET_asprintf (&arg, "%s@%s:%s/%s", username, pg->hosts[off].hostname, baseservicehome, pg->hosts[off].hostname);
+ else
+ GNUNET_asprintf (&arg, "%s:%s/%s", pg->hosts[off].hostname, baseservicehome, pg->hosts[off].hostname);
+
+ /* FIXME: Doesn't support ssh_port option! */
+ proc = GNUNET_OS_start_process (NULL, NULL, "rsync", "rsync", "-r", newservicehome, arg, NULL);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "copying directory with command rsync -r %s %s\n", newservicehome, arg);
+
+ GNUNET_free (arg);
+ if (NULL == proc)
+ {
+ GNUNET_log (
+ GNUNET_ERROR_TYPE_ERROR,
+ _
+ ("Could not start `%s' process to copy configuration directory.\n"),
+ "scp");
+ GNUNET_assert(0);
+ }
+ GNUNET_OS_process_wait (proc);
+ GNUNET_OS_process_close (proc);
+ }
+ /* Now all the configuration files and hostkeys are copied to the remote host. Call the hostkey callback for each peer! */
+ GNUNET_SCHEDULER_add_now(&call_hostkey_callbacks, pg);
+ }
+ GNUNET_free (baseservicehome);
+#endif
return pg;
}
unsigned int *running_permute;
unsigned int *stopped_permute;
+ shutdown_ctx = NULL;
+ peer_shutdown_ctx = NULL;
+ peer_restart_ctx = NULL;
+ churn_startup_ctx = NULL;
+
running = 0;
stopped = 0;
GNUNET_SCHEDULER_add_now (&schedule_shutdown_task, peer_shutdown_ctx);
if (NULL != pg->peers[off].cfg)
+ {
GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
+ pg->peers[off].cfg = NULL;
+ }
#if OLD
conn_iter = pg->peers[off].allowed_peers_head;
while (conn_iter != NULL)