diff options
Diffstat (limited to 'src/hostlist/gnunet-daemon-hostlist_server.c')
-rw-r--r-- | src/hostlist/gnunet-daemon-hostlist_server.c | 142 |
1 files changed, 74 insertions, 68 deletions
diff --git a/src/hostlist/gnunet-daemon-hostlist_server.c b/src/hostlist/gnunet-daemon-hostlist_server.c index 54db95009..c4a7aab03 100644 --- a/src/hostlist/gnunet-daemon-hostlist_server.c +++ b/src/hostlist/gnunet-daemon-hostlist_server.c | |||
@@ -42,6 +42,10 @@ | |||
42 | #define GNUNET_ADV_TIMEOUT \ | 42 | #define GNUNET_ADV_TIMEOUT \ |
43 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) | 43 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) |
44 | 44 | ||
45 | /** | ||
46 | * Map with hellos we build the hostlist with. | ||
47 | */ | ||
48 | struct GNUNET_CONTAINER_MultiPeerMap *hellos; | ||
45 | 49 | ||
46 | /** | 50 | /** |
47 | * Handle to the HTTP server as provided by libmicrohttpd for IPv6. | 51 | * Handle to the HTTP server as provided by libmicrohttpd for IPv6. |
@@ -69,6 +73,12 @@ static struct GNUNET_STATISTICS_Handle *stats; | |||
69 | static struct GNUNET_CORE_Handle *core; | 73 | static struct GNUNET_CORE_Handle *core; |
70 | 74 | ||
71 | /** | 75 | /** |
76 | * The task to delayed start the notification process intially. | ||
77 | * We like to give transport some time to give us our hello to distribute it. | ||
78 | */ | ||
79 | struct GNUNET_SCHEDULER_Task *peerstore_notify_task; | ||
80 | |||
81 | /** | ||
72 | * Our peerstore notification context. We use notification | 82 | * Our peerstore notification context. We use notification |
73 | * to instantly learn about new peers as they are discovered. | 83 | * to instantly learn about new peers as they are discovered. |
74 | */ | 84 | */ |
@@ -111,11 +121,6 @@ static char *hostlist_uri; | |||
111 | struct HostSet | 121 | struct HostSet |
112 | { | 122 | { |
113 | /** | 123 | /** |
114 | * Iterator used to build @e data (NULL when done). | ||
115 | */ | ||
116 | struct GNUNET_PEERSTORE_IterateContext *pitr; | ||
117 | |||
118 | /** | ||
119 | * Place where we accumulate all of the HELLO messages. | 124 | * Place where we accumulate all of the HELLO messages. |
120 | */ | 125 | */ |
121 | char *data; | 126 | char *data; |
@@ -188,64 +193,27 @@ finish_response () | |||
188 | * @param hello hello message for the peer (can be NULL) | 193 | * @param hello hello message for the peer (can be NULL) |
189 | * @param err_msg message | 194 | * @param err_msg message |
190 | */ | 195 | */ |
191 | static void | 196 | static enum GNUNET_GenericReturnValue |
192 | host_processor (void *cls, | 197 | host_processor (void *cls, |
193 | const struct GNUNET_PEERSTORE_Record *record, | 198 | const struct GNUNET_PeerIdentity *peer, |
194 | const char *emsg) | 199 | void *value) |
195 | { | 200 | { |
201 | (void *) cls; | ||
196 | size_t old; | 202 | size_t old; |
197 | size_t s; | 203 | size_t s; |
198 | struct GNUNET_MessageHeader *hello; | 204 | struct GNUNET_MessageHeader *hello = value; |
199 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | 205 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); |
200 | struct GNUNET_TIME_Absolute hello_exp; | 206 | struct GNUNET_TIME_Absolute hello_exp; |
201 | 207 | ||
202 | if (NULL != emsg) | 208 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
203 | { | 209 | "host_processor\n"); |
204 | GNUNET_assert (NULL == &record->peer); | ||
205 | builder->pitr = NULL; | ||
206 | GNUNET_free (builder->data); | ||
207 | GNUNET_free (builder); | ||
208 | builder = NULL; | ||
209 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
210 | _ ("Error in communication with PEERSTORE service: %s\n"), | ||
211 | emsg); | ||
212 | return; | ||
213 | } | ||
214 | if (NULL == record) | ||
215 | { | ||
216 | builder->pitr = NULL; | ||
217 | finish_response (); | ||
218 | return; | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | hello = record->value; | ||
223 | if ((0 == record->value_size)) | ||
224 | { | ||
225 | GNUNET_break (0); | ||
226 | return; | ||
227 | } | ||
228 | hello_exp = GNUNET_HELLO_builder_get_expiration_time (hello); | ||
229 | if (GNUNET_TIME_absolute_cmp (hello_exp, <, now)) | ||
230 | { | ||
231 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
232 | "HELLO for peer `%4s' has expired address, not suitable for hostlist!\n", | ||
233 | GNUNET_i2s (&record->peer)); | ||
234 | GNUNET_STATISTICS_update (stats, | ||
235 | gettext_noop ( | ||
236 | "Expired HELLO encountered (ignored)"), | ||
237 | 1, | ||
238 | GNUNET_NO); | ||
239 | return; | ||
240 | } | ||
241 | } | ||
242 | old = builder->size; | 210 | old = builder->size; |
243 | s = ntohs (hello->size); | 211 | s = ntohs (hello->size); |
244 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 212 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
245 | "Received %u bytes of `%s' from peer `%s' for hostlist.\n", | 213 | "Received %u bytes of `%s' from peer `%s' for hostlist.\n", |
246 | (unsigned int) s, | 214 | (unsigned int) s, |
247 | "HELLO", | 215 | "HELLO", |
248 | GNUNET_i2s (&record->peer)); | 216 | GNUNET_i2s (peer)); |
249 | if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) || | 217 | if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) || |
250 | (old + s >= MAX_BYTES_PER_HOSTLISTS)) | 218 | (old + s >= MAX_BYTES_PER_HOSTLISTS)) |
251 | { | 219 | { |
@@ -255,14 +223,16 @@ host_processor (void *cls, | |||
255 | "bytes not included in hostlist (size limit)"), | 223 | "bytes not included in hostlist (size limit)"), |
256 | s, | 224 | s, |
257 | GNUNET_NO); | 225 | GNUNET_NO); |
258 | return; | 226 | return GNUNET_YES; |
259 | } | 227 | } |
260 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 228 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
261 | "Adding peer `%s' to hostlist (%u bytes)\n", | 229 | "Adding peer `%s' to hostlist (%u bytes)\n", |
262 | GNUNET_i2s (&record->peer), | 230 | GNUNET_i2s (peer), |
263 | (unsigned int) s); | 231 | (unsigned int) s); |
264 | GNUNET_array_grow (builder->data, builder->size, old + s); | 232 | GNUNET_array_grow (builder->data, builder->size, old + s); |
265 | GNUNET_memcpy (&builder->data[old], hello, s); | 233 | GNUNET_memcpy (&builder->data[old], hello, s); |
234 | |||
235 | return GNUNET_YES; | ||
266 | } | 236 | } |
267 | 237 | ||
268 | 238 | ||
@@ -500,20 +470,23 @@ process_notify (void *cls, | |||
500 | const struct GNUNET_MessageHeader *hello, | 470 | const struct GNUNET_MessageHeader *hello, |
501 | const char *err_msg) | 471 | const char *err_msg) |
502 | { | 472 | { |
473 | unsigned int map_size; | ||
474 | struct GNUNET_MessageHeader *hello_cpy; | ||
475 | struct GNUNET_PeerIdentity *peer_cpy; | ||
476 | |||
477 | map_size = GNUNET_CONTAINER_multipeermap_size (hellos); | ||
503 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 478 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
504 | "Peerstore is notifying us to rebuild our hostlist\n"); | 479 | "Peerstore is notifying us to rebuild our hostlist map size %u\n", |
480 | map_size); | ||
505 | if (NULL != err_msg) | 481 | if (NULL != err_msg) |
482 | { | ||
506 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 483 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
507 | _ ("Error in communication with PEERSTORE service: %s\n"), | 484 | _ ("Error in communication with PEERSTORE service: %s\n"), |
508 | err_msg); | 485 | err_msg); |
486 | return; | ||
487 | } | ||
509 | if (NULL != builder) | 488 | if (NULL != builder) |
510 | { | 489 | { |
511 | /* restart re-build already in progress ... */ | ||
512 | if (NULL != builder->pitr) | ||
513 | { | ||
514 | GNUNET_PEERSTORE_iterate_cancel (builder->pitr); | ||
515 | builder->pitr = NULL; | ||
516 | } | ||
517 | GNUNET_free (builder->data); | 490 | GNUNET_free (builder->data); |
518 | builder->size = 0; | 491 | builder->size = 0; |
519 | builder->data = NULL; | 492 | builder->data = NULL; |
@@ -522,9 +495,27 @@ process_notify (void *cls, | |||
522 | { | 495 | { |
523 | builder = GNUNET_new (struct HostSet); | 496 | builder = GNUNET_new (struct HostSet); |
524 | } | 497 | } |
525 | GNUNET_assert (NULL != peerstore); | 498 | |
526 | builder->pitr = | 499 | peer_cpy = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
527 | GNUNET_PEERSTORE_iterate (peerstore, "hostlist", NULL, GNUNET_PEERSTORE_HELLO_KEY, &host_processor, NULL); | 500 | GNUNET_memcpy (peer_cpy, peer, sizeof (struct GNUNET_PeerIdentity)); |
501 | hello_cpy = GNUNET_malloc (ntohs (hello->size)); | ||
502 | GNUNET_memcpy (hello_cpy, hello, ntohs (hello->size)); | ||
503 | GNUNET_assert (GNUNET_YES == | ||
504 | GNUNET_CONTAINER_multipeermap_put (hellos, | ||
505 | peer_cpy, | ||
506 | (struct | ||
507 | GNUNET_MessageHeader *) | ||
508 | hello_cpy, | ||
509 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
510 | if (0 != GNUNET_CONTAINER_multipeermap_iterate (hellos, | ||
511 | &host_processor, | ||
512 | NULL)) | ||
513 | finish_response (); | ||
514 | map_size = GNUNET_CONTAINER_multipeermap_size (hellos); | ||
515 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
516 | "1 Peerstore is notifying us to rebuild our hostlist map size %u peer %s\n", | ||
517 | map_size, | ||
518 | GNUNET_i2s (peer)); | ||
528 | } | 519 | } |
529 | 520 | ||
530 | 521 | ||
@@ -605,6 +596,19 @@ prepare_daemon (struct MHD_Daemon *daemon_handle) | |||
605 | } | 596 | } |
606 | 597 | ||
607 | 598 | ||
599 | static void | ||
600 | start_notify (void *cls) | ||
601 | { | ||
602 | (void) cls; | ||
603 | |||
604 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
605 | "Starting to process new hellos to add to hostlist.\n"); | ||
606 | peerstore_notify = | ||
607 | GNUNET_PEERSTORE_hello_changed_notify (peerstore, GNUNET_NO, | ||
608 | &process_notify, NULL); | ||
609 | } | ||
610 | |||
611 | |||
608 | /** | 612 | /** |
609 | * Start server offering our hostlist. | 613 | * Start server offering our hostlist. |
610 | * | 614 | * |
@@ -634,6 +638,7 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c, | |||
634 | const struct sockaddr *sa4; | 638 | const struct sockaddr *sa4; |
635 | const struct sockaddr *sa6; | 639 | const struct sockaddr *sa6; |
636 | 640 | ||
641 | hellos = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES); | ||
637 | advertising = advertise; | 642 | advertising = advertise; |
638 | if (! advertising) | 643 | if (! advertising) |
639 | { | 644 | { |
@@ -817,7 +822,9 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c, | |||
817 | hostlist_task_v4 = prepare_daemon (daemon_handle_v4); | 822 | hostlist_task_v4 = prepare_daemon (daemon_handle_v4); |
818 | if (NULL != daemon_handle_v6) | 823 | if (NULL != daemon_handle_v6) |
819 | hostlist_task_v6 = prepare_daemon (daemon_handle_v6); | 824 | hostlist_task_v6 = prepare_daemon (daemon_handle_v6); |
820 | peerstore_notify = GNUNET_PEERSTORE_hello_changed_notify (peerstore, GNUNET_NO, &process_notify, NULL); | 825 | peerstore_notify_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, |
826 | start_notify, | ||
827 | NULL); | ||
821 | return GNUNET_OK; | 828 | return GNUNET_OK; |
822 | } | 829 | } |
823 | 830 | ||
@@ -859,13 +866,12 @@ GNUNET_HOSTLIST_server_stop () | |||
859 | GNUNET_PEERSTORE_hello_changed_notify_cancel (peerstore_notify); | 866 | GNUNET_PEERSTORE_hello_changed_notify_cancel (peerstore_notify); |
860 | peerstore_notify = NULL; | 867 | peerstore_notify = NULL; |
861 | } | 868 | } |
869 | else if (NULL != peerstore_notify_task) | ||
870 | { | ||
871 | GNUNET_SCHEDULER_cancel (peerstore_notify_task); | ||
872 | } | ||
862 | if (NULL != builder) | 873 | if (NULL != builder) |
863 | { | 874 | { |
864 | if (NULL != builder->pitr) | ||
865 | { | ||
866 | GNUNET_PEERSTORE_iterate_cancel (builder->pitr); | ||
867 | builder->pitr = NULL; | ||
868 | } | ||
869 | GNUNET_free (builder->data); | 875 | GNUNET_free (builder->data); |
870 | GNUNET_free (builder); | 876 | GNUNET_free (builder); |
871 | builder = NULL; | 877 | builder = NULL; |