GNUnet  0.10.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 {
98  struct Hostlist *prev;
99 
103  struct Hostlist *next;
104 
108  const char *hostlist_uri;
109 
118  uint64_t quality;
119 
124 
129 
133  uint32_t hello_count;
134 
138  uint32_t times_used;
139 };
140 
141 
145 static const struct GNUNET_CONFIGURATION_Handle *cfg;
146 
151 
155 static char *proxy;
156 
160 static char *proxy_username;
161 
165 static char *proxy_password;
166 
170 static curl_proxytype proxy_type;
171 
175 static size_t download_pos;
176 
180 static char *current_url;
181 
185 static CURL *curl;
186 
190 static CURLM *multi;
191 
195 static uint32_t stat_bytes_downloaded;
196 
201 
206 
211 
216 
221 
226 
231 
235 static struct Hostlist *linked_list_head;
236 
240 static struct Hostlist *linked_list_tail;
241 
245 static struct Hostlist *current_hostlist;
246 
250 static unsigned int linked_list_size;
251 
255 static struct Hostlist *hostlist_to_test;
256 
261 
265 static int stat_bogus_url;
266 
271 
276 
281 
285 static unsigned int stat_use_bootstrap;
286 
290 static int stat_learning;
291 
295 static unsigned int stat_download_successful;
296 
300 static unsigned int stat_hellos_obtained;
301 
305 static unsigned int stat_connection_count;
306 
310 static struct GNUNET_PEERINFO_Handle *pi;
311 
312 
322 static size_t
323 callback_download(void *ptr, size_t size, size_t nmemb, void *ctx)
324 {
325  static char download_buffer[GNUNET_MAX_MESSAGE_SIZE - 1];
326  const char *cbuf = ptr;
327  const struct GNUNET_MessageHeader *msg;
328  size_t total;
329  size_t cpy;
330  size_t left;
331  uint16_t msize;
332 
333  total = size * nmemb;
334  stat_bytes_downloaded += total;
335  if ((total == 0) || (stat_bogus_url))
336  {
337  return total; /* ok, no data or bogus data */
338  }
339 
341  gettext_noop(
342  "# bytes downloaded from hostlist servers"),
343  (int64_t)total,
344  GNUNET_NO);
345  left = total;
346  while ((left > 0) || (download_pos > 0))
347  {
349  GNUNET_memcpy(&download_buffer[download_pos], cbuf, cpy);
350  cbuf += cpy;
351  download_pos += cpy;
352  left -= cpy;
353  if (download_pos < sizeof(struct GNUNET_MessageHeader))
354  {
355  GNUNET_assert(0 == left);
356  break;
357  }
358  msg = (const struct GNUNET_MessageHeader *)download_buffer;
359  msize = ntohs(msg->size);
360  if (msize < sizeof(struct GNUNET_MessageHeader))
361  {
363  stats,
364  gettext_noop("# invalid HELLOs downloaded from hostlist servers"),
365  1,
366  GNUNET_NO);
368  _("Invalid `%s' message received from hostlist at `%s'\n"),
369  "HELLO",
370  current_url);
372  stat_bogus_url = 1;
373  return total;
374  }
375  if (download_pos < msize)
376  {
377  GNUNET_assert(left == 0);
378  break;
379  }
380  if (GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)msg) == msize)
381  {
383  "Received valid `%s' message from hostlist server.\n",
384  "HELLO");
386  stats,
387  gettext_noop("# valid HELLOs downloaded from hostlist servers"),
388  1,
389  GNUNET_NO);
391  (void)
393  (const struct GNUNET_HELLO_Message *)msg,
394  NULL,
395  NULL);
396  }
397  else
398  {
400  stats,
401  gettext_noop("# invalid HELLOs downloaded from hostlist servers"),
402  1,
403  GNUNET_NO);
405  _("Invalid `%s' message received from hostlist at `%s'\n"),
406  "HELLO",
407  current_url);
410  return total;
411  }
412  memmove(download_buffer, &download_buffer[msize], download_pos - msize);
413  download_pos -= msize;
414  }
415  return total;
416 }
417 
418 
424 static char *
426 {
427  char *servers;
428  char *ret;
429  size_t urls;
430  size_t pos;
431 
433  "HOSTLIST",
434  "SERVERS",
435  &servers))
436  {
438  "hostlist",
439  "SERVERS");
440  return NULL;
441  }
442 
443  urls = 0;
444  if (strlen(servers) > 0)
445  {
446  urls++;
447  pos = strlen(servers) - 1;
448  while (pos > 0)
449  {
450  if (servers[pos] == ' ')
451  urls++;
452  pos--;
453  }
454  }
455  if (urls == 0)
456  {
458  "hostlist",
459  "SERVERS");
460  GNUNET_free(servers);
461  return NULL;
462  }
463 
465  pos = strlen(servers) - 1;
466  while (pos > 0)
467  {
468  if (servers[pos] == ' ')
469  {
470  urls--;
471  servers[pos] = '\0';
472  }
473  if (urls == 0)
474  {
475  pos++;
476  break;
477  }
478  pos--;
479  }
480  ret = GNUNET_strdup(&servers[pos]);
481  GNUNET_free(servers);
482  return ret;
483 }
484 
485 
490 static char *
492 {
493  uint32_t index;
494  unsigned int counter;
495  struct Hostlist *pos;
496 
497  if (GNUNET_NO == stat_learning)
498  {
500  "Using preconfigured bootstrap server\n");
501  current_hostlist = NULL;
502  return get_bootstrap_server();
503  }
504 
505  if ((GNUNET_YES == stat_testing_hostlist) && (NULL != hostlist_to_test))
506  {
508  "Testing new advertised hostlist if it is obtainable\n");
509  current_hostlist = hostlist_to_test;
510  return GNUNET_strdup(hostlist_to_test->hostlist_uri);
511  }
512 
514  {
516  "Using preconfigured bootstrap server\n");
517  current_hostlist = NULL;
518  return get_bootstrap_server();
519  }
520  index =
522  counter = 0;
523  pos = linked_list_head;
524  while (counter < index)
525  {
526  pos = pos->next;
527  counter++;
528  }
530  "Using learned hostlist `%s'\n",
531  pos->hostlist_uri);
532  current_hostlist = pos;
533  return GNUNET_strdup(pos->hostlist_uri);
534 }
535 
536 
537 #define CURL_EASY_SETOPT(c, a, b) \
538  do \
539  { \
540  ret = curl_easy_setopt(c, a, b); \
541  if (CURLE_OK != ret) \
542  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
543  _("%s failed at %s:%d: `%s'\n"), \
544  "curl_easy_setopt", \
545  __FILE__, \
546  __LINE__, \
547  curl_easy_strerror(ret)); \
548  } while (0)
549 
550 
556 static void
557 save_hostlist_file(int shutdown);
558 
559 
567 static uint64_t
568 checked_add(uint64_t val1, uint64_t val2)
569 {
570  static uint64_t temp;
571  static uint64_t maxv;
572 
573  maxv = 0;
574  maxv--;
575 
576  temp = val1 + val2;
577  if (temp < val1)
578  return maxv;
579  return temp;
580 }
581 
582 
590 static uint64_t
591 checked_sub(uint64_t val1, uint64_t val2)
592 {
593  if (val1 <= val2)
594  return 0;
595  return(val1 - val2);
596 }
597 
598 
605 static int
607 {
608  struct Hostlist *pos;
609 
610  pos = linked_list_head;
611  while (pos != NULL)
612  {
613  if (0 == strcmp(pos->hostlist_uri, uri))
614  return GNUNET_YES;
615  pos = pos->next;
616  }
617  return GNUNET_NO;
618 }
619 
620 
625 static struct Hostlist *
627 {
628  struct Hostlist *pos;
629  struct Hostlist *lowest;
630 
631  if (linked_list_size == 0)
632  return NULL;
633  lowest = linked_list_head;
634  pos = linked_list_head->next;
635  while (pos != NULL)
636  {
637  if (pos->quality < lowest->quality)
638  lowest = pos;
639  pos = pos->next;
640  }
641  return lowest;
642 }
643 
644 
650 static void
652 {
653  struct Hostlist *lowest_quality;
654 
656  {
657  /* No free entries available, replace existing entry */
658  lowest_quality = linked_list_get_lowest_quality();
659  GNUNET_assert(lowest_quality != NULL);
660  GNUNET_log(
662  "Removing hostlist with URI `%s' which has the worst quality of all (%llu)\n",
663  lowest_quality->hostlist_uri,
664  (unsigned long long)lowest_quality->quality);
665  GNUNET_CONTAINER_DLL_remove(linked_list_head,
666  linked_list_tail,
667  lowest_quality);
669  GNUNET_free(lowest_quality);
670  }
671  GNUNET_CONTAINER_DLL_insert(linked_list_head,
672  linked_list_tail,
673  hostlist_to_test);
675  GNUNET_STATISTICS_set(stats,
676  gettext_noop("# advertised hostlist URIs"),
678  GNUNET_NO);
680 }
681 
682 
686 static void
688 {
689  char *stat;
690 
691  if (((stat_use_bootstrap == GNUNET_NO) && (NULL != current_hostlist)) ||
692  ((stat_testing_hostlist == GNUNET_YES) && (NULL != current_hostlist)))
693  {
695  "Updating hostlist statics for URI `%s'\n",
696  current_hostlist->hostlist_uri);
697  current_hostlist->hello_count = stat_hellos_obtained;
698  current_hostlist->time_last_usage = GNUNET_TIME_absolute_get();
699  current_hostlist->quality =
700  checked_add(current_hostlist->quality,
703  {
704  current_hostlist->times_used++;
705  current_hostlist->quality =
707  GNUNET_asprintf(&stat,
708  gettext_noop("# advertised URI `%s' downloaded"),
709  current_hostlist->hostlist_uri);
710 
711  GNUNET_STATISTICS_update(stats, stat, 1, GNUNET_YES);
712  GNUNET_free(stat);
713  }
714  else
715  current_hostlist->quality =
716  checked_sub(current_hostlist->quality, HOSTLIST_FAILED_DOWNLOAD);
717  }
718  current_hostlist = NULL;
719  /* Alternating the usage of preconfigured and learned hostlists */
720 
722  return;
723 
724  if (GNUNET_YES == stat_learning)
725  {
728  else
730  }
731  else
733 }
734 
735 
740 static void
742 {
743  CURLMcode mret;
744 
746  (GNUNET_NO == stat_download_successful) && (NULL != hostlist_to_test))
747  {
748  GNUNET_log(
750  _(
751  "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI gets dismissed.\n"),
752  hostlist_to_test->hostlist_uri);
753  }
754 
756  {
758  }
759  if (NULL != hostlist_to_test)
760  {
761  GNUNET_free(hostlist_to_test);
762  hostlist_to_test = NULL;
763  }
764 
765  if (NULL != multi)
766  {
767  mret = curl_multi_remove_handle(multi, curl);
768  if (mret != CURLM_OK)
769  {
771  _("%s failed at %s:%d: `%s'\n"),
772  "curl_multi_remove_handle",
773  __FILE__,
774  __LINE__,
775  curl_multi_strerror(mret));
776  }
777  mret = curl_multi_cleanup(multi);
778  if (mret != CURLM_OK)
780  _("%s failed at %s:%d: `%s'\n"),
781  "curl_multi_cleanup",
782  __FILE__,
783  __LINE__,
784  curl_multi_strerror(mret));
785  multi = NULL;
786  }
787  if (NULL != curl)
788  {
789  curl_easy_cleanup(curl);
790  curl = NULL;
791  }
793  current_url = NULL;
796 }
797 
798 
806 static void
807 task_download(void *cls);
808 
809 
814 static void
816 {
817  CURLMcode mret;
818  fd_set rs;
819  fd_set ws;
820  fd_set es;
821  int max;
822  struct GNUNET_NETWORK_FDSet *grs;
823  struct GNUNET_NETWORK_FDSet *gws;
824  long timeout;
825  struct GNUNET_TIME_Relative rtime;
826 
827  max = -1;
828  FD_ZERO(&rs);
829  FD_ZERO(&ws);
830  FD_ZERO(&es);
831  mret = curl_multi_fdset(multi, &rs, &ws, &es, &max);
832  if (mret != CURLM_OK)
833  {
835  _("%s failed at %s:%d: `%s'\n"),
836  "curl_multi_fdset",
837  __FILE__,
838  __LINE__,
839  curl_multi_strerror(mret));
840  clean_up();
841  return;
842  }
843  mret = curl_multi_timeout(multi, &timeout);
844  if (mret != CURLM_OK)
845  {
847  _("%s failed at %s:%d: `%s'\n"),
848  "curl_multi_timeout",
849  __FILE__,
850  __LINE__,
851  curl_multi_strerror(mret));
852  clean_up();
853  return;
854  }
855  rtime = GNUNET_TIME_relative_min(
860  GNUNET_NETWORK_fdset_copy_native(grs, &rs, max + 1);
861  GNUNET_NETWORK_fdset_copy_native(gws, &ws, max + 1);
863  "Scheduling task for hostlist download using cURL\n");
865  rtime,
866  grs,
867  gws,
868  &task_download,
869  multi);
872 }
873 
874 
881 static void
882 task_download(void *cls)
883 {
884  int running;
885  struct CURLMsg *msg;
886  CURLMcode mret;
887 
888  ti_download = NULL;
889  if (0 == GNUNET_TIME_absolute_get_remaining(end_time).rel_value_us)
890  {
892  _("Timeout trying to download hostlist from `%s'\n"),
893  current_url);
894  update_hostlist();
895  clean_up();
896  return;
897  }
899  "Ready for processing hostlist client request\n");
900  do
901  {
902  running = 0;
904  {
906  _(
907  "Download limit of %u bytes exceeded, stopping download\n"),
909  clean_up();
910  return;
911  }
912  mret = curl_multi_perform(multi, &running);
913  if (running == 0)
914  {
915  do
916  {
917  msg = curl_multi_info_read(multi, &running);
918  GNUNET_break(msg != NULL);
919  if (msg == NULL)
920  break;
921  switch (msg->msg)
922  {
923  case CURLMSG_DONE:
924  if ((msg->data.result != CURLE_OK) &&
925  (msg->data.result != CURLE_GOT_NOTHING))
927  _("Download of hostlist from `%s' failed: `%s'\n"),
928  current_url,
929  curl_easy_strerror(msg->data.result));
930  else
931  {
933  _("Download of hostlist `%s' completed.\n"),
934  current_url);
936  update_hostlist();
938  {
939  GNUNET_log(
941  _("Adding successfully tested hostlist `%s' datastore.\n"),
942  current_url);
943  insert_hostlist();
944  hostlist_to_test = NULL;
946  }
947  }
948  clean_up();
949  return;
950 
951  default:
952  break;
953  }
954  }
955  while ((running > 0));
956  }
957  }
958  while (mret == CURLM_CALL_MULTI_PERFORM);
959 
960  if (mret != CURLM_OK)
961  {
963  _("%s failed at %s:%d: `%s'\n"),
964  "curl_multi_perform",
965  __FILE__,
966  __LINE__,
967  curl_multi_strerror(mret));
968  clean_up();
969  }
971 }
972 
973 
978 static void
980 {
981  CURLcode ret;
982  CURLMcode mret;
983 
984 
986  if (current_url == NULL)
987  return;
988  curl = curl_easy_init();
989  multi = NULL;
990  if (curl == NULL)
991  {
992  GNUNET_break(0);
993  clean_up();
994  return;
995  }
997  _("Bootstrapping using hostlist at `%s'.\n"),
998  current_url);
999 
1004 
1006  gettext_noop("# hostlist downloads initiated"),
1007  1,
1008  GNUNET_NO);
1009  if (NULL != proxy)
1010  {
1011  CURL_EASY_SETOPT(curl, CURLOPT_PROXY, proxy);
1012  CURL_EASY_SETOPT(curl, CURLOPT_PROXYTYPE, proxy_type);
1013  if (NULL != proxy_username)
1014  CURL_EASY_SETOPT(curl, CURLOPT_PROXYUSERNAME, proxy_username);
1015  if (NULL != proxy_password)
1016  CURL_EASY_SETOPT(curl, CURLOPT_PROXYPASSWORD, proxy_password);
1017  }
1018  download_pos = 0;
1019  stat_bogus_url = 0;
1020  CURL_EASY_SETOPT(curl, CURLOPT_WRITEFUNCTION, &callback_download);
1021  if (ret != CURLE_OK)
1022  {
1023  clean_up();
1024  return;
1025  }
1026  CURL_EASY_SETOPT(curl, CURLOPT_WRITEDATA, NULL);
1027  if (ret != CURLE_OK)
1028  {
1029  clean_up();
1030  return;
1031  }
1032  CURL_EASY_SETOPT(curl, CURLOPT_FOLLOWLOCATION, 1);
1034  CURLOPT_REDIR_PROTOCOLS,
1035  CURLPROTO_HTTP | CURLPROTO_HTTPS);
1036  CURL_EASY_SETOPT(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
1037  CURL_EASY_SETOPT(curl, CURLOPT_MAXREDIRS, 4);
1038  /* no need to abort if the above failed */
1039  CURL_EASY_SETOPT(curl, CURLOPT_URL, current_url);
1040  if (ret != CURLE_OK)
1041  {
1042  clean_up();
1043  return;
1044  }
1045  CURL_EASY_SETOPT(curl, CURLOPT_FAILONERROR, 1);
1046 #if 0
1047  CURL_EASY_SETOPT(curl, CURLOPT_VERBOSE, 1);
1048 #endif
1049  CURL_EASY_SETOPT(curl, CURLOPT_BUFFERSIZE, GNUNET_MAX_MESSAGE_SIZE);
1050  if (0 == strncmp(current_url, "http", 4))
1051  CURL_EASY_SETOPT(curl, CURLOPT_USERAGENT, "GNUnet");
1052  CURL_EASY_SETOPT(curl, CURLOPT_CONNECTTIMEOUT, 60L);
1053  CURL_EASY_SETOPT(curl, CURLOPT_TIMEOUT, 60L);
1054  multi = curl_multi_init();
1055  if (multi == NULL)
1056  {
1057  GNUNET_break(0);
1058  /* clean_up (); */
1059  return;
1060  }
1061  mret = curl_multi_add_handle(multi, curl);
1062  if (mret != CURLM_OK)
1063  {
1065  _("%s failed at %s:%d: `%s'\n"),
1066  "curl_multi_add_handle",
1067  __FILE__,
1068  __LINE__,
1069  curl_multi_strerror(mret));
1070  mret = curl_multi_cleanup(multi);
1071  if (mret != CURLM_OK)
1073  _("%s failed at %s:%d: `%s'\n"),
1074  "curl_multi_cleanup",
1075  __FILE__,
1076  __LINE__,
1077  curl_multi_strerror(mret));
1078  multi = NULL;
1079  clean_up();
1080  return;
1081  }
1083  download_prepare();
1084 }
1085 
1086 
1087 static void
1089 {
1090  ti_download_dispatcher_task = NULL;
1091  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Download is initiated...\n");
1093  {
1094  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Download can start immediately...\n");
1096  }
1097  else
1098  {
1100  "Download in progess, have to wait...\n");
1101  ti_download_dispatcher_task =
1104  NULL);
1105  }
1106 }
1107 
1108 
1114 static void
1115 task_check(void *cls)
1116 {
1117  static int once;
1118  struct GNUNET_TIME_Relative delay;
1119 
1120  ti_check_download = NULL;
1121  if (stats == NULL)
1122  {
1123  curl_global_cleanup();
1124  return; /* in shutdown */
1125  }
1127  (NULL == ti_download_dispatcher_task))
1128  ti_download_dispatcher_task =
1130 
1131  delay = hostlist_delay;
1132  if (0 == hostlist_delay.rel_value_us)
1134  else
1137  GNUNET_TIME_UNIT_HOURS.rel_value_us * (1 + stat_connection_count))
1138  hostlist_delay =
1140  (1 + stat_connection_count));
1141  GNUNET_STATISTICS_set(stats,
1142  gettext_noop(
1143  "# milliseconds between hostlist downloads"),
1144  hostlist_delay.rel_value_us / 1000LL,
1145  GNUNET_YES);
1146  if (0 == once)
1147  {
1148  delay = GNUNET_TIME_UNIT_ZERO;
1149  once = 1;
1150  }
1151  GNUNET_log(
1153  _("Have %u/%u connections. Will consider downloading hostlist in %s\n"),
1157  ti_check_download = GNUNET_SCHEDULER_add_delayed(delay, &task_check, NULL);
1158 }
1159 
1160 
1166 static void
1168 {
1169  ti_testing_intervall_task = NULL;
1172  "Testing new hostlist advertisements is allowed again\n");
1173 }
1174 
1175 
1181 static void
1183 {
1184  ti_saving_task = NULL;
1186 
1188  "Hostlists will be saved to file again in %s\n",
1190  GNUNET_YES));
1191  ti_saving_task =
1193 }
1194 
1195 
1203 static void *
1205  const struct GNUNET_PeerIdentity *peer,
1206  struct GNUNET_MQ_Handle *mq)
1207 {
1211  gettext_noop("# active connections"),
1212  1,
1213  GNUNET_NO);
1214  return NULL;
1215 }
1216 
1217 
1224 static void
1226  const struct GNUNET_PeerIdentity *peer,
1227  void *internal_cls)
1228 {
1232  gettext_noop("# active connections"),
1233  -1,
1234  GNUNET_NO);
1235 }
1236 
1237 
1243 static void
1245 {
1246  size_t uri_size;
1247  struct Hostlist *hostlist;
1248 
1249  uri_size = strlen(uri) + 1;
1251  "Hostlist client recieved advertisement containing URI `%s'\n",
1252  uri);
1253  if (GNUNET_NO != linked_list_contains(uri))
1254  {
1255  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "URI `%s' is already known\n", uri);
1256  return;
1257  }
1258 
1260  {
1261  GNUNET_log(
1263  "Currently not accepting new advertisements: interval between to advertisements is not reached\n");
1264  return;
1265  }
1267  {
1268  GNUNET_log(
1270  "Currently not accepting new advertisements: we are already testing a hostlist\n");
1271  return;
1272  }
1273 
1274  hostlist = GNUNET_malloc(sizeof(struct Hostlist) + uri_size);
1275  hostlist->hostlist_uri = (const char *)&hostlist[1];
1276  GNUNET_memcpy(&hostlist[1], uri, uri_size);
1278  hostlist->quality = HOSTLIST_INITIAL;
1279  hostlist_to_test = hostlist;
1280 
1283  ti_testing_intervall_task =
1286  NULL);
1287 
1289  "Testing new hostlist advertisements is locked for the next %s\n",
1291  GNUNET_YES));
1292 
1293  ti_download_dispatcher_task =
1295 }
1296 
1297 
1306 static void
1307 primary_task(void *cls, int success)
1308 {
1309  if (NULL != ti_check_download)
1310  {
1311  GNUNET_SCHEDULER_cancel(ti_check_download);
1312  ti_check_download = NULL;
1313  }
1314  sget = NULL;
1315  GNUNET_assert(NULL != stats);
1317  "Statistics request done, scheduling hostlist download\n");
1318  ti_check_download = GNUNET_SCHEDULER_add_now(&task_check, NULL);
1319 }
1320 
1321 
1330 static void
1332 {
1334  sget = NULL;
1335  ti_check_download = GNUNET_SCHEDULER_add_now(&task_check, NULL);
1336 }
1337 
1338 
1348 static int
1349 process_stat(void *cls,
1350  const char *subsystem,
1351  const char *name,
1352  uint64_t value,
1353  int is_persistent)
1354 {
1355  hostlist_delay.rel_value_us = value * 1000LL;
1357  "Initial time between hostlist downloads is %s\n",
1359  GNUNET_YES));
1360  return GNUNET_OK;
1361 }
1362 
1363 
1367 static void
1369 {
1370  char *filename;
1371  char *uri;
1372  char *emsg;
1373  struct Hostlist *hostlist;
1374  uint32_t times_used;
1375  uint32_t hellos_returned;
1376  uint64_t quality;
1377  uint64_t last_used;
1378  uint64_t created;
1379  uint32_t counter;
1380  struct GNUNET_BIO_ReadHandle *rh;
1381 
1382  uri = NULL;
1384  "HOSTLIST",
1385  "HOSTLISTFILE",
1386  &filename))
1387  {
1389  "hostlist",
1390  "HOSTLISTFILE");
1391  return;
1392  }
1393 
1395  _("Loading saved hostlist entries from file `%s' \n"),
1396  filename);
1397  if (GNUNET_NO == GNUNET_DISK_file_test(filename))
1398  {
1400  _("Hostlist file `%s' does not exist\n"),
1401  filename);
1402  GNUNET_free(filename);
1403  return;
1404  }
1405 
1406  rh = GNUNET_BIO_read_open(filename);
1407  if (NULL == rh)
1408  {
1410  _(
1411  "Could not open file `%s' for reading to load hostlists: %s\n"),
1412  filename,
1413  strerror(errno));
1414  GNUNET_free(filename);
1415  return;
1416  }
1417 
1418  counter = 0;
1419  while ((GNUNET_OK == GNUNET_BIO_read_string(rh, "url", &uri, MAX_URL_LEN)) &&
1420  (NULL != uri) &&
1421  (GNUNET_OK == GNUNET_BIO_read_int32(rh, &times_used)) &&
1422  (GNUNET_OK == GNUNET_BIO_read_int64(rh, &quality)) &&
1423  (GNUNET_OK == GNUNET_BIO_read_int64(rh, &last_used)) &&
1424  (GNUNET_OK == GNUNET_BIO_read_int64(rh, &created)) &&
1425  (GNUNET_OK == GNUNET_BIO_read_int32(rh, &hellos_returned)))
1426  {
1427  hostlist = GNUNET_malloc(sizeof(struct Hostlist) + strlen(uri) + 1);
1428  hostlist->hello_count = hellos_returned;
1429  hostlist->hostlist_uri = (const char *)&hostlist[1];
1430  GNUNET_memcpy(&hostlist[1], uri, strlen(uri) + 1);
1431  hostlist->quality = quality;
1432  hostlist->time_creation.abs_value_us = created;
1433  hostlist->time_last_usage.abs_value_us = last_used;
1434  GNUNET_CONTAINER_DLL_insert(linked_list_head, linked_list_tail, hostlist);
1435  linked_list_size++;
1437  "Added hostlist entry eith URI `%s' \n",
1438  hostlist->hostlist_uri);
1439  GNUNET_free(uri);
1440  uri = NULL;
1441  counter++;
1442  if (counter >= MAX_NUMBER_HOSTLISTS)
1443  break;
1444  }
1445 
1447  _("%u hostlist URIs loaded from file\n"),
1448  counter);
1449  GNUNET_STATISTICS_set(stats,
1450  gettext_noop("# hostlist URIs read from file"),
1451  counter,
1452  GNUNET_YES);
1453  GNUNET_STATISTICS_set(stats,
1454  gettext_noop("# advertised hostlist URIs"),
1456  GNUNET_NO);
1457 
1458  GNUNET_free_non_null(uri);
1459  emsg = NULL;
1460  (void)GNUNET_BIO_read_close(rh, &emsg);
1461  if (emsg != NULL)
1462  GNUNET_free(emsg);
1463  GNUNET_free(filename);
1464 }
1465 
1466 
1472 static void
1473 save_hostlist_file(int shutdown)
1474 {
1475  char *filename;
1476  struct Hostlist *pos;
1477  struct GNUNET_BIO_WriteHandle *wh;
1478  int ok;
1479  uint32_t counter;
1480 
1482  "HOSTLIST",
1483  "HOSTLISTFILE",
1484  &filename))
1485  {
1487  "hostlist",
1488  "HOSTLISTFILE");
1489  return;
1490  }
1492  {
1493  GNUNET_free(filename);
1494  return;
1495  }
1496  wh = GNUNET_BIO_write_open(filename);
1497  if (NULL == wh)
1498  {
1500  _(
1501  "Could not open file `%s' for writing to save hostlists: %s\n"),
1502  filename,
1503  strerror(errno));
1504  GNUNET_free(filename);
1505  return;
1506  }
1508  _("Writing %u hostlist URIs to `%s'\n"),
1510  filename);
1511  /* add code to write hostlists to file using bio */
1512  ok = GNUNET_YES;
1513  counter = 0;
1514  while (NULL != (pos = linked_list_head))
1515  {
1516  if (GNUNET_YES == shutdown)
1517  {
1518  GNUNET_CONTAINER_DLL_remove(linked_list_head, linked_list_tail, pos);
1519  linked_list_size--;
1520  }
1521  if (GNUNET_YES == ok)
1522  {
1523  if ((GNUNET_OK != GNUNET_BIO_write_string(wh, pos->hostlist_uri)) ||
1524  (GNUNET_OK != GNUNET_BIO_write_int32(wh, pos->times_used)) ||
1525  (GNUNET_OK != GNUNET_BIO_write_int64(wh, pos->quality)) ||
1526  (GNUNET_OK !=
1528  (GNUNET_OK !=
1531  {
1533  _("Error writing hostlist URIs to file `%s'\n"),
1534  filename);
1535  ok = GNUNET_NO;
1536  }
1537  }
1538 
1539  if (GNUNET_YES == shutdown)
1540  GNUNET_free(pos);
1541  counter++;
1542  if (counter >= MAX_NUMBER_HOSTLISTS)
1543  break;
1544  }
1545  GNUNET_STATISTICS_set(stats,
1546  gettext_noop("# hostlist URIs written to file"),
1547  counter,
1548  GNUNET_YES);
1549 
1550  if (GNUNET_OK != GNUNET_BIO_write_close(wh))
1552  _("Error writing hostlist URIs to file `%s'\n"),
1553  filename);
1554  GNUNET_free(filename);
1555 }
1556 
1557 
1569 int
1571  struct GNUNET_STATISTICS_Handle *st,
1575  int learn)
1576 {
1577  char *filename;
1578  char *proxytype_str;
1579  int result;
1580 
1581  GNUNET_assert(NULL != st);
1582  if (0 != curl_global_init(CURL_GLOBAL_WIN32))
1583  {
1584  GNUNET_break(0);
1585  return GNUNET_SYSERR;
1586  }
1587  cfg = c;
1588  stats = st;
1589 
1590  /* Read proxy configuration */
1591  pi = GNUNET_PEERINFO_connect(c);
1592  if (GNUNET_OK ==
1593  GNUNET_CONFIGURATION_get_value_string(cfg, "HOSTLIST", "PROXY", &proxy))
1594  {
1595  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found proxy host: `%s'\n", proxy);
1596  /* proxy username */
1598  "HOSTLIST",
1599  "PROXY_USERNAME",
1600  &proxy_username))
1601  {
1603  "Found proxy username name: `%s'\n",
1604  proxy_username);
1605  }
1606 
1607  /* proxy password */
1609  "HOSTLIST",
1610  "PROXY_PASSWORD",
1611  &proxy_password))
1612  {
1614  "Found proxy password name: `%s'\n",
1615  proxy_password);
1616  }
1617 
1618  /* proxy type */
1620  "HOSTLIST",
1621  "PROXY_TYPE",
1622  &proxytype_str))
1623  {
1624  GNUNET_STRINGS_utf8_toupper(proxytype_str, proxytype_str);
1625  proxy_type = CURLPROXY_HTTP;
1626  if (0 == strcmp(proxytype_str, "HTTP"))
1627  proxy_type = CURLPROXY_HTTP;
1628  else if (0 == strcmp(proxytype_str, "HTTP_1_0"))
1629  proxy_type = CURLPROXY_HTTP_1_0;
1630  else if (0 == strcmp(proxytype_str, "SOCKS4"))
1631  proxy_type = CURLPROXY_SOCKS4;
1632  else if (0 == strcmp(proxytype_str, "SOCKS5"))
1633  proxy_type = CURLPROXY_SOCKS5;
1634  else if (0 == strcmp(proxytype_str, "SOCKS4A"))
1635  proxy_type = CURLPROXY_SOCKS4A;
1636  else if (0 == strcmp(proxytype_str, "SOCKS5_HOSTNAME"))
1637  proxy_type = CURLPROXY_SOCKS5_HOSTNAME;
1638  else
1639  {
1640  GNUNET_log(
1642  _(
1643  "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"),
1644  proxytype_str);
1645  GNUNET_free(proxytype_str);
1646  GNUNET_free(proxy);
1647  proxy = NULL;
1649  proxy_username = NULL;
1651  proxy_password = NULL;
1652 
1653  return GNUNET_SYSERR;
1654  }
1655  }
1656  GNUNET_free_non_null(proxytype_str);
1657  }
1658 
1659  stat_learning = learn;
1660  *ch = &handler_connect;
1661  *dh = &handler_disconnect;
1662  linked_list_head = NULL;
1663  linked_list_tail = NULL;
1667 
1668  if (GNUNET_YES == stat_learning)
1669  {
1670  *msgh = &handler_advertisement;
1672  _("Learning is enabled on this peer\n"));
1675  "Hostlists will be saved to file again in %s\n",
1677  GNUNET_YES));
1680  NULL);
1681  }
1682  else
1683  {
1685  _("Learning is not enabled on this peer\n"));
1686  *msgh = NULL;
1688  "HOSTLIST",
1689  "HOSTLISTFILE",
1690  &filename))
1691  {
1692  if (GNUNET_YES == GNUNET_DISK_file_test(filename))
1693  {
1694  result = remove(filename);
1695  if (0 == result)
1696  GNUNET_log(
1698  _(
1699  "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"),
1700  filename);
1701  else
1703  "remove",
1704  filename);
1705  }
1706  }
1707  GNUNET_free(filename);
1708  }
1710  "Loading stats value on hostlist download frequency\n");
1711  sget = GNUNET_STATISTICS_get(stats,
1712  "hostlist",
1713  gettext_noop(
1714  "# milliseconds between hostlist downloads"),
1715  &primary_task,
1716  &process_stat,
1717  NULL);
1718  if (NULL == sget)
1719  {
1721  "Statistics request failed, scheduling hostlist download\n");
1722  ti_check_download = GNUNET_SCHEDULER_add_now(&task_check, NULL);
1723  }
1724  else
1725  {
1728  NULL);
1729  }
1730  return GNUNET_OK;
1731 }
1732 
1733 
1737 void
1739 {
1740  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Hostlist client shutdown\n");
1741  if (NULL != sget)
1742  {
1744  sget = NULL;
1745  }
1746  stats = NULL;
1747  if (GNUNET_YES == stat_learning)
1749  if (NULL != ti_saving_task)
1750  {
1751  GNUNET_SCHEDULER_cancel(ti_saving_task);
1752  ti_saving_task = NULL;
1753  }
1754  if (NULL != ti_download_dispatcher_task)
1755  {
1756  GNUNET_SCHEDULER_cancel(ti_download_dispatcher_task);
1757  ti_download_dispatcher_task = NULL;
1758  }
1759  if (NULL != ti_testing_intervall_task)
1760  {
1761  GNUNET_SCHEDULER_cancel(ti_testing_intervall_task);
1762  ti_testing_intervall_task = NULL;
1763  }
1764  if (NULL != ti_download)
1765  {
1766  GNUNET_SCHEDULER_cancel(ti_download);
1767  ti_download = NULL;
1768  update_hostlist();
1769  clean_up();
1770  }
1771  if (NULL != ti_check_download)
1772  {
1773  GNUNET_SCHEDULER_cancel(ti_check_download);
1774  ti_check_download = NULL;
1775  curl_global_cleanup();
1776  }
1778  proxy = NULL;
1780  proxy_username = NULL;
1782  proxy_password = NULL;
1783  if (NULL != pi)
1784  {
1786  pi = NULL;
1787  }
1788  cfg = NULL;
1789 }
1790 
1791 /* 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:541
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:83
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:128
#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:521
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:597
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).
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
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.
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:118
#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:1108
#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:93
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:1254
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:1237
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1238
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:577
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
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:1264
#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:686
static int once
Global to mark if we&#39;ve run the initialization.
Definition: gnsrecord.c:67
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:1784
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:440
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:378
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:552
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:232
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:66
#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.
const char * name
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:436
#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:84
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:83
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open(const char *fn)
Open a file for writing.
Definition: bio.c:408
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:131
#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:643
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:154
int GNUNET_BIO_write_int32(struct GNUNET_BIO_WriteHandle *h, int32_t i)
Write an (u)int32_t.
Definition: bio.c:580
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:956