aboutsummaryrefslogtreecommitdiff
path: root/src/topology
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-06-15 01:28:43 +0000
committerChristian Grothoff <christian@grothoff.org>2009-06-15 01:28:43 +0000
commit4d8a954dceadaced33de7d54470276e40ffd13e9 (patch)
tree946daed2a10abc484a0f224cb8149d8927a382dc /src/topology
parent8bef8cb95d339e9c2e59f2b84744b233ba81a364 (diff)
downloadgnunet-4d8a954dceadaced33de7d54470276e40ffd13e9.tar.gz
gnunet-4d8a954dceadaced33de7d54470276e40ffd13e9.zip
implemented advertising
Diffstat (limited to 'src/topology')
-rw-r--r--src/topology/Makefile.am1
-rw-r--r--src/topology/gnunet-daemon-topology.c328
2 files changed, 325 insertions, 4 deletions
diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am
index 775db33e9..fad32ed79 100644
--- a/src/topology/Makefile.am
+++ b/src/topology/Makefile.am
@@ -13,6 +13,7 @@ gnunet_daemon_topology_SOURCES = \
13gnunet_daemon_topology_LDADD = \ 13gnunet_daemon_topology_LDADD = \
14 $(top_builddir)/src/core/libgnunetcore.la \ 14 $(top_builddir)/src/core/libgnunetcore.la \
15 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 15 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
16 $(top_builddir)/src/transport/libgnunettransport.la \
16 $(top_builddir)/src/util/libgnunetutil.la \ 17 $(top_builddir)/src/util/libgnunetutil.la \
17 $(GN_LIBINTL) 18 $(GN_LIBINTL)
18 19
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index 2b25dccdd..0ef896714 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -29,6 +29,7 @@
29#include "gnunet_core_service.h" 29#include "gnunet_core_service.h"
30#include "gnunet_protocols.h" 30#include "gnunet_protocols.h"
31#include "gnunet_peerinfo_service.h" 31#include "gnunet_peerinfo_service.h"
32#include "gnunet_transport_service.h"
32#include "gnunet_util_lib.h" 33#include "gnunet_util_lib.h"
33 34
34 35
@@ -46,6 +47,19 @@
46 */ 47 */
47#define BLACKLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) 48#define BLACKLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
48 49
50/**
51 * How frequently are we allowed to ask PEERINFO for more
52 * HELLO's to advertise (at most)?
53 */
54#define MIN_HELLO_GATHER_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 27)
55
56/**
57 * How often do we at most advertise the same HELLO to the same peer?
58 * Also used to remove HELLOs of peers that PEERINFO no longer lists
59 * from our cache.
60 */
61#define HELLO_ADVERTISEMENT_MIN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
62
49 63
50/** 64/**
51 * List of neighbours, friends and blacklisted peers. 65 * List of neighbours, friends and blacklisted peers.
@@ -75,6 +89,11 @@ struct PeerList
75 struct GNUNET_TIME_Absolute blacklisted_until; 89 struct GNUNET_TIME_Absolute blacklisted_until;
76 90
77 /** 91 /**
92 * Last time we transmitted a HELLO to this peer?
93 */
94 struct GNUNET_TIME_Absolute last_hello_sent;
95
96 /**
78 * ID of the peer. 97 * ID of the peer.
79 */ 98 */
80 struct GNUNET_PeerIdentity id; 99 struct GNUNET_PeerIdentity id;
@@ -83,6 +102,48 @@ struct PeerList
83 102
84 103
85/** 104/**
105 * List of HELLOs we may consider for advertising.
106 */
107struct HelloList
108{
109 /**
110 * This is a linked list.
111 */
112 struct HelloList *next;
113
114 /**
115 * Pointer to the HELLO message. Memory allocated as part
116 * of the "struct HelloList" --- do not free!
117 */
118 struct GNUNET_HELLO_Message *msg;
119
120 /**
121 * Bloom filter used to mark which peers already got
122 * this HELLO.
123 */
124 struct GNUNET_CONTAINER_BloomFilter *filter;
125
126 /**
127 * What peer is this HELLO for?
128 */
129 struct GNUNET_PeerIdentity id;
130
131 /**
132 * When should we remove this entry from the linked list (either
133 * resetting the filter or possibly eliminating it for good because
134 * we no longer consider the peer to be participating in the
135 * network)?
136 */
137 struct GNUNET_TIME_Absolute expiration;
138};
139
140
141/**
142 * Linked list of HELLOs for advertising.
143 */
144static struct HelloList *hellos;
145
146/**
86 * Our scheduler. 147 * Our scheduler.
87 */ 148 */
88static struct GNUNET_SCHEDULER_Handle * sched; 149static struct GNUNET_SCHEDULER_Handle * sched;
@@ -96,6 +157,11 @@ static struct GNUNET_CONFIGURATION_Handle * cfg;
96 * Handle to the core API. 157 * Handle to the core API.
97 */ 158 */
98static struct GNUNET_CORE_Handle *handle; 159static struct GNUNET_CORE_Handle *handle;
160
161/**
162 * Handle to the transport API.
163 */
164static struct GNUNET_TRANSPORT_Handle *transport;
99 165
100/** 166/**
101 * Identity of this peer. 167 * Identity of this peer.
@@ -109,6 +175,11 @@ static struct GNUNET_PeerIdentity my_identity;
109static struct PeerList *friends; 175static struct PeerList *friends;
110 176
111/** 177/**
178 * Timestamp from the last time we tried to gather HELLOs.
179 */
180static struct GNUNET_TIME_Absolute last_hello_gather_time;
181
182/**
112 * Flag to disallow non-friend connections (pure F2F mode). 183 * Flag to disallow non-friend connections (pure F2F mode).
113 */ 184 */
114static int friends_only; 185static int friends_only;
@@ -139,6 +210,12 @@ static unsigned int friend_count;
139 */ 210 */
140static int autoconnect; 211static int autoconnect;
141 212
213/**
214 * Are we currently having a request pending with
215 * PEERINFO asking for HELLOs for advertising?
216 */
217static int hello_gathering_active;
218
142 219
143 220
144/** 221/**
@@ -393,14 +470,85 @@ schedule_peer_search ()
393} 470}
394 471
395 472
473
474
475/**
476 * Iterator called on each address.
477 *
478 * @param cls flag that we will set if we see any addresses.
479 */
480static int
481address_iterator (void *cls,
482 const char *tname,
483 struct GNUNET_TIME_Absolute expiration,
484 const void *addr, size_t addrlen)
485{
486 int *flag = cls;
487 *flag = GNUNET_YES;
488 return GNUNET_SYSERR;
489}
490
491
492/**
493 * We've gotten a HELLO from another peer.
494 * Consider it for advertising.
495 */
496static void
497consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
498{
499 int have_address;
500 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
501 struct GNUNET_PeerIdentity pid;
502 struct HelloList *pos;
503 uint16_t size;
504
505 have_address = GNUNET_NO;
506 GNUNET_HELLO_iterate_addresses (hello,
507 GNUNET_NO,
508 &address_iterator,
509 &have_address);
510 if (GNUNET_NO == have_address)
511 return; /* no point in advertising this one... */
512 GNUNET_HELLO_get_key (hello, &pkey);
513 GNUNET_CRYPTO_hash (&pkey, sizeof (pkey), &pid.hashPubKey);
514 pos = hellos;
515 while (pos != NULL)
516 {
517 if (0 == memcmp (&pos->id,
518 &pid,
519 sizeof(struct GNUNET_PeerIdentity)))
520 return; /* duplicate, at least "mostly" */
521 pos = pos->next;
522 }
523 size = GNUNET_HELLO_size (hello);
524 pos = GNUNET_malloc (sizeof(struct HelloList) + size);
525 pos->msg = (struct GNUNET_HELLO_Message*) &pos[1];
526 memcpy (&pos->msg, hello, size);
527 pos->id = pid;
528 pos->expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY);
529 /* 2^{-5} chance of not sending a HELLO to a peer is
530 acceptably small (if the filter is 50% full);
531 64 bytes of memory are small compared to the rest
532 of the data structure and would only really become
533 "useless" once a HELLO has been passed on to ~100
534 other peers, which is likely more than enough in
535 any case; hence 64, 5 as bloomfilter parameters. */
536 pos->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, 64, 5);
537 /* never send a peer its own HELLO */
538 GNUNET_CONTAINER_bloomfilter_add (pos->filter, &pos->id.hashPubKey);
539 pos->next = hellos;
540 hellos = pos;
541}
542
543
396/** 544/**
397 * Peerinfo calls this function to let us know about a 545 * Peerinfo calls this function to let us know about a
398 * possible peer that we might want to connect to. 546 * possible peer that we might want to connect to.
399 */ 547 */
400static void 548static void
401process_peer (void *cls, 549process_peer (void *cls,
402 const struct GNUNET_PeerIdentity * peer, 550 const struct GNUNET_PeerIdentity *peer,
403 const struct GNUNET_HELLO_Message * hello, 551 const struct GNUNET_HELLO_Message *hello,
404 uint32_t trust) 552 uint32_t trust)
405{ 553{
406 struct PeerList *pos; 554 struct PeerList *pos;
@@ -420,6 +568,7 @@ process_peer (void *cls,
420 peer, sizeof (struct GNUNET_PeerIdentity))) 568 peer, sizeof (struct GNUNET_PeerIdentity)))
421 return; /* that's me! */ 569 return; /* that's me! */
422 570
571 consider_for_advertising (hello);
423 pos = friends; 572 pos = friends;
424 while (pos != NULL) 573 while (pos != NULL)
425 { 574 {
@@ -436,7 +585,7 @@ process_peer (void *cls,
436 } 585 }
437 } 586 }
438 pos = pos->next; 587 pos = pos->next;
439 } 588 }
440 if (GNUNET_YES == friends_only) 589 if (GNUNET_YES == friends_only)
441 return; 590 return;
442 if (friend_count < minimum_friend_count) 591 if (friend_count < minimum_friend_count)
@@ -681,6 +830,162 @@ read_friends_file (struct GNUNET_CONFIGURATION_Handle *cfg)
681 830
682 831
683/** 832/**
833 * This function is called whenever an encrypted HELLO message is
834 * received.
835 *
836 * @param cls closure
837 * @param peer the other peer involved (sender or receiver, NULL
838 * for loopback messages where we are both sender and receiver)
839 * @param message the actual HELLO message
840 * @return GNUNET_OK to keep the connection open,
841 * GNUNET_SYSERR to close it (signal serious error)
842 */
843static int
844handle_encrypted_hello (void *cls,
845 const struct GNUNET_PeerIdentity * other,
846 const struct GNUNET_MessageHeader *
847 message)
848{
849 if (transport != NULL)
850 GNUNET_TRANSPORT_offer_hello (transport,
851 message);
852 return GNUNET_OK;
853}
854
855
856/**
857 * Peerinfo calls this function to let us know about a
858 * possible peer that we might want to connect to.
859 */
860static void
861gather_hello_callback (void *cls,
862 const struct GNUNET_PeerIdentity *peer,
863 const struct GNUNET_HELLO_Message *hello,
864 uint32_t trust)
865{
866 if (peer == NULL)
867 {
868 hello_gathering_active = GNUNET_NO;
869 return;
870 }
871 if (hello != NULL)
872 consider_for_advertising (hello);
873}
874
875
876/**
877 * Function to fill send buffer with HELLO.
878 *
879 * @param receiver the receiver of the message
880 * @param position is the reference to the
881 * first unused position in the buffer where GNUnet is building
882 * the message
883 * @param padding is the number of bytes left in that buffer.
884 * @return the number of bytes written to
885 * that buffer (must be a positive number).
886 */
887static unsigned int
888hello_advertising (void *cls,
889 const struct GNUNET_PeerIdentity *
890 receiver,
891 void *position, unsigned int padding)
892{
893 struct PeerList *pl;
894 struct HelloList *pos;
895 struct HelloList *prev;
896 struct HelloList *next;
897 uint16_t size;
898
899 pl = friends;
900 while (pl != NULL)
901 {
902 if (0 == memcmp (&pl->id, receiver, sizeof (struct GNUNET_PeerIdentity)))
903 break;
904 pl = pl->next;
905 }
906 if (pl == NULL)
907 {
908 GNUNET_break (0);
909 return 0;
910 }
911 /* find applicable HELLOs */
912 prev = NULL;
913 next = hellos;
914 while (NULL != (pos = next))
915 {
916 next = pos->next;
917 if (GNUNET_NO ==
918 GNUNET_CONTAINER_bloomfilter_test (pos->filter,
919 &receiver->hashPubKey))
920 break;
921 if (0 == GNUNET_TIME_absolute_get_remaining (pos->expiration).value)
922 {
923 /* time to discard... */
924 if (prev == NULL)
925 prev->next = next;
926 else
927 hellos = next;
928 GNUNET_CONTAINER_bloomfilter_free (pos->filter);
929 GNUNET_free (pos);
930 }
931 else
932 {
933 prev = pos;
934 }
935 }
936 if (pos != NULL)
937 {
938 size = GNUNET_HELLO_size (pos->msg);
939 if (size < padding)
940 {
941 memcpy (position, pos->msg, size);
942 GNUNET_CONTAINER_bloomfilter_add (pos->filter,
943 &receiver->hashPubKey);
944 }
945 else
946 {
947 size = 0;
948 }
949 return size;
950 }
951 if ( (GNUNET_NO == hello_gathering_active) &&
952 (GNUNET_TIME_absolute_get_duration (last_hello_gather_time).value >
953 MIN_HELLO_GATHER_DELAY.value) )
954 {
955 hello_gathering_active = GNUNET_YES;
956 last_hello_gather_time = GNUNET_TIME_absolute_get();
957 GNUNET_PEERINFO_for_all (cfg,
958 sched,
959 NULL,
960 0, GNUNET_TIME_UNIT_FOREVER_REL,
961 &gather_hello_callback, NULL);
962 }
963 return 0;
964}
965
966
967/**
968 * Last task run during shutdown. Disconnects us from
969 * the transport and core.
970 */
971static void
972cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
973{
974 struct PeerList *pl;
975
976 GNUNET_TRANSPORT_disconnect (transport);
977 transport = NULL;
978 GNUNET_CORE_disconnect (handle);
979 handle = NULL;
980 while (NULL != (pl = friends))
981 {
982 friends = pl->next;
983 GNUNET_free (pl);
984 }
985}
986
987
988/**
684 * Main function that will be run. 989 * Main function that will be run.
685 * 990 *
686 * @param cls closure 991 * @param cls closure
@@ -698,6 +1003,7 @@ run (void *cls,
698{ 1003{
699 struct GNUNET_CORE_MessageHandler handlers[] = 1004 struct GNUNET_CORE_MessageHandler handlers[] =
700 { 1005 {
1006 { &handle_encrypted_hello, GNUNET_MESSAGE_TYPE_HELLO, 0},
701 { NULL, 0, 0 } 1007 { NULL, 0, 0 }
702 }; 1008 };
703 unsigned long long opt; 1009 unsigned long long opt;
@@ -726,6 +1032,13 @@ run (void *cls,
726 if ( (friends_only == GNUNET_YES) || 1032 if ( (friends_only == GNUNET_YES) ||
727 (minimum_friend_count > 0) ) 1033 (minimum_friend_count > 0) )
728 read_friends_file (cfg); 1034 read_friends_file (cfg);
1035
1036 transport = GNUNET_TRANSPORT_connect (sched,
1037 cfg,
1038 NULL,
1039 NULL,
1040 NULL,
1041 NULL);
729 GNUNET_CORE_connect (sched, 1042 GNUNET_CORE_connect (sched,
730 cfg, 1043 cfg,
731 GNUNET_TIME_UNIT_FOREVER_REL, 1044 GNUNET_TIME_UNIT_FOREVER_REL,
@@ -733,10 +1046,17 @@ run (void *cls,
733 &core_init, 1046 &core_init,
734 &connect_notify, 1047 &connect_notify,
735 &disconnect_notify, 1048 &disconnect_notify,
736 NULL, 1049 &hello_advertising,
737 NULL, GNUNET_NO, 1050 NULL, GNUNET_NO,
738 NULL, GNUNET_NO, 1051 NULL, GNUNET_NO,
739 handlers); 1052 handlers);
1053
1054 GNUNET_SCHEDULER_add_delayed (sched,
1055 GNUNET_YES,
1056 GNUNET_SCHEDULER_PRIORITY_IDLE,
1057 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1058 GNUNET_TIME_UNIT_FOREVER_REL,
1059 &cleaning_task, NULL);
740} 1060}
741 1061
742 1062