[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r33489 - gnunet/src/hostlist
From: |
gnunet |
Subject: |
[GNUnet-SVN] r33489 - gnunet/src/hostlist |
Date: |
Tue, 3 Jun 2014 10:41:00 +0200 |
Author: grothoff
Date: 2014-06-03 10:41:00 +0200 (Tue, 03 Jun 2014)
New Revision: 33489
Added:
gnunet/src/hostlist/gnunet-daemon-hostlist_client.c
gnunet/src/hostlist/gnunet-daemon-hostlist_client.h
gnunet/src/hostlist/gnunet-daemon-hostlist_server.c
gnunet/src/hostlist/gnunet-daemon-hostlist_server.h
Removed:
gnunet/src/hostlist/hostlist-client.c
gnunet/src/hostlist/hostlist-client.h
gnunet/src/hostlist/hostlist-server.c
gnunet/src/hostlist/hostlist-server.h
Modified:
gnunet/src/hostlist/Makefile.am
gnunet/src/hostlist/gnunet-daemon-hostlist.c
gnunet/src/hostlist/gnunet-daemon-hostlist.h
gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c
Log:
-doxygen, code cleanup
Modified: gnunet/src/hostlist/Makefile.am
===================================================================
--- gnunet/src/hostlist/Makefile.am 2014-06-03 08:19:03 UTC (rev 33488)
+++ gnunet/src/hostlist/Makefile.am 2014-06-03 08:41:00 UTC (rev 33489)
@@ -12,7 +12,8 @@
endif
if HAVE_MHD
- HOSTLIST_SERVER_SOURCES = hostlist-server.c hostlist-server.h
+ HOSTLIST_SERVER_SOURCES = \
+ gnunet-daemon-hostlist_server.c gnunet-daemon-hostlist_server.h
GN_LIBMHD = -lmicrohttpd
endif
@@ -23,7 +24,7 @@
gnunet_daemon_hostlist_SOURCES = \
gnunet-daemon-hostlist.c gnunet-daemon-hostlist.h \
- hostlist-client.c hostlist-client.h \
+ gnunet-daemon-hostlist_client.c gnunet-daemon-hostlist_client.h \
$(HOSTLIST_SERVER_SOURCES)
gnunet_daemon_hostlist_LDADD = \
Modified: gnunet/src/hostlist/gnunet-daemon-hostlist.c
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist.c 2014-06-03 08:19:03 UTC
(rev 33488)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist.c 2014-06-03 08:41:00 UTC
(rev 33489)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
+ (C) 2007, 2008, 2009, 2014 Christian Grothoff (and other contributing
authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -23,10 +23,8 @@
* @brief code for bootstrapping via hostlist servers
* @author Christian Grothoff
*/
-
-#include <stdlib.h>
#include "platform.h"
-#include "hostlist-client.h"
+#include "gnunet-daemon-hostlist_client.h"
#include "gnunet_core_service.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
@@ -34,7 +32,7 @@
#if HAVE_MHD
-#include "hostlist-server.h"
+#include "gnunet-daemon-hostlist_server.h"
/**
* Set if we are allowed to advertise our hostlist to others.
@@ -123,9 +121,19 @@
};
GNUNET_NETWORK_STRUCT_END
+
+/**
+ * Our own peer identity.
+ */
static struct GNUNET_PeerIdentity me;
+/**
+ * Callback invoked once our connection to CORE service is up.
+ *
+ * @param cls NULL
+ * @param my_identity our peer's identity
+ */
static void
core_init (void *cls,
const struct GNUNET_PeerIdentity *my_identity)
@@ -143,7 +151,8 @@
* @return #GNUNET_OK on success
*/
static int
-advertisement_handler (void *cls, const struct GNUNET_PeerIdentity *peer,
+advertisement_handler (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_MessageHeader *message)
{
GNUNET_assert (NULL != client_adv_handler);
@@ -182,7 +191,8 @@
* @param peer peer identity this notification is about
*/
static void
-disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
+disconnect_handler (void *cls,
+ const struct GNUNET_PeerIdentity *peer)
{
if (0 == memcmp (&me, peer, sizeof (struct GNUNET_PeerIdentity)))
return;
@@ -200,13 +210,17 @@
/**
* Last task run during shutdown. Disconnects us from
* the other services.
+ *
+ * @param cls NULL
+ * @param tc scheduler context
*/
static void
-cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+cleaning_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Hostlist daemon is shutting down\n");
- if (core != NULL)
+ if (NULL != core)
{
GNUNET_CORE_disconnect (core);
core = NULL;
@@ -221,7 +235,7 @@
GNUNET_HOSTLIST_server_stop ();
}
#endif
- if (stats != NULL)
+ if (NULL != stats)
{
GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
stats = NULL;
@@ -238,7 +252,9 @@
* @param cfg configuration
*/
static void
-run (void *cls, char *const *args, const char *cfgfile,
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
static const struct GNUNET_CORE_MessageHandler learn_handlers[] = {
@@ -248,15 +264,14 @@
static const struct GNUNET_CORE_MessageHandler no_learn_handlers[] = {
{NULL, 0, 0}
};
- if ((!bootstrapping) && (!learning)
+ if ((! bootstrapping) && (! learning)
#if HAVE_MHD
- && (!provide_hostlist)
+ && (! provide_hostlist)
#endif
)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("None of the functions for the hostlist daemon were enabled.
I have no reason to run!\n"));
+ _("None of the functions for the hostlist daemon were enabled.
I have no reason to run!\n"));
return;
}
stats = GNUNET_STATISTICS_create ("hostlist", cfg);
@@ -332,7 +347,8 @@
ret =
(GNUNET_OK ==
GNUNET_PROGRAM_run (argc, argv, "hostlist",
- _("GNUnet hostlist server and client"), options,
+ _("GNUnet hostlist server and client"),
+ options,
&run, NULL)) ? 0 : 1;
GNUNET_free ((void*) argv);
return ret;
Modified: gnunet/src/hostlist/gnunet-daemon-hostlist.h
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist.h 2014-06-03 08:19:03 UTC
(rev 33488)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist.h 2014-06-03 08:41:00 UTC
(rev 33489)
@@ -25,23 +25,19 @@
*/
#include <stdlib.h>
#include "platform.h"
-#include "hostlist-client.h"
-#include "hostlist-server.h"
#include "gnunet_core_service.h"
-#include "gnunet_getopt_lib.h"
#include "gnunet_protocols.h"
-#include "gnunet_program_lib.h"
#include "gnunet_statistics_service.h"
-#include "gnunet_strings_lib.h"
-#include "gnunet_time_lib.h"
#include "gnunet_util_lib.h"
/**
- * General hostlist daemon debugging.
+ * How long can hostlist URLs be?
*/
-#define DEBUG_HOSTLIST GNUNET_EXTRA_LOGGING
+#define MAX_URL_LEN 1000
-#define MAX_URL_LEN 1000
+/**
+ * How many bytes do we download at most from a hostlist server?
+ */
#define MAX_BYTES_PER_HOSTLISTS 500000
/* end of gnunet-daemon-hostlist.h */
Copied: gnunet/src/hostlist/gnunet-daemon-hostlist_client.c (from rev 33486,
gnunet/src/hostlist/hostlist-client.c)
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist_client.c
(rev 0)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist_client.c 2014-06-03 08:41:00 UTC
(rev 33489)
@@ -0,0 +1,1710 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001-2010, 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file hostlist/gnunet-daemon-hostlist_client.c
+ * @brief hostlist support. Downloads HELLOs via HTTP.
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet-daemon-hostlist_client.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_transport_service.h"
+#include "gnunet-daemon-hostlist.h"
+#include <curl/curl.h>
+
+
+/**
+ * Number of connections that we must have to NOT download
+ * hostlists anymore.
+ */
+#define MIN_CONNECTIONS 4
+
+/**
+ * Maximum number of hostlist that are saved
+ */
+#define MAX_NUMBER_HOSTLISTS 30
+
+/**
+ * Time interval hostlists are saved to disk
+ */
+#define SAVING_INTERVAL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_MINUTES, 30)
+
+/**
+ * Time interval between two hostlist tests
+ */
+#define TESTING_INTERVAL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 3)
+
+/**
+ * Time interval for download dispatcher before a download is re-scheduled
+ */
+#define WAITING_INTERVAL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 1)
+
+/**
+ * Defines concerning the hostlist quality metric
+ */
+
+/**
+ * Initial quality of a new created hostlist
+ */
+#define HOSTLIST_INITIAL 10000
+
+/**
+ * Value subtracted each time a hostlist download fails
+ */
+#define HOSTLIST_FAILED_DOWNLOAD 100
+
+/**
+ * Value added each time a hostlist download is successful
+ */
+#define HOSTLIST_SUCCESSFUL_DOWNLOAD 100
+
+/**
+ * Value added for each valid HELLO recived during a hostlist download
+ */
+#define HOSTLIST_SUCCESSFUL_HELLO 1
+
+
+
+/**
+ * A single hostlist obtained by hostlist advertisements
+ */
+struct Hostlist
+{
+ /**
+ * previous entry, used to manage entries in a double linked list
+ */
+ struct Hostlist *prev;
+
+ /**
+ * next entry, used to manage entries in a double linked list
+ */
+ struct Hostlist *next;
+
+ /**
+ * URI where hostlist can be obtained
+ */
+ const char *hostlist_uri;
+
+ /**
+ * Value describing the quality of the hostlist, the bigger the better but
(should) never < 0
+ * used for deciding which hostlist is replaced if MAX_NUMBER_HOSTLISTS in
data structure is reached
+ * intial value = HOSTLIST_INITIAL
+ * increased every successful download by HOSTLIST_SUCCESSFULL_DOWNLOAD
+ * increased every successful download by number of obtained HELLO messages
+ * decreased every failed download by HOSTLIST_SUCCESSFULL_DOWNLOAD
+ */
+ uint64_t quality;
+
+ /**
+ * Time the hostlist advertisement was recieved and the entry was created
+ */
+ struct GNUNET_TIME_Absolute time_creation;
+
+ /**
+ * Last time the hostlist was obtained
+ */
+ struct GNUNET_TIME_Absolute time_last_usage;
+
+ /**
+ * Number of HELLO messages obtained during last download
+ */
+ uint32_t hello_count;
+
+ /**
+ * Number of times the hostlist was successfully obtained
+ */
+ uint32_t times_used;
+
+};
+
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Statistics handle.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Transport handle.
+ */
+static struct GNUNET_TRANSPORT_Handle *transport;
+
+/**
+ * Proxy hostname or ip we are using (can be NULL).
+ */
+static char *proxy;
+
+/**
+ * Proxy username we are using (can be NULL).
+ */
+static char *proxy_username;
+
+/**
+ * Proxy password we are using (can be NULL).
+ */
+static char *proxy_password;
+
+/**
+ * Proxy type we are using (can be NULL).
+ */
+static curl_proxytype proxy_type;
+
+/**
+ * Number of bytes valid in 'download_buffer'.
+ */
+static size_t download_pos;
+
+/**
+ * Current URL that we are using.
+ */
+static char *current_url;
+
+/**
+ * Current CURL handle.
+ */
+static CURL *curl;
+
+/**
+ * Current multi-CURL handle.
+ */
+static CURLM *multi;
+
+/**
+ * How many bytes did we download from the current hostlist URL?
+ */
+static uint32_t stat_bytes_downloaded;
+
+/**
+ * Amount of time we wait between hostlist downloads.
+ */
+static struct GNUNET_TIME_Relative hostlist_delay;
+
+/**
+ * ID of the task, checking if hostlist download should take plate
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_check_download;
+
+/**
+ * ID of the task downloading the hostlist
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_download;
+
+/**
+ * ID of the task saving the hostlsit in a regular intervall
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_saving_task;
+
+/**
+ * ID of the task called to initiate a download
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_download_dispatcher_task;
+
+/**
+ * ID of the task controlling the locking between two hostlist tests
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_testing_intervall_task;
+
+/**
+ * At what time MUST the current hostlist request be done?
+ */
+static struct GNUNET_TIME_Absolute end_time;
+
+/**
+ * Head of the linked list used to store hostlists
+ */
+static struct Hostlist *linked_list_head;
+
+/**
+ * Tail of the linked list used to store hostlists
+ */
+static struct Hostlist *linked_list_tail;
+
+/**
+ * Current hostlist used for downloading
+ */
+static struct Hostlist *current_hostlist;
+
+/**
+ * Size of the linke list used to store hostlists
+ */
+static unsigned int linked_list_size;
+
+/**
+ * Head of the linked list used to store hostlists
+ */
+static struct Hostlist *hostlist_to_test;
+
+/**
+ * Handle for our statistics GET operation.
+ */
+static struct GNUNET_STATISTICS_GetHandle *sget;
+
+/**
+ * Set to GNUNET_YES if the current URL had some problems.
+ */
+static int stat_bogus_url;
+
+/**
+ * Value controlling if a hostlist is tested at the moment
+ */
+static int stat_testing_hostlist;
+
+/**
+ * Value controlling if a hostlist testing is allowed at the moment
+ */
+static int stat_testing_allowed;
+
+/**
+ * Value controlling if a hostlist download is running at the moment
+ */
+static int stat_download_in_progress;
+
+/**
+ * Value saying if a preconfigured bootstrap server is used
+ */
+static unsigned int stat_use_bootstrap;
+
+/**
+ * Set if we are allowed to learn new hostlists and use them
+ */
+static int stat_learning;
+
+/**
+ * Value saying if hostlist download was successful
+ */
+static unsigned int stat_download_successful;
+
+/**
+ * Value saying how many valid HELLO messages were obtained during download
+ */
+static unsigned int stat_hellos_obtained;
+
+/**
+ * Number of active connections (according to core service).
+ */
+static unsigned int stat_connection_count;
+
+
+/**
+ * Process downloaded bits by calling callback on each HELLO.
+ *
+ * @param ptr buffer with downloaded data
+ * @param size size of a record
+ * @param nmemb number of records downloaded
+ * @param ctx unused
+ * @return number of bytes that were processed (always size*nmemb)
+ */
+static size_t
+callback_download (void *ptr,
+ size_t size,
+ size_t nmemb,
+ void *ctx)
+{
+ static char download_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+ const char *cbuf = ptr;
+ const struct GNUNET_MessageHeader *msg;
+ size_t total;
+ size_t cpy;
+ size_t left;
+ uint16_t msize;
+
+ total = size * nmemb;
+ stat_bytes_downloaded += total;
+ if ((total == 0) || (stat_bogus_url))
+ {
+ return total; /* ok, no data or bogus data */
+ }
+
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("# bytes downloaded from hostlist servers"),
+ (int64_t) total, GNUNET_NO);
+ left = total;
+ while ((left > 0) || (download_pos > 0))
+ {
+ cpy = GNUNET_MIN (left, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - download_pos);
+ memcpy (&download_buffer[download_pos], cbuf, cpy);
+ cbuf += cpy;
+ download_pos += cpy;
+ left -= cpy;
+ if (download_pos < sizeof (struct GNUNET_MessageHeader))
+ {
+ GNUNET_assert (0 == left);
+ break;
+ }
+ msg = (const struct GNUNET_MessageHeader *) download_buffer;
+ msize = ntohs (msg->size);
+ if (msize < sizeof (struct GNUNET_MessageHeader))
+ {
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("# invalid HELLOs downloaded from hostlist
servers"),
+ 1, GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Invalid `%s' message received from hostlist at `%s'\n"),
+ "HELLO", current_url);
+ stat_hellos_obtained++;
+ stat_bogus_url = 1;
+ return total;
+ }
+ if (download_pos < msize)
+ {
+ GNUNET_assert (left == 0);
+ break;
+ }
+ if (GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) msg) == msize)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received valid `%s' message from hostlist server.\n",
+ "HELLO");
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("# valid HELLOs downloaded from hostlist
servers"),
+ 1, GNUNET_NO);
+ stat_hellos_obtained++;
+ GNUNET_TRANSPORT_offer_hello (transport, msg, NULL, NULL);
+ }
+ else
+ {
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("# invalid HELLOs downloaded from hostlist
servers"),
+ 1, GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Invalid `%s' message received from hostlist at `%s'\n"),
+ "HELLO", current_url);
+ stat_bogus_url = GNUNET_YES;
+ stat_hellos_obtained++;
+ return total;
+ }
+ memmove (download_buffer, &download_buffer[msize], download_pos - msize);
+ download_pos -= msize;
+ }
+ return total;
+}
+
+
+/**
+ * Obtain a hostlist URL that we should use.
+ *
+ * @return NULL if there is no URL available
+ */
+static char *
+get_bootstrap_server ()
+{
+ char *servers;
+ char *ret;
+ size_t urls;
+ size_t pos;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST", "SERVERS",
+ &servers))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ "hostlist", "SERVERS");
+ return NULL;
+ }
+
+ urls = 0;
+ if (strlen (servers) > 0)
+ {
+ urls++;
+ pos = strlen (servers) - 1;
+ while (pos > 0)
+ {
+ if (servers[pos] == ' ')
+ urls++;
+ pos--;
+ }
+ }
+ if (urls == 0)
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ "hostlist", "SERVERS");
+ GNUNET_free (servers);
+ return NULL;
+ }
+
+ urls = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, urls) + 1;
+ pos = strlen (servers) - 1;
+ while (pos > 0)
+ {
+ if (servers[pos] == ' ')
+ {
+ urls--;
+ servers[pos] = '\0';
+ }
+ if (urls == 0)
+ {
+ pos++;
+ break;
+ }
+ pos--;
+ }
+ ret = GNUNET_strdup (&servers[pos]);
+ GNUNET_free (servers);
+ return ret;
+}
+
+
+/**
+ * Method deciding if a preconfigured or advertisied hostlist is used on a
50:50 ratio
+ * @return uri to use, NULL if there is no URL available
+ */
+static char *
+download_get_url ()
+{
+ uint32_t index;
+ unsigned int counter;
+ struct Hostlist *pos;
+
+ if (GNUNET_NO == stat_learning)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Using preconfigured bootstrap server\n");
+ current_hostlist = NULL;
+ return get_bootstrap_server ();
+ }
+
+ if ((GNUNET_YES == stat_testing_hostlist) && (NULL != hostlist_to_test))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Testing new advertised hostlist if it is obtainable\n");
+ current_hostlist = hostlist_to_test;
+ return GNUNET_strdup (hostlist_to_test->hostlist_uri);
+ }
+
+ if ((GNUNET_YES == stat_use_bootstrap) || (linked_list_size == 0))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Using preconfigured bootstrap server\n");
+ current_hostlist = NULL;
+ return get_bootstrap_server ();
+ }
+ index =
+ GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, linked_list_size);
+ counter = 0;
+ pos = linked_list_head;
+ while (counter < index)
+ {
+ pos = pos->next;
+ counter++;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using learned hostlist `%s'\n",
+ pos->hostlist_uri);
+ current_hostlist = pos;
+ return GNUNET_strdup (pos->hostlist_uri);
+}
+
+
+#define CURL_EASY_SETOPT(c, a, b) do { ret = curl_easy_setopt (c, a, b); if
(CURLE_OK != ret) GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("%s failed at %s:%d:
`%s'\n"), "curl_easy_setopt", __FILE__, __LINE__, curl_easy_strerror (ret)); }
while (0)
+
+
+/**
+ * Method to save hostlist to a file during hostlist client shutdown
+ *
+ * @param shutdown set if called because of shutdown, entries in linked list
will be destroyed
+ */
+static void
+save_hostlist_file (int shutdown);
+
+
+/**
+ * Add val2 to val1 with overflow check
+ *
+ * @param val1 value 1
+ * @param val2 value 2
+ * @return result
+ */
+static uint64_t
+checked_add (uint64_t val1,
+ uint64_t val2)
+{
+ static uint64_t temp;
+ static uint64_t maxv;
+
+ maxv = 0;
+ maxv--;
+
+ temp = val1 + val2;
+ if (temp < val1)
+ return maxv;
+ return temp;
+}
+
+
+/**
+ * Subtract val2 from val1 with underflow check
+ *
+ * @param val1 value 1
+ * @param val2 value 2
+ * @return result
+ */
+static uint64_t
+checked_sub (uint64_t val1,
+ uint64_t val2)
+{
+ if (val1 <= val2)
+ return 0;
+ return (val1 - val2);
+}
+
+
+/**
+ * Method to check if a URI is in hostlist linked list
+ *
+ * @param uri uri to check
+ * @return #GNUNET_YES if existing in linked list, #GNUNET_NO if not
+ */
+static int
+linked_list_contains (const char *uri)
+{
+ struct Hostlist *pos;
+
+ pos = linked_list_head;
+ while (pos != NULL)
+ {
+ if (0 == strcmp (pos->hostlist_uri, uri))
+ return GNUNET_YES;
+ pos = pos->next;
+ }
+ return GNUNET_NO;
+}
+
+
+/**
+ * Method returning the hostlist element with the lowest quality in the
datastore
+ * @return hostlist with lowest quality
+ */
+static struct Hostlist *
+linked_list_get_lowest_quality ()
+{
+ struct Hostlist *pos;
+ struct Hostlist *lowest;
+
+ if (linked_list_size == 0)
+ return NULL;
+ lowest = linked_list_head;
+ pos = linked_list_head->next;
+ while (pos != NULL)
+ {
+ if (pos->quality < lowest->quality)
+ lowest = pos;
+ pos = pos->next;
+ }
+ return lowest;
+}
+
+
+/**
+ * Method to insert a hostlist into the datastore. If datastore
+ * contains maximum number of elements, the elements with lowest
+ * quality is dismissed
+ */
+static void
+insert_hostlist ()
+{
+ struct Hostlist *lowest_quality;
+
+ if (MAX_NUMBER_HOSTLISTS <= linked_list_size)
+ {
+ /* No free entries available, replace existing entry */
+ lowest_quality = linked_list_get_lowest_quality ();
+ GNUNET_assert (lowest_quality != NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Removing hostlist with URI `%s' which has the worst quality
of all (%llu)\n",
+ lowest_quality->hostlist_uri,
+ (unsigned long long) lowest_quality->quality);
+ GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail,
+ lowest_quality);
+ linked_list_size--;
+ GNUNET_free (lowest_quality);
+ }
+ GNUNET_CONTAINER_DLL_insert (linked_list_head, linked_list_tail,
+ hostlist_to_test);
+ linked_list_size++;
+ GNUNET_STATISTICS_set (stats, gettext_noop ("# advertised hostlist URIs"),
+ linked_list_size, GNUNET_NO);
+ stat_testing_hostlist = GNUNET_NO;
+}
+
+
+/**
+ * Method updating hostlist statistics
+ */
+static void
+update_hostlist ()
+{
+ char *stat;
+
+ if (((stat_use_bootstrap == GNUNET_NO) && (NULL != current_hostlist)) ||
+ ((stat_testing_hostlist == GNUNET_YES) && (NULL != current_hostlist)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Updating hostlist statics for URI `%s'\n",
+ current_hostlist->hostlist_uri);
+ current_hostlist->hello_count = stat_hellos_obtained;
+ current_hostlist->time_last_usage = GNUNET_TIME_absolute_get ();
+ current_hostlist->quality =
+ checked_add (current_hostlist->quality,
+ (stat_hellos_obtained * HOSTLIST_SUCCESSFUL_HELLO));
+ if (GNUNET_YES == stat_download_successful)
+ {
+ current_hostlist->times_used++;
+ current_hostlist->quality =
+ checked_add (current_hostlist->quality,
HOSTLIST_SUCCESSFUL_DOWNLOAD);
+ GNUNET_asprintf (&stat, gettext_noop ("# advertised URI `%s'
downloaded"),
+ current_hostlist->hostlist_uri);
+
+ GNUNET_STATISTICS_update (stats, stat, 1, GNUNET_YES);
+ GNUNET_free (stat);
+ }
+ else
+ current_hostlist->quality =
+ checked_sub (current_hostlist->quality, HOSTLIST_FAILED_DOWNLOAD);
+ }
+ current_hostlist = NULL;
+ /* Alternating the usage of preconfigured and learned hostlists */
+
+ if (stat_testing_hostlist == GNUNET_YES)
+ return;
+
+ if (GNUNET_YES == stat_learning)
+ {
+ if (stat_use_bootstrap == GNUNET_YES)
+ stat_use_bootstrap = GNUNET_NO;
+ else
+ stat_use_bootstrap = GNUNET_YES;
+ }
+ else
+ stat_use_bootstrap = GNUNET_YES;
+}
+
+
+/**
+ * Clean up the state from the task that downloaded the
+ * hostlist and schedule the next task.
+ */
+static void
+clean_up ()
+{
+ CURLMcode mret;
+
+ if ((stat_testing_hostlist == GNUNET_YES) &&
+ (GNUNET_NO == stat_download_successful) && (NULL != hostlist_to_test))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _
+ ("Advertised hostlist with URI `%s' could not be downloaded.
Advertised URI gets dismissed.\n"),
+ hostlist_to_test->hostlist_uri);
+ }
+
+ if (stat_testing_hostlist == GNUNET_YES)
+ {
+ stat_testing_hostlist = GNUNET_NO;
+ }
+ if (NULL != hostlist_to_test)
+ {
+ GNUNET_free (hostlist_to_test);
+ hostlist_to_test = NULL;
+ }
+
+ if (multi != NULL)
+ {
+ mret = curl_multi_remove_handle (multi, curl);
+ if (mret != CURLM_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
+ "curl_multi_remove_handle", __FILE__, __LINE__,
+ curl_multi_strerror (mret));
+ }
+ mret = curl_multi_cleanup (multi);
+ if (mret != CURLM_OK)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
+ "curl_multi_cleanup", __FILE__, __LINE__,
+ curl_multi_strerror (mret));
+ multi = NULL;
+ }
+ if (curl != NULL)
+ {
+ curl_easy_cleanup (curl);
+ curl = NULL;
+ }
+ GNUNET_free_non_null (current_url);
+ current_url = NULL;
+ stat_bytes_downloaded = 0;
+ stat_download_in_progress = GNUNET_NO;
+}
+
+
+/**
+ * Task that is run when we are ready to receive more data from the hostlist
+ * server.
+ *
+ * @param cls closure, unused
+ * @param tc task context, unused
+ */
+static void
+task_download (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Ask CURL for the select set and then schedule the
+ * receiving task with the scheduler.
+ */
+static void
+download_prepare ()
+{
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ struct GNUNET_NETWORK_FDSet *grs;
+ struct GNUNET_NETWORK_FDSet *gws;
+ long timeout;
+ struct GNUNET_TIME_Relative rtime;
+
+ max = -1;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
+ "curl_multi_fdset", __FILE__, __LINE__,
+ curl_multi_strerror (mret));
+ clean_up ();
+ return;
+ }
+ mret = curl_multi_timeout (multi, &timeout);
+ if (mret != CURLM_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
+ "curl_multi_timeout", __FILE__, __LINE__,
+ curl_multi_strerror (mret));
+ clean_up ();
+ return;
+ }
+ rtime =
+ GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (end_time),
+ GNUNET_TIME_relative_multiply
+ (GNUNET_TIME_UNIT_MILLISECONDS, timeout));
+ grs = GNUNET_NETWORK_fdset_create ();
+ gws = GNUNET_NETWORK_fdset_create ();
+ GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Scheduling task for hostlist download using cURL\n");
+ ti_download =
+ GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+ rtime, grs, gws,
+ &task_download, multi);
+ GNUNET_NETWORK_fdset_destroy (gws);
+ GNUNET_NETWORK_fdset_destroy (grs);
+}
+
+
+/**
+ * Task that is run when we are ready to receive more data from the hostlist
+ * server.
+ *
+ * @param cls closure, unused
+ * @param tc task context, unused
+ */
+static void
+task_download (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ int running;
+ struct CURLMsg *msg;
+ CURLMcode mret;
+
+ ti_download = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Shutdown requested while trying to download hostlist from
`%s'\n",
+ current_url);
+ update_hostlist ();
+ clean_up ();
+ return;
+ }
+ if (0 == GNUNET_TIME_absolute_get_remaining (end_time).rel_value_us)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Timeout trying to download hostlist from `%s'\n"),
+ current_url);
+ update_hostlist ();
+ clean_up ();
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Ready for processing hostlist client request\n");
+ do
+ {
+ running = 0;
+ if (stat_bytes_downloaded > MAX_BYTES_PER_HOSTLISTS)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Download limit of %u bytes exceeded, stopping
download\n"),
+ MAX_BYTES_PER_HOSTLISTS);
+ clean_up ();
+ return;
+ }
+ mret = curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ do
+ {
+ msg = curl_multi_info_read (multi, &running);
+ GNUNET_break (msg != NULL);
+ if (msg == NULL)
+ break;
+ switch (msg->msg)
+ {
+ case CURLMSG_DONE:
+ if ((msg->data.result != CURLE_OK) &&
+ (msg->data.result != CURLE_GOT_NOTHING))
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Download of hostlist from `%s' failed: `%s'\n"),
+ current_url,
+ curl_easy_strerror (msg->data.result));
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Download of hostlist `%s' completed.\n"),
+ current_url);
+ stat_download_successful = GNUNET_YES;
+ update_hostlist ();
+ if (GNUNET_YES == stat_testing_hostlist)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _
+ ("Adding successfully tested hostlist `%s'
datastore.\n"),
+ current_url);
+ insert_hostlist ();
+ hostlist_to_test = NULL;
+ stat_testing_hostlist = GNUNET_NO;
+ }
+ }
+ clean_up ();
+ return;
+ default:
+ break;
+ }
+
+ }
+ while ((running > 0));
+ }
+ }
+ while (mret == CURLM_CALL_MULTI_PERFORM);
+
+ if (mret != CURLM_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("%s failed at %s:%d: `%s'\n"),
+ "curl_multi_perform", __FILE__, __LINE__,
+ curl_multi_strerror (mret));
+ clean_up ();
+ }
+ download_prepare ();
+}
+
+
+/**
+ * Main function that will download a hostlist and process its
+ * data.
+ */
+static void
+download_hostlist ()
+{
+ CURLcode ret;
+ CURLMcode mret;
+
+
+ current_url = download_get_url ();
+ if (current_url == NULL)
+ return;
+ curl = curl_easy_init ();
+ multi = NULL;
+ if (curl == NULL)
+ {
+ GNUNET_break (0);
+ clean_up ();
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
+ _("Bootstrapping using hostlist at `%s'.\n"), current_url);
+
+ stat_download_in_progress = GNUNET_YES;
+ stat_download_successful = GNUNET_NO;
+ stat_hellos_obtained = 0;
+ stat_bytes_downloaded = 0;
+
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# hostlist downloads initiated"), 1,
+ GNUNET_NO);
+ if (proxy != NULL)
+ {
+ CURL_EASY_SETOPT (curl, CURLOPT_PROXY, proxy);
+ CURL_EASY_SETOPT (curl, CURLOPT_PROXYTYPE, proxy_type);
+ if (NULL != proxy_username)
+ CURL_EASY_SETOPT (curl, CURLOPT_PROXYUSERNAME, proxy_username);
+ if (NULL != proxy_password)
+ CURL_EASY_SETOPT (curl, CURLOPT_PROXYPASSWORD, proxy_password);
+ }
+ download_pos = 0;
+ stat_bogus_url = 0;
+ CURL_EASY_SETOPT (curl, CURLOPT_WRITEFUNCTION, &callback_download);
+ if (ret != CURLE_OK)
+ {
+ clean_up ();
+ return;
+ }
+ CURL_EASY_SETOPT (curl, CURLOPT_WRITEDATA, NULL);
+ if (ret != CURLE_OK)
+ {
+ clean_up ();
+ return;
+ }
+ CURL_EASY_SETOPT (curl, CURLOPT_FOLLOWLOCATION, 1);
+ CURL_EASY_SETOPT (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP |
CURLPROTO_HTTPS);
+ CURL_EASY_SETOPT (curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+ CURL_EASY_SETOPT (curl, CURLOPT_MAXREDIRS, 4);
+ /* no need to abort if the above failed */
+ CURL_EASY_SETOPT (curl, CURLOPT_URL, current_url);
+ if (ret != CURLE_OK)
+ {
+ clean_up ();
+ return;
+ }
+ CURL_EASY_SETOPT (curl, CURLOPT_FAILONERROR, 1);
+#if 0
+ CURL_EASY_SETOPT (curl, CURLOPT_VERBOSE, 1);
+#endif
+ CURL_EASY_SETOPT (curl, CURLOPT_BUFFERSIZE, GNUNET_SERVER_MAX_MESSAGE_SIZE);
+ if (0 == strncmp (current_url, "http", 4))
+ CURL_EASY_SETOPT (curl, CURLOPT_USERAGENT, "GNUnet");
+ CURL_EASY_SETOPT (curl, CURLOPT_CONNECTTIMEOUT, 60L);
+ CURL_EASY_SETOPT (curl, CURLOPT_TIMEOUT, 60L);
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ GNUNET_break (0);
+ /* clean_up (); */
+ return;
+ }
+ mret = curl_multi_add_handle (multi, curl);
+ if (mret != CURLM_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
+ "curl_multi_add_handle", __FILE__, __LINE__,
+ curl_multi_strerror (mret));
+ mret = curl_multi_cleanup (multi);
+ if (mret != CURLM_OK)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
+ "curl_multi_cleanup", __FILE__, __LINE__,
+ curl_multi_strerror (mret));
+ multi = NULL;
+ clean_up ();
+ return;
+ }
+ end_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
+ download_prepare ();
+}
+
+
+static void
+task_download_dispatcher (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ ti_download_dispatcher_task = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download is initiated...\n");
+ if (GNUNET_NO == stat_download_in_progress)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download can start
immediately...\n");
+ download_hostlist ();
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Download in progess, have to wait...\n");
+ ti_download_dispatcher_task =
+ GNUNET_SCHEDULER_add_delayed (WAITING_INTERVAL,
+ &task_download_dispatcher, NULL);
+ }
+}
+
+
+/**
+ * Task that checks if we should try to download a hostlist.
+ * If so, we initiate the download, otherwise we schedule
+ * this task again for a later time.
+ */
+static void
+task_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ static int once;
+ struct GNUNET_TIME_Relative delay;
+
+ ti_check_download = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ if (stats == NULL)
+ {
+ curl_global_cleanup ();
+ return; /* in shutdown */
+ }
+ if ( (stat_connection_count < MIN_CONNECTIONS) &&
+ (GNUNET_SCHEDULER_NO_TASK == ti_download_dispatcher_task) )
+ ti_download_dispatcher_task =
+ GNUNET_SCHEDULER_add_now (&task_download_dispatcher, NULL);
+
+ delay = hostlist_delay;
+ if (0 == hostlist_delay.rel_value_us)
+ hostlist_delay = GNUNET_TIME_UNIT_SECONDS;
+ else
+ hostlist_delay = GNUNET_TIME_relative_multiply (hostlist_delay, 2);
+ if (hostlist_delay.rel_value_us >
+ GNUNET_TIME_UNIT_HOURS.rel_value_us * (1 + stat_connection_count))
+ hostlist_delay =
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS,
+ (1 + stat_connection_count));
+ GNUNET_STATISTICS_set (stats,
+ gettext_noop
+ ("# milliseconds between hostlist downloads"),
+ hostlist_delay.rel_value_us / 1000LL,
+ GNUNET_YES);
+ if (0 == once)
+ {
+ delay = GNUNET_TIME_UNIT_ZERO;
+ once = 1;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Have %u/%u connections. Will consider downloading hostlist
in %s\n"),
+ stat_connection_count, MIN_CONNECTIONS,
+ GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
+ ti_check_download = GNUNET_SCHEDULER_add_delayed (delay, &task_check, NULL);
+}
+
+
+/**
+ * This tasks sets hostlist testing to allowed after intervall between to
testings is reached
+ *
+ * @param cls closure
+ * @param tc TaskContext
+ */
+static void
+task_testing_intervall_reset (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ ti_testing_intervall_task = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ stat_testing_allowed = GNUNET_OK;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Testing new hostlist advertisements is allowed again\n");
+}
+
+
+/**
+ * Task that writes hostlist entries to a file on a regular base
+ *
+ * @param cls closure
+ * @param tc TaskContext
+ */
+static void
+task_hostlist_saving (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ ti_saving_task = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ save_hostlist_file (GNUNET_NO);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Hostlists will be saved to file again in %s\n",
+ GNUNET_STRINGS_relative_time_to_string(SAVING_INTERVAL,
GNUNET_YES));
+ ti_saving_task =
+ GNUNET_SCHEDULER_add_delayed (SAVING_INTERVAL, &task_hostlist_saving,
+ NULL);
+}
+
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+handler_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+ GNUNET_assert (stat_connection_count < UINT_MAX);
+ stat_connection_count++;
+ GNUNET_STATISTICS_update (stats, gettext_noop ("# active connections"), 1,
+ GNUNET_NO);
+}
+
+
+/**
+ * Method called whenever a given peer disconnects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+handler_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+ GNUNET_assert (stat_connection_count > 0);
+ stat_connection_count--;
+ GNUNET_STATISTICS_update (stats, gettext_noop ("# active connections"), -1,
+ GNUNET_NO);
+}
+
+
+/**
+ * Method called whenever an advertisement message arrives.
+ *
+ * @param cls closure (always NULL)
+ * @param peer the peer sending the message
+ * @param message the actual message
+ * @return #GNUNET_OK to keep the connection open,
+ * #GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handler_advertisement (void *cls, const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_MessageHeader *message)
+{
+ size_t size;
+ size_t uri_size;
+ const struct GNUNET_MessageHeader *incoming;
+ const char *uri;
+ struct Hostlist *hostlist;
+
+ GNUNET_assert (ntohs (message->type) ==
+ GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
+ size = ntohs (message->size);
+ if (size <= sizeof (struct GNUNET_MessageHeader))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ incoming = (const struct GNUNET_MessageHeader *) message;
+ uri = (const char *) &incoming[1];
+ uri_size = size - sizeof (struct GNUNET_MessageHeader);
+ if (uri[uri_size - 1] != '\0')
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Hostlist client recieved advertisement from `%s' containing URI
`%s'\n",
+ GNUNET_i2s (peer), uri);
+ if (GNUNET_NO != linked_list_contains (uri))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URI `%s' is already known\n", uri);
+ return GNUNET_OK;
+ }
+
+ if (GNUNET_NO == stat_testing_allowed)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Currently not accepting new advertisements: interval between
to advertisements is not reached\n");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_YES == stat_testing_hostlist)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Currently not accepting new advertisements: we are already
testing a hostlist\n");
+ return GNUNET_SYSERR;
+ }
+
+ hostlist = GNUNET_malloc (sizeof (struct Hostlist) + uri_size);
+ hostlist->hostlist_uri = (const char *) &hostlist[1];
+ memcpy (&hostlist[1], uri, uri_size);
+ hostlist->time_creation = GNUNET_TIME_absolute_get ();
+ hostlist->quality = HOSTLIST_INITIAL;
+ hostlist_to_test = hostlist;
+
+ stat_testing_hostlist = GNUNET_YES;
+ stat_testing_allowed = GNUNET_NO;
+ ti_testing_intervall_task =
+ GNUNET_SCHEDULER_add_delayed (TESTING_INTERVAL,
+ &task_testing_intervall_reset, NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Testing new hostlist advertisements is locked for the next
%s\n",
+ GNUNET_STRINGS_relative_time_to_string (TESTING_INTERVAL,
+ GNUNET_YES));
+
+ ti_download_dispatcher_task =
+ GNUNET_SCHEDULER_add_now (&task_download_dispatcher, NULL);
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Continuation called by the statistics code once
+ * we go the stat. Initiates hostlist download scheduling.
+ *
+ * @param cls closure
+ * @param success #GNUNET_OK if statistics were
+ * successfully obtained, #GNUNET_SYSERR if not.
+ */
+static void
+primary_task (void *cls, int success)
+{
+ sget = NULL;
+ GNUNET_assert (stats != NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Statistics request done, scheduling hostlist download\n");
+ ti_check_download = GNUNET_SCHEDULER_add_now (&task_check, NULL);
+}
+
+
+/**
+ * We've received the previous delay value from statistics. Remember it.
+ *
+ * @param cls NULL, unused
+ * @param subsystem should be "hostlist", unused
+ * @param name will be "milliseconds between hostlist downloads", unused
+ * @param value previous delay value, in milliseconds (!)
+ * @param is_persistent unused, will be #GNUNET_YES
+ */
+static int
+process_stat (void *cls,
+ const char *subsystem,
+ const char *name,
+ uint64_t value,
+ int is_persistent)
+{
+ hostlist_delay.rel_value_us = value * 1000LL;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Initial time between hostlist downloads is %s\n",
+ GNUNET_STRINGS_relative_time_to_string (hostlist_delay,
GNUNET_YES));
+ return GNUNET_OK;
+}
+
+
+/**
+ * Method to load persistent hostlist file during hostlist client startup
+ */
+static void
+load_hostlist_file ()
+{
+ char *filename;
+ char *uri;
+ char *emsg;
+ struct Hostlist *hostlist;
+ uint32_t times_used;
+ uint32_t hellos_returned;
+ uint64_t quality;
+ uint64_t last_used;
+ uint64_t created;
+ uint32_t counter;
+ struct GNUNET_BIO_ReadHandle *rh;
+
+ uri = NULL;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST", "HOSTLISTFILE",
+ &filename))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ "hostlist", "HOSTLISTFILE");
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Loading saved hostlist entries from file `%s' \n"),
+ filename);
+ if (GNUNET_NO == GNUNET_DISK_file_test (filename))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Hostlist file `%s' does not exist\n"), filename);
+ GNUNET_free (filename);
+ return;
+ }
+
+ rh = GNUNET_BIO_read_open (filename);
+ if (NULL == rh)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Could not open file `%s' for reading to load hostlists:
%s\n"),
+ filename, STRERROR (errno));
+ GNUNET_free (filename);
+ return;
+ }
+
+ counter = 0;
+ while ((GNUNET_OK == GNUNET_BIO_read_string (rh, "url", &uri, MAX_URL_LEN))
&&
+ (NULL != uri) && (GNUNET_OK == GNUNET_BIO_read_int32 (rh,
×_used))
+ && (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality)) &&
+ (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used)) &&
+ (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &created)) &&
+ (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &hellos_returned)))
+ {
+ hostlist = GNUNET_malloc (sizeof (struct Hostlist) + strlen (uri) + 1);
+ hostlist->hello_count = hellos_returned;
+ hostlist->hostlist_uri = (const char *) &hostlist[1];
+ memcpy (&hostlist[1], uri, strlen (uri) + 1);
+ hostlist->quality = quality;
+ hostlist->time_creation.abs_value_us = created;
+ hostlist->time_last_usage.abs_value_us = last_used;
+ GNUNET_CONTAINER_DLL_insert (linked_list_head, linked_list_tail, hostlist);
+ linked_list_size++;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Added hostlist entry eith URI `%s' \n",
+ hostlist->hostlist_uri);
+ GNUNET_free (uri);
+ uri = NULL;
+ counter++;
+ if (counter >= MAX_NUMBER_HOSTLISTS)
+ break;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("%u hostlist URIs loaded from file\n"),
+ counter);
+ GNUNET_STATISTICS_set (stats,
+ gettext_noop ("# hostlist URIs read from file"),
+ counter, GNUNET_YES);
+ GNUNET_STATISTICS_set (stats,
+ gettext_noop ("# advertised hostlist URIs"),
+ linked_list_size, GNUNET_NO);
+
+ GNUNET_free_non_null (uri);
+ emsg = NULL;
+ (void) GNUNET_BIO_read_close (rh, &emsg);
+ if (emsg != NULL)
+ GNUNET_free (emsg);
+ GNUNET_free (filename);
+}
+
+
+/**
+ * Method to save persistent hostlist file during hostlist client shutdown
+ *
+ * @param shutdown set if called because of shutdown, entries in linked list
will be destroyed
+ */
+static void
+save_hostlist_file (int shutdown)
+{
+ char *filename;
+ struct Hostlist *pos;
+ struct GNUNET_BIO_WriteHandle *wh;
+ int ok;
+ uint32_t counter;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST", "HOSTLISTFILE",
+ &filename))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ "hostlist", "HOSTLISTFILE");
+ return;
+ }
+ if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
+ {
+ GNUNET_free (filename);
+ return;
+ }
+ wh = GNUNET_BIO_write_open (filename);
+ if (NULL == wh)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _
+ ("Could not open file `%s' for writing to save hostlists:
%s\n"),
+ filename, STRERROR (errno));
+ GNUNET_free (filename);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Writing %u hostlist URIs to `%s'\n"),
+ linked_list_size, filename);
+ /* add code to write hostlists to file using bio */
+ ok = GNUNET_YES;
+ counter = 0;
+ while (NULL != (pos = linked_list_head))
+ {
+ if (GNUNET_YES == shutdown)
+ {
+ GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail, pos);
+ linked_list_size--;
+ }
+ if (GNUNET_YES == ok)
+ {
+ if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pos->hostlist_uri)) ||
+ (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->times_used)) ||
+ (GNUNET_OK != GNUNET_BIO_write_int64 (wh, pos->quality)) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_write_int64 (wh, pos->time_last_usage.abs_value_us)) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_write_int64 (wh, pos->time_creation.abs_value_us)) ||
+ (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->hello_count)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Error writing hostlist URIs to file `%s'\n"), filename);
+ ok = GNUNET_NO;
+ }
+ }
+
+ if (GNUNET_YES == shutdown)
+ GNUNET_free (pos);
+ counter++;
+ if (counter >= MAX_NUMBER_HOSTLISTS)
+ break;
+ }
+ GNUNET_STATISTICS_set (stats,
+ gettext_noop ("# hostlist URIs written to file"),
+ counter, GNUNET_YES);
+
+ if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Error writing hostlist URIs to file `%s'\n"), filename);
+ GNUNET_free (filename);
+}
+
+
+/**
+ * Start downloading hostlists from hostlist servers as necessary.
+ *
+ * @param c configuration to use
+ * @param st statistics handle to use
+ * @param ch[OUT] set to handler for CORE connect events
+ * @param dh[OUT] set to handler for CORE disconnect events
+ * @param msgh[OUT] set to handler for CORE advertisement messages
+ * @param learn should we learn hostlist URLs from CORE
+ * @return #GNUNET_OK on success
+ */
+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_CORE_MessageCallback *msgh,
+ int learn)
+{
+ char *filename;
+ char *proxytype_str;
+ int result;
+
+ GNUNET_assert (NULL != st);
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL);
+ if (NULL == transport)
+ {
+ curl_global_cleanup ();
+ return GNUNET_SYSERR;
+ }
+ cfg = c;
+ stats = st;
+
+ /* Read proxy configuration */
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
+ "HOSTLIST", "PROXY", &proxy))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found proxy host: `%s'\n",
+ proxy);
+ /* proxy username */
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
+ "HOSTLIST", "PROXY_USERNAME", &proxy_username))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found proxy username name: `%s'\n",
+ proxy_username);
+ }
+
+ /* proxy password */
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
+ "HOSTLIST", "PROXY_PASSWORD", &proxy_password))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found proxy password name: `%s'\n",
+ proxy_password);
+ }
+
+ /* proxy type */
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
+ "HOSTLIST", "PROXY_TYPE", &proxytype_str))
+ {
+ GNUNET_STRINGS_utf8_toupper (proxytype_str, proxytype_str);
+
+ proxy_type = CURLPROXY_HTTP;
+ if (0 == strcmp(proxytype_str, "HTTP"))
+ proxy_type = CURLPROXY_HTTP;
+ else if (0 == strcmp(proxytype_str, "HTTP_1_0"))
+ proxy_type = CURLPROXY_HTTP_1_0;
+ else if (0 == strcmp(proxytype_str, "SOCKS4"))
+ proxy_type = CURLPROXY_SOCKS4;
+ else if (0 == strcmp(proxytype_str, "SOCKS5"))
+ proxy_type = CURLPROXY_SOCKS5;
+ else if (0 == strcmp(proxytype_str, "SOCKS4A"))
+ proxy_type = CURLPROXY_SOCKS4A;
+ else if (0 == strcmp(proxytype_str, "SOCKS5_HOSTNAME"))
+ proxy_type = CURLPROXY_SOCKS5_HOSTNAME ;
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid proxy type: `%s', disabling proxy! Check
configuration!\n"),
+ proxytype_str);
+ GNUNET_free (proxytype_str);
+
+ GNUNET_free (proxy);
+ proxy = NULL;
+ GNUNET_free_non_null (proxy_username);
+ proxy_username = NULL;
+ GNUNET_free_non_null (proxy_password);
+ proxy_password = NULL;
+
+ return GNUNET_SYSERR;
+ }
+ }
+ GNUNET_free_non_null (proxytype_str);
+ }
+
+ stat_learning = learn;
+ *ch = &handler_connect;
+ *dh = &handler_disconnect;
+ linked_list_head = NULL;
+ linked_list_tail = NULL;
+ stat_use_bootstrap = GNUNET_YES;
+ stat_testing_hostlist = GNUNET_NO;
+ stat_testing_allowed = GNUNET_YES;
+
+ if (GNUNET_YES == stat_learning)
+ {
+ *msgh = &handler_advertisement;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Learning is enabled on this peer\n"));
+ load_hostlist_file ();
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Hostlists will be saved to file again in %s\n",
+ GNUNET_STRINGS_relative_time_to_string (SAVING_INTERVAL,
GNUNET_YES));
+ ti_saving_task =
+ GNUNET_SCHEDULER_add_delayed (SAVING_INTERVAL, &task_hostlist_saving,
+ NULL);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Learning is not enabled on this peer\n"));
+ *msgh = NULL;
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST",
+ "HOSTLISTFILE", &filename))
+ {
+ if (GNUNET_YES == GNUNET_DISK_file_test (filename))
+ {
+ result = remove (filename);
+ if (result == 0)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _
+ ("Since learning is not enabled on this peer, hostlist
file `%s' was removed\n"),
+ filename);
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Hostlist file `%s' could not be removed\n"),
filename);
+ }
+ }
+ GNUNET_free (filename);
+ }
+ sget = GNUNET_STATISTICS_get (stats, "hostlist",
+ gettext_noop
+ ("# milliseconds between hostlist downloads"),
+ GNUNET_TIME_UNIT_MINUTES, &primary_task,
&process_stat,
+ NULL);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Stop downloading hostlists from hostlist servers as necessary.
+ */
+void
+GNUNET_HOSTLIST_client_stop ()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist client shutdown\n");
+ if (NULL != sget)
+ {
+ GNUNET_STATISTICS_get_cancel (sget);
+ sget = NULL;
+ }
+ stats = NULL;
+ if (GNUNET_YES == stat_learning)
+ save_hostlist_file (GNUNET_YES);
+ if (ti_saving_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (ti_saving_task);
+ ti_saving_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ if (ti_download_dispatcher_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (ti_download_dispatcher_task);
+ ti_download_dispatcher_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (ti_testing_intervall_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (ti_testing_intervall_task);
+ ti_testing_intervall_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (ti_download != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (ti_download);
+ ti_download = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (ti_check_download != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (ti_check_download);
+ ti_check_download = GNUNET_SCHEDULER_NO_TASK;
+ curl_global_cleanup ();
+ }
+ if (NULL != transport)
+ {
+ GNUNET_TRANSPORT_disconnect (transport);
+ transport = NULL;
+ }
+ GNUNET_free_non_null (proxy);
+ proxy = NULL;
+ GNUNET_free_non_null (proxy_username);
+ proxy_username = NULL;
+ GNUNET_free_non_null (proxy_password);
+ proxy_password = NULL;
+
+ cfg = NULL;
+}
+
+/* end of gnunet-daemon-hostlist_client.c */
Copied: gnunet/src/hostlist/gnunet-daemon-hostlist_client.h (from rev 33486,
gnunet/src/hostlist/hostlist-client.h)
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist_client.h
(rev 0)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist_client.h 2014-06-03 08:41:00 UTC
(rev 33489)
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file hostlist/gnunet-daemon-hostlist_client.h
+ * @brief hostlist support. Downloads HELLOs via HTTP.
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_DAEMON_HOSTLIST_CLIENT_H
+#define GNUNET_DAEMON_HOSTLIST_CLIENT_H
+
+#include "gnunet_core_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_util_lib.h"
+
+
+/**
+ * Start downloading hostlists from hostlist servers as necessary.
+ *
+ * @param c the configuration to use
+ * @param st hande for publishing statistics
+ * @param ch[OUT] set to handler for connect notifications
+ * @param dh[OUT] set to handler for disconnect notifications
+ * @param msgh[OUT] set to handler for message handler notifications
+ * @param learn set if client is learning new hostlists
+ * @return #GNUNET_OK on success
+ */
+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_CORE_MessageCallback *msgh,
+ int learn);
+
+
+/**
+ * Stop downloading hostlists from hostlist servers as necessary.
+ */
+void
+GNUNET_HOSTLIST_client_stop (void);
+
+
+#endif
+/* end of gnunet-daemon-hostlist_client.h */
Copied: gnunet/src/hostlist/gnunet-daemon-hostlist_server.c (from rev 33488,
gnunet/src/hostlist/hostlist-server.c)
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist_server.c
(rev 0)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist_server.c 2014-06-03 08:41:00 UTC
(rev 33489)
@@ -0,0 +1,888 @@
+/*
+ This file is part of GNUnet.
+ (C) 2008, 2009, 2010, 2014 Christian Grothoff (and other contributing
authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file hostlist/gnunet-daemon-hostlist_server.c
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ * @author David Barksdale
+ * @brief application to provide an integrated hostlist HTTP server
+ */
+#include "platform.h"
+#include <microhttpd.h>
+#include "gnunet-daemon-hostlist_server.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_peerinfo_service.h"
+#include "gnunet-daemon-hostlist.h"
+#include "gnunet_resolver_service.h"
+
+
+/**
+ * How long until our hostlist advertisment transmission via CORE should
+ * time out?
+ */
+#define GNUNET_ADV_TIMEOUT GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_MINUTES, 5)
+
+
+/**
+ * Handle to the HTTP server as provided by libmicrohttpd for IPv6.
+ */
+static struct MHD_Daemon *daemon_handle_v6;
+
+/**
+ * Handle to the HTTP server as provided by libmicrohttpd for IPv4.
+ */
+static struct MHD_Daemon *daemon_handle_v4;
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * For keeping statistics.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Handle to the core service (NULL until we've connected to it).
+ */
+static struct GNUNET_CORE_Handle *core;
+
+/**
+ * Handle to the peerinfo notify service (NULL until we've connected to it).
+ */
+static struct GNUNET_PEERINFO_NotifyContext *notify;
+
+/**
+ * Our primary task for IPv4.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v4;
+
+/**
+ * Our primary task for IPv6.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v6;
+
+/**
+ * Our canonical response.
+ */
+static struct MHD_Response *response;
+
+/**
+ * Handle for accessing peerinfo service.
+ */
+static struct GNUNET_PEERINFO_Handle *peerinfo;
+
+/**
+ * Set if we are allowed to advertise our hostlist to others.
+ */
+static int advertising;
+
+/**
+ * Buffer for the hostlist address
+ */
+static char *hostlist_uri;
+
+
+/**
+ * Context for host processor.
+ */
+struct HostSet
+{
+ unsigned int size;
+
+ char *data;
+
+ struct GNUNET_PEERINFO_IteratorContext *pitr;
+};
+
+
+/**
+ * NULL if we are not currenlty iterating over peer information.
+ */
+static struct HostSet *builder;
+
+
+/**
+ * Function that assembles our response.
+ */
+static void
+finish_response ()
+{
+ if (NULL != response)
+ MHD_destroy_response (response);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating hostlist response with %u bytes\n",
+ (unsigned int) builder->size);
+ response =
+ MHD_create_response_from_data (builder->size, builder->data, MHD_YES,
+ MHD_NO);
+ if ((NULL == daemon_handle_v4) && (NULL == daemon_handle_v6))
+ {
+ MHD_destroy_response (response);
+ response = NULL;
+ }
+ GNUNET_STATISTICS_set (stats, gettext_noop ("bytes in hostlist"),
+ builder->size, GNUNET_YES);
+ GNUNET_free (builder);
+ builder = NULL;
+}
+
+
+/**
+ * Set @a cls to #GNUNET_YES (we have an address!).
+ *
+ * @param cls closure, an `int *`
+ * @param address the address (ignored)
+ * @param expiration expiration time (call is ignored if this is in the past)
+ * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured)
+ */
+static int
+check_has_addr (void *cls,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_TIME_Absolute expiration)
+{
+ int *arg = cls;
+
+ if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
+ {
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("expired addresses encountered"),
1,
+ GNUNET_YES);
+ return GNUNET_YES; /* ignore this address */
+ }
+ *arg = GNUNET_YES;
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Callback that processes each of the known HELLOs for the
+ * hostlist response construction.
+ *
+ * @param cls closure, NULL
+ * @param peer id of the peer, NULL for last call
+ * @param hello hello message for the peer (can be NULL)
+ * @param error message
+ */
+static void
+host_processor (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Message *hello,
+ const char *err_msg)
+{
+ size_t old;
+ size_t s;
+ int has_addr;
+
+ if (NULL != err_msg)
+ {
+ GNUNET_assert (NULL == peer);
+ builder->pitr = NULL;
+ GNUNET_free_non_null (builder->data);
+ GNUNET_free (builder);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Error in communication with PEERINFO service: %s\n"),
+ err_msg);
+ return;
+ }
+ if (NULL == peer)
+ {
+ builder->pitr = NULL;
+ finish_response ();
+ return;
+ }
+ if (NULL == hello)
+ return;
+ has_addr = GNUNET_NO;
+ GNUNET_HELLO_iterate_addresses (hello,
+ GNUNET_NO,
+ &check_has_addr,
+ &has_addr);
+ if (GNUNET_NO == has_addr)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "HELLO for peer `%4s' has no address, not suitable for
hostlist!\n",
+ GNUNET_i2s (peer));
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("HELLOs without addresses encountered
(ignored)"),
+ 1, GNUNET_NO);
+ return;
+ }
+ old = builder->size;
+ s = GNUNET_HELLO_size (hello);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
+ (unsigned int) s,
+ "HELLO",
+ GNUNET_i2s (peer));
+ if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) ||
+ (old + s >= MAX_BYTES_PER_HOSTLISTS))
+ {
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("bytes not included in hostlist (size limit)"),
+ s, GNUNET_NO);
+ return; /* too large, skip! */
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Adding peer `%s' to hostlist (%u bytes)\n",
+ GNUNET_i2s (peer),
+ (unsigned int) s);
+ GNUNET_array_grow (builder->data, builder->size, old + s);
+ memcpy (&builder->data[old], hello, s);
+}
+
+
+/**
+ * Hostlist access policy (very permissive, allows everything).
+ * Returns #MHD_NO only if we are not yet ready to serve.
+ *
+ * @param cls closure
+ * @param addr address information from the client
+ * @param addrlen length of @a addr
+ * @return #MHD_YES if connection is allowed, #MHD_NO if not (we are not ready)
+ */
+static int
+accept_policy_callback (void *cls,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ if (NULL == response)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received request for hostlist, but I am not yet ready;
rejecting!\n");
+ return MHD_NO;
+ }
+ return MHD_YES; /* accept all */
+}
+
+
+/**
+ * Add headers to a request indicating that we allow Cross-Origin Resource
+ * Sharing.
+ *
+ * @param response response to add headers to
+ */
+static void
+add_cors_headers (struct MHD_Response *response)
+{
+ MHD_add_response_header (response,
+ "Access-Control-Allow-Origin",
+ "*");
+ MHD_add_response_header (response,
+ "Access-Control-Allow-Methods",
+ "GET, OPTIONS");
+ MHD_add_response_header (response,
+ "Access-Control-Max-Age",
+ "86400");
+}
+
+
+/**
+ * Main request handler.
+ *
+ * @param cls argument given together with the function
+ * pointer when the handler was registered with MHD
+ * @param url the requested url
+ * @param method the HTTP method used (#MHD_HTTP_METHOD_GET,
+ * #MHD_HTTP_METHOD_PUT, etc.)
+ * @param version the HTTP version string (i.e.
+ * #MHD_HTTP_VERSION_1_1)
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ * for a POST that fits into memory and that is encoded
+ * with a supported encoding, the POST data will NOT be
+ * given in upload_data and is instead available as
+ * part of #MHD_get_connection_values; very large POST
+ * data *will* be made available incrementally in
+ * @a upload_data)
+ * @param upload_data_size set initially to the size of the
+ * @a upload_data provided; the method must update this
+ * value to the number of bytes NOT processed;
+ * @param con_cls pointer that the callback can set to some
+ * address and that will be preserved by MHD for future
+ * calls for this request; since the access handler may
+ * be called many times (i.e., for a PUT/POST operation
+ * with plenty of upload data) this allows the application
+ * to easily associate some request-specific state.
+ * If necessary, this state can be cleaned up in the
+ * global #MHD_RequestCompletedCallback (which
+ * can be set with the #MHD_OPTION_NOTIFY_COMPLETED).
+ * Initially, `*con_cls` will be NULL.
+ * @return #MHD_YES if the connection was handled successfully,
+ * #MHD_NO if the socket must be closed due to a serios
+ * error while handling the request
+ */
+static int
+access_handler_callback (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
+{
+ static int dummy;
+
+ /* CORS pre-flight request */
+ if (0 == strcmp (MHD_HTTP_METHOD_OPTIONS, method))
+ {
+ struct MHD_Response *options_response;
+ int rc;
+
+ options_response = MHD_create_response_from_buffer (0, NULL,
+
MHD_RESPMEM_PERSISTENT);
+ add_cors_headers(options_response);
+ rc = MHD_queue_response (connection, MHD_HTTP_OK, options_response);
+ MHD_destroy_response (options_response);
+ return rc;
+ }
+ if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Refusing `%s' request to hostlist server\n"), method);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("hostlist requests refused (not HTTP GET)"), 1,
+ GNUNET_YES);
+ return MHD_NO;
+ }
+ if (NULL == *con_cls)
+ {
+ (*con_cls) = &dummy;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending 100 CONTINUE reply\n");
+ return MHD_YES; /* send 100 continue */
+ }
+ if (0 != *upload_data_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Refusing `%s' request with %llu bytes of upload data\n"),
+ method, (unsigned long long) *upload_data_size);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("hostlist requests refused (upload data)"), 1,
+ GNUNET_YES);
+ return MHD_NO; /* do not support upload data */
+ }
+ if (NULL == response)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Could not handle hostlist request since I do not have a
response yet\n"));
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop
+ ("hostlist requests refused (not ready)"), 1,
+ GNUNET_YES);
+ return MHD_NO; /* internal error, no response yet */
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Received request for our hostlist\n"));
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("hostlist requests processed"),
+ 1, GNUNET_YES);
+ add_cors_headers (response);
+ return MHD_queue_response (connection, MHD_HTTP_OK, response);
+}
+
+
+/**
+ * Handler called by CORE when CORE is ready to transmit message
+ *
+ * @param cls closure
+ * @param size size of buffer to copy message to
+ * @param buf buffer to copy message to
+ * @return number of bytes copied to @a buf
+ */
+static size_t
+adv_transmit_ready (void *cls,
+ size_t size,
+ void *buf)
+{
+ static uint64_t hostlist_adv_count;
+ size_t transmission_size;
+ size_t uri_size; /* Including \0 termination! */
+ struct GNUNET_MessageHeader header;
+ char *cbuf;
+
+ if (NULL == buf)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Transmission failed, buffer invalid!\n");
+ return 0;
+ }
+ uri_size = strlen (hostlist_uri) + 1;
+ transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size;
+ header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
+ header.size = htons (transmission_size);
+ GNUNET_assert (size >= transmission_size);
+ memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader));
+ cbuf = buf;
+ memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)], hostlist_uri, uri_size);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sent advertisement message: Copied %u bytes into buffer!\n",
+ (unsigned int) transmission_size);
+ hostlist_adv_count++;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " # Sent advertisement message: %u\n",
+ hostlist_adv_count);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# hostlist advertisements send"), 1,
+ GNUNET_NO);
+ return transmission_size;
+}
+
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+connect_handler (void *cls,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ size_t size;
+
+ if (!advertising)
+ return;
+ if (NULL == hostlist_uri)
+ return;
+ size = strlen (hostlist_uri) + 1;
+ if (size + sizeof (struct GNUNET_MessageHeader) >=
+ GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ size += sizeof (struct GNUNET_MessageHeader);
+ if (NULL == core)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Asked CORE to transmit advertisement message with a size of %u
bytes to peer `%s'\n",
+ size,
+ GNUNET_i2s (peer));
+ if (NULL ==
+ GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES,
+ GNUNET_CORE_PRIO_BEST_EFFORT,
+ GNUNET_ADV_TIMEOUT,
+ peer,
+ size,
+ &adv_transmit_ready, NULL))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Advertisement message could not be queued by core\n"));
+ }
+}
+
+
+/**
+ * Method called whenever a given peer disconnects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+disconnect_handler (void *cls,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ /* nothing to do */
+}
+
+
+/**
+ * PEERINFO calls this function to let us know about a possible peer
+ * that we might want to connect to.
+ *
+ * @param cls closure (not used)
+ * @param peer potential peer to connect to
+ * @param hello HELLO for this peer (or NULL)
+ * @param err_msg NULL if successful, otherwise contains error message
+ */
+static void
+process_notify (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Message *hello,
+ const char *err_msg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Peerinfo is notifying us to rebuild our hostlist\n");
+ if (NULL != err_msg)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Error in communication with PEERINFO service: %s\n"),
+ err_msg);
+ if (NULL != builder)
+ {
+ /* restart re-build already in progress ... */
+ GNUNET_PEERINFO_iterate_cancel (builder->pitr);
+ GNUNET_free_non_null (builder->data);
+ builder->size = 0;
+ builder->data = NULL;
+ }
+ else
+ {
+ builder = GNUNET_new (struct HostSet);
+ }
+ GNUNET_assert (NULL != peerinfo);
+ builder->pitr =
+ GNUNET_PEERINFO_iterate (peerinfo, GNUNET_NO, NULL,
GNUNET_TIME_UNIT_MINUTES,
+ &host_processor, NULL);
+}
+
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier
+prepare_daemon (struct MHD_Daemon *daemon_handle);
+
+
+/**
+ * Call MHD to process pending requests and then go back
+ * and schedule the next run.
+ *
+ * @param cls the `struct MHD_Daemon` of the HTTP server to run
+ * @param tc scheduler context
+ */
+static void
+run_daemon (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct MHD_Daemon *daemon_handle = cls;
+
+ if (daemon_handle == daemon_handle_v4)
+ hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
+ else
+ hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
+
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
+ if (daemon_handle == daemon_handle_v4)
+ hostlist_task_v4 = prepare_daemon (daemon_handle);
+ else
+ hostlist_task_v6 = prepare_daemon (daemon_handle);
+}
+
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ *
+ * @param daemon_handle HTTP server to prepare to run
+ */
+static GNUNET_SCHEDULER_TaskIdentifier
+prepare_daemon (struct MHD_Daemon *daemon_handle)
+{
+ GNUNET_SCHEDULER_TaskIdentifier ret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ struct GNUNET_NETWORK_FDSet *wrs;
+ struct GNUNET_NETWORK_FDSet *wws;
+ int max;
+ MHD_UNSIGNED_LONG_LONG timeout;
+ int haveto;
+ struct GNUNET_TIME_Relative tv;
+
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ wrs = GNUNET_NETWORK_fdset_create ();
+ wws = GNUNET_NETWORK_fdset_create ();
+ max = -1;
+ GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es,
&max));
+ haveto = MHD_get_timeout (daemon_handle, &timeout);
+ if (haveto == MHD_YES)
+ tv.rel_value_us = (uint64_t) timeout * 1000LL;
+ else
+ tv = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+ ret =
+ GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
+ tv, wrs, wws,
+ &run_daemon, daemon_handle);
+ GNUNET_NETWORK_fdset_destroy (wrs);
+ GNUNET_NETWORK_fdset_destroy (wws);
+ return ret;
+}
+
+
+/**
+ * Start server offering our hostlist.
+ *
+ * @param c configuration to use
+ * @param st statistics handle to use
+ * @param co core handle to use
+ * @param server_ch[OUT] set to handler for CORE connect events
+ * @param server_dh[OUT] set to handler for CORE disconnect events
+ * @param advertise #GNUNET_YES if we should advertise our hostlist
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
+ struct GNUNET_STATISTICS_Handle *st,
+ struct GNUNET_CORE_Handle *co,
+ GNUNET_CORE_ConnectEventHandler *server_ch,
+ GNUNET_CORE_DisconnectEventHandler *server_dh,
+ int advertise)
+{
+ unsigned long long port;
+ char *hostname;
+ char *ipv4;
+ char *ipv6;
+ size_t size;
+ struct in_addr i4;
+ struct in6_addr i6;
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ const struct sockaddr *sa4;
+ const struct sockaddr *sa6;
+
+ advertising = advertise;
+ if (! advertising)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Advertising not enabled on this hostlist server\n");
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Advertising enabled on this hostlist server\n");
+ cfg = c;
+ stats = st;
+ peerinfo = GNUNET_PEERINFO_connect (cfg);
+ if (NULL == peerinfo)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Could not access PEERINFO service. Exiting.\n"));
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ "HOSTLIST",
+ "HTTPPORT",
+ &port))
+ return GNUNET_SYSERR;
+ if ((0 == port) || (port > UINT16_MAX))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid port number %llu. Exiting.\n"),
+ port);
+ return GNUNET_SYSERR;
+ }
+
+ if (GNUNET_SYSERR ==
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "HOSTLIST",
+ "EXTERNAL_DNS_NAME",
+ &hostname))
+ hostname = GNUNET_RESOLVER_local_fqdn_get ();
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Hostlist service starts on %s:%llu\n"),
+ hostname, port);
+ if (NULL != hostname)
+ {
+ size = strlen (hostname);
+ if (size + 15 > MAX_URL_LEN)
+ {
+ GNUNET_break (0);
+ }
+ else
+ {
+ GNUNET_asprintf (&hostlist_uri,
+ "http://%s:%u/", hostname,
+ (unsigned int) port);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Address to obtain hostlist: `%s'\n"),
+ hostlist_uri);
+ }
+ GNUNET_free (hostname);
+ }
+
+ if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV4"))
+ {
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST",
+ "BINDTOIP", &ipv4));
+ }
+ else
+ ipv4 = NULL;
+ if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV6"))
+ {
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST",
+ "BINDTOIP", &ipv6));
+ }
+ else
+ ipv6 = NULL;
+ sa4 = NULL;
+ if (NULL != ipv4)
+ {
+ if (1 == inet_pton (AF_INET, ipv4, &i4))
+ {
+ memset (&v4, 0, sizeof (v4));
+ v4.sin_family = AF_INET;
+ v4.sin_addr = i4;
+ v4.sin_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ v4.sin_len = sizeof (v4);
+#endif
+ sa4 = (const struct sockaddr *) &v4;
+ }
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("`%s' is not a valid IPv4 address! Ignoring
BINDTOIPV4.\n"),
+ ipv4);
+ GNUNET_free (ipv4);
+ }
+ sa6 = NULL;
+ if (NULL != ipv6)
+ {
+ if (1 == inet_pton (AF_INET6, ipv6, &i6))
+ {
+ memset (&v6, 0, sizeof (v6));
+ v6.sin6_family = AF_INET6;
+ v6.sin6_addr = i6;
+ v6.sin6_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ v6.sin6_len = sizeof (v6);
+#endif
+ sa6 = (const struct sockaddr *) &v6;
+ }
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("`%s' is not a valid IPv6 address! Ignoring
BINDTOIPV6.\n"),
+ ipv6);
+ GNUNET_free (ipv6);
+ }
+
+ daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 | MHD_USE_DEBUG,
+ (uint16_t) port,
+ &accept_policy_callback, NULL,
+ &access_handler_callback, NULL,
+ MHD_OPTION_CONNECTION_LIMIT,
+ (unsigned int) 16,
+ MHD_OPTION_PER_IP_CONNECTION_LIMIT,
+ (unsigned int) 1,
+ MHD_OPTION_CONNECTION_TIMEOUT,
+ (unsigned int) 16,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ (size_t) (16 * 1024),
+ MHD_OPTION_SOCK_ADDR,
+ sa6,
+ MHD_OPTION_END);
+ daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG | MHD_USE_DEBUG,
+ (uint16_t) port,
+ &accept_policy_callback, NULL,
+ &access_handler_callback, NULL,
+ MHD_OPTION_CONNECTION_LIMIT,
+ (unsigned int) 16,
+ MHD_OPTION_PER_IP_CONNECTION_LIMIT,
+ (unsigned int) 1,
+ MHD_OPTION_CONNECTION_TIMEOUT,
+ (unsigned int) 16,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ (size_t) (16 * 1024),
+ MHD_OPTION_SOCK_ADDR,
+ sa4,
+ MHD_OPTION_END);
+
+ if ( (NULL == daemon_handle_v6) &&
+ (NULL == daemon_handle_v4) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Could not start hostlist HTTP server on port %u\n"),
+ (unsigned short) port);
+ return GNUNET_SYSERR;
+ }
+
+ core = co;
+ *server_ch = &connect_handler;
+ *server_dh = &disconnect_handler;
+ if (NULL != daemon_handle_v4)
+ hostlist_task_v4 = prepare_daemon (daemon_handle_v4);
+ if (NULL != daemon_handle_v6)
+ hostlist_task_v6 = prepare_daemon (daemon_handle_v6);
+ notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO,
+ &process_notify, NULL);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Stop server offering our hostlist.
+ */
+void
+GNUNET_HOSTLIST_server_stop ()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist server shutdown\n");
+ if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6)
+ {
+ GNUNET_SCHEDULER_cancel (hostlist_task_v6);
+ hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4)
+ {
+ GNUNET_SCHEDULER_cancel (hostlist_task_v4);
+ hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != daemon_handle_v4)
+ {
+ MHD_stop_daemon (daemon_handle_v4);
+ daemon_handle_v4 = NULL;
+ }
+ if (NULL != daemon_handle_v6)
+ {
+ MHD_stop_daemon (daemon_handle_v6);
+ daemon_handle_v6 = NULL;
+ }
+ if (NULL != response)
+ {
+ MHD_destroy_response (response);
+ response = NULL;
+ }
+ if (NULL != notify)
+ {
+ GNUNET_PEERINFO_notify_cancel (notify);
+ notify = NULL;
+ }
+ if (NULL != builder)
+ {
+ GNUNET_PEERINFO_iterate_cancel (builder->pitr);
+ builder->pitr = NULL;
+ GNUNET_free_non_null (builder->data);
+ GNUNET_free (builder);
+ }
+ if (NULL != peerinfo)
+ {
+ GNUNET_PEERINFO_disconnect (peerinfo);
+ peerinfo = NULL;
+ }
+ cfg = NULL;
+ stats = NULL;
+ core = NULL;
+}
+
+/* end of gnunet-daemon-hostlist_server.c */
Copied: gnunet/src/hostlist/gnunet-daemon-hostlist_server.h (from rev 33486,
gnunet/src/hostlist/hostlist-server.h)
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist_server.h
(rev 0)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist_server.h 2014-06-03 08:41:00 UTC
(rev 33489)
@@ -0,0 +1,63 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file hostlist/gnunet-daemon-hostlist_server.h
+ * @brief hostlist support. Downloads HELLOs via HTTP.
+ * @author Christian Grothoff
+ */
+
+#ifndef GNUNET_DAEMON_HOSTLIST_SERVER_H
+#define GNUNET_DAEMON_HOSTLIST_SERVER_H
+
+#include "gnunet_core_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_util_lib.h"
+
+
+/**
+ * Start server offering our hostlist.
+ *
+ * @param c configuration to use
+ * @param st statistics handle to use
+ * @param co core handle to use
+ * @param server_ch[OUT] set to handler for CORE connect events
+ * @param server_dh[OUT] set to handler for CORE disconnect events
+ * @param advertise #GNUNET_YES if we should advertise our hostlist
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
+ struct GNUNET_STATISTICS_Handle *st,
+ struct GNUNET_CORE_Handle *core,
+ GNUNET_CORE_ConnectEventHandler *server_ch,
+ GNUNET_CORE_DisconnectEventHandler *server_dh,
+ int advertise);
+
+
+/**
+ * Stop server offering our hostlist.
+ */
+void
+GNUNET_HOSTLIST_server_stop (void);
+
+
+#endif
+/* end of gnunet-daemon-hostlist_server.h */
Deleted: gnunet/src/hostlist/hostlist-client.c
===================================================================
--- gnunet/src/hostlist/hostlist-client.c 2014-06-03 08:19:03 UTC (rev
33488)
+++ gnunet/src/hostlist/hostlist-client.c 2014-06-03 08:41:00 UTC (rev
33489)
@@ -1,1654 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 Christian Grothoff
(and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file hostlist/hostlist-client.c
- * @brief hostlist support. Downloads HELLOs via HTTP.
- * @author Christian Grothoff
- * @author Matthias Wachs
- */
-
-#include "platform.h"
-#include "hostlist-client.h"
-#include "gnunet_core_service.h"
-#include "gnunet_hello_lib.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_transport_service.h"
-#include "gnunet-daemon-hostlist.h"
-#include <curl/curl.h>
-#include "gnunet_util_lib.h"
-
-
-/**
- * Number of connections that we must have to NOT download
- * hostlists anymore.
- */
-#define MIN_CONNECTIONS 4
-
-/**
- * Interval between two advertised hostlist tests
- */
-#define TESTING_INTERVAL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 5)
-
-/**
- * A single hostlist obtained by hostlist advertisements
- */
-struct Hostlist
-{
- /**
- * previous entry, used to manage entries in a double linked list
- */
- struct Hostlist *prev;
-
- /**
- * next entry, used to manage entries in a double linked list
- */
- struct Hostlist *next;
-
- /**
- * URI where hostlist can be obtained
- */
- const char *hostlist_uri;
-
- /**
- * Value describing the quality of the hostlist, the bigger the better but
(should) never < 0
- * used for deciding which hostlist is replaced if MAX_NUMBER_HOSTLISTS in
data structure is reached
- * intial value = HOSTLIST_INITIAL
- * increased every successful download by HOSTLIST_SUCCESSFULL_DOWNLOAD
- * increased every successful download by number of obtained HELLO messages
- * decreased every failed download by HOSTLIST_SUCCESSFULL_DOWNLOAD
- */
- uint64_t quality;
-
- /**
- * Time the hostlist advertisement was recieved and the entry was created
- */
- struct GNUNET_TIME_Absolute time_creation;
-
- /**
- * Last time the hostlist was obtained
- */
- struct GNUNET_TIME_Absolute time_last_usage;
-
- /**
- * Number of HELLO messages obtained during last download
- */
- uint32_t hello_count;
-
- /**
- * Number of times the hostlist was successfully obtained
- */
- uint32_t times_used;
-
-};
-
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Statistics handle.
- */
-static struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Transport handle.
- */
-static struct GNUNET_TRANSPORT_Handle *transport;
-
-/**
- * Proxy hostname or ip we are using (can be NULL).
- */
-static char *proxy;
-
-/**
- * Proxy username we are using (can be NULL).
- */
-static char *proxy_username;
-
-/**
- * Proxy password we are using (can be NULL).
- */
-static char *proxy_password;
-
-/**
- * Proxy type we are using (can be NULL).
- */
-static curl_proxytype proxy_type;
-
-/**
- * Number of bytes valid in 'download_buffer'.
- */
-static size_t download_pos;
-
-/**
- * Current URL that we are using.
- */
-static char *current_url;
-
-/**
- * Current CURL handle.
- */
-static CURL *curl;
-
-/**
- * Current multi-CURL handle.
- */
-static CURLM *multi;
-
-/**
- * How many bytes did we download from the current hostlist URL?
- */
-static uint32_t stat_bytes_downloaded;
-
-/**
- * Amount of time we wait between hostlist downloads.
- */
-static struct GNUNET_TIME_Relative hostlist_delay;
-
-/**
- * ID of the task, checking if hostlist download should take plate
- */
-static GNUNET_SCHEDULER_TaskIdentifier ti_check_download;
-
-/**
- * ID of the task downloading the hostlist
- */
-static GNUNET_SCHEDULER_TaskIdentifier ti_download;
-
-/**
- * ID of the task saving the hostlsit in a regular intervall
- */
-static GNUNET_SCHEDULER_TaskIdentifier ti_saving_task;
-
-/**
- * ID of the task called to initiate a download
- */
-static GNUNET_SCHEDULER_TaskIdentifier ti_download_dispatcher_task;
-
-/**
- * ID of the task controlling the locking between two hostlist tests
- */
-static GNUNET_SCHEDULER_TaskIdentifier ti_testing_intervall_task;
-
-/**
- * At what time MUST the current hostlist request be done?
- */
-static struct GNUNET_TIME_Absolute end_time;
-
-/**
- * Head of the linked list used to store hostlists
- */
-static struct Hostlist *linked_list_head;
-
-/**
- * Tail of the linked list used to store hostlists
- */
-static struct Hostlist *linked_list_tail;
-
-/**
- * Current hostlist used for downloading
- */
-static struct Hostlist *current_hostlist;
-
-/**
- * Size of the linke list used to store hostlists
- */
-static unsigned int linked_list_size;
-
-/**
- * Head of the linked list used to store hostlists
- */
-static struct Hostlist *hostlist_to_test;
-
-/**
- * Handle for our statistics GET operation.
- */
-static struct GNUNET_STATISTICS_GetHandle *sget;
-
-/**
- * Set to GNUNET_YES if the current URL had some problems.
- */
-static int stat_bogus_url;
-
-/**
- * Value controlling if a hostlist is tested at the moment
- */
-static int stat_testing_hostlist;
-
-/**
- * Value controlling if a hostlist testing is allowed at the moment
- */
-static int stat_testing_allowed;
-
-/**
- * Value controlling if a hostlist download is running at the moment
- */
-static int stat_download_in_progress;
-
-/**
- * Value saying if a preconfigured bootstrap server is used
- */
-static unsigned int stat_use_bootstrap;
-
-/**
- * Set if we are allowed to learn new hostlists and use them
- */
-static int stat_learning;
-
-/**
- * Value saying if hostlist download was successful
- */
-static unsigned int stat_download_successful;
-
-/**
- * Value saying how many valid HELLO messages were obtained during download
- */
-static unsigned int stat_hellos_obtained;
-
-/**
- * Number of active connections (according to core service).
- */
-static unsigned int stat_connection_count;
-
-
-/**
- * Process downloaded bits by calling callback on each HELLO.
- *
- * @param ptr buffer with downloaded data
- * @param size size of a record
- * @param nmemb number of records downloaded
- * @param ctx unused
- * @return number of bytes that were processed (always size*nmemb)
- */
-static size_t
-callback_download (void *ptr, size_t size, size_t nmemb, void *ctx)
-{
- static char download_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
- const char *cbuf = ptr;
- const struct GNUNET_MessageHeader *msg;
- size_t total;
- size_t cpy;
- size_t left;
- uint16_t msize;
-
- total = size * nmemb;
- stat_bytes_downloaded += total;
- if ((total == 0) || (stat_bogus_url))
- {
- return total; /* ok, no data or bogus data */
- }
-
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("# bytes downloaded from hostlist servers"),
- (int64_t) total, GNUNET_NO);
- left = total;
- while ((left > 0) || (download_pos > 0))
- {
- cpy = GNUNET_MIN (left, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - download_pos);
- memcpy (&download_buffer[download_pos], cbuf, cpy);
- cbuf += cpy;
- download_pos += cpy;
- left -= cpy;
- if (download_pos < sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_assert (0 == left);
- break;
- }
- msg = (const struct GNUNET_MessageHeader *) download_buffer;
- msize = ntohs (msg->size);
- if (msize < sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("# invalid HELLOs downloaded from hostlist
servers"),
- 1, GNUNET_NO);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Invalid `%s' message received from hostlist at `%s'\n"),
- "HELLO", current_url);
- stat_hellos_obtained++;
- stat_bogus_url = 1;
- return total;
- }
- if (download_pos < msize)
- {
- GNUNET_assert (left == 0);
- break;
- }
- if (GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) msg) == msize)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received valid `%s' message from hostlist server.\n",
- "HELLO");
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("# valid HELLOs downloaded from hostlist
servers"),
- 1, GNUNET_NO);
- stat_hellos_obtained++;
- GNUNET_TRANSPORT_offer_hello (transport, msg, NULL, NULL);
- }
- else
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("# invalid HELLOs downloaded from hostlist
servers"),
- 1, GNUNET_NO);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Invalid `%s' message received from hostlist at `%s'\n"),
- "HELLO", current_url);
- stat_bogus_url = GNUNET_YES;
- stat_hellos_obtained++;
- return total;
- }
- memmove (download_buffer, &download_buffer[msize], download_pos - msize);
- download_pos -= msize;
- }
- return total;
-}
-
-
-/**
- * Obtain a hostlist URL that we should use.
- *
- * @return NULL if there is no URL available
- */
-static char *
-get_bootstrap_server ()
-{
- char *servers;
- char *ret;
- size_t urls;
- size_t pos;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST", "SERVERS",
- &servers))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "hostlist", "SERVERS");
- return NULL;
- }
-
- urls = 0;
- if (strlen (servers) > 0)
- {
- urls++;
- pos = strlen (servers) - 1;
- while (pos > 0)
- {
- if (servers[pos] == ' ')
- urls++;
- pos--;
- }
- }
- if (urls == 0)
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "hostlist", "SERVERS");
- GNUNET_free (servers);
- return NULL;
- }
-
- urls = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, urls) + 1;
- pos = strlen (servers) - 1;
- while (pos > 0)
- {
- if (servers[pos] == ' ')
- {
- urls--;
- servers[pos] = '\0';
- }
- if (urls == 0)
- {
- pos++;
- break;
- }
- pos--;
- }
- ret = GNUNET_strdup (&servers[pos]);
- GNUNET_free (servers);
- return ret;
-}
-
-
-/**
- * Method deciding if a preconfigured or advertisied hostlist is used on a
50:50 ratio
- * @return uri to use, NULL if there is no URL available
- */
-static char *
-download_get_url ()
-{
- uint32_t index;
- unsigned int counter;
- struct Hostlist *pos;
-
- if (GNUNET_NO == stat_learning)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Using preconfigured bootstrap server\n");
- current_hostlist = NULL;
- return get_bootstrap_server ();
- }
-
- if ((GNUNET_YES == stat_testing_hostlist) && (NULL != hostlist_to_test))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Testing new advertised hostlist if it is obtainable\n");
- current_hostlist = hostlist_to_test;
- return GNUNET_strdup (hostlist_to_test->hostlist_uri);
- }
-
- if ((GNUNET_YES == stat_use_bootstrap) || (linked_list_size == 0))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Using preconfigured bootstrap server\n");
- current_hostlist = NULL;
- return get_bootstrap_server ();
- }
- index =
- GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, linked_list_size);
- counter = 0;
- pos = linked_list_head;
- while (counter < index)
- {
- pos = pos->next;
- counter++;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using learned hostlist `%s'\n",
- pos->hostlist_uri);
- current_hostlist = pos;
- return GNUNET_strdup (pos->hostlist_uri);
-}
-
-
-#define CURL_EASY_SETOPT(c, a, b) do { ret = curl_easy_setopt (c, a, b); if
(CURLE_OK != ret) GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("%s failed at %s:%d:
`%s'\n"), "curl_easy_setopt", __FILE__, __LINE__, curl_easy_strerror (ret)); }
while (0)
-
-
-/**
- * Method to save hostlist to a file during hostlist client shutdown
- * @param shutdown set if called because of shutdown, entries in linked list
will be destroyed
- */
-static void
-save_hostlist_file (int shutdown);
-
-
-/**
- * add val2 to val1 with overflow check
- *
- * @param val1 value 1
- * @param val2 value 2
- * @return result
- */
-static uint64_t
-checked_add (uint64_t val1, uint64_t val2)
-{
- static uint64_t temp;
- static uint64_t maxv;
-
- maxv = 0;
- maxv--;
-
- temp = val1 + val2;
- if (temp < val1)
- return maxv;
- return temp;
-}
-
-
-/**
- * Subtract val2 from val1 with underflow check
- *
- * @param val1 value 1
- * @param val2 value 2
- * @return result
- */
-static uint64_t
-checked_sub (uint64_t val1, uint64_t val2)
-{
- if (val1 <= val2)
- return 0;
- return (val1 - val2);
-}
-
-
-/**
- * Method to check if a URI is in hostlist linked list
- *
- * @param uri uri to check
- * @return #GNUNET_YES if existing in linked list, #GNUNET_NO if not
- */
-static int
-linked_list_contains (const char *uri)
-{
- struct Hostlist *pos;
-
- pos = linked_list_head;
- while (pos != NULL)
- {
- if (0 == strcmp (pos->hostlist_uri, uri))
- return GNUNET_YES;
- pos = pos->next;
- }
- return GNUNET_NO;
-}
-
-
-/**
- * Method returning the hostlist element with the lowest quality in the
datastore
- * @return hostlist with lowest quality
- */
-static struct Hostlist *
-linked_list_get_lowest_quality ()
-{
- struct Hostlist *pos;
- struct Hostlist *lowest;
-
- if (linked_list_size == 0)
- return NULL;
- lowest = linked_list_head;
- pos = linked_list_head->next;
- while (pos != NULL)
- {
- if (pos->quality < lowest->quality)
- lowest = pos;
- pos = pos->next;
- }
- return lowest;
-}
-
-
-/**
- * Method to insert a hostlist into the datastore. If datastore
- * contains maximum number of elements, the elements with lowest
- * quality is dismissed
- */
-static void
-insert_hostlist ()
-{
- struct Hostlist *lowest_quality;
-
- if (MAX_NUMBER_HOSTLISTS <= linked_list_size)
- {
- /* No free entries available, replace existing entry */
- lowest_quality = linked_list_get_lowest_quality ();
- GNUNET_assert (lowest_quality != NULL);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Removing hostlist with URI `%s' which has the worst quality
of all (%llu)\n",
- lowest_quality->hostlist_uri,
- (unsigned long long) lowest_quality->quality);
- GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail,
- lowest_quality);
- linked_list_size--;
- GNUNET_free (lowest_quality);
- }
- GNUNET_CONTAINER_DLL_insert (linked_list_head, linked_list_tail,
- hostlist_to_test);
- linked_list_size++;
- GNUNET_STATISTICS_set (stats, gettext_noop ("# advertised hostlist URIs"),
- linked_list_size, GNUNET_NO);
- stat_testing_hostlist = GNUNET_NO;
-}
-
-
-/**
- * Method updating hostlist statistics
- */
-static void
-update_hostlist ()
-{
- char *stat;
-
- if (((stat_use_bootstrap == GNUNET_NO) && (NULL != current_hostlist)) ||
- ((stat_testing_hostlist == GNUNET_YES) && (NULL != current_hostlist)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Updating hostlist statics for URI `%s'\n",
- current_hostlist->hostlist_uri);
- current_hostlist->hello_count = stat_hellos_obtained;
- current_hostlist->time_last_usage = GNUNET_TIME_absolute_get ();
- current_hostlist->quality =
- checked_add (current_hostlist->quality,
- (stat_hellos_obtained * HOSTLIST_SUCCESSFUL_HELLO));
- if (GNUNET_YES == stat_download_successful)
- {
- current_hostlist->times_used++;
- current_hostlist->quality =
- checked_add (current_hostlist->quality,
HOSTLIST_SUCCESSFUL_DOWNLOAD);
- GNUNET_asprintf (&stat, gettext_noop ("# advertised URI `%s'
downloaded"),
- current_hostlist->hostlist_uri);
-
- GNUNET_STATISTICS_update (stats, stat, 1, GNUNET_YES);
- GNUNET_free (stat);
- }
- else
- current_hostlist->quality =
- checked_sub (current_hostlist->quality, HOSTLIST_FAILED_DOWNLOAD);
- }
- current_hostlist = NULL;
- /* Alternating the usage of preconfigured and learned hostlists */
-
- if (stat_testing_hostlist == GNUNET_YES)
- return;
-
- if (GNUNET_YES == stat_learning)
- {
- if (stat_use_bootstrap == GNUNET_YES)
- stat_use_bootstrap = GNUNET_NO;
- else
- stat_use_bootstrap = GNUNET_YES;
- }
- else
- stat_use_bootstrap = GNUNET_YES;
-}
-
-
-/**
- * Clean up the state from the task that downloaded the
- * hostlist and schedule the next task.
- */
-static void
-clean_up ()
-{
- CURLMcode mret;
-
- if ((stat_testing_hostlist == GNUNET_YES) &&
- (GNUNET_NO == stat_download_successful) && (NULL != hostlist_to_test))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Advertised hostlist with URI `%s' could not be downloaded.
Advertised URI gets dismissed.\n"),
- hostlist_to_test->hostlist_uri);
- }
-
- if (stat_testing_hostlist == GNUNET_YES)
- {
- stat_testing_hostlist = GNUNET_NO;
- }
- if (NULL != hostlist_to_test)
- {
- GNUNET_free (hostlist_to_test);
- hostlist_to_test = NULL;
- }
-
- if (multi != NULL)
- {
- mret = curl_multi_remove_handle (multi, curl);
- if (mret != CURLM_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_remove_handle", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- }
- mret = curl_multi_cleanup (multi);
- if (mret != CURLM_OK)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_cleanup", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- multi = NULL;
- }
- if (curl != NULL)
- {
- curl_easy_cleanup (curl);
- curl = NULL;
- }
- GNUNET_free_non_null (current_url);
- current_url = NULL;
- stat_bytes_downloaded = 0;
- stat_download_in_progress = GNUNET_NO;
-}
-
-
-/**
- * Task that is run when we are ready to receive more data from the hostlist
- * server.
- *
- * @param cls closure, unused
- * @param tc task context, unused
- */
-static void
-task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Ask CURL for the select set and then schedule the
- * receiving task with the scheduler.
- */
-static void
-download_prepare ()
-{
- CURLMcode mret;
- fd_set rs;
- fd_set ws;
- fd_set es;
- int max;
- struct GNUNET_NETWORK_FDSet *grs;
- struct GNUNET_NETWORK_FDSet *gws;
- long timeout;
- struct GNUNET_TIME_Relative rtime;
-
- max = -1;
- FD_ZERO (&rs);
- FD_ZERO (&ws);
- FD_ZERO (&es);
- mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
- if (mret != CURLM_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_fdset", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- clean_up ();
- return;
- }
- mret = curl_multi_timeout (multi, &timeout);
- if (mret != CURLM_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_timeout", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- clean_up ();
- return;
- }
- rtime =
- GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (end_time),
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, timeout));
- grs = GNUNET_NETWORK_fdset_create ();
- gws = GNUNET_NETWORK_fdset_create ();
- GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
- GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Scheduling task for hostlist download using cURL\n");
- ti_download =
- GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- rtime, grs, gws,
- &task_download, multi);
- GNUNET_NETWORK_fdset_destroy (gws);
- GNUNET_NETWORK_fdset_destroy (grs);
-}
-
-
-/**
- * Task that is run when we are ready to receive more data from the hostlist
- * server.
- *
- * @param cls closure, unused
- * @param tc task context, unused
- */
-static void
-task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- int running;
- struct CURLMsg *msg;
- CURLMcode mret;
-
- ti_download = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Shutdown requested while trying to download hostlist from
`%s'\n",
- current_url);
- update_hostlist ();
- clean_up ();
- return;
- }
- if (0 == GNUNET_TIME_absolute_get_remaining (end_time).rel_value_us)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Timeout trying to download hostlist from `%s'\n"),
- current_url);
- update_hostlist ();
- clean_up ();
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Ready for processing hostlist client request\n");
- do
- {
- running = 0;
- if (stat_bytes_downloaded > MAX_BYTES_PER_HOSTLISTS)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Download limit of %u bytes exceeded, stopping
download\n"),
- MAX_BYTES_PER_HOSTLISTS);
- clean_up ();
- return;
- }
- mret = curl_multi_perform (multi, &running);
- if (running == 0)
- {
- do
- {
- msg = curl_multi_info_read (multi, &running);
- GNUNET_break (msg != NULL);
- if (msg == NULL)
- break;
- switch (msg->msg)
- {
- case CURLMSG_DONE:
- if ((msg->data.result != CURLE_OK) &&
- (msg->data.result != CURLE_GOT_NOTHING))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Download of hostlist from `%s' failed: `%s'\n"),
- current_url,
- curl_easy_strerror (msg->data.result));
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Download of hostlist `%s' completed.\n"),
- current_url);
- stat_download_successful = GNUNET_YES;
- update_hostlist ();
- if (GNUNET_YES == stat_testing_hostlist)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Adding successfully tested hostlist `%s'
datastore.\n"),
- current_url);
- insert_hostlist ();
- hostlist_to_test = NULL;
- stat_testing_hostlist = GNUNET_NO;
- }
- }
- clean_up ();
- return;
- default:
- break;
- }
-
- }
- while ((running > 0));
- }
- }
- while (mret == CURLM_CALL_MULTI_PERFORM);
-
- if (mret != CURLM_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_perform", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- clean_up ();
- }
- download_prepare ();
-}
-
-
-/**
- * Main function that will download a hostlist and process its
- * data.
- */
-static void
-download_hostlist ()
-{
- CURLcode ret;
- CURLMcode mret;
-
-
- current_url = download_get_url ();
- if (current_url == NULL)
- return;
- curl = curl_easy_init ();
- multi = NULL;
- if (curl == NULL)
- {
- GNUNET_break (0);
- clean_up ();
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
- _("Bootstrapping using hostlist at `%s'.\n"), current_url);
-
- stat_download_in_progress = GNUNET_YES;
- stat_download_successful = GNUNET_NO;
- stat_hellos_obtained = 0;
- stat_bytes_downloaded = 0;
-
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# hostlist downloads initiated"), 1,
- GNUNET_NO);
- if (proxy != NULL)
- {
- CURL_EASY_SETOPT (curl, CURLOPT_PROXY, proxy);
- CURL_EASY_SETOPT (curl, CURLOPT_PROXYTYPE, proxy_type);
- if (NULL != proxy_username)
- CURL_EASY_SETOPT (curl, CURLOPT_PROXYUSERNAME, proxy_username);
- if (NULL != proxy_password)
- CURL_EASY_SETOPT (curl, CURLOPT_PROXYPASSWORD, proxy_password);
- }
- download_pos = 0;
- stat_bogus_url = 0;
- CURL_EASY_SETOPT (curl, CURLOPT_WRITEFUNCTION, &callback_download);
- if (ret != CURLE_OK)
- {
- clean_up ();
- return;
- }
- CURL_EASY_SETOPT (curl, CURLOPT_WRITEDATA, NULL);
- if (ret != CURLE_OK)
- {
- clean_up ();
- return;
- }
- CURL_EASY_SETOPT (curl, CURLOPT_FOLLOWLOCATION, 1);
- CURL_EASY_SETOPT (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP |
CURLPROTO_HTTPS);
- CURL_EASY_SETOPT (curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
- CURL_EASY_SETOPT (curl, CURLOPT_MAXREDIRS, 4);
- /* no need to abort if the above failed */
- CURL_EASY_SETOPT (curl, CURLOPT_URL, current_url);
- if (ret != CURLE_OK)
- {
- clean_up ();
- return;
- }
- CURL_EASY_SETOPT (curl, CURLOPT_FAILONERROR, 1);
-#if 0
- CURL_EASY_SETOPT (curl, CURLOPT_VERBOSE, 1);
-#endif
- CURL_EASY_SETOPT (curl, CURLOPT_BUFFERSIZE, GNUNET_SERVER_MAX_MESSAGE_SIZE);
- if (0 == strncmp (current_url, "http", 4))
- CURL_EASY_SETOPT (curl, CURLOPT_USERAGENT, "GNUnet");
- CURL_EASY_SETOPT (curl, CURLOPT_CONNECTTIMEOUT, 60L);
- CURL_EASY_SETOPT (curl, CURLOPT_TIMEOUT, 60L);
-#if 0
- /* this should no longer be needed; we're now single-threaded! */
- CURL_EASY_SETOPT (curl, CURLOPT_NOSIGNAL, 1);
-#endif
- multi = curl_multi_init ();
- if (multi == NULL)
- {
- GNUNET_break (0);
- /* clean_up (); */
- return;
- }
- mret = curl_multi_add_handle (multi, curl);
- if (mret != CURLM_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_add_handle", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- mret = curl_multi_cleanup (multi);
- if (mret != CURLM_OK)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_cleanup", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- multi = NULL;
- clean_up ();
- return;
- }
- end_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
- download_prepare ();
-}
-
-
-static void
-task_download_dispatcher (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- ti_download_dispatcher_task = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download is initiated...\n");
- if (GNUNET_NO == stat_download_in_progress)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download can start
immediately...\n");
- download_hostlist ();
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Download in progess, have to wait...\n");
- ti_download_dispatcher_task =
- GNUNET_SCHEDULER_add_delayed (WAITING_INTERVALL,
- &task_download_dispatcher, NULL);
- }
-}
-
-
-/**
- * Task that checks if we should try to download a hostlist.
- * If so, we initiate the download, otherwise we schedule
- * this task again for a later time.
- */
-static void
-task_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- static int once;
- struct GNUNET_TIME_Relative delay;
-
- ti_check_download = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- if (stats == NULL)
- {
- curl_global_cleanup ();
- return; /* in shutdown */
- }
- if ( (stat_connection_count < MIN_CONNECTIONS) &&
- (GNUNET_SCHEDULER_NO_TASK == ti_download_dispatcher_task) )
- ti_download_dispatcher_task =
- GNUNET_SCHEDULER_add_now (&task_download_dispatcher, NULL);
-
- delay = hostlist_delay;
- if (0 == hostlist_delay.rel_value_us)
- hostlist_delay = GNUNET_TIME_UNIT_SECONDS;
- else
- hostlist_delay = GNUNET_TIME_relative_multiply (hostlist_delay, 2);
- if (hostlist_delay.rel_value_us >
- GNUNET_TIME_UNIT_HOURS.rel_value_us * (1 + stat_connection_count))
- hostlist_delay =
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS,
- (1 + stat_connection_count));
- GNUNET_STATISTICS_set (stats,
- gettext_noop
- ("# milliseconds between hostlist downloads"),
- hostlist_delay.rel_value_us / 1000LL,
- GNUNET_YES);
- if (0 == once)
- {
- delay = GNUNET_TIME_UNIT_ZERO;
- once = 1;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Have %u/%u connections. Will consider downloading hostlist
in %s\n"),
- stat_connection_count, MIN_CONNECTIONS,
- GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
- ti_check_download = GNUNET_SCHEDULER_add_delayed (delay, &task_check, NULL);
-}
-
-
-/**
- * This tasks sets hostlist testing to allowed after intervall between to
testings is reached
- *
- * @param cls closure
- * @param tc TaskContext
- */
-static void
-task_testing_intervall_reset (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- ti_testing_intervall_task = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- stat_testing_allowed = GNUNET_OK;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Testing new hostlist advertisements is allowed again\n");
-}
-
-
-/**
- * Task that writes hostlist entries to a file on a regular base
- *
- * @param cls closure
- * @param tc TaskContext
- */
-static void
-task_hostlist_saving (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- ti_saving_task = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- save_hostlist_file (GNUNET_NO);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Hostlists will be saved to file again in %s\n",
- GNUNET_STRINGS_relative_time_to_string(SAVING_INTERVALL,
GNUNET_YES));
- ti_saving_task =
- GNUNET_SCHEDULER_add_delayed (SAVING_INTERVALL, &task_hostlist_saving,
- NULL);
-}
-
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-handler_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
- GNUNET_assert (stat_connection_count < UINT_MAX);
- stat_connection_count++;
- GNUNET_STATISTICS_update (stats, gettext_noop ("# active connections"), 1,
- GNUNET_NO);
-}
-
-
-/**
- * Method called whenever a given peer disconnects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-handler_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
- GNUNET_assert (stat_connection_count > 0);
- stat_connection_count--;
- GNUNET_STATISTICS_update (stats, gettext_noop ("# active connections"), -1,
- GNUNET_NO);
-}
-
-
-/**
- * Method called whenever an advertisement message arrives.
- *
- * @param cls closure (always NULL)
- * @param peer the peer sending the message
- * @param message the actual message
- * @return #GNUNET_OK to keep the connection open,
- * #GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handler_advertisement (void *cls, const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_MessageHeader *message)
-{
- size_t size;
- size_t uri_size;
- const struct GNUNET_MessageHeader *incoming;
- const char *uri;
- struct Hostlist *hostlist;
-
- GNUNET_assert (ntohs (message->type) ==
- GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
- size = ntohs (message->size);
- if (size <= sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- incoming = (const struct GNUNET_MessageHeader *) message;
- uri = (const char *) &incoming[1];
- uri_size = size - sizeof (struct GNUNET_MessageHeader);
- if (uri[uri_size - 1] != '\0')
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Hostlist client recieved advertisement from `%s' containing URI
`%s'\n",
- GNUNET_i2s (peer), uri);
- if (GNUNET_NO != linked_list_contains (uri))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URI `%s' is already known\n", uri);
- return GNUNET_OK;
- }
-
- if (GNUNET_NO == stat_testing_allowed)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Currently not accepting new advertisements: interval between
to advertisements is not reached\n");
- return GNUNET_SYSERR;
- }
- if (GNUNET_YES == stat_testing_hostlist)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Currently not accepting new advertisements: we are already
testing a hostlist\n");
- return GNUNET_SYSERR;
- }
-
- hostlist = GNUNET_malloc (sizeof (struct Hostlist) + uri_size);
- hostlist->hostlist_uri = (const char *) &hostlist[1];
- memcpy (&hostlist[1], uri, uri_size);
- hostlist->time_creation = GNUNET_TIME_absolute_get ();
- hostlist->quality = HOSTLIST_INITIAL;
- hostlist_to_test = hostlist;
-
- stat_testing_hostlist = GNUNET_YES;
- stat_testing_allowed = GNUNET_NO;
- ti_testing_intervall_task =
- GNUNET_SCHEDULER_add_delayed (TESTING_INTERVAL,
- &task_testing_intervall_reset, NULL);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Testing new hostlist advertisements is locked for the next
%s\n",
- GNUNET_STRINGS_relative_time_to_string (TESTING_INTERVAL,
- GNUNET_YES));
-
- ti_download_dispatcher_task =
- GNUNET_SCHEDULER_add_now (&task_download_dispatcher, NULL);
-
- return GNUNET_OK;
-}
-
-
-/**
- * Continuation called by the statistics code once
- * we go the stat. Initiates hostlist download scheduling.
- *
- * @param cls closure
- * @param success #GNUNET_OK if statistics were
- * successfully obtained, #GNUNET_SYSERR if not.
- */
-static void
-primary_task (void *cls, int success)
-{
- sget = NULL;
- GNUNET_assert (stats != NULL);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Statistics request done, scheduling hostlist download\n");
- ti_check_download = GNUNET_SCHEDULER_add_now (&task_check, NULL);
-}
-
-
-/**
- * We've received the previous delay value from statistics. Remember it.
- *
- * @param cls NULL, unused
- * @param subsystem should be "hostlist", unused
- * @param name will be "milliseconds between hostlist downloads", unused
- * @param value previous delay value, in milliseconds (!)
- * @param is_persistent unused, will be GNUNET_YES
- */
-static int
-process_stat (void *cls, const char *subsystem, const char *name,
- uint64_t value, int is_persistent)
-{
- hostlist_delay.rel_value_us = value * 1000LL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Initial time between hostlist downloads is %s\n",
- GNUNET_STRINGS_relative_time_to_string (hostlist_delay,
GNUNET_YES));
- return GNUNET_OK;
-}
-
-
-/**
- * Method to load persistent hostlist file during hostlist client startup
- */
-static void
-load_hostlist_file ()
-{
- char *filename;
- char *uri;
- char *emsg;
- struct Hostlist *hostlist;
- uint32_t times_used;
- uint32_t hellos_returned;
- uint64_t quality;
- uint64_t last_used;
- uint64_t created;
- uint32_t counter;
-
- uri = NULL;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST", "HOSTLISTFILE",
- &filename))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "hostlist", "HOSTLISTFILE");
- return;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Loading saved hostlist entries from file `%s' \n"),
- filename);
- if (GNUNET_NO == GNUNET_DISK_file_test (filename))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Hostlist file `%s' does not exist\n"), filename);
- GNUNET_free (filename);
- return;
- }
-
- struct GNUNET_BIO_ReadHandle *rh = GNUNET_BIO_read_open (filename);
-
- if (NULL == rh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Could not open file `%s' for reading to load hostlists:
%s\n"),
- filename, STRERROR (errno));
- GNUNET_free (filename);
- return;
- }
-
- counter = 0;
- while ((GNUNET_OK == GNUNET_BIO_read_string (rh, "url", &uri, MAX_URL_LEN))
&&
- (NULL != uri) && (GNUNET_OK == GNUNET_BIO_read_int32 (rh,
×_used))
- && (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality)) &&
- (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used)) &&
- (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &created)) &&
- (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &hellos_returned)))
- {
- hostlist = GNUNET_malloc (sizeof (struct Hostlist) + strlen (uri) + 1);
- hostlist->hello_count = hellos_returned;
- hostlist->hostlist_uri = (const char *) &hostlist[1];
- memcpy (&hostlist[1], uri, strlen (uri) + 1);
- hostlist->quality = quality;
- hostlist->time_creation.abs_value_us = created;
- hostlist->time_last_usage.abs_value_us = last_used;
- GNUNET_CONTAINER_DLL_insert (linked_list_head, linked_list_tail, hostlist);
- linked_list_size++;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Added hostlist entry eith URI `%s' \n",
- hostlist->hostlist_uri);
- GNUNET_free (uri);
- uri = NULL;
- counter++;
- if (counter >= MAX_NUMBER_HOSTLISTS)
- break;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("%u hostlist URIs loaded from file\n"),
- counter);
- GNUNET_STATISTICS_set (stats, gettext_noop ("# hostlist URIs read from
file"),
- counter, GNUNET_YES);
- GNUNET_STATISTICS_set (stats, gettext_noop ("# advertised hostlist URIs"),
- linked_list_size, GNUNET_NO);
-
- GNUNET_free_non_null (uri);
- emsg = NULL;
- (void) GNUNET_BIO_read_close (rh, &emsg);
- if (emsg != NULL)
- GNUNET_free (emsg);
- GNUNET_free (filename);
-}
-
-
-/**
- * Method to save persistent hostlist file during hostlist client shutdown
- * @param shutdown set if called because of shutdown, entries in linked list
will be destroyed
- */
-static void
-save_hostlist_file (int shutdown)
-{
- char *filename;
- struct Hostlist *pos;
- struct GNUNET_BIO_WriteHandle *wh;
- int ok;
- uint32_t counter;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST", "HOSTLISTFILE",
- &filename))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "hostlist", "HOSTLISTFILE");
- return;
- }
- if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
- {
- GNUNET_free (filename);
- return;
- }
- wh = GNUNET_BIO_write_open (filename);
- if (NULL == wh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Could not open file `%s' for writing to save hostlists:
%s\n"),
- filename, STRERROR (errno));
- GNUNET_free (filename);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Writing %u hostlist URIs to `%s'\n"),
- linked_list_size, filename);
- /* add code to write hostlists to file using bio */
- ok = GNUNET_YES;
- counter = 0;
- while (NULL != (pos = linked_list_head))
- {
- if (GNUNET_YES == shutdown)
- {
- GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail, pos);
- linked_list_size--;
- }
- if (GNUNET_YES == ok)
- {
- if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pos->hostlist_uri)) ||
- (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->times_used)) ||
- (GNUNET_OK != GNUNET_BIO_write_int64 (wh, pos->quality)) ||
- (GNUNET_OK !=
- GNUNET_BIO_write_int64 (wh, pos->time_last_usage.abs_value_us)) ||
- (GNUNET_OK !=
- GNUNET_BIO_write_int64 (wh, pos->time_creation.abs_value_us)) ||
- (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->hello_count)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Error writing hostlist URIs to file `%s'\n"), filename);
- ok = GNUNET_NO;
- }
- }
-
- if (GNUNET_YES == shutdown)
- GNUNET_free (pos);
- counter++;
- if (counter >= MAX_NUMBER_HOSTLISTS)
- break;
- }
- GNUNET_STATISTICS_set (stats,
- gettext_noop ("# hostlist URIs written to file"),
- counter, GNUNET_YES);
-
- if (GNUNET_OK != GNUNET_BIO_write_close (wh))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Error writing hostlist URIs to file `%s'\n"), filename);
- GNUNET_free (filename);
-}
-
-
-/**
- * Start downloading hostlists from hostlist servers as necessary.
- */
-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_CORE_MessageCallback *msgh, int learn)
-{
- char *filename;
- char *proxytype_str;
- int result;
-
- GNUNET_assert (NULL != st);
- if (0 != curl_global_init (CURL_GLOBAL_WIN32))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL);
- if (NULL == transport)
- {
- curl_global_cleanup ();
- return GNUNET_SYSERR;
- }
- cfg = c;
- stats = st;
-
- /* Read proxy configuration */
- if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
- "HOSTLIST", "PROXY", &proxy))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Found proxy host: `%s'\n",
- proxy);
- /* proxy username */
- if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
- "HOSTLIST", "PROXY_USERNAME", &proxy_username))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Found proxy username name: `%s'\n",
- proxy_username);
- }
-
- /* proxy password */
- if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
- "HOSTLIST", "PROXY_PASSWORD", &proxy_password))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Found proxy password name: `%s'\n",
- proxy_password);
- }
-
- /* proxy type */
- if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
- "HOSTLIST", "PROXY_TYPE", &proxytype_str))
- {
- GNUNET_STRINGS_utf8_toupper (proxytype_str, proxytype_str);
-
- proxy_type = CURLPROXY_HTTP;
- if (0 == strcmp(proxytype_str, "HTTP"))
- proxy_type = CURLPROXY_HTTP;
- else if (0 == strcmp(proxytype_str, "HTTP_1_0"))
- proxy_type = CURLPROXY_HTTP_1_0;
- else if (0 == strcmp(proxytype_str, "SOCKS4"))
- proxy_type = CURLPROXY_SOCKS4;
- else if (0 == strcmp(proxytype_str, "SOCKS5"))
- proxy_type = CURLPROXY_SOCKS5;
- else if (0 == strcmp(proxytype_str, "SOCKS4A"))
- proxy_type = CURLPROXY_SOCKS4A;
- else if (0 == strcmp(proxytype_str, "SOCKS5_HOSTNAME"))
- proxy_type = CURLPROXY_SOCKS5_HOSTNAME ;
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid proxy type: `%s', disabling proxy! Check
configuration!\n"),
- proxytype_str);
- GNUNET_free (proxytype_str);
-
- GNUNET_free (proxy);
- proxy = NULL;
- GNUNET_free_non_null (proxy_username);
- proxy_username = NULL;
- GNUNET_free_non_null (proxy_password);
- proxy_password = NULL;
-
- return GNUNET_SYSERR;
- }
- }
- GNUNET_free_non_null (proxytype_str);
- }
-
- stat_learning = learn;
- *ch = &handler_connect;
- *dh = &handler_disconnect;
- linked_list_head = NULL;
- linked_list_tail = NULL;
- stat_use_bootstrap = GNUNET_YES;
- stat_testing_hostlist = GNUNET_NO;
- stat_testing_allowed = GNUNET_YES;
-
- if (GNUNET_YES == stat_learning)
- {
- *msgh = &handler_advertisement;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Learning is enabled on this peer\n"));
- load_hostlist_file ();
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Hostlists will be saved to file again in %s\n",
- GNUNET_STRINGS_relative_time_to_string (SAVING_INTERVALL,
GNUNET_YES));
- ti_saving_task =
- GNUNET_SCHEDULER_add_delayed (SAVING_INTERVALL, &task_hostlist_saving,
- NULL);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Learning is not enabled on this peer\n"));
- *msgh = NULL;
- if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST",
- "HOSTLISTFILE", &filename))
- {
- if (GNUNET_YES == GNUNET_DISK_file_test (filename))
- {
- result = remove (filename);
- if (result == 0)
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Since learning is not enabled on this peer, hostlist
file `%s' was removed\n"),
- filename);
- else
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Hostlist file `%s' could not be removed\n"),
filename);
- }
- }
- GNUNET_free (filename);
- }
- sget = GNUNET_STATISTICS_get (stats, "hostlist",
- gettext_noop
- ("# milliseconds between hostlist downloads"),
- GNUNET_TIME_UNIT_MINUTES, &primary_task,
&process_stat,
- NULL);
- return GNUNET_OK;
-}
-
-
-/**
- * Stop downloading hostlists from hostlist servers as necessary.
- */
-void
-GNUNET_HOSTLIST_client_stop ()
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist client shutdown\n");
- if (NULL != sget)
- {
- GNUNET_STATISTICS_get_cancel (sget);
- sget = NULL;
- }
- stats = NULL;
- if (GNUNET_YES == stat_learning)
- save_hostlist_file (GNUNET_YES);
- if (ti_saving_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (ti_saving_task);
- ti_saving_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- if (ti_download_dispatcher_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (ti_download_dispatcher_task);
- ti_download_dispatcher_task = GNUNET_SCHEDULER_NO_TASK;
- }
- if (ti_testing_intervall_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (ti_testing_intervall_task);
- ti_testing_intervall_task = GNUNET_SCHEDULER_NO_TASK;
- }
- if (ti_download != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (ti_download);
- ti_download = GNUNET_SCHEDULER_NO_TASK;
- }
- if (ti_check_download != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (ti_check_download);
- ti_check_download = GNUNET_SCHEDULER_NO_TASK;
- curl_global_cleanup ();
- }
- if (transport != NULL)
- {
- GNUNET_TRANSPORT_disconnect (transport);
- transport = NULL;
- }
- GNUNET_free_non_null (proxy);
- proxy = NULL;
- GNUNET_free_non_null (proxy_username);
- proxy_username = NULL;
- GNUNET_free_non_null (proxy_password);
- proxy_password = NULL;
-
- cfg = NULL;
-}
-
-/* end of hostlist-client.c */
Deleted: gnunet/src/hostlist/hostlist-client.h
===================================================================
--- gnunet/src/hostlist/hostlist-client.h 2014-06-03 08:19:03 UTC (rev
33488)
+++ gnunet/src/hostlist/hostlist-client.h 2014-06-03 08:41:00 UTC (rev
33489)
@@ -1,108 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2009 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file hostlist/hostlist-client.h
- * @brief hostlist support. Downloads HELLOs via HTTP.
- * @author Christian Grothoff
- */
-
-#ifndef HOSTLIST_CLIENT_H
-#define HOSTLIST_CLIENT_H
-
-#include "gnunet_core_service.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_time_lib.h"
-
-/**
- * Maximum number of hostlist that are saved
- */
-#define MAX_NUMBER_HOSTLISTS 30
-
-/**
- * Time intervall hostlists are saved to disk
- */
-#define SAVING_INTERVALL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_MINUTES, 30)
-
-/**
- * Time interval between two hostlist tests
- */
-#define TESTING_INTERVALL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 3)
-
-/**
- * Time interval for download dispatcher before a download is re-scheduled
- */
-#define WAITING_INTERVALL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 1)
-
-/**
- * Defines concerning the hostlist quality metric
- */
-
-/**
- * Initial quality of a new created hostlist
- */
-#define HOSTLIST_INITIAL 10000
-
-/**
- * Value subtracted each time a hostlist download fails
- */
-#define HOSTLIST_FAILED_DOWNLOAD 100
-
-/**
- * Value added each time a hostlist download is successful
- */
-#define HOSTLIST_SUCCESSFUL_DOWNLOAD 100
-
-/**
- * Value added for each valid HELLO recived during a hostlist download
- */
-#define HOSTLIST_SUCCESSFUL_HELLO 1
-
-
-
-/**
- * Start downloading hostlists from hostlist servers as necessary.
- *
- * @param c the configuration to use
- * @param st hande for publishing statistics
- * @param ch set to handler for connect notifications
- * @param dh set to handler for disconnect notifications
- * @param msgh set to handler for message handler notifications
- * @param learn set if client is learning new hostlists
- * @return GNUNET_OK on success
- */
-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_CORE_MessageCallback *msgh, int learn);
-
-
-/**
- * Stop downloading hostlists from hostlist servers as necessary.
- */
-void
-GNUNET_HOSTLIST_client_stop (void);
-
-
-#endif
-/* end of hostlist-client.h */
Deleted: gnunet/src/hostlist/hostlist-server.c
===================================================================
--- gnunet/src/hostlist/hostlist-server.c 2014-06-03 08:19:03 UTC (rev
33488)
+++ gnunet/src/hostlist/hostlist-server.c 2014-06-03 08:41:00 UTC (rev
33489)
@@ -1,802 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2008, 2009, 2010, 2014 Christian Grothoff (and other contributing
authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file hostlist/hostlist-server.c
- * @author Christian Grothoff, Matthias Wachs, David Barksdale
- * @brief application to provide an integrated hostlist HTTP server
- */
-
-#include "platform.h"
-#include <microhttpd.h>
-#include "hostlist-server.h"
-#include "gnunet_hello_lib.h"
-#include "gnunet_peerinfo_service.h"
-#include "gnunet-daemon-hostlist.h"
-#include "gnunet_resolver_service.h"
-
-
-/**
- * Handle to the HTTP server as provided by libmicrohttpd for IPv6.
- */
-static struct MHD_Daemon *daemon_handle_v6;
-
-/**
- * Handle to the HTTP server as provided by libmicrohttpd for IPv4.
- */
-static struct MHD_Daemon *daemon_handle_v4;
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * For keeping statistics.
- */
-static struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Handle to the core service (NULL until we've connected to it).
- */
-static struct GNUNET_CORE_Handle *core;
-
-/**
- * Handle to the peerinfo notify service (NULL until we've connected to it).
- */
-static struct GNUNET_PEERINFO_NotifyContext *notify;
-
-/**
- * Our primary task for IPv4.
- */
-static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v4;
-
-/**
- * Our primary task for IPv6.
- */
-static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v6;
-
-/**
- * Our canonical response.
- */
-static struct MHD_Response *response;
-
-/**
- * Handle for accessing peerinfo service.
- */
-static struct GNUNET_PEERINFO_Handle *peerinfo;
-
-/**
- * Set if we are allowed to advertise our hostlist to others.
- */
-static int advertising;
-
-/**
- * Buffer for the hostlist address
- */
-static char *hostlist_uri;
-
-
-/**
- * Context for host processor.
- */
-struct HostSet
-{
- unsigned int size;
-
- char *data;
-
- struct GNUNET_PEERINFO_IteratorContext *pitr;
-};
-
-
-/**
- * NULL if we are not currenlty iterating over peer information.
- */
-static struct HostSet *builder;
-
-
-/**
- * Function that assembles our response.
- */
-static void
-finish_response ()
-{
- if (NULL != response)
- MHD_destroy_response (response);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Creating hostlist response with %u bytes\n",
- (unsigned int) builder->size);
- response =
- MHD_create_response_from_data (builder->size, builder->data, MHD_YES,
- MHD_NO);
- if ((NULL == daemon_handle_v4) && (NULL == daemon_handle_v6))
- {
- MHD_destroy_response (response);
- response = NULL;
- }
- GNUNET_STATISTICS_set (stats, gettext_noop ("bytes in hostlist"),
- builder->size, GNUNET_YES);
- GNUNET_free (builder);
- builder = NULL;
-}
-
-
-/**
- * Set @a cls to #GNUNET_YES (we have an address!).
- *
- * @param cls closure, an `int *`
- * @param address the address (ignored)
- * @param expiration expiration time (call is ignored if this is in the past)
- * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured)
- */
-static int
-check_has_addr (void *cls, const struct GNUNET_HELLO_Address *address,
- struct GNUNET_TIME_Absolute expiration)
-{
- int *arg = cls;
-
- if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("expired addresses encountered"),
1,
- GNUNET_YES);
- return GNUNET_YES; /* ignore this address */
- }
- *arg = GNUNET_YES;
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Callback that processes each of the known HELLOs for the
- * hostlist response construction.
- */
-static void
-host_processor (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Message *hello,
- const char *err_msg)
-{
- size_t old;
- size_t s;
- int has_addr;
-
- if (NULL != err_msg)
- {
- GNUNET_assert (NULL == peer);
- builder->pitr = NULL;
- GNUNET_free_non_null (builder->data);
- GNUNET_free (builder);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Error in communication with PEERINFO service: %s\n"),
- err_msg);
- return;
- }
- if (NULL == peer)
- {
- builder->pitr = NULL;
- finish_response ();
- return;
- }
- if (NULL == hello)
- return;
- has_addr = GNUNET_NO;
- GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_has_addr,
&has_addr);
- if (GNUNET_NO == has_addr)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "HELLO for peer `%4s' has no address, not suitable for
hostlist!\n",
- GNUNET_i2s (peer));
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("HELLOs without addresses encountered
(ignored)"),
- 1, GNUNET_NO);
- return;
- }
- old = builder->size;
- s = GNUNET_HELLO_size (hello);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
- (unsigned int) s, "HELLO", GNUNET_i2s (peer));
- if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) ||
- (old + s >= MAX_BYTES_PER_HOSTLISTS))
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("bytes not included in hostlist (size limit)"),
- s, GNUNET_NO);
- return; /* too large, skip! */
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Adding peer `%s' to hostlist (%u bytes)\n", GNUNET_i2s (peer),
- (unsigned int) s);
- GNUNET_array_grow (builder->data, builder->size, old + s);
- memcpy (&builder->data[old], hello, s);
-}
-
-
-
-/**
- * Hostlist access policy (very permissive, allows everything).
- */
-static int
-accept_policy_callback (void *cls, const struct sockaddr *addr,
- socklen_t addrlen)
-{
- if (NULL == response)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received request for hostlist, but I am not yet ready;
rejecting!\n");
- return MHD_NO;
- }
- return MHD_YES; /* accept all */
-}
-
-
-/**
- * Add headers to a request indicating that we allow Cross-Origin Resource
- * Sharing.
- */
-static void
-add_cors_headers(struct MHD_Response *response)
-{
- MHD_add_response_header (response,
- "Access-Control-Allow-Origin",
- "*");
- MHD_add_response_header (response,
- "Access-Control-Allow-Methods",
- "GET, OPTIONS");
- MHD_add_response_header (response,
- "Access-Control-Max-Age",
- "86400");
-}
-
-
-/**
- * Main request handler.
- */
-static int
-access_handler_callback (void *cls, struct MHD_Connection *connection,
- const char *url, const char *method,
- const char *version, const char *upload_data,
- size_t * upload_data_size, void **con_cls)
-{
- static int dummy;
-
- /* CORS pre-flight request */
- if (0 == strcmp (MHD_HTTP_METHOD_OPTIONS, method))
- {
- struct MHD_Response *options_response;
- int rc;
-
- options_response = MHD_create_response_from_buffer (0, NULL,
-
MHD_RESPMEM_PERSISTENT);
- add_cors_headers(options_response);
- rc = MHD_queue_response (connection, MHD_HTTP_OK, options_response);
- MHD_destroy_response (options_response);
- return rc;
- }
- if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Refusing `%s' request to hostlist server\n"), method);
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("hostlist requests refused (not HTTP GET)"), 1,
- GNUNET_YES);
- return MHD_NO;
- }
- if (NULL == *con_cls)
- {
- (*con_cls) = &dummy;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending 100 CONTINUE reply\n");
- return MHD_YES; /* send 100 continue */
- }
- if (0 != *upload_data_size)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Refusing `%s' request with %llu bytes of upload data\n"),
- method, (unsigned long long) *upload_data_size);
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("hostlist requests refused (upload data)"), 1,
- GNUNET_YES);
- return MHD_NO; /* do not support upload data */
- }
- if (NULL == response)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Could not handle hostlist request since I do not have a
response yet\n"));
- GNUNET_STATISTICS_update (stats,
- gettext_noop
- ("hostlist requests refused (not ready)"), 1,
- GNUNET_YES);
- return MHD_NO; /* internal error, no response yet */
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Received request for our hostlist\n"));
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("hostlist requests processed"),
- 1, GNUNET_YES);
- add_cors_headers (response);
- return MHD_queue_response (connection, MHD_HTTP_OK, response);
-}
-
-
-/**
- * Handler called by core when core is ready to transmit message
- * @param cls closure
- * @param size size of buffer to copy message to
- * @param buf buffer to copy message to
- */
-static size_t
-adv_transmit_ready (void *cls, size_t size, void *buf)
-{
- static uint64_t hostlist_adv_count;
- size_t transmission_size;
- size_t uri_size; /* Including \0 termination! */
- struct GNUNET_MessageHeader header;
- char *cbuf;
-
- if (NULL == buf)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmission failed, buffer invalid!\n");
- return 0;
- }
- uri_size = strlen (hostlist_uri) + 1;
- transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size;
- header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
- header.size = htons (transmission_size);
- GNUNET_assert (size >= transmission_size);
- memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader));
- cbuf = buf;
- memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)], hostlist_uri, uri_size);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sent advertisement message: Copied %u bytes into buffer!\n",
- (unsigned int) transmission_size);
- hostlist_adv_count++;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " # Sent advertisement message: %u\n",
- hostlist_adv_count);
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# hostlist advertisements send"), 1,
- GNUNET_NO);
- return transmission_size;
-}
-
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
- size_t size;
-
- if (!advertising)
- return;
- if (NULL == hostlist_uri)
- return;
- size = strlen (hostlist_uri) + 1;
- if (size + sizeof (struct GNUNET_MessageHeader) >=
- GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- return;
- }
- size += sizeof (struct GNUNET_MessageHeader);
- if (NULL == core)
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Asked core to transmit advertisement message with a size of %u
bytes to peer `%s'\n",
- size, GNUNET_i2s (peer));
- if (NULL ==
- GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES,
- GNUNET_CORE_PRIO_BEST_EFFORT,
- GNUNET_ADV_TIMEOUT, peer, size,
- &adv_transmit_ready, NULL))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Advertisement message could not be queued by core\n"));
- }
-}
-
-
-/**
- * Method called whenever a given peer disconnects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
- /* nothing to do */
-}
-
-
-/**
- * PEERINFO calls this function to let us know about a possible peer
- * that we might want to connect to.
- *
- * @param cls closure (not used)
- * @param peer potential peer to connect to
- * @param hello HELLO for this peer (or NULL)
- * @param err_msg NULL if successful, otherwise contains error message
- */
-static void
-process_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Message *hello, const char *err_msg)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Peerinfo is notifying us to rebuild our hostlist\n");
- if (NULL != err_msg)
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Error in communication with PEERINFO service: %s\n"),
- err_msg);
- if (NULL != builder)
- {
- /* restart re-build already in progress ... */
- GNUNET_PEERINFO_iterate_cancel (builder->pitr);
- GNUNET_free_non_null (builder->data);
- builder->size = 0;
- builder->data = NULL;
- }
- else
- {
- builder = GNUNET_new (struct HostSet);
- }
- GNUNET_assert (NULL != peerinfo);
- builder->pitr =
- GNUNET_PEERINFO_iterate (peerinfo, GNUNET_NO, NULL,
GNUNET_TIME_UNIT_MINUTES,
- &host_processor, NULL);
-}
-
-
-/**
- * Function that queries MHD's select sets and
- * starts the task waiting for them.
- */
-static GNUNET_SCHEDULER_TaskIdentifier
-prepare_daemon (struct MHD_Daemon *daemon_handle);
-
-
-/**
- * Call MHD to process pending requests and then go back
- * and schedule the next run.
- */
-static void
-run_daemon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct MHD_Daemon *daemon_handle = cls;
-
- if (daemon_handle == daemon_handle_v4)
- hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
- else
- hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
-
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
- if (daemon_handle == daemon_handle_v4)
- hostlist_task_v4 = prepare_daemon (daemon_handle);
- else
- hostlist_task_v6 = prepare_daemon (daemon_handle);
-}
-
-
-/**
- * Function that queries MHD's select sets and
- * starts the task waiting for them.
- */
-static GNUNET_SCHEDULER_TaskIdentifier
-prepare_daemon (struct MHD_Daemon *daemon_handle)
-{
- GNUNET_SCHEDULER_TaskIdentifier ret;
- fd_set rs;
- fd_set ws;
- fd_set es;
- struct GNUNET_NETWORK_FDSet *wrs;
- struct GNUNET_NETWORK_FDSet *wws;
- int max;
- MHD_UNSIGNED_LONG_LONG timeout;
- int haveto;
- struct GNUNET_TIME_Relative tv;
-
- FD_ZERO (&rs);
- FD_ZERO (&ws);
- FD_ZERO (&es);
- wrs = GNUNET_NETWORK_fdset_create ();
- wws = GNUNET_NETWORK_fdset_create ();
- max = -1;
- GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es,
&max));
- haveto = MHD_get_timeout (daemon_handle, &timeout);
- if (haveto == MHD_YES)
- tv.rel_value_us = (uint64_t) timeout * 1000LL;
- else
- tv = GNUNET_TIME_UNIT_FOREVER_REL;
- GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
- GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
- ret =
- GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
- tv, wrs, wws,
- &run_daemon, daemon_handle);
- GNUNET_NETWORK_fdset_destroy (wrs);
- GNUNET_NETWORK_fdset_destroy (wws);
- return ret;
-}
-
-
-/**
- * Start server offering our hostlist.
- *
- * @return #GNUNET_OK on success
- */
-int
-GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
- struct GNUNET_STATISTICS_Handle *st,
- struct GNUNET_CORE_Handle *co,
- GNUNET_CORE_ConnectEventHandler *server_ch,
- GNUNET_CORE_DisconnectEventHandler *server_dh,
- int advertise)
-{
- unsigned long long port;
- char *hostname;
- char *ipv4;
- char *ipv6;
- size_t size;
- struct in_addr i4;
- struct in6_addr i6;
- struct sockaddr_in v4;
- struct sockaddr_in6 v6;
- const struct sockaddr *sa4;
- const struct sockaddr *sa6;
-
- advertising = advertise;
- if (! advertising)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Advertising not enabled on this hostlist server\n");
- else
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Advertising enabled on this hostlist server\n");
- cfg = c;
- stats = st;
- peerinfo = GNUNET_PEERINFO_connect (cfg);
- if (NULL == peerinfo)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Could not access PEERINFO service. Exiting.\n"));
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
- "HOSTLIST",
- "HTTPPORT",
- &port))
- return GNUNET_SYSERR;
- if ((0 == port) || (port > UINT16_MAX))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid port number %llu. Exiting.\n"),
- port);
- return GNUNET_SYSERR;
- }
-
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "HOSTLIST",
- "EXTERNAL_DNS_NAME",
- &hostname))
- hostname = GNUNET_RESOLVER_local_fqdn_get ();
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Hostlist service starts on %s:%llu\n"),
- hostname, port);
- if (NULL != hostname)
- {
- size = strlen (hostname);
- if (size + 15 > MAX_URL_LEN)
- {
- GNUNET_break (0);
- }
- else
- {
- GNUNET_asprintf (&hostlist_uri,
- "http://%s:%u/", hostname,
- (unsigned int) port);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Address to obtain hostlist: `%s'\n"),
- hostlist_uri);
- }
- GNUNET_free (hostname);
- }
-
- if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV4"))
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST",
- "BINDTOIP", &ipv4));
- }
- else
- ipv4 = NULL;
- if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV6"))
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST",
- "BINDTOIP", &ipv6));
- }
- else
- ipv6 = NULL;
- sa4 = NULL;
- if (NULL != ipv4)
- {
- if (1 == inet_pton (AF_INET, ipv4, &i4))
- {
- memset (&v4, 0, sizeof (v4));
- v4.sin_family = AF_INET;
- v4.sin_addr = i4;
- v4.sin_port = htons (port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
- v4.sin_len = sizeof (v4);
-#endif
- sa4 = (const struct sockaddr *) &v4;
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("`%s' is not a valid IPv4 address! Ignoring
BINDTOIPV4.\n"),
- ipv4);
- GNUNET_free (ipv4);
- }
- sa6 = NULL;
- if (NULL != ipv6)
- {
- if (1 == inet_pton (AF_INET6, ipv6, &i6))
- {
- memset (&v6, 0, sizeof (v6));
- v6.sin6_family = AF_INET6;
- v6.sin6_addr = i6;
- v6.sin6_port = htons (port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
- v6.sin6_len = sizeof (v6);
-#endif
- sa6 = (const struct sockaddr *) &v6;
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("`%s' is not a valid IPv6 address! Ignoring
BINDTOIPV6.\n"),
- ipv6);
- GNUNET_free (ipv6);
- }
-
- daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 | MHD_USE_DEBUG,
- (uint16_t) port,
- &accept_policy_callback, NULL,
- &access_handler_callback, NULL,
- MHD_OPTION_CONNECTION_LIMIT,
- (unsigned int) 16,
- MHD_OPTION_PER_IP_CONNECTION_LIMIT,
- (unsigned int) 1,
- MHD_OPTION_CONNECTION_TIMEOUT,
- (unsigned int) 16,
- MHD_OPTION_CONNECTION_MEMORY_LIMIT,
- (size_t) (16 * 1024),
- MHD_OPTION_SOCK_ADDR,
- sa6,
- MHD_OPTION_END);
- daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG | MHD_USE_DEBUG,
- (uint16_t) port,
- &accept_policy_callback, NULL,
- &access_handler_callback, NULL,
- MHD_OPTION_CONNECTION_LIMIT,
- (unsigned int) 16,
- MHD_OPTION_PER_IP_CONNECTION_LIMIT,
- (unsigned int) 1,
- MHD_OPTION_CONNECTION_TIMEOUT,
- (unsigned int) 16,
- MHD_OPTION_CONNECTION_MEMORY_LIMIT,
- (size_t) (16 * 1024),
- MHD_OPTION_SOCK_ADDR,
- sa4,
- MHD_OPTION_END);
-
- if ( (NULL == daemon_handle_v6) &&
- (NULL == daemon_handle_v4) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Could not start hostlist HTTP server on port %u\n"),
- (unsigned short) port);
- return GNUNET_SYSERR;
- }
-
- core = co;
- *server_ch = &connect_handler;
- *server_dh = &disconnect_handler;
- if (NULL != daemon_handle_v4)
- hostlist_task_v4 = prepare_daemon (daemon_handle_v4);
- if (NULL != daemon_handle_v6)
- hostlist_task_v6 = prepare_daemon (daemon_handle_v6);
- notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO,
- &process_notify, NULL);
- return GNUNET_OK;
-}
-
-
-/**
- * Stop server offering our hostlist.
- */
-void
-GNUNET_HOSTLIST_server_stop ()
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist server shutdown\n");
- if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6)
- {
- GNUNET_SCHEDULER_cancel (hostlist_task_v6);
- hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
- }
- if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4)
- {
- GNUNET_SCHEDULER_cancel (hostlist_task_v4);
- hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
- }
- if (NULL != daemon_handle_v4)
- {
- MHD_stop_daemon (daemon_handle_v4);
- daemon_handle_v4 = NULL;
- }
- if (NULL != daemon_handle_v6)
- {
- MHD_stop_daemon (daemon_handle_v6);
- daemon_handle_v6 = NULL;
- }
- if (NULL != response)
- {
- MHD_destroy_response (response);
- response = NULL;
- }
- if (NULL != notify)
- {
- GNUNET_PEERINFO_notify_cancel (notify);
- notify = NULL;
- }
- if (NULL != builder)
- {
- GNUNET_PEERINFO_iterate_cancel (builder->pitr);
- builder->pitr = NULL;
- GNUNET_free_non_null (builder->data);
- GNUNET_free (builder);
- }
- if (NULL != peerinfo)
- {
- GNUNET_PEERINFO_disconnect (peerinfo);
- peerinfo = NULL;
- }
- cfg = NULL;
- stats = NULL;
- core = NULL;
-}
-
-/* end of hostlist-server.c */
Deleted: gnunet/src/hostlist/hostlist-server.h
===================================================================
--- gnunet/src/hostlist/hostlist-server.h 2014-06-03 08:19:03 UTC (rev
33488)
+++ gnunet/src/hostlist/hostlist-server.h 2014-06-03 08:41:00 UTC (rev
33489)
@@ -1,58 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2009 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file hostlist/hostlist-server.h
- * @brief hostlist support. Downloads HELLOs via HTTP.
- * @author Christian Grothoff
- */
-
-#ifndef HOSTLIST_SERVER_H
-#define HOSTLIST_SERVER_H
-
-#include "gnunet_core_service.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_util_lib.h"
-
-#define GNUNET_ADV_TIMEOUT GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_MINUTES, 5)
-
-/**
- * Start server offering our hostlist.
- *
- * @return GNUNET_OK on success
- */
-int
-GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
- struct GNUNET_STATISTICS_Handle *st,
- struct GNUNET_CORE_Handle *core,
- GNUNET_CORE_ConnectEventHandler *server_ch,
- GNUNET_CORE_DisconnectEventHandler *server_dh,
- int advertise);
-
-
-/**
- * Stop server offering our hostlist.
- */
-void
-GNUNET_HOSTLIST_server_stop (void);
-
-
-#endif
-/* end of hostlist-server.h */
Modified: gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c
===================================================================
--- gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c 2014-06-03
08:19:03 UTC (rev 33488)
+++ gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c 2014-06-03
08:41:00 UTC (rev 33489)
@@ -37,7 +37,7 @@
*/
#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 180)
-#define CHECK_INTERVALL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 1)
+#define CHECK_INTERVAL GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 1)
struct PeerContext
@@ -304,7 +304,7 @@
&process_adv_sent, NULL);
}
check_task =
- GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL, &check_statistics, NULL);
+ GNUNET_SCHEDULER_add_delayed (CHECK_INTERVAL, &check_statistics, NULL);
}
@@ -452,7 +452,7 @@
timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_error, NULL);
check_task =
- GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL, &check_statistics, NULL);
+ GNUNET_SCHEDULER_add_delayed (CHECK_INTERVAL, &check_statistics, NULL);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r33489 - gnunet/src/hostlist,
gnunet <=