aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo/gnunet-service-peerinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/peerinfo/gnunet-service-peerinfo.c')
-rw-r--r--src/peerinfo/gnunet-service-peerinfo.c195
1 files changed, 99 insertions, 96 deletions
diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c
index ee8749955..4879eea34 100644
--- a/src/peerinfo/gnunet-service-peerinfo.c
+++ b/src/peerinfo/gnunet-service-peerinfo.c
@@ -33,6 +33,7 @@
33 33
34#include "platform.h" 34#include "platform.h"
35#include "gnunet_crypto_lib.h" 35#include "gnunet_crypto_lib.h"
36#include "gnunet_container_lib.h"
36#include "gnunet_disk_lib.h" 37#include "gnunet_disk_lib.h"
37#include "gnunet_hello_lib.h" 38#include "gnunet_hello_lib.h"
38#include "gnunet_protocols.h" 39#include "gnunet_protocols.h"
@@ -57,11 +58,6 @@ struct HostEntry
57{ 58{
58 59
59 /** 60 /**
60 * This is a linked list.
61 */
62 struct HostEntry *next;
63
64 /**
65 * Identity of the peer. 61 * Identity of the peer.
66 */ 62 */
67 struct GNUNET_PeerIdentity identity; 63 struct GNUNET_PeerIdentity identity;
@@ -75,9 +71,10 @@ struct HostEntry
75 71
76 72
77/** 73/**
78 * The in-memory list of known hosts. 74 * The in-memory list of known hosts, mapping of
75 * host IDs to 'struct HostEntry*' values.
79 */ 76 */
80static struct HostEntry *hosts; 77static struct GNUNET_CONTAINER_MultiHashMap *hostmap;
81 78
82/** 79/**
83 * Clients to immediately notify about all changes. 80 * Clients to immediately notify about all changes.
@@ -163,24 +160,6 @@ get_host_filename (const struct GNUNET_PeerIdentity *id)
163 160
164 161
165/** 162/**
166 * Find the host entry for the given peer. FIXME: replace by hash map!
167 * @return NULL if not found
168 */
169static struct HostEntry *
170lookup_host_entry (const struct GNUNET_PeerIdentity *id)
171{
172 struct HostEntry *pos;
173
174 pos = hosts;
175 while ((pos != NULL) &&
176 (0 !=
177 memcmp (id, &pos->identity, sizeof (struct GNUNET_PeerIdentity))))
178 pos = pos->next;
179 return pos;
180}
181
182
183/**
184 * Broadcast information about the given entry to all 163 * Broadcast information about the given entry to all
185 * clients that care. 164 * clients that care.
186 * 165 *
@@ -215,7 +194,8 @@ add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
215 struct GNUNET_TIME_Absolute now; 194 struct GNUNET_TIME_Absolute now;
216 char *fn; 195 char *fn;
217 196
218 entry = lookup_host_entry (identity); 197 entry = GNUNET_CONTAINER_multihashmap_get (hostmap,
198 &identity->hashPubKey);
219 if (entry != NULL) 199 if (entry != NULL)
220 return; 200 return;
221 GNUNET_STATISTICS_update (stats, 201 GNUNET_STATISTICS_update (stats,
@@ -250,8 +230,10 @@ add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
250 } 230 }
251 } 231 }
252 GNUNET_free (fn); 232 GNUNET_free (fn);
253 entry->next = hosts; 233 GNUNET_CONTAINER_multihashmap_put (hostmap,
254 hosts = entry; 234 &identity->hashPubKey,
235 entry,
236 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
255 notify_all (entry); 237 notify_all (entry);
256} 238}
257 239
@@ -275,7 +257,8 @@ remove_garbage (const char *fullname)
275 257
276 258
277static int 259static int
278hosts_directory_scan_callback (void *cls, const char *fullname) 260hosts_directory_scan_callback (void *cls,
261 const char *fullname)
279{ 262{
280 unsigned int *matched = cls; 263 unsigned int *matched = cls;
281 struct GNUNET_PeerIdentity identity; 264 struct GNUNET_PeerIdentity identity;
@@ -350,7 +333,8 @@ bind_address (const struct GNUNET_PeerIdentity *peer,
350 struct GNUNET_TIME_Absolute delta; 333 struct GNUNET_TIME_Absolute delta;
351 334
352 add_host_to_known_hosts (peer); 335 add_host_to_known_hosts (peer);
353 host = lookup_host_entry (peer); 336 host = GNUNET_CONTAINER_multihashmap_get (hostmap,
337 &peer->hashPubKey);
354 GNUNET_assert (host != NULL); 338 GNUNET_assert (host != NULL);
355 if (host->hello == NULL) 339 if (host->hello == NULL)
356 { 340 {
@@ -383,63 +367,43 @@ bind_address (const struct GNUNET_PeerIdentity *peer,
383} 367}
384 368
385 369
370
386/** 371/**
387 * Do transmit info either for only the host matching the given 372 * Do transmit info about peer to given host.
388 * argument or for all known hosts.
389 * 373 *
390 * @param only NULL to hit all hosts, otherwise specifies a particular target 374 * @param cls NULL to hit all hosts, otherwise specifies a particular target
391 * @param client who is making the request (and will thus receive our confirmation) 375 * @param key hostID
376 * @param value information to transmit
377 * @return GNUNET_YES (continue to iterate)
392 */ 378 */
393static void 379static int
394send_to_each_host (const struct GNUNET_PeerIdentity *only, 380add_to_tc (void *cls,
395 struct GNUNET_SERVER_Client *client) 381 const GNUNET_HashCode *key,
382 void *value)
396{ 383{
397 struct HostEntry *pos; 384 struct GNUNET_SERVER_TransmitContext *tc = cls;
385 struct HostEntry *pos = value;
398 struct InfoMessage *im; 386 struct InfoMessage *im;
399 uint16_t hs; 387 uint16_t hs;
400 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; 388 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
401 struct GNUNET_SERVER_TransmitContext *tc;
402 int match;
403 389
404 tc = GNUNET_SERVER_transmit_context_create (client); 390 hs = 0;
405 match = GNUNET_NO; 391 im = (struct InfoMessage *) buf;
406 pos = hosts; 392 if (pos->hello != NULL)
407 while (pos != NULL)
408 { 393 {
409 if ((only == NULL) || 394 hs = GNUNET_HELLO_size (pos->hello);
410 (0 == 395 GNUNET_assert (hs <
411 memcmp (only, &pos->identity, 396 GNUNET_SERVER_MAX_MESSAGE_SIZE -
412 sizeof (struct GNUNET_PeerIdentity)))) 397 sizeof (struct InfoMessage));
413 { 398 memcpy (&im[1], pos->hello, hs);
414 hs = 0;
415 im = (struct InfoMessage *) buf;
416 if (pos->hello != NULL)
417 {
418 hs = GNUNET_HELLO_size (pos->hello);
419 GNUNET_assert (hs <
420 GNUNET_SERVER_MAX_MESSAGE_SIZE -
421 sizeof (struct InfoMessage));
422 memcpy (&im[1], pos->hello, hs);
423 match = GNUNET_YES;
424 }
425 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
426 im->header.size = htons (sizeof (struct InfoMessage) + hs);
427 im->reserved = htonl (0);
428 im->peer = pos->identity;
429 GNUNET_SERVER_transmit_context_append_message (tc,
430 &im->header);
431 }
432 pos = pos->next;
433 } 399 }
434 if ( (only != NULL) && 400 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
435 (match == GNUNET_NO) ) 401 im->header.size = htons (sizeof (struct InfoMessage) + hs);
436 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 402 im->reserved = htonl (0);
437 "No `%s' message was found for peer `%4s'\n", 403 im->peer = pos->identity;
438 "HELLO", 404 GNUNET_SERVER_transmit_context_append_message (tc,
439 GNUNET_i2s (only)); 405 &im->header);
440 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, 406 return GNUNET_YES;
441 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
442 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
443} 407}
444 408
445 409
@@ -500,7 +464,6 @@ cron_clean_data_hosts (void *cls,
500 now = GNUNET_TIME_absolute_get (); 464 now = GNUNET_TIME_absolute_get ();
501 GNUNET_DISK_directory_scan (networkIdDirectory, 465 GNUNET_DISK_directory_scan (networkIdDirectory,
502 &discard_hosts_helper, &now); 466 &discard_hosts_helper, &now);
503
504 GNUNET_SCHEDULER_add_delayed (tc->sched, 467 GNUNET_SCHEDULER_add_delayed (tc->sched,
505 DATA_HOST_CLEAN_FREQ, 468 DATA_HOST_CLEAN_FREQ,
506 &cron_clean_data_hosts, NULL); 469 &cron_clean_data_hosts, NULL);
@@ -553,6 +516,7 @@ handle_get (void *cls,
553 const struct GNUNET_MessageHeader *message) 516 const struct GNUNET_MessageHeader *message)
554{ 517{
555 const struct ListPeerMessage *lpm; 518 const struct ListPeerMessage *lpm;
519 struct GNUNET_SERVER_TransmitContext *tc;
556 520
557 lpm = (const struct ListPeerMessage *) message; 521 lpm = (const struct ListPeerMessage *) message;
558#if DEBUG_PEERINFO 522#if DEBUG_PEERINFO
@@ -561,7 +525,14 @@ handle_get (void *cls,
561 "GET", 525 "GET",
562 GNUNET_i2s (&lpm->peer)); 526 GNUNET_i2s (&lpm->peer));
563#endif 527#endif
564 send_to_each_host (&lpm->peer, client); 528 tc = GNUNET_SERVER_transmit_context_create (client);
529 GNUNET_CONTAINER_multihashmap_get_multiple (hostmap,
530 &lpm->peer.hashPubKey,
531 &add_to_tc,
532 tc);
533 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
534 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
535 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
565} 536}
566 537
567 538
@@ -577,12 +548,39 @@ handle_get_all (void *cls,
577 struct GNUNET_SERVER_Client *client, 548 struct GNUNET_SERVER_Client *client,
578 const struct GNUNET_MessageHeader *message) 549 const struct GNUNET_MessageHeader *message)
579{ 550{
551 struct GNUNET_SERVER_TransmitContext *tc;
552
580#if DEBUG_PEERINFO 553#if DEBUG_PEERINFO
581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
582 "`%s' message received\n", 555 "`%s' message received\n",
583 "GET_ALL"); 556 "GET_ALL");
584#endif 557#endif
585 send_to_each_host (NULL, client); 558 tc = GNUNET_SERVER_transmit_context_create (client);
559 GNUNET_CONTAINER_multihashmap_iterate (hostmap,
560 &add_to_tc,
561 tc);
562 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
563 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
564 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
565}
566
567
568static int
569do_notify_entry (void *cls,
570 const GNUNET_HashCode *key,
571 void *value)
572{
573 struct GNUNET_SERVER_Client *client = cls;
574 struct HostEntry *he = value;
575 struct InfoMessage *msg;
576
577 msg = make_info_message (he);
578 GNUNET_SERVER_notification_context_unicast (notify_list,
579 client,
580 &msg->header,
581 GNUNET_NO);
582 GNUNET_free (msg);
583 return GNUNET_YES;
586} 584}
587 585
588 586
@@ -595,12 +593,9 @@ handle_get_all (void *cls,
595 */ 593 */
596static void 594static void
597handle_notify (void *cls, 595handle_notify (void *cls,
598 struct GNUNET_SERVER_Client *client, 596 struct GNUNET_SERVER_Client *client,
599 const struct GNUNET_MessageHeader *message) 597 const struct GNUNET_MessageHeader *message)
600{ 598{
601 struct InfoMessage *msg;
602 struct HostEntry *pos;
603
604#if DEBUG_PEERINFO 599#if DEBUG_PEERINFO
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606 "`%s' message received\n", 601 "`%s' message received\n",
@@ -608,20 +603,22 @@ handle_notify (void *cls,
608#endif 603#endif
609 GNUNET_SERVER_notification_context_add (notify_list, 604 GNUNET_SERVER_notification_context_add (notify_list,
610 client); 605 client);
611 pos = hosts; 606 GNUNET_CONTAINER_multihashmap_iterate (hostmap,
612 while (NULL != pos) 607 &do_notify_entry,
613 { 608 client);
614 msg = make_info_message (pos);
615 GNUNET_SERVER_notification_context_unicast (notify_list,
616 client,
617 &msg->header,
618 GNUNET_NO);
619 GNUNET_free (msg);
620 pos = pos->next;
621 }
622} 609}
623 610
624 611
612static int
613free_host_entry (void *cls,
614 const GNUNET_HashCode *key,
615 void *value)
616{
617 struct HostEntry *he = value;
618 GNUNET_free (he);
619 return GNUNET_YES;
620}
621
625/** 622/**
626 * Clean up our state. Called during shutdown. 623 * Clean up our state. Called during shutdown.
627 * 624 *
@@ -634,6 +631,10 @@ shutdown_task (void *cls,
634{ 631{
635 GNUNET_SERVER_notification_context_destroy (notify_list); 632 GNUNET_SERVER_notification_context_destroy (notify_list);
636 notify_list = NULL; 633 notify_list = NULL;
634 GNUNET_CONTAINER_multihashmap_iterate (hostmap,
635 &free_host_entry,
636 NULL);
637 GNUNET_CONTAINER_multihashmap_destroy (hostmap);
637 if (stats != NULL) 638 if (stats != NULL)
638 { 639 {
639 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 640 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
@@ -666,6 +667,8 @@ run (void *cls,
666 sizeof (struct GNUNET_MessageHeader)}, 667 sizeof (struct GNUNET_MessageHeader)},
667 {NULL, NULL, 0, 0} 668 {NULL, NULL, 0, 0}
668 }; 669 };
670
671 hostmap = GNUNET_CONTAINER_multihashmap_create (1024);
669 stats = GNUNET_STATISTICS_create (sched, "peerinfo", cfg); 672 stats = GNUNET_STATISTICS_create (sched, "peerinfo", cfg);
670 notify_list = GNUNET_SERVER_notification_context_create (server, 0); 673 notify_list = GNUNET_SERVER_notification_context_create (server, 0);
671 GNUNET_assert (GNUNET_OK == 674 GNUNET_assert (GNUNET_OK ==