aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/testing/Makefile.am3
-rw-r--r--src/testing/test_testing_connect.c9
-rw-r--r--src/testing/test_testing_data_topology_clique.conf7
-rw-r--r--src/testing/test_testing_topology_clique.c305
-rw-r--r--src/testing/testing.c380
-rw-r--r--src/testing/testing_group.c228
6 files changed, 647 insertions, 285 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 4ddcc2b97..934ecc612 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -60,4 +60,5 @@ test_testing_topology_clique_LDADD = \
60EXTRA_DIST = \ 60EXTRA_DIST = \
61 test_testing_data.conf \ 61 test_testing_data.conf \
62 test_testing_connect_peer1.conf \ 62 test_testing_connect_peer1.conf \
63 test_testing_connect_peer2.conf 63 test_testing_connect_peer2.conf \
64 test_testing_data_topology_clique.conf
diff --git a/src/testing/test_testing_connect.c b/src/testing/test_testing_connect.c
index 70fcccd98..5cd6274ea 100644
--- a/src/testing/test_testing_connect.c
+++ b/src/testing/test_testing_connect.c
@@ -64,6 +64,12 @@ end1_cb (void *cls, const char *emsg)
64 d2 = NULL; 64 d2 = NULL;
65} 65}
66 66
67static void
68finish_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
69{
70 GNUNET_TESTING_daemon_stop (d1, &end1_cb, NULL);
71 d1 = NULL;
72}
67 73
68static void 74static void
69my_connect_complete (void *cls, 75my_connect_complete (void *cls,
@@ -75,8 +81,7 @@ my_connect_complete (void *cls,
75 struct GNUNET_TESTING_Daemon *second_daemon, 81 struct GNUNET_TESTING_Daemon *second_daemon,
76 const char *emsg) 82 const char *emsg)
77{ 83{
78 GNUNET_TESTING_daemon_stop (d1, &end1_cb, NULL); 84 GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL);
79 d1 = NULL;
80} 85}
81 86
82 87
diff --git a/src/testing/test_testing_data_topology_clique.conf b/src/testing/test_testing_data_topology_clique.conf
index a015b9b66..6f9a7739e 100644
--- a/src/testing/test_testing_data_topology_clique.conf
+++ b/src/testing/test_testing_data_topology_clique.conf
@@ -8,8 +8,9 @@ PORT = 2564
8[transport] 8[transport]
9PORT = 2565 9PORT = 2565
10PLUGINS = tcp 10PLUGINS = tcp
11#PREFIX = xterm -e xterm -T transport -e gdb -x cmd --args 11#PREFIX = xterm -e xterm -T transport -e gdb --args
12#PREFIX = valgrind --tool=memcheck --log-file=logs%p 12#PREFIX = valgrind --tool=memcheck --log-file=logs%p
13#DEBUG = YES
13 14
14[arm] 15[arm]
15PORT = 2566 16PORT = 2566
@@ -26,8 +27,10 @@ PORT = 2569
26 27
27[core] 28[core]
28PORT = 2570 29PORT = 2570
30#DEBUG = YES
29 31
30[testing] 32[testing]
31NUM_PEERS = 6 33NUM_PEERS = 2
32WEAKRANDOM = YES 34WEAKRANDOM = YES
33TOPOLOGY = 0 35TOPOLOGY = 0
36F2F = YES
diff --git a/src/testing/test_testing_topology_clique.c b/src/testing/test_testing_topology_clique.c
index 3d37d542b..a51d77f98 100644
--- a/src/testing/test_testing_topology_clique.c
+++ b/src/testing/test_testing_topology_clique.c
@@ -23,10 +23,10 @@
23 */ 23 */
24#include "platform.h" 24#include "platform.h"
25#include "gnunet_testing_lib.h" 25#include "gnunet_testing_lib.h"
26#include "gnunet_core_service.h"
26 27
27#define VERBOSE GNUNET_NO 28#define VERBOSE GNUNET_NO
28 29
29
30/** 30/**
31 * How long until we give up on connecting the peers? 31 * How long until we give up on connecting the peers?
32 */ 32 */
@@ -38,7 +38,9 @@ static int ok;
38 38
39static unsigned long long num_peers; 39static unsigned long long num_peers;
40 40
41static int total_connections; 41static unsigned int total_connections;
42
43static unsigned int expected_connections;
42 44
43static int peers_left; 45static int peers_left;
44 46
@@ -50,15 +52,238 @@ const struct GNUNET_CONFIGURATION_Handle *main_cfg;
50 52
51GNUNET_SCHEDULER_TaskIdentifier die_task; 53GNUNET_SCHEDULER_TaskIdentifier die_task;
52 54
55static struct GNUNET_CORE_Handle *peer1handle;
56
57static struct GNUNET_CORE_Handle *peer2handle;
58
59#define MTYPE 12345
53 60
54static void 61static void
55finish_testing () 62finish_testing ()
56{ 63{
57 GNUNET_assert (pg != NULL); 64 GNUNET_assert (pg != NULL);
65
66 if (peer1handle != NULL)
67 GNUNET_CORE_disconnect(peer1handle);
68 if (peer2handle != NULL)
69 GNUNET_CORE_disconnect(peer2handle);
70
58 GNUNET_TESTING_daemons_stop (pg); 71 GNUNET_TESTING_daemons_stop (pg);
59 ok = 0; 72 ok = 0;
60} 73}
61 74
75static int
76process_mtype (void *cls,
77 const struct GNUNET_PeerIdentity *peer,
78 const struct GNUNET_MessageHeader *message,
79 struct GNUNET_TIME_Relative latency,
80 uint32_t distance)
81{
82#if VERBOSE
83 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
84 "Receiving message from `%4s'.\n", GNUNET_i2s (peer));
85#endif
86 GNUNET_SCHEDULER_cancel (sched, die_task);
87 GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL);
88 return GNUNET_OK;
89}
90
91
92static void
93connect_notify (void *cls,
94 const struct GNUNET_PeerIdentity *peer,
95 struct GNUNET_TIME_Relative latency,
96 uint32_t distance)
97{
98#if VERBOSE
99 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
100 "Encrypted connection established to peer `%4s' with latency %llu\n",
101 GNUNET_i2s (peer), latency.value);
102#endif
103}
104
105
106static void
107disconnect_notify (void *cls,
108 const struct GNUNET_PeerIdentity *peer)
109{
110#if VERBOSE
111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
112 "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer));
113#endif
114}
115
116
117static int
118inbound_notify (void *cls,
119 const struct GNUNET_PeerIdentity *other,
120 const struct GNUNET_MessageHeader *message,
121 struct GNUNET_TIME_Relative latency,
122 uint32_t distance)
123{
124#if VERBOSE
125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
126 "Core provides inbound data from `%4s'.\n", GNUNET_i2s (other));
127#endif
128 return GNUNET_OK;
129}
130
131
132static int
133outbound_notify (void *cls,
134 const struct GNUNET_PeerIdentity *other,
135 const struct GNUNET_MessageHeader *message,
136 struct GNUNET_TIME_Relative latency,
137 uint32_t distance)
138{
139#if VERBOSE
140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
141 "Core notifies about outbound data for `%4s'.\n",
142 GNUNET_i2s (other));
143#endif
144 return GNUNET_OK;
145}
146
147static void
148end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
149{
150#if VERBOSE
151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
152 "End badly was called... stopping daemons.\n");
153#endif
154
155 if (peer1handle != NULL)
156 {
157 GNUNET_CORE_disconnect(peer1handle);
158 peer1handle = NULL;
159 }
160 if (peer2handle != NULL)
161 {
162 GNUNET_CORE_disconnect(peer2handle);
163 peer2handle = NULL;
164 }
165
166 if (pg != NULL)
167 {
168 GNUNET_TESTING_daemons_stop (pg);
169 ok = 7331; /* Opposite of leet */
170 }
171 else
172 ok = 401; /* Never got peers started */
173}
174
175static size_t
176transmit_ready (void *cls, size_t size, void *buf)
177{
178 struct GNUNET_MessageHeader *m;
179
180 GNUNET_assert (buf != NULL);
181 m = (struct GNUNET_MessageHeader *) buf;
182 m->type = htons (MTYPE);
183 m->size = htons (sizeof (struct GNUNET_MessageHeader));
184 GNUNET_SCHEDULER_cancel(sched, die_task);
185 die_task =
186 GNUNET_SCHEDULER_add_delayed (sched,
187 TIMEOUT, &end_badly, "from transmit ready");
188
189 return sizeof (struct GNUNET_MessageHeader);
190}
191
192
193static struct GNUNET_CORE_MessageHandler handlers[] = {
194 {&process_mtype, MTYPE, sizeof (struct GNUNET_MessageHeader)},
195 {NULL, 0, 0}
196};
197
198
199static void
200init_notify (void *cls,
201 struct GNUNET_CORE_Handle *server,
202 const struct GNUNET_PeerIdentity *my_identity,
203 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
204{
205 struct GNUNET_TESTING_Daemon *connected_peer = cls;
206 struct GNUNET_TESTING_Daemon *peer1;
207 struct GNUNET_TESTING_Daemon *peer2;
208
209 peer1 = GNUNET_TESTING_daemon_get(pg, 0);
210 peer2 = GNUNET_TESTING_daemon_get(pg, 1);
211#if VERBOSE
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
213 "Core connection to `%4s' established, setting up handles\n",
214 GNUNET_i2s (my_identity));
215#endif
216
217 if (connected_peer == peer1)
218 {
219 peer1handle = server;
220#if VERBOSE
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting core to peer 2\n");
222#endif
223 /* connect p2 */
224 GNUNET_CORE_connect (sched,
225 peer2->cfg,
226 TIMEOUT,
227 peer2,
228 &init_notify,
229 NULL,
230 &connect_notify,
231 &disconnect_notify,
232 &inbound_notify,
233 GNUNET_YES,
234 &outbound_notify, GNUNET_YES, handlers);
235 }
236 else
237 {
238 GNUNET_assert(connected_peer == peer2);
239 peer2handle = server;
240#if VERBOSE
241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
242 "Asking core (1) for transmission to peer `%4s'\n",
243 GNUNET_i2s (&peer2->id));
244#endif
245
246 if (NULL == GNUNET_CORE_notify_transmit_ready (peer1->server,
247 0,
248 TIMEOUT,
249 &peer2->id,
250 sizeof (struct GNUNET_MessageHeader),
251 &transmit_ready, &peer1))
252 {
253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
254 "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
255 GNUNET_i2s (&peer2->id));
256 }
257
258 }
259}
260
261
262static void
263send_test_messages ()
264{
265 struct GNUNET_TESTING_Daemon *peer1;
266 struct GNUNET_TESTING_Daemon *peer2;
267
268 peer1 = GNUNET_TESTING_daemon_get(pg, 0);
269 peer2 = GNUNET_TESTING_daemon_get(pg, 1);
270
271 die_task = GNUNET_SCHEDULER_add_delayed (sched,
272 TIMEOUT,
273 &end_badly, "from send test messages");
274
275 /* Send a message from peer 1 to peer 2 */
276 GNUNET_CORE_connect (sched,
277 peer1->cfg,
278 TIMEOUT,
279 peer1,
280 &init_notify,
281 NULL,
282 &connect_notify,
283 &disconnect_notify,
284 &inbound_notify,
285 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
286}
62 287
63void 288void
64topology_callback (void *cls, 289topology_callback (void *cls,
@@ -75,14 +300,17 @@ topology_callback (void *cls,
75 * even though we know that X peers exist in i... But we may want to 300 * even though we know that X peers exist in i... But we may want to
76 * know about the peer for logging purposes here (I'm sure we will actually 301 * know about the peer for logging purposes here (I'm sure we will actually
77 * so the API may need changed). Question, should the API expose what 302 * so the API may need changed). Question, should the API expose what
78 * a peer group is, or provide convenience/accessor functions? */ 303 * a peer group is, or provide convenience/accessor functions?
304 *
305 * For now, I've added accessor functions, which seems like a software
306 * engineering kind of solution, but who knows/cares. */
79 if (emsg == NULL) 307 if (emsg == NULL)
80 { 308 {
81 total_connections++; 309 total_connections++;
82#if VERBOSE 310#if VERBOSE
83 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n", 311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n",
84 GNUNET_TESTING_daemon_get_shortname (first_daemon), 312 first_daemon->shortname,
85 GNUNET_TESTING_daemon_get_shortname (second_daemon)); 313 second_daemon->shortname);
86#endif 314#endif
87 } 315 }
88#if VERBOSE 316#if VERBOSE
@@ -90,78 +318,37 @@ topology_callback (void *cls,
90 { 318 {
91 319
92 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect peer %s to peer %s with error %s\n", 320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect peer %s to peer %s with error %s\n",
93 GNUNET_TESTING_daemon_get_shortname (first_daemon), 321 first_daemon->shortname,
94 GNUNET_TESTING_daemon_get_shortname (second_daemon), emsg); 322 second_daemon->shortname, emsg);
95 } 323 }
96#endif 324#endif
97 325
98 if (total_connections * 2 == num_peers * (num_peers - 1)) 326 if (total_connections == expected_connections)
99 { 327 {
100#if VERBOSE 328#if VERBOSE
101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
102 "Created %d total connections, which is our target number! Ending test.\n", 330 "Created %d total connections, which is our target number! Ending test.\n",
103 total_connections * 2); 331 total_connections);
104#endif 332#endif
333
105 GNUNET_SCHEDULER_cancel (sched, die_task); 334 GNUNET_SCHEDULER_cancel (sched, die_task);
106 finish_testing (); 335 die_task = GNUNET_SCHEDULER_add_now (sched, &send_test_messages, NULL);
107 } 336 }
108 else 337 else
109 { 338 {
110#if VERBOSE 339#if VERBOSE
111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
112 "Have %d total connections, Need %d\n", 341 "Have %d total connections, Need %d\n",
113 total_connections * 2, num_peers * (num_peers - 1)); 342 total_connections, expected_connections);
114#endif 343#endif
115 } 344 }
116} 345}
117 346
118 347
119static void 348static void
120end_badly ()
121{
122 GNUNET_SCHEDULER_cancel (sched, die_task);
123 if (pg != NULL)
124 {
125 GNUNET_TESTING_daemons_stop (pg);
126 ok = 7331; /* Opposite of leet */
127 }
128 else
129 ok = 401; /* Never got peers started */
130}
131
132
133static void
134create_topology () 349create_topology ()
135{ 350{
136 int expected_connections; /* Is there any way we can use this to check 351 expected_connections = -1;
137 how many connections we are expecting to
138 finish the topology? It would be nice so
139 that we could estimate completion time,
140 but since GNUNET_TESTING_create_topology
141 goes off and starts connecting we may get
142 the topology callback before we have
143 finished and not know how many! We could
144 just never touch expected_connections,
145 and if we get called back when it's still
146 0 then we know we can't believe it. I
147 don't like this though, because it may
148 technically be possible for all connections
149 to have been created and the callback
150 called without us setting
151 expected_connections! Other options are
152 doing a trial connection setup, or
153 calculating the number of connections.
154 Problem with calculating is that for random
155 topologies this isn't reliable. Problem
156 with counting is we then iterate over them
157 twice instead of once. Probably the best
158 option though. Grr, also doing trial
159 connection set up means we need to call
160 fake_topology_create and then
161 real_topology_create which is also ugly.
162 Then we need to maintain state inside pg as
163 well, which I was trying to avoid. */
164
165 if ((pg != NULL) && (peers_left == 0)) 352 if ((pg != NULL) && (peers_left == 0))
166 { 353 {
167 /* create_topology will read the topology information from 354 /* create_topology will read the topology information from
@@ -178,11 +365,9 @@ create_topology ()
178 } 365 }
179 366
180 GNUNET_SCHEDULER_cancel (sched, die_task); 367 GNUNET_SCHEDULER_cancel (sched, die_task);
181
182 die_task = GNUNET_SCHEDULER_add_delayed (sched, 368 die_task = GNUNET_SCHEDULER_add_delayed (sched,
183 GNUNET_TIME_relative_multiply 369 TIMEOUT,
184 (GNUNET_TIME_UNIT_SECONDS, 20), 370 &end_badly, NULL);
185 &finish_testing, NULL);
186} 371}
187 372
188 373
@@ -259,7 +444,7 @@ run (void *cls,
259static int 444static int
260check () 445check ()
261{ 446{
262 char *const argv[] = { "test-testing-topology", 447 char *const argv[] = { "test-testing-topology-clique",
263 "-c", 448 "-c",
264 "test_testing_data_topology_clique.conf", 449 "test_testing_data_topology_clique.conf",
265#if VERBOSE 450#if VERBOSE
@@ -271,7 +456,7 @@ check ()
271 GNUNET_GETOPT_OPTION_END 456 GNUNET_GETOPT_OPTION_END
272 }; 457 };
273 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, 458 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
274 argv, "test-testing-topology", "nohelp", 459 argv, "test-testing-topology-clique", "nohelp",
275 options, &run, &ok); 460 options, &run, &ok);
276 return ok; 461 return ok;
277} 462}
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 8ceaace75..bddd0f30c 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -54,160 +54,6 @@
54 */ 54 */
55#define MAX_EXEC_WAIT_RUNS 50 55#define MAX_EXEC_WAIT_RUNS 50
56 56
57/**
58 * Phases of starting GNUnet on a system.
59 */
60enum StartPhase
61{
62 /**
63 * Copy the configuration file to the target system.
64 */
65 SP_COPYING,
66
67 /**
68 * Configuration file has been copied, start ARM on target system.
69 */
70 SP_COPIED,
71
72 /**
73 * ARM has been started, check that it has properly daemonized and
74 * then try to connect to the CORE service (which should be
75 * auto-started by ARM).
76 */
77 SP_START_ARMING,
78
79 /**
80 * We're waiting for CORE to start.
81 */
82 SP_START_CORE,
83
84 /**
85 * Core has notified us that we've established a connection to the service.
86 * The main FSM halts here and waits to be moved to UPDATE or CLEANUP.
87 */
88 SP_START_DONE,
89
90 /**
91 * We've been asked to terminate the instance and are now waiting for
92 * the remote command to delete the configuration file to complete.
93 */
94 SP_CLEANUP,
95
96 /**
97 * We've received a configuration update and are currently waiting for
98 * the copy process for the update to complete. Once it is, we will
99 * return to "SP_START_DONE" (and rely on ARM to restart all affected
100 * services).
101 */
102 SP_CONFIG_UPDATE
103};
104
105
106/**
107 * Handle for a GNUnet daemon (technically a set of
108 * daemons; the handle is really for the master ARM
109 * daemon) started by the testing library.
110 */
111struct GNUNET_TESTING_Daemon
112{
113 /**
114 * Our scheduler.
115 */
116 struct GNUNET_SCHEDULER_Handle *sched;
117
118 /**
119 * Our configuration.
120 */
121 struct GNUNET_CONFIGURATION_Handle *cfg;
122
123 /**
124 * Host to run GNUnet on.
125 */
126 char *hostname;
127
128 /* Result of GNUNET_i2s of this peer, for printing */
129 char *shortname;
130
131 /**
132 * Username we are using.
133 */
134 char *username;
135
136 /**
137 * Name of the configuration file
138 */
139 char *cfgfile;
140
141 /**
142 * Function to call when the peer is running.
143 */
144 GNUNET_TESTING_NotifyDaemonRunning cb;
145
146 /**
147 * Closure for cb.
148 */
149 void *cb_cls;
150
151 /**
152 * Arguments from "daemon_stop" call.
153 */
154 GNUNET_TESTING_NotifyCompletion dead_cb;
155
156 /**
157 * Closure for 'dead_cb'.
158 */
159 void *dead_cb_cls;
160
161 /**
162 * Arguments from "daemon_stop" call.
163 */
164 GNUNET_TESTING_NotifyCompletion update_cb;
165
166 /**
167 * Closure for 'update_cb'.
168 */
169 void *update_cb_cls;
170
171 /**
172 * Identity of this peer (once started).
173 */
174 struct GNUNET_PeerIdentity id;
175
176 /**
177 * Flag to indicate that we've already been asked
178 * to terminate (but could not because some action
179 * was still pending).
180 */
181 int dead;
182
183 /**
184 * PID of the process that we started last.
185 */
186 pid_t pid;
187
188 /**
189 * How many iterations have we been waiting for
190 * the started process to complete?
191 */
192 unsigned int wait_runs;
193
194 /**
195 * In which phase are we during the start of
196 * this process?
197 */
198 enum StartPhase phase;
199
200 /**
201 * ID of the current task.
202 */
203 GNUNET_SCHEDULER_TaskIdentifier task;
204
205 /**
206 * Handle to the server.
207 */
208 struct GNUNET_CORE_Handle *server;
209};
210
211 57
212/** 58/**
213 * Function called after GNUNET_CORE_connect has succeeded 59 * Function called after GNUNET_CORE_connect has succeeded
@@ -793,11 +639,21 @@ struct ConnectContext
793 */ 639 */
794 struct GNUNET_TESTING_Daemon *d1; 640 struct GNUNET_TESTING_Daemon *d1;
795 641
642 /*
643 * Handle to core of first daemon (to check connect)
644 */
645 struct GNUNET_CORE_Handle * d1core;
646
796 /** 647 /**
797 * Testing handle to the second daemon. 648 * Testing handle to the second daemon.
798 */ 649 */
799 struct GNUNET_TESTING_Daemon *d2; 650 struct GNUNET_TESTING_Daemon *d2;
800 651
652 /*
653 * Handle to core of second daemon (to check connect)
654 */
655 struct GNUNET_CORE_Handle * d2core;
656
801 /** 657 /**
802 * Transport handle to the first daemon. 658 * Transport handle to the first daemon.
803 */ 659 */
@@ -830,10 +686,61 @@ struct ConnectContext
830 */ 686 */
831 struct GNUNET_TIME_Absolute timeout; 687 struct GNUNET_TIME_Absolute timeout;
832 688
689 /*
690 * Hello timeout task
691 */
692 GNUNET_SCHEDULER_TaskIdentifier hello_send_task;
693
694 /*
695 * Connect timeout task
696 */
697 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
698
699 /**
700 * When should this operation be complete (or we must trigger
701 * a timeout).
702 */
703 struct GNUNET_TIME_Relative timeout_hello;
704
705 /*
706 * The current hello message we have (for d1)
707 */
708 struct GNUNET_MessageHeader *hello;
709
710 /*
711 * Was the connection successful?
712 */
713 int connected;
833}; 714};
834 715
835 716
836/** 717/**
718 * Receive the HELLO from one peer, give it to the other
719 * and ask them to connect.
720 *
721 * @param cls "struct ConnectContext"
722 * @param message HELLO message of peer
723 */
724static void
725process_hello (void *cls, const struct GNUNET_MessageHeader *message)
726{
727 struct ConnectContext *ctx = cls;
728
729#if DEBUG_TESTING
730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
731 "Received `%s' from transport service of `%4s'\n",
732 "HELLO", GNUNET_i2s (&ctx->d1->id));
733#endif
734
735 GNUNET_assert (message != NULL);
736 GNUNET_free_non_null(ctx->hello);
737 ctx->hello = GNUNET_malloc(ntohs(message->size));
738 memcpy(ctx->hello, message, ntohs(message->size));
739
740}
741
742
743/**
837 * Notify callback about success or failure of the attempt 744 * Notify callback about success or failure of the attempt
838 * to connect the two peers 745 * to connect the two peers
839 * 746 *
@@ -846,16 +753,33 @@ notify_connect_result (void *cls,
846{ 753{
847 struct ConnectContext *ctx = cls; 754 struct ConnectContext *ctx = cls;
848 755
756 GNUNET_TRANSPORT_get_hello_cancel (ctx->d1th, &process_hello, ctx);
757 GNUNET_SCHEDULER_cancel(ctx->d1->sched, ctx->hello_send_task);
758
849 if (ctx->cb != NULL) 759 if (ctx->cb != NULL)
850 { 760 {
851 if ((tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT) != 0) 761 if (ctx->connected == GNUNET_NO)
852 ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg, 762 {
853 ctx->d2->cfg, ctx->d1, ctx->d2, 763 ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg,
854 _("Peers failed to connect")); 764 ctx->d2->cfg, ctx->d1, ctx->d2,
765 _("Peers failed to connect"));
766 }
855 else 767 else
856 ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg, 768 {
857 ctx->d2->cfg, ctx->d1, ctx->d2, NULL); 769 ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg,
770 ctx->d2->cfg, ctx->d1, ctx->d2, NULL);
771 GNUNET_SCHEDULER_cancel(ctx->d1->sched, ctx->timeout_task);
772 }
858 } 773 }
774
775 ctx->ntr = NULL;
776 GNUNET_TRANSPORT_disconnect (ctx->d1th);
777 ctx->d1th = NULL;
778 GNUNET_TRANSPORT_disconnect (ctx->d2th);
779 ctx->d2th = NULL;
780 GNUNET_CORE_disconnect (ctx->d1core);
781 ctx->d1core = NULL;
782
859 GNUNET_free (ctx); 783 GNUNET_free (ctx);
860} 784}
861 785
@@ -868,74 +792,48 @@ notify_connect_result (void *cls,
868 * @param buf where to copy the message, NULL on error 792 * @param buf where to copy the message, NULL on error
869 * @return number of bytes copied to buf 793 * @return number of bytes copied to buf
870 */ 794 */
871static size_t 795static void
872transmit_ready (void *cls, size_t size, void *buf) 796connect_notify (void *cls, const struct GNUNET_PeerIdentity * peer, struct GNUNET_TIME_Relative latency,
797 uint32_t distance)
873{ 798{
874 struct ConnectContext *ctx = cls; 799 struct ConnectContext *ctx = cls;
875 800
876#if DEBUG_TESTING 801#if DEBUG_TESTING
877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 802 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
878 "Core notified us about readiness to transmit message, connection must be up!\n"); 803 "Core notified us about connection to a peer\n\n\n");
879#endif 804#endif
880 ctx->ntr = NULL; 805 if (memcmp(&ctx->d2->id, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
881 GNUNET_TRANSPORT_disconnect (ctx->d1th); 806 {
882 ctx->d1th = NULL; 807#if DEBUG_TESTING
883 GNUNET_TRANSPORT_disconnect (ctx->d2th); 808 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
884 ctx->d2th = NULL; 809 "Core notified us about connection to peer %s\n\n\n", GNUNET_i2s(peer));
885 GNUNET_SCHEDULER_add_continuation (ctx->d1->sched,
886 &notify_connect_result,
887 ctx,
888 (buf == NULL) ?
889 GNUNET_SCHEDULER_REASON_TIMEOUT :
890 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
891 return 0;
892}
893
894
895#if 0
896static void
897timeout_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
898{
899 GNUNET_TRANSPORT_get_hello_cancel (ctx->d1th, &process_hello, ctx);
900 GNUNET_TRANSPORT_disconnect (ctx->d1th);
901 GNUNET_TRANSPORT_disconnect (ctx->d2th);
902 if (NULL != ctx->cb)
903 ctx->cb (ctx->cb_cls, _("Failed to receive `HELLO' from peer\n"));
904 GNUNET_free (ctx);
905}
906#endif 810#endif
811 /*
812 * If we disconnect here, then the hello may never get sent (if it was delayed!)
813 * However I'm sure there was a reason it was here... so I'm just commenting.
814 */
815 ctx->connected = GNUNET_YES;
816 GNUNET_SCHEDULER_add_now (ctx->d1->sched,
817 &notify_connect_result,
818 ctx);
819 }
907 820
821}
908 822
909/**
910 * Receive the HELLO from one peer, give it to the other
911 * and ask them to connect.
912 *
913 * @param cls "struct ConnectContext"
914 * @param message HELLO message of peer
915 */
916static void 823static void
917process_hello (void *cls, const struct GNUNET_MessageHeader *message) 824send_hello(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
918{ 825{
919 struct ConnectContext *ctx = cls; 826 struct ConnectContext *ctx = cls;
920 827
921 /* first of all, stop the notification stuff */ 828 GNUNET_assert (ctx->hello != NULL);
922 GNUNET_TRANSPORT_get_hello_cancel (ctx->d1th, &process_hello, ctx); 829 GNUNET_TRANSPORT_offer_hello (ctx->d2th, ctx->hello);
923#if DEBUG_TESTING 830
924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 831 ctx->timeout_hello = GNUNET_TIME_relative_multiply(ctx->timeout_hello, 2);
925 "Received `%s' from transport service of `%4s'\n", 832 ctx->hello_send_task = GNUNET_SCHEDULER_add_delayed(ctx->d1->sched, ctx->timeout_hello, &send_hello, ctx);
926 "HELLO", GNUNET_i2s (&ctx->d1->id));
927#endif
928 GNUNET_assert (message != NULL);
929 GNUNET_TRANSPORT_offer_hello (ctx->d2th, message);
930 ctx->ntr
931 = GNUNET_CORE_notify_transmit_ready (ctx->d2->server,
932 0,
933 GNUNET_TIME_absolute_get_remaining
934 (ctx->timeout), &ctx->d1->id,
935 sizeof (struct GNUNET_MessageHeader),
936 &transmit_ready, ctx);
937} 833}
938 834
835
836#if HIDDEN
939/* 837/*
940 * Accessor function since we have hidden what GNUNET_TESTING_Daemon is 838 * Accessor function since we have hidden what GNUNET_TESTING_Daemon is
941 * 839 *
@@ -947,6 +845,32 @@ GNUNET_TESTING_daemon_get_shortname (struct GNUNET_TESTING_Daemon *d)
947 return d->shortname; 845 return d->shortname;
948} 846}
949 847
848char *
849GNUNET_TESTING_daemon_get_hostname (struct GNUNET_TESTING_Daemon *d)
850{
851 return d->hostname;
852}
853
854char *
855GNUNET_TESTING_daemon_get_username (struct GNUNET_TESTING_Daemon *d)
856{
857 return d->username;
858}
859
860struct GNUNET_PeerIdentity *
861GNUNET_TESTING_daemon_get_peer (struct GNUNET_TESTING_Daemon *d)
862{
863 return &d->id;
864}
865
866struct GNUNET_CONFIGURATION_Handle *
867GNUNET_TESTING_daemon_get_config (struct GNUNET_TESTING_Daemon *d)
868{
869 return d->cfg;
870}
871#endif
872
873
950/** 874/**
951 * Establish a connection between two GNUnet daemons. 875 * Establish a connection between two GNUnet daemons.
952 * 876 *
@@ -965,6 +889,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
965 void *cb_cls) 889 void *cb_cls)
966{ 890{
967 struct ConnectContext *ctx; 891 struct ConnectContext *ctx;
892 static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
968 893
969 if ((d1->server == NULL) || (d2->server == NULL)) 894 if ((d1->server == NULL) || (d2->server == NULL))
970 { 895 {
@@ -979,6 +904,8 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
979 ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); 904 ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
980 ctx->cb = cb; 905 ctx->cb = cb;
981 ctx->cb_cls = cb_cls; 906 ctx->cb_cls = cb_cls;
907 ctx->timeout_hello = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 800);
908 ctx->connected = GNUNET_NO;
982#if DEBUG_TESTING 909#if DEBUG_TESTING
983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 910 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
984 "Asked to connect peer %s to peer %s\n", 911 "Asked to connect peer %s to peer %s\n",
@@ -986,6 +913,24 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 913 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
987 "Connecting to transport service of peer %s\n", d1->shortname); 914 "Connecting to transport service of peer %s\n", d1->shortname);
988#endif 915#endif
916
917 ctx->d1core = GNUNET_CORE_connect (d1->sched,
918 d1->cfg,
919 timeout,
920 ctx,
921 NULL,
922 NULL, &connect_notify, NULL,
923 NULL, GNUNET_NO,
924 NULL, GNUNET_NO, no_handlers);
925 if (ctx->d1core == NULL)
926 {
927 GNUNET_free (ctx);
928 if (NULL != cb)
929 cb (cb_cls, &d1->id, &d2->id, d1->cfg, d2->cfg, d1, d2,
930 _("Failed to connect to core service of first peer!\n"));
931 return;
932 }
933
989 ctx->d1th = GNUNET_TRANSPORT_connect (d1->sched, 934 ctx->d1th = GNUNET_TRANSPORT_connect (d1->sched,
990 d1->cfg, d1, NULL, NULL, NULL); 935 d1->cfg, d1, NULL, NULL, NULL);
991 if (ctx->d1th == NULL) 936 if (ctx->d1th == NULL)
@@ -1004,6 +949,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
1004 "Connecting to transport service of peer %s\n", d2->shortname); 949 "Connecting to transport service of peer %s\n", d2->shortname);
1005 950
1006#endif 951#endif
952
1007 ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched, 953 ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched,
1008 d2->cfg, d2, NULL, NULL, NULL); 954 d2->cfg, d2, NULL, NULL, NULL);
1009 if (ctx->d2th == NULL) 955 if (ctx->d2th == NULL)
@@ -1020,9 +966,13 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
1020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 966 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1021 "Asking for hello from peer %s\n", GNUNET_i2s (&d1->id)); 967 "Asking for hello from peer %s\n", GNUNET_i2s (&d1->id));
1022#endif 968#endif
1023 /* FIXME: need to handle timeout: start timeout task 969
1024 as well here! (use 'timeout_hello_task') */ 970 ctx->timeout_task = GNUNET_SCHEDULER_add_delayed (d1->sched,
971 timeout,
972 &notify_connect_result, ctx);
973
1025 GNUNET_TRANSPORT_get_hello (ctx->d1th, &process_hello, ctx); 974 GNUNET_TRANSPORT_get_hello (ctx->d1th, &process_hello, ctx);
975 ctx->hello_send_task = GNUNET_SCHEDULER_add_delayed(ctx->d1->sched, ctx->timeout_hello, &send_hello, ctx);
1026} 976}
1027 977
1028 978
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c
index 424dada34..fd1338e1e 100644
--- a/src/testing/testing_group.c
+++ b/src/testing/testing_group.c
@@ -46,6 +46,20 @@
46 46
47#define CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) 47#define CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
48 48
49struct PeerConnection
50{
51 /*
52 * Linked list
53 */
54 struct PeerConnection *next;
55
56 /*
57 * Pointer to daemon handle
58 */
59 struct GNUNET_TESTING_Daemon *daemon;
60
61};
62
49/** 63/**
50 * Data we keep per peer. 64 * Data we keep per peer.
51 */ 65 */
@@ -63,6 +77,12 @@ struct PeerData
63 * Handle for controlling the daemon. 77 * Handle for controlling the daemon.
64 */ 78 */
65 struct GNUNET_TESTING_Daemon *daemon; 79 struct GNUNET_TESTING_Daemon *daemon;
80
81 /*
82 * Linked list of peer connections (simply indexes of PeerGroup)
83 * FIXME: Question, store pointer or integer? Pointer for now...
84 */
85 struct PeerConnection *connected_peers;
66}; 86};
67 87
68 88
@@ -202,6 +222,79 @@ make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port)
202 return uc.ret; 222 return uc.ret;
203} 223}
204 224
225/*
226 * Add entries to the peers connected list
227 *
228 * @param pg the peer group we are working with
229 * @param first index of the first peer
230 * @param second index of the second peer
231 *
232 * @return the number of connections added (can be 0 1 or 2)
233 *
234 * FIXME: add both, or only add one?
235 * - if both are added, then we have to keep track
236 * when connecting so we don't double connect
237 * - if only one is added, we need to iterate over
238 * both lists to find out if connection already exists
239 * - having both allows the whitelisting/friend file
240 * creation to be easier
241 *
242 * -- For now, add both, we have to iterate over each to
243 * check for duplicates anyways, so we'll take the performance
244 * hit assuming we don't have __too__ many connections
245 *
246 */
247static int
248add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
249{
250 int added;
251 struct PeerConnection *first_iter;
252 struct PeerConnection *second_iter;
253 int add_first;
254 int add_second;
255 struct PeerConnection *new_first;
256 struct PeerConnection *new_second;
257
258 first_iter = pg->peers[first].connected_peers;
259 add_first = GNUNET_YES;
260 while (first_iter != NULL)
261 {
262 if (first_iter->daemon == pg->peers[second].daemon)
263 add_first = GNUNET_NO;
264 first_iter = first_iter->next;
265 }
266
267 second_iter = pg->peers[second].connected_peers;
268 add_second = GNUNET_YES;
269 while (second_iter != NULL)
270 {
271 if (second_iter->daemon == pg->peers[first].daemon)
272 add_second = GNUNET_NO;
273 second_iter = second_iter->next;
274 }
275
276 added = 0;
277 if (add_first)
278 {
279 new_first = GNUNET_malloc(sizeof(struct PeerConnection));
280 new_first->daemon = pg->peers[second].daemon;
281 new_first->next = pg->peers[first].connected_peers;
282 pg->peers[first].connected_peers = new_first;
283 added++;
284 }
285
286 if (add_second)
287 {
288 new_second = GNUNET_malloc(sizeof(struct PeerConnection));
289 new_second->daemon = pg->peers[first].daemon;
290 new_second->next = pg->peers[second].connected_peers;
291 pg->peers[second].connected_peers = new_second;
292 added++;
293 }
294
295 return added;
296}
297
205static int 298static int
206create_clique (struct GNUNET_TESTING_PeerGroup *pg) 299create_clique (struct GNUNET_TESTING_PeerGroup *pg)
207{ 300{
@@ -221,12 +314,12 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg)
221 "Connecting peer %d to peer %d\n", 314 "Connecting peer %d to peer %d\n",
222 outer_count, inner_count); 315 outer_count, inner_count);
223#endif 316#endif
224 GNUNET_TESTING_daemons_connect (pg->peers[outer_count].daemon, 317 connect_attempts += add_connections(pg, outer_count, inner_count);
318 /*GNUNET_TESTING_daemons_connect (pg->peers[outer_count].daemon,
225 pg->peers[inner_count].daemon, 319 pg->peers[inner_count].daemon,
226 CONNECT_TIMEOUT, 320 CONNECT_TIMEOUT,
227 pg->notify_connection, 321 pg->notify_connection,
228 pg->notify_connection_cls); 322 pg->notify_connection_cls);*/
229 connect_attempts++;
230 } 323 }
231 } 324 }
232 325
@@ -235,6 +328,111 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg)
235 328
236 329
237/* 330/*
331 * Create the friend files based on the PeerConnection's
332 * of each peer in the peer group, and copy the files
333 * to the appropriate place
334 *
335 * @param pg the peer group we are dealing with
336 */
337static void
338create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
339{
340 FILE *temp_friend_handle;
341 unsigned int pg_iter;
342 struct PeerConnection *connection_iter;
343 struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
344 char *temp_service_path;
345 pid_t pid;
346 char *arg;
347 struct GNUNET_PeerIdentity *temppeer;
348 const char * mytemp;
349
350 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
351 {
352 mytemp = GNUNET_DISK_mktemp("friends");
353 temp_friend_handle = fopen (mytemp, "wt");
354 connection_iter = pg->peers[pg_iter].connected_peers;
355 while (connection_iter != NULL)
356 {
357 temppeer = &connection_iter->daemon->id;
358 GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc);
359 fprintf(temp_friend_handle, "%s\n", (char *)&peer_enc);
360 connection_iter = connection_iter->next;
361 }
362
363 fclose(temp_friend_handle);
364
365 GNUNET_CONFIGURATION_get_value_string(pg->peers[pg_iter].daemon->cfg, "PATHS", "SERVICEHOME", &temp_service_path);
366
367 if (temp_service_path == NULL)
368 {
369 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
370 _("No SERVICEHOME specified in peer configuration, can't copy friends file!\n"));
371 fclose(temp_friend_handle);
372 unlink(mytemp);
373 break;
374 }
375
376 if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */
377 {
378 GNUNET_asprintf (&arg, "%s/friends", temp_service_path);
379 pid = GNUNET_OS_start_process ("mv",
380 "mv", mytemp, arg, NULL);
381#if VERBOSE_TESTING
382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
383 _("Copying file with command cp %s %s\n"), mytemp, arg);
384#endif
385 GNUNET_free(arg);
386 }
387 else /* Remote, scp the file to the correct place */
388 {
389 if (NULL != pg->peers[pg_iter].daemon->username)
390 GNUNET_asprintf (&arg, "%s@%s:%s/friends", pg->peers[pg_iter].daemon->username, pg->peers[pg_iter].daemon->hostname, temp_service_path);
391 else
392 GNUNET_asprintf (&arg, "%s:%s/friends", pg->peers[pg_iter].daemon->hostname, temp_service_path);
393 pid = GNUNET_OS_start_process ("scp",
394 "scp", mytemp, arg, NULL);
395#if VERBOSE_TESTING
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
397 _("Copying file with command scp %s %s\n"), mytemp, arg);
398#endif
399 GNUNET_free(arg);
400 }
401
402 }
403}
404
405
406
407/*
408 * Connect the topology as specified by the PeerConnection's
409 * of each peer in the peer group
410 *
411 * @param pg the peer group we are dealing with
412 */
413static void
414connect_topology (struct GNUNET_TESTING_PeerGroup *pg)
415{
416 unsigned int pg_iter;
417 struct PeerConnection *connection_iter;
418
419 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
420 {
421 connection_iter = pg->peers[pg_iter].connected_peers;
422 while (connection_iter != NULL)
423 {
424 GNUNET_TESTING_daemons_connect (pg->peers[pg_iter].daemon,
425 connection_iter->daemon,
426 CONNECT_TIMEOUT,
427 pg->notify_connection,
428 pg->notify_connection_cls);
429 connection_iter = connection_iter->next;
430 }
431 }
432}
433
434
435/*
238 * Takes a peer group and attempts to create a topology based on the 436 * Takes a peer group and attempts to create a topology based on the
239 * one specified in the configuration file. Returns the number of connections 437 * one specified in the configuration file. Returns the number of connections
240 * that will attempt to be created, but this will happen asynchronously(?) so 438 * that will attempt to be created, but this will happen asynchronously(?) so
@@ -247,7 +445,6 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg)
247int 445int
248GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg) 446GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg)
249{ 447{
250 /* Put stuff at home in here... */
251 unsigned long long topology_num; 448 unsigned long long topology_num;
252 int ret; 449 int ret;
253 450
@@ -330,6 +527,11 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg)
330 ret = GNUNET_SYSERR; 527 ret = GNUNET_SYSERR;
331 break; 528 break;
332 } 529 }
530
531 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F"))
532 create_and_copy_friend_files(pg);
533
534 connect_topology(pg);
333 } 535 }
334 else 536 else
335 { 537 {
@@ -374,6 +576,7 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
374 const char *hostname; 576 const char *hostname;
375 char *baseservicehome; 577 char *baseservicehome;
376 char *newservicehome; 578 char *newservicehome;
579 char *tmpdir;
377 struct GNUNET_CONFIGURATION_Handle *pcfg; 580 struct GNUNET_CONFIGURATION_Handle *pcfg;
378 unsigned int off; 581 unsigned int off;
379 unsigned int hostcnt; 582 unsigned int hostcnt;
@@ -475,7 +678,9 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
475 } 678 }
476 else 679 else
477 { 680 {
478 tempsize = snprintf (NULL, 0, "%s/%d/", "/tmp/gnunet-testing-test-test", off) + 1; /* FIXME: set a default path, or read the TMPDIR variable or something */ 681 tmpdir = getenv ("TMPDIR");
682 tmpdir = tmpdir ? tmpdir : "/tmp";
683 tempsize = snprintf (NULL, 0, "%s/%s/%d/", tmpdir, "gnunet-testing-test-test", off) + 1;
479 newservicehome = GNUNET_malloc (tempsize); 684 newservicehome = GNUNET_malloc (tempsize);
480 snprintf (newservicehome, tempsize, "%s/%d/", 685 snprintf (newservicehome, tempsize, "%s/%d/",
481 "/tmp/gnunet-testing-test-test", off); 686 "/tmp/gnunet-testing-test-test", off);
@@ -496,6 +701,18 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
496 return pg; 701 return pg;
497} 702}
498 703
704/*
705 * Get a daemon by number, so callers don't have to do nasty
706 * offsetting operation.
707 */
708struct GNUNET_TESTING_Daemon *
709GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int position)
710{
711 if (position < pg->total)
712 return pg->peers[position].daemon;
713 else
714 return NULL;
715}
499 716
500/** 717/**
501 * Shutdown all peers started in the given group. 718 * Shutdown all peers started in the given group.
@@ -513,6 +730,7 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg)
513 continuations to be called here? This 730 continuations to be called here? This
514 would require us to take a continuation 731 would require us to take a continuation
515 as well... */ 732 as well... */
733
516 if (NULL != pg->peers[off].daemon) 734 if (NULL != pg->peers[off].daemon)
517 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL); 735 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL);
518 if (NULL != pg->peers[off].cfg) 736 if (NULL != pg->peers[off].cfg)