diff options
-rw-r--r-- | src/nse/Makefile.am | 12 | ||||
-rw-r--r-- | src/nse/gnunet-service-nse.c | 692 | ||||
-rw-r--r-- | src/nse/nse.h | 10 | ||||
-rw-r--r-- | src/nse/nse_api.c | 3 | ||||
-rw-r--r-- | src/nse/test_nse.conf | 20 | ||||
-rw-r--r-- | src/nse/test_nse_api.c | 5 | ||||
-rw-r--r-- | src/nse/test_nse_multipeer.c | 233 |
7 files changed, 778 insertions, 197 deletions
diff --git a/src/nse/Makefile.am b/src/nse/Makefile.am index fa9d43f4d..a13d6d8b1 100644 --- a/src/nse/Makefile.am +++ b/src/nse/Makefile.am | |||
@@ -40,13 +40,15 @@ gnunet_service_nse_LDADD = \ | |||
40 | $(top_builddir)/src/nse/libgnunetnse.la \ | 40 | $(top_builddir)/src/nse/libgnunetnse.la \ |
41 | $(top_builddir)/src/util/libgnunetutil.la \ | 41 | $(top_builddir)/src/util/libgnunetutil.la \ |
42 | $(top_builddir)/src/core/libgnunetcore.la \ | 42 | $(top_builddir)/src/core/libgnunetcore.la \ |
43 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
43 | -lm \ | 44 | -lm \ |
44 | $(GN_LIBINTL) | 45 | $(GN_LIBINTL) |
45 | gnunet_service_nse_DEPENDENCIES = \ | 46 | gnunet_service_nse_DEPENDENCIES = \ |
46 | libgnunetnse.la | 47 | libgnunetnse.la |
47 | 48 | ||
48 | check_PROGRAMS = \ | 49 | check_PROGRAMS = \ |
49 | test_nse_api | 50 | test_nse_api \ |
51 | test_nse_multipeer | ||
50 | 52 | ||
51 | if ENABLE_TEST_RUN | 53 | if ENABLE_TEST_RUN |
52 | TESTS = $(check_PROGRAMS) $(check_SCRIPTS) | 54 | TESTS = $(check_PROGRAMS) $(check_SCRIPTS) |
@@ -58,9 +60,15 @@ test_nse_api_LDADD = \ | |||
58 | $(top_builddir)/src/nse/libgnunetnse.la \ | 60 | $(top_builddir)/src/nse/libgnunetnse.la \ |
59 | $(top_builddir)/src/util/libgnunetutil.la | 61 | $(top_builddir)/src/util/libgnunetutil.la |
60 | 62 | ||
63 | test_nse_multipeer_SOURCES = \ | ||
64 | test_nse_multipeer.c | ||
65 | test_nse_multipeer_LDADD = \ | ||
66 | $(top_builddir)/src/nse/libgnunetnse.la \ | ||
67 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
68 | $(top_builddir)/src/testing/libgnunettesting.la | ||
61 | 69 | ||
62 | EXTRA_DIST = \ | 70 | EXTRA_DIST = \ |
63 | test_nse_api_data.conf \ | 71 | test_nse.conf \ |
64 | $(check_SCRIPTS) | 72 | $(check_SCRIPTS) |
65 | 73 | ||
66 | 74 | ||
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c index 50ec9a013..90fc680d3 100644 --- a/src/nse/gnunet-service-nse.c +++ b/src/nse/gnunet-service-nse.c | |||
@@ -1,22 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 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 | 7 | by the Free Software Foundation; either version 3, or (at your |
8 | option) any later version. | 8 | option) any later version. |
9 | 9 | ||
10 | GNUnet is distributed in the hope that it will be useful, but | 10 | GNUnet is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | General Public License for more details. | 13 | General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License | 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 | 16 | along with GNUnet; see the file COPYING. If not, write to the |
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 | Boston, MA 02111-1307, USA. | 18 | Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file nse/gnunet-service-nse.c | 22 | * @file nse/gnunet-service-nse.c |
@@ -44,16 +44,17 @@ | |||
44 | #include "gnunet_signatures.h" | 44 | #include "gnunet_signatures.h" |
45 | #include "gnunet_service_lib.h" | 45 | #include "gnunet_service_lib.h" |
46 | #include "gnunet_server_lib.h" | 46 | #include "gnunet_server_lib.h" |
47 | #include "gnunet_statistics_service.h" | ||
47 | #include "gnunet_core_service.h" | 48 | #include "gnunet_core_service.h" |
48 | #include "gnunet_time_lib.h" | 49 | #include "gnunet_time_lib.h" |
49 | #include "gnunet_nse_service.h" | 50 | #include "gnunet_nse_service.h" |
50 | #include "nse.h" | 51 | #include "nse.h" |
51 | 52 | ||
52 | #define DEFAULT_HISTORY_SIZE 10 | 53 | #define DEFAULT_HISTORY_SIZE 50 |
53 | 54 | ||
54 | #define DEFAULT_CORE_QUEUE_SIZE 32 | 55 | #define DEFAULT_CORE_QUEUE_SIZE 32 |
55 | 56 | ||
56 | #define DEFAULT_NSE_PRIORITY 0 | 57 | #define DEFAULT_NSE_PRIORITY 5 |
57 | 58 | ||
58 | /** | 59 | /** |
59 | * Entry in the list of clients which | 60 | * Entry in the list of clients which |
@@ -115,6 +116,11 @@ struct NSEPeerEntry | |||
115 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 116 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
116 | 117 | ||
117 | /** | 118 | /** |
119 | * Handle to the statistics service. | ||
120 | */ | ||
121 | static struct GNUNET_STATISTICS_Handle *stats; | ||
122 | |||
123 | /** | ||
118 | * Handle to the core service. | 124 | * Handle to the core service. |
119 | */ | 125 | */ |
120 | static struct GNUNET_CORE_Handle *coreAPI; | 126 | static struct GNUNET_CORE_Handle *coreAPI; |
@@ -161,7 +167,8 @@ static unsigned int size_estimates[DEFAULT_HISTORY_SIZE]; | |||
161 | /** | 167 | /** |
162 | * Array of size estimate messages. | 168 | * Array of size estimate messages. |
163 | */ | 169 | */ |
164 | static struct GNUNET_NSE_FloodMessage size_estimate_messages[DEFAULT_HISTORY_SIZE]; | 170 | static struct GNUNET_NSE_FloodMessage |
171 | size_estimate_messages[DEFAULT_HISTORY_SIZE]; | ||
165 | 172 | ||
166 | /** | 173 | /** |
167 | * Index of most recent estimate. | 174 | * Index of most recent estimate. |
@@ -234,22 +241,21 @@ static struct GNUNET_NSE_FloodMessage flood_message; | |||
234 | * @param message the message received | 241 | * @param message the message received |
235 | */ | 242 | */ |
236 | static void | 243 | static void |
237 | handle_start_message (void *cls, | 244 | handle_start_message(void *cls, struct GNUNET_SERVER_Client *client, |
238 | struct GNUNET_SERVER_Client *client, | 245 | const struct GNUNET_MessageHeader *message) |
239 | const struct GNUNET_MessageHeader *message) | ||
240 | { | 246 | { |
241 | if ((ntohs (message->size) != sizeof(struct GNUNET_MessageHeader)) | 247 | if ((ntohs (message->size) != sizeof(struct GNUNET_MessageHeader)) |
242 | || (ntohs (message->type) != GNUNET_MESSAGE_TYPE_NSE_START)) | 248 | || (ntohs (message->type) != GNUNET_MESSAGE_TYPE_NSE_START)) |
243 | return; | 249 | return; |
244 | 250 | ||
245 | #if DEBUG_NSE | 251 | #if DEBUG_NSE |
246 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "NSE", "Received START message from client\n"); | 252 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "NSE", |
253 | "Received START message from client\n"); | ||
247 | #endif | 254 | #endif |
248 | GNUNET_SERVER_notification_context_add (nc, client); | 255 | GNUNET_SERVER_notification_context_add (nc, client); |
249 | GNUNET_SERVER_receive_done(client, GNUNET_OK); | 256 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
250 | } | 257 | } |
251 | 258 | ||
252 | |||
253 | /** | 259 | /** |
254 | * Called when core is ready to send a message we asked for | 260 | * Called when core is ready to send a message we asked for |
255 | * out to the destination. | 261 | * out to the destination. |
@@ -260,23 +266,41 @@ handle_start_message (void *cls, | |||
260 | * @return number of bytes written to buf | 266 | * @return number of bytes written to buf |
261 | */ | 267 | */ |
262 | static size_t | 268 | static size_t |
263 | transmit_ready (void *cls, size_t size, void *buf) | 269 | transmit_ready(void *cls, size_t size, void *buf) |
264 | { | 270 | { |
265 | struct NSEPeerEntry *peer_entry = cls; | 271 | struct NSEPeerEntry *peer_entry = cls; |
266 | char *cbuf = buf; | 272 | char *cbuf = buf; |
267 | 273 | ||
268 | size_t msize; | 274 | size_t msize; |
269 | peer_entry->th = NULL; | 275 | peer_entry->th = NULL; |
276 | #if DEBUG_NSE | ||
277 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s: transmit_ready called\n", | ||
278 | GNUNET_i2s (&my_identity)); | ||
279 | #endif | ||
270 | if (buf == NULL) /* client disconnected */ | 280 | if (buf == NULL) /* client disconnected */ |
271 | return 0; | 281 | { |
282 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
283 | "%s: transmit_ready called (disconnect)\n", | ||
284 | GNUNET_i2s (&my_identity)); | ||
285 | return 0; | ||
286 | } | ||
272 | 287 | ||
273 | if (peer_entry->pending_message == NULL) | 288 | if (peer_entry->pending_message == NULL) |
274 | return 0; | 289 | { |
290 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
291 | "%s: transmit_ready called (no message)\n", | ||
292 | GNUNET_i2s (&my_identity)); | ||
293 | return 0; | ||
294 | } | ||
275 | 295 | ||
276 | msize = ntohs(peer_entry->pending_message->size); | 296 | msize = ntohs (peer_entry->pending_message->size); |
277 | if (msize <= size) | 297 | if (msize <= size) |
278 | memcpy(cbuf, peer_entry->pending_message, msize); | 298 | memcpy (cbuf, peer_entry->pending_message, msize); |
279 | 299 | #if DEBUG_NSE | |
300 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
301 | "%s: transmit_ready called (transmit %d bytes)\n", | ||
302 | GNUNET_i2s (&my_identity), msize); | ||
303 | #endif | ||
280 | return msize; | 304 | return msize; |
281 | } | 305 | } |
282 | 306 | ||
@@ -288,35 +312,82 @@ transmit_ready (void *cls, size_t size, void *buf) | |||
288 | * | 312 | * |
289 | * @param message the network flood message | 313 | * @param message the network flood message |
290 | */ | 314 | */ |
291 | static void update_network_size_estimate(struct GNUNET_NSE_FloodMessage *message) | 315 | static void |
316 | update_network_size_estimate(struct GNUNET_NSE_FloodMessage *message) | ||
292 | { | 317 | { |
293 | unsigned int i; | 318 | unsigned int i; |
294 | unsigned int count; | 319 | unsigned int count; |
295 | double average; | 320 | double average; |
321 | double std_dev; | ||
322 | double diff; | ||
296 | 323 | ||
297 | size_estimates[estimate_index] = htons(message->distance); | 324 | size_estimates[estimate_index] = htonl (message->distance); |
298 | memcpy(&size_estimate_messages[estimate_index], message, sizeof(struct GNUNET_NSE_FloodMessage)); | 325 | memcpy (&size_estimate_messages[estimate_index], message, |
326 | sizeof(struct GNUNET_NSE_FloodMessage)); | ||
299 | 327 | ||
300 | count = 0; | 328 | count = 0; |
329 | std_dev = 0.0; | ||
330 | average = 0.0; | ||
301 | for (i = 0; i < DEFAULT_HISTORY_SIZE; i++) | 331 | for (i = 0; i < DEFAULT_HISTORY_SIZE; i++) |
302 | { | 332 | { |
303 | if (size_estimate_messages[i].distance != 0) | 333 | if (size_estimate_messages[i].distance != 0) |
304 | { | 334 | { |
305 | average += 1 << htons(size_estimate_messages[i].distance); | 335 | #if AVERAGE_SQUARE |
336 | average += (1 << htonl (size_estimate_messages[i].distance)); | ||
337 | #else | ||
338 | average += htonl (size_estimate_messages[i].distance); | ||
339 | #endif | ||
306 | count++; | 340 | count++; |
307 | } | 341 | } |
308 | } | 342 | } |
309 | average /= (double)count; | 343 | |
310 | current_estimate_message.size_estimate = average; | 344 | if (count > 0) |
311 | /* Finally, broadcast the current estimate to all clients */ | 345 | { |
312 | GNUNET_SERVER_notification_context_broadcast (nc, | 346 | average /= (double) count; |
313 | ¤t_estimate_message.header, | 347 | for (i = 0; i < DEFAULT_HISTORY_SIZE; i++) |
314 | GNUNET_NO); | 348 | { |
349 | if (size_estimate_messages[i].distance != 0) | ||
350 | { | ||
351 | #if DEBUG_NSE | ||
352 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: estimate %d %d\n", GNUNET_i2s(&my_identity), i, (1 << htonl(size_estimate_messages[i].distance))); | ||
353 | #endif | ||
354 | #if AVERAGE_SQUARE | ||
355 | diff = average | ||
356 | - (1 << htonl (size_estimate_messages[i].distance)); | ||
357 | #else | ||
358 | diff = average - htonl (size_estimate_messages[i].distance); | ||
359 | #endif | ||
360 | std_dev += diff * diff; | ||
361 | } | ||
362 | } | ||
363 | std_dev /= count; | ||
364 | std_dev = sqrt (std_dev); | ||
365 | current_estimate_message.header.size | ||
366 | = htons (sizeof(struct GNUNET_NSE_ClientMessage)); | ||
367 | current_estimate_message.header.type | ||
368 | = htons (GNUNET_MESSAGE_TYPE_NSE_ESTIMATE); | ||
369 | current_estimate_message.size_estimate = average; | ||
370 | current_estimate_message.std_deviation = std_dev; | ||
371 | /* Finally, broadcast the current estimate to all clients */ | ||
372 | #if DEBUG_NSE | ||
373 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
374 | "%s: sending estimate %f -- %f to client\n", | ||
375 | GNUNET_i2s (&my_identity), | ||
376 | average, | ||
377 | std_dev); | ||
378 | #endif | ||
379 | GNUNET_SERVER_notification_context_broadcast ( | ||
380 | nc, | ||
381 | ¤t_estimate_message.header, | ||
382 | GNUNET_NO); | ||
383 | |||
384 | GNUNET_STATISTICS_set (stats, "Current network size estimate", | ||
385 | (uint64_t) average, GNUNET_NO); | ||
386 | } | ||
315 | } | 387 | } |
316 | 388 | ||
317 | static void | 389 | static void |
318 | send_flood_message (void *cls, | 390 | send_flood_message(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc); |
319 | const struct GNUNET_SCHEDULER_TaskContext * tc); | ||
320 | 391 | ||
321 | /** | 392 | /** |
322 | * Schedule a flood message to be sent. | 393 | * Schedule a flood message to be sent. |
@@ -332,13 +403,11 @@ send_flood_message (void *cls, | |||
332 | * always be a message scheduled to be sent. | 403 | * always be a message scheduled to be sent. |
333 | */ | 404 | */ |
334 | static void | 405 | static void |
335 | schedule_flood_message (void *cls, | 406 | schedule_flood_message(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
336 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
337 | { | 407 | { |
338 | GNUNET_HashCode timestamp_hash; | 408 | GNUNET_HashCode timestamp_hash; |
339 | struct GNUNET_TIME_Absolute curr_time; | 409 | struct GNUNET_TIME_Absolute curr_time; |
340 | struct GNUNET_TIME_Relative offset; | 410 | struct GNUNET_TIME_Relative offset; |
341 | struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; | ||
342 | unsigned int matching_bits; | 411 | unsigned int matching_bits; |
343 | double millisecond_offset; | 412 | double millisecond_offset; |
344 | 413 | ||
@@ -348,29 +417,46 @@ schedule_flood_message (void *cls, | |||
348 | 417 | ||
349 | GNUNET_assert(flood_task == GNUNET_SCHEDULER_NO_TASK); | 418 | GNUNET_assert(flood_task == GNUNET_SCHEDULER_NO_TASK); |
350 | 419 | ||
351 | if (0 != GNUNET_TIME_absolute_get_remaining(next_timestamp).rel_value) | 420 | if (0 != GNUNET_TIME_absolute_get_remaining (next_timestamp).rel_value) |
352 | { | 421 | { |
353 | GNUNET_break(0); /* Shouldn't ever happen! */ | 422 | GNUNET_break(0); /* Shouldn't ever happen! */ |
354 | schedule_flood_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(next_timestamp), &schedule_flood_message, NULL); | 423 | schedule_flood_task |
424 | = GNUNET_SCHEDULER_add_delayed ( | ||
425 | GNUNET_TIME_absolute_get_remaining ( | ||
426 | next_timestamp), | ||
427 | &schedule_flood_message, NULL); | ||
355 | } | 428 | } |
356 | 429 | ||
357 | /* Get the current UTC time */ | 430 | /* Get the current UTC time */ |
358 | curr_time = GNUNET_TIME_absolute_get(); | 431 | curr_time = GNUNET_TIME_absolute_get (); |
359 | /* Find the previous interval start time */ | 432 | /* Find the previous interval start time */ |
360 | previous_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) * GNUNET_NSE_INTERVAL; | 433 | previous_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) |
434 | * GNUNET_NSE_INTERVAL; | ||
361 | /* Find the next interval start time */ | 435 | /* Find the next interval start time */ |
362 | next_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) * (GNUNET_NSE_INTERVAL + 1); | 436 | next_timestamp.abs_value = previous_timestamp.abs_value + GNUNET_NSE_INTERVAL; |
363 | 437 | #if DEBUG_NSE | |
364 | GNUNET_CRYPTO_hash(&next_timestamp.abs_value, sizeof(uint64_t), ×tamp_hash); | 438 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
365 | matching_bits = GNUNET_CRYPTO_hash_matching_bits(×tamp_hash, &my_identity.hashPubKey); | 439 | "%s: curr_time %lu, prev timestamp %lu, next timestamp %lu\n", |
366 | 440 | GNUNET_i2s (&my_identity), curr_time.abs_value, | |
367 | flood_message.timestamp = GNUNET_TIME_absolute_hton(next_timestamp); | 441 | previous_timestamp.abs_value, next_timestamp.abs_value); |
368 | flood_message.distance = htons(matching_bits); | 442 | #endif |
369 | flood_message.enc_type = htons(0); | 443 | GNUNET_CRYPTO_hash (&next_timestamp.abs_value, |
370 | flood_message.proof_of_work = htonl(0); | 444 | sizeof(next_timestamp.abs_value), ×tamp_hash); |
371 | purpose.purpose = GNUNET_SIGNATURE_PURPOSE_NSE_SEND; | 445 | matching_bits = GNUNET_CRYPTO_hash_matching_bits (×tamp_hash, |
372 | purpose.size = sizeof(struct GNUNET_NSE_FloodMessage) - sizeof(struct GNUNET_MessageHeader) - sizeof(flood_message.proof_of_work) - sizeof(flood_message.signature); | 446 | &my_identity.hashPubKey); |
373 | GNUNET_CRYPTO_rsa_sign(my_private_key, &purpose, &flood_message.signature); | 447 | |
448 | flood_message.header.size = htons (sizeof(struct GNUNET_NSE_FloodMessage)); | ||
449 | flood_message.header.type = htons (GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD); | ||
450 | flood_message.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_NSE_SEND); | ||
451 | flood_message.purpose.size = htonl (sizeof(struct GNUNET_NSE_FloodMessage) | ||
452 | - sizeof(struct GNUNET_MessageHeader) - sizeof(flood_message.signature)); | ||
453 | flood_message.distance = htonl (matching_bits); | ||
454 | flood_message.timestamp = GNUNET_TIME_absolute_hton (next_timestamp); | ||
455 | memcpy (&flood_message.pkey, &my_public_key, | ||
456 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | ||
457 | flood_message.proof_of_work = htonl (0); | ||
458 | GNUNET_CRYPTO_rsa_sign (my_private_key, &flood_message.purpose, | ||
459 | &flood_message.signature); | ||
374 | 460 | ||
375 | /*S + f/2 - (f / pi) * (atan(x - p'))*/ | 461 | /*S + f/2 - (f / pi) * (atan(x - p'))*/ |
376 | 462 | ||
@@ -378,21 +464,135 @@ schedule_flood_message (void *cls, | |||
378 | // f is frequency (GNUNET_NSE_INTERVAL) | 464 | // f is frequency (GNUNET_NSE_INTERVAL) |
379 | // x is matching_bits | 465 | // x is matching_bits |
380 | // p' is current_size_estimate | 466 | // p' is current_size_estimate |
381 | millisecond_offset = ((double)GNUNET_NSE_INTERVAL / (double)2) - ((GNUNET_NSE_INTERVAL / M_PI) * atan(matching_bits - current_size_estimate)); | 467 | millisecond_offset = ((double) GNUNET_NSE_INTERVAL / (double) 2) |
382 | 468 | - ((GNUNET_NSE_INTERVAL / M_PI) * atan (matching_bits | |
383 | fprintf(stderr, "my id matches %d bits, offset is %lu\n", matching_bits, (uint64_t)millisecond_offset); | 469 | - current_size_estimate)); |
384 | 470 | #if DEBUG_NSE | |
385 | estimate_index += 1; | 471 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
472 | "%s: id matches %d bits, offset is %lu\n\n", | ||
473 | GNUNET_i2s (&my_identity), matching_bits, | ||
474 | (uint64_t) millisecond_offset); | ||
475 | #endif | ||
476 | /* Stop initial call from incrementing */ | ||
477 | if (size_estimate_messages[estimate_index].distance != 0) | ||
478 | estimate_index += 1; | ||
386 | 479 | ||
387 | if (estimate_index >= DEFAULT_HISTORY_SIZE) | 480 | if (estimate_index >= DEFAULT_HISTORY_SIZE) |
388 | estimate_index = 0; | 481 | estimate_index = 0; |
389 | 482 | ||
390 | offset.rel_value = (uint64_t)millisecond_offset + GNUNET_TIME_absolute_get_remaining (next_timestamp).rel_value; | 483 | if (millisecond_offset < curr_time.abs_value - previous_timestamp.abs_value) |
391 | flood_task = GNUNET_SCHEDULER_add_delayed (offset, | 484 | offset.rel_value = 0; |
392 | &send_flood_message, NULL); | 485 | else |
486 | offset.rel_value = (uint64_t) millisecond_offset + curr_time.abs_value | ||
487 | - previous_timestamp.abs_value; | ||
488 | #if DEBUG_NSE | ||
489 | GNUNET_log ( | ||
490 | GNUNET_ERROR_TYPE_WARNING, | ||
491 | "%s: milliseconds until next timestamp %lu, sending flood in %lu\n", | ||
492 | GNUNET_i2s (&my_identity), | ||
493 | GNUNET_TIME_absolute_get_remaining (next_timestamp).rel_value, | ||
494 | offset.rel_value); | ||
495 | #endif | ||
496 | flood_task = GNUNET_SCHEDULER_add_delayed (offset, &send_flood_message, NULL); | ||
393 | 497 | ||
394 | } | 498 | } |
395 | 499 | ||
500 | #if VERIFY_CRYPTO | ||
501 | /** | ||
502 | * Check whether the given public key | ||
503 | * and integer are a valid proof of work. | ||
504 | * | ||
505 | * @param pkey the public key | ||
506 | * @param val the integer | ||
507 | * @param want the number of trailing zeroes | ||
508 | * | ||
509 | * @return GNUNET_YES if valid, GNUNET_NO if not | ||
510 | */ | ||
511 | static int check_proof_of_work(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey, uint64_t val, unsigned int want) | ||
512 | { | ||
513 | |||
514 | return GNUNET_YES; | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * Count the trailing zeroes in hash. | ||
519 | * | ||
520 | * @param hash | ||
521 | * | ||
522 | * @return the number of trailing zero bits. | ||
523 | */ | ||
524 | static unsigned int count_trailing_zeroes(GNUNET_HashCode *hash) | ||
525 | { | ||
526 | unsigned int hash_count; | ||
527 | |||
528 | hash_count = sizeof(GNUNET_HashCode) * 8; | ||
529 | while ((0 == GNUNET_CRYPTO_hash_get_bit(hash, hash_count))) | ||
530 | hash_count--; | ||
531 | return (sizeof(GNUNET_HashCode) * 8) - hash_count; | ||
532 | } | ||
533 | |||
534 | /** | ||
535 | * Given a public key, find an integer such that | ||
536 | * the hash of the key concatenated with the integer | ||
537 | * has <param>want</param> trailing 0 bits. | ||
538 | * | ||
539 | * @param pkey the public key | ||
540 | * @param want the number of trailing 0 bits | ||
541 | * | ||
542 | * @return 64 bit number that satisfies the | ||
543 | * requirements | ||
544 | * | ||
545 | * FIXME: use pointer and return GNUNET_YES or | ||
546 | * GNUNET_NO in case no such number works? | ||
547 | */ | ||
548 | static uint64_t find_proof_of_work(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey, unsigned int want) | ||
549 | { | ||
550 | uint64_t counter; | ||
551 | static char buf[sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sizeof(uint64_t)]; | ||
552 | unsigned int data_size; | ||
553 | static GNUNET_HashCode result; | ||
554 | |||
555 | data_size = sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sizeof(uint64_t); | ||
556 | memcpy(buf, pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | ||
557 | counter = 0; | ||
558 | while (counter != (uint64_t)-1) | ||
559 | { | ||
560 | memcpy(&buf[sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)], &counter, sizeof(uint64_t)); | ||
561 | GNUNET_CRYPTO_hash(buf, data_size, &result); | ||
562 | if (want == count_trailing_zeroes(&result)) /* Found good proof of work! */ | ||
563 | break; | ||
564 | counter++; | ||
565 | } | ||
566 | if (counter < (uint64_t)-1) | ||
567 | return counter; /* Found valid proof of work */ | ||
568 | else | ||
569 | return 0; /* Did not find valid proof of work */ | ||
570 | } | ||
571 | |||
572 | /** | ||
573 | * An incoming flood message has been received which claims | ||
574 | * to have more bits matching than any we know in this time | ||
575 | * period. Verify the signature and/or proof of work. | ||
576 | * | ||
577 | * @param incoming_flood the message to verify | ||
578 | * | ||
579 | * @return GNUNET_YES if the message is verified | ||
580 | * GNUNET_NO if the key/signature don't verify | ||
581 | */ | ||
582 | static int verify_message_crypto(struct GNUNET_NSE_FloodMessage *incoming_flood) | ||
583 | { | ||
584 | int ret; | ||
585 | if (GNUNET_OK == (ret | ||
586 | = GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_NSE_SEND, | ||
587 | &incoming_flood->purpose, | ||
588 | &incoming_flood->signature, | ||
589 | &incoming_flood->pkey))) | ||
590 | return GNUNET_YES; | ||
591 | |||
592 | return GNUNET_NO; | ||
593 | } | ||
594 | #endif | ||
595 | |||
396 | /** | 596 | /** |
397 | * Core handler for size estimate flooding messages. | 597 | * Core handler for size estimate flooding messages. |
398 | * | 598 | * |
@@ -408,20 +608,89 @@ handle_p2p_size_estimate(void *cls, const struct GNUNET_PeerIdentity *peer, | |||
408 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) | 608 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) |
409 | { | 609 | { |
410 | struct GNUNET_NSE_FloodMessage *incoming_flood; | 610 | struct GNUNET_NSE_FloodMessage *incoming_flood; |
611 | struct GNUNET_TIME_Absolute curr_time; | ||
612 | uint64_t drift; | ||
411 | 613 | ||
412 | if (ntohs(message->size) != sizeof(struct GNUNET_NSE_FloodMessage)) | 614 | #if DEBUG_NSE |
413 | return GNUNET_NO; | 615 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s: received flood message!\n", |
616 | GNUNET_i2s (&my_identity)); | ||
617 | #endif | ||
618 | if (ntohs (message->size) != sizeof(struct GNUNET_NSE_FloodMessage)) | ||
619 | { | ||
620 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s: bad message size!\n", | ||
621 | GNUNET_i2s (&my_identity)); | ||
622 | return GNUNET_NO; | ||
623 | } | ||
414 | 624 | ||
415 | incoming_flood = (struct GNUNET_NSE_FloodMessage *)message; | 625 | GNUNET_STATISTICS_update (stats, "# flood messages received", 1, GNUNET_NO); |
416 | if (ntohs(incoming_flood->distance) <= ntohs(size_estimate_messages[estimate_index].distance)) /* Not closer than our most recent message */ | 626 | incoming_flood = (struct GNUNET_NSE_FloodMessage *) message; |
417 | return GNUNET_OK; | 627 | if (ntohl (incoming_flood->distance) |
628 | <= ntohl (size_estimate_messages[estimate_index].distance)) /* Not closer than our most recent message */ | ||
629 | { | ||
630 | #if DEBUG_NSE | ||
631 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
632 | "%s: distance %d not greater than %d, discarding\n", | ||
633 | GNUNET_i2s (&my_identity), ntohl (incoming_flood->distance), | ||
634 | ntohl (size_estimate_messages[estimate_index].distance)); | ||
635 | #endif | ||
636 | GNUNET_STATISTICS_update (stats, | ||
637 | "# flood messages discarded (had closer)", 1, | ||
638 | GNUNET_NO); | ||
639 | return GNUNET_OK; | ||
640 | } | ||
641 | |||
642 | curr_time = GNUNET_TIME_absolute_get (); | ||
643 | if (curr_time.abs_value | ||
644 | > GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp).abs_value) | ||
645 | drift = curr_time.abs_value | ||
646 | - GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp).abs_value; | ||
647 | else | ||
648 | drift = GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp).abs_value | ||
649 | - curr_time.abs_value; | ||
650 | |||
651 | if (drift > GNUNET_NSE_DRIFT_TOLERANCE) | ||
652 | { | ||
653 | GNUNET_STATISTICS_update ( | ||
654 | stats, | ||
655 | "# flood messages discarded (clock skew too high)", | ||
656 | 1, GNUNET_NO); | ||
657 | return GNUNET_OK; | ||
658 | } | ||
659 | |||
660 | #if VERIFY_CRYPTO | ||
661 | if (GNUNET_YES != verify_message_crypto(incoming_flood)) | ||
662 | { | ||
663 | GNUNET_STATISTICS_update (stats, | ||
664 | "# flood messages discarded (bad crypto)", | ||
665 | 1, GNUNET_NO); | ||
666 | return GNUNET_OK; | ||
667 | } | ||
668 | #endif | ||
418 | 669 | ||
419 | /* Have a new, better size estimate! */ | 670 | /* Have a new, better size estimate! */ |
420 | update_network_size_estimate(incoming_flood); | 671 | update_network_size_estimate (incoming_flood); |
672 | |||
673 | if (flood_task != GNUNET_SCHEDULER_NO_TASK) | ||
674 | { | ||
675 | #if DEBUG_NSE | ||
676 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s: received closer message, canceling my flood task!\n", GNUNET_i2s(&my_identity)); | ||
677 | #endif | ||
678 | GNUNET_SCHEDULER_cancel (flood_task); | ||
679 | flood_task = GNUNET_SCHEDULER_NO_TASK; | ||
680 | } | ||
421 | 681 | ||
682 | /** Commenting out prevents forwarding of messages */ | ||
683 | #if DO_FORWARD | ||
684 | GNUNET_SCHEDULER_add_now(&send_flood_message, &size_estimate_messages[estimate_index]); | ||
685 | #endif | ||
422 | if (schedule_flood_task != GNUNET_SCHEDULER_NO_TASK) | 686 | if (schedule_flood_task != GNUNET_SCHEDULER_NO_TASK) |
423 | GNUNET_SCHEDULER_cancel(schedule_flood_task); | 687 | GNUNET_SCHEDULER_cancel (schedule_flood_task); |
424 | schedule_flood_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(next_timestamp), &schedule_flood_message, NULL); | 688 | |
689 | schedule_flood_task | ||
690 | = GNUNET_SCHEDULER_add_delayed ( | ||
691 | GNUNET_TIME_absolute_get_remaining ( | ||
692 | next_timestamp), | ||
693 | &schedule_flood_message, NULL); | ||
425 | 694 | ||
426 | return GNUNET_OK; | 695 | return GNUNET_OK; |
427 | } | 696 | } |
@@ -429,39 +698,80 @@ handle_p2p_size_estimate(void *cls, const struct GNUNET_PeerIdentity *peer, | |||
429 | /** | 698 | /** |
430 | * Send a flood message. | 699 | * Send a flood message. |
431 | * | 700 | * |
432 | * If we've gotten here, it means we haven't received | 701 | * If we've gotten here, it means either we haven't received |
433 | * a network size estimate message closer than ours. | 702 | * a network size estimate message closer than ours, or |
703 | * we need to forward a message we received which was closer | ||
704 | * than ours. | ||
434 | */ | 705 | */ |
435 | static void | 706 | static void |
436 | send_flood_message (void *cls, | 707 | send_flood_message(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) |
437 | const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
438 | { | 708 | { |
439 | struct NSEPeerEntry *peer_entry; | 709 | struct NSEPeerEntry *peer_entry; |
710 | struct GNUNET_NSE_FloodMessage *to_send; | ||
711 | |||
712 | if (cls == NULL) /* Means we are sending our OWN flood message */ | ||
713 | to_send = &flood_message; | ||
714 | else | ||
715 | /* Received a message from another peer that should be forwarded */ | ||
716 | to_send = (struct GNUNET_NSE_FloodMessage *) cls; | ||
440 | 717 | ||
441 | flood_task = GNUNET_SCHEDULER_NO_TASK; | 718 | flood_task = GNUNET_SCHEDULER_NO_TASK; |
442 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | 719 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) |
443 | return; | 720 | return; |
444 | 721 | #if DEBUG_NSE | |
722 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
723 | "%s: my time has come, sending flood message of size %d!\n", | ||
724 | GNUNET_i2s (&my_identity), ntohs (to_send->header.size)); | ||
725 | #endif | ||
445 | peer_entry = peers_head; | 726 | peer_entry = peers_head; |
446 | 727 | ||
447 | while (peer_entry != NULL) | 728 | while (peer_entry != NULL) |
448 | { | 729 | { |
730 | peer_entry->pending_message = &to_send->header; | ||
449 | peer_entry->th | 731 | peer_entry->th |
450 | = GNUNET_CORE_notify_transmit_ready (coreAPI, | 732 | = GNUNET_CORE_notify_transmit_ready ( |
451 | GNUNET_YES, | 733 | coreAPI, |
734 | GNUNET_NO, | ||
452 | DEFAULT_NSE_PRIORITY, | 735 | DEFAULT_NSE_PRIORITY, |
453 | GNUNET_TIME_absolute_get_remaining ( | 736 | GNUNET_TIME_absolute_get_remaining ( |
454 | next_timestamp), | 737 | next_timestamp), |
455 | &peer_entry->id, | 738 | &peer_entry->id, |
456 | ntohs (flood_message.header.size), | 739 | ntohs (to_send->header.size), |
457 | &transmit_ready, peer_entry); | 740 | &transmit_ready, peer_entry); |
741 | if (peer_entry->th == NULL) | ||
742 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
743 | "%s: transmit handle is null!\n", GNUNET_i2s (&my_identity)); | ||
744 | #if DEBUG_NSE | ||
745 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
746 | "%s: Sending flood message (distance %d) to %s!\n", | ||
747 | GNUNET_i2s (&my_identity), ntohl (to_send->distance), | ||
748 | GNUNET_h2s (&peer_entry->id.hashPubKey)); | ||
749 | #endif | ||
458 | peer_entry = peer_entry->next; | 750 | peer_entry = peer_entry->next; |
459 | } | 751 | } |
460 | 752 | ||
461 | update_network_size_estimate(&flood_message); | 753 | if (cls == NULL) /* Need to update our size estimate */ |
754 | { | ||
755 | update_network_size_estimate (to_send); | ||
756 | GNUNET_STATISTICS_update (stats, "# flood messages sent", 1, GNUNET_NO); | ||
757 | } | ||
758 | else | ||
759 | GNUNET_STATISTICS_update (stats, "# flood messages forwarded", 1, GNUNET_NO); | ||
760 | |||
761 | #if DEBUG_NSE | ||
762 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
763 | "%s: scheduling schedule_flood_message in %lu\n", | ||
764 | GNUNET_i2s (&my_identity), | ||
765 | GNUNET_TIME_absolute_get_remaining (next_timestamp).rel_value); | ||
766 | #endif | ||
462 | if (schedule_flood_task != GNUNET_SCHEDULER_NO_TASK) | 767 | if (schedule_flood_task != GNUNET_SCHEDULER_NO_TASK) |
463 | GNUNET_SCHEDULER_cancel(schedule_flood_task); | 768 | GNUNET_SCHEDULER_cancel (schedule_flood_task); |
464 | schedule_flood_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(next_timestamp), &schedule_flood_message, NULL); | 769 | |
770 | schedule_flood_task | ||
771 | = GNUNET_SCHEDULER_add_delayed ( | ||
772 | GNUNET_TIME_absolute_get_remaining ( | ||
773 | next_timestamp), | ||
774 | &schedule_flood_message, NULL); | ||
465 | } | 775 | } |
466 | 776 | ||
467 | /** | 777 | /** |
@@ -472,18 +782,19 @@ send_flood_message (void *cls, | |||
472 | * @param atsi performance data | 782 | * @param atsi performance data |
473 | */ | 783 | */ |
474 | static void | 784 | static void |
475 | handle_core_connect (void *cls, | 785 | handle_core_connect(void *cls, const struct GNUNET_PeerIdentity *peer, |
476 | const struct GNUNET_PeerIdentity *peer, | 786 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) |
477 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) | ||
478 | { | 787 | { |
479 | struct NSEPeerEntry *peer_entry; | 788 | struct NSEPeerEntry *peer_entry; |
480 | 789 | ||
790 | if (0 == (memcmp (peer, &my_identity, sizeof(struct GNUNET_PeerIdentity)))) | ||
791 | return; /* Do not connect to self... */ | ||
792 | |||
481 | peer_entry = GNUNET_malloc(sizeof(struct NSEPeerEntry)); | 793 | peer_entry = GNUNET_malloc(sizeof(struct NSEPeerEntry)); |
482 | memcpy(&peer_entry->id, peer, sizeof(struct GNUNET_PeerIdentity)); | 794 | memcpy (&peer_entry->id, peer, sizeof(struct GNUNET_PeerIdentity)); |
483 | GNUNET_CONTAINER_DLL_insert(peers_head, peers_tail, peer_entry); | 795 | GNUNET_CONTAINER_DLL_insert(peers_head, peers_tail, peer_entry); |
484 | } | 796 | } |
485 | 797 | ||
486 | |||
487 | /** | 798 | /** |
488 | * Method called whenever a peer disconnects. | 799 | * Method called whenever a peer disconnects. |
489 | * | 800 | * |
@@ -491,30 +802,37 @@ handle_core_connect (void *cls, | |||
491 | * @param peer peer identity this notification is about | 802 | * @param peer peer identity this notification is about |
492 | */ | 803 | */ |
493 | static void | 804 | static void |
494 | handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) | 805 | handle_core_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer) |
495 | { | 806 | { |
496 | struct NSEPeerEntry *pos; | 807 | struct NSEPeerEntry *pos; |
497 | 808 | ||
809 | if (0 == (memcmp (peer, &my_identity, sizeof(struct GNUNET_PeerIdentity)))) | ||
810 | return; /* Ignore disconnect from self... */ | ||
811 | |||
498 | pos = peers_head; | 812 | pos = peers_head; |
499 | while ((NULL != pos) && (0 != memcmp(&pos->id, peer, sizeof(struct GNUNET_PeerIdentity)))) | 813 | while ((NULL != pos) && (0 != memcmp (&pos->id, peer, |
814 | sizeof(struct GNUNET_PeerIdentity)))) | ||
500 | pos = pos->next; | 815 | pos = pos->next; |
501 | if (pos == NULL) | 816 | if (pos == NULL) |
502 | { | 817 | { |
503 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received disconnect before connect!\n"); | 818 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
819 | "Received disconnect before connect!\n"); | ||
504 | GNUNET_break(0); /* Should never receive a disconnect message for a peer we don't know about... */ | 820 | GNUNET_break(0); /* Should never receive a disconnect message for a peer we don't know about... */ |
505 | return; | 821 | return; |
506 | } | 822 | } |
507 | 823 | ||
824 | /* TODO: decide whether to copy the message, or always use the static pointer */ | ||
825 | #if TODO | ||
508 | if (pos->pending_message != NULL) | 826 | if (pos->pending_message != NULL) |
509 | GNUNET_free(pos->pending_message); | 827 | GNUNET_free(pos->pending_message); |
828 | #endif | ||
510 | 829 | ||
511 | if (pos->th != NULL) | 830 | if (pos->th != NULL) |
512 | GNUNET_CORE_notify_transmit_ready_cancel(pos->th); | 831 | GNUNET_CORE_notify_transmit_ready_cancel (pos->th); |
513 | GNUNET_CONTAINER_DLL_remove(peers_head, peers_tail, pos); | 832 | GNUNET_CONTAINER_DLL_remove(peers_head, peers_tail, pos); |
514 | GNUNET_free(pos); | 833 | GNUNET_free(pos); |
515 | } | 834 | } |
516 | 835 | ||
517 | |||
518 | /** | 836 | /** |
519 | * A client disconnected. Remove it from the | 837 | * A client disconnected. Remove it from the |
520 | * global DLL of clients. | 838 | * global DLL of clients. |
@@ -523,8 +841,7 @@ handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) | |||
523 | * @param client identification of the client | 841 | * @param client identification of the client |
524 | */ | 842 | */ |
525 | static void | 843 | static void |
526 | handle_client_disconnect (void *cls, | 844 | handle_client_disconnect(void *cls, struct GNUNET_SERVER_Client* client) |
527 | struct GNUNET_SERVER_Client* client) | ||
528 | { | 845 | { |
529 | struct ClientListEntry *cle; | 846 | struct ClientListEntry *cle; |
530 | 847 | ||
@@ -533,15 +850,15 @@ handle_client_disconnect (void *cls, | |||
533 | 850 | ||
534 | if (cle != NULL) | 851 | if (cle != NULL) |
535 | { | 852 | { |
536 | GNUNET_SERVER_client_drop(cle->client); | 853 | GNUNET_SERVER_client_drop (cle->client); |
537 | GNUNET_CONTAINER_DLL_remove(cle_head, | 854 | GNUNET_CONTAINER_DLL_remove(cle_head, |
538 | cle_tail, | 855 | cle_tail, |
539 | cle); | 856 | cle); |
540 | GNUNET_free(cle); | 857 | GNUNET_free(cle); |
541 | } | 858 | } |
542 | if (coreAPI != NULL) | 859 | if (coreAPI != NULL) |
543 | { | 860 | { |
544 | GNUNET_CORE_disconnect(coreAPI); | 861 | GNUNET_CORE_disconnect (coreAPI); |
545 | coreAPI = NULL; | 862 | coreAPI = NULL; |
546 | } | 863 | } |
547 | } | 864 | } |
@@ -553,32 +870,33 @@ handle_client_disconnect (void *cls, | |||
553 | * @param tc unused | 870 | * @param tc unused |
554 | */ | 871 | */ |
555 | static void | 872 | static void |
556 | shutdown_task (void *cls, | 873 | shutdown_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
557 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
558 | { | 874 | { |
559 | struct ClientListEntry *cle; | 875 | struct ClientListEntry *cle; |
560 | 876 | ||
561 | if (flood_task != GNUNET_SCHEDULER_NO_TASK) | 877 | if (flood_task != GNUNET_SCHEDULER_NO_TASK) |
562 | GNUNET_SCHEDULER_cancel(flood_task); | 878 | GNUNET_SCHEDULER_cancel (flood_task); |
563 | GNUNET_SERVER_notification_context_destroy (nc); | 879 | GNUNET_SERVER_notification_context_destroy (nc); |
564 | nc = NULL; | 880 | nc = NULL; |
565 | while (NULL != (cle = cle_head)) | 881 | while (NULL != (cle = cle_head)) |
566 | { | 882 | { |
567 | GNUNET_SERVER_client_drop (cle->client); | 883 | GNUNET_SERVER_client_drop (cle->client); |
568 | GNUNET_CONTAINER_DLL_remove (cle_head, | 884 | GNUNET_CONTAINER_DLL_remove (cle_head, |
569 | cle_tail, | 885 | cle_tail, |
570 | cle); | 886 | cle); |
571 | GNUNET_free (cle); | 887 | GNUNET_free (cle); |
572 | } | 888 | } |
573 | 889 | ||
574 | if (coreAPI != NULL) | 890 | if (coreAPI != NULL) |
575 | { | 891 | { |
576 | GNUNET_CORE_disconnect(coreAPI); | 892 | GNUNET_CORE_disconnect (coreAPI); |
577 | coreAPI = NULL; | 893 | coreAPI = NULL; |
578 | } | 894 | } |
579 | 895 | ||
580 | } | 896 | if (stats != NULL) |
897 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
581 | 898 | ||
899 | } | ||
582 | 900 | ||
583 | /** | 901 | /** |
584 | * Called on core init/fail. | 902 | * Called on core init/fail. |
@@ -589,42 +907,54 @@ shutdown_task (void *cls, | |||
589 | * @param publicKey the public key of this peer | 907 | * @param publicKey the public key of this peer |
590 | */ | 908 | */ |
591 | void | 909 | void |
592 | core_init (void *cls, | 910 | core_init(void *cls, struct GNUNET_CORE_Handle *server, |
593 | struct GNUNET_CORE_Handle *server, | 911 | const struct GNUNET_PeerIdentity *identity, |
594 | const struct GNUNET_PeerIdentity *identity, | 912 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey) |
595 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey) | ||
596 | { | 913 | { |
914 | struct GNUNET_TIME_Absolute curr_time; | ||
597 | if (server == NULL) | 915 | if (server == NULL) |
598 | { | 916 | { |
599 | #if DEBUG_NSE | 917 | #if DEBUG_NSE |
600 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 918 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s: Connection to core FAILED!\n", |
601 | "%s: Connection to core FAILED!\n", "nse", | 919 | "nse", GNUNET_i2s (identity)); |
602 | GNUNET_i2s (identity)); | ||
603 | #endif | 920 | #endif |
604 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | 921 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); |
605 | return; | 922 | return; |
606 | } | 923 | } |
607 | #if DEBUG_NSE | ||
608 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
609 | "%s: Core connection initialized, I am peer: %s\n", "nse", | ||
610 | GNUNET_i2s (identity)); | ||
611 | #endif | ||
612 | 924 | ||
613 | /* Copy our identity so we can use it */ | 925 | /* Copy our identity so we can use it */ |
614 | memcpy (&my_identity, identity, sizeof (struct GNUNET_PeerIdentity)); | 926 | memcpy (&my_identity, identity, sizeof(struct GNUNET_PeerIdentity)); |
615 | /* Copy our public key for inclusion in flood messages */ | 927 | /* Copy our public key for inclusion in flood messages */ |
616 | memcpy (&my_public_key, publicKey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | 928 | memcpy (&my_public_key, publicKey, |
617 | 929 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | |
618 | flood_message.header.size = htons(sizeof(struct GNUNET_NSE_FloodMessage)); | ||
619 | flood_message.header.type = htons(GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD); | ||
620 | memcpy(&flood_message.pkey, &my_public_key, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | ||
621 | 930 | ||
622 | if (flood_task != GNUNET_SCHEDULER_NO_TASK) | 931 | if (flood_task != GNUNET_SCHEDULER_NO_TASK) |
623 | GNUNET_SCHEDULER_cancel(flood_task); | 932 | GNUNET_SCHEDULER_cancel (flood_task); |
624 | 933 | ||
625 | schedule_flood_task = GNUNET_SCHEDULER_add_now(&schedule_flood_message, NULL); | 934 | /* Get the current UTC time */ |
935 | curr_time = GNUNET_TIME_absolute_get (); | ||
936 | /* Find the previous interval start time */ | ||
937 | previous_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) | ||
938 | * GNUNET_NSE_INTERVAL; | ||
939 | /* Find the next interval start time */ | ||
940 | next_timestamp.abs_value = previous_timestamp.abs_value + GNUNET_NSE_INTERVAL; | ||
626 | 941 | ||
627 | GNUNET_SERVER_notification_context_broadcast (nc, | 942 | #if DEBUG_NSE |
943 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
944 | "%s: Core connection initialized, I am peer: %s, scheduling flood task in %lu\n", "nse", | ||
945 | GNUNET_i2s (identity), GNUNET_TIME_absolute_get_remaining(next_timestamp)); | ||
946 | #endif | ||
947 | /* FIXME: In production, we'd likely want to do this immediately, but in test-beds it causes stupid behavior */ | ||
948 | if (schedule_flood_task != GNUNET_SCHEDULER_NO_TASK) | ||
949 | GNUNET_SCHEDULER_cancel (schedule_flood_task); | ||
950 | schedule_flood_task | ||
951 | = GNUNET_SCHEDULER_add_delayed ( | ||
952 | GNUNET_TIME_absolute_get_remaining ( | ||
953 | next_timestamp), | ||
954 | &schedule_flood_message, NULL); | ||
955 | |||
956 | GNUNET_SERVER_notification_context_broadcast ( | ||
957 | nc, | ||
628 | ¤t_estimate_message.header, | 958 | ¤t_estimate_message.header, |
629 | GNUNET_NO); | 959 | GNUNET_NO); |
630 | } | 960 | } |
@@ -637,31 +967,28 @@ core_init (void *cls, | |||
637 | * @param c configuration to use | 967 | * @param c configuration to use |
638 | */ | 968 | */ |
639 | static void | 969 | static void |
640 | run (void *cls, | 970 | run(void *cls, struct GNUNET_SERVER_Handle *server, |
641 | struct GNUNET_SERVER_Handle *server, | 971 | const struct GNUNET_CONFIGURATION_Handle *c) |
642 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
643 | { | 972 | { |
644 | char *keyfile; | 973 | char *keyfile; |
645 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { | 974 | static const struct GNUNET_SERVER_MessageHandler handlers[] = |
646 | {&handle_start_message, NULL, GNUNET_MESSAGE_TYPE_NSE_START, 0}, | 975 | { |
647 | {NULL, NULL, 0, 0} | 976 | { &handle_start_message, NULL, GNUNET_MESSAGE_TYPE_NSE_START, 0 }, |
648 | }; | 977 | { NULL, NULL, 0, 0 } }; |
649 | 978 | ||
650 | static const struct GNUNET_CORE_MessageHandler core_handlers[] = { | 979 | static const struct GNUNET_CORE_MessageHandler core_handlers[] = |
651 | {&handle_p2p_size_estimate, GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD, 0}, | 980 | { |
652 | {NULL, 0, 0} | 981 | { &handle_p2p_size_estimate, GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD, 0 }, |
653 | }; | 982 | { NULL, 0, 0 } }; |
654 | 983 | ||
655 | cfg = c; | 984 | cfg = c; |
656 | 985 | ||
657 | if (GNUNET_OK != | 986 | if (GNUNET_OK |
658 | GNUNET_CONFIGURATION_get_value_filename (c, | 987 | != GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", |
659 | "GNUNETD", | 988 | &keyfile)) |
660 | "HOSTKEY", &keyfile)) | ||
661 | { | 989 | { |
662 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 990 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ |
663 | _ | 991 | ("NSE service is lacking key configuration settings. Exiting.\n")); |
664 | ("NSE service is lacking key configuration settings. Exiting.\n")); | ||
665 | GNUNET_SCHEDULER_shutdown (); | 992 | GNUNET_SCHEDULER_shutdown (); |
666 | return; | 993 | return; |
667 | } | 994 | } |
@@ -671,31 +998,29 @@ run (void *cls, | |||
671 | if (my_private_key == NULL) | 998 | if (my_private_key == NULL) |
672 | { | 999 | { |
673 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1000 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
674 | _("NSE Service could not access hostkey. Exiting.\n")); | 1001 | _("NSE Service could not access hostkey. Exiting.\n")); |
675 | GNUNET_SCHEDULER_shutdown (); | 1002 | GNUNET_SCHEDULER_shutdown (); |
676 | return; | 1003 | return; |
677 | } | 1004 | } |
678 | 1005 | ||
679 | GNUNET_SERVER_add_handlers (server, handlers); | 1006 | GNUNET_SERVER_add_handlers (server, handlers); |
680 | nc = GNUNET_SERVER_notification_context_create (server, 16); | 1007 | nc = GNUNET_SERVER_notification_context_create (server, 16); |
681 | GNUNET_SERVER_disconnect_notify (server, | 1008 | GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); |
682 | &handle_client_disconnect, | ||
683 | NULL); | ||
684 | 1009 | ||
685 | flood_task = GNUNET_SCHEDULER_NO_TASK; | 1010 | flood_task = GNUNET_SCHEDULER_NO_TASK; |
686 | /** Connect to core service and register core handlers */ | 1011 | /** Connect to core service and register core handlers */ |
687 | coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */ | 1012 | coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */ |
688 | DEFAULT_CORE_QUEUE_SIZE, /* queue size */ | 1013 | DEFAULT_CORE_QUEUE_SIZE, /* queue size */ |
689 | NULL, /* Closure passed to functions */ | 1014 | NULL, /* Closure passed to functions */ |
690 | &core_init, /* Call core_init once connected */ | 1015 | &core_init, /* Call core_init once connected */ |
691 | &handle_core_connect, /* Handle connects */ | 1016 | &handle_core_connect, /* Handle connects */ |
692 | &handle_core_disconnect, /* Handle disconnects */ | 1017 | &handle_core_disconnect, /* Handle disconnects */ |
693 | NULL, /* Do we care about "status" updates? */ | 1018 | NULL, /* Do we care about "status" updates? */ |
694 | NULL, /* Don't want notified about all incoming messages */ | 1019 | NULL, /* Don't want notified about all incoming messages */ |
695 | GNUNET_NO, /* For header only inbound notification */ | 1020 | GNUNET_NO, /* For header only inbound notification */ |
696 | NULL, /* Don't want notified about all outbound messages */ | 1021 | NULL, /* Don't want notified about all outbound messages */ |
697 | GNUNET_NO, /* For header only outbound notification */ | 1022 | GNUNET_NO, /* For header only outbound notification */ |
698 | core_handlers); /* Register these handlers */ | 1023 | core_handlers); /* Register these handlers */ |
699 | 1024 | ||
700 | if (coreAPI == NULL) | 1025 | if (coreAPI == NULL) |
701 | { | 1026 | { |
@@ -703,26 +1028,26 @@ run (void *cls, | |||
703 | return; | 1028 | return; |
704 | } | 1029 | } |
705 | 1030 | ||
1031 | stats = GNUNET_STATISTICS_create ("NSE", cfg); | ||
1032 | |||
706 | increment | 1033 | increment |
707 | = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | 1034 | = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, |
708 | GNUNET_NSE_INTERVAL | 1035 | GNUNET_NSE_INTERVAL |
709 | / (sizeof(GNUNET_HashCode) | 1036 | / (sizeof(GNUNET_HashCode) * 8)); |
710 | * 8)); | ||
711 | /* Set we have no idea defaults for network size estimate */ | 1037 | /* Set we have no idea defaults for network size estimate */ |
712 | current_size_estimate = 0.0; | 1038 | current_size_estimate = 0.0; |
713 | current_std_dev = NAN; | 1039 | current_std_dev = NAN; |
714 | size_estimates[estimate_index] = 0; | 1040 | size_estimates[estimate_index] = 0; |
715 | current_estimate_message.header.size = htons(sizeof(struct GNUNET_NSE_ClientMessage)); | 1041 | current_estimate_message.header.size |
716 | current_estimate_message.header.type = htons(GNUNET_MESSAGE_TYPE_NSE_ESTIMATE); | 1042 | = htons (sizeof(struct GNUNET_NSE_ClientMessage)); |
1043 | current_estimate_message.header.type | ||
1044 | = htons (GNUNET_MESSAGE_TYPE_NSE_ESTIMATE); | ||
717 | current_estimate_message.size_estimate = current_size_estimate; | 1045 | current_estimate_message.size_estimate = current_size_estimate; |
718 | current_estimate_message.std_deviation = current_std_dev; | 1046 | current_estimate_message.std_deviation = current_std_dev; |
719 | 1047 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | |
720 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
721 | &shutdown_task, | ||
722 | NULL); | 1048 | NULL); |
723 | } | 1049 | } |
724 | 1050 | ||
725 | |||
726 | /** | 1051 | /** |
727 | * The main function for the statistics service. | 1052 | * The main function for the statistics service. |
728 | * | 1053 | * |
@@ -731,14 +1056,11 @@ run (void *cls, | |||
731 | * @return 0 ok, 1 on error | 1056 | * @return 0 ok, 1 on error |
732 | */ | 1057 | */ |
733 | int | 1058 | int |
734 | main (int argc, char *const *argv) | 1059 | main(int argc, char * const *argv) |
735 | { | 1060 | { |
736 | return (GNUNET_OK == | 1061 | return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "nse", |
737 | GNUNET_SERVICE_run (argc, | 1062 | GNUNET_SERVICE_OPTION_NONE, &run, |
738 | argv, | 1063 | NULL)) ? 0 : 1; |
739 | "nse", | ||
740 | GNUNET_SERVICE_OPTION_NONE, | ||
741 | &run, NULL)) ? 0 : 1; | ||
742 | } | 1064 | } |
743 | 1065 | ||
744 | /* End of gnunet-service-nse.c */ | 1066 | /* End of gnunet-service-nse.c */ |
diff --git a/src/nse/nse.h b/src/nse/nse.h index 59dd6bc1b..245bd4ca7 100644 --- a/src/nse/nse.h +++ b/src/nse/nse.h | |||
@@ -30,7 +30,9 @@ | |||
30 | 30 | ||
31 | #include "gnunet_common.h" | 31 | #include "gnunet_common.h" |
32 | 32 | ||
33 | #define DEBUG_NSE GNUNET_YES | 33 | #define DEBUG_NSE GNUNET_NO |
34 | |||
35 | #define VERIFY_CRYPTO GNUNET_NO | ||
34 | 36 | ||
35 | 37 | ||
36 | /** | 38 | /** |
@@ -95,16 +97,16 @@ struct GNUNET_NSE_FloodMessage | |||
95 | struct GNUNET_MessageHeader header; | 97 | struct GNUNET_MessageHeader header; |
96 | 98 | ||
97 | /** | 99 | /** |
98 | * Magic header code(?) | 100 | * Purpose. |
99 | */ | 101 | */ |
100 | uint16_t enc_type; | 102 | struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; |
101 | 103 | ||
102 | /** | 104 | /** |
103 | * Number of matching bits between the hash | 105 | * Number of matching bits between the hash |
104 | * of timestamp and the initiator's public | 106 | * of timestamp and the initiator's public |
105 | * key. | 107 | * key. |
106 | */ | 108 | */ |
107 | uint16_t distance; | 109 | uint32_t distance; |
108 | 110 | ||
109 | /** | 111 | /** |
110 | * The current timestamp value (which all | 112 | * The current timestamp value (which all |
diff --git a/src/nse/nse_api.c b/src/nse/nse_api.c index 20c28e94f..4c441608f 100644 --- a/src/nse/nse_api.c +++ b/src/nse/nse_api.c | |||
@@ -105,6 +105,9 @@ void message_handler (void *cls, | |||
105 | struct GNUNET_NSE_Handle *h = cls; | 105 | struct GNUNET_NSE_Handle *h = cls; |
106 | struct GNUNET_NSE_ClientMessage *client_msg; | 106 | struct GNUNET_NSE_ClientMessage *client_msg; |
107 | 107 | ||
108 | if (msg == NULL) /* Error, timeout, death */ | ||
109 | return; | ||
110 | |||
108 | if ((ntohs (msg->size) < sizeof(struct GNUNET_NSE_ClientMessage)) | 111 | if ((ntohs (msg->size) < sizeof(struct GNUNET_NSE_ClientMessage)) |
109 | || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_NSE_ESTIMATE)) | 112 | || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_NSE_ESTIMATE)) |
110 | { | 113 | { |
diff --git a/src/nse/test_nse.conf b/src/nse/test_nse.conf index 554cc4c0f..32f7a3262 100644 --- a/src/nse/test_nse.conf +++ b/src/nse/test_nse.conf | |||
@@ -5,12 +5,14 @@ DEFAULTCONFIG = test_nse.conf | |||
5 | [nse] | 5 | [nse] |
6 | PORT = 22353 | 6 | PORT = 22353 |
7 | UNIXPATH = /tmp/test-nse-service-nse.unix | 7 | UNIXPATH = /tmp/test-nse-service-nse.unix |
8 | BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/nse/.libs/gnunet-service-nse | ||
9 | PREFIX = valgrind --leak-check=full --log-file=valgrind_nse.%p | ||
8 | AUTOSTART = YES | 10 | AUTOSTART = YES |
9 | DEBUG = YES | 11 | DEBUG = YES |
10 | 12 | ||
11 | [arm] | 13 | [arm] |
12 | PORT = 22354 | 14 | PORT = 22354 |
13 | DEFAULTSERVICES = nse | 15 | DEFAULTSERVICES = nse core |
14 | UNIXPATH = /tmp/test-nse-service-arm.unix | 16 | UNIXPATH = /tmp/test-nse-service-arm.unix |
15 | #DEBUG = YES | 17 | #DEBUG = YES |
16 | 18 | ||
@@ -24,14 +26,26 @@ AUTOSTART = NO | |||
24 | AUTOSTART = NO | 26 | AUTOSTART = NO |
25 | 27 | ||
26 | [transport] | 28 | [transport] |
27 | AUTOSTART = NO | 29 | AUTOSTART = YES |
28 | 30 | ||
29 | [core] | 31 | [core] |
30 | AUTOSTART = YES | 32 | AUTOSTART = YES |
31 | 33 | ||
32 | [peerinfo] | 34 | [peerinfo] |
33 | AUTOSTART = NO | 35 | AUTOSTART = YES |
34 | 36 | ||
35 | [dns] | 37 | [dns] |
36 | AUTOSTART = NO | 38 | AUTOSTART = NO |
37 | 39 | ||
40 | [testing] | ||
41 | NUM_PEERS = 40 | ||
42 | WEAKRANDOM = YES | ||
43 | TOPOLOGY = CLIQUE | ||
44 | F2F = NO | ||
45 | CONNECT_TIMEOUT = 60 | ||
46 | CONNECT_ATTEMPTS = 3 | ||
47 | #DEBUG = YES | ||
48 | HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat | ||
49 | MAX_CONCURRENT_SSH = 20 | ||
50 | USE_PROGRESSBARS = YES | ||
51 | PEERGROUP_TIMEOUT = 180 | ||
diff --git a/src/nse/test_nse_api.c b/src/nse/test_nse_api.c index f7274640a..4f83a6d78 100644 --- a/src/nse/test_nse_api.c +++ b/src/nse/test_nse_api.c | |||
@@ -71,9 +71,9 @@ static void end_test (void *cls, | |||
71 | * @param estimate the value of the current network size estimate | 71 | * @param estimate the value of the current network size estimate |
72 | * @param std_dev standard deviation (rounded down to nearest integer) | 72 | * @param std_dev standard deviation (rounded down to nearest integer) |
73 | * of the size estimation values seen | 73 | * of the size estimation values seen |
74 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | 74 | * |
75 | */ | 75 | */ |
76 | static int | 76 | static void |
77 | check_nse_message (void *cls, double estimate, double std_dev) | 77 | check_nse_message (void *cls, double estimate, double std_dev) |
78 | { | 78 | { |
79 | int *ok = cls; | 79 | int *ok = cls; |
@@ -87,7 +87,6 @@ check_nse_message (void *cls, double estimate, double std_dev) | |||
87 | if (die_task != GNUNET_SCHEDULER_NO_TASK) | 87 | if (die_task != GNUNET_SCHEDULER_NO_TASK) |
88 | GNUNET_SCHEDULER_cancel(die_task); | 88 | GNUNET_SCHEDULER_cancel(die_task); |
89 | GNUNET_SCHEDULER_add_now(&end_test, NULL); | 89 | GNUNET_SCHEDULER_add_now(&end_test, NULL); |
90 | return GNUNET_OK; | ||
91 | } | 90 | } |
92 | 91 | ||
93 | static void | 92 | static void |
diff --git a/src/nse/test_nse_multipeer.c b/src/nse/test_nse_multipeer.c new file mode 100644 index 000000000..600e0c2f2 --- /dev/null +++ b/src/nse/test_nse_multipeer.c | |||
@@ -0,0 +1,233 @@ | |||
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 | * @file nse/test_nse_multipeer.c | ||
22 | * | ||
23 | * @brief Testcase for the network size estimation service. Starts | ||
24 | * a peergroup with a given number of peers, then waits to | ||
25 | * receive size estimates from each peer. Expects to wait | ||
26 | * for one message from each peer. | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_testing_lib.h" | ||
30 | #include "gnunet_nse_service.h" | ||
31 | |||
32 | #define VERBOSE GNUNET_NO | ||
33 | |||
34 | #define NUM_PEERS 4 | ||
35 | |||
36 | struct NSEPeer | ||
37 | { | ||
38 | struct NSEPeer *prev; | ||
39 | |||
40 | struct NSEPeer *next; | ||
41 | |||
42 | struct GNUNET_TESTING_Daemon *daemon; | ||
43 | |||
44 | struct GNUNET_NSE_Handle *nse_handle; | ||
45 | }; | ||
46 | |||
47 | struct NSEPeer *peer_head; | ||
48 | |||
49 | struct NSEPeer *peer_tail; | ||
50 | |||
51 | /** | ||
52 | * How long until we give up on connecting the peers? | ||
53 | */ | ||
54 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500) | ||
55 | |||
56 | static int ok; | ||
57 | |||
58 | static int peers_left; | ||
59 | |||
60 | static unsigned int num_peers; | ||
61 | |||
62 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
63 | |||
64 | /** | ||
65 | * Check whether peers successfully shut down. | ||
66 | */ | ||
67 | void | ||
68 | shutdown_callback (void *cls, const char *emsg) | ||
69 | { | ||
70 | if (emsg != NULL) | ||
71 | { | ||
72 | #if VERBOSE | ||
73 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); | ||
74 | #endif | ||
75 | if (ok == 0) | ||
76 | ok = 666; | ||
77 | } | ||
78 | else | ||
79 | { | ||
80 | #if VERBOSE | ||
81 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
82 | "All peers successfully shut down!\n"); | ||
83 | #endif | ||
84 | ok = 0; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | shutdown_task (void *cls, | ||
90 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
91 | { | ||
92 | struct NSEPeer *pos; | ||
93 | #if VERBOSE | ||
94 | fprintf(stderr, "Ending test.\n"); | ||
95 | #endif | ||
96 | |||
97 | while (NULL != (pos = peer_head)) | ||
98 | { | ||
99 | GNUNET_NSE_disconnect(pos->nse_handle); | ||
100 | GNUNET_CONTAINER_DLL_remove(peer_head, peer_tail, pos); | ||
101 | GNUNET_free(pos); | ||
102 | } | ||
103 | |||
104 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * Callback to call when network size estimate is updated. | ||
109 | * | ||
110 | * @param cls closure | ||
111 | * @param estimate the value of the current network size estimate | ||
112 | * @param std_dev standard deviation (rounded down to nearest integer) | ||
113 | * of the size estimation values seen | ||
114 | * | ||
115 | */ | ||
116 | static void | ||
117 | handle_estimate (void *cls, double estimate, double std_dev) | ||
118 | { | ||
119 | struct NSEPeer *peer = cls; | ||
120 | fprintf(stderr, "Received network size estimate from peer %s. Size: %f std.dev. %f\n", GNUNET_i2s(&peer->daemon->id), estimate, std_dev); | ||
121 | } | ||
122 | |||
123 | static void | ||
124 | connect_nse_service (void *cls, | ||
125 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
126 | { | ||
127 | struct NSEPeer *current_peer; | ||
128 | unsigned int i; | ||
129 | #if VERBOSE | ||
130 | fprintf(stderr, "TEST_NSE_MULTIPEER: connecting to nse service of peers\n"); | ||
131 | #endif | ||
132 | for (i = 0; i < num_peers; i++) | ||
133 | { | ||
134 | current_peer = GNUNET_malloc(sizeof(struct NSEPeer)); | ||
135 | current_peer->daemon = GNUNET_TESTING_daemon_get(pg, i); | ||
136 | current_peer->nse_handle = GNUNET_NSE_connect (current_peer->daemon->cfg, &handle_estimate, current_peer); | ||
137 | GNUNET_assert(current_peer->nse_handle != NULL); | ||
138 | |||
139 | GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static void | ||
144 | my_cb (void *cls, | ||
145 | const char *emsg) | ||
146 | { | ||
147 | if (emsg != NULL) | ||
148 | { | ||
149 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
150 | "Peergroup callback called with error, aborting test!\n"); | ||
151 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n"); | ||
152 | ok = 1; | ||
153 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
154 | return; | ||
155 | } | ||
156 | #if VERBOSE | ||
157 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
158 | "Peer Group started successfully, connecting to NSE service for each peer!\n"); | ||
159 | #endif | ||
160 | |||
161 | GNUNET_SCHEDULER_add_now(&connect_nse_service, NULL); | ||
162 | } | ||
163 | |||
164 | |||
165 | static void | ||
166 | run (void *cls, | ||
167 | char *const *args, | ||
168 | const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
169 | { | ||
170 | struct GNUNET_CONFIGURATION_Handle *testing_cfg; | ||
171 | unsigned long long total_peers; | ||
172 | ok = 1; | ||
173 | testing_cfg = GNUNET_CONFIGURATION_create(); | ||
174 | GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_load(testing_cfg, cfgfile)); | ||
175 | #if VERBOSE | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); | ||
177 | GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", | ||
178 | "use_progressbars", | ||
179 | "YES"); | ||
180 | #endif | ||
181 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing", "num_peers", &total_peers)) | ||
182 | total_peers = NUM_PEERS; | ||
183 | |||
184 | peers_left = total_peers; | ||
185 | num_peers = peers_left; | ||
186 | pg = GNUNET_TESTING_peergroup_start(testing_cfg, | ||
187 | peers_left, | ||
188 | TIMEOUT, | ||
189 | NULL, | ||
190 | &my_cb, NULL, | ||
191 | NULL); | ||
192 | GNUNET_assert (pg != NULL); | ||
193 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &shutdown_task, NULL); | ||
194 | } | ||
195 | |||
196 | static int | ||
197 | check () | ||
198 | { | ||
199 | char *const argv[] = { "test-nse-multipeer", | ||
200 | "-c", | ||
201 | "test_nse.conf", | ||
202 | #if VERBOSE | ||
203 | "-L", "DEBUG", | ||
204 | #endif | ||
205 | NULL | ||
206 | }; | ||
207 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
208 | GNUNET_GETOPT_OPTION_END | ||
209 | }; | ||
210 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, | ||
211 | argv, "test-nse-multipeer", "nohelp", | ||
212 | options, &run, &ok); | ||
213 | return ok; | ||
214 | } | ||
215 | |||
216 | int | ||
217 | main (int argc, char *argv[]) | ||
218 | { | ||
219 | int ret; | ||
220 | |||
221 | GNUNET_log_setup ("test-nse-multipeer", | ||
222 | #if VERBOSE | ||
223 | "DEBUG", | ||
224 | #else | ||
225 | "WARNING", | ||
226 | #endif | ||
227 | NULL); | ||
228 | ret = check (); | ||
229 | GNUNET_DISK_directory_remove ("/tmp/test-nse-multipeer"); | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | /* end of test_nse_multipeer.c */ | ||