GNUnet  0.11.x
gnunet-daemon-hostlist_client.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2001-2010, 2014, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
26 #include "platform.h"
28 #include "gnunet_hello_lib.h"
32 #include "gnunet-daemon-hostlist.h"
33 /* Just included for the right curl.h */
34 #include "gnunet_curl_lib.h"
35 
36 
41 #define MIN_CONNECTIONS 4
42 
46 #define MAX_NUMBER_HOSTLISTS 30
47 
51 #define SAVING_INTERVAL \
52  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
53 
57 #define TESTING_INTERVAL \
58  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
59 
63 #define WAITING_INTERVAL \
64  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
65 
73 #define HOSTLIST_INITIAL 10000
74 
78 #define HOSTLIST_FAILED_DOWNLOAD 100
79 
83 #define HOSTLIST_SUCCESSFUL_DOWNLOAD 100
84 
88 #define HOSTLIST_SUCCESSFUL_HELLO 1
89 
90 
94 struct Hostlist
95 {
99  struct Hostlist *prev;
100 
104  struct Hostlist *next;
105 
109  const char *hostlist_uri;
110 
119  uint64_t quality;
120 
125 
130 
134  uint32_t hello_count;
135 
139  uint32_t times_used;
140 };
141 
142 
146 static const struct GNUNET_CONFIGURATION_Handle *cfg;
147 
152 
156 static char *proxy;
157 
161 static char *proxy_username;
162 
166 static char *proxy_password;
167 
171 static curl_proxytype proxy_type;
172 
176 static size_t download_pos;
177 
181 static char *current_url;
182 
186 static CURL *curl;
187 
191 static CURLM *multi;
192 
196 static uint32_t stat_bytes_downloaded;
197 
202 
207 
212 
217 
222 
227 
232 
236 static struct Hostlist *linked_list_head;
237 
241 static struct Hostlist *linked_list_tail;
242 
246 static struct Hostlist *current_hostlist;
247 
251 static unsigned int linked_list_size;
252 
256 static struct Hostlist *hostlist_to_test;
257 
262 
266 static int stat_bogus_url;
267 
272 
277 
282 
286 static unsigned int stat_use_bootstrap;
287 
291 static int stat_learning;
292 
296 static unsigned int stat_download_successful;
297 
301 static unsigned int stat_hellos_obtained;
302 
306 static unsigned int stat_connection_count;
307 
311 static struct GNUNET_PEERINFO_Handle *pi;
312 
313 
323 static size_t
324 callback_download (void *ptr, size_t size, size_t nmemb, void *ctx)
325 {
326  static char download_buffer[GNUNET_MAX_MESSAGE_SIZE - 1];
327  const char *cbuf = ptr;
328  const struct GNUNET_MessageHeader *msg;
329  size_t total;
330  size_t cpy;
331  size_t left;
332  uint16_t msize;
333 
334  total = size * nmemb;
335  stat_bytes_downloaded += total;
336  if ((total == 0) || (stat_bogus_url))
337  {
338  return total; /* ok, no data or bogus data */
339  }
340 
342  gettext_noop (
343  "# bytes downloaded from hostlist servers"),
344  (int64_t) total,
345  GNUNET_NO);
346  left = total;
347  while ((left > 0) || (download_pos > 0))
348  {
349  cpy = GNUNET_MIN (left, GNUNET_MAX_MESSAGE_SIZE - 1 - download_pos);
350  GNUNET_memcpy (&download_buffer[download_pos], cbuf, cpy);
351  cbuf += cpy;
352  download_pos += cpy;
353  left -= cpy;
354  if (download_pos < sizeof(struct GNUNET_MessageHeader))
355  {
356  GNUNET_assert (0 == left);
357  break;
358  }
359  msg = (const struct GNUNET_MessageHeader *) download_buffer;
360  msize = ntohs (msg->size);
361  if (msize < sizeof(struct GNUNET_MessageHeader))
362  {
364  stats,
365  gettext_noop ("# invalid HELLOs downloaded from hostlist servers"),
366  1,
367  GNUNET_NO);
369  _ ("Invalid `%s' message received from hostlist at `%s'\n"),
370  "HELLO",
371  current_url);
373  stat_bogus_url = 1;
374  return total;
375  }
376  if (download_pos < msize)
377  {
378  GNUNET_assert (left == 0);
379  break;
380  }
381  if (GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) msg) == msize)
382  {
384  "Received valid `%s' message from hostlist server.\n",
385  "HELLO");
387  stats,
388  gettext_noop ("# valid HELLOs downloaded from hostlist servers"),
389  1,
390  GNUNET_NO);
392  (void)
394  (const struct GNUNET_HELLO_Message *) msg,
395  NULL,
396  NULL);
397  }
398  else
399  {
401  stats,
402  gettext_noop ("# invalid HELLOs downloaded from hostlist servers"),
403  1,
404  GNUNET_NO);
406  _ ("Invalid `%s' message received from hostlist at `%s'\n"),
407  "HELLO",
408  current_url);
411  return total;
412  }
413  memmove (download_buffer, &download_buffer[msize], download_pos - msize);
414  download_pos -= msize;
415  }
416  return total;
417 }
418 
419 
425 static char *
427 {
428  char *servers;
429  char *ret;
430  size_t urls;
431  size_t pos;
432 
434  "HOSTLIST",
435  "SERVERS",
436  &servers))
437  {
439  "hostlist",
440  "SERVERS");
441  return NULL;
442  }
443 
444  urls = 0;
445  if (strlen (servers) > 0)
446  {
447  urls++;
448  pos = strlen (servers) - 1;
449  while (pos > 0)
450  {
451  if (servers[pos] == ' ')
452  urls++;
453  pos--;
454  }
455  }
456  if (urls == 0)
457  {
459  "hostlist",
460  "SERVERS");
461  GNUNET_free (servers);
462  return NULL;
463  }
464 
466  pos = strlen (servers) - 1;
467  while (pos > 0)
468  {
469  if (servers[pos] == ' ')
470  {
471  urls--;
472  servers[pos] = '\0';
473  }
474  if (urls == 0)
475  {
476  pos++;
477  break;
478  }
479  pos--;
480  }
481  ret = GNUNET_strdup (&servers[pos]);
482  GNUNET_free (servers);
483  return ret;
484 }
485 
486 
491 static char *
493 {
494  uint32_t index;
495  unsigned int counter;
496  struct Hostlist *pos;
497 
498  if (GNUNET_NO == stat_learning)
499  {
501  "Using preconfigured bootstrap server\n");
502  current_hostlist = NULL;
503  return get_bootstrap_server ();
504  }
505 
506  if ((GNUNET_YES == stat_testing_hostlist) && (NULL != hostlist_to_test))
507  {
509  "Testing new advertised hostlist if it is obtainable\n");
510  current_hostlist = hostlist_to_test;
511  return GNUNET_strdup (hostlist_to_test->hostlist_uri);
512  }
513 
515  {
517  "Using preconfigured bootstrap server\n");
518  current_hostlist = NULL;
519  return get_bootstrap_server ();
520  }
521  index =
523  counter = 0;
524  pos = linked_list_head;
525  while (counter < index)
526  {
527  pos = pos->next;
528  counter++;
529  }
531  "Using learned hostlist `%s'\n",
532  pos->hostlist_uri);
533  current_hostlist = pos;
534  return GNUNET_strdup (pos->hostlist_uri);
535 }
536 
537 
538 #define CURL_EASY_SETOPT(c, a, b) \
539  do \
540  { \
541  ret = curl_easy_setopt (c, a, b); \
542  if (CURLE_OK != ret) \
543  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
544  _ ("%s failed at %s:%d: `%s'\n"), \
545  "curl_easy_setopt", \
546  __FILE__, \
547  __LINE__, \
548  curl_easy_strerror (ret)); \
549  } while (0)
550 
551 
557 static void
558 save_hostlist_file (int shutdown);
559 
560 
568 static uint64_t
569 checked_add (uint64_t val1, uint64_t val2)
570 {
571  static uint64_t temp;
572  static uint64_t maxv;
573 
574  maxv = 0;
575  maxv--;
576 
577  temp = val1 + val2;
578  if (temp < val1)
579  return maxv;
580  return temp;
581 }
582 
583 
591 static uint64_t
592 checked_sub (uint64_t val1, uint64_t val2)
593 {
594  if (val1 <= val2)
595  return 0;
596  return(val1 - val2);
597 }
598 
599 
606 static int
608 {
609  struct Hostlist *pos;
610 
611  pos = linked_list_head;
612  while (pos != NULL)
613  {
614  if (0 == strcmp (pos->hostlist_uri, uri))
615  return GNUNET_YES;
616  pos = pos->next;
617  }
618  return GNUNET_NO;
619 }
620 
621 
626 static struct Hostlist *
628 {
629  struct Hostlist *pos;
630  struct Hostlist *lowest;
631 
632  if (linked_list_size == 0)
633  return NULL;
634  lowest = linked_list_head;
635  pos = linked_list_head->next;
636  while (pos != NULL)
637  {
638  if (pos->quality < lowest->quality)
639  lowest = pos;
640  pos = pos->next;
641  }
642  return lowest;
643 }
644 
645 
651 static void
653 {
654  struct Hostlist *lowest_quality;
655 
657  {
658  /* No free entries available, replace existing entry */
659  lowest_quality = linked_list_get_lowest_quality ();
660  GNUNET_assert (lowest_quality != NULL);
661  GNUNET_log (
663  "Removing hostlist with URI `%s' which has the worst quality of all (%llu)\n",
664  lowest_quality->hostlist_uri,
665  (unsigned long long) lowest_quality->quality);
666  GNUNET_CONTAINER_DLL_remove (linked_list_head,
667  linked_list_tail,
668  lowest_quality);
670  GNUNET_free (lowest_quality);
671  }
672  GNUNET_CONTAINER_DLL_insert (linked_list_head,
673  linked_list_tail,
674  hostlist_to_test);
676  GNUNET_STATISTICS_set (stats,
677  gettext_noop ("# advertised hostlist URIs"),
679  GNUNET_NO);
681 }
682 
683 
687 static void
689 {
690  char *stat;
691 
692  if (((stat_use_bootstrap == GNUNET_NO) && (NULL != current_hostlist)) ||
693  ((stat_testing_hostlist == GNUNET_YES) && (NULL != current_hostlist)))
694  {
696  "Updating hostlist statics for URI `%s'\n",
697  current_hostlist->hostlist_uri);
698  current_hostlist->hello_count = stat_hellos_obtained;
699  current_hostlist->time_last_usage = GNUNET_TIME_absolute_get ();
700  current_hostlist->quality =
701  checked_add (current_hostlist->quality,
704  {
705  current_hostlist->times_used++;
706  current_hostlist->quality =
707  checked_add (current_hostlist->quality, HOSTLIST_SUCCESSFUL_DOWNLOAD);
708  GNUNET_asprintf (&stat,
709  gettext_noop ("# advertised URI `%s' downloaded"),
710  current_hostlist->hostlist_uri);
711 
712  GNUNET_STATISTICS_update (stats, stat, 1, GNUNET_YES);
713  GNUNET_free (stat);
714  }
715  else
716  current_hostlist->quality =
717  checked_sub (current_hostlist->quality, HOSTLIST_FAILED_DOWNLOAD);
718  }
719  current_hostlist = NULL;
720  /* Alternating the usage of preconfigured and learned hostlists */
721 
723  return;
724 
725  if (GNUNET_YES == stat_learning)
726  {
729  else
731  }
732  else
734 }
735 
736 
741 static void
743 {
744  CURLMcode mret;
745 
747  (GNUNET_NO == stat_download_successful) && (NULL != hostlist_to_test))
748  {
749  GNUNET_log (
751  _ (
752  "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI gets dismissed.\n"),
753  hostlist_to_test->hostlist_uri);
754  }
755 
757  {
759  }
760  if (NULL != hostlist_to_test)
761  {
762  GNUNET_free (hostlist_to_test);
763  hostlist_to_test = NULL;
764  }
765 
766  if (NULL != multi)
767  {
768  mret = curl_multi_remove_handle (multi, curl);
769  if (mret != CURLM_OK)
770  {
772  _ ("%s failed at %s:%d: `%s'\n"),
773  "curl_multi_remove_handle",
774  __FILE__,
775  __LINE__,
776  curl_multi_strerror (mret));
777  }
778  mret = curl_multi_cleanup (multi);
779  if (mret != CURLM_OK)
781  _ ("%s failed at %s:%d: `%s'\n"),
782  "curl_multi_cleanup",
783  __FILE__,
784  __LINE__,
785  curl_multi_strerror (mret));
786  multi = NULL;
787  }
788  if (NULL != curl)
789  {
790  curl_easy_cleanup (curl);
791  curl = NULL;
792  }
794  current_url = NULL;
797 }
798 
799 
807 static void
808 task_download (void *cls);
809 
810 
815 static void
817 {
818  CURLMcode mret;
819  fd_set rs;
820  fd_set ws;
821  fd_set es;
822  int max;
823  struct GNUNET_NETWORK_FDSet *grs;
824  struct GNUNET_NETWORK_FDSet *gws;
825  long timeout;
826  struct GNUNET_TIME_Relative rtime;
827 
828  max = -1;
829  FD_ZERO (&rs);
830  FD_ZERO (&ws);
831  FD_ZERO (&es);
832  mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
833  if (mret != CURLM_OK)
834  {
836  _ ("%s failed at %s:%d: `%s'\n"),
837  "curl_multi_fdset",
838  __FILE__,
839  __LINE__,
840  curl_multi_strerror (mret));
841  clean_up ();
842  return;
843  }
844  mret = curl_multi_timeout (multi, &timeout);
845  if (mret != CURLM_OK)
846  {
848  _ ("%s failed at %s:%d: `%s'\n"),
849  "curl_multi_timeout",
850  __FILE__,
851  __LINE__,
852  curl_multi_strerror (mret));
853  clean_up ();
854  return;
855  }
856  rtime = GNUNET_TIME_relative_min (
861  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
862  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
864  "Scheduling task for hostlist download using cURL\n");
866  rtime,
867  grs,
868  gws,
869  &task_download,
870  multi);
873 }
874 
875 
882 static void
883 task_download (void *cls)
884 {
885  int running;
886  struct CURLMsg *msg;
887  CURLMcode mret;
888 
889  ti_download = NULL;
890  if (0 == GNUNET_TIME_absolute_get_remaining (end_time).rel_value_us)
891  {
893  _ ("Timeout trying to download hostlist from `%s'\n"),
894  current_url);
895  update_hostlist ();
896  clean_up ();
897  return;
898  }
900  "Ready for processing hostlist client request\n");
901  do
902  {
903  running = 0;
905  {
907  _ (
908  "Download limit of %u bytes exceeded, stopping download\n"),
910  clean_up ();
911  return;
912  }
913  mret = curl_multi_perform (multi, &running);
914  if (running == 0)
915  {
916  do
917  {
918  msg = curl_multi_info_read (multi, &running);
919  GNUNET_break (msg != NULL);
920  if (msg == NULL)
921  break;
922  switch (msg->msg)
923  {
924  case CURLMSG_DONE:
925  if ((msg->data.result != CURLE_OK) &&
926  (msg->data.result != CURLE_GOT_NOTHING))
928  _ ("Download of hostlist from `%s' failed: `%s'\n"),
929  current_url,
930  curl_easy_strerror (msg->data.result));
931  else
932  {
934  _ ("Download of hostlist `%s' completed.\n"),
935  current_url);
937  update_hostlist ();
939  {
940  GNUNET_log (
942  _ ("Adding successfully tested hostlist `%s' datastore.\n"),
943  current_url);
944  insert_hostlist ();
945  hostlist_to_test = NULL;
947  }
948  }
949  clean_up ();
950  return;
951 
952  default:
953  break;
954  }
955  }
956  while ((running > 0));
957  }
958  }
959  while (mret == CURLM_CALL_MULTI_PERFORM);
960 
961  if (mret != CURLM_OK)
962  {
964  _ ("%s failed at %s:%d: `%s'\n"),
965  "curl_multi_perform",
966  __FILE__,
967  __LINE__,
968  curl_multi_strerror (mret));
969  clean_up ();
970  }
971  download_prepare ();
972 }
973 
974 
979 static void
981 {
982  CURLcode ret;
983  CURLMcode mret;
984 
985 
987  if (current_url == NULL)
988  return;
989  curl = curl_easy_init ();
990  multi = NULL;
991  if (curl == NULL)
992  {
993  GNUNET_break (0);
994  clean_up ();
995  return;
996  }
998  _ ("Bootstrapping using hostlist at `%s'.\n"),
999  current_url);
1000 
1005 
1006  GNUNET_STATISTICS_update (stats,
1007  gettext_noop ("# hostlist downloads initiated"),
1008  1,
1009  GNUNET_NO);
1010  if (NULL != proxy)
1011  {
1012  CURL_EASY_SETOPT (curl, CURLOPT_PROXY, proxy);
1013  CURL_EASY_SETOPT (curl, CURLOPT_PROXYTYPE, proxy_type);
1014  if (NULL != proxy_username)
1015  CURL_EASY_SETOPT (curl, CURLOPT_PROXYUSERNAME, proxy_username);
1016  if (NULL != proxy_password)
1017  CURL_EASY_SETOPT (curl, CURLOPT_PROXYPASSWORD, proxy_password);
1018  }
1019  download_pos = 0;
1020  stat_bogus_url = 0;
1021  CURL_EASY_SETOPT (curl, CURLOPT_WRITEFUNCTION, &callback_download);
1022  if (ret != CURLE_OK)
1023  {
1024  clean_up ();
1025  return;
1026  }
1027  CURL_EASY_SETOPT (curl, CURLOPT_WRITEDATA, NULL);
1028  if (ret != CURLE_OK)
1029  {
1030  clean_up ();
1031  return;
1032  }
1033  CURL_EASY_SETOPT (curl, CURLOPT_FOLLOWLOCATION, 1);
1035  CURLOPT_REDIR_PROTOCOLS,
1036  CURLPROTO_HTTP | CURLPROTO_HTTPS);
1037  CURL_EASY_SETOPT (curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
1038  CURL_EASY_SETOPT (curl, CURLOPT_MAXREDIRS, 4);
1039  /* no need to abort if the above failed */
1040  CURL_EASY_SETOPT (curl, CURLOPT_URL, current_url);
1041  if (ret != CURLE_OK)
1042  {
1043  clean_up ();
1044  return;
1045  }
1046  CURL_EASY_SETOPT (curl, CURLOPT_FAILONERROR, 1);
1047 #if 0
1048  CURL_EASY_SETOPT (curl, CURLOPT_VERBOSE, 1);
1049 #endif
1050  CURL_EASY_SETOPT (curl, CURLOPT_BUFFERSIZE, GNUNET_MAX_MESSAGE_SIZE);
1051  if (0 == strncmp (current_url, "http", 4))
1052  CURL_EASY_SETOPT (curl, CURLOPT_USERAGENT, "GNUnet");
1053  CURL_EASY_SETOPT (curl, CURLOPT_CONNECTTIMEOUT, 60L);
1054  CURL_EASY_SETOPT (curl, CURLOPT_TIMEOUT, 60L);
1055  multi = curl_multi_init ();
1056  if (multi == NULL)
1057  {
1058  GNUNET_break (0);
1059  /* clean_up (); */
1060  return;
1061  }
1062  mret = curl_multi_add_handle (multi, curl);
1063  if (mret != CURLM_OK)
1064  {
1066  _ ("%s failed at %s:%d: `%s'\n"),
1067  "curl_multi_add_handle",
1068  __FILE__,
1069  __LINE__,
1070  curl_multi_strerror (mret));
1071  mret = curl_multi_cleanup (multi);
1072  if (mret != CURLM_OK)
1074  _ ("%s failed at %s:%d: `%s'\n"),
1075  "curl_multi_cleanup",
1076  __FILE__,
1077  __LINE__,
1078  curl_multi_strerror (mret));
1079  multi = NULL;
1080  clean_up ();
1081  return;
1082  }
1084  download_prepare ();
1085 }
1086 
1087 
1088 static void
1090 {
1091  ti_download_dispatcher_task = NULL;
1092  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download is initiated...\n");
1094  {
1095  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download can start immediately...\n");
1096  download_hostlist ();
1097  }
1098  else
1099  {
1101  "Download in progess, have to wait...\n");
1102  ti_download_dispatcher_task =
1105  NULL);
1106  }
1107 }
1108 
1109 
1115 static void
1116 task_check (void *cls)
1117 {
1118  static int once;
1119  struct GNUNET_TIME_Relative delay;
1120 
1121  ti_check_download = NULL;
1122  if (stats == NULL)
1123  {
1124  curl_global_cleanup ();
1125  return; /* in shutdown */
1126  }
1128  (NULL == ti_download_dispatcher_task))
1129  ti_download_dispatcher_task =
1131 
1132  delay = hostlist_delay;
1133  if (0 == hostlist_delay.rel_value_us)
1135  else
1138  GNUNET_TIME_UNIT_HOURS.rel_value_us * (1 + stat_connection_count))
1139  hostlist_delay =
1141  (1 + stat_connection_count));
1142  GNUNET_STATISTICS_set (stats,
1143  gettext_noop (
1144  "# milliseconds between hostlist downloads"),
1145  hostlist_delay.rel_value_us / 1000LL,
1146  GNUNET_YES);
1147  if (0 == once)
1148  {
1149  delay = GNUNET_TIME_UNIT_ZERO;
1150  once = 1;
1151  }
1152  GNUNET_log (
1154  _ ("Have %u/%u connections. Will consider downloading hostlist in %s\n"),
1158  ti_check_download = GNUNET_SCHEDULER_add_delayed (delay, &task_check, NULL);
1159 }
1160 
1161 
1167 static void
1169 {
1170  ti_testing_intervall_task = NULL;
1173  "Testing new hostlist advertisements is allowed again\n");
1174 }
1175 
1176 
1182 static void
1184 {
1185  ti_saving_task = NULL;
1187 
1189  "Hostlists will be saved to file again in %s\n",
1191  GNUNET_YES));
1192  ti_saving_task =
1194 }
1195 
1196 
1204 static void *
1205 handler_connect (void *cls,
1206  const struct GNUNET_PeerIdentity *peer,
1207  struct GNUNET_MQ_Handle *mq)
1208 {
1209  GNUNET_assert (stat_connection_count < UINT_MAX);
1211  GNUNET_STATISTICS_update (stats,
1212  gettext_noop ("# active connections"),
1213  1,
1214  GNUNET_NO);
1215  return NULL;
1216 }
1217 
1218 
1225 static void
1227  const struct GNUNET_PeerIdentity *peer,
1228  void *internal_cls)
1229 {
1232  GNUNET_STATISTICS_update (stats,
1233  gettext_noop ("# active connections"),
1234  -1,
1235  GNUNET_NO);
1236 }
1237 
1238 
1244 static void
1246 {
1247  size_t uri_size;
1248  struct Hostlist *hostlist;
1249 
1250  uri_size = strlen (uri) + 1;
1252  "Hostlist client recieved advertisement containing URI `%s'\n",
1253  uri);
1254  if (GNUNET_NO != linked_list_contains (uri))
1255  {
1256  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URI `%s' is already known\n", uri);
1257  return;
1258  }
1259 
1261  {
1262  GNUNET_log (
1264  "Currently not accepting new advertisements: interval between to advertisements is not reached\n");
1265  return;
1266  }
1268  {
1269  GNUNET_log (
1271  "Currently not accepting new advertisements: we are already testing a hostlist\n");
1272  return;
1273  }
1274 
1275  hostlist = GNUNET_malloc (sizeof(struct Hostlist) + uri_size);
1276  hostlist->hostlist_uri = (const char *) &hostlist[1];
1277  GNUNET_memcpy (&hostlist[1], uri, uri_size);
1278  hostlist->time_creation = GNUNET_TIME_absolute_get ();
1279  hostlist->quality = HOSTLIST_INITIAL;
1280  hostlist_to_test = hostlist;
1281 
1284  ti_testing_intervall_task =
1287  NULL);
1288 
1290  "Testing new hostlist advertisements is locked for the next %s\n",
1292  GNUNET_YES));
1293 
1294  ti_download_dispatcher_task =
1296 }
1297 
1298 
1307 static void
1308 primary_task (void *cls, int success)
1309 {
1310  if (NULL != ti_check_download)
1311  {
1312  GNUNET_SCHEDULER_cancel (ti_check_download);
1313  ti_check_download = NULL;
1314  }
1315  sget = NULL;
1316  GNUNET_assert (NULL != stats);
1318  "Statistics request done, scheduling hostlist download\n");
1319  ti_check_download = GNUNET_SCHEDULER_add_now (&task_check, NULL);
1320 }
1321 
1322 
1331 static void
1333 {
1335  sget = NULL;
1336  ti_check_download = GNUNET_SCHEDULER_add_now (&task_check, NULL);
1337 }
1338 
1339 
1349 static int
1350 process_stat (void *cls,
1351  const char *subsystem,
1352  const char *name,
1353  uint64_t value,
1354  int is_persistent)
1355 {
1356  hostlist_delay.rel_value_us = value * 1000LL;
1358  "Initial time between hostlist downloads is %s\n",
1360  GNUNET_YES));
1361  return GNUNET_OK;
1362 }
1363 
1364 
1368 static void
1370 {
1371  char *filename;
1372  char *uri;
1373  char *emsg;
1374  struct Hostlist *hostlist;
1375  uint32_t times_used;
1376  uint32_t hellos_returned;
1377  uint64_t quality;
1378  uint64_t last_used;
1379  uint64_t created;
1380  uint32_t counter;
1381  struct GNUNET_BIO_ReadHandle *rh;
1382 
1383  uri = NULL;
1385  "HOSTLIST",
1386  "HOSTLISTFILE",
1387  &filename))
1388  {
1390  "hostlist",
1391  "HOSTLISTFILE");
1392  return;
1393  }
1394 
1396  _ ("Loading saved hostlist entries from file `%s' \n"),
1397  filename);
1398  if (GNUNET_NO == GNUNET_DISK_file_test (filename))
1399  {
1401  _ ("Hostlist file `%s' does not exist\n"),
1402  filename);
1403  GNUNET_free (filename);
1404  return;
1405  }
1406 
1407  rh = GNUNET_BIO_read_open (filename);
1408  if (NULL == rh)
1409  {
1411  _ (
1412  "Could not open file `%s' for reading to load hostlists: %s\n"),
1413  filename,
1414  strerror (errno));
1415  GNUNET_free (filename);
1416  return;
1417  }
1418 
1419  counter = 0;
1420  while ((GNUNET_OK == GNUNET_BIO_read_string (rh, "url", &uri, MAX_URL_LEN)) &&
1421  (NULL != uri) &&
1422  (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &times_used)) &&
1423  (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality)) &&
1424  (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used)) &&
1425  (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &created)) &&
1426  (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &hellos_returned)))
1427  {
1428  hostlist = GNUNET_malloc (sizeof(struct Hostlist) + strlen (uri) + 1);
1429  hostlist->hello_count = hellos_returned;
1430  hostlist->hostlist_uri = (const char *) &hostlist[1];
1431  GNUNET_memcpy (&hostlist[1], uri, strlen (uri) + 1);
1432  hostlist->quality = quality;
1433  hostlist->time_creation.abs_value_us = created;
1434  hostlist->time_last_usage.abs_value_us = last_used;
1435  GNUNET_CONTAINER_DLL_insert (linked_list_head, linked_list_tail, hostlist);
1436  linked_list_size++;
1438  "Added hostlist entry eith URI `%s' \n",
1439  hostlist->hostlist_uri);
1440  GNUNET_free (uri);
1441  uri = NULL;
1442  counter++;
1443  if (counter >= MAX_NUMBER_HOSTLISTS)
1444  break;
1445  }
1446 
1448  _ ("%u hostlist URIs loaded from file\n"),
1449  counter);
1450  GNUNET_STATISTICS_set (stats,
1451  gettext_noop ("# hostlist URIs read from file"),
1452  counter,
1453  GNUNET_YES);
1454  GNUNET_STATISTICS_set (stats,
1455  gettext_noop ("# advertised hostlist URIs"),
1457  GNUNET_NO);
1458 
1459  GNUNET_free_non_null (uri);
1460  emsg = NULL;
1461  (void) GNUNET_BIO_read_close (rh, &emsg);
1462  if (emsg != NULL)
1463  GNUNET_free (emsg);
1464  GNUNET_free (filename);
1465 }
1466 
1467 
1473 static void
1474 save_hostlist_file (int shutdown)
1475 {
1476  char *filename;
1477  struct Hostlist *pos;
1478  struct GNUNET_BIO_WriteHandle *wh;
1479  int ok;
1480  uint32_t counter;
1481 
1483  "HOSTLIST",
1484  "HOSTLISTFILE",
1485  &filename))
1486  {
1488  "hostlist",
1489  "HOSTLISTFILE");
1490  return;
1491  }
1493  {
1494  GNUNET_free (filename);
1495  return;
1496  }
1497  wh = GNUNET_BIO_write_open (filename);
1498  if (NULL == wh)
1499  {
1501  _ (
1502  "Could not open file `%s' for writing to save hostlists: %s\n"),
1503  filename,
1504  strerror (errno));
1505  GNUNET_free (filename);
1506  return;
1507  }
1509  _ ("Writing %u hostlist URIs to `%s'\n"),
1511  filename);
1512  /* add code to write hostlists to file using bio */
1513  ok = GNUNET_YES;
1514  counter = 0;
1515  while (NULL != (pos = linked_list_head))
1516  {
1517  if (GNUNET_YES == shutdown)
1518  {
1519  GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail, pos);
1520  linked_list_size--;
1521  }
1522  if (GNUNET_YES == ok)
1523  {
1524  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pos->hostlist_uri)) ||
1525  (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->times_used)) ||
1526  (GNUNET_OK != GNUNET_BIO_write_int64 (wh, pos->quality)) ||
1527  (GNUNET_OK !=
1529  (GNUNET_OK !=
1532  {
1534  _ ("Error writing hostlist URIs to file `%s'\n"),
1535  filename);
1536  ok = GNUNET_NO;
1537  }
1538  }
1539 
1540  if (GNUNET_YES == shutdown)
1541  GNUNET_free (pos);
1542  counter++;
1543  if (counter >= MAX_NUMBER_HOSTLISTS)
1544  break;
1545  }
1546  GNUNET_STATISTICS_set (stats,
1547  gettext_noop ("# hostlist URIs written to file"),
1548  counter,
1549  GNUNET_YES);
1550 
1551  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
1553  _ ("Error writing hostlist URIs to file `%s'\n"),
1554  filename);
1555  GNUNET_free (filename);
1556 }
1557 
1558 
1570 int
1572  struct GNUNET_STATISTICS_Handle *st,
1576  int learn)
1577 {
1578  char *filename;
1579  char *proxytype_str;
1580  int result;
1581 
1582  GNUNET_assert (NULL != st);
1583  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
1584  {
1585  GNUNET_break (0);
1586  return GNUNET_SYSERR;
1587  }
1588  cfg = c;
1589  stats = st;
1590 
1591  /* Read proxy configuration */
1592  pi = GNUNET_PEERINFO_connect (c);
1593  if (GNUNET_OK ==
1594  GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST", "PROXY", &proxy))
1595  {
1596  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found proxy host: `%s'\n", proxy);
1597  /* proxy username */
1599  "HOSTLIST",
1600  "PROXY_USERNAME",
1601  &proxy_username))
1602  {
1604  "Found proxy username name: `%s'\n",
1605  proxy_username);
1606  }
1607 
1608  /* proxy password */
1610  "HOSTLIST",
1611  "PROXY_PASSWORD",
1612  &proxy_password))
1613  {
1615  "Found proxy password name: `%s'\n",
1616  proxy_password);
1617  }
1618 
1619  /* proxy type */
1621  "HOSTLIST",
1622  "PROXY_TYPE",
1623  &proxytype_str))
1624  {
1625  GNUNET_STRINGS_utf8_toupper (proxytype_str, proxytype_str);
1626  proxy_type = CURLPROXY_HTTP;
1627  if (0 == strcmp (proxytype_str, "HTTP"))
1628  proxy_type = CURLPROXY_HTTP;
1629  else if (0 == strcmp (proxytype_str, "HTTP_1_0"))
1630  proxy_type = CURLPROXY_HTTP_1_0;
1631  else if (0 == strcmp (proxytype_str, "SOCKS4"))
1632  proxy_type = CURLPROXY_SOCKS4;
1633  else if (0 == strcmp (proxytype_str, "SOCKS5"))
1634  proxy_type = CURLPROXY_SOCKS5;
1635  else if (0 == strcmp (proxytype_str, "SOCKS4A"))
1636  proxy_type = CURLPROXY_SOCKS4A;
1637  else if (0 == strcmp (proxytype_str, "SOCKS5_HOSTNAME"))
1638  proxy_type = CURLPROXY_SOCKS5_HOSTNAME;
1639  else
1640  {
1641  GNUNET_log (
1643  _ (
1644  "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"),
1645  proxytype_str);
1646  GNUNET_free (proxytype_str);
1647  GNUNET_free (proxy);
1648  proxy = NULL;
1650  proxy_username = NULL;
1652  proxy_password = NULL;
1653 
1654  return GNUNET_SYSERR;
1655  }
1656  }
1657  GNUNET_free_non_null (proxytype_str);
1658  }
1659 
1660  stat_learning = learn;
1661  *ch = &handler_connect;
1662  *dh = &handler_disconnect;
1663  linked_list_head = NULL;
1664  linked_list_tail = NULL;
1668 
1669  if (GNUNET_YES == stat_learning)
1670  {
1671  *msgh = &handler_advertisement;
1673  _ ("Learning is enabled on this peer\n"));
1674  load_hostlist_file ();
1676  "Hostlists will be saved to file again in %s\n",
1678  GNUNET_YES));
1681  NULL);
1682  }
1683  else
1684  {
1686  _ ("Learning is not enabled on this peer\n"));
1687  *msgh = NULL;
1689  "HOSTLIST",
1690  "HOSTLISTFILE",
1691  &filename))
1692  {
1693  if (GNUNET_YES == GNUNET_DISK_file_test (filename))
1694  {
1695  result = remove (filename);
1696  if (0 == result)
1697  GNUNET_log (
1699  _ (
1700  "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"),
1701  filename);
1702  else
1704  "remove",
1705  filename);
1706  }
1707  }
1708  GNUNET_free (filename);
1709  }
1711  "Loading stats value on hostlist download frequency\n");
1712  sget = GNUNET_STATISTICS_get (stats,
1713  "hostlist",
1714  gettext_noop (
1715  "# milliseconds between hostlist downloads"),
1716  &primary_task,
1717  &process_stat,
1718  NULL);
1719  if (NULL == sget)
1720  {
1722  "Statistics request failed, scheduling hostlist download\n");
1723  ti_check_download = GNUNET_SCHEDULER_add_now (&task_check, NULL);
1724  }
1725  else
1726  {
1729  NULL);
1730  }
1731  return GNUNET_OK;
1732 }
1733 
1734 
1738 void
1740 {
1741  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist client shutdown\n");
1742  if (NULL != sget)
1743  {
1745  sget = NULL;
1746  }
1747  stats = NULL;
1748  if (GNUNET_YES == stat_learning)
1750  if (NULL != ti_saving_task)
1751  {
1752  GNUNET_SCHEDULER_cancel (ti_saving_task);
1753  ti_saving_task = NULL;
1754  }
1755  if (NULL != ti_download_dispatcher_task)
1756  {
1757  GNUNET_SCHEDULER_cancel (ti_download_dispatcher_task);
1758  ti_download_dispatcher_task = NULL;
1759  }
1760  if (NULL != ti_testing_intervall_task)
1761  {
1762  GNUNET_SCHEDULER_cancel (ti_testing_intervall_task);
1763  ti_testing_intervall_task = NULL;
1764  }
1765  if (NULL != ti_download)
1766  {
1767  GNUNET_SCHEDULER_cancel (ti_download);
1768  ti_download = NULL;
1769  update_hostlist ();
1770  clean_up ();
1771  }
1772  if (NULL != ti_check_download)
1773  {
1774  GNUNET_SCHEDULER_cancel (ti_check_download);
1775  ti_check_download = NULL;
1776  curl_global_cleanup ();
1777  }
1779  proxy = NULL;
1781  proxy_username = NULL;
1783  proxy_password = NULL;
1784  if (NULL != pi)
1785  {
1787  pi = NULL;
1788  }
1789  cfg = NULL;
1790 }
1791 
1792 
1793 /* end of gnunet-daemon-hostlist_client.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:544
struct GNUNET_TIME_Absolute time_last_usage
Last time the hostlist was obtained.
common internal definitions for hostlist daemon
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
#define MAX_URL_LEN
How long can hostlist URLs be?
#define MAX_BYTES_PER_HOSTLISTS
How many bytes do we download at most from a hostlist server?
Handle to the peerinfo service.
Definition: peerinfo_api.c:84
A HELLO message is used to exchange information about transports with other peers.
static char * subsystem
Set to subsystem that we&#39;re going to get stats for (or NULL for all).
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_TIME_UNIT_HOURS
One hour.
uint64_t rel_value_us
The actual value.
static uint64_t checked_add(uint64_t val1, uint64_t val2)
Add val2 to val1 with overflow check.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_HOSTLIST_client_stop()
Stop downloading hostlists from hostlist servers as necessary.
#define TESTING_INTERVAL
Time interval between two hostlist tests.
struct GNUNET_TIME_Absolute time_creation
Time the hostlist advertisement was recieved and the entry was created.
uint64_t quality
Value describing the quality of the hostlist, the bigger the better but (should) never < 0 used for d...
static void task_download(void *cls)
Task that is run when we are ready to receive more data from the hostlist server. ...
static unsigned int stat_connection_count
Number of active connections (according to core service).
struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the peerinfo service.
Definition: peerinfo_api.c:130
#define HOSTLIST_INITIAL
Defines concerning the hostlist quality metric.
#define WAITING_INTERVAL
Time interval for download dispatcher before a download is re-scheduled.
library to make it easy to download JSON replies over HTTP
static int stat_learning
Set if we are allowed to learn new hostlists and use them.
static struct GNUNET_TIME_Absolute end_time
At what time MUST the current hostlist request be done?
#define GNUNET_TIME_UNIT_MINUTES
One minute.
int GNUNET_BIO_write_string(struct GNUNET_BIO_WriteHandle *h, const char *s)
Write a string to a file.
Definition: bio.c:523
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
static struct GNUNET_SCHEDULER_Task * ti_download_dispatcher_task
ID of the task called to initiate a download.
static struct GNUNET_SCHEDULER_Task * ti_saving_task
ID of the task saving the hostlsit in a regular intervall.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_BIO_write_int64(struct GNUNET_BIO_WriteHandle *h, int64_t i)
Write an (u)int64_t.
Definition: bio.c:599
static void load_hostlist_file()
Method to load persistent hostlist file during hostlist client startup.
void(* GNUNET_CORE_DisconnectEventHandler)(void *cls, const struct GNUNET_PeerIdentity *peer, void *peer_cls)
Method called whenever a peer disconnects.
#define GNUNET_TIME_UNIT_SECONDS
One second.
static void handler_advertisement(const char *uri)
Method called whenever an advertisement message arrives.
void GNUNET_STATISTICS_get_cancel(struct GNUNET_STATISTICS_GetHandle *gh)
Cancel a GNUNET_STATISTICS_get request.
static struct GNUNET_SCHEDULER_Task * ti_download
ID of the task downloading the hostlist.
static int ok
Return value from &#39;main&#39; (0 == success)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static curl_proxytype proxy_type
Proxy type we are using (can be NULL).
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
static int process_stat(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
We&#39;ve received the previous delay value from statistics.
static void * handler_connect(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Method called whenever a given peer connects.
Linked list of things we still need to do.
#define GNUNET_NO
Definition: gnunet_common.h:78
static size_t download_pos
Number of bytes valid in &#39;download_buffer&#39;.
static void primary_task(void *cls, int success)
Continuation called by the statistics code once we go the stat.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
struct Hostlist * next
next entry, used to manage entries in a double linked list
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static void update_hostlist()
Method updating hostlist statistics.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static char * proxy_username
Proxy username we are using (can be NULL).
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
Handle for the service.
static char * current_url
Current URL that we are using.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define HOSTLIST_SUCCESSFUL_HELLO
Value added for each valid HELLO recived during a hostlist download.
uint64_t abs_value_us
The actual value.
static char * proxy
Proxy hostname or ip we are using (can be NULL).
int GNUNET_BIO_read_close(struct GNUNET_BIO_ReadHandle *h, char **emsg)
Close an open file.
Definition: bio.c:119
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
void GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds)
Copy a native fd set into the GNUnet representation.
Definition: network.c:1120
#define CURL_EASY_SETOPT(c, a, b)
static char * proxy_password
Proxy password we are using (can be NULL).
void *(* GNUNET_CORE_ConnectEventHandler)(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Method called whenever a given peer connects.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static void stat_timeout_task(void *cls)
Continuation called by the statistics code once we go the stat.
struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open(const char *fn)
Open a file for reading.
Definition: bio.c:94
uint32_t hello_count
Number of HELLO messages obtained during last download.
#define GNUNET_BIO_read_int64(h, i)
Read an (u)int64_t.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1266
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
static void insert_hostlist()
Method to insert a hostlist into the datastore.
void(* GNUNET_HOSTLIST_UriHandler)(const char *uri)
Function that handles an advertised URI.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1253
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1250
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:578
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static int stat_testing_allowed
Value controlling if a hostlist testing is allowed at the moment.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1280
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
static CURLM * multi
Current multi-CURL handle.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:687
static int once
Global to mark if we&#39;ve run the initialization.
Definition: gnsrecord.c:68
static unsigned int stat_download_successful
Value saying if hostlist download was successful.
collection of IO descriptors
static char * filename
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1810
static int result
Global testing status.
static int linked_list_contains(const char *uri)
Method to check if a URI is in hostlist linked list.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:442
const char * hostlist_uri
URI where hostlist can be obtained.
static unsigned int stat_use_bootstrap
Value saying if a preconfigured bootstrap server is used.
static void task_download_dispatcher(void *cls)
static int stat_bogus_url
Set to GNUNET_YES if the current URL had some problems.
struct Hostlist * prev
previous entry, used to manage entries in a double linked list
static struct Hostlist * linked_list_head
Head of the linked list used to store hostlists.
Handle for buffered writing.
Definition: bio.c:379
static size_t callback_download(void *ptr, size_t size, size_t nmemb, void *ctx)
Process downloaded bits by calling callback on each HELLO.
static struct Hostlist * linked_list_tail
Tail of the linked list used to store hostlists.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
static void handler_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer, void *internal_cls)
Method called whenever a given peer disconnects.
struct GNUNET_MQ_Envelope * GNUNET_PEERINFO_add_peer(struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_HELLO_Message *hello, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Add a host to the persistent list.
Definition: peerinfo_api.c:553
static struct GNUNET_SCHEDULER_Task * ti_testing_intervall_task
ID of the task controlling the locking between two hostlist tests.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
int GNUNET_BIO_read_string(struct GNUNET_BIO_ReadHandle *h, const char *what, char **result, size_t max_length)
Read 0-terminated string from a file.
Definition: bio.c:233
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static void task_check(void *cls)
Task that checks if we should try to download a hostlist.
static void download_hostlist()
Main function that will download a hostlist and process its data.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static struct Hostlist * current_hostlist
Current hostlist used for downloading.
static CURL * curl
Current CURL handle.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
static char * get_bootstrap_server()
Obtain a hostlist URL that we should use.
static unsigned int linked_list_size
Size of the linke list used to store hostlists.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define HOSTLIST_SUCCESSFUL_DOWNLOAD
Value added each time a hostlist download is successful.
#define GNUNET_BIO_read_int32(h, i)
Read an (u)int32_t.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
int GNUNET_HOSTLIST_client_start(const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_STATISTICS_Handle *st, GNUNET_CORE_ConnectEventHandler *ch, GNUNET_CORE_DisconnectEventHandler *dh, GNUNET_HOSTLIST_UriHandler *msgh, int learn)
Start downloading hostlists from hostlist servers as necessary.
static struct GNUNET_TESTBED_BarrierWaitHandle * wh
Our barrier wait handle.
static unsigned int stat_hellos_obtained
Value saying how many valid HELLO messages were obtained during download.
int GNUNET_BIO_write_close(struct GNUNET_BIO_WriteHandle *h)
Close an open file for writing.
Definition: bio.c:438
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
Handle to a message queue.
Definition: mq.c:85
static void download_prepare()
Ask CURL for the select set and then schedule the receiving task with the scheduler.
static void save_hostlist_file(int shutdown)
Method to save hostlist to a file during hostlist client shutdown.
static void clean_up()
Clean up the state from the task that downloaded the hostlist and schedule the next task...
static void task_testing_intervall_reset(void *cls)
This tasks sets hostlist testing to allowed after intervall between to testings is reached...
static struct GNUNET_STATISTICS_GetHandle * sget
Handle for our statistics GET operation.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls)
Get statistic from the peer.
static struct GNUNET_SCHEDULER_Task * ti_check_download
ID of the task, checking if hostlist download should take plate.
configuration data
Definition: configuration.c:85
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open(const char *fn)
Open a file for writing.
Definition: bio.c:410
const char * name
uint32_t times_used
Number of times the hostlist was successfully obtained.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
#define SAVING_INTERVAL
Time interval hostlists are saved to disk.
static uint32_t stat_bytes_downloaded
How many bytes did we download from the current hostlist URL?
static char * download_get_url()
Method deciding if a preconfigured or advertisied hostlist is used on a 50:50 ratio.
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:652
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void GNUNET_PEERINFO_disconnect(struct GNUNET_PEERINFO_Handle *h)
Disconnect from the peerinfo service.
Definition: peerinfo_api.c:156
int GNUNET_BIO_write_int32(struct GNUNET_BIO_WriteHandle *h, int32_t i)
Write an (u)int32_t.
Definition: bio.c:582
static void task_hostlist_saving(void *cls)
Task that writes hostlist entries to a file on a regular base.
static struct Hostlist * linked_list_get_lowest_quality()
Method returning the hostlist element with the lowest quality in the datastore.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
#define MAX_NUMBER_HOSTLISTS
Maximum number of hostlist that are saved.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
static int stat_download_in_progress
Value controlling if a hostlist download is running at the moment.
#define HOSTLIST_FAILED_DOWNLOAD
Value subtracted each time a hostlist download fails.
A single hostlist obtained by hostlist advertisements.
#define MIN_CONNECTIONS
Number of connections that we must have to NOT download hostlists anymore.
Run with the default priority (normal P2P operations).
static uint64_t checked_sub(uint64_t val1, uint64_t val2)
Subtract val2 from val1 with underflow check.
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static struct GNUNET_STATISTICS_Handle * stats
Statistics handle.
static int stat_testing_hostlist
Value controlling if a hostlist is tested at the moment.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
Handle for buffered reading.
Definition: bio.c:53
static struct Hostlist * hostlist_to_test
Head of the linked list used to store hostlists.
static struct GNUNET_TIME_Relative hostlist_delay
Amount of time we wait between hostlist downloads.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966