[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-donau] branch master updated: [donau] uncomment most of donau-htt
From: |
gnunet |
Subject: |
[taler-donau] branch master updated: [donau] uncomment most of donau-httpd.c |
Date: |
Thu, 07 Dec 2023 17:01:15 +0100 |
This is an automated email from the git hooks/post-receive script.
lukas-matyja pushed a commit to branch master
in repository donau.
The following commit(s) were added to refs/heads/master by this push:
new e028dbc [donau] uncomment most of donau-httpd.c
new d6a9b5e Merge remote-tracking branch 'refs/remotes/origin/master'
e028dbc is described below
commit e028dbc25cabe76425fff32243e774b57ddf7d59
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
AuthorDate: Thu Dec 7 17:00:18 2023 +0100
[donau] uncomment most of donau-httpd.c
---
src/donau/Makefile.am | 3 +
src/donau/donau-httpd.c | 2690 +++++++++++++++++++++++------------------------
2 files changed, 1345 insertions(+), 1348 deletions(-)
diff --git a/src/donau/Makefile.am b/src/donau/Makefile.am
index 4e9011f..37aaf43 100644
--- a/src/donau/Makefile.am
+++ b/src/donau/Makefile.am
@@ -30,6 +30,9 @@ donau_httpd_LDADD = \
$(top_builddir)/src/donaudb/libtalerdonaudb.la \
$(top_builddir)/src/util/libtalerdonauutil.la \
-lmicrohttpd \
+ -ltalermhd \
+ -ltalerutil \
+ -ltalertemplating \
-lgnunetcurl \
-lgnunetutil \
-lgnunetjson \
diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c
index 8360e99..3e5e7cc 100644
--- a/src/donau/donau-httpd.c
+++ b/src/donau/donau-httpd.c
@@ -36,126 +36,126 @@
#include <gnunet/gnunet_mhd_compat.h>
#include "donau_util.h"
-// /**
-// * Backlog for listen operation on unix domain sockets.
-// */
-// #define UNIX_BACKLOG 50
-
-// /**
-// * How often will we try to connect to the database before giving up?
-// */
-// #define MAX_DB_RETRIES 5
-
-// /**
-// * Above what request latency do we start to log?
-// */
-/* #define WARN_LATENCY GNUNET_TIME_relative_multiply ( \
+/**
+ * Backlog for listen operation on unix domain sockets.
+ */
+#define UNIX_BACKLOG 50
+
+/**
+ * How often will we try to connect to the database before giving up?
+ */
+#define MAX_DB_RETRIES 5
+
+/**
+ * Above what request latency do we start to log?
+ */
+ #define WARN_LATENCY GNUNET_TIME_relative_multiply ( \
GNUNET_TIME_UNIT_MILLISECONDS, 500)
-*/
-// /**
-// * Are clients allowed to request /keys for times other than the
-// * current time? Allowing this could be abused in a DoS-attack
-// * as building new /keys responses is expensive. Should only be
-// * enabled for testcases, development and test systems.
-// */
-// int TEH_allow_keys_timetravel;
+
+/**
+ * Are clients allowed to request /keys for times other than the
+ * current time? Allowing this could be abused in a DoS-attack
+ * as building new /keys responses is expensive. Should only be
+ * enabled for testcases, development and test systems.
+ */
+int TEH_allow_keys_timetravel;
/**
* Should we allow two HTTPDs to bind to the same port?
*/
static int allow_address_reuse;
-// /**
-// * The donau's configuration (global)
-// */
-// const struct GNUNET_CONFIGURATION_Handle *TEH_cfg;
-
-// /**
-// * Configuration of age restriction
-// *
-// * Set after loading the library, enabled in database event handler.
-// */
-// bool TEH_age_restriction_enabled = false;
-// struct TALER_AgeRestrictionConfig TEH_age_restriction_config = {0};
-
-// /**
-// * Handle to the HTTP server.
-// */
-// static struct MHD_Daemon *mhd;
-
-// /**
-// * How long is caching /keys allowed at most? (global)
-// */
-// struct GNUNET_TIME_Relative TEH_max_keys_caching;
-
-// /**
-// * How long is the delay before we close reserves?
-// */
-// struct GNUNET_TIME_Relative TEH_reserve_closing_delay;
-
-// /**
-// * Master public key (according to the
-// * configuration in the donau directory). (global)
-// */
-// struct TALER_MasterPublicKeyP TEH_master_public_key;
-
-// /**
-// * Key used to encrypt KYC attribute data in our database.
-// */
-// struct TALER_AttributeEncryptionKeyP TEH_attribute_key;
-
-// /**
-// * Our DB plugin. (global)
-// */
-// struct DONAUDB_Plugin *TEH_plugin;
-
-// /**
-// * Absolute STEFAN parameter.
-// */
-// struct TALER_Amount TEH_stefan_abs;
-
-// /**
-// * Logarithmic STEFAN parameter.
-// */
-// struct TALER_Amount TEH_stefan_log;
-
-// /**
-// * Linear STEFAN parameter.
-// */
-// struct TALER_Amount TEH_stefan_lin;
-
-// /**
-// * Default number of fractional digits to render
-// * amounts with.
-// */
-// unsigned int TEH_currency_fraction_digits;
-
-// /**
-// * Our currency.
-// */
-// char *TEH_currency;
-
-// /**
-// * Name of the KYC-AML-trigger evaluation binary.
-// */
-// char *TEH_kyc_aml_trigger;
-
-// /**
-// * Option set to #GNUNET_YES if rewards are enabled.
-// */
-// int TEH_enable_rewards;
-
-// /**
-// * What is the largest amount we allow a peer to
-// * merge into a reserve before always triggering
-// * an AML check?
-// */
-// struct TALER_Amount TEH_aml_threshold;
-
-// /**
-// * Our base URL.
-// */
-// char *TEH_base_url;
+/**
+ * The donau's configuration (global)
+ */
+const struct GNUNET_CONFIGURATION_Handle *TEH_cfg;
+
+/**
+ * Configuration of age restriction
+ *
+ * Set after loading the library, enabled in database event handler.
+ */
+bool TEH_age_restriction_enabled = false;
+struct TALER_AgeRestrictionConfig TEH_age_restriction_config = {0};
+
+/**
+ * Handle to the HTTP server.
+ */
+static struct MHD_Daemon *mhd;
+
+/**
+ * How long is caching /keys allowed at most? (global)
+ */
+struct GNUNET_TIME_Relative TEH_max_keys_caching;
+
+/**
+ * How long is the delay before we close reserves?
+ */
+struct GNUNET_TIME_Relative TEH_reserve_closing_delay;
+
+/**
+ * Master public key (according to the
+ * configuration in the donau directory). (global)
+ */
+struct TALER_MasterPublicKeyP TEH_master_public_key;
+
+/**
+ * Key used to encrypt KYC attribute data in our database.
+ */
+struct TALER_AttributeEncryptionKeyP TEH_attribute_key;
+
+/**
+ * Our DB plugin. (global)
+ */
+struct DONAUDB_Plugin *TEH_plugin;
+
+/**
+ * Absolute STEFAN parameter.
+ */
+struct TALER_Amount TEH_stefan_abs;
+
+/**
+ * Logarithmic STEFAN parameter.
+ */
+struct TALER_Amount TEH_stefan_log;
+
+/**
+ * Linear STEFAN parameter.
+ */
+struct TALER_Amount TEH_stefan_lin;
+
+/**
+ * Default number of fractional digits to render
+ * amounts with.
+ */
+unsigned int TEH_currency_fraction_digits;
+
+/**
+ * Our currency.
+ */
+char *TEH_currency;
+
+/**
+ * Name of the KYC-AML-trigger evaluation binary.
+ */
+char *TEH_kyc_aml_trigger;
+
+/**
+ * Option set to #GNUNET_YES if rewards are enabled.
+ */
+int TEH_enable_rewards;
+
+/**
+ * What is the largest amount we allow a peer to
+ * merge into a reserve before always triggering
+ * an AML check?
+ */
+struct TALER_Amount TEH_aml_threshold;
+
+/**
+ * Our base URL.
+ */
+char *TEH_base_url;
/**
* Default timeout in seconds for HTTP requests.
@@ -167,84 +167,84 @@ static unsigned int connection_timeout = 30;
*/
static int connection_close;
-// /**
-// * -I command-line flag given?
-// */
-// int TEH_check_invariants_flag;
-
-// /**
-// * True if we should commit suicide once all active
-// * connections are finished.
-// */
-// bool TEH_suicide;
-
-// /**
-// * Signature of the configuration of all enabled extensions,
-// * signed by the donau's offline master key with purpose
-// * TALER_SIGNATURE_MASTER_EXTENSION.
-// */
-// struct TALER_MasterSignatureP TEH_extensions_sig;
-// bool TEH_extensions_signed = false;
-
-// /**
-// * Value to return from main()
-// */
-// static int global_ret;
-
-// /**
-// * Port to run the daemon on.
-// */
-// static uint16_t serve_port;
-
-// /**
-// * Counter for the number of requests this HTTP has processed so far.
-// */
-// static unsigned long long req_count;
-
-// /**
-// * Counter for the number of open connections.
-// */
-// static unsigned long long active_connections;
-
-// /**
-// * Limit for the number of requests this HTTP may process before restarting.
-// * (This was added as one way of dealing with unavoidable memory
fragmentation
-// * happening slowly over time.)
-// */
-// static unsigned long long req_max;
-
-// /**
-// * Context for all CURL operations (useful to the event loop)
-// */
-// struct GNUNET_CURL_Context *TEH_curl_ctx;
-
-// /**
-// * Context for integrating #TEH_curl_ctx with the
-// * GNUnet event loop.
-// */
-// static struct GNUNET_CURL_RescheduleContext *donau_curl_rc;
-
-// /**
-// * Signature of functions that handle operations on coins.
-// *
-// * @param connection the MHD connection to handle
-// * @param coin_pub the public key of the coin
-// * @param root uploaded JSON data
-// * @return MHD result code
-// */
-// typedef MHD_RESULT
-// (*CoinOpHandler)(struct MHD_Connection *connection,
-// const struct TALER_CoinSpendPublicKeyP *coin_pub,
-// const json_t *root);
-
-
-// /**
-// * Generate a 404 "not found" reply on @a connection with
-// * the hint @a details.
-// *
-// * @param connection where to send the reply on
-// * @param details details for the error message, can be NULL
-// */
+/**
+ * -I command-line flag given?
+ */
+int TEH_check_invariants_flag;
+
+/**
+ * True if we should commit suicide once all active
+ * connections are finished.
+ */
+bool TEH_suicide;
+
+/**
+ * Signature of the configuration of all enabled extensions,
+ * signed by the donau's offline master key with purpose
+ * TALER_SIGNATURE_MASTER_EXTENSION.
+ */
+struct TALER_MasterSignatureP TEH_extensions_sig;
+bool TEH_extensions_signed = false;
+
+/**
+ * Value to return from main()
+ */
+static int global_ret;
+
+/**
+ * Port to run the daemon on.
+ */
+static uint16_t serve_port;
+
+/**
+ * Counter for the number of requests this HTTP has processed so far.
+ */
+//static unsigned long long req_count;
+
+/**
+ * Counter for the number of open connections.
+ */
+static unsigned long long active_connections;
+
+/**
+ * Limit for the number of requests this HTTP may process before restarting.
+ * (This was added as one way of dealing with unavoidable memory fragmentation
+ * happening slowly over time.)
+ */
+static unsigned long long req_max;
+
+/**
+ * Context for all CURL operations (useful to the event loop)
+ */
+struct GNUNET_CURL_Context *TEH_curl_ctx;
+
+/**
+ * Context for integrating #TEH_curl_ctx with the
+ * GNUnet event loop.
+ */
+static struct GNUNET_CURL_RescheduleContext *donau_curl_rc;
+
+/**
+ * Signature of functions that handle operations on coins.
+ *
+ * @param connection the MHD connection to handle
+ * @param coin_pub the public key of the coin
+ * @param root uploaded JSON data
+ * @return MHD result code
+ */
+typedef MHD_RESULT
+(*CoinOpHandler)(struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root);
+
+
+/**
+ * Generate a 404 "not found" reply on @a connection with
+ * the hint @a details.
+ *
+ * @param connection where to send the reply on
+ * @param details details for the error message, can be NULL
+ */
// static MHD_RESULT
// r404 (struct MHD_Connection *connection,
// const char *details)
@@ -256,1195 +256,1190 @@ static int connection_close;
// }
-// /**
-// * Function called whenever MHD is done with a request. If the
-// * request was a POST, we may have stored a `struct Buffer *` in the
-// * @a con_cls that might still need to be cleaned up. Call the
-// * respective function to free the memory.
-// *
-// * @param cls client-defined closure
-// * @param connection connection handle
-// * @param con_cls value as set by the last call to
-// * the #MHD_AccessHandlerCallback
-// * @param toe reason for request termination
-// * @see #MHD_OPTION_NOTIFY_COMPLETED
-// * @ingroup request
-// */
-// static void
-// handle_mhd_completion_callback (void *cls,
-// struct MHD_Connection *connection,
-// void **con_cls,
-// enum MHD_RequestTerminationCode toe)
-// {
-// struct TEH_RequestContext *rc = *con_cls;
-// struct GNUNET_AsyncScopeSave old_scope;
-
-// (void) cls;
-// if (NULL == rc)
-// return;
-// GNUNET_async_scope_enter (&rc->async_scope_id,
-// &old_scope);
-// check_suicide ();
-// TEH_check_invariants ();
-// if (NULL != rc->rh_cleaner)
-// rc->rh_cleaner (rc);
-// TEH_check_invariants ();
-// {
-// #if MHD_VERSION >= 0x00097304
-// const union MHD_ConnectionInfo *ci;
-// unsigned int http_status = 0;
-
-// ci = MHD_get_connection_info (connection,
-// MHD_CONNECTION_INFO_HTTP_STATUS);
-// if (NULL != ci)
-// http_status = ci->http_status;
-// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-// "Request for `%s' completed with HTTP status %u (%d)\n",
-// rc->url,
-// http_status,
-// toe);
-// #else
-// (void) connection;
-// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-// "Request for `%s' completed (%d)\n",
-// rc->url,
-// toe);
-// #endif
-// }
-
-// TALER_MHD_parse_post_cleanup_callback (rc->opaque_post_parsing_context);
-// /* Sanity-check that we didn't leave any transactions hanging */
-// // GNUNET_break (GNUNET_OK ==
-// // TEH_plugin->preflight (TEH_plugin->cls));
-// {
-// struct GNUNET_TIME_Relative latency;
-
-// latency = GNUNET_TIME_absolute_get_duration (rc->start_time);
-// if (latency.rel_value_us >
-// WARN_LATENCY.rel_value_us)
-// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-// "Request for `%s' took %s\n",
-// rc->url,
-// GNUNET_STRINGS_relative_time_to_string (latency,
-// GNUNET_YES));
-// }
-// GNUNET_free (rc);
-// *con_cls = NULL;
-// GNUNET_async_scope_restore (&old_scope);
-// }
+/**
+ * Function called whenever MHD is done with a request. If the
+ * request was a POST, we may have stored a `struct Buffer *` in the
+ * @a con_cls that might still need to be cleaned up. Call the
+ * respective function to free the memory.
+ *
+ * @param cls client-defined closure
+ * @param connection connection handle
+ * @param con_cls value as set by the last call to
+ * the #MHD_AccessHandlerCallback
+ * @param toe reason for request termination
+ * @see #MHD_OPTION_NOTIFY_COMPLETED
+ * @ingroup request
+ */
+static void
+handle_mhd_completion_callback (void *cls,
+ struct MHD_Connection *connection,
+ void **con_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ struct TEH_RequestContext *rc = *con_cls;
+ struct GNUNET_AsyncScopeSave old_scope;
+
+ (void) cls;
+ if (NULL == rc)
+ return;
+ GNUNET_async_scope_enter (&rc->async_scope_id,
+ &old_scope);
+ //check_suicide ();
+ //TEH_check_invariants ();
+ if (NULL != rc->rh_cleaner)
+ rc->rh_cleaner (rc);
+ //TEH_check_invariants ();
+ {
+#if MHD_VERSION >= 0x00097304
+ const union MHD_ConnectionInfo *ci;
+ unsigned int http_status = 0;
+
+ ci = MHD_get_connection_info (connection,
+ MHD_CONNECTION_INFO_HTTP_STATUS);
+ if (NULL != ci)
+ http_status = ci->http_status;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Request for `%s' completed with HTTP status %u (%d)\n",
+ rc->url,
+ http_status,
+ toe);
+#else
+ (void) connection;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Request for `%s' completed (%d)\n",
+ rc->url,
+ toe);
+#endif
+ }
+
+ TALER_MHD_parse_post_cleanup_callback (rc->opaque_post_parsing_context);
+ /* Sanity-check that we didn't leave any transactions hanging */
+ GNUNET_break (GNUNET_OK ==
+ TEH_plugin->preflight (TEH_plugin->cls));
+ {
+ struct GNUNET_TIME_Relative latency;
+
+ latency = GNUNET_TIME_absolute_get_duration (rc->start_time);
+ if (latency.rel_value_us >
+ WARN_LATENCY.rel_value_us)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Request for `%s' took %s\n",
+ rc->url,
+ GNUNET_STRINGS_relative_time_to_string (latency,
+ GNUNET_YES));
+ }
+ GNUNET_free (rc);
+ *con_cls = NULL;
+ GNUNET_async_scope_restore (&old_scope);
+}
-// /**
-// * We found a request handler responsible for handling a request. Parse the
-// * @a upload_data (if applicable) and the @a url and call the
-// * handler.
-// *
-// * @param rc request context
-// * @param url rest of the URL to parse
-// * @param upload_data upload data to parse (if available)
-// * @param[in,out] upload_data_size number of bytes in @a upload_data
-// * @return MHD result code
-// */
-// static MHD_RESULT
-// proceed_with_handler (struct TEH_RequestContext *rc,
-// const char *url,
-// const char *upload_data,
-// size_t *upload_data_size)
-// {
-// const struct TEH_RequestHandler *rh = rc->rh;
-// const char *args[rh->nargs + 2];
-// size_t ulen = strlen (url) + 1;
-// json_t *root = NULL;
-// MHD_RESULT ret;
-
-// /* We do check for "ulen" here, because we'll later stack-allocate a
buffer
-// of that size and don't want to enable malicious clients to cause us
-// huge stack allocations. */
-// if (ulen > 512)
-// {
-// /* 512 is simply "big enough", as it is bigger than "6 * 54",
-// which is the longest URL format we ever get (for
-// /deposits/). The value should be adjusted if we ever define protocol
-// endpoints with plausibly longer inputs. */
-// GNUNET_break_op (0);
-// return TALER_MHD_reply_with_error (rc->connection,
-// MHD_HTTP_URI_TOO_LONG,
-// TALER_EC_GENERIC_URI_TOO_LONG,
-// url);
-// }
-
-// /* All POST endpoints come with a body in JSON format. So we parse
-// the JSON here. */
-// if (0 == strcasecmp (rh->method,
-// MHD_HTTP_METHOD_POST))
-// {
-// enum GNUNET_GenericReturnValue res;
-
-// res = TALER_MHD_parse_post_json (rc->connection,
-// &rc->opaque_post_parsing_context,
-// upload_data,
-// upload_data_size,
-// &root);
-// if (GNUNET_SYSERR == res)
-// {
-// GNUNET_assert (NULL == root);
-// return MHD_NO; /* bad upload, could not even generate error */
-// }
-// if ( (GNUNET_NO == res) ||
-// (NULL == root) )
-// {
-// GNUNET_assert (NULL == root);
-// return MHD_YES; /* so far incomplete upload or parser error */
-// }
-// }
-
-// {
-// char d[ulen];
-// unsigned int i;
-// char *sp;
-
-// /* Parse command-line arguments */
-// /* make a copy of 'url' because 'strtok_r()' will modify */
-// GNUNET_memcpy (d,
-// url,
-// ulen);
-// i = 0;
-// args[i++] = strtok_r (d, "/", &sp);
-// while ( (NULL != args[i - 1]) &&
-// (i <= rh->nargs + 1) )
-// args[i++] = strtok_r (NULL, "/", &sp);
-// /* make sure above loop ran nicely until completion, and also
-// that there is no excess data in 'd' afterwards */
-// if ( ( (rh->nargs_is_upper_bound) &&
-// (i - 1 > rh->nargs) ) ||
-// ( (! rh->nargs_is_upper_bound) &&
-// (i - 1 != rh->nargs) ) )
-// {
-// char emsg[128 + 512];
-
-// GNUNET_snprintf (emsg,
-// sizeof (emsg),
-// "Got %u+/%u segments for `%s' request (`%s')",
-// i - 1,
-// rh->nargs,
-// rh->url,
-// url);
-// GNUNET_break_op (0);
-// json_decref (root);
-// return TALER_MHD_reply_with_error (rc->connection,
-// MHD_HTTP_NOT_FOUND,
-//
TALER_EC_DONAU_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
-// emsg);
-// }
-// GNUNET_assert (NULL == args[i - 1]);
-
-// /* Above logic ensures that 'root' is exactly non-NULL for POST
operations,
-// so we test for 'root' to decide which handler to invoke. */
-// if (0 == strcasecmp (rh->method,
-// MHD_HTTP_METHOD_POST))
-// ret = rh->handler.post (rc,
-// root,
-// args);
-// else if (0 == strcasecmp (rh->method,
-// MHD_HTTP_METHOD_DELETE))
-// ret = rh->handler.delete (rc,
-// args);
-// else /* Only GET left */
-// ret = rh->handler.get (rc,
-// args);
-// }
-// json_decref (root);
-// return ret;
-// }
+/**
+ * We found a request handler responsible for handling a request. Parse the
+ * @a upload_data (if applicable) and the @a url and call the
+ * handler.
+ *
+ * @param rc request context
+ * @param url rest of the URL to parse
+ * @param upload_data upload data to parse (if available)
+ * @param[in,out] upload_data_size number of bytes in @a upload_data
+ * @return MHD result code
+ */
+static MHD_RESULT
+proceed_with_handler (struct TEH_RequestContext *rc,
+ const char *url,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ const struct TEH_RequestHandler *rh = rc->rh;
+ const char *args[rh->nargs + 2];
+ size_t ulen = strlen (url) + 1;
+ json_t *root = NULL;
+ MHD_RESULT ret;
+
+ /* We do check for "ulen" here, because we'll later stack-allocate a buffer
+ of that size and don't want to enable malicious clients to cause us
+ huge stack allocations. */
+ if (ulen > 512)
+ {
+ /* 512 is simply "big enough", as it is bigger than "6 * 54",
+ which is the longest URL format we ever get (for
+ /deposits/). The value should be adjusted if we ever define protocol
+ endpoints with plausibly longer inputs. */
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_URI_TOO_LONG,
+ TALER_EC_GENERIC_URI_TOO_LONG,
+ url);
+ }
+
+ /* All POST endpoints come with a body in JSON format. So we parse
+ the JSON here. */
+ if (0 == strcasecmp (rh->method,
+ MHD_HTTP_METHOD_POST))
+ {
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_post_json (rc->connection,
+ &rc->opaque_post_parsing_context,
+ upload_data,
+ upload_data_size,
+ &root);
+ if (GNUNET_SYSERR == res)
+ {
+ GNUNET_assert (NULL == root);
+ return MHD_NO; /* bad upload, could not even generate error */
+ }
+ if ( (GNUNET_NO == res) ||
+ (NULL == root) )
+ {
+ GNUNET_assert (NULL == root);
+ return MHD_YES; /* so far incomplete upload or parser error */
+ }
+ }
+
+ {
+ char d[ulen];
+ unsigned int i;
+ char *sp;
+
+ /* Parse command-line arguments */
+ /* make a copy of 'url' because 'strtok_r()' will modify */
+ GNUNET_memcpy (d,
+ url,
+ ulen);
+ i = 0;
+ args[i++] = strtok_r (d, "/", &sp);
+ while ( (NULL != args[i - 1]) &&
+ (i <= rh->nargs + 1) )
+ args[i++] = strtok_r (NULL, "/", &sp);
+ /* make sure above loop ran nicely until completion, and also
+ that there is no excess data in 'd' afterwards */
+ if ( ( (rh->nargs_is_upper_bound) &&
+ (i - 1 > rh->nargs) ) ||
+ ( (! rh->nargs_is_upper_bound) &&
+ (i - 1 != rh->nargs) ) )
+ {
+ char emsg[128 + 512];
+
+ GNUNET_snprintf (emsg,
+ sizeof (emsg),
+ "Got %u+/%u segments for `%s' request (`%s')",
+ i - 1,
+ rh->nargs,
+ rh->url,
+ url);
+ GNUNET_break_op (0);
+ json_decref (root);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_NOT_FOUND,
+
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
+ emsg);
+ }
+ GNUNET_assert (NULL == args[i - 1]);
+
+ /* Above logic ensures that 'root' is exactly non-NULL for POST operations,
+ so we test for 'root' to decide which handler to invoke. */
+ if (0 == strcasecmp (rh->method,
+ MHD_HTTP_METHOD_POST))
+ ret = rh->handler.post (rc,
+ root,
+ args);
+ else if (0 == strcasecmp (rh->method,
+ MHD_HTTP_METHOD_DELETE))
+ ret = rh->handler.delete (rc,
+ args);
+ else /* Only GET left */
+ ret = rh->handler.get (rc,
+ args);
+ }
+ json_decref (root);
+ return ret;
+}
-// /**
-// * Handle a "/seed" request.
-// *
-// * @param rc request context
-// * @param args array of additional options (must be empty for this function)
-// * @return MHD result code
-// */
-// static MHD_RESULT
-// handler_seed (struct TEH_RequestContext *rc,
-// const char *const args[])
-// {
-// #define SEED_SIZE 32
-// char *body;
-// MHD_RESULT ret;
-// struct MHD_Response *resp;
-
-// (void) args;
-// body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use
free() */
-// if (NULL == body)
-// return MHD_NO;
-// GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
-// body,
-// SEED_SIZE);
-// resp = MHD_create_response_from_buffer (SEED_SIZE,
-// body,
-// MHD_RESPMEM_MUST_FREE);
-// TALER_MHD_add_global_headers (resp);
-// ret = MHD_queue_response (rc->connection,
-// MHD_HTTP_OK,
-// resp);
-// GNUNET_break (MHD_YES == ret);
-// MHD_destroy_response (resp);
-// return ret;
-// #undef SEED_SIZE
-// }
+/**
+ * Handle a "/seed" request.
+ *
+ * @param rc request context
+ * @param args array of additional options (must be empty for this function)
+ * @return MHD result code
+ */
+static MHD_RESULT
+handler_seed (struct TEH_RequestContext *rc,
+ const char *const args[])
+{
+#define SEED_SIZE 32
+ char *body;
+ MHD_RESULT ret;
+ struct MHD_Response *resp;
+
+ (void) args;
+ body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use free()
*/
+ if (NULL == body)
+ return MHD_NO;
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+ body,
+ SEED_SIZE);
+ resp = MHD_create_response_from_buffer (SEED_SIZE,
+ body,
+ MHD_RESPMEM_MUST_FREE);
+ TALER_MHD_add_global_headers (resp);
+ ret = MHD_queue_response (rc->connection,
+ MHD_HTTP_OK,
+ resp);
+ GNUNET_break (MHD_YES == ret);
+ MHD_destroy_response (resp);
+ return ret;
+#undef SEED_SIZE
+}
-// /**
-// * Handle incoming HTTP request.
-// *
-// * @param cls closure for MHD daemon (unused)
-// * @param connection the connection
-// * @param url the requested url
-// * @param method the method (POST, GET, ...)
-// * @param version HTTP version (ignored)
-// * @param upload_data request data
-// * @param upload_data_size size of @a upload_data in bytes
-// * @param con_cls closure for request (a `struct TEH_RequestContext *`)
-// * @return MHD result code
-// */
-// static MHD_RESULT
-// handle_mhd_request (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 struct TEH_RequestHandler handlers[] = {
+/**
+ * Handle incoming HTTP request.
+ *
+ * @param cls closure for MHD daemon (unused)
+ * @param connection the connection
+ * @param url the requested url
+ * @param method the method (POST, GET, ...)
+ * @param version HTTP version (ignored)
+ * @param upload_data request data
+ * @param upload_data_size size of @a upload_data in bytes
+ * @param con_cls closure for request (a `struct TEH_RequestContext *`)
+ * @return MHD result code
+ */
+static MHD_RESULT
+handle_mhd_request (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 struct TEH_RequestHandler handlers[] = {
/* /robots.txt: disallow everything */
-// {
-// .url = "robots.txt",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &TEH_handler_static_response,
-// .mime_type = "text/plain",
-// .data = "User-agent: *\nDisallow: /\n",
-// .response_code = MHD_HTTP_OK
-// },
+{
+ .url = "robots.txt",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = &TEH_handler_static_response,
+ .mime_type = "text/plain",
+ .data = "User-agent: *\nDisallow: /\n",
+ .response_code = MHD_HTTP_OK
+},
/* Landing page, tell humans to go away. */
-// {
-// .url = "",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = TEH_handler_static_response,
-// .mime_type = "text/plain",
-// .data =
-// "Hello, I'm the Taler donau. This HTTP server is not for humans.\n",
-// .response_code = MHD_HTTP_OK
-// },
+{
+ .url = "",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = TEH_handler_static_response,
+ .mime_type = "text/plain",
+ .data =
+ "Hello, I'm the Taler donau. This HTTP server is not for humans.\n",
+ .response_code = MHD_HTTP_OK
+},
/* AGPL licensing page, redirect to source. As per the AGPL-license, every
deployment is required to offer the user a download of the source of
the actual deployment. We make this easy by including a redirect to the
source here. */
-// {
-// .url = "agpl",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &TEH_handler_agpl_redirect
-// },
-// {
-// .url = "seed",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &handler_seed
-// },
+{
+ .url = "agpl",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = &TEH_handler_agpl_redirect
+},
+{
+ .url = "seed",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &handler_seed
+},
/* Configuration */
-// {
-// .url = "config",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &TEH_handler_config
-// },
+{
+ .url = "config",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = &TEH_handler_config
+},
/* Performance metrics */
-// {
-// .url = "metrics",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &TEH_handler_metrics
-// },
+{
+ .url = "metrics",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = &TEH_handler_metrics
+},
/* Terms of service */
-// {
-// .url = "terms",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &TEH_handler_terms
-// },
+{
+ .url = "terms",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = &TEH_handler_terms
+},
/* Privacy policy */
-// {
-// .url = "privacy",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &TEH_handler_privacy
-// },
+{
+ .url = "privacy",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = &TEH_handler_privacy
+},
/* Return key material and fundamental properties for this donau */
-// {
-// .url = "keys",
-// .method = MHD_HTTP_METHOD_GET,
-// .handler.get = &TEH_keys_get_handler,
-// },
+{
+ .url = "keys",
+ .method = MHD_HTTP_METHOD_GET,
+ //.handler.get = &TEH_keys_get_handler,
+},
/* request R, used in clause schnorr withdraw and refresh */
-// {
-// .url = "csr-melt",
-// .method = MHD_HTTP_METHOD_POST,
-// .handler.post = &TEH_handler_csr_melt,
-// .nargs = 0
-// },
-
-
-// /* mark end of list */
-// {
-// .url = NULL
-// }
-// };
-// struct TEH_RequestContext *rc = *con_cls;
-// struct GNUNET_AsyncScopeSave old_scope;
-// const char *correlation_id = NULL;
-
-// (void) cls;
-// (void) version;
-// if (NULL == rc)
-// {
-// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-// "Handling new request\n");
-
-// /* We're in a new async scope! */
-// rc = *con_cls = GNUNET_new (struct TEH_RequestContext);
-// rc->start_time = GNUNET_TIME_absolute_get ();
-// GNUNET_async_scope_fresh (&rc->async_scope_id);
-// TEH_check_invariants ();
-// rc->url = url;
-// rc->connection = connection;
-// /* We only read the correlation ID on the first callback for every
client */
-// correlation_id = MHD_lookup_connection_value (connection,
-// MHD_HEADER_KIND,
-// "Taler-Correlation-Id");
-// if ( (NULL != correlation_id) &&
-// (GNUNET_YES !=
-// GNUNET_CURL_is_valid_scope_id (correlation_id)) )
-// {
-// GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-// "illegal incoming correlation ID\n");
-// correlation_id = NULL;
-// }
-
-// /* Check if upload is in bounds */
-// if (0 == strcasecmp (method,
-// MHD_HTTP_METHOD_POST))
-// {
-// TALER_MHD_check_content_length (connection,
-// TALER_MHD_REQUEST_BUFFER_MAX);
-// }
-// }
-
-// GNUNET_async_scope_enter (&rc->async_scope_id,
-// &old_scope);
-// TEH_check_invariants ();
-// if (NULL != correlation_id)
-// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-// "Handling request (%s) for URL '%s', correlation_id=%s\n",
-// method,
-// url,
-// correlation_id);
-// else
-// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-// "Handling request (%s) for URL '%s'\n",
-// method,
-// url);
-// /* on repeated requests, check our cache first */
-// if (NULL != rc->rh)
-// {
-// MHD_RESULT ret;
-// const char *start;
-
-// if ('\0' == url[0])
-// /* strange, should start with '/', treat as just "/" */
-// url = "/";
-// start = strchr (url + 1, '/');
-// if (NULL == start)
-// start = "";
-// ret = proceed_with_handler (rc,
-// start,
-// upload_data,
-// upload_data_size);
-// GNUNET_async_scope_restore (&old_scope);
-// return ret;
-// }
-
-// if ( (0 == strcasecmp (method,
-// MHD_HTTP_METHOD_OPTIONS)) &&
-// (0 == strcmp ("*",
-// url)) )
-// return TALER_MHD_reply_cors_preflight (connection);
-
-// if (0 == strcasecmp (method,
-// MHD_HTTP_METHOD_HEAD))
-// method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do
the rest */
-
-// /* parse first part of URL */
-// {
-// bool found = false;
-// size_t tok_size;
-// const char *tok;
-// const char *rest;
-
-// if ('\0' == url[0])
-// /* strange, should start with '/', treat as just "/" */
-// url = "/";
-// tok = url + 1;
-// rest = strchr (tok, '/');
-// if (NULL == rest)
-// {
-// tok_size = strlen (tok);
-// }
-// else
-// {
-// tok_size = rest - tok;
-// rest++; /* skip over '/' */
-// }
-// for (unsigned int i = 0; NULL != handlers[i].url; i++)
-// {
-// struct TEH_RequestHandler *rh = &handlers[i];
-
-// if ( (0 != strncmp (tok,
-// rh->url,
-// tok_size)) ||
-// (tok_size != strlen (rh->url) ) )
-// continue;
-// found = true;
-// /* The URL is a match! What we now do depends on the method. */
-// if (0 == strcasecmp (method,
-// MHD_HTTP_METHOD_OPTIONS))
-// {
-// GNUNET_async_scope_restore (&old_scope);
-// return TALER_MHD_reply_cors_preflight (connection);
-// }
-// GNUNET_assert (NULL != rh->method);
-// if (0 == strcasecmp (method,
-// rh->method))
-// {
-// MHD_RESULT ret;
-
-// /* cache to avoid the loop next time */
-// rc->rh = rh;
-// /* run handler */
-// ret = proceed_with_handler (rc,
-// url + tok_size + 1,
-// upload_data,
-// upload_data_size);
-// GNUNET_async_scope_restore (&old_scope);
-// return ret;
-// }
-// }
-
-// if (found)
-// {
-// /* we found a matching address, but the method is wrong */
-// struct MHD_Response *reply;
-// MHD_RESULT ret;
-// char *allowed = NULL;
-
-// GNUNET_break_op (0);
-// for (unsigned int i = 0; NULL != handlers[i].url; i++)
-// {
-// struct TEH_RequestHandler *rh = &handlers[i];
-
-// if ( (0 != strncmp (tok,
-// rh->url,
-// tok_size)) ||
-// (tok_size != strlen (rh->url) ) )
-// continue;
-// if (NULL == allowed)
-// {
-// allowed = GNUNET_strdup (rh->method);
-// }
-// else
-// {
-// char *tmp;
-
-// GNUNET_asprintf (&tmp,
-// "%s, %s",
-// allowed,
-// rh->method);
-// GNUNET_free (allowed);
-// allowed = tmp;
-// }
-// if (0 == strcasecmp (rh->method,
-// MHD_HTTP_METHOD_GET))
-// {
-// char *tmp;
-
-// GNUNET_asprintf (&tmp,
-// "%s, %s",
-// allowed,
-// MHD_HTTP_METHOD_HEAD);
-// GNUNET_free (allowed);
-// allowed = tmp;
-// }
-// }
-// reply = TALER_MHD_make_error (TALER_EC_GENERIC_METHOD_INVALID,
-// method);
-// GNUNET_break (MHD_YES ==
-// MHD_add_response_header (reply,
-// MHD_HTTP_HEADER_ALLOW,
-// allowed));
-// GNUNET_free (allowed);
-// ret = MHD_queue_response (connection,
-// MHD_HTTP_METHOD_NOT_ALLOWED,
-// reply);
-// MHD_destroy_response (reply);
-// return ret;
-// }
-// }
-
-// /* No handler matches, generate not found */
-// {
-// MHD_RESULT ret;
-
-// ret = TALER_MHD_reply_with_error (connection,
-// MHD_HTTP_NOT_FOUND,
-// TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
-// url);
-// GNUNET_async_scope_restore (&old_scope);
-// return ret;
-// }
-// }
+{
+ .url = "csr-melt",
+ .method = MHD_HTTP_METHOD_POST,
+ //.handler.post = &TEH_handler_csr_melt,
+ .nargs = 0
+},
-// /**
-// * Load configuration parameters for the donau
-// * server into the corresponding global variables.
-// *
-// * @return #GNUNET_OK on success
-// */
-// static enum GNUNET_GenericReturnValue
-// donau_serve_process_config (void)
-// {
-// if (GNUNET_OK !=
-// TALER_KYCLOGIC_kyc_init (TEH_cfg))
-// {
-// return GNUNET_SYSERR;
-// }
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_number (TEH_cfg,
-// "donau",
-// "MAX_REQUESTS",
-// &req_max))
-// {
-// req_max = ULLONG_MAX;
-// }
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
-// "donaudb",
-// "IDLE_RESERVE_EXPIRATION_TIME",
-// &TEH_reserve_closing_delay))
-// {
-// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-// "donaudb",
-// "IDLE_RESERVE_EXPIRATION_TIME");
-// /* use default */
-// TEH_reserve_closing_delay
-// = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS,
-// 4);
-// }
-
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
-// "donau",
-// "MAX_KEYS_CACHING",
-// &TEH_max_keys_caching))
-// {
-// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-// "donau",
-// "MAX_KEYS_CACHING",
-// "valid relative time expected");
-// return GNUNET_SYSERR;
-// }
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
-// "donau",
-// "KYC_AML_TRIGGER",
-// &TEH_kyc_aml_trigger))
-// {
-// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-// "donau",
-// "KYC_AML_TRIGGER");
-// return GNUNET_SYSERR;
-// }
-// if (GNUNET_OK !=
-// TALER_config_get_currency (TEH_cfg,
-// &TEH_currency))
-// {
-// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-// "taler",
-// "CURRENCY");
-// return GNUNET_SYSERR;
-// }
-// {
-// unsigned long long cfd;
-
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_number (TEH_cfg,
-// "donau",
-// "CURRENCY_FRACTION_DIGITS",
-// &cfd))
-// cfd = 0;
-// if (cfd > 8)
-// {
-// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-// "taler",
-// "CURRENCY_FRACTION_DIGITS",
-// "Value must be below 8");
-// return GNUNET_SYSERR;
-// }
-// TEH_currency_fraction_digits = (unsigned int) cfd;
-// }
-// if (GNUNET_OK !=
-// TALER_config_get_amount (TEH_cfg,
-// "donau",
-// "AML_THRESHOLD",
-// &TEH_aml_threshold))
-// {
-// GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-// "Need amount in section `donau' under `AML_THRESHOLD'\n");
-// return GNUNET_SYSERR;
-// }
-// if (GNUNET_OK !=
-// TALER_config_get_amount (TEH_cfg,
-// "donau",
-// "STEFAN_ABS",
-// &TEH_stefan_abs))
-// {
-// GNUNET_assert (GNUNET_OK ==
-// TALER_amount_set_zero (TEH_currency,
-// &TEH_stefan_abs));
-// }
-// if (GNUNET_OK !=
-// TALER_config_get_amount (TEH_cfg,
-// "donau",
-// "STEFAN_LOG",
-// &TEH_stefan_log))
-// {
-// GNUNET_assert (GNUNET_OK ==
-// TALER_amount_set_zero (TEH_currency,
-// &TEH_stefan_log));
-// }
-// if (GNUNET_OK !=
-// TALER_config_get_amount (TEH_cfg,
-// "donau",
-// "STEFAN_LIN",
-// &TEH_stefan_lin))
-// {
-// GNUNET_assert (GNUNET_OK ==
-// TALER_amount_set_zero (TEH_currency,
-// &TEH_stefan_lin));
-// }
-
-// if (0 != strcmp (TEH_currency,
-// TEH_aml_threshold.currency))
-// {
-// GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-// "Amount in section `donau' under `AML_THRESHOLD' uses the
wrong currency!\n");
-// return GNUNET_SYSERR;
-// }
-// TEH_enable_rewards
-// = GNUNET_CONFIGURATION_get_value_yesno (
-// TEH_cfg,
-// "donau",
-// "ENABLE_REWARDS");
-// if (GNUNET_SYSERR == TEH_enable_rewards)
-// {
-// GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-// "Need YES or NO in section `donau' under
`ENABLE_REWARDS'\n");
-// return GNUNET_SYSERR;
-// }
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
-// "donau",
-// "BASE_URL",
-// &TEH_base_url))
-// {
-// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-// "donau",
-// "BASE_URL");
-// return GNUNET_SYSERR;
-// }
-// if (! TALER_url_valid_charset (TEH_base_url))
-// {
-// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-// "donau",
-// "BASE_URL",
-// "invalid URL");
-// return GNUNET_SYSERR;
-// }
-
-// {
-// char *master_public_key_str;
-
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
-// "donau",
-// "MASTER_PUBLIC_KEY",
-// &master_public_key_str))
-// {
-// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-// "donau",
-// "MASTER_PUBLIC_KEY");
-// return GNUNET_SYSERR;
-// }
-// if (GNUNET_OK !=
-// GNUNET_CRYPTO_eddsa_public_key_from_string (master_public_key_str,
-// strlen (
-//
master_public_key_str),
-// &TEH_master_public_key.
-// eddsa_pub))
-// {
-// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-// "donau",
-// "MASTER_PUBLIC_KEY",
-// "invalid base32 encoding for a master
public key");
-// GNUNET_free (master_public_key_str);
-// return GNUNET_SYSERR;
-// }
-// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-// "Launching donau with public key `%s'...\n",
-// master_public_key_str);
-// GNUNET_free (master_public_key_str);
-// }
-
-// {
-// char *attr_enc_key_str;
-
-// if (GNUNET_OK !=
-// GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
-// "donau",
-// "ATTRIBUTE_ENCRYPTION_KEY",
-// &attr_enc_key_str))
-// {
-// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-// "donau",
-// "ATTRIBUTE_ENCRYPTION_KEY");
-// return GNUNET_SYSERR;
-// }
-// GNUNET_CRYPTO_hash (attr_enc_key_str,
-// strlen (attr_enc_key_str),
-// &TEH_attribute_key.hash);
-// GNUNET_free (attr_enc_key_str);
-// }
-
-// for (unsigned int i = 0; i<MAX_DB_RETRIES; i++)
-// {
-// TEH_plugin = DONAUDB_plugin_load (TEH_cfg);
-// if (NULL != TEH_plugin)
-// break;
-// GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-// "Failed to connect to DB, will try again %u times\n",
-// MAX_DB_RETRIES - i);
-// sleep (1);
-// }
-// if (NULL == TEH_plugin)
-// {
-// GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-// "Failed to initialize DB subsystem. Giving up.\n");
-// return GNUNET_SYSERR;
-// }
-// return GNUNET_OK;
-// }
+ /* mark end of list */
+ {
+ .url = NULL
+ }
+ };
+ struct TEH_RequestContext *rc = *con_cls;
+ struct GNUNET_AsyncScopeSave old_scope;
+ const char *correlation_id = NULL;
+
+ (void) cls;
+ (void) version;
+ if (NULL == rc)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling new request\n");
+
+ /* We're in a new async scope! */
+ rc = *con_cls = GNUNET_new (struct TEH_RequestContext);
+ rc->start_time = GNUNET_TIME_absolute_get ();
+ GNUNET_async_scope_fresh (&rc->async_scope_id);
+ //TEH_check_invariants ();
+ rc->url = url;
+ rc->connection = connection;
+ /* We only read the correlation ID on the first callback for every client
*/
+ correlation_id = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ "Taler-Correlation-Id");
+ if ( (NULL != correlation_id) &&
+ (GNUNET_YES !=
+ GNUNET_CURL_is_valid_scope_id (correlation_id)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "illegal incoming correlation ID\n");
+ correlation_id = NULL;
+ }
+
+ /* Check if upload is in bounds */
+ if (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_POST))
+ {
+ TALER_MHD_check_content_length (connection,
+ TALER_MHD_REQUEST_BUFFER_MAX);
+ }
+ }
+
+ GNUNET_async_scope_enter (&rc->async_scope_id,
+ &old_scope);
+ //TEH_check_invariants ();
+ if (NULL != correlation_id)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling request (%s) for URL '%s', correlation_id=%s\n",
+ method,
+ url,
+ correlation_id);
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling request (%s) for URL '%s'\n",
+ method,
+ url);
+ /* on repeated requests, check our cache first */
+ if (NULL != rc->rh)
+ {
+ MHD_RESULT ret;
+ const char *start;
+
+ if ('\0' == url[0])
+ /* strange, should start with '/', treat as just "/" */
+ url = "/";
+ start = strchr (url + 1, '/');
+ if (NULL == start)
+ start = "";
+ ret = proceed_with_handler (rc,
+ start,
+ upload_data,
+ upload_data_size);
+ GNUNET_async_scope_restore (&old_scope);
+ return ret;
+ }
+
+ if ( (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_OPTIONS)) &&
+ (0 == strcmp ("*",
+ url)) )
+ return TALER_MHD_reply_cors_preflight (connection);
+
+ if (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_HEAD))
+ method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the
rest */
+
+ /* parse first part of URL */
+ {
+ bool found = false;
+ size_t tok_size;
+ const char *tok;
+ const char *rest;
+
+ if ('\0' == url[0])
+ /* strange, should start with '/', treat as just "/" */
+ url = "/";
+ tok = url + 1;
+ rest = strchr (tok, '/');
+ if (NULL == rest)
+ {
+ tok_size = strlen (tok);
+ }
+ else
+ {
+ tok_size = rest - tok;
+ rest++; /* skip over '/' */
+ }
+ for (unsigned int i = 0; NULL != handlers[i].url; i++)
+ {
+ struct TEH_RequestHandler *rh = &handlers[i];
+
+ if ( (0 != strncmp (tok,
+ rh->url,
+ tok_size)) ||
+ (tok_size != strlen (rh->url) ) )
+ continue;
+ found = true;
+ /* The URL is a match! What we now do depends on the method. */
+ if (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_OPTIONS))
+ {
+ GNUNET_async_scope_restore (&old_scope);
+ return TALER_MHD_reply_cors_preflight (connection);
+ }
+ GNUNET_assert (NULL != rh->method);
+ if (0 == strcasecmp (method,
+ rh->method))
+ {
+ MHD_RESULT ret;
+
+ /* cache to avoid the loop next time */
+ rc->rh = rh;
+ /* run handler */
+ ret = proceed_with_handler (rc,
+ url + tok_size + 1,
+ upload_data,
+ upload_data_size);
+ GNUNET_async_scope_restore (&old_scope);
+ return ret;
+ }
+ }
+
+ if (found)
+ {
+ /* we found a matching address, but the method is wrong */
+ struct MHD_Response *reply;
+ MHD_RESULT ret;
+ char *allowed = NULL;
+
+ GNUNET_break_op (0);
+ for (unsigned int i = 0; NULL != handlers[i].url; i++)
+ {
+ struct TEH_RequestHandler *rh = &handlers[i];
+
+ if ( (0 != strncmp (tok,
+ rh->url,
+ tok_size)) ||
+ (tok_size != strlen (rh->url) ) )
+ continue;
+ if (NULL == allowed)
+ {
+ allowed = GNUNET_strdup (rh->method);
+ }
+ else
+ {
+ char *tmp;
+
+ GNUNET_asprintf (&tmp,
+ "%s, %s",
+ allowed,
+ rh->method);
+ GNUNET_free (allowed);
+ allowed = tmp;
+ }
+ if (0 == strcasecmp (rh->method,
+ MHD_HTTP_METHOD_GET))
+ {
+ char *tmp;
+
+ GNUNET_asprintf (&tmp,
+ "%s, %s",
+ allowed,
+ MHD_HTTP_METHOD_HEAD);
+ GNUNET_free (allowed);
+ allowed = tmp;
+ }
+ }
+ reply = TALER_MHD_make_error (TALER_EC_GENERIC_METHOD_INVALID,
+ method);
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (reply,
+ MHD_HTTP_HEADER_ALLOW,
+ allowed));
+ GNUNET_free (allowed);
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_METHOD_NOT_ALLOWED,
+ reply);
+ MHD_destroy_response (reply);
+ return ret;
+ }
+ }
+
+ /* No handler matches, generate not found */
+ {
+ MHD_RESULT ret;
+
+ ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+ url);
+ GNUNET_async_scope_restore (&old_scope);
+ return ret;
+ }
+}
-// /**
-// * Called when the main thread exits, writes out performance
-// * stats if requested.
-// */
-// static void
-// write_stats (void)
-// {
-// struct GNUNET_DISK_FileHandle *fh;
-// pid_t pid = getpid ();
-// char *benchmark_dir;
-// char *s;
-// struct rusage usage;
-
-// benchmark_dir = getenv ("GNUNET_BENCHMARK_DIR");
-// if (NULL == benchmark_dir)
-// return;
-// GNUNET_asprintf (&s,
-// "%s/taler-donau-%llu.txt",
-// benchmark_dir,
-// (unsigned long long) pid);
-// fh = GNUNET_DISK_file_open (s,
-// (GNUNET_DISK_OPEN_WRITE
-// | GNUNET_DISK_OPEN_TRUNCATE
-// | GNUNET_DISK_OPEN_CREATE),
-// (GNUNET_DISK_PERM_USER_READ
-// | GNUNET_DISK_PERM_USER_WRITE));
-// GNUNET_free (s);
-// if (NULL == fh)
-// return; /* permission denied? */
-
-// /* Collect stats, summed up for all threads */
-// GNUNET_assert (0 ==
-// getrusage (RUSAGE_SELF,
-// &usage));
-// GNUNET_asprintf (&s,
-// "time_donau sys %llu user %llu\n",
-// (unsigned long long) (usage.ru_stime.tv_sec * 1000 * 1000
-// + usage.ru_stime.tv_usec),
-// (unsigned long long) (usage.ru_utime.tv_sec * 1000 * 1000
-// + usage.ru_utime.tv_usec));
-// GNUNET_assert (GNUNET_SYSERR !=
-// GNUNET_DISK_file_write_blocking (fh,
-// s,
-// strlen (s)));
-// GNUNET_free (s);
-// GNUNET_assert (GNUNET_OK ==
-// GNUNET_DISK_file_close (fh));
-// }
+/**
+ * Load configuration parameters for the donau
+ * server into the corresponding global variables.
+ *
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+donau_serve_process_config (void)
+{
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (TEH_cfg,
+ "donau",
+ "MAX_REQUESTS",
+ &req_max))
+ {
+ req_max = ULLONG_MAX;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
+ "donaudb",
+ "IDLE_RESERVE_EXPIRATION_TIME",
+ &TEH_reserve_closing_delay))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "donaudb",
+ "IDLE_RESERVE_EXPIRATION_TIME");
+ /* use default */
+ TEH_reserve_closing_delay
+ = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS,
+ 4);
+ }
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
+ "donau",
+ "MAX_KEYS_CACHING",
+ &TEH_max_keys_caching))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "donau",
+ "MAX_KEYS_CACHING",
+ "valid relative time expected");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
+ "donau",
+ "KYC_AML_TRIGGER",
+ &TEH_kyc_aml_trigger))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "donau",
+ "KYC_AML_TRIGGER");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ TALER_config_get_currency (TEH_cfg,
+ &TEH_currency))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler",
+ "CURRENCY");
+ return GNUNET_SYSERR;
+ }
+ {
+ unsigned long long cfd;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (TEH_cfg,
+ "donau",
+ "CURRENCY_FRACTION_DIGITS",
+ &cfd))
+ cfd = 0;
+ if (cfd > 8)
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "taler",
+ "CURRENCY_FRACTION_DIGITS",
+ "Value must be below 8");
+ return GNUNET_SYSERR;
+ }
+ TEH_currency_fraction_digits = (unsigned int) cfd;
+ }
+ if (GNUNET_OK !=
+ TALER_config_get_amount (TEH_cfg,
+ "donau",
+ "AML_THRESHOLD",
+ &TEH_aml_threshold))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Need amount in section `donau' under `AML_THRESHOLD'\n");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ TALER_config_get_amount (TEH_cfg,
+ "donau",
+ "STEFAN_ABS",
+ &TEH_stefan_abs))
+ {
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TEH_currency,
+ &TEH_stefan_abs));
+ }
+ if (GNUNET_OK !=
+ TALER_config_get_amount (TEH_cfg,
+ "donau",
+ "STEFAN_LOG",
+ &TEH_stefan_log))
+ {
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TEH_currency,
+ &TEH_stefan_log));
+ }
+ if (GNUNET_OK !=
+ TALER_config_get_amount (TEH_cfg,
+ "donau",
+ "STEFAN_LIN",
+ &TEH_stefan_lin))
+ {
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TEH_currency,
+ &TEH_stefan_lin));
+ }
+
+ if (0 != strcmp (TEH_currency,
+ TEH_aml_threshold.currency))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Amount in section `donau' under `AML_THRESHOLD' uses the
wrong currency!\n");
+ return GNUNET_SYSERR;
+ }
+ TEH_enable_rewards
+ = GNUNET_CONFIGURATION_get_value_yesno (
+ TEH_cfg,
+ "donau",
+ "ENABLE_REWARDS");
+ if (GNUNET_SYSERR == TEH_enable_rewards)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Need YES or NO in section `donau' under `ENABLE_REWARDS'\n");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
+ "donau",
+ "BASE_URL",
+ &TEH_base_url))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "donau",
+ "BASE_URL");
+ return GNUNET_SYSERR;
+ }
+ if (! TALER_url_valid_charset (TEH_base_url))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "donau",
+ "BASE_URL",
+ "invalid URL");
+ return GNUNET_SYSERR;
+ }
+
+ {
+ char *master_public_key_str;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
+ "donau",
+ "MASTER_PUBLIC_KEY",
+ &master_public_key_str))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "donau",
+ "MASTER_PUBLIC_KEY");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_public_key_from_string (master_public_key_str,
+ strlen (
+ master_public_key_str),
+ &TEH_master_public_key.
+ eddsa_pub))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "donau",
+ "MASTER_PUBLIC_KEY",
+ "invalid base32 encoding for a master public
key");
+ GNUNET_free (master_public_key_str);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Launching donau with public key `%s'...\n",
+ master_public_key_str);
+ GNUNET_free (master_public_key_str);
+ }
+
+ {
+ char *attr_enc_key_str;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
+ "donau",
+ "ATTRIBUTE_ENCRYPTION_KEY",
+ &attr_enc_key_str))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "donau",
+ "ATTRIBUTE_ENCRYPTION_KEY");
+ return GNUNET_SYSERR;
+ }
+ GNUNET_CRYPTO_hash (attr_enc_key_str,
+ strlen (attr_enc_key_str),
+ &TEH_attribute_key.hash);
+ GNUNET_free (attr_enc_key_str);
+ }
+
+ for (unsigned int i = 0; i<MAX_DB_RETRIES; i++)
+ {
+ TEH_plugin = DONAUDB_plugin_load (TEH_cfg);
+ if (NULL != TEH_plugin)
+ break;
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to connect to DB, will try again %u times\n",
+ MAX_DB_RETRIES - i);
+ sleep (1);
+ }
+ if (NULL == TEH_plugin)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to initialize DB subsystem. Giving up.\n");
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Called when the main thread exits, writes out performance
+ * stats if requested.
+ */
+static void
+write_stats (void)
+{
+ struct GNUNET_DISK_FileHandle *fh;
+ pid_t pid = getpid ();
+ char *benchmark_dir;
+ char *s;
+ struct rusage usage;
+
+ benchmark_dir = getenv ("GNUNET_BENCHMARK_DIR");
+ if (NULL == benchmark_dir)
+ return;
+ GNUNET_asprintf (&s,
+ "%s/taler-donau-%llu.txt",
+ benchmark_dir,
+ (unsigned long long) pid);
+ fh = GNUNET_DISK_file_open (s,
+ (GNUNET_DISK_OPEN_WRITE
+ | GNUNET_DISK_OPEN_TRUNCATE
+ | GNUNET_DISK_OPEN_CREATE),
+ (GNUNET_DISK_PERM_USER_READ
+ | GNUNET_DISK_PERM_USER_WRITE));
+ GNUNET_free (s);
+ if (NULL == fh)
+ return; /* permission denied? */
+
+ /* Collect stats, summed up for all threads */
+ GNUNET_assert (0 ==
+ getrusage (RUSAGE_SELF,
+ &usage));
+ GNUNET_asprintf (&s,
+ "time_donau sys %llu user %llu\n",
+ (unsigned long long) (usage.ru_stime.tv_sec * 1000 * 1000
+ + usage.ru_stime.tv_usec),
+ (unsigned long long) (usage.ru_utime.tv_sec * 1000 * 1000
+ + usage.ru_utime.tv_usec));
+ GNUNET_assert (GNUNET_SYSERR !=
+ GNUNET_DISK_file_write_blocking (fh,
+ s,
+ strlen (s)));
+ GNUNET_free (s);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_DISK_file_close (fh));
+}
-// /* Developer logic for supporting the `-f' option. */
-// #if HAVE_DEVELOPER
+/* Developer logic for supporting the `-f' option. */
+#if HAVE_DEVELOPER
/**
* Option `-f' (specifies an input file to give to the HTTP server).
*/
static char *input_filename;
-// /**
-// * Run 'nc' or 'ncat' as a fake HTTP client using #input_filename
-// * as the input for the request. If launching the client worked,
-// * run the #TEH_KS_loop() event loop as usual.
-// *
-// * @return child pid
-// */
-// static pid_t
-// run_fake_client (void)
-// {
-// pid_t cld;
-// char ports[6];
-// int fd;
-
-// if (0 == strcmp (input_filename,
-// "-"))
-// fd = STDIN_FILENO;
-// else
-// fd = open (input_filename,
-// O_RDONLY);
-// if (-1 == fd)
-// {
-// fprintf (stderr,
-// "Failed to open `%s': %s\n",
-// input_filename,
-// strerror (errno));
-// return -1;
-// }
-// /* Fake HTTP client request with #input_filename as input.
-// We do this using the nc tool. */
-// GNUNET_snprintf (ports,
-// sizeof (ports),
-// "%u",
-// serve_port);
-// if (0 == (cld = fork ()))
-// {
-// GNUNET_break (0 == close (0));
-// GNUNET_break (0 == dup2 (fd, 0));
-// GNUNET_break (0 == close (fd));
-// if ( (0 != execlp ("nc",
-// "nc",
-// "localhost",
-// ports,
-// "-w", "30",
-// NULL)) &&
-// (0 != execlp ("ncat",
-// "ncat",
-// "localhost",
-// ports,
-// "-i", "30",
-// NULL)) )
-// {
-// fprintf (stderr,
-// "Failed to run both `nc' and `ncat': %s\n",
-// strerror (errno));
-// }
-// _exit (1);
-// }
-// /* parent process */
-// if (0 != strcmp (input_filename,
-// "-"))
-// GNUNET_break (0 == close (fd));
-// return cld;
-// }
+/**
+ * Run 'nc' or 'ncat' as a fake HTTP client using #input_filename
+ * as the input for the request. If launching the client worked,
+ * run the #TEH_KS_loop() event loop as usual.
+ *
+ * @return child pid
+ */
+static pid_t
+run_fake_client (void)
+{
+ pid_t cld;
+ char ports[6];
+ int fd;
+
+ if (0 == strcmp (input_filename,
+ "-"))
+ fd = STDIN_FILENO;
+ else
+ fd = open (input_filename,
+ O_RDONLY);
+ if (-1 == fd)
+ {
+ fprintf (stderr,
+ "Failed to open `%s': %s\n",
+ input_filename,
+ strerror (errno));
+ return -1;
+ }
+ /* Fake HTTP client request with #input_filename as input.
+ We do this using the nc tool. */
+ GNUNET_snprintf (ports,
+ sizeof (ports),
+ "%u",
+ serve_port);
+ if (0 == (cld = fork ()))
+ {
+ GNUNET_break (0 == close (0));
+ GNUNET_break (0 == dup2 (fd, 0));
+ GNUNET_break (0 == close (fd));
+ if ( (0 != execlp ("nc",
+ "nc",
+ "localhost",
+ ports,
+ "-w", "30",
+ NULL)) &&
+ (0 != execlp ("ncat",
+ "ncat",
+ "localhost",
+ ports,
+ "-i", "30",
+ NULL)) )
+ {
+ fprintf (stderr,
+ "Failed to run both `nc' and `ncat': %s\n",
+ strerror (errno));
+ }
+ _exit (1);
+ }
+ /* parent process */
+ if (0 != strcmp (input_filename,
+ "-"))
+ GNUNET_break (0 == close (fd));
+ return cld;
+}
-// /**
-// * Run the donau to serve a single request only, without threads.
-// *
-// * @return #GNUNET_OK on success
-// */
-// static void
-// run_single_request (void)
-// {
-// pid_t xfork;
-
-// xfork = fork ();
-// if (-1 == xfork)
-// {
-// global_ret = EXIT_FAILURE;
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// if (0 == xfork)
-// {
-// pid_t cld;
-
-// cld = run_fake_client ();
-// if (-1 == cld)
-// _exit (EXIT_FAILURE);
-// _exit (EXIT_SUCCESS);
-// }
-
-// {
-// int status;
-
-// if (xfork != waitpid (xfork,
-// &status,
-// 0))
-// GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-// "Waiting for `nc' child failed: %s\n",
-// strerror (errno));
-// }
-// }
+/**
+ * Run the donau to serve a single request only, without threads.
+ *
+ * @return #GNUNET_OK on success
+ */
+static void
+run_single_request (void)
+{
+ pid_t xfork;
+
+ xfork = fork ();
+ if (-1 == xfork)
+ {
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (0 == xfork)
+ {
+ pid_t cld;
+
+ cld = run_fake_client ();
+ if (-1 == cld)
+ _exit (EXIT_FAILURE);
+ _exit (EXIT_SUCCESS);
+ }
+
+ {
+ int status;
+
+ if (xfork != waitpid (xfork,
+ &status,
+ 0))
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Waiting for `nc' child failed: %s\n",
+ strerror (errno));
+ }
+}
+#endif
+/* end of HAVE_DEVELOPER */
-// /* end of HAVE_DEVELOPER */
-// #endif
-
-
-// /**
-// * Signature of the callback used by MHD to notify the application
-// * about completed connections. If we are running in test-mode with
-// * an input_filename, this function is used to terminate the HTTPD
-// * after the first request has been processed.
-// *
-// * @param cls client-defined closure, NULL
-// * @param connection connection handle (ignored)
-// * @param socket_context socket-specific pointer (ignored)
-// * @param toe reason for connection notification
-// */
-// static void
-// connection_done (void *cls,
-// struct MHD_Connection *connection,
-// void **socket_context,
-// enum MHD_ConnectionNotificationCode toe)
-// {
-// (void) cls;
-// (void) connection;
-// (void) socket_context;
-
-// switch (toe)
-// {
-// case MHD_CONNECTION_NOTIFY_STARTED:
-// active_connections++;
-// break;
-// case MHD_CONNECTION_NOTIFY_CLOSED:
-// active_connections--;
-// if (TEH_suicide &&
-// (0 == active_connections) )
-// GNUNET_SCHEDULER_shutdown ();
-// break;
-// }
-// #if HAVE_DEVELOPER
-// /* We only act if the connection is closed. */
-// if (MHD_CONNECTION_NOTIFY_CLOSED != toe)
-// return;
-// if (NULL != input_filename)
-// GNUNET_SCHEDULER_shutdown ();
-// #endif
-// }
-// /**
-// * Function run on shutdown.
-// *
-// * @param cls NULL
-// */
-// static void
-// do_shutdown (void *cls)
-// {
-// struct MHD_Daemon *mhd;
-// (void) cls;
-
-// mhd = TALER_MHD_daemon_stop ();
-// TEH_resume_keys_requests (true);
-// TEH_deposits_get_cleanup ();
-// TEH_reserves_get_cleanup ();
-// TEH_purses_get_cleanup ();
-// TEH_kyc_check_cleanup ();
-// TEH_kyc_proof_cleanup ();
-// TALER_KYCLOGIC_kyc_done ();
-// if (NULL != mhd)
-// {
-// MHD_stop_daemon (mhd);
-// mhd = NULL;
-// }
-// TEH_wire_done ();
-// TEH_extensions_done ();
-// TEH_keys_finished ();
-// if (NULL != TEH_plugin)
-// {
-// DONAUDB_plugin_unload (TEH_plugin);
-// TEH_plugin = NULL;
-// }
-// if (NULL != TEH_curl_ctx)
-// {
-// GNUNET_CURL_fini (TEH_curl_ctx);
-// TEH_curl_ctx = NULL;
-// }
-// if (NULL != donau_curl_rc)
-// {
-// GNUNET_CURL_gnunet_rc_destroy (donau_curl_rc);
-// donau_curl_rc = NULL;
-// }
-// TALER_TEMPLATING_done ();
-// }
+/**
+ * Signature of the callback used by MHD to notify the application
+ * about completed connections. If we are running in test-mode with
+ * an input_filename, this function is used to terminate the HTTPD
+ * after the first request has been processed.
+ *
+ * @param cls client-defined closure, NULL
+ * @param connection connection handle (ignored)
+ * @param socket_context socket-specific pointer (ignored)
+ * @param toe reason for connection notification
+ */
+static void
+connection_done (void *cls,
+ struct MHD_Connection *connection,
+ void **socket_context,
+ enum MHD_ConnectionNotificationCode toe)
+{
+ (void) cls;
+ (void) connection;
+ (void) socket_context;
+
+ switch (toe)
+ {
+ case MHD_CONNECTION_NOTIFY_STARTED:
+ active_connections++;
+ break;
+ case MHD_CONNECTION_NOTIFY_CLOSED:
+ active_connections--;
+ if (TEH_suicide &&
+ (0 == active_connections) )
+ GNUNET_SCHEDULER_shutdown ();
+ break;
+ }
+#if HAVE_DEVELOPER
+ /* We only act if the connection is closed. */
+ if (MHD_CONNECTION_NOTIFY_CLOSED != toe)
+ return;
+ if (NULL != input_filename)
+ GNUNET_SCHEDULER_shutdown ();
+#endif
+}
-// /**
-// * Main function that will be run by the scheduler.
-// *
-// * @param cls closure
-// * @param args remaining command-line arguments
-// * @param cfgfile name of the configuration file used (for saving, can be
-// * NULL!)
-// * @param config configuration
-// */
-// static void
-// run (void *cls,
-// char *const *args,
-// const char *cfgfile,
-// const struct GNUNET_CONFIGURATION_Handle *config)
-// {
-// enum TALER_MHD_GlobalOptions go;
-// int fh;
-
-// (void) cls;
-// (void) args;
-// (void ) cfgfile;
-// go = TALER_MHD_GO_NONE;
-// if (connection_close)
-// go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE;
-// TALER_MHD_setup (go);
-// TEH_cfg = config;
-
-// if (GNUNET_OK !=
-// donau_serve_process_config ())
-// {
-// global_ret = EXIT_NOTCONFIGURED;
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// if (GNUNET_OK !=
-// TALER_TEMPLATING_init ("donau"))
-// {
-// global_ret = EXIT_FAILURE;
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// // if (GNUNET_SYSERR ==
-// // TEH_plugin->preflight (TEH_plugin->cls))
-// // {
-// // global_ret = EXIT_FAILURE;
-// // GNUNET_SCHEDULER_shutdown ();
-// // return;
-// // }
-// if (GNUNET_OK !=
-// TEH_extensions_init ())
-// {
-// global_ret = EXIT_FAILURE;
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// if (GNUNET_OK !=
-// TEH_keys_init ())
-// {
-// global_ret = EXIT_FAILURE;
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// if (GNUNET_OK !=
-// TEH_wire_init ())
-// {
-// global_ret = EXIT_FAILURE;
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-
-// TEH_load_terms (TEH_cfg);
-// TEH_curl_ctx
-// = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
-// &donau_curl_rc);
-// if (NULL == TEH_curl_ctx)
-// {
-// GNUNET_break (0);
-// global_ret = EXIT_FAILURE;
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// donau_curl_rc = GNUNET_CURL_gnunet_rc_create (TEH_curl_ctx);
-// GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
-// NULL);
-// fh = TALER_MHD_bind (TEH_cfg,
-// "donau",
-// &serve_port);
-// if ( (0 == serve_port) &&
-// (-1 == fh) )
-// {
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME
-// | MHD_USE_PIPE_FOR_SHUTDOWN
-// | MHD_USE_DEBUG | MHD_USE_DUAL_STACK
-// | MHD_USE_TCP_FASTOPEN,
-// (-1 == fh) ? serve_port : 0,
-// NULL, NULL,
-// &handle_mhd_request, NULL,
-// MHD_OPTION_LISTEN_BACKLOG_SIZE,
-// (unsigned int) 1024,
-// MHD_OPTION_LISTEN_SOCKET,
-// fh,
-// MHD_OPTION_EXTERNAL_LOGGER,
-// &TALER_MHD_handle_logs,
-// NULL,
-// MHD_OPTION_NOTIFY_COMPLETED,
-// &handle_mhd_completion_callback,
-// NULL,
-// MHD_OPTION_NOTIFY_CONNECTION,
-// &connection_done,
-// NULL,
-// MHD_OPTION_CONNECTION_TIMEOUT,
-// connection_timeout,
-// (0 == allow_address_reuse)
-// ? MHD_OPTION_END
-// : MHD_OPTION_LISTENING_ADDRESS_REUSE,
-// (unsigned int) allow_address_reuse,
-// MHD_OPTION_END);
-// if (NULL == mhd)
-// {
-// GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-// "Failed to launch HTTP service. Is the port in use?\n");
-// GNUNET_SCHEDULER_shutdown ();
-// return;
-// }
-// global_ret = EXIT_SUCCESS;
-// TALER_MHD_daemon_start (mhd);
-// atexit (&write_stats);
-
-// #if HAVE_DEVELOPER
-// if (NULL != input_filename)
-// run_single_request ();
-// #endif
-// }
+/**
+ * Function run on shutdown.
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+ struct MHD_Daemon *mhd;
+ (void) cls;
+
+ mhd = TALER_MHD_daemon_stop ();
+ // TEH_resume_keys_requests (true);
+ // TEH_deposits_get_cleanup ();
+ // TEH_reserves_get_cleanup ();
+ // TEH_purses_get_cleanup ();
+ // TEH_kyc_check_cleanup ();
+ // TEH_kyc_proof_cleanup ();
+ // TALER_KYCLOGIC_kyc_done ();
+ if (NULL != mhd)
+ {
+ MHD_stop_daemon (mhd);
+ mhd = NULL;
+ }
+ // TEH_wire_done ();
+ // TEH_extensions_done ();
+ // TEH_keys_finished ();
+ if (NULL != TEH_plugin)
+ {
+ DONAUDB_plugin_unload (TEH_plugin);
+ TEH_plugin = NULL;
+ }
+ if (NULL != TEH_curl_ctx)
+ {
+ GNUNET_CURL_fini (TEH_curl_ctx);
+ TEH_curl_ctx = NULL;
+ }
+ if (NULL != donau_curl_rc)
+ {
+ GNUNET_CURL_gnunet_rc_destroy (donau_curl_rc);
+ donau_curl_rc = NULL;
+ }
+ TALER_TEMPLATING_done ();
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be
+ * NULL!)
+ * @param config configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *config)
+{
+ enum TALER_MHD_GlobalOptions go;
+ int fh;
+
+ (void) cls;
+ (void) args;
+ (void ) cfgfile;
+ go = TALER_MHD_GO_NONE;
+ if (connection_close)
+ go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE;
+ TALER_MHD_setup (go);
+ TEH_cfg = config;
+
+ if (GNUNET_OK !=
+ donau_serve_process_config ())
+ {
+ global_ret = EXIT_NOTCONFIGURED;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_TEMPLATING_init ("donau"))
+ {
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_SYSERR ==
+ TEH_plugin->preflight (TEH_plugin->cls))
+ {
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ // if (GNUNET_OK !=
+ // TEH_extensions_init ())
+ // {
+ // global_ret = EXIT_FAILURE;
+ // GNUNET_SCHEDULER_shutdown ();
+ // return;
+ // }
+ // if (GNUNET_OK !=
+ // TEH_keys_init ())
+ // {
+ // global_ret = EXIT_FAILURE;
+ // GNUNET_SCHEDULER_shutdown ();
+ // return;
+ // }
+ // if (GNUNET_OK !=
+ // TEH_wire_init ())
+ // {
+ // global_ret = EXIT_FAILURE;
+ // GNUNET_SCHEDULER_shutdown ();
+ // return;
+ // }
+
+ //TEH_load_terms (TEH_cfg);
+ TEH_curl_ctx
+ = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &donau_curl_rc);
+ if (NULL == TEH_curl_ctx)
+ {
+ GNUNET_break (0);
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ donau_curl_rc = GNUNET_CURL_gnunet_rc_create (TEH_curl_ctx);
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+ NULL);
+ fh = TALER_MHD_bind (TEH_cfg,
+ "donau",
+ &serve_port);
+ if ( (0 == serve_port) &&
+ (-1 == fh) )
+ {
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME
+ | MHD_USE_PIPE_FOR_SHUTDOWN
+ | MHD_USE_DEBUG | MHD_USE_DUAL_STACK
+ | MHD_USE_TCP_FASTOPEN,
+ (-1 == fh) ? serve_port : 0,
+ NULL, NULL,
+ &handle_mhd_request, NULL,
+ MHD_OPTION_LISTEN_BACKLOG_SIZE,
+ (unsigned int) 1024,
+ MHD_OPTION_LISTEN_SOCKET,
+ fh,
+ MHD_OPTION_EXTERNAL_LOGGER,
+ &TALER_MHD_handle_logs,
+ NULL,
+ MHD_OPTION_NOTIFY_COMPLETED,
+ &handle_mhd_completion_callback,
+ NULL,
+ MHD_OPTION_NOTIFY_CONNECTION,
+ &connection_done,
+ NULL,
+ MHD_OPTION_CONNECTION_TIMEOUT,
+ connection_timeout,
+ (0 == allow_address_reuse)
+ ? MHD_OPTION_END
+ : MHD_OPTION_LISTENING_ADDRESS_REUSE,
+ (unsigned int) allow_address_reuse,
+ MHD_OPTION_END);
+ if (NULL == mhd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to launch HTTP service. Is the port in use?\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ global_ret = EXIT_SUCCESS;
+ TALER_MHD_daemon_start (mhd);
+ atexit (&write_stats);
+
+#if HAVE_DEVELOPER
+ if (NULL != input_filename)
+ run_single_request ();
+#endif
+}
/**
* The main function of the taler-donau-httpd server ("the donau").
@@ -1488,17 +1483,16 @@ main (int argc,
(void)options[0]; // delete me
ret = 1; // delete me
DONAU_OS_init ();
- // ret = GNUNET_PROGRAM_run (argc, argv,
- // "taler-donau-httpd",
- // "Taler donau HTTP service",
- // options,
- // &run, NULL);
+ ret = GNUNET_PROGRAM_run (argc, argv,
+ "taler-donau-httpd",
+ "Taler donau HTTP service",
+ options,
+ &run, NULL);
if (GNUNET_SYSERR == ret)
return EXIT_INVALIDARGUMENT;
if (GNUNET_NO == ret)
return EXIT_SUCCESS;
- // return global_ret;
- return -1;
+ return global_ret;
}
/* end of taler-donau-httpd.c */
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-donau] branch master updated: [donau] uncomment most of donau-httpd.c,
gnunet <=