From 256e783449308d848bb687f5e9e79fde1c5fe03d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 13 Jun 2009 06:10:10 +0000 Subject: server draft --- src/hostlist/Makefile.am | 4 +- src/hostlist/gnunet-daemon-hostlist.c | 17 ++- src/hostlist/hostlist-server.c | 232 ++++++++++++++++++++++++++++++++++ src/hostlist/hostlist-server.h | 54 ++++++++ 4 files changed, 301 insertions(+), 6 deletions(-) create mode 100644 src/hostlist/hostlist-server.c create mode 100644 src/hostlist/hostlist-server.h (limited to 'src') diff --git a/src/hostlist/Makefile.am b/src/hostlist/Makefile.am index efa4d6962..911c086ac 100644 --- a/src/hostlist/Makefile.am +++ b/src/hostlist/Makefile.am @@ -10,8 +10,8 @@ bin_PROGRAMS = \ gnunet_daemon_hostlist_SOURCES = \ gnunet-daemon-hostlist.c \ - hostlist-client.c hostlist-client.h -# hostlist-server.c hostlist-server.h + hostlist-client.c hostlist-client.h \ + hostlist-server.c hostlist-server.h gnunet_daemon_hostlist_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c index f11bcd87d..da2553238 100644 --- a/src/hostlist/gnunet-daemon-hostlist.c +++ b/src/hostlist/gnunet-daemon-hostlist.c @@ -27,6 +27,7 @@ #include #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" @@ -37,6 +38,11 @@ #include "gnunet_util_lib.h" +/** + * Set if we are allowed to advertise our hostlist to others. + */ +static int advertising; + /** * Set if we are allowed to learn about peers by accessing * hostlist servers. @@ -63,6 +69,8 @@ static struct GNUNET_STATISTICS_Handle *stats; * gnunet-daemon-hostlist command line options. */ static struct GNUNET_GETOPT_CommandLineOption options[] = { + { 'a', "advertise", NULL, gettext_noop ("advertise our hostlist to other peers"), + GNUNET_NO, &GNUNET_GETOPT_set_one, &advertising }, { 'b', "bootstrap", NULL, gettext_noop ("bootstrap using hostlists (it is highly recommended that you always use this option)"), GNUNET_NO, &GNUNET_GETOPT_set_one, &bootstrapping }, { 'e', "enable-learning", NULL, gettext_noop ("enable learning about hostlist servers from other peers"), @@ -82,7 +90,10 @@ core_init (void *cls, GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey) { - /* TODO: provide "server" to 'hostlist' module (if applicable) */ + if (advertising && (NULL != server)) + { + /* TODO: provide "server" to 'hostlist' module */ + } } @@ -145,9 +156,7 @@ run (void *cls, } if (provide_hostlist) { - // FIXME! - // (initialize MHD server and run using scheduler; - // use peerinfo to gather HELLOs) + GNUNET_HOSTLIST_server_start (cfg, sched, stats); } GNUNET_CORE_connect (sched, cfg, GNUNET_TIME_UNIT_FOREVER_REL, diff --git a/src/hostlist/hostlist-server.c b/src/hostlist/hostlist-server.c new file mode 100644 index 000000000..a2bbe2dec --- /dev/null +++ b/src/hostlist/hostlist-server.c @@ -0,0 +1,232 @@ +/* + This file is part of GNUnet. + (C) 2008 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 2, 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 + * @brief application to provide an integrated hostlist HTTP server + */ + +#include "platform.h" +#include +#include "hostlist-server.h" +#include "gnunet_hello_lib.h" +#include "gnunet_peerinfo_service.h" + +/** + * How often should we recalculate our response to hostlist requests? + */ +#define RESPONSE_UPDATE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) + +/** + * Handle to the HTTP server as provided by libmicrohttpd. + */ +static struct MHD_Daemon *daemon_handle; + +/** + * Our configuration. + */ +static struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * Our scheduler. + */ +static struct GNUNET_SCHEDULER_Handle *sched; + +/** + * Our canonical response. + */ +static struct MHD_Response *response; + +/** + * Context for host processor. + */ +struct HostSet +{ + size_t size; + + char *data; +}; + + +/** + * Task that will produce a new response object. + */ +static void +update_response (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Function that assembles our response. + */ +static void +finish_response (struct HostSet *results) +{ + if (response != NULL) + MHD_destroy_response (response); + response = MHD_create_response_from_data (results->size, + results->data, MHD_YES, MHD_NO); + GNUNET_free (results); + /* schedule next update of the response */ + GNUNET_SCHEDULER_add_delayed (sched, + GNUNET_NO, + GNUNET_SCHEDULER_PRIORITY_IDLE, + GNUNET_SCHEDULER_NO_PREREQUISITE_TASK, + RESPONSE_UPDATE_FREQUENCY, + &update_response, + NULL); +} + + +/** + * 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, + uint32_t trust) +{ + struct HostSet *results = cls; + size_t old; + size_t s; + + if (peer == NULL) + finish_response (results); + old = results->size; + s = GNUNET_HELLO_size(hello); + if (old + s >= GNUNET_MAX_MALLOC_CHECKED) + return; /* too large, skip! */ + GNUNET_array_grow (results->data, + results->size, + old + s); + memcpy (&results->data[old], hello, s); +} + + +/** + * Task that will produce a new response object. + */ +static void +update_response (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct HostSet *results; + + results = GNUNET_malloc(sizeof(struct HostSet)); + GNUNET_PEERINFO_for_all (cfg, sched, + NULL, + 0, + GNUNET_TIME_UNIT_MINUTES, + &host_processor, + results); +} + + + +static int +accept_policy_callback (void *cls, + const struct sockaddr *addr, socklen_t addrlen) +{ + return MHD_YES; /* accept all */ +} + + +static int +access_handler_callback (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + unsigned int *upload_data_size, void **con_cls) +{ + static int dummy; + + if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) + return MHD_NO; + if (NULL == *con_cls) + { + (*con_cls) = &dummy; + return MHD_YES; /* send 100 continue */ + } + if (*upload_data_size != 0) + return MHD_NO; /* do not support upload data */ + if (response == NULL) + return MHD_NO; /* internal error, no response yet */ + return MHD_queue_response (connection, MHD_HTTP_OK, response); +} + + +/** + * Start server offering our hostlist. + * + * @return GNUNET_OK on success + */ +int +GNUNET_HOSTLIST_server_start (struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SCHEDULER_Handle *s, + struct GNUNET_STATISTICS_Handle *st) +{ + unsigned long long port; + + sched = s; + cfg = c; + if (-1 == GNUNET_CONFIGURATION_get_value_number (cfg, + "HOSTLIST", + "PORT", + &port)) + return GNUNET_SYSERR; + /* FIXME: must use *external* SELECT mode since our + code is NOT thread safe! Integrate with scheduler! */ + daemon_handle = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_IPv6, + (unsigned short) port, + &accept_policy_callback, + NULL, + &access_handler_callback, + NULL, + MHD_OPTION_CONNECTION_LIMIT, 16, + MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1, + MHD_OPTION_CONNECTION_TIMEOUT, 16, + MHD_OPTION_CONNECTION_MEMORY_LIMIT, + 16 * 1024, MHD_OPTION_END); + if (daemon_handle == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Could not start hostlist HTTP server on port %u\n"), + (unsigned short) port); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +/** + * Stop server offering our hostlist. + */ +void +GNUNET_HOSTLIST_server_stop () +{ + MHD_stop_daemon (daemon_handle); + daemon_handle = NULL; +} + +/* end of hostlist-server.c */ diff --git a/src/hostlist/hostlist-server.h b/src/hostlist/hostlist-server.h new file mode 100644 index 000000000..16f6848a5 --- /dev/null +++ b/src/hostlist/hostlist-server.h @@ -0,0 +1,54 @@ +/* + 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 2, 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" + + +/** + * Start server offering our hostlist. + * + * @return GNUNET_OK on success + */ +int +GNUNET_HOSTLIST_server_start (struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SCHEDULER_Handle *s, + struct GNUNET_STATISTICS_Handle *st); + + +/** + * Stop server offering our hostlist. + */ +void +GNUNET_HOSTLIST_server_stop (void); + + +#endif +/* end of hostlist-server.h */ -- cgit v1.2.3