summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hostlist/gnunet-daemon-hostlist.c50
-rw-r--r--src/hostlist/gnunet-daemon-hostlist.h25
-rw-r--r--src/hostlist/hostlist-client.c451
-rw-r--r--src/hostlist/hostlist-client.h42
-rw-r--r--src/hostlist/hostlist-server.c214
-rw-r--r--src/hostlist/hostlist-server.h2
6 files changed, 324 insertions, 460 deletions
diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c
index 3622e0e8f..c06ee5f56 100644
--- a/src/hostlist/gnunet-daemon-hostlist.c
+++ b/src/hostlist/gnunet-daemon-hostlist.c
@@ -168,21 +168,11 @@ static int advertisement_handler (void *cls,
168 struct GNUNET_TIME_Relative latency, 168 struct GNUNET_TIME_Relative latency,
169 uint32_t distance) 169 uint32_t distance)
170{ 170{
171 if ( !learning ) 171 GNUNET_assert (NULL != client_adv_handler);
172 { 172 return (*client_adv_handler) (cls, peer, message, latency, distance);
173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
174 "Recieved hostlist advertisement, but I am not learning!\n");
175 return GNUNET_NO;
176 }
177
178 if (learning && (NULL != client_adv_handler))
179 {
180 (*client_adv_handler) (cls, peer, message, latency, distance);
181 return GNUNET_YES;
182 }
183 return GNUNET_NO;
184} 173}
185 174
175
186/** 176/**
187 * Method called whenever a given peer connects. Wrapper to call both client's and server's functions 177 * Method called whenever a given peer connects. Wrapper to call both client's and server's functions
188 * 178 *
@@ -260,14 +250,22 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
260} 250}
261 251
262/** 252/**
263 * List of handlers for the messages understood by this 253 * List of handlers if we are learning.
264 * service.
265 */ 254 */
266static struct GNUNET_CORE_MessageHandler handlers[] = { 255static struct GNUNET_CORE_MessageHandler learn_handlers[] = {
267 { &advertisement_handler, GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT, 0}, 256 { &advertisement_handler, GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT, 0},
257 { NULL, 0, 0 }
258};
259
260
261/**
262 * List of handlers if we are not learning.
263 */
264static struct GNUNET_CORE_MessageHandler no_learn_handlers[] = {
268 { NULL, 0, 0 } 265 { NULL, 0, 0 }
269}; 266};
270 267
268
271/** 269/**
272 * Main function that will be run. 270 * Main function that will be run.
273 * 271 *
@@ -295,13 +293,13 @@ run (void *cls,
295 stats = GNUNET_STATISTICS_create (sched, "hostlist", cfg); 293 stats = GNUNET_STATISTICS_create (sched, "hostlist", cfg);
296 294
297 core = GNUNET_CORE_connect (sched, cfg, 295 core = GNUNET_CORE_connect (sched, cfg,
298 GNUNET_TIME_UNIT_FOREVER_REL, 296 GNUNET_TIME_UNIT_FOREVER_REL,
299 NULL, 297 NULL,
300 &core_init, 298 &core_init,
301 NULL, &connect_handler, &disconnect_handler, 299 NULL, &connect_handler, &disconnect_handler,
302 NULL, GNUNET_NO, 300 NULL, GNUNET_NO,
303 NULL, GNUNET_NO, 301 NULL, GNUNET_NO,
304 handlers); 302 learning? learn_handlers : no_learn_handlers);
305 303
306 if (bootstrapping) 304 if (bootstrapping)
307 { 305 {
@@ -312,10 +310,6 @@ run (void *cls,
312 { 310 {
313 GNUNET_HOSTLIST_server_start (cfg, sched, stats, core, &server_ch, &server_dh, advertising ); 311 GNUNET_HOSTLIST_server_start (cfg, sched, stats, core, &server_ch, &server_dh, advertising );
314 } 312 }
315 if (learning)
316 {
317
318 }
319 313
320 GNUNET_SCHEDULER_add_delayed (sched, 314 GNUNET_SCHEDULER_add_delayed (sched,
321 GNUNET_TIME_UNIT_FOREVER_REL, 315 GNUNET_TIME_UNIT_FOREVER_REL,
diff --git a/src/hostlist/gnunet-daemon-hostlist.h b/src/hostlist/gnunet-daemon-hostlist.h
index 7c30344b2..0b185ab7e 100644
--- a/src/hostlist/gnunet-daemon-hostlist.h
+++ b/src/hostlist/gnunet-daemon-hostlist.h
@@ -41,30 +41,5 @@
41 */ 41 */
42#define DEBUG_HOSTLIST GNUNET_NO 42#define DEBUG_HOSTLIST GNUNET_NO
43 43
44/**
45 * A HOSTLIST_ADV message is used to exchange information about
46 * hostlist advertisements. This struct is always
47 * followed by the actual url under which the hostlist can be obtained:
48 *
49 * 1) transport-name (0-terminated)
50 * 2) address-length (uint32_t, network byte order; possibly
51 * unaligned!)
52 * 3) address expiration (GNUNET_TIME_AbsoluteNBO); possibly
53 * unaligned!)
54 * 4) address (address-length bytes; possibly unaligned!)
55 */
56struct GNUNET_HOSTLIST_ADV_Message
57{
58 /**
59 * Type will be GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT.
60 */
61 struct GNUNET_MessageHeader header;
62
63 /**
64 * Always zero (for alignment).
65 */
66 uint32_t reserved GNUNET_PACKED;
67};
68
69 44
70/* end of gnunet-daemon-hostlist.h */ 45/* end of gnunet-daemon-hostlist.h */
diff --git a/src/hostlist/hostlist-client.c b/src/hostlist/hostlist-client.c
index ccc00a2ab..d882cdfbd 100644
--- a/src/hostlist/hostlist-client.c
+++ b/src/hostlist/hostlist-client.c
@@ -21,7 +21,8 @@
21/** 21/**
22 * @file hostlist/hostlist-client.c 22 * @file hostlist/hostlist-client.c
23 * @brief hostlist support. Downloads HELLOs via HTTP. 23 * @brief hostlist support. Downloads HELLOs via HTTP.
24 * @author Christian Grothoff, Matthias Wachs 24 * @author Christian Grothoff
25 * @author Matthias Wachs
25 */ 26 */
26 27
27#include "platform.h" 28#include "platform.h"
@@ -37,6 +38,8 @@
37 38
38#define DEBUG_HOSTLIST_CLIENT GNUNET_YES 39#define DEBUG_HOSTLIST_CLIENT GNUNET_YES
39 40
41#define MAX_URL_LEN 1000
42
40/** 43/**
41 * Number of connections that we must have to NOT download 44 * Number of connections that we must have to NOT download
42 * hostlists anymore. 45 * hostlists anymore.
@@ -44,6 +47,58 @@
44#define MIN_CONNECTIONS 4 47#define MIN_CONNECTIONS 4
45 48
46/** 49/**
50 * A single hostlist obtained by hostlist advertisements
51 */
52struct GNUNET_Hostlist
53{
54 struct GNUNET_Hostlist * prev;
55
56 struct GNUNET_Hostlist * next;
57
58 /**
59 * URI where hostlist can be obtained
60 */
61 const char *hostlist_uri;
62
63 /**
64 * Peer offering the hostlist. TO BE REMOVED.
65 */
66 struct GNUNET_PeerIdentity peer;
67
68 /**
69 * Value describing the quality of the hostlist, the bigger the better but (should) never < 0
70 * used for deciding which hostlist is replaced if MAX_NUMBER_HOSTLISTS in data structure is reached
71 * intial value = HOSTLIST_INITIAL
72 * increased every successful download by HOSTLIST_SUCCESSFULL_DOWNLOAD
73 * increased every successful download by number of obtained HELLO messages
74 * decreased every failed download by HOSTLIST_SUCCESSFULL_DOWNLOAD
75 */
76 uint64_t quality;
77
78 /**
79 * Time the hostlist advertisement was recieved and the entry was created
80 */
81 struct GNUNET_TIME_Absolute time_creation;
82
83 /**
84 * Last time the hostlist was obtained
85 */
86 struct GNUNET_TIME_Absolute time_last_usage;
87
88 /**
89 * Number of HELLO messages obtained during last download
90 */
91 uint32_t hello_count;
92
93 /**
94 * Number of times the hostlist was obtained
95 */
96 uint32_t times_used;
97
98};
99
100
101/**
47 * Our configuration. 102 * Our configuration.
48 */ 103 */
49static const struct GNUNET_CONFIGURATION_Handle *cfg; 104static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -114,19 +169,18 @@ static int bogus_url;
114static unsigned int connection_count; 169static unsigned int connection_count;
115 170
116/** 171/**
117 * Set if the user allows us to learn about new hostlists
118 * from the network.
119 */
120static int learning;
121
122/**
123 * At what time MUST the current hostlist request be done? 172 * At what time MUST the current hostlist request be done?
124 */ 173 */
125static struct GNUNET_TIME_Absolute end_time; 174static struct GNUNET_TIME_Absolute end_time;
126 175
127struct GNUNET_Hostlist * dll_head; 176/* DLL_? */
128struct GNUNET_Hostlist * dll_tail; 177static struct GNUNET_Hostlist * dll_head;
129int dll_size; 178
179/* DLL_? */
180static struct GNUNET_Hostlist * dll_tail;
181
182/* DLL_? */
183static unsigned int dll_size;
130 184
131/** 185/**
132 * Process downloaded bits by calling callback on each HELLO. 186 * Process downloaded bits by calling callback on each HELLO.
@@ -352,7 +406,7 @@ clean_up ()
352 * receiving task with the scheduler. 406 * receiving task with the scheduler.
353 */ 407 */
354static void 408static void
355run_multi (); 409run_multi (void);
356 410
357 411
358/** 412/**
@@ -723,88 +777,54 @@ disconnect_handler (void *cls,
723 GNUNET_NO); 777 GNUNET_NO);
724} 778}
725 779
726static int dll_contains ( char * uri)
727{
728 struct GNUNET_Hostlist * actual = dll_head;
729
730 if (dll_size == 0)
731 return GNUNET_NO;
732 actual = dll_head;
733 780
734 while ( GNUNET_YES ) 781/* DLL_? */
735 { 782static int
736 if ( 0 == strcmp(actual->hostlist_uri,uri) ) return GNUNET_YES; 783dll_contains (const char * uri)
737 if (actual == dll_tail) break; 784{
738 actual = actual->next; 785 struct GNUNET_Hostlist * pos;
739 }
740 786
787 pos = dll_head;
788 while (pos != NULL)
789 {
790 if (0 == strcmp(pos->hostlist_uri, uri) )
791 return GNUNET_YES;
792 pos = pos->next;
793 }
741 return GNUNET_NO; 794 return GNUNET_NO;
742} 795}
743 796
744struct GNUNET_Hostlist * dll_get ( char * uri )
745{
746 struct GNUNET_Hostlist * actual = dll_head;
747
748 if (dll_size == 0)
749 return NULL;
750 actual = dll_head;
751
752 while ( GNUNET_YES)
753 {
754 if ( 0 == strcmp(actual->hostlist_uri,uri) ) return actual;
755 if (actual == dll_tail) break;
756 actual = actual->next;
757 }
758
759 return NULL;
760}
761 797
762struct GNUNET_Hostlist * dll_get_lowest_quality ( ) 798/* DLL_? */
799static struct GNUNET_Hostlist *
800dll_get_lowest_quality ( )
763{ 801{
764 struct GNUNET_Hostlist * actual = dll_head; 802 struct GNUNET_Hostlist * pos;
765 struct GNUNET_Hostlist * lowest = NULL; 803 struct GNUNET_Hostlist * lowest;
766 804
767 if (dll_size == 0) 805 if (dll_size == 0)
768 return lowest; 806 return NULL;
769 807 lowest = dll_head;
770 lowest = dll_tail; 808 pos = dll_head->next;
771 actual = dll_head; 809 while (pos != NULL)
772 810 {
773 while ( GNUNET_YES) 811 if (pos->quality < lowest->quality)
774 { 812 lowest = pos;
775 if ( actual->quality < lowest->quality) lowest = actual; 813 pos = pos->next;
776 if (actual == dll_tail) break; 814 }
777 actual = actual->next;
778 }
779
780 return lowest; 815 return lowest;
781} 816}
782 817
783static int dll_insert ( struct GNUNET_Hostlist * elem)
784{
785 if (dll_size <= MAX_NUMBER_HOSTLISTS)
786 {
787 GNUNET_CONTAINER_DLL_insert(dll_head, dll_tail,elem);
788 dll_size++;
789 return GNUNET_OK;
790 }
791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
792 "Maximum number of %u for hostlist entries reached, \n", MAX_NUMBER_HOSTLISTS );
793 return GNUNET_SYSERR;
794}
795 818
796static int dll_remove ( struct GNUNET_Hostlist * elem) 819#if DUMMY
820/* TO BE REMOVED later */
821static void dll_insert ( struct GNUNET_Hostlist *hostlist)
797{ 822{
798 if ( GNUNET_YES == dll_contains (elem->hostlist_uri)) 823 GNUNET_CONTAINER_DLL_insert(dll_head, dll_tail, hostlist);
799 { 824 dll_size++;
800 GNUNET_CONTAINER_DLL_remove(dll_head, dll_tail,elem);
801 dll_size--;
802 return GNUNET_OK;
803 }
804 return GNUNET_SYSERR;
805} 825}
806 826
807void create_dummy_entries () 827static void create_dummy_entries ()
808{ 828{
809 829
810 /* test */ 830 /* test */
@@ -869,6 +889,7 @@ void create_dummy_entries ()
869 "Adding test peer '%s' with URI %s and quality %u to dll \n", GNUNET_h2s (&hostlist4->peer.hashPubKey) , hostlist4->hostlist_uri, hostlist4->quality); 889 "Adding test peer '%s' with URI %s and quality %u to dll \n", GNUNET_h2s (&hostlist4->peer.hashPubKey) , hostlist4->hostlist_uri, hostlist4->quality);
870 dll_insert (hostlist4); 890 dll_insert (hostlist4);
871} 891}
892#endif
872 893
873/** 894/**
874 * Method called whenever an advertisement message arrives. 895 * Method called whenever an advertisement message arrives.
@@ -886,81 +907,64 @@ advertisement_handler (void *cls,
886 struct GNUNET_TIME_Relative latency, 907 struct GNUNET_TIME_Relative latency,
887 uint32_t distance) 908 uint32_t distance)
888{ 909{
889 if ( !learning ) 910 size_t size;
890 return GNUNET_NO; 911 size_t uri_size;
891 912 const struct GNUNET_MessageHeader * incoming;
892 int size = ntohs (message->size); 913 const char *uri;
893 int uri_size = size - sizeof ( struct GNUNET_HOSTLIST_ADV_Message );
894 char * uri = GNUNET_malloc ( uri_size );
895 struct GNUNET_Hostlist * hostlist; 914 struct GNUNET_Hostlist * hostlist;
896 915
897 if ( ntohs (message->type) != GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT) 916 GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
898 return GNUNET_NO; 917 size = ntohs (message->size);
899 918 if (size <= sizeof(struct GNUNET_MessageHeader))
900 const struct GNUNET_HOSTLIST_ADV_Message * incoming = (const struct GNUNET_HOSTLIST_ADV_Message *) message;
901 memcpy ( uri, &incoming[1], uri_size );
902 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
903 "Hostlist client recieved advertisement from '%s' containing URI %s\n", GNUNET_i2s (peer), uri );
904
905 create_dummy_entries();
906
907 hostlist = GNUNET_malloc ( sizeof (struct GNUNET_Hostlist) );
908
909 hostlist->peer = (*peer);
910 hostlist->hello_count = 0;
911 hostlist->hostlist_uri = GNUNET_malloc ( uri_size);
912 memcpy ( hostlist->hostlist_uri, &incoming[1], uri_size );
913 hostlist->time_creation = GNUNET_TIME_absolute_get();
914 hostlist->time_last_usage = GNUNET_TIME_absolute_get_zero();
915 hostlist->times_used = 0;
916 hostlist->quality = HOSTLIST_INITIAL;
917
918 if ( GNUNET_YES != dll_contains (hostlist->hostlist_uri) )
919 { 919 {
920 if ( MAX_NUMBER_HOSTLISTS > dll_size ) 920 GNUNET_break_op (0);
921 { 921 return GNUNET_SYSERR;
922 /* Entries available, add hostlist to dll */
923 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
924 "Adding uri '%s' to dll\n", hostlist->hostlist_uri );
925 dll_insert ( hostlist );
926 return GNUNET_YES;
927 }
928 else
929 {
930 /* No free entries available, replace existing entry */
931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
932 "No free slots for hostlist available, searching for hostlist to replace\n" );
933
934 struct GNUNET_Hostlist * lowest_quality = dll_get_lowest_quality();
935
936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
937 "Hostlist with URI %s has the worst quality of all with value %u \n", lowest_quality->hostlist_uri, lowest_quality->quality );
938 /* replacing the entry with worst quality, if quality is below initial quality value */
939 if ( lowest_quality->quality < HOSTLIST_INITIAL)
940 {
941 dll_remove(lowest_quality);
942 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
943 "URI '%s' removed \n",lowest_quality->hostlist_uri);
944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
945 "URI '%s' added %s\n", hostlist->hostlist_uri);
946 dll_insert ( hostlist );
947 }
948 return GNUNET_YES;
949 }
950 } 922 }
951 else 923 incoming = (const struct GNUNET_MessageHeader *) message;
924 uri = (const char*) &incoming[1];
925 uri_size = size - sizeof (struct GNUNET_MessageHeader);
926 if (uri [uri_size - 1] != '\0')
952 { 927 {
953 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 928 GNUNET_break_op (0);
954 "Hostlist URI already in database\n"); 929 return GNUNET_SYSERR;
955 } 930 }
931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
932 "Hostlist client recieved advertisement from `%s' containing URI `%s'\n",
933 GNUNET_i2s (peer),
934 uri);
935 if (GNUNET_YES != dll_contains (uri))
936 return GNUNET_OK;
937 hostlist = GNUNET_malloc (sizeof (struct GNUNET_Hostlist) + uri_size);
938 hostlist->peer = *peer;
939 hostlist->hostlist_uri = (const char*) &hostlist[1];
940 memcpy (&hostlist[1], uri, uri_size);
941 hostlist->time_creation = GNUNET_TIME_absolute_get();
942 hostlist->time_last_usage = GNUNET_TIME_absolute_get_zero();
943 hostlist->quality = HOSTLIST_INITIAL;
944#if DUMMY
945 create_dummy_entries(); /* FIXME: remove later... */
946#endif
947 GNUNET_CONTAINER_DLL_insert(dll_head, dll_tail, hostlist);
948 dll_size++;
949
950 if (MAX_NUMBER_HOSTLISTS >= dll_size)
951 return GNUNET_OK;
956 952
957 /* since hostlist already existed in hashmap, object can be destroyed */ 953 /* No free entries available, replace existing entry */
958 GNUNET_free ( hostlist->hostlist_uri ); 954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
959 GNUNET_free ( hostlist ); 955 "Removing lowest quality entry\n" );
960 956 struct GNUNET_Hostlist * lowest_quality = dll_get_lowest_quality();
961 return GNUNET_YES; 957 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
958 "Hostlist with URI `%s' has the worst quality of all with value %llu\n",
959 lowest_quality->hostlist_uri,
960 (unsigned long long) lowest_quality->quality);
961 GNUNET_CONTAINER_DLL_remove (dll_head, dll_tail, lowest_quality);
962 dll_size--;
963 GNUNET_free (lowest_quality);
964 return GNUNET_OK;
962} 965}
963 966
967
964/** 968/**
965 * Continuation called by the statistics code once 969 * Continuation called by the statistics code once
966 * we go the stat. Initiates hostlist download scheduling. 970 * we go the stat. Initiates hostlist download scheduling.
@@ -998,11 +1002,13 @@ process_stat (void *cls,
998 1002
999/** 1003/**
1000 * Method to load persistent hostlist file during hostlist client startup 1004 * Method to load persistent hostlist file during hostlist client startup
1001 * param c configuration to use
1002 */ 1005 */
1003static int load_hostlist_file () 1006static void
1007load_hostlist_file ()
1004{ 1008{
1005 char *filename; 1009 char *filename;
1010 char *uri;
1011 char *emsg;
1006 1012
1007 if (GNUNET_OK != 1013 if (GNUNET_OK !=
1008 GNUNET_CONFIGURATION_get_value_string (cfg, 1014 GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -1013,46 +1019,57 @@ static int load_hostlist_file ()
1013 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1019 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1014 _("No `%s' specified in `%s' configuration, cannot load hostlists from file.\n"), 1020 _("No `%s' specified in `%s' configuration, cannot load hostlists from file.\n"),
1015 "HOSTLISTFILE", "HOSTLIST"); 1021 "HOSTLISTFILE", "HOSTLIST");
1016 return GNUNET_SYSERR; 1022 return;
1017 } 1023 }
1018 1024
1019 struct GNUNET_BIO_ReadHandle * rh = GNUNET_BIO_read_open (filename); 1025 struct GNUNET_BIO_ReadHandle * rh = GNUNET_BIO_read_open (filename);
1020 if ( NULL == rh) 1026 if (NULL == rh)
1021 { 1027 {
1022 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1028 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1023 ("Could not open file %s for reading to load hostlists\n"), filename); 1029 _("Could not open file `%s' for reading to load hostlists: %s\n"),
1024 return GNUNET_SYSERR; 1030 filename,
1031 STRERROR (errno));
1032 GNUNET_free (filename);
1033 return;
1025 } 1034 }
1026 1035
1027 /* add code to read hostlists to file using bio */ 1036 /* add code to read hostlists to file using bio */
1028 char *buffer = GNUNET_malloc (1000 * sizeof (char)); 1037 uri = NULL;
1029 /* char *token; 1038 while ( (GNUNET_OK == GNUNET_BIO_read_string (rh, "url" , &uri, MAX_URL_LEN)) &&
1030 1039#if 0
1031 while (GNUNET_OK == GNUNET_BIO_read_string (rh, NULL , &buffer, 1000) ) 1040 (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &times_used)) &&
1032 { 1041 (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &hellos_returned)) &&
1033 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1042 (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used.value)) &&
1034 ("Read from file %s : %s \n"), filename, buffer); 1043 (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &created.value)) &&
1035 1044 (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality))
1036 pch = strtok (str," ,.-"); 1045#else
1037 while (pch != NULL) 1046 (1)
1047#endif
1048)
1038 { 1049 {
1039 printf ("%s\n",pch); 1050#if 0
1040 pch = strtok (NULL, " ,.-"); 1051 hostlist = GNUNET_malloc (...);
1041 } 1052#endif
1042 1053 uri = NULL;
1043 } 1054 }
1044 */ 1055 GNUNET_free_non_null (uri);
1045 GNUNET_BIO_read_close ( rh , &buffer); 1056 emsg = NULL;
1046 return GNUNET_OK; 1057 GNUNET_BIO_read_close (rh, &emsg);
1058 if (emsg != NULL)
1059 GNUNET_free (emsg);
1060 GNUNET_free (filename);
1047} 1061}
1048 1062
1063
1049/** 1064/**
1050 * Method to load persistent hostlist file during hostlist client shutdown 1065 * Method to load persistent hostlist file during hostlist client shutdown
1051 * param c configuration to use
1052 */ 1066 */
1053static int save_hostlist_file () 1067static void save_hostlist_file ()
1054{ 1068{
1055 char *filename; 1069 char *filename;
1070 struct GNUNET_Hostlist *pos;
1071 struct GNUNET_BIO_WriteHandle * wh;
1072 int ok;
1056 1073
1057 if (GNUNET_OK != 1074 if (GNUNET_OK !=
1058 GNUNET_CONFIGURATION_get_value_string (cfg, 1075 GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -1063,71 +1080,48 @@ static int save_hostlist_file ()
1063 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1080 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1064 _("No `%s' specified in `%s' configuration, cannot save hostlists to file.\n"), 1081 _("No `%s' specified in `%s' configuration, cannot save hostlists to file.\n"),
1065 "HOSTLISTFILE", "HOSTLIST"); 1082 "HOSTLISTFILE", "HOSTLIST");
1066 return GNUNET_SYSERR; 1083 return;
1067 } 1084 }
1068 1085 wh = GNUNET_BIO_write_open (filename);
1069 struct GNUNET_BIO_WriteHandle * wh = GNUNET_BIO_write_open (filename);
1070 if ( NULL == wh) 1086 if ( NULL == wh)
1071 { 1087 {
1072 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1088 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1073 ("Could not open file %s for writing to save hostlists\n"), 1089 _("Could not open file `%s' for writing to save hostlists: %s\n"),
1074 filename); 1090 filename,
1075 return GNUNET_SYSERR; 1091 STRERROR (errno));
1092 return;
1076 } 1093 }
1094 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1095 _("Writing hostlist URIs to `%s'\n"),
1096 filename);
1077 1097
1078 /* add code to write hostlists to file using bio */ 1098 /* add code to write hostlists to file using bio */
1079 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1099 ok = GNUNET_YES;
1080 "Writing hostlist to disk\n"); 1100 while (NULL != (pos = dll_head))
1081 struct GNUNET_Hostlist * actual = dll_head; 1101 {
1082 struct GNUNET_Hostlist * next; 1102 GNUNET_CONTAINER_DLL_remove (dll_head, dll_tail, pos);
1083 char * content = GNUNET_malloc(1000 * sizeof (char)); 1103 dll_size--;
1084 char * buffer = GNUNET_malloc(1000 * sizeof (char)); 1104 if (GNUNET_YES == ok)
1085 1105 {
1086 actual = dll_head; 1106 if ( (GNUNET_OK !=
1087 while ( GNUNET_YES) 1107 GNUNET_BIO_write_string (wh, pos->hostlist_uri)) ||
1088 { 1108 (GNUNET_OK !=
1089 /* serialize content */ 1109 GNUNET_BIO_write_int32 (wh, pos->times_used)) ||
1090 /* uri;hello_count;quality; */ 1110 (0) )
1091 strcpy(content,actual->hostlist_uri); 1111 {
1092 strcat(content,";"); 1112 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1093 sprintf(buffer, "%lu", actual->hello_count); 1113 _("Error writing hostlist URIs to file `%s'\n"),
1094 strcat(content,buffer); 1114 filename);
1095 strcat(content,";"); 1115 ok = GNUNET_NO;
1096 sprintf(buffer, "%llu", (long long unsigned int) actual->quality); 1116 }
1097 strcat(content,buffer); 1117 }
1098 strcat(content,";"); 1118 GNUNET_free (pos);
1099 sprintf(buffer, "%llu", (long long unsigned int) actual->time_creation.value); 1119 }
1100 strcat(content,buffer);
1101 strcat(content,";");
1102 sprintf(buffer, "%llu", (long long unsigned int) actual->time_last_usage.value);
1103 strcat(content,buffer);
1104 strcat(content,";");
1105 sprintf(buffer, "%lu", actual->times_used);
1106 strcat(content,buffer);
1107 strcat(content,";");
1108
1109 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1110 ("Content to write: %s\n"),
1111 content);
1112
1113 GNUNET_BIO_write_string ( wh, content );
1114
1115
1116 if (actual == dll_tail) break;
1117 next = actual->next;
1118 GNUNET_free (actual->hostlist_uri);
1119 GNUNET_free (actual);
1120 actual = next;
1121 }
1122 GNUNET_free (actual->hostlist_uri);
1123 GNUNET_free (actual);
1124 GNUNET_free (content);
1125
1126 if ( GNUNET_OK != GNUNET_BIO_write_close ( wh ) ) 1120 if ( GNUNET_OK != GNUNET_BIO_write_close ( wh ) )
1127 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1121 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1128 ("Error while closing file %s\n"), 1122 _("Error writing hostlist URIs to file `%s'\n"),
1129 filename); 1123 filename);
1130 return GNUNET_OK; 1124 GNUNET_free (filename);
1131} 1125}
1132 1126
1133/** 1127/**
@@ -1164,9 +1158,10 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
1164 proxy = NULL; 1158 proxy = NULL;
1165 *ch = &connect_handler; 1159 *ch = &connect_handler;
1166 *dh = &disconnect_handler; 1160 *dh = &disconnect_handler;
1167 *msgh = &advertisement_handler; 1161 if (learn)
1168 1162 *msgh = &advertisement_handler;
1169 learning = learn; 1163 else
1164 *msgh = NULL;
1170 dll_head = NULL; 1165 dll_head = NULL;
1171 dll_tail = NULL; 1166 dll_tail = NULL;
1172 load_hostlist_file (); 1167 load_hostlist_file ();
diff --git a/src/hostlist/hostlist-client.h b/src/hostlist/hostlist-client.h
index 37fc55c19..1393df8f1 100644
--- a/src/hostlist/hostlist-client.h
+++ b/src/hostlist/hostlist-client.h
@@ -42,48 +42,6 @@
42#define HOSTLIST_FAILED_DOWNLOAD 100 42#define HOSTLIST_FAILED_DOWNLOAD 100
43#define HOSTLIST_SUCCESSFUL_DOWNLOAD 100 43#define HOSTLIST_SUCCESSFUL_DOWNLOAD 100
44 44
45/*
46 * a single hostlist obtained by hostlist advertisements
47 */
48struct GNUNET_Hostlist
49{
50 struct GNUNET_Hostlist * prev;
51 struct GNUNET_Hostlist * next;
52 /*
53 * peer offering the hostlist
54 */
55 struct GNUNET_PeerIdentity peer;
56 /*
57 * URI where hostlist can be obtained
58 */
59 char * hostlist_uri;
60 /*
61 * number of HELLO messages obtained during last download
62 */
63 unsigned long hello_count;
64 /*
65 * number of times the hostlist was obtained
66 */
67 unsigned long times_used;
68 /*
69 * time the hostlist advertisement was recieved and the entry was created
70 */
71 struct GNUNET_TIME_Absolute time_creation;
72 /*
73 * last time the hostlist was obtained
74 */
75 struct GNUNET_TIME_Absolute time_last_usage;
76 /*
77 * value describing the quality of the hostlist, the bigger the better but (should) never < 0
78 * used for deciding which hostlist is replaced if MAX_NUMBER_HOSTLISTS in data structure is reached
79 * intial value = HOSTLIST_INITIAL
80 * increased every successful download by HOSTLIST_SUCCESSFULL_DOWNLOAD
81 * increased every successful download by number of obtained HELLO messages
82 * decreased every failed download by HOSTLIST_SUCCESSFULL_DOWNLOAD
83 */
84 uint64_t quality;
85};
86
87 45
88/** 46/**
89 * Start downloading hostlists from hostlist servers as necessary. 47 * Start downloading hostlists from hostlist servers as necessary.
diff --git a/src/hostlist/hostlist-server.c b/src/hostlist/hostlist-server.c
index c04e99c42..e9a72d42b 100644
--- a/src/hostlist/hostlist-server.c
+++ b/src/hostlist/hostlist-server.c
@@ -109,15 +109,18 @@ struct HostSet
109 */ 109 */
110static int advertising; 110static int advertising;
111 111
112/* 112/**
113 * How many times was the hostlist advertised? 113 * How many times was the hostlist advertised?
114 */ 114 */
115static uint64_t hostlist_adv_count = 0; 115static uint64_t hostlist_adv_count;
116 116
117/* 117/* FIXME: define once... */
118#define MAX_URL_LEN 1000
119
120/**
118 * Buffer for the hostlist address 121 * Buffer for the hostlist address
119 */ 122 */
120char hostlist_uri[255]; 123static char * hostlist_uri;
121 124
122 125
123/** 126/**
@@ -373,6 +376,7 @@ access_handler_callback (void *cls,
373 return MHD_queue_response (connection, MHD_HTTP_OK, response); 376 return MHD_queue_response (connection, MHD_HTTP_OK, response);
374} 377}
375 378
379
376/** 380/**
377 * Handler called by core when core is ready to transmit message 381 * Handler called by core when core is ready to transmit message
378 * @param cls closure 382 * @param cls closure
@@ -384,139 +388,35 @@ adv_transmit_ready ( void *cls, size_t size, void *buf)
384{ 388{
385 size_t transmission_size; 389 size_t transmission_size;
386 size_t uri_size; /* Including \0 termination! */ 390 size_t uri_size; /* Including \0 termination! */
387 uri_size = strlen ( hostlist_uri ) + 1; 391 struct GNUNET_MessageHeader header;
388 392 char *cbuf;
389 struct GNUNET_HOSTLIST_ADV_Message * adv_message;
390 adv_message = GNUNET_malloc ( sizeof(struct GNUNET_HOSTLIST_ADV_Message) + uri_size);
391 if ( NULL == adv_message)
392 {
393 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
394 "Could not allocate memory for the message");
395 return GNUNET_NO;
396 }
397 transmission_size = sizeof (struct GNUNET_HOSTLIST_ADV_Message) + uri_size;
398
399 adv_message->header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
400 adv_message->header.size = htons (transmission_size);
401 memcpy(&adv_message[1],hostlist_uri,uri_size);
402 393
403 if (buf == NULL) 394 if (buf == NULL)
404 { 395 {
405 GNUNET_log ( GNUNET_ERROR_TYPE_DEBUG, "Transmission failed, buffer invalid!\n" ); 396 GNUNET_log ( GNUNET_ERROR_TYPE_DEBUG,
397 "Transmission failed, buffer invalid!\n" );
406 return 0; 398 return 0;
407 } 399 }
408 400 uri_size = strlen ( hostlist_uri ) + 1;
409 if ( size >= transmission_size ) 401 transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size;
410 { 402 header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
411 memcpy ( buf, adv_message, transmission_size ); 403 header.size = htons (transmission_size);
412 GNUNET_log ( GNUNET_ERROR_TYPE_DEBUG, "Sent advertisement message: Copied %d bytes into buffer!\n", transmission_size); 404 GNUNET_assert (size >= transmission_size);
413 GNUNET_free ( adv_message ); 405 memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader));
414 return transmission_size; 406 cbuf = buf;
415 } 407 memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)],
416 408 hostlist_uri, uri_size);
409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
410 "Sent advertisement message: Copied %u bytes into buffer!\n",
411 (unsigned int) transmission_size);
417 hostlist_adv_count++; 412 hostlist_adv_count++;
418 GNUNET_STATISTICS_set (stats, 413 GNUNET_STATISTICS_set (stats,
419 gettext_noop("# hostlist advertisements send"), 414 gettext_noop("# hostlist advertisements send"),
420 hostlist_adv_count, 415 hostlist_adv_count,
421 GNUNET_YES); 416 GNUNET_YES);
422 417 return transmission_size;
423 GNUNET_free (adv_message );
424 return size;
425} 418}
426 419
427/**
428 * Method that asks core service to transmit the message to the peer
429 * @param peer peer to transmit message to
430 * @param size size of the message
431 */
432static size_t
433adv_transmit_message ( const struct GNUNET_PeerIdentity * peer, size_t size )
434{
435 /* transmit message to peer */
436 if ( NULL == core)
437 {
438 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
439 _("Not connected to core, unable to send advertisement message\n"));
440 return GNUNET_NO;
441 }
442
443 struct GNUNET_TIME_Relative timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, GNUNET_ADV_TIMEOUT);
444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
445 _("Asked core to transmit advertisement message with a size of %u bytes\n"), size);
446 struct GNUNET_CORE_TransmitHandle * th;
447 th = GNUNET_CORE_notify_transmit_ready (core,
448 0,
449 timeout,
450 peer,
451 size,
452 &adv_transmit_ready, NULL);
453 if ( NULL == th )
454 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
455 _("Advertisement message could not be queued by core\n"));
456 return GNUNET_NO;
457
458 return GNUNET_YES;
459}
460
461/**
462 * Method that assembles our hostlist advertisement message
463 * @param peer peer to send the hostlist advertisement
464 */
465static size_t
466adv_create_message ( const struct GNUNET_PeerIdentity * peer )
467
468{
469 size_t length = 0;
470 size_t size = 0;
471 unsigned long long port;
472
473 char *uri;
474 char hostname[GNUNET_OS_get_hostname_max_length() + 1];
475 char *protocol = "http://";
476 char *port_s = GNUNET_malloc(6 * sizeof(char));
477
478 if (0 != gethostname (hostname, sizeof (hostname) - 1))
479 {
480 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
481 "Could not get system's hostname, unable to create advertisement message");
482 return GNUNET_NO;
483 }
484 if (-1 == GNUNET_CONFIGURATION_get_value_number (cfg,
485 "HOSTLIST",
486 "HTTPPORT",
487 &port))
488 return GNUNET_SYSERR;
489
490 sprintf(port_s, "%llu", port);
491 length = strlen(hostname)+strlen(protocol)+strlen(port_s)+2;
492 size = (length+1) * sizeof (char);
493 uri = GNUNET_malloc(size);
494 uri = strcpy(uri, protocol);
495 uri = strcat(uri, hostname);
496 uri = strcat(uri, ":");
497 uri = strcat(uri, port_s);
498 uri = strcat(uri, "/");
499 if ( length < 255);
500 strcpy(hostlist_uri,uri);
501
502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Address to obtain hostlist: %s\n", hostlist_uri);
503
504 if ( ( size + sizeof( struct GNUNET_HOSTLIST_ADV_Message )) > GNUNET_SERVER_MAX_MESSAGE_SIZE)
505 {
506 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
507 "Advertisement message is bigger than GNUNET allows");
508 return GNUNET_NO;
509 }
510
511 /* Request core to transmit message to peer */
512 size = size + sizeof ( struct GNUNET_HOSTLIST_ADV_Message );
513 adv_transmit_message(peer, size);
514
515 GNUNET_free ( port_s );
516 GNUNET_free ( uri );
517
518 return GNUNET_OK;
519}
520 420
521/** 421/**
522 * Method called whenever a given peer connects. 422 * Method called whenever a given peer connects.
@@ -533,18 +433,37 @@ connect_handler (void *cls,
533 struct GNUNET_TIME_Relative latency, 433 struct GNUNET_TIME_Relative latency,
534 uint32_t distance) 434 uint32_t distance)
535{ 435{
436 size_t size;
437
536 if ( !advertising ) 438 if ( !advertising )
537 return; 439 return;
538 440 if (hostlist_uri == NULL)
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "A new peer connected to the server, preparing to send hostlist advertisement\n");
541 /* create a new advertisement message */
542 if ( (GNUNET_OK != adv_create_message(peer)))
543 {
544 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
545 _(" GNUNET_OK Could not create a hostlist advertisement message, impossible to advertise hostlist\n"));
546 return; 441 return;
547 } 442 size = strlen (hostlist_uri) + 1;
443 if (size + sizeof (struct GNUNET_MessageHeader) > GNUNET_SERVER_MAX_MESSAGE_SIZE)
444 {
445 GNUNET_break (0);
446 return;
447 }
448 size += sizeof (struct GNUNET_MessageHeader);
449 if (NULL == core)
450 {
451 GNUNET_break (0);
452 return;
453 }
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
455 "Asked core to transmit advertisement message with a size of %u bytes\n",
456 size);
457 if (NULL == GNUNET_CORE_notify_transmit_ready (core,
458 0,
459 GNUNET_ADV_TIMEOUT,
460 peer,
461 size,
462 &adv_transmit_ready, NULL))
463 {
464 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
465 _("Advertisement message could not be queued by core\n"));
466 }
548} 467}
549 468
550 469
@@ -559,7 +478,7 @@ disconnect_handler (void *cls,
559 const struct 478 const struct
560 GNUNET_PeerIdentity * peer) 479 GNUNET_PeerIdentity * peer)
561{ 480{
562 481 /* nothing to do */
563} 482}
564 483
565 484
@@ -570,6 +489,7 @@ disconnect_handler (void *cls,
570static GNUNET_SCHEDULER_TaskIdentifier 489static GNUNET_SCHEDULER_TaskIdentifier
571prepare_daemon (struct MHD_Daemon *daemon_handle); 490prepare_daemon (struct MHD_Daemon *daemon_handle);
572 491
492
573/** 493/**
574 * Call MHD to process pending requests and then go back 494 * Call MHD to process pending requests and then go back
575 * and schedule the next run. 495 * and schedule the next run.
@@ -666,6 +586,8 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
666 int advertise) 586 int advertise)
667{ 587{
668 unsigned long long port; 588 unsigned long long port;
589 char *hostname;
590 size_t size;
669 591
670 advertising = advertise; 592 advertising = advertise;
671 if ( !advertising ) 593 if ( !advertising )
@@ -685,6 +607,26 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
685 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 607 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
686 _("Hostlist service starts on port %llu\n"), 608 _("Hostlist service starts on port %llu\n"),
687 port); 609 port);
610 hostname = GNUNET_RESOLVER_local_hostname_get ();
611 if (NULL != hostname)
612 {
613 size = strlen (hostname);
614 if (size + 15 > MAX_URL_LEN)
615 {
616 GNUNET_break (0);
617 }
618 else
619 {
620 GNUNET_asprintf (&hostlist_uri,
621 "http://%s:%u/",
622 hostname,
623 (unsigned int) port);
624 GNUNET_free (hostname);
625 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
626 _("Address to obtain hostlist: `%s'\n"),
627 hostlist_uri);
628 }
629 }
688 daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 630 daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6
689#if DEBUG_HOSTLIST_SERVER 631#if DEBUG_HOSTLIST_SERVER
690 | MHD_USE_DEBUG 632 | MHD_USE_DEBUG
@@ -725,7 +667,7 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
725 return GNUNET_SYSERR; 667 return GNUNET_SYSERR;
726 } 668 }
727 669
728 core=co; 670 core = co;
729 671
730 *server_ch = &connect_handler; 672 *server_ch = &connect_handler;
731 *server_dh = &disconnect_handler; 673 *server_dh = &disconnect_handler;
diff --git a/src/hostlist/hostlist-server.h b/src/hostlist/hostlist-server.h
index cffcac05f..f704f890d 100644
--- a/src/hostlist/hostlist-server.h
+++ b/src/hostlist/hostlist-server.h
@@ -31,7 +31,7 @@
31#include "gnunet_statistics_service.h" 31#include "gnunet_statistics_service.h"
32#include "gnunet_util_lib.h" 32#include "gnunet_util_lib.h"
33 33
34#define GNUNET_ADV_TIMEOUT 2500 34#define GNUNET_ADV_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
35 35
36/** 36/**
37 * Start server offering our hostlist. 37 * Start server offering our hostlist.