aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/experimentation/Makefile.am72
-rw-r--r--src/experimentation/experimentation.conf.in11
-rw-r--r--src/experimentation/gnunet-daemon-experimentation.c124
-rw-r--r--src/experimentation/gnunet-daemon-experimentation.h499
-rw-r--r--src/experimentation/gnunet-daemon-experimentation_capabilities.c172
-rw-r--r--src/experimentation/gnunet-daemon-experimentation_experiments.c503
-rw-r--r--src/experimentation/gnunet-daemon-experimentation_nodes.c1157
-rw-r--r--src/experimentation/gnunet-daemon-experimentation_scheduler.c448
-rw-r--r--src/experimentation/gnunet-daemon-experimentation_storage.c53
-rw-r--r--src/experimentation/test_experimentation_clique.conf43
-rw-r--r--src/experimentation/test_experimentation_clique_connect.c416
-rw-r--r--src/experimentation/test_experimentation_clique_run.c389
-rw-r--r--src/experimentation/test_experiments.exp9
15 files changed, 0 insertions, 3900 deletions
diff --git a/configure.ac b/configure.ac
index 1db9b1b76..4391b20a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1443,8 +1443,6 @@ src/dv/Makefile
1443src/dv/dv.conf 1443src/dv/dv.conf
1444src/env/Makefile 1444src/env/Makefile
1445src/exit/Makefile 1445src/exit/Makefile
1446src/experimentation/Makefile
1447src/experimentation/experimentation.conf
1448src/fragmentation/Makefile 1446src/fragmentation/Makefile
1449src/fs/Makefile 1447src/fs/Makefile
1450src/fs/fs.conf 1448src/fs/fs.conf
diff --git a/src/Makefile.am b/src/Makefile.am
index 0902d259f..0452a4ad3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,7 +7,6 @@ if HAVE_TESTING
7 TESTBED = testbed 7 TESTBED = testbed
8 CONSENSUS = consensus 8 CONSENSUS = consensus
9 SECRETSHARING = secretsharing 9 SECRETSHARING = secretsharing
10 EXPERIMENTATION = experimentation
11 SENSOR = sensor 10 SENSOR = sensor
12 SENSORDASHBOARD = sensordashboard 11 SENSORDASHBOARD = sensordashboard
13endif 12endif
@@ -23,7 +22,6 @@ if HAVE_EXPERIMENTAL
23 social \ 22 social \
24 $(CONSENSUS) \ 23 $(CONSENSUS) \
25 $(SECRETSHARING) \ 24 $(SECRETSHARING) \
26 $(EXPERIMENTATION) \
27 $(SENSOR) \ 25 $(SENSOR) \
28 $(SENSORDASHBOARD) 26 $(SENSORDASHBOARD)
29endif 27endif
diff --git a/src/experimentation/Makefile.am b/src/experimentation/Makefile.am
deleted file mode 100644
index 26a467393..000000000
--- a/src/experimentation/Makefile.am
+++ /dev/null
@@ -1,72 +0,0 @@
1AM_CPPFLAGS = -I$(top_srcdir)/src/include
2
3pkgcfgdir= $(pkgdatadir)/config.d/
4
5libexecdir= $(pkglibdir)/libexec/
6
7pkgcfg_DATA = \
8 experimentation.conf
9
10if MINGW
11 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32
12endif
13
14if USE_COVERAGE
15 AM_CFLAGS = --coverage -O0
16 XLIB = -lgcov
17endif
18
19
20if HAVE_EXPERIMENTAL
21 TEXT_EXP_CLIQUE = test_experimentation_clique_connect test_experimentation_clique_run
22endif
23
24check_PROGRAMS = \
25 $(TEXT_EXP_CLIQUE)
26
27if ENABLE_TEST_RUN
28 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
29 TESTS = \
30 $(TEXT_EXP_CLIQUE)
31endif
32
33libexec_PROGRAMS = \
34 gnunet-daemon-experimentation
35
36gnunet_daemon_experimentation_SOURCES = \
37 gnunet-daemon-experimentation.c gnunet-daemon-experimentation.h \
38 gnunet-daemon-experimentation_capabilities.c \
39 gnunet-daemon-experimentation_nodes.c \
40 gnunet-daemon-experimentation_scheduler.c \
41 gnunet-daemon-experimentation_experiments.c \
42 gnunet-daemon-experimentation_storage.c
43gnunet_daemon_experimentation_LDADD = \
44 $(top_builddir)/src/core/libgnunetcore.la \
45 $(top_builddir)/src/statistics/libgnunetstatistics.la \
46 $(top_builddir)/src/util/libgnunetutil.la
47
48test_experimentation_clique_connect_SOURCES = \
49 test_experimentation_clique_connect.c
50test_experimentation_clique_connect_LDADD = \
51 $(top_builddir)/src/util/libgnunetutil.la \
52 $(top_builddir)/src/statistics/libgnunetstatistics.la \
53 $(top_builddir)/src/testbed/libgnunettestbed.la
54
55test_experimentation_clique_run_SOURCES = \
56 test_experimentation_clique_run.c
57test_experimentation_clique_run_LDADD = \
58 $(top_builddir)/src/util/libgnunetutil.la \
59 $(top_builddir)/src/statistics/libgnunetstatistics.la \
60 $(top_builddir)/src/testbed/libgnunettestbed.la
61
62#test_experimentation_clique_run_SOURCES = \
63# test_experimentation_clique_run.c
64#test_experimentation_clique_run_LDADD = \
65# $(top_builddir)/src/util/libgnunetutil.la \
66# $(top_builddir)/src/statistics/libgnunetstatistics.la \
67# $(top_builddir)/src/testbed/libgnunettestbed.la
68
69
70EXTRA_DIST = \
71 test_experimentation_clique.conf \
72 test_experiments.exp \ No newline at end of file
diff --git a/src/experimentation/experimentation.conf.in b/src/experimentation/experimentation.conf.in
deleted file mode 100644
index 6b3974684..000000000
--- a/src/experimentation/experimentation.conf.in
+++ /dev/null
@@ -1,11 +0,0 @@
1[experimentation]
2AUTOSTART = NO
3# PORT = 2106
4HOSTNAME = localhost
5BINARY = gnunet-daemon-experimentation
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-daemon-experimentation.sock
9UNIX_MATCH_UID = YES
10UNIX_MATCH_GID = YES
11ISSUERS = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG
diff --git a/src/experimentation/gnunet-daemon-experimentation.c b/src/experimentation/gnunet-daemon-experimentation.c
deleted file mode 100644
index e0ebdf365..000000000
--- a/src/experimentation/gnunet-daemon-experimentation.c
+++ /dev/null
@@ -1,124 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file experimentation/gnunet-daemon-experimentation.c
23 * @brief experimentation daemon
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_core_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-daemon-experimentation.h"
32
33
34/**
35 * Statistics handle shared between components
36 */
37struct GNUNET_STATISTICS_Handle *GED_stats;
38
39
40/**
41 * Configuration handle shared between components
42 */
43struct GNUNET_CONFIGURATION_Handle *GED_cfg;
44
45
46/**
47 * Task run during shutdown to stop all submodules of the experimentation daemon.
48 *
49 * @param cls unused
50 * @param tc unused
51 */
52static void
53shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
54{
55 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Experimentation daemon shutting down ...\n"));
56
57 GED_scheduler_stop ();
58 GED_nodes_stop ();
59 GED_experiments_stop ();
60 GED_storage_stop ();
61 GED_capabilities_stop ();
62}
63
64
65/**
66 * Function starting all submodules of the experimentation daemon.
67 *
68 * @param cls always NULL
69 * @param args temaining command line arguments
70 * @param cfgfile configuration file used
71 * @param cfg configuration handle
72 */
73static void
74run (void *cls, char *const *args, const char *cfgfile,
75 const struct GNUNET_CONFIGURATION_Handle *cfg)
76{
77 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Experimentation daemon starting ...\n"));
78
79 GED_cfg = (struct GNUNET_CONFIGURATION_Handle *) cfg;
80 GED_stats = GNUNET_STATISTICS_create ("experimentation", cfg);
81 if (NULL == GED_stats)
82 {
83 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create statistics!\n"));
84 return;
85 }
86
87 GED_capabilities_start ();
88
89 GED_storage_start ();
90
91 if (GNUNET_SYSERR == GED_experiments_start ())
92 {
93 GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
94 return;
95 }
96
97 GED_nodes_start ();
98 GED_scheduler_start ();
99 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
100 NULL);
101}
102
103
104/**
105 * The main function for the experimentation daemon.
106 *
107 * @param argc number of arguments from the command line
108 * @param argv command line arguments
109 * @return 0 ok, 1 on error
110 */
111int
112main (int argc, char *const *argv)
113{
114 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
115 GNUNET_GETOPT_OPTION_END
116 };
117
118 return (GNUNET_OK ==
119 GNUNET_PROGRAM_run (argc, argv, "experimentation",
120 _("GNUnet experimentation daemon"), options,
121 &run, NULL)) ? 0 : 1;
122}
123
124/* end of gnunet-daemon-experimentation.c */
diff --git a/src/experimentation/gnunet-daemon-experimentation.h b/src/experimentation/gnunet-daemon-experimentation.h
deleted file mode 100644
index 977d663e8..000000000
--- a/src/experimentation/gnunet-daemon-experimentation.h
+++ /dev/null
@@ -1,499 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file experimentation/gnunet-daemon-experimentation.h
23 * @brief experimentation daemon
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#ifndef GNUNET_DAEMON_EXPERIMENTATION_H
28#define GNUNET_DAEMON_EXPERIMENTATION_H
29#include "platform.h"
30#include "gnunet_getopt_lib.h"
31#include "gnunet_util_lib.h"
32#include "gnunet_core_service.h"
33#include "gnunet_statistics_service.h"
34
35
36/**
37 * Timeout between request and expected response
38 */
39#define EXP_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
40
41/**
42 * Default experiment frequency
43 */
44#define EXP_DEFAULT_EXP_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 6)
45
46/**
47 * Default experiment duration
48 */
49#define EXP_DEFAULT_EXP_DUR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
50
51/**
52 * Statistics handle shared between components
53 */
54extern struct GNUNET_STATISTICS_Handle *GED_stats;
55
56/**
57 * Configuration handle shared between components
58 */
59extern struct GNUNET_CONFIGURATION_Handle *GED_cfg;
60
61/**
62 * Capability value shared between components
63 */
64extern uint32_t GSE_node_capabilities;
65
66
67/**
68 * Capabilities a node has or an experiment requires
69 */
70enum GNUNET_EXPERIMENTATION_capabilities
71{
72 NONE = 0,
73 PLUGIN_TCP = 1,
74 PLUGIN_UDP = 2,
75 PLUGIN_UNIX = 4,
76 PLUGIN_HTTP_CLIENT = 8,
77 PLUGIN_HTTP_SERVER = 16,
78 PLUGIN_HTTPS_CLIENT = 32,
79 PLUGIN_HTTPS_SERVER = 64,
80 PLUGIN_WLAN = 128,
81 HAVE_IPV6 = 256,
82 BEHIND_NAT = 512
83};
84
85
86/**
87 * Struct to store information about a specific experiment
88 */
89struct Experiment
90{
91 /* Header */
92 /* ----------------- */
93 char *name;
94
95 /**
96 * Experiment issuer
97 */
98 struct GNUNET_CRYPTO_EddsaPublicKey issuer;
99
100 /**
101 * Experiment version as timestamp of creation
102 */
103 struct GNUNET_TIME_Absolute version;
104
105 /**
106 * Description
107 */
108 char *description;
109
110 /**
111 * Required capabilities
112 */
113 uint32_t required_capabilities;
114
115 /* Experiment timing */
116 /* ----------------- */
117
118 /**
119 * When to start experiment
120 */
121 struct GNUNET_TIME_Absolute start;
122
123 /**
124 * When to end experiment
125 */
126 struct GNUNET_TIME_Absolute stop;
127
128 /**
129 * How often to run experiment
130 */
131 struct GNUNET_TIME_Relative frequency;
132
133 /**
134 * How long to run each execution
135 */
136 struct GNUNET_TIME_Relative duration;
137
138
139 /* Experiment itself */
140 /* ----------------- */
141
142 /* TBD */
143};
144
145
146/**
147 * A experimentation node
148 */
149struct Node
150{
151 /**
152 * Peer id
153 */
154 struct GNUNET_PeerIdentity id;
155
156 /**
157 * Task for response timeout
158 */
159 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
160
161 /**
162 * Core transmission handle
163 */
164 struct GNUNET_CORE_TransmitHandle *cth;
165
166 /**
167 * Node capabilities
168 */
169 uint32_t capabilities;
170
171 /**
172 * Experiment version as timestamp of creation
173 */
174 struct GNUNET_TIME_Absolute version;
175
176 struct NodeComCtx *e_req_head;
177
178 struct NodeComCtx *e_req_tail;
179
180 /**
181 * Array of issuers accepted by this neighbor.
182 */
183 struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id;
184
185 unsigned int issuer_count;
186
187};
188
189
190GNUNET_NETWORK_STRUCT_BEGIN
191
192/**
193 * Experimentation request message
194 * Used to detect experimentation capability
195 *
196 * This struct is followed by issuer identities:
197 * (issuer_count * struct GNUNET_CRYPTO_EddsaPublicKey)
198 *
199 */
200struct Experimentation_Request
201{
202 struct GNUNET_MessageHeader msg;
203
204 uint32_t capabilities GNUNET_PACKED;
205
206 uint32_t issuer_count GNUNET_PACKED;
207};
208
209
210/**
211 * Experimentation response message
212 * Sent if peer is running the daemon
213 *
214 * This struct is followed by issuer identities:
215 * (issuer_count * struct GNUNET_CRYPTO_EddsaPublicKey)
216 */
217struct Experimentation_Response
218{
219 struct GNUNET_MessageHeader msg;
220
221 uint32_t capabilities GNUNET_PACKED;
222
223 uint32_t issuer_count GNUNET_PACKED;
224};
225
226
227/**
228 * Struct to store information about an experiment issuer
229 */
230struct Issuer
231{
232 struct GNUNET_CRYPTO_EddsaPublicKey pubkey;
233};
234
235
236/**
237 * Hashmap containing valid experiment issuers
238 * (the key is the hash of the respective public key,
239 * the values are of type `struct Issuer').
240 */
241struct GNUNET_CONTAINER_MultiHashMap *valid_issuers;
242
243/**
244 * Experiment start message
245 *
246 * struct is followed by string with length len_name
247 */
248struct GED_start_message
249{
250 struct GNUNET_MessageHeader header;
251
252 /**
253 * String length of experiment name following the struct
254 */
255 uint32_t len_name GNUNET_PACKED;
256
257 /**
258 * Experiment issuer
259 */
260 struct GNUNET_CRYPTO_EddsaPublicKey issuer;
261
262 /**
263 * Experiment version as timestamp of creation
264 */
265 struct GNUNET_TIME_AbsoluteNBO version_nbo;
266};
267
268
269struct GED_start_ack_message
270{
271 struct GNUNET_MessageHeader header;
272
273 /**
274 * String length of experiment name following the struct
275 */
276 uint32_t len_name GNUNET_PACKED;
277
278 /**
279 * Experiment issuer
280 */
281 struct GNUNET_CRYPTO_EddsaPublicKey issuer;
282
283 /**
284 * Experiment version as timestamp of creation
285 */
286 struct GNUNET_TIME_AbsoluteNBO version_nbo;
287};
288
289
290struct GED_stop_message
291{
292 struct GNUNET_MessageHeader header;
293
294 /**
295 * String length of experiment name following the struct
296 */
297 uint32_t len_name GNUNET_PACKED;
298
299 /**
300 * Experiment issuer
301 */
302 struct GNUNET_CRYPTO_EddsaPublicKey issuer;
303
304 /**
305 * Experiment version as timestamp of creation
306 */
307 struct GNUNET_TIME_AbsoluteNBO version_nbo;
308};
309
310GNUNET_NETWORK_STRUCT_END
311
312
313int
314GED_nodes_rts (struct Node *n);
315
316
317int
318GED_nodes_send_start (struct Node *n, struct Experiment *e);
319
320
321/**
322 * Confirm a experiment START with a node
323 *
324 * @return #GNUNET_NO if core was busy with sending, #GNUNET_OK otherwise
325 */
326int
327GED_nodes_send_start_ack (struct Node *n, struct Experiment *e);
328
329/**
330 * Start the nodes management
331 */
332void
333GED_nodes_start (void);
334
335
336/**
337 * Stop the nodes management
338 */
339void
340GED_nodes_stop (void);
341
342
343/**
344 * Print a single capability value
345 *
346 * @param cap capability value
347 * @return the string to print
348 */
349const char *
350GED_capability_to_str (uint32_t cap);
351
352
353/**
354 * Are the capabilities provided?
355 *
356 * @param have bitstring containing the provided capabilities
357 * @param desired bitstring containing the desired capabilities\
358 * @return #GNUNET_YES or #GNUNET_NO
359 */
360int
361GED_capabilities_have (uint32_t have, uint32_t desired);
362
363
364/**
365 * Start the detecting capabilities
366 */
367void
368GED_capabilities_start (void);
369
370
371/**
372 * Stop the detecting capabilities
373 */
374void
375GED_capabilities_stop (void);
376
377
378/**
379 * Start experiments management
380 *
381 * @return #GNUNET_YES or #GNUNET_NO
382 */
383int
384GED_experiments_issuer_accepted (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_ID);
385
386
387/*
388 * Find an experiment based on issuer name and version
389 *
390 * @param issuer the issuer
391 * @param name experiment name
392 * @param version experiment version
393 * @return the experiment or NULL if not found
394 */
395struct Experiment *
396GED_experiments_find (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
397 const char *name,
398 const struct GNUNET_TIME_Absolute version);
399
400
401typedef void (*GNUNET_EXPERIMENTATION_experiments_get_cb) (struct Node *n,
402 struct Experiment *e);
403
404
405void
406GED_experiments_get (struct Node *n,
407 struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
408 GNUNET_EXPERIMENTATION_experiments_get_cb get_cb);
409
410
411/**
412 * Start experiments management
413 *
414 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
415 */
416int
417GED_experiments_start (void);
418
419
420/**
421 * Stop experiments management
422 */
423void
424GED_experiments_stop (void);
425
426
427/**
428 * Handle a START message from a remote node
429 *
430 * @param n the node
431 * @param e the experiment
432 */
433void
434GED_scheduler_handle_start (struct Node *n, struct Experiment *e);
435
436
437/**
438 * Handle a START_ACL message from a remote node
439 *
440 * @param n the node
441 * @param e the experiment
442 */
443void
444GED_scheduler_handle_start_ack (struct Node *n, struct Experiment *e);
445
446
447/**
448 * Handle a STOP message from a remote node
449 *
450 * @param n the node
451 * @param e the experiment
452 */
453void
454GED_scheduler_handle_stop (struct Node *n, struct Experiment *e);
455
456
457/**
458 * Add a new experiment for a node
459 *
460 * @param n the node
461 * @param e the experiment
462 * @param outbound are we initiator (#GNUNET_YES) or client (#GNUNET_NO)?
463 */
464void
465GED_scheduler_add (struct Node *n,
466 struct Experiment *e,
467 int outbound);
468
469
470/**
471 * Start the scheduler component
472 */
473void
474GED_scheduler_start (void);
475
476
477/**
478 * Stop the scheduler component
479 */
480void
481GED_scheduler_stop (void);
482
483
484/**
485 * Start the storage component
486 */
487void
488GED_storage_start (void);
489
490
491/**
492 * Stop the storage component
493 */
494void
495GED_storage_stop (void);
496
497
498#endif /* #ifndef GNUNET_DAEMON_EXPERIMENTATION_H */
499/* end of gnunet-daemon-experimentation.h */
diff --git a/src/experimentation/gnunet-daemon-experimentation_capabilities.c b/src/experimentation/gnunet-daemon-experimentation_capabilities.c
deleted file mode 100644
index 7d74c2827..000000000
--- a/src/experimentation/gnunet-daemon-experimentation_capabilities.c
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file experimentation/gnunet-daemon-experimentation_capabilities.c
23 * @brief experimentation daemon: capabilities management
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_core_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-daemon-experimentation.h"
32
33
34/**
35 * Capability value shared between components
36 */
37uint32_t GSE_node_capabilities;
38
39
40/**
41 * Capabilities defined at the moment
42 */
43#define GNUNET_EXPERIMENTATION_capabilities_count 11
44
45
46/**
47 * Capabilities a node has or an experiment requires string
48 */
49#define GNUNET_EXPERIMENTATION_capabilities_string {"NONE", "PLUGIN_TCP", "PLUGIN_UDP", "PLUGIN_UNIX", "PLUGIN_HTTP_CLIENT", "PLUGIN_HTTP_SERVER", "PLUGIN_HTTPS_CLIENT", "PLUGIN_HTTPS_SERVER", "PLUGIN_WLAN", "HAVE_IPV6", "BEHIND_NAT"}
50
51
52/**
53 * Print a single capability value
54 *
55 * @param cap capability value
56 * @return the string to print
57 */
58const char *
59GED_capability_to_str (uint32_t cap)
60{
61 char * capstr[] = GNUNET_EXPERIMENTATION_capabilities_string;
62 unsigned index = 0;
63 uint32_t test = 0;
64
65 if (0 == cap)
66 return capstr[0];
67
68 index = (log(cap) / log (2)) + 1;
69
70 test = 1 << (index - 1);
71 if (test != cap)
72 return "UNDEFINED";
73
74 if (index < GNUNET_EXPERIMENTATION_capabilities_count)
75 return capstr[index];
76 else
77 return "UNDEFINED";
78
79
80}
81
82
83/**
84 * Are the capabilities provided?
85 *
86 * @param have bitstring containing the provided capabilities
87 * @param desired bitstring containing the desired capabilities\
88 * @return GNUNET_YES or GNUNET_NO
89 */
90int
91GED_capabilities_have (uint32_t have, uint32_t desired)
92{
93 if (desired == (desired & have))
94 return GNUNET_YES;
95 else
96 return GNUNET_NO;
97}
98
99
100/**
101 * Start the detecting capabilities
102 */
103void
104GED_capabilities_start ()
105{
106 char *plugins;
107 char *pos;
108 unsigned int c1;
109 uint32_t index;
110 GSE_node_capabilities = NONE;
111
112 /* Plugins configured */
113
114 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GED_cfg,
115 "TRANSPORT", "PLUGINS", &plugins))
116 {
117 for (pos = strtok (plugins, " "); pos != NULL; pos = strtok (NULL, " "))
118 {
119 if (0 == strcmp (pos, "tcp"))
120 GSE_node_capabilities |= PLUGIN_TCP;
121 else if (0 == strcmp (pos, "udp"))
122 GSE_node_capabilities |= PLUGIN_UDP;
123 else if (0 == strcmp (pos, "unix"))
124 GSE_node_capabilities |= PLUGIN_UNIX;
125 else if (0 == strcmp (pos, "http_client"))
126 GSE_node_capabilities |= PLUGIN_HTTP_CLIENT;
127 else if (0 == strcmp (pos, "http_server"))
128 GSE_node_capabilities |= PLUGIN_HTTP_SERVER;
129 else if (0 == strcmp (pos, "https_client"))
130 GSE_node_capabilities |= PLUGIN_HTTP_CLIENT;
131 else if (0 == strcmp (pos, "https_server"))
132 GSE_node_capabilities |= PLUGIN_HTTPS_SERVER;
133 else if (0 == strcmp (pos, "wlan"))
134 GSE_node_capabilities |= PLUGIN_WLAN;
135 }
136 GNUNET_free (plugins);
137 }
138
139 /* IPv6 enabled
140 * FIXE: just having it not enabled is not really sufficient */
141 if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (GED_cfg,
142 "NAT", "DISABLEV6"))
143 GSE_node_capabilities |= HAVE_IPV6;
144
145 /* Behind NAT */
146 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (GED_cfg,
147 "NAT", "BEHIND_NAT"))
148 GSE_node_capabilities |= BEHIND_NAT;
149
150 for (c1 = 0 ; c1 < 32; c1++)
151 {
152 index = 1;
153 index = index << c1;
154 if (GNUNET_YES == GED_capabilities_have (GSE_node_capabilities, index))
155 {
156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We have `%s'\n",
157 GED_capability_to_str(index));
158 }
159 }
160}
161
162
163/**
164 * Stop the detecting capabilities
165 */
166void
167GED_capabilities_stop ()
168{
169
170}
171
172/* end of gnunet-daemon-experimentation_capabilities.c */
diff --git a/src/experimentation/gnunet-daemon-experimentation_experiments.c b/src/experimentation/gnunet-daemon-experimentation_experiments.c
deleted file mode 100644
index 471a7bfdc..000000000
--- a/src/experimentation/gnunet-daemon-experimentation_experiments.c
+++ /dev/null
@@ -1,503 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012,2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file experimentation/gnunet-daemon-experimentation_experiments.c
23 * @brief experimentation daemon: experiment management
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_core_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-daemon-experimentation.h"
32
33
34/**
35 * Hashmap containing valid experiment issuers.
36 */
37struct GNUNET_CONTAINER_MultiHashMap *valid_issuers;
38
39/**
40 * Hashmap containing valid experiments
41 */
42static struct GNUNET_CONTAINER_MultiHashMap *experiments;
43
44
45/**
46 * Verify experiment signature
47 *
48 * @param i issuer
49 * @param e experiment
50 * @return #GNUNET_OK or #GNUNET_SYSERR
51 */
52static int
53experiment_verify (struct Issuer *i, struct Experiment *e)
54{
55 GNUNET_assert (NULL != i);
56 GNUNET_assert (NULL != e);
57
58 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
59 "Verification: to be implemented\n");
60 return GNUNET_OK;
61}
62
63
64static int
65free_experiment (void *cls,
66 const struct GNUNET_HashCode * key,
67 void *value)
68{
69 struct Experiment *e = value;
70
71 GNUNET_break (0 == GNUNET_CONTAINER_multihashmap_remove (experiments, key, value));
72 GNUNET_free_non_null (e->description);
73 GNUNET_free_non_null (e->name);
74 GNUNET_free (e);
75 return GNUNET_OK;
76}
77
78
79/**
80 * Free issuer element
81 *
82 * @param cls unused
83 * @param key the key
84 * @param value the issuer element to free
85 * @return GNUNET_OK to continue
86 */
87static int
88free_issuer (void *cls,
89 const struct GNUNET_HashCode * key,
90 void *value)
91{
92 struct Issuer *i = value;
93
94 GNUNET_break (0 == GNUNET_CONTAINER_multihashmap_remove (valid_issuers,
95 key,
96 i));
97 GNUNET_free (i);
98 return GNUNET_OK;
99}
100
101
102/**
103 * Is peer a valid issuer
104 *
105 * @return #GNUNET_YES or #GNUNET_NO
106 */
107int
108GED_experiments_issuer_accepted (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id)
109{
110 struct GNUNET_HashCode hash;
111
112 GNUNET_CRYPTO_hash (issuer_id, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), &hash);
113 if (GNUNET_CONTAINER_multihashmap_contains (valid_issuers, &hash))
114 return GNUNET_YES;
115 return GNUNET_NO;
116}
117
118
119/**
120 * Get the key under which the given experiment is stored in the
121 * experiment map.
122 */
123static void
124get_experiment_key (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
125 const char *name,
126 const struct GNUNET_TIME_Absolute version,
127 struct GNUNET_HashCode *key)
128{
129 GNUNET_assert (GNUNET_YES ==
130 GNUNET_CRYPTO_kdf (key, sizeof (struct GNUNET_HashCode),
131 issuer, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
132 name, strlen (name),
133 &version, sizeof (version),
134 NULL, 0));
135}
136
137
138/**
139 * Find an experiment based on issuer name and version
140 *
141 * @param issuer the issuer
142 * @param name experiment name
143 * @param version experiment version
144 * @return the experiment or NULL if not found
145 */
146struct Experiment *
147GED_experiments_find (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
148 const char *name,
149 const struct GNUNET_TIME_Absolute version)
150{
151 struct GNUNET_HashCode hc;
152
153 get_experiment_key (issuer,
154 name,
155 version,
156 &hc);
157 return GNUNET_CONTAINER_multihashmap_get (experiments,
158 &hc);
159}
160
161
162struct GetCtx
163{
164 struct Node *n;
165
166 GNUNET_EXPERIMENTATION_experiments_get_cb get_cb;
167
168 struct GNUNET_CRYPTO_EddsaPublicKey *issuer;
169};
170
171
172static int
173get_it (void *cls,
174 const struct GNUNET_HashCode *key,
175 void *value)
176{
177 struct GetCtx *get_ctx = cls;
178 struct Experiment *e = value;
179
180 if (0 == memcmp (&e->issuer,
181 get_ctx->issuer,
182 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
183 get_ctx->get_cb (get_ctx->n, e);
184 return GNUNET_OK;
185}
186
187
188void
189GED_experiments_get (struct Node *n,
190 struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
191 GNUNET_EXPERIMENTATION_experiments_get_cb get_cb)
192{
193 struct GetCtx get_ctx;
194
195 GNUNET_assert (NULL != n);
196 GNUNET_assert (NULL != experiments);
197 GNUNET_assert (NULL != get_cb);
198 get_ctx.n = n;
199 get_ctx.get_cb = get_cb;
200 get_ctx.issuer = issuer;
201 GNUNET_CONTAINER_multihashmap_iterate (experiments,
202 &get_it, &get_ctx);
203 get_cb (n, NULL); // FIXME: ugly, end is easily signalled as we return: synchronous API!
204}
205
206
207/**
208 * Add a new experiment
209 */
210int
211GNUNET_EXPERIMENTATION_experiments_add (struct Issuer *i,
212 const char *name,
213 const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id,
214 struct GNUNET_TIME_Absolute version,
215 char *description,
216 uint32_t required_capabilities,
217 struct GNUNET_TIME_Absolute start,
218 struct GNUNET_TIME_Relative frequency,
219 struct GNUNET_TIME_Relative duration,
220 struct GNUNET_TIME_Absolute stop)
221{
222 struct Experiment *e;
223 struct GNUNET_HashCode hc;
224
225 e = GNUNET_new (struct Experiment);
226 e->name = GNUNET_strdup (name);
227 e->issuer = *issuer_id;
228 e->version = version;
229 if (NULL != description)
230 e->description = GNUNET_strdup (description);
231 e->required_capabilities = required_capabilities;
232 e->start = start;
233 e->frequency = frequency;
234 e->duration = duration;
235 e->stop = stop;
236
237 /* verify experiment */
238 if (GNUNET_SYSERR == experiment_verify (i, e))
239 {
240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
241 _("Experiment `%s': Experiment signature is invalid\n"),
242 name);
243 GNUNET_free (e);
244 GNUNET_free_non_null (e->name);
245 GNUNET_free_non_null (e->description);
246 return GNUNET_SYSERR;
247 }
248
249 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
250 _("Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu sec. \n"),
251 e->name,
252 GNUNET_STRINGS_absolute_time_to_string (start),
253 GNUNET_STRINGS_absolute_time_to_string (stop),
254 (long long unsigned int) frequency.rel_value_us / 1000000LL,
255 (long long unsigned int) duration.rel_value_us / 1000000LL);
256 get_experiment_key (&e->issuer,
257 name,
258 version,
259 &hc);
260 GNUNET_CONTAINER_multihashmap_put (experiments,
261 &hc,
262 e,
263 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
264 GNUNET_STATISTICS_set (GED_stats,
265 "# experiments",
266 GNUNET_CONTAINER_multihashmap_size (experiments), GNUNET_NO);
267
268 return GNUNET_OK;
269}
270
271
272/**
273 * Parse a configuration section containing experiments
274 *
275 * @param cls configuration handle
276 * @param name section name
277 */
278static void
279exp_file_iterator (void *cls,
280 const char *name)
281{
282 struct GNUNET_CONFIGURATION_Handle *exp = cls;
283 struct Issuer *i;
284 char *val;
285 unsigned long long number;
286 /* Experiment values */
287 struct GNUNET_CRYPTO_EddsaPublicKey issuer;
288 struct GNUNET_TIME_Absolute version;
289 char *description;
290 uint32_t required_capabilities;
291 struct GNUNET_TIME_Absolute start ;
292 struct GNUNET_TIME_Absolute stop;
293 struct GNUNET_TIME_Relative frequency;
294 struct GNUNET_TIME_Relative duration;
295 struct GNUNET_HashCode phash;
296
297 /* Mandatory fields */
298
299 /* Issuer */
300 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (exp, name, "ISSUER", &val))
301 {
302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
303 _("Experiment `%s': Issuer missing\n"), name);
304 return;
305 }
306 if (GNUNET_SYSERR ==
307 GNUNET_CRYPTO_eddsa_public_key_from_string (val,
308 strlen (val),
309 &issuer))
310 {
311 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
312 _("Experiment `%s': Issuer invalid\n"), name);
313 GNUNET_free (val);
314 return;
315 }
316 GNUNET_CRYPTO_hash (&issuer, sizeof (issuer), &phash);
317 if (NULL == (i = GNUNET_CONTAINER_multihashmap_get (valid_issuers, &phash)))
318 {
319 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
320 _("Experiment `%s': Issuer not accepted!\n"), name);
321 GNUNET_free (val);
322 return;
323 }
324 GNUNET_free (val);
325
326 /* Version */
327 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "VERSION", &number))
328 {
329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
330 _("Experiment `%s': Version missing or invalid \n"), name);
331 return;
332 }
333 version.abs_value_us = number; // FIXME: what is this supposed to be? Version != TIME!???
334
335 /* Required capabilities */
336 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "CAPABILITIES", &number))
337 {
338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
339 _("Experiment `%s': Required capabilities missing \n"), name);
340 return;
341 }
342 if (number > UINT32_MAX)
343 {
344 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
345 _("Experiment `%s': Required capabilities invalid \n"), name);
346 return;
347 }
348 required_capabilities = number;
349
350 /* Optional fields */
351
352 /* Description */
353 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (exp, name, "DESCRIPTION", &description))
354 description = NULL;
355
356 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "START", (long long unsigned int *) &start.abs_value_us))
357 start = GNUNET_TIME_UNIT_ZERO_ABS;
358
359 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (exp, name, "FREQUENCY", &frequency))
360 frequency = EXP_DEFAULT_EXP_FREQ;
361 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (exp, name, "DURATION", &duration))
362 duration = EXP_DEFAULT_EXP_DUR;
363 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "STOP", (long long unsigned int *)&stop.abs_value_us))
364 stop = GNUNET_TIME_UNIT_FOREVER_ABS;
365
366 GNUNET_EXPERIMENTATION_experiments_add (i, name, &issuer, version,
367 description, required_capabilities,
368 start, frequency, duration, stop);
369 GNUNET_free_non_null (description);
370}
371
372
373/**
374 * Load experiments from file
375 *
376 * @param file source file
377 */
378static void
379load_file (const char * file)
380{
381 struct GNUNET_CONFIGURATION_Handle *exp = GNUNET_CONFIGURATION_create();
382
383 if (NULL == exp)
384 return;
385
386 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (exp, file))
387 {
388 GNUNET_CONFIGURATION_destroy (exp);
389 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
390 _("Failed to parse file `%s'\n"),
391 file);
392 return;
393 }
394 GNUNET_CONFIGURATION_iterate_sections (exp, &exp_file_iterator, exp);
395 GNUNET_CONFIGURATION_destroy (exp);
396}
397
398
399/**
400 * Start experiments management
401 */
402int
403GED_experiments_start ()
404{
405 struct Issuer *i;
406 char *issuers;
407 char *file;
408 char *pos;
409 struct GNUNET_CRYPTO_EddsaPublicKey issuer_ID;
410 struct GNUNET_HashCode hash;
411
412 /* Load valid issuer */
413 if (GNUNET_SYSERR ==
414 GNUNET_CONFIGURATION_get_value_string (GED_cfg,
415 "EXPERIMENTATION",
416 "ISSUERS",
417 &issuers))
418 {
419 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
420 _("No valid experiment issuers configured! Set value to public keys of issuers! Exiting.\n"));
421 GED_experiments_stop ();
422 return GNUNET_SYSERR;
423 }
424
425 valid_issuers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
426 for (pos = strtok (issuers, " "); pos != NULL; pos = strtok (NULL, " "))
427 {
428 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_public_key_from_string (pos,
429 strlen (pos),
430 &issuer_ID))
431 {
432 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
433 "EXPERIMENTATION",
434 "ISSUERS",
435 _("Invalid value for public key\n"));
436 GED_experiments_stop ();
437 GNUNET_free (issuers);
438 return GNUNET_SYSERR;
439 }
440 i = GNUNET_new (struct Issuer);
441 i->pubkey = issuer_ID;
442 GNUNET_CRYPTO_hash( &issuer_ID, sizeof (issuer_ID), &hash);
443 GNUNET_CONTAINER_multihashmap_put (valid_issuers,
444 &hash,
445 i,
446 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
447 }
448 GNUNET_free (issuers);
449 if (0 == GNUNET_CONTAINER_multihashmap_size (valid_issuers))
450 {
451 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
452 _("No valid experiment issuers configured! Set value to public keys of issuers! Exiting.\n"));
453 GED_experiments_stop ();
454 return GNUNET_SYSERR;
455 }
456 GNUNET_STATISTICS_set (GED_stats,
457 "# issuer",
458 GNUNET_CONTAINER_multihashmap_size (valid_issuers),
459 GNUNET_NO);
460
461 experiments = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
462 /* Load experiments from file */
463 if (GNUNET_SYSERR ==
464 GNUNET_CONFIGURATION_get_value_string (GED_cfg,
465 "EXPERIMENTATION",
466 "EXPERIMENTS",
467 &file))
468 return GNUNET_OK;
469
470 if (GNUNET_YES != GNUNET_DISK_file_test (file))
471 {
472 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
473 _("Cannot read experiments file `%s'\n"), file);
474 GNUNET_free (file);
475 return GNUNET_OK;
476 }
477 load_file (file);
478 GNUNET_free (file);
479 return GNUNET_OK;
480}
481
482
483/**
484 * Stop experiments management
485 */
486void
487GED_experiments_stop ()
488{
489 if (NULL != valid_issuers)
490 {
491 GNUNET_CONTAINER_multihashmap_iterate (valid_issuers, &free_issuer, NULL);
492 GNUNET_CONTAINER_multihashmap_destroy (valid_issuers);
493 }
494 valid_issuers = NULL;
495 if (NULL != experiments)
496 {
497 GNUNET_CONTAINER_multihashmap_iterate (experiments, &free_experiment, NULL);
498 GNUNET_CONTAINER_multihashmap_destroy (experiments);
499 }
500 experiments = NULL;
501}
502
503/* end of gnunet-daemon-experimentation_experiments.c */
diff --git a/src/experimentation/gnunet-daemon-experimentation_nodes.c b/src/experimentation/gnunet-daemon-experimentation_nodes.c
deleted file mode 100644
index 1c4152793..000000000
--- a/src/experimentation/gnunet-daemon-experimentation_nodes.c
+++ /dev/null
@@ -1,1157 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012-2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file experimentation/gnunet-daemon-experimentation_nodes.c
23 * @brief experimentation daemon: node management
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_core_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-daemon-experimentation.h"
32
33
34#define FAST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
35
36/**
37 * Core handle
38 */
39static struct GNUNET_CORE_Handle *ch;
40
41/**
42 * Peer's own identity
43 */
44static struct GNUNET_PeerIdentity me;
45
46/**
47 * Nodes with a pending request
48 */
49static struct GNUNET_CONTAINER_MultiPeerMap *nodes_requested;
50
51/**
52 * Active experimentation nodes
53 */
54static struct GNUNET_CONTAINER_MultiPeerMap *nodes_active;
55
56/**
57 * Inactive experimentation nodes
58 * To be excluded from future requests
59 */
60static struct GNUNET_CONTAINER_MultiPeerMap *nodes_inactive;
61
62
63struct NodeComCtx
64{
65 struct NodeComCtx *prev;
66 struct NodeComCtx *next;
67
68 struct Node *n;
69 struct Experiment *e;
70
71 size_t size;
72 GNUNET_CONNECTION_TransmitReadyNotify notify;
73 void *notify_cls;
74};
75
76
77/**
78 * Update statistics
79 *
80 * @param m peermap to update values from
81 */
82static void
83update_stats (struct GNUNET_CONTAINER_MultiPeerMap *m)
84{
85 GNUNET_assert (NULL != m);
86 GNUNET_assert (NULL != GED_stats);
87
88 if (m == nodes_active)
89 {
90 GNUNET_STATISTICS_set (GED_stats, "# nodes active",
91 GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO);
92 }
93 else if (m == nodes_inactive)
94 {
95 GNUNET_STATISTICS_set (GED_stats, "# nodes inactive",
96 GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO);
97 }
98 else if (m == nodes_requested)
99 {
100 GNUNET_STATISTICS_set (GED_stats, "# nodes requested",
101 GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO);
102 }
103 else
104 GNUNET_break (0);
105}
106
107
108/**
109 * Clean up node
110 *
111 * @param cls the peermap to clean up
112 * @param key key of the current node
113 * @param value related node object
114 * @return always #GNUNET_OK
115 */
116static int
117cleanup_node (void *cls,
118 const struct GNUNET_PeerIdentity * key,
119 void *value)
120{
121 struct Node *n;
122 struct NodeComCtx *e_cur;
123 struct NodeComCtx *e_next;
124 struct GNUNET_CONTAINER_MultiPeerMap *cur = cls;
125
126 n = value;
127 if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
128 {
129 GNUNET_SCHEDULER_cancel (n->timeout_task);
130 n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
131 }
132
133 if (NULL != n->cth)
134 {
135 GNUNET_CORE_notify_transmit_ready_cancel (n->cth);
136 n->cth = NULL;
137 }
138 e_next = n->e_req_head;
139 while (NULL != (e_cur = e_next))
140 {
141 e_next = e_cur->next;
142 GNUNET_CONTAINER_DLL_remove (n->e_req_head, n->e_req_tail, e_cur);
143 GNUNET_free (e_cur);
144 }
145 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (cur, key, value));
146 GNUNET_free (value);
147 return GNUNET_OK;
148}
149
150
151/**
152 * Check if id passed is my id
153 *
154 * @param id the id to check
155 * @return GNUNET_YES or GNUNET_NO
156 */
157static int
158is_me (const struct GNUNET_PeerIdentity *id)
159{
160 if (0 == memcmp (&me, id, sizeof (me)))
161 return GNUNET_YES;
162 else
163 return GNUNET_NO;
164}
165
166
167/**
168 * Core startup callback
169 *
170 * @param cls unused
171 * @param my_identity my id
172 */
173static void
174core_startup_handler (void *cls,
175 const struct GNUNET_PeerIdentity *my_identity)
176{
177 me = *my_identity;
178}
179
180
181static void
182schedule_transmisson (struct NodeComCtx *e_ctx);
183
184
185static size_t
186transmit_read_wrapper (void *cls, size_t bufsize, void *buf)
187{
188 struct NodeComCtx *e_ctx = cls;
189 struct NodeComCtx *next;
190
191 size_t res = e_ctx->notify (e_ctx->notify_cls, bufsize, buf);
192 e_ctx->n->cth = NULL;
193
194 GNUNET_CONTAINER_DLL_remove (e_ctx->n->e_req_head, e_ctx->n->e_req_tail, e_ctx);
195 next = e_ctx->n->e_req_head;
196 GNUNET_free (e_ctx);
197
198 if (NULL != next)
199 {
200 /* Schedule next message */
201 schedule_transmisson (next);
202 }
203 return res;
204}
205
206
207static void
208schedule_transmisson (struct NodeComCtx *e_ctx)
209{
210 if (NULL != e_ctx->n->cth)
211 return;
212
213 e_ctx->n->cth = GNUNET_CORE_notify_transmit_ready (ch, GNUNET_NO,
214 GNUNET_CORE_PRIO_BEST_EFFORT,
215 FAST_TIMEOUT,
216 &e_ctx->n->id, e_ctx->size,
217 transmit_read_wrapper, e_ctx);
218 if (NULL == e_ctx->n->cth)
219 {
220 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
221 _("Cannot send message to peer `%s' for experiment `%s'\n"),
222 GNUNET_i2s(&e_ctx->n->id), e_ctx->e->name);
223 GNUNET_free (e_ctx);
224 }
225}
226
227
228/**
229 * Remove experimentation request due to timeout
230 *
231 * @param cls the related node
232 * @param tc scheduler's task context
233 */
234static void
235remove_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
236{
237 struct Node *n = cls;
238
239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
240 "Removing request for peer %s due to timeout\n",
241 GNUNET_i2s (&n->id));
242 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_requested, &n->id))
243 {
244 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, &n->id, n));
245 update_stats (nodes_requested);
246 GNUNET_CONTAINER_multipeermap_put (nodes_inactive, &n->id, n,
247 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
248 update_stats (nodes_inactive);
249 }
250 n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
251}
252
253
254static int
255append_public_key (void *cls,
256 const struct GNUNET_HashCode *key,
257 void *value)
258{
259 struct GNUNET_CRYPTO_EddsaPublicKey **issuers = cls;
260 struct Issuer *issuer = value;
261
262 *issuers[0] = issuer->pubkey;
263 *issuers = &((*issuers)[1]);
264 return GNUNET_OK;
265}
266
267
268/**
269 * Core's transmit notify callback to send request
270 *
271 * @param cls the related node
272 * @param bufsize buffer size
273 * @param buf the buffer to copy to
274 * @return bytes passed
275 */
276static size_t
277send_experimentation_request_cb (void *cls, size_t bufsize, void *buf)
278{
279 struct Node *n = cls;
280 struct Experimentation_Request msg;
281 unsigned int my_issuer_count = GNUNET_CONTAINER_multihashmap_size (valid_issuers);
282 size_t msg_size = sizeof (msg);
283 size_t ri_size = sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) * my_issuer_count;
284 size_t total_size = msg_size + ri_size;
285 struct GNUNET_CRYPTO_EddsaPublicKey *issuers;
286
287 n->cth = NULL;
288 if (NULL == buf)
289 {
290 /* client disconnected */
291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
292 "Client disconnected\n");
293 if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
294 GNUNET_SCHEDULER_cancel (n->timeout_task);
295 GNUNET_SCHEDULER_add_now (&remove_request, n);
296 return 0;
297 }
298 GNUNET_assert (bufsize >= total_size);
299 msg.msg.size = htons (total_size);
300 msg.msg.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_REQUEST);
301 msg.capabilities = htonl (GSE_node_capabilities);
302 msg.issuer_count = htonl (my_issuer_count);
303 memcpy (buf, &msg, msg_size);
304 issuers = (struct GNUNET_CRYPTO_EddsaPublicKey *) buf + msg_size;
305 GNUNET_CONTAINER_multihashmap_iterate (valid_issuers,
306 &append_public_key,
307 &issuers);
308 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
309 _("Sending experimentation request to peer %s\n"),
310 GNUNET_i2s (&n->id));
311 return total_size;
312}
313
314
315/**
316 * Send request to peer to start add him to to the set of experimentation nodes
317 *
318 * @param peer the peer to send to
319 */
320static void
321send_experimentation_request (const struct GNUNET_PeerIdentity *peer)
322{
323 struct Node *n;
324 struct NodeComCtx *e_ctx;
325 size_t size;
326 size_t c_issuers;
327
328 c_issuers = GNUNET_CONTAINER_multihashmap_size (valid_issuers);
329 size = sizeof (struct Experimentation_Request) +
330 c_issuers * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey);
331 n = GNUNET_new (struct Node);
332 n->id = *peer;
333 n->timeout_task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &remove_request, n);
334 n->capabilities = NONE;
335
336 e_ctx = GNUNET_new (struct NodeComCtx);
337 e_ctx->n = n;
338 e_ctx->e = NULL;
339 e_ctx->size = size;
340 e_ctx->notify = &send_experimentation_request_cb;
341 e_ctx->notify_cls = n;
342 GNUNET_CONTAINER_DLL_insert_tail(n->e_req_head, n->e_req_tail, e_ctx);
343 schedule_transmisson (e_ctx);
344
345 GNUNET_assert (GNUNET_OK ==
346 GNUNET_CONTAINER_multipeermap_put (nodes_requested,
347 peer, n,
348 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
349 update_stats (nodes_requested);
350}
351
352
353/**
354 * Core's transmit notify callback to send response
355 *
356 * @param cls the related node
357 * @param bufsize buffer size
358 * @param buf the buffer to copy to
359 * @return bytes passed
360 */
361static size_t
362send_response_cb (void *cls, size_t bufsize, void *buf)
363{
364 struct Node *n = cls;
365 struct Experimentation_Response msg;
366 size_t c_issuers = GNUNET_CONTAINER_multihashmap_size (valid_issuers);
367 size_t ri_size = c_issuers * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey);
368 size_t msg_size = sizeof (msg);
369 size_t total_size = msg_size + ri_size;
370 struct GNUNET_CRYPTO_EddsaPublicKey *issuers;
371
372 n->cth = NULL;
373 if (buf == NULL)
374 {
375 /* client disconnected */
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
377 "Client disconnected\n");
378 return 0;
379 }
380 GNUNET_assert (bufsize >= total_size);
381
382 msg.msg.size = htons (total_size);
383 msg.msg.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_RESPONSE);
384 msg.capabilities = htonl (GSE_node_capabilities);
385 msg.issuer_count = htonl (c_issuers);
386 memcpy (buf, &msg, msg_size);
387 issuers = (struct GNUNET_CRYPTO_EddsaPublicKey *) buf + msg_size;
388 GNUNET_CONTAINER_multihashmap_iterate (valid_issuers,
389 &append_public_key,
390 &issuers);
391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
392 "Sending response to peer %s\n",
393 GNUNET_i2s (&n->id));
394 return total_size;
395}
396
397
398static void
399get_experiments_cb (struct Node *n, struct Experiment *e)
400{
401 static int counter = 0;
402 if (NULL == e)
403 return; /* Done */
404
405 /* Tell the scheduler to add a node with an experiment */
406 GED_scheduler_add (n, e, GNUNET_YES);
407 counter ++;
408}
409
410
411struct Node *
412get_node (const struct GNUNET_PeerIdentity *id)
413{
414 struct Node * res;
415 struct Node * tmp;
416
417 res = NULL;
418 tmp = NULL;
419 tmp = GNUNET_CONTAINER_multipeermap_get (nodes_active, id);
420 if (res == NULL)
421 res = tmp;
422
423 tmp = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, id);
424 if (res == NULL)
425 res = tmp;
426 else
427 GNUNET_break (0); /* Multiple instances */
428
429 tmp = GNUNET_CONTAINER_multipeermap_get (nodes_requested, id);
430 if (res == NULL)
431 res = tmp;
432 else
433 GNUNET_break (0); /* Multiple instances */
434
435 return res;
436}
437
438
439/**
440 * Set a specific node as active
441 *
442 * @param n the node
443 */
444static void
445node_make_active (struct Node *n)
446{
447 int c1;
448
449 GNUNET_CONTAINER_multipeermap_put (nodes_active,
450 &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
451 update_stats (nodes_active);
452 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
453 _("Added peer `%s' as active node\n"),
454 GNUNET_i2s (&n->id));
455 /* Request experiments for this node to start them */
456 for (c1 = 0; c1 < n->issuer_count; c1++)
457 {
458 GED_experiments_get (n, &n->issuer_id[c1], &get_experiments_cb);
459 }
460}
461
462
463/**
464 * Handle a request and send a response
465 *
466 * @param peer the source
467 * @param message the message
468 */
469static void
470handle_request (const struct GNUNET_PeerIdentity *peer,
471 const struct GNUNET_MessageHeader *message)
472{
473 struct Node *n;
474 struct NodeComCtx *e_ctx;
475 const struct Experimentation_Request *rm = (const struct Experimentation_Request *) message;
476 const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1];
477 unsigned int my_issuer_count = GNUNET_CONTAINER_multihashmap_size (valid_issuers);
478 int c1;
479 int c2;
480 uint32_t ic;
481 uint32_t ic_accepted;
482 int make_active;
483
484 if (ntohs (message->size) < sizeof (struct Experimentation_Request))
485 {
486 GNUNET_break (0);
487 return;
488 }
489 ic = ntohl (rm->issuer_count);
490 if (ntohs (message->size) !=
491 sizeof (struct Experimentation_Request) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
492 {
493 GNUNET_break (0);
494 return;
495 }
496
497 make_active = GNUNET_NO;
498 if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer)))
499 {
500 /* Nothing to do */
501 }
502 else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer)))
503 {
504 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n));
505 if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
506 {
507 GNUNET_SCHEDULER_cancel (n->timeout_task);
508 n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
509 }
510 update_stats (nodes_requested);
511 make_active = GNUNET_YES;
512 }
513 else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer)))
514 {
515 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n));
516 update_stats (nodes_inactive);
517 make_active = GNUNET_YES;
518 }
519 else
520 {
521 /* Create new node */
522 n = GNUNET_new (struct Node);
523 n->id = *peer;
524 n->capabilities = NONE;
525 make_active = GNUNET_YES;
526 }
527
528 /* Update node */
529 n->capabilities = ntohl (rm->capabilities);
530
531 /* Filter accepted issuer */
532 ic_accepted = 0;
533 for (c1 = 0; c1 < ic; c1++)
534 {
535 if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1]))
536 ic_accepted ++;
537 }
538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
539 "Request from peer `%s' with %u issuers, we accepted %u issuer \n",
540 GNUNET_i2s (peer), ic, ic_accepted);
541 GNUNET_free_non_null (n->issuer_id);
542 n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
543 c2 = 0;
544 for (c1 = 0; c1 < ic; c1++)
545 {
546 if (GNUNET_YES == GED_experiments_issuer_accepted (&rmi[c1]))
547 {
548 n->issuer_id[c2] = rmi[c1];
549 c2 ++;
550 }
551 }
552 n->issuer_count = ic_accepted;
553
554 if (GNUNET_YES == make_active)
555 node_make_active (n);
556
557 /* Send response */
558 e_ctx = GNUNET_new (struct NodeComCtx);
559 e_ctx->n = n;
560 e_ctx->e = NULL;
561 e_ctx->size = sizeof (struct Experimentation_Response) +
562 my_issuer_count * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey);
563 e_ctx->notify = &send_response_cb;
564 e_ctx->notify_cls = n;
565
566 GNUNET_CONTAINER_DLL_insert_tail(n->e_req_head, n->e_req_tail, e_ctx);
567 schedule_transmisson (e_ctx);
568}
569
570
571/**
572 * Handle a response
573 *
574 * @param peer the source
575 * @param message the message
576 */
577static void handle_response (const struct GNUNET_PeerIdentity *peer,
578 const struct GNUNET_MessageHeader *message)
579{
580 struct Node *n;
581 const struct Experimentation_Response *rm = (const struct Experimentation_Response *) message;
582 const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1];
583 uint32_t ic;
584 uint32_t ic_accepted;
585 int make_active;
586 unsigned int c1;
587 unsigned int c2;
588
589 if (ntohs (message->size) < sizeof (struct Experimentation_Response))
590 {
591 GNUNET_break (0);
592 return;
593 }
594 ic = ntohl (rm->issuer_count);
595 if (ntohs (message->size) != sizeof (struct Experimentation_Response) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
596 {
597 GNUNET_break (0);
598 return;
599 }
600
601 make_active = GNUNET_NO;
602 if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer)))
603 {
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
605 "Received %s from %s peer `%s'\n",
606 "RESPONSE", "active", GNUNET_i2s (peer));
607 }
608 else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer)))
609 {
610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n",
611 "RESPONSE", "requested", GNUNET_i2s (peer));
612 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n));
613 if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
614 {
615 GNUNET_SCHEDULER_cancel (n->timeout_task);
616 n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
617 }
618 update_stats (nodes_requested);
619 make_active = GNUNET_YES;
620 }
621 else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer)))
622 {
623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
624 "Received %s from peer `%s'\n",
625 "RESPONSE", "inactive", GNUNET_i2s (peer));
626 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n));
627 update_stats (nodes_inactive);
628 make_active = GNUNET_YES;
629 }
630 else
631 {
632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n",
633 "RESPONSE", "unknown", GNUNET_i2s (peer));
634 return;
635 }
636
637 /* Update */
638 n->capabilities = ntohl (rm->capabilities);
639
640 /* Filter accepted issuer */
641 ic_accepted = 0;
642 for (c1 = 0; c1 < ic; c1++)
643 {
644 if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1]))
645 ic_accepted ++;
646 }
647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
648 "Response from peer `%s' with %u issuers, we accepted %u issuer \n",
649 GNUNET_i2s (peer), ic, ic_accepted);
650 GNUNET_free_non_null (n->issuer_id);
651 n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_PeerIdentity));
652 c2 = 0;
653 for (c1 = 0; c1 < ic; c1++)
654 {
655 if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1]))
656 {
657 n->issuer_id[c2] = rmi[c1];
658 c2 ++;
659 }
660 }
661 n->issuer_count = ic_accepted;
662
663 if (GNUNET_YES == make_active)
664 node_make_active (n);
665}
666
667
668/**
669 * Handle a response
670 *
671 * @param peer the source
672 * @param message the message
673 */
674static void
675handle_start (const struct GNUNET_PeerIdentity *peer,
676 const struct GNUNET_MessageHeader *message)
677{
678 uint16_t size;
679 uint32_t name_len;
680 const struct GED_start_message *msg;
681 const char *name;
682 struct Node *n;
683 struct Experiment *e;
684
685 if (NULL == peer)
686 {
687 GNUNET_break (0);
688 return;
689 }
690 if (NULL == message)
691 {
692 GNUNET_break (0);
693 return;
694 }
695
696 size = ntohs (message->size);
697 if (size < sizeof (struct GED_start_message))
698 {
699 GNUNET_break (0);
700 return;
701 }
702 msg = (const struct GED_start_message *) message;
703 name_len = ntohl (msg->len_name);
704 if (size != sizeof (struct GED_start_message) + name_len)
705 {
706 GNUNET_break (0);
707 return;
708 }
709
710 n = get_node (peer);
711 if (NULL == n)
712 {
713 GNUNET_break (0);
714 return;
715 }
716 name = (const char *) &msg[1];
717 if (name[name_len-1] != '\0')
718 {
719 GNUNET_break (0);
720 return;
721 }
722 if (name_len != strlen (name) + 1)
723 {
724 GNUNET_break (0);
725 return;
726 }
727 e = GED_experiments_find (&msg->issuer, name, GNUNET_TIME_absolute_ntoh(msg->version_nbo));
728 if (NULL == e)
729 {
730 GNUNET_break (0);
731 return;
732 }
733 GED_scheduler_handle_start (n, e);
734}
735
736
737/**
738 * Handle a response
739 *
740 * @param peer the source
741 * @param message the message
742 */
743static void
744handle_start_ack (const struct GNUNET_PeerIdentity *peer,
745 const struct GNUNET_MessageHeader *message)
746{
747 uint16_t size;
748 uint32_t name_len;
749 const struct GED_start_ack_message *msg;
750 const char *name;
751 struct Node *n;
752 struct Experiment *e;
753
754 if (NULL == peer)
755 {
756 GNUNET_break (0);
757 return;
758 }
759 if (NULL == message)
760 {
761 GNUNET_break (0);
762 return;
763 }
764
765 size = ntohs (message->size);
766 if (size < sizeof (struct GED_start_ack_message))
767 {
768 GNUNET_break (0);
769 return;
770 }
771 msg = (const struct GED_start_ack_message *) message;
772 name_len = ntohl (msg->len_name);
773 if (size != sizeof (struct GED_start_message) + name_len)
774 {
775 GNUNET_break (0);
776 return;
777 }
778
779 n = get_node (peer);
780 if (NULL == n)
781 {
782 GNUNET_break (0);
783 return;
784 }
785 name = (const char *) &msg[1];
786 if (name[name_len-1] != '\0')
787 {
788 GNUNET_break (0);
789 return;
790 }
791 if (name_len != strlen (name) + 1)
792 {
793 GNUNET_break (0);
794 return;
795 }
796
797 e = GED_experiments_find (&msg->issuer, name, GNUNET_TIME_absolute_ntoh(msg->version_nbo));
798 if (NULL == e)
799 {
800 GNUNET_break (0);
801 return;
802 }
803 GED_scheduler_handle_start_ack (n, e);
804}
805
806
807/**
808 * Handle a response
809 *
810 * @param peer the source
811 * @param message the message
812 */
813static void
814handle_stop (const struct GNUNET_PeerIdentity *peer,
815 const struct GNUNET_MessageHeader *message)
816{
817 uint16_t size;
818 uint32_t name_len;
819 const struct GED_stop_message *msg;
820 const char *name;
821 struct Node *n;
822 struct Experiment *e;
823
824 if (NULL == peer)
825 {
826 GNUNET_break (0);
827 return;
828 }
829 if (NULL == message)
830 {
831 GNUNET_break (0);
832 return;
833 }
834
835 size = ntohs (message->size);
836 if (size < sizeof (struct GED_stop_message))
837 {
838 GNUNET_break (0);
839 return;
840 }
841 msg = (const struct GED_stop_message *) message;
842 name_len = ntohl (msg->len_name);
843 if (size != sizeof (struct GED_start_message) + name_len)
844 {
845 GNUNET_break (0);
846 return;
847 }
848
849 n = get_node (peer);
850 if (NULL == n)
851 {
852 GNUNET_break (0);
853 return;
854 }
855 name = (const char *) &msg[1];
856 if (name[name_len-1] != '\0')
857 {
858 GNUNET_break (0);
859 return;
860 }
861
862 if (name_len != strlen (name) + 1)
863 {
864 GNUNET_break (0);
865 return;
866 }
867
868 e = GED_experiments_find (&msg->issuer, name, GNUNET_TIME_absolute_ntoh(msg->version_nbo));
869 if (NULL == e)
870 {
871 GNUNET_break (0);
872 return;
873 }
874 GED_scheduler_handle_stop (n, e);
875}
876
877
878/**
879 * Method called whenever a given peer connects.
880 *
881 * @param cls closure
882 * @param peer peer identity this notification is about
883 */
884static void
885core_connect_handler (void *cls,
886 const struct GNUNET_PeerIdentity *peer)
887{
888 if (GNUNET_YES == is_me(peer))
889 return;
890
891 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connected to peer %s\n"),
892 GNUNET_i2s (peer));
893
894 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_requested, peer))
895 return; /* We already sent a request */
896
897 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_active, peer))
898 return; /* This peer is known as active */
899
900 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_inactive, peer))
901 return; /* This peer is known as inactive */
902
903 send_experimentation_request (peer);
904}
905
906
907/**
908 * Method called whenever a given peer disconnects.
909 *
910 * @param cls closure
911 * @param peer peer identity this notification is about
912 */
913static void
914core_disconnect_handler (void *cls,
915 const struct GNUNET_PeerIdentity * peer)
916{
917 struct Node *n;
918 if (GNUNET_YES == is_me(peer))
919 return;
920
921 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Disconnected from peer %s\n"),
922 GNUNET_i2s (peer));
923
924 if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer)))
925 cleanup_node (nodes_requested, peer, n);
926
927 if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer)))
928 cleanup_node (nodes_active, peer, n);
929
930 if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer)))
931 cleanup_node (nodes_inactive, peer, n);
932}
933
934
935/**
936 * Handle a request and send a response
937 *
938 * @param cls unused
939 * @param other the sender
940 * @param message the message
941 * @return GNUNET_OK to keep connection, GNUNET_SYSERR on error
942 */
943static int
944core_receive_handler (void *cls,
945 const struct GNUNET_PeerIdentity *other,
946 const struct GNUNET_MessageHeader *message)
947{
948 if (ntohs (message->size) < sizeof (struct GNUNET_MessageHeader))
949 {
950 GNUNET_break (0);
951 return GNUNET_SYSERR;
952 }
953
954 switch (ntohs (message->type)) {
955 case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_REQUEST:
956 handle_request (other, message);
957 break;
958 case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_RESPONSE:
959 handle_response (other, message);
960 break;
961 case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START:
962 handle_start (other, message);
963 break;
964 case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START_ACK:
965 handle_start_ack (other, message);
966 break;
967 case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_STOP:
968 handle_stop (other, message);
969 break;
970 default:
971 break;
972 }
973
974 return GNUNET_OK;
975}
976
977
978static size_t
979node_experiment_start_cb (void *cls, size_t bufsize, void *buf)
980{
981 struct NodeComCtx *e_ctx = cls;
982 struct GED_start_message *msg;
983 size_t name_len;
984 size_t size;
985
986 if (NULL == buf)
987 return 0;
988
989 name_len = strlen(e_ctx->e->name) + 1;
990 size = sizeof (struct GED_start_message) + name_len;
991
992 msg = GNUNET_malloc (size);
993 msg->header.size = htons (size);
994 msg->header.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START);
995 msg->issuer = e_ctx->e->issuer;
996 msg->version_nbo = GNUNET_TIME_absolute_hton(e_ctx->e->version);
997 msg->len_name = htonl (name_len);
998 memcpy (&msg[1], e_ctx->e->name, name_len);
999
1000 memcpy (buf, msg, size);
1001 GNUNET_free (msg);
1002 return size;
1003}
1004
1005
1006static size_t
1007node_experiment_start_ack_cb (void *cls, size_t bufsize, void *buf)
1008{
1009 struct NodeComCtx *e_ctx = cls;
1010 struct GED_start_ack_message *msg;
1011 size_t name_len;
1012 size_t size;
1013 if (NULL == buf)
1014 return 0;
1015
1016 name_len = strlen(e_ctx->e->name) + 1;
1017 size = sizeof (struct GED_start_ack_message) + name_len;
1018
1019 msg = GNUNET_malloc (size);
1020 msg->header.size = htons (size);
1021 msg->header.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START_ACK);
1022 msg->issuer = e_ctx->e->issuer;
1023 msg->version_nbo = GNUNET_TIME_absolute_hton(e_ctx->e->version);
1024 msg->len_name = htonl (name_len);
1025 memcpy (&msg[1], e_ctx->e->name, name_len);
1026
1027 memcpy (buf, msg, size);
1028 GNUNET_free (msg);
1029 return size;
1030}
1031
1032
1033
1034
1035/**
1036 * Confirm a experiment START with a node
1037 *
1038 * @return GNUNET_NO if core was busy with sending, GNUNET_OK otherwise
1039 */
1040int
1041GED_nodes_send_start_ack (struct Node *n, struct Experiment *e)
1042{
1043 struct NodeComCtx *e_ctx;
1044
1045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1046 "Sending %s for experiment request to peer `%s' for experiment `%s'\n",
1047 "START_ACK" ,GNUNET_i2s(&n->id), e->name);
1048
1049 e_ctx = GNUNET_new (struct NodeComCtx);
1050 e_ctx->n = n;
1051 e_ctx->e = e;
1052 e_ctx->size = sizeof (struct GED_start_ack_message) + strlen (e->name) + 1;
1053 e_ctx->notify = &node_experiment_start_ack_cb;
1054 e_ctx->notify_cls = e_ctx;
1055
1056 GNUNET_CONTAINER_DLL_insert_tail (n->e_req_head, n->e_req_tail, e_ctx);
1057 schedule_transmisson (e_ctx);
1058 return GNUNET_OK;
1059}
1060
1061
1062/**
1063 * Request a experiment to start with a node
1064 *
1065 * @return GNUNET_NO if core was busy with sending, GNUNET_OK otherwise
1066 */
1067int
1068GED_nodes_send_start (struct Node *n, struct Experiment *e)
1069{
1070 struct NodeComCtx *e_ctx;
1071
1072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1073 "Sending %s for experiment request to peer `%s' for experiment `%s'\n",
1074 "START", GNUNET_i2s(&n->id), e->name);
1075
1076 e_ctx = GNUNET_new (struct NodeComCtx);
1077 e_ctx->n = n;
1078 e_ctx->e = e;
1079 e_ctx->size = sizeof (struct GED_start_message) + strlen (e->name) + 1;
1080 e_ctx->notify = &node_experiment_start_cb;
1081 e_ctx->notify_cls = e_ctx;
1082
1083 GNUNET_CONTAINER_DLL_insert_tail (n->e_req_head, n->e_req_tail, e_ctx);
1084 schedule_transmisson (e_ctx);
1085 return GNUNET_OK;
1086}
1087
1088
1089/**
1090 * Start the nodes management
1091 */
1092void
1093GED_nodes_start ()
1094{
1095 /* Connecting to core service to find partners */
1096 ch = GNUNET_CORE_connect (GED_cfg, NULL,
1097 &core_startup_handler,
1098 &core_connect_handler,
1099 &core_disconnect_handler,
1100 &core_receive_handler,
1101 GNUNET_NO, NULL, GNUNET_NO, NULL);
1102 if (NULL == ch)
1103 {
1104 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to connect to CORE service!\n"));
1105 return;
1106 }
1107
1108 nodes_requested = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1109 nodes_active = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1110 nodes_inactive = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1111}
1112
1113
1114/**
1115 * Stop the nodes management
1116 */
1117void
1118GED_nodes_stop ()
1119{
1120 if (NULL != ch)
1121 {
1122 GNUNET_CORE_disconnect (ch);
1123 ch = NULL;
1124 }
1125
1126 if (NULL != nodes_requested)
1127 {
1128 GNUNET_CONTAINER_multipeermap_iterate (nodes_requested,
1129 &cleanup_node,
1130 nodes_requested);
1131 update_stats (nodes_requested);
1132 GNUNET_CONTAINER_multipeermap_destroy (nodes_requested);
1133 nodes_requested = NULL;
1134 }
1135
1136 if (NULL != nodes_active)
1137 {
1138 GNUNET_CONTAINER_multipeermap_iterate (nodes_active,
1139 &cleanup_node,
1140 nodes_active);
1141 update_stats (nodes_active);
1142 GNUNET_CONTAINER_multipeermap_destroy (nodes_active);
1143 nodes_active = NULL;
1144 }
1145
1146 if (NULL != nodes_inactive)
1147 {
1148 GNUNET_CONTAINER_multipeermap_iterate (nodes_inactive,
1149 &cleanup_node,
1150 nodes_inactive);
1151 update_stats (nodes_inactive);
1152 GNUNET_CONTAINER_multipeermap_destroy (nodes_inactive);
1153 nodes_inactive = NULL;
1154 }
1155}
1156
1157/* end of gnunet-daemon-experimentation_nodes.c */
diff --git a/src/experimentation/gnunet-daemon-experimentation_scheduler.c b/src/experimentation/gnunet-daemon-experimentation_scheduler.c
deleted file mode 100644
index c13434e9b..000000000
--- a/src/experimentation/gnunet-daemon-experimentation_scheduler.c
+++ /dev/null
@@ -1,448 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file experimentation/gnunet-daemon-experimentation_scheduler.c
23 * @brief experimentation daemon: execute experiments
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_core_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-daemon-experimentation.h"
32
33/**
34 * An experiment is added during startup as not running NOT_RUNNING
35 *
36 * The scheduler then decides to schedule it and sends a request to the
37 * remote peer, if core cannot send since it is busy we wait for some time
38 * and change state to BUSY, if we can send we change to REQUESTED and wait
39 * for remote peers ACK.
40 *
41 * When we receive an ACK we change to STARTED and when scheduler decides that
42 * the experiment is finished we change to STOPPED.
43 */
44
45enum ExperimentState
46{
47 /* Experiment is added and waiting to be executed */
48 NOT_RUNNING,
49 /* Cannot send request to remote peer, core is busy*/
50 BUSY,
51 /* We requested experiment and wait for remote peer to ACK */
52 REQUESTED,
53 /* Experiment is running */
54 STARTED,
55 /* Experiment is done */
56 STOPPED
57};
58
59struct ScheduledExperiment {
60 struct ScheduledExperiment *next;
61 struct ScheduledExperiment *prev;
62
63 struct Experiment *e;
64 struct Node *n;
65 int state;
66 int outbound;
67 GNUNET_SCHEDULER_TaskIdentifier task;
68};
69
70struct ScheduledExperiment *waiting_in_head;
71struct ScheduledExperiment *waiting_in_tail;
72
73struct ScheduledExperiment *running_in_head;
74struct ScheduledExperiment *running_in_tail;
75
76struct ScheduledExperiment *waiting_out_head;
77struct ScheduledExperiment *waiting_out_tail;
78
79struct ScheduledExperiment *running_out_head;
80struct ScheduledExperiment *running_out_tail;
81
82
83static unsigned int experiments_scheduled;
84static unsigned int experiments_outbound_running;
85static unsigned int experiments_inbound_running;
86static unsigned int experiments_requested;
87
88
89static struct ScheduledExperiment *
90find_experiment (struct ScheduledExperiment *head, struct ScheduledExperiment *tail,
91 struct Node *n, struct Experiment *e, int outbound)
92{
93 struct ScheduledExperiment *cur;
94 for (cur = head; NULL != cur; cur = cur->next)
95 {
96 if ((cur->n == n) && (cur->e == e) && (cur->outbound == outbound)) /* Node and experiment are equal */
97 break;
98 }
99 return cur;
100}
101
102static void
103request_timeout (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc)
104{
105 struct ScheduledExperiment *se = cls;
106 se->task = GNUNET_SCHEDULER_NO_TASK;
107
108 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Peer `%s' did not respond to request for experiment `%s'\n"),
109 GNUNET_i2s (&se->n->id), se->e->name);
110
111 GNUNET_CONTAINER_DLL_remove (waiting_out_head, waiting_out_tail, se);
112 GNUNET_free (se);
113
114 /* Remove experiment */
115 GNUNET_assert (experiments_requested > 0);
116 experiments_requested --;
117 GNUNET_STATISTICS_set (GED_stats, "# experiments requested", experiments_requested, GNUNET_NO);
118}
119
120static void run_experiment_inbound (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc)
121{
122 struct ScheduledExperiment *se = cls;
123 struct GNUNET_TIME_Relative start;
124 struct GNUNET_TIME_Relative end;
125
126 se->task = GNUNET_SCHEDULER_NO_TASK;
127
128 switch (se->state) {
129 case NOT_RUNNING:
130 /* Send START_ACK message */
131 GED_nodes_send_start_ack (se->n, se->e);
132 se->state = REQUESTED;
133 /* Schedule to run */
134 start = GNUNET_TIME_absolute_get_remaining(se->e->start);
135 if (0 == start.rel_value_us)
136 se->task = GNUNET_SCHEDULER_add_now (&run_experiment_inbound, se);
137 else
138 se->task = GNUNET_SCHEDULER_add_delayed (start, &run_experiment_inbound, se);
139 break;
140 case REQUESTED:
141 experiments_inbound_running ++;
142 GNUNET_STATISTICS_set (GED_stats, "# experiments inbound running", experiments_inbound_running, GNUNET_NO);
143 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting inbound experiment `%s' with peer `%s'\n"),
144 se->e->name, GNUNET_i2s (&se->n->id));
145 se->state = STARTED;
146 se->task = GNUNET_SCHEDULER_add_now (&run_experiment_inbound, se);
147 break;
148 case STARTED:
149 /* Experiment is running */
150 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running %s experiment `%s' peer for `%s'\n",
151 "inbound", GNUNET_i2s (&se->n->id), se->e->name);
152
153 /* do work here */
154
155 /* Reschedule */
156 end = GNUNET_TIME_absolute_get_remaining(GNUNET_TIME_absolute_add (se->e->stop, se->e->frequency));
157 if (0 == end.rel_value_us)
158 {
159 se->state = STOPPED;
160 return; /* End of experiment is reached */
161 }
162 /* Reschedule */
163 se->task = GNUNET_SCHEDULER_add_delayed (se->e->frequency, &run_experiment_inbound, se);
164 break;
165 case STOPPED:
166 /* Experiment expired */
167 break;
168 default:
169 break;
170 }
171
172}
173
174static void run_experiment_outbound (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc)
175{
176 struct ScheduledExperiment *se = cls;
177 struct GNUNET_TIME_Relative end;
178
179 se->task = GNUNET_SCHEDULER_NO_TASK;
180
181 switch (se->state) {
182 case NOT_RUNNING:
183 /* Send START message */
184 GED_nodes_send_start (se->n, se->e);
185 se->state = REQUESTED;
186 se->task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &request_timeout, se);
187 experiments_requested ++;
188 GNUNET_STATISTICS_set (GED_stats, "# experiments requested", experiments_requested, GNUNET_NO);
189 break;
190 case REQUESTED:
191 /* Expecting START_ACK */
192 GNUNET_break (0);
193 break;
194 case STARTED:
195 /* Experiment is running */
196 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running %s experiment `%s' peer for `%s'\n",
197 "outbound", GNUNET_i2s (&se->n->id), se->e->name);
198
199 /* do work here */
200
201 /* Reschedule */
202 end = GNUNET_TIME_absolute_get_remaining(GNUNET_TIME_absolute_add (se->e->stop, se->e->frequency));
203 if (0 == end.rel_value_us)
204 {
205 se->state = STOPPED;
206 return; /* End of experiment is reached */
207 }
208 /* Reschedule */
209 se->task = GNUNET_SCHEDULER_add_delayed (se->e->frequency, &run_experiment_outbound, se);
210 break;
211 case STOPPED:
212 /* Experiment expired */
213 break;
214 default:
215 break;
216 }
217}
218
219
220/**
221 * Handle a START message from a remote node
222 *
223 * @param n the node
224 * @param e the experiment
225 */
226void
227GED_scheduler_handle_start (struct Node *n, struct Experiment *e)
228{
229 if ((NULL != find_experiment (waiting_in_head, waiting_in_tail, n, e, GNUNET_NO)) ||
230 (NULL != find_experiment (running_in_head, running_in_tail, n, e, GNUNET_NO)))
231 {
232 GNUNET_break_op (0);
233 return;
234 }
235
236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
237 "Received %s message from peer %s for experiment `%s'\n",
238 "START", GNUNET_i2s (&n->id), e->name);
239 GED_scheduler_add (n, e, GNUNET_NO);
240}
241
242
243/**
244 * Handle a START_ACK message from a remote node
245 *
246 * @param n the node
247 * @param e the experiment
248 */
249void
250GED_scheduler_handle_start_ack (struct Node *n, struct Experiment *e)
251{
252 struct ScheduledExperiment *se;
253
254 if (NULL == (se = find_experiment (waiting_out_head, waiting_out_tail, n, e, GNUNET_YES)))
255 {
256 GNUNET_break (0);
257 return;
258 }
259
260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s message from peer %s for requested experiment `%s'\n",
261 "START_ACK", GNUNET_i2s (&n->id), e->name);
262
263 if (GNUNET_SCHEDULER_NO_TASK != se->task)
264 {
265 GNUNET_SCHEDULER_cancel (se->task); /* *Canceling timeout task */
266 se->task = GNUNET_SCHEDULER_NO_TASK;
267 }
268
269 /* Remove from waiting list, add to running list */
270 GNUNET_CONTAINER_DLL_remove (waiting_out_head, waiting_out_tail, se);
271 GNUNET_CONTAINER_DLL_insert (running_out_head, running_out_tail, se);
272
273 /* Change state and schedule to run */
274 experiments_outbound_running ++;
275 GNUNET_STATISTICS_set (GED_stats, "# experiments outbound running", experiments_outbound_running, GNUNET_NO);
276 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting outbound experiment `%s' with peer `%s'\n"),
277 e->name, GNUNET_i2s (&n->id));
278 se->state = STARTED;
279 se->task = GNUNET_SCHEDULER_add_now (&run_experiment_outbound, se);
280}
281
282
283/**
284 * Handle a STOP message from a remote node
285 *
286 * @param n the node
287 * @param e the experiment
288 */
289void
290GED_scheduler_handle_stop (struct Node *n, struct Experiment *e)
291{
292 struct ScheduledExperiment *se;
293
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Received %s message from peer %s for experiment `%s'\n"),
295 "STOP", GNUNET_i2s (&n->id), e->name);
296
297 if (NULL != (se = find_experiment (waiting_in_head, waiting_in_tail, n, e, GNUNET_NO)))
298 {
299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s message from peer %s for waiting experiment `%s'\n",
300 "STOP", GNUNET_i2s (&n->id), e->name);
301 }
302
303 if (NULL != (se = find_experiment (running_in_head, running_in_tail, n, e, GNUNET_NO)))
304 {
305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s message from peer %s for running experiment `%s'\n",
306 "STOP", GNUNET_i2s (&n->id), e->name);
307 }
308
309}
310
311/**
312 * Add a new experiment for a node
313 *
314 * @param n the node
315 * @param e the experiment
316 * @param outbound are we initiator (GNUNET_YES) or client (GNUNET_NO)?
317 */
318void
319GED_scheduler_add (struct Node *n, struct Experiment *e, int outbound)
320{
321 struct ScheduledExperiment *se;
322 struct GNUNET_TIME_Relative start;
323 struct GNUNET_TIME_Relative end;
324
325 GNUNET_assert ((GNUNET_YES == outbound) || (GNUNET_NO == outbound));
326
327 start = GNUNET_TIME_absolute_get_remaining(e->start);
328 end = GNUNET_TIME_absolute_get_remaining(e->stop);
329 if (0 == end.rel_value_us)
330 return; /* End of experiment is reached */
331
332 /* Add additional checks here if required */
333 se = GNUNET_new (struct ScheduledExperiment);
334 se->state = NOT_RUNNING;
335 se->outbound = outbound;
336 se->e = e;
337 se->n = n;
338
339 if (GNUNET_YES == outbound)
340 {
341 if (0 == start.rel_value_us)
342 se->task = GNUNET_SCHEDULER_add_now (&run_experiment_outbound, se);
343 else
344 se->task = GNUNET_SCHEDULER_add_delayed (start, &run_experiment_outbound, se);
345 GNUNET_CONTAINER_DLL_insert (waiting_out_head, waiting_out_tail, se);
346 }
347 else
348 {
349 if (0 == start.rel_value_us)
350 se->task = GNUNET_SCHEDULER_add_now (&run_experiment_inbound, se);
351 else
352 se->task = GNUNET_SCHEDULER_add_delayed (start, &run_experiment_inbound, se);
353 GNUNET_CONTAINER_DLL_insert (waiting_in_head, waiting_in_tail, se);
354 }
355
356 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added %s experiment `%s' for node to be scheduled\n",
357 (GNUNET_YES == outbound) ? "outbound" : "inbound", e->name, GNUNET_i2s(&se->n->id));
358 experiments_scheduled ++;
359 GNUNET_STATISTICS_set (GED_stats, "# experiments scheduled", experiments_scheduled, GNUNET_NO);
360
361}
362
363/**
364 * Start the scheduler component
365 */
366void
367GED_scheduler_start ()
368{
369 experiments_requested = 0;
370 experiments_scheduled = 0;
371}
372
373
374/**
375 * Stop the scheduler component
376 */
377void
378GED_scheduler_stop ()
379{
380 struct ScheduledExperiment *cur;
381 struct ScheduledExperiment *next;
382
383 next = waiting_in_head;
384 while (NULL != (cur = next))
385 {
386 next = cur->next;
387 GNUNET_CONTAINER_DLL_remove (waiting_in_head, waiting_in_tail, cur);
388 if (GNUNET_SCHEDULER_NO_TASK != cur->task)
389 {
390 GNUNET_SCHEDULER_cancel (cur->task);
391 cur->task = GNUNET_SCHEDULER_NO_TASK;
392 }
393 GNUNET_free (cur);
394 GNUNET_assert (experiments_scheduled > 0);
395 experiments_scheduled --;
396 GNUNET_STATISTICS_set (GED_stats, "# experiments scheduled", experiments_scheduled, GNUNET_NO);
397 }
398
399 next = running_in_head;
400 while (NULL != (cur = next))
401 {
402 next = cur->next;
403 GNUNET_CONTAINER_DLL_remove (running_in_head, running_in_tail, cur);
404 if (GNUNET_SCHEDULER_NO_TASK != cur->task)
405 {
406 GNUNET_SCHEDULER_cancel (cur->task);
407 cur->task = GNUNET_SCHEDULER_NO_TASK;
408 }
409 GNUNET_free (cur);
410 GNUNET_assert (experiments_outbound_running > 0);
411 experiments_inbound_running --;
412 GNUNET_STATISTICS_set (GED_stats, "# experiments inbound running", experiments_inbound_running, GNUNET_NO);
413 }
414
415 next = waiting_out_head;
416 while (NULL != (cur = next))
417 {
418 next = cur->next;
419 GNUNET_CONTAINER_DLL_remove (waiting_out_head, waiting_out_tail, cur);
420 if (GNUNET_SCHEDULER_NO_TASK != cur->task)
421 {
422 GNUNET_SCHEDULER_cancel (cur->task);
423 cur->task = GNUNET_SCHEDULER_NO_TASK;
424 }
425 GNUNET_free (cur);
426 GNUNET_assert (experiments_scheduled > 0);
427 experiments_scheduled --;
428 GNUNET_STATISTICS_set (GED_stats, "# experiments scheduled", experiments_scheduled, GNUNET_NO);
429 }
430
431 next = running_out_head;
432 while (NULL != (cur = next))
433 {
434 next = cur->next;
435 GNUNET_CONTAINER_DLL_remove (running_out_head, running_out_tail, cur);
436 if (GNUNET_SCHEDULER_NO_TASK != cur->task)
437 {
438 GNUNET_SCHEDULER_cancel (cur->task);
439 cur->task = GNUNET_SCHEDULER_NO_TASK;
440 }
441 GNUNET_free (cur);
442 GNUNET_assert (experiments_outbound_running > 0);
443 experiments_outbound_running --;
444 GNUNET_STATISTICS_set (GED_stats, "# experiments outbound running", experiments_outbound_running, GNUNET_NO);
445 }
446}
447
448/* end of gnunet-daemon-experimentation_scheduler.c */
diff --git a/src/experimentation/gnunet-daemon-experimentation_storage.c b/src/experimentation/gnunet-daemon-experimentation_storage.c
deleted file mode 100644
index 8c6214c7b..000000000
--- a/src/experimentation/gnunet-daemon-experimentation_storage.c
+++ /dev/null
@@ -1,53 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file experimentation/gnunet-daemon-experimentation_storage.c
23 * @brief experimentation daemon: store results
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_core_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-daemon-experimentation.h"
32
33
34/**
35 * Start the storage component
36 */
37void
38GED_storage_start ()
39{
40
41}
42
43
44/**
45 * Stop the storage component
46 */
47void
48GED_storage_stop ()
49{
50
51}
52
53/* end of gnunet-daemon-experimentation_storage.c */
diff --git a/src/experimentation/test_experimentation_clique.conf b/src/experimentation/test_experimentation_clique.conf
deleted file mode 100644
index 1ab9aa2dd..000000000
--- a/src/experimentation/test_experimentation_clique.conf
+++ /dev/null
@@ -1,43 +0,0 @@
1[testbed]
2AUTOSTART = NO
3PORT = 12113
4ACCEPT_FROM = 127.0.0.1;
5HOSTNAME = localhost
6NEIGHBOUR_LIMIT = 100
7TOPOLOGY = RANDOM
8#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
9
10[dhtcache]
11QUOTA = 1 MB
12DATABASE = heap
13
14[transport]
15PLUGINS = udp
16ACCEPT_FROM6 = ::1;
17ACCEPT_FROM = 127.0.0.1;
18NEIGHBOUR_LIMIT = 50
19PORT = 12365
20
21[experimentation]
22#PREFIX = valgrind --leak-check=full
23ISSUERS = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG
24EXPERIMENTS = test_experiments.exp
25
26[ats]
27WAN_QUOTA_OUT = 3932160
28WAN_QUOTA_IN = 3932160
29
30[core]
31USE_EPHEMERAL_KEYS = NO
32
33[transport-udp]
34TIMEOUT = 300 s
35
36[PATHS]
37GNUNET_TEST_HOME = /tmp/test-experimentation/
38
39[nat]
40RETURN_LOCAL_ADDRESSES = YES
41
42[peerinfo]
43NO_IO = YES
diff --git a/src/experimentation/test_experimentation_clique_connect.c b/src/experimentation/test_experimentation_clique_connect.c
deleted file mode 100644
index f7fa02df5..000000000
--- a/src/experimentation/test_experimentation_clique_connect.c
+++ /dev/null
@@ -1,416 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/experimentation/test_experimentation_clique_connect.c
23 * @brief test case to connect experimentation daemons in a clique
24 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25 * @author Matthias Wachs
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testbed_service.h"
31
32
33/**
34 * Number of peers we want to start
35 */
36#define NUM_PEERS 2
37
38#define NUM_ISSUER 1
39
40#define NUM_EXPERIMENTS 2
41
42#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (5 * NUM_PEERS) + 20)
43
44/**
45 * Array of peers
46 */
47static struct GNUNET_TESTBED_Peer **peers;
48
49/**
50 * Operation handle
51 */
52static struct GNUNET_TESTBED_Operation *op;
53
54/**
55 * Shutdown task
56 */
57static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
58
59/**
60 * Testing result
61 */
62static int result;
63
64/**
65 * Counter for counting overlay connections
66 */
67static unsigned int overlay_connects;
68
69/**
70 * Information we track for a peer in the testbed.
71 */
72struct ExperimentationPeer
73{
74 /**
75 * Handle with testbed.
76 */
77 struct GNUNET_TESTBED_Peer *daemon;
78
79 /**
80 * Testbed operation to connect to statistics service
81 */
82 struct GNUNET_TESTBED_Operation *stat_op;
83
84 /**
85 * Handle to the statistics service
86 */
87 struct GNUNET_STATISTICS_Handle *sh;
88
89 unsigned int active_nodes;
90 unsigned int requested_nodes;
91 unsigned int inactive_nodes;
92 unsigned int issuer;
93 unsigned int experiments;
94};
95
96
97struct ExperimentationPeer bp_slaves[NUM_PEERS];
98
99/**
100 * Shutdown nicely
101 *
102 * @param cls NULL
103 * @param tc the task context
104 */
105static void
106do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
107{
108 unsigned int peer;
109 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
110
111 for (peer = 0; peer < NUM_PEERS; peer++)
112 {
113 if (NULL != bp_slaves[peer].stat_op)
114 GNUNET_TESTBED_operation_done (bp_slaves[peer].stat_op);
115 bp_slaves[peer].stat_op = NULL;
116 }
117
118 if (NULL != op)
119 {
120 GNUNET_TESTBED_operation_done (op);
121 op = NULL;
122 }
123 GNUNET_SCHEDULER_shutdown ();
124}
125
126/**
127 * Controller event callback
128 *
129 * @param cls NULL
130 * @param event the controller event
131 */
132static void
133controller_event_cb (void *cls,
134 const struct GNUNET_TESTBED_EventInformation *event)
135{
136 switch (event->type)
137 {
138 case GNUNET_TESTBED_ET_CONNECT:
139 overlay_connects++;
140 if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects)
141 {
142 result = GNUNET_OK;
143 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers connected \n", NUM_PEERS);
144 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
145 {
146 GNUNET_SCHEDULER_cancel (shutdown_task);
147 }
148 shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL);
149 }
150 break;
151 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
152 break;
153 default:
154 GNUNET_break (0);
155 result = GNUNET_SYSERR;
156 GNUNET_SCHEDULER_cancel (shutdown_task);
157 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
158 }
159}
160
161static void
162check_end ()
163{
164 static int last_active_value = 0;
165 static int last_issuer_value = 0;
166 static int last_experiments_value = 0;
167 unsigned int peer;
168 unsigned int total_active = 0;
169 unsigned int total_inactive = 0;
170 unsigned int total_requested = 0;
171 unsigned int issuer = 0;
172 unsigned int experiments = 0;
173
174 for (peer = 0; peer < NUM_PEERS; peer++)
175 {
176 total_active += bp_slaves[peer].active_nodes;
177 total_requested += bp_slaves[peer].requested_nodes;
178 total_inactive += bp_slaves[peer].inactive_nodes;
179 if (NUM_ISSUER == bp_slaves[peer].issuer)
180 issuer ++;
181 if (NUM_EXPERIMENTS == bp_slaves[peer].experiments)
182 experiments ++;
183 }
184 if ((last_issuer_value < issuer) && (issuer == NUM_PEERS))
185 fprintf (stderr, "I");
186 last_issuer_value = issuer;
187
188 if ((last_experiments_value < experiments) && (experiments == NUM_PEERS))
189 fprintf (stderr, "E");
190 last_experiments_value = experiments;
191
192 if (last_active_value < total_active)
193 fprintf (stderr, ".");
194 last_active_value = total_active;
195
196
197 if ((total_active == (NUM_PEERS * (NUM_PEERS -1))) &&
198 (total_requested == 0) && (total_inactive == 0) &&
199 (issuer == NUM_PEERS) && (experiments == NUM_PEERS))
200 {
201 fprintf (stderr, "\n");
202 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers active in a clique\n", NUM_PEERS);
203 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
204 }
205}
206
207
208
209/**
210 * Callback function to process statistic values.
211 *
212 * @param cls struct StatsContext
213 * @param subsystem name of subsystem that created the statistic
214 * @param name the name of the datum
215 * @param value the current value
216 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
217 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
218 */
219static int
220stat_iterator (void *cls, const char *subsystem, const char *name,
221 uint64_t value, int is_persistent)
222{
223 struct ExperimentationPeer *peer = cls;
224
225 if (0 == strcmp (name, "# nodes active"))
226 {
227 peer->active_nodes = value;
228 }
229 if (0 == strcmp (name, "# nodes inactive"))
230 {
231 peer->inactive_nodes = value;
232 }
233 if (0 == strcmp (name, "# nodes requested"))
234 {
235 peer->requested_nodes = value;
236 }
237 if (0 == strcmp (name, "# issuer"))
238 {
239 peer->issuer = value;
240 }
241 if (0 == strcmp (name, "# experiments"))
242 {
243 peer->experiments = value;
244 }
245
246 check_end ();
247
248 return GNUNET_OK;
249}
250
251/**
252 * Called after successfully opening a connection to a peer's statistics
253 * service; we register statistics monitoring here.
254 *
255 * @param cls the callback closure from functions generating an operation
256 * @param op the operation that has been finished
257 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
258 * @param emsg error message in case the operation has failed; will be NULL if
259 * operation has executed successfully.
260 */
261static void
262stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
263 void *ca_result, const char *emsg )
264{
265 struct GNUNET_STATISTICS_Handle *sh = ca_result;
266 struct ExperimentationPeer *peer = cls;
267
268 if (NULL != emsg)
269 {
270 GNUNET_break (0);
271 return;
272 }
273
274 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
275 (sh, "experimentation", "# nodes active",
276 stat_iterator, peer));
277 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
278 (sh, "experimentation", "# nodes inactive",
279 stat_iterator, peer));
280 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
281 (sh, "experimentation", "# nodes requested",
282 stat_iterator, peer));
283 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
284 (sh, "experimentation", "# issuer",
285 stat_iterator, peer));
286 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
287 (sh, "experimentation", "# experiments",
288 stat_iterator, peer));
289}
290
291/**
292 * Called to open a connection to the peer's statistics
293 *
294 * @param cls peer context
295 * @param cfg configuration of the peer to connect to; will be available until
296 * GNUNET_TESTBED_operation_done() is called on the operation returned
297 * from GNUNET_TESTBED_service_connect()
298 * @return service handle to return in 'op_result', NULL on error
299 */
300static void *
301stat_connect_adapter (void *cls,
302 const struct GNUNET_CONFIGURATION_Handle *cfg)
303{
304 struct ExperimentationPeer *peer = cls;
305 peer->sh = GNUNET_STATISTICS_create ("experimentation", cfg);
306 if (NULL == peer->sh)
307 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create statistics \n");
308 return peer->sh;
309}
310
311
312/**
313 * Called to disconnect from peer's statistics service
314 *
315 * @param cls peer context
316 * @param op_result service handle returned from the connect adapter
317 */
318static void
319stat_disconnect_adapter (void *cls, void *op_result)
320{
321 struct ExperimentationPeer *peer = cls;
322
323 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
324 (peer->sh, "experimentation", "# nodes active",
325 stat_iterator, peer));
326 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
327 (peer->sh, "experimentation", "# nodes inactive",
328 stat_iterator, peer));
329 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
330 (peer->sh, "experimentation", "# nodes requested",
331 stat_iterator, peer));
332 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
333 (peer->sh, "experimentation", "# issuer",
334 stat_iterator, peer));
335 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
336 (peer->sh, "experimentation", "# experiments",
337 stat_iterator, peer));
338 GNUNET_STATISTICS_destroy (op_result, GNUNET_NO);
339 peer->sh = NULL;
340}
341
342
343
344/**
345 * Signature of a main function for a testcase.
346 *
347 * @param cls closure
348 * @param h the run handle
349 * @param num_peers number of peers in 'peers'
350 * @param peers_ handle to peers run in the testbed
351 * @param links_succeeded the number of overlay link connection attempts that
352 * succeeded
353 * @param links_failed the number of overlay link connection attempts that
354 * failed
355 */
356static void
357test_master (void *cls,
358 struct GNUNET_TESTBED_RunHandle *h,
359 unsigned int num_peers,
360 struct GNUNET_TESTBED_Peer **peers_,
361 unsigned int links_succeeded,
362 unsigned int links_failed)
363{
364 unsigned int peer;
365
366 GNUNET_assert (NULL == cls);
367 GNUNET_assert (NUM_PEERS == num_peers);
368 GNUNET_assert (NULL != peers_);
369 for (peer = 0; peer < num_peers; peer++)
370 {
371 GNUNET_assert (NULL != peers_[peer]);
372 /* Connect to peer's statistic service */
373 bp_slaves[peer].stat_op = GNUNET_TESTBED_service_connect (NULL,
374 peers_[peer], "statistics",
375 &stat_comp_cb, &bp_slaves[peer],
376 &stat_connect_adapter,
377 &stat_disconnect_adapter,
378 &bp_slaves[peer]);
379
380 }
381 peers = peers_;
382 overlay_connects = 0;
383 op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL,
384 NULL,
385 NULL,
386 GNUNET_TESTBED_TOPOLOGY_CLIQUE,
387 /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */
388 /* NUM_PEERS, */
389 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
390 GNUNET_assert (NULL != op);
391 shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL);
392}
393
394
395/**
396 * Main function
397 */
398int
399main (int argc, char **argv)
400{
401 uint64_t event_mask;
402
403 result = GNUNET_SYSERR;
404 event_mask = 0;
405 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
406 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
407 (void) GNUNET_TESTBED_test_run ("test_experimentation_clique_connect",
408 "test_experimentation_clique.conf", NUM_PEERS,
409 event_mask, &controller_event_cb, NULL,
410 &test_master, NULL);
411 if (GNUNET_OK != result)
412 return 1;
413 return 0;
414}
415
416/* end of test_experimentation_clique_connect.c */
diff --git a/src/experimentation/test_experimentation_clique_run.c b/src/experimentation/test_experimentation_clique_run.c
deleted file mode 100644
index 875e7501d..000000000
--- a/src/experimentation/test_experimentation_clique_run.c
+++ /dev/null
@@ -1,389 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/experimentation/test_experimentation_clique_run.c
23 * @brief test case to run experiments with experimentation daemons in a clique
24 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25 * @author Matthias Wachs
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testbed_service.h"
31
32
33/**
34 * Number of peers we want to start
35 */
36#define NUM_PEERS 2
37
38#define NUM_ISSUER 1
39
40#define NUM_EXPERIMENTS 2
41
42#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (5 * NUM_PEERS) + 20)
43
44/**
45 * Array of peers
46 */
47static struct GNUNET_TESTBED_Peer **peers;
48
49/**
50 * Operation handle
51 */
52static struct GNUNET_TESTBED_Operation *op;
53
54/**
55 * Shutdown task
56 */
57static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
58
59/**
60 * Testing result
61 */
62static int result;
63
64/**
65 * Counter for counting overlay connections
66 */
67static unsigned int overlay_connects;
68
69/**
70 * Information we track for a peer in the testbed.
71 */
72struct ExperimentationPeer
73{
74 /**
75 * Handle with testbed.
76 */
77 struct GNUNET_TESTBED_Peer *daemon;
78
79 /**
80 * Testbed operation to connect to statistics service
81 */
82 struct GNUNET_TESTBED_Operation *stat_op;
83
84 /**
85 * Handle to the statistics service
86 */
87 struct GNUNET_STATISTICS_Handle *sh;
88
89 unsigned int active_nodes;
90 unsigned int requested_nodes;
91 unsigned int inactive_nodes;
92 unsigned int issuer;
93 unsigned int experiments_active;
94 unsigned int experiments_outbound_running;
95 unsigned int experiments_inbound_running;
96};
97
98
99struct ExperimentationPeer bp_slaves[NUM_PEERS];
100
101/**
102 * Shutdown nicely
103 *
104 * @param cls NULL
105 * @param tc the task context
106 */
107static void
108do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
109{
110 unsigned int peer;
111 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
112
113 for (peer = 0; peer < NUM_PEERS; peer++)
114 {
115 if (NULL != bp_slaves[peer].stat_op)
116 GNUNET_TESTBED_operation_done (bp_slaves[peer].stat_op);
117 bp_slaves[peer].stat_op = NULL;
118 }
119
120 if (NULL != op)
121 {
122 GNUNET_TESTBED_operation_done (op);
123 op = NULL;
124 }
125 GNUNET_SCHEDULER_shutdown ();
126}
127
128/**
129 * Controller event callback
130 *
131 * @param cls NULL
132 * @param event the controller event
133 */
134static void
135controller_event_cb (void *cls,
136 const struct GNUNET_TESTBED_EventInformation *event)
137{
138 switch (event->type)
139 {
140 case GNUNET_TESTBED_ET_CONNECT:
141 overlay_connects++;
142 if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects)
143 {
144 result = GNUNET_OK;
145 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers connected \n", NUM_PEERS);
146 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
147 {
148 GNUNET_SCHEDULER_cancel (shutdown_task);
149 }
150 shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL);
151 }
152 break;
153 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
154 break;
155 default:
156 GNUNET_break (0);
157 result = GNUNET_SYSERR;
158 GNUNET_SCHEDULER_cancel (shutdown_task);
159 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
160 }
161}
162
163static void
164check_end ()
165{
166 static int last_in_experiments_value = 0;
167 static int last_out_experiments_value = 0;
168 unsigned int peer;
169 unsigned int t_running_outbound_experiments = 0;
170 unsigned int t_running_inbound_experiments = 0;
171
172 for (peer = 0; peer < NUM_PEERS; peer++)
173 {
174 t_running_outbound_experiments += bp_slaves[peer].experiments_outbound_running;
175 t_running_inbound_experiments += bp_slaves[peer].experiments_inbound_running;
176
177 }
178
179 //fprintf (stderr, "%u %u \n", t_running_outbound_experiments, t_running_inbound_experiments);
180 if (last_in_experiments_value < t_running_inbound_experiments)
181 fprintf (stderr, ".");
182 last_in_experiments_value = t_running_inbound_experiments;
183 if (last_out_experiments_value < t_running_outbound_experiments)
184 fprintf (stderr, ".");
185 last_out_experiments_value = t_running_outbound_experiments;
186
187
188
189 if ((t_running_inbound_experiments == (NUM_PEERS * NUM_EXPERIMENTS)) &&
190 (t_running_outbound_experiments == (NUM_PEERS * NUM_EXPERIMENTS)))
191 {
192 fprintf (stderr, "\n");
193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "All %u peers are running experiments\n", NUM_PEERS);
194 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
195 }
196}
197
198
199
200/**
201 * Callback function to process statistic values.
202 *
203 * @param cls struct StatsContext
204 * @param subsystem name of subsystem that created the statistic
205 * @param name the name of the datum
206 * @param value the current value
207 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
208 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
209 */
210static int
211stat_iterator (void *cls, const char *subsystem, const char *name,
212 uint64_t value, int is_persistent)
213{
214 struct ExperimentationPeer *peer = cls;
215
216 if (0 == strcmp (name, "# experiments active"))
217 {
218 peer->experiments_active = value;
219 }
220
221 if (0 == strcmp (name, "# experiments outbound running"))
222 {
223 peer->experiments_outbound_running = value;
224 }
225
226 if (0 == strcmp (name, "# experiments inbound running"))
227 {
228 peer->experiments_inbound_running = value;
229 }
230
231
232 check_end ();
233
234 return GNUNET_OK;
235}
236
237/**
238 * Called after successfully opening a connection to a peer's statistics
239 * service; we register statistics monitoring here.
240 *
241 * @param cls the callback closure from functions generating an operation
242 * @param op the operation that has been finished
243 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
244 * @param emsg error message in case the operation has failed; will be NULL if
245 * operation has executed successfully.
246 */
247static void
248stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
249 void *ca_result, const char *emsg )
250{
251 //struct GNUNET_STATISTICS_Handle *sh = ca_result;
252 struct ExperimentationPeer *peer = cls;
253
254 if (NULL != emsg)
255 {
256 GNUNET_break (0);
257 return;
258 }
259
260 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
261 (peer->sh, "experimentation", "# experiments active",
262 stat_iterator, peer));
263 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
264 (peer->sh, "experimentation", "# experiments outbound running",
265 stat_iterator, peer));
266 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
267 (peer->sh, "experimentation", "# experiments inbound running",
268 stat_iterator, peer));
269}
270
271/**
272 * Called to open a connection to the peer's statistics
273 *
274 * @param cls peer context
275 * @param cfg configuration of the peer to connect to; will be available until
276 * GNUNET_TESTBED_operation_done() is called on the operation returned
277 * from GNUNET_TESTBED_service_connect()
278 * @return service handle to return in 'op_result', NULL on error
279 */
280static void *
281stat_connect_adapter (void *cls,
282 const struct GNUNET_CONFIGURATION_Handle *cfg)
283{
284 struct ExperimentationPeer *peer = cls;
285 peer->sh = GNUNET_STATISTICS_create ("experimentation", cfg);
286 if (NULL == peer->sh)
287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create statistics \n");
288 return peer->sh;
289}
290
291
292/**
293 * Called to disconnect from peer's statistics service
294 *
295 * @param cls peer context
296 * @param op_result service handle returned from the connect adapter
297 */
298static void
299stat_disconnect_adapter (void *cls, void *op_result)
300{
301 struct ExperimentationPeer *peer = cls;
302 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
303 (peer->sh, "experimentation", "# experiments active",
304 stat_iterator, peer));
305 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
306 (peer->sh, "experimentation", "# experiments outbound running",
307 stat_iterator, peer));
308 GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
309 (peer->sh, "experimentation", "# experiments inbound running",
310 stat_iterator, peer));
311 GNUNET_STATISTICS_destroy (op_result, GNUNET_NO);
312 peer->sh = NULL;
313}
314
315
316
317/**
318 * Signature of a main function for a testcase.
319 *
320 * @param cls closure
321 * @param h the run handle
322 * @param num_peers number of peers in 'peers'
323 * @param peers_ handle to peers run in the testbed
324 * @param links_succeeded the number of overlay link connection attempts that
325 * succeeded
326 * @param links_failed the number of overlay link connection attempts that
327 * failed
328 */
329static void
330test_master (void *cls,
331 struct GNUNET_TESTBED_RunHandle *h,
332 unsigned int num_peers,
333 struct GNUNET_TESTBED_Peer **peers_,
334 unsigned int links_succeeded,
335 unsigned int links_failed)
336{
337 unsigned int peer;
338
339 GNUNET_assert (NULL == cls);
340 GNUNET_assert (NUM_PEERS == num_peers);
341 GNUNET_assert (NULL != peers_);
342 for (peer = 0; peer < num_peers; peer++)
343 {
344 GNUNET_assert (NULL != peers_[peer]);
345 /* Connect to peer's statistic service */
346 bp_slaves[peer].stat_op = GNUNET_TESTBED_service_connect (NULL,
347 peers_[peer], "statistics",
348 &stat_comp_cb, &bp_slaves[peer],
349 &stat_connect_adapter,
350 &stat_disconnect_adapter,
351 &bp_slaves[peer]);
352
353 }
354 peers = peers_;
355 overlay_connects = 0;
356 op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL,
357 NULL,
358 NULL,
359 GNUNET_TESTBED_TOPOLOGY_CLIQUE,
360 /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */
361 /* NUM_PEERS, */
362 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
363 GNUNET_assert (NULL != op);
364 shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL);
365}
366
367
368/**
369 * Main function
370 */
371int
372main (int argc, char **argv)
373{
374 uint64_t event_mask;
375
376 result = GNUNET_SYSERR;
377 event_mask = 0;
378 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
379 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
380 (void) GNUNET_TESTBED_test_run ("test_experimentation_clique_run",
381 "test_experimentation_clique.conf", NUM_PEERS,
382 event_mask, &controller_event_cb, NULL,
383 &test_master, NULL);
384 if (GNUNET_OK != result)
385 return 1;
386 return 0;
387}
388
389/* end of test_experimentation_clique_run.c */
diff --git a/src/experimentation/test_experiments.exp b/src/experimentation/test_experiments.exp
deleted file mode 100644
index 035ac4b24..000000000
--- a/src/experimentation/test_experiments.exp
+++ /dev/null
@@ -1,9 +0,0 @@
1[test-experiment-1]
2ISSUER = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG
3VERSION = 1
4CAPABILITIES = 0
5
6[test-experiment-2]
7ISSUER = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG
8VERSION = 1
9CAPABILITIES = 0 \ No newline at end of file