gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: -start kyc-tester helper


From: gnunet
Subject: [taler-exchange] branch master updated: -start kyc-tester helper
Date: Sun, 07 Aug 2022 21:48:41 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new d4fb0695 -start kyc-tester helper
d4fb0695 is described below

commit d4fb0695ceb2f1c1ceb0ef1fc6fdded668396d4d
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Aug 7 21:48:38 2022 +0200

    -start kyc-tester helper
---
 src/exchange/taler-exchange-httpd.c      |   1 -
 src/kyclogic/Makefile.am                 |  29 +-
 src/kyclogic/plugin_kyclogic_oauth2.c    |   2 +-
 src/kyclogic/plugin_kyclogic_template.c  |  17 +-
 src/kyclogic/taler-exchange-kyc-tester.c | 801 +++++++++++++++++++++++++++++++
 5 files changed, 837 insertions(+), 13 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index 14cc8c1c..fefded57 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -25,7 +25,6 @@
 #include <jansson.h>
 #include <microhttpd.h>
 #include <sched.h>
-#include <pthread.h>
 #include <sys/resource.h>
 #include <limits.h>
 #include "taler_mhd_lib.h"
diff --git a/src/kyclogic/Makefile.am b/src/kyclogic/Makefile.am
index 4a4f60a4..7c754a80 100644
--- a/src/kyclogic/Makefile.am
+++ b/src/kyclogic/Makefile.am
@@ -16,10 +16,37 @@ EXTRA_DIST = \
   kyclogic.conf \
   kyclogic-oauth2.conf
 
+bin_PROGRAMS = \
+  taler-exchange-kyc-tester
+
+taler_exchange_kyc_tester_SOURCES = \
+  taler-exchange-kyc-tester.c
+taler_exchange_kyc_tester_LDADD = \
+  $(LIBGCRYPT_LIBS) \
+  $(top_builddir)/src/mhd/libtalermhd.la \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  -lmicrohttpd \
+  -lgnunetcurl \
+  -lgnunetutil \
+  -lgnunetjson \
+  -ljansson \
+  -lcurl \
+  -lz \
+  $(XLIB)
+
+
+
 plugindir = $(libdir)/taler
 
 plugin_LTLIBRARIES = \
-  libtaler_plugin_kyclogic_oauth2.la
+  libtaler_plugin_kyclogic_oauth2.la \
+  libtaler_plugin_kyclogic_template.la
+
+libtaler_plugin_kyclogic_template_la_SOURCES = \
+  plugin_kyclogic_template.c
+libtaler_plugin_kyclogic_template_la_LIBADD = \
+  $(LTLIBINTL)
 
 libtaler_plugin_kyclogic_oauth2_la_SOURCES = \
   plugin_kyclogic_oauth2.c
diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c 
b/src/kyclogic/plugin_kyclogic_oauth2.c
index ac13355e..42f195be 100644
--- a/src/kyclogic/plugin_kyclogic_oauth2.c
+++ b/src/kyclogic/plugin_kyclogic_oauth2.c
@@ -975,7 +975,7 @@ oauth2_webhook (void *cls,
                 TALER_KYCLOGIC_ProviderLookupCallback plc,
                 void *plc_cls,
                 const char *http_method,
-                const char *url_path[],
+                const char *const url_path[],
                 struct MHD_Connection *connection,
                 const json_t *body,
                 TALER_KYCLOGIC_WebhookCallback cb,
diff --git a/src/kyclogic/plugin_kyclogic_template.c 
b/src/kyclogic/plugin_kyclogic_template.c
index 1cc9b97c..e59c15da 100644
--- a/src/kyclogic/plugin_kyclogic_template.c
+++ b/src/kyclogic/plugin_kyclogic_template.c
@@ -164,10 +164,6 @@ struct TALER_KYCLOGIC_WebhookHandle
    */
   const struct TALER_KYCLOGIC_ProviderDetails *pd;
 
-  /**
-   * Overall plugin state.
-   */
-  struct PluginState *ps;
 };
 
 
@@ -210,6 +206,7 @@ template_unload_configuration (struct 
TALER_KYCLOGIC_ProviderDetails *pd)
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param pd provider configuration details
  * @param account_id which account to trigger process for
+ * @param legitimization_uuid unique ID for the legitimization process
  * @param cb function to call with the result
  * @param cb_cls closure for @a cb
  * @return handle to cancel operation early
@@ -218,6 +215,7 @@ static struct TALER_KYCLOGIC_InitiateHandle *
 template_initiate (void *cls,
                    const struct TALER_KYCLOGIC_ProviderDetails *pd,
                    const struct TALER_PaytoHashP *account_id,
+                   uint64_t legitimization_uuid,
                    TALER_KYCLOGIC_InitiateCallback cb,
                    void *cb_cls)
 {
@@ -230,7 +228,7 @@ template_initiate (void *cls,
   ih->h_payto = *account_id;
   ih->pd = pd;
   GNUNET_break (0); // FIXME: add actual initiation logic!
-  return res;
+  return ih;
 }
 
 
@@ -282,7 +280,7 @@ template_proof (void *cls,
   ph->cb_cls = cb_cls;
 
   GNUNET_break (0); // FIXME: start check!
-  return ps;
+  return ph;
 }
 
 
@@ -321,10 +319,9 @@ template_webhook (void *cls,
                   TALER_KYCLOGIC_ProviderLookupCallback plc,
                   void *plc_cls,
                   const char *http_method,
-                  const char *url_path,
+                  const char *const url_path[],
                   struct MHD_Connection *connection,
-                  size_t body_size,
-                  const void *body,
+                  const json_t *body,
                   TALER_KYCLOGIC_WebhookCallback cb,
                   void *cb_cls)
 {
@@ -370,7 +367,7 @@ libtaler_plugin_kyclogic_template_init (void *cls)
   ps = GNUNET_new (struct PluginState);
   ps->cfg = cfg;
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
+      GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "exchange",
                                              "BASE_URL",
                                              &ps->exchange_base_url))
diff --git a/src/kyclogic/taler-exchange-kyc-tester.c 
b/src/kyclogic/taler-exchange-kyc-tester.c
new file mode 100644
index 00000000..24809a82
--- /dev/null
+++ b/src/kyclogic/taler-exchange-kyc-tester.c
@@ -0,0 +1,801 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 Taler Systems SA
+
+   TALER is free software; you can redistribute it and/or modify it under the
+   terms of the GNU Affero General Public License as published by the Free 
Software
+   Foundation; either version 3, or (at your option) any later version.
+
+   TALER 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 Affero General Public License for more 
details.
+
+   You should have received a copy of the GNU Affero General Public License 
along with
+   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file taler-exchange-kyc-tester.c
+ * @brief tool to test KYC integrations
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <jansson.h>
+#include <microhttpd.h>
+#include <sched.h>
+#include <sys/resource.h>
+#include <limits.h>
+#include "taler_mhd_lib.h"
+#include "taler_json_lib.h"
+#include "taler_crypto_lib.h"
+#include "taler_kyclogic_plugin.h"
+#include <gnunet/gnunet_mhd_compat.h>
+
+
+/**
+ * @brief Context in which the exchange is processing
+ *        all requests
+ */
+struct TEKT_RequestContext
+{
+
+  /**
+   * Opaque parsing context.
+   */
+  void *opaque_post_parsing_context;
+
+  /**
+   * Request handler responsible for this request.
+   */
+  const struct TEKT_RequestHandler *rh;
+
+  /**
+   * Request URL (for logging).
+   */
+  const char *url;
+
+  /**
+   * Connection we are processing.
+   */
+  struct MHD_Connection *connection;
+
+  /**
+   * @e rh-specific cleanup routine. Function called
+   * upon completion of the request that should
+   * clean up @a rh_ctx. Can be NULL.
+   */
+  void
+  (*rh_cleaner)(struct TEKT_RequestContext *rc);
+
+  /**
+   * @e rh-specific context. Place where the request
+   * handler can associate state with this request.
+   * Can be NULL.
+   */
+  void *rh_ctx;
+};
+
+
+/**
+ * @brief Struct describing an URL and the handler for it.
+ */
+struct TEKT_RequestHandler
+{
+
+  /**
+   * URL the handler is for (first part only).
+   */
+  const char *url;
+
+  /**
+   * Method the handler is for.
+   */
+  const char *method;
+
+  /**
+   * Callbacks for handling of the request. Which one is used
+   * depends on @e method.
+   */
+  union
+  {
+    /**
+     * Function to call to handle a GET requests (and those
+     * with @e method NULL).
+     *
+     * @param rc context for the request
+     * @param mime_type the @e mime_type for the reply (hint, can be NULL)
+     * @param args array of arguments, needs to be of length @e args_expected
+     * @return MHD result code
+     */
+    MHD_RESULT
+    (*get)(struct TEKT_RequestContext *rc,
+           const char *const args[]);
+
+
+    /**
+     * Function to call to handle a POST request.
+     *
+     * @param rc context for the request
+     * @param json uploaded JSON data
+     * @param args array of arguments, needs to be of length @e args_expected
+     * @return MHD result code
+     */
+    MHD_RESULT
+    (*post)(struct TEKT_RequestContext *rc,
+            const json_t *root,
+            const char *const args[]);
+
+  } handler;
+
+  /**
+   * Number of arguments this handler expects in the @a args array.
+   */
+  unsigned int nargs;
+
+  /**
+   * Is the number of arguments given in @e nargs only an upper bound,
+   * and calling with fewer arguments could be OK?
+   */
+  bool nargs_is_upper_bound;
+
+  /**
+   * Mime type to use in reply (hint, can be NULL).
+   */
+  const char *mime_type;
+
+  /**
+   * Raw data for the @e handler, can be NULL for none provided.
+   */
+  const void *data;
+
+  /**
+   * Number of bytes in @e data, 0 for data is 0-terminated (!).
+   */
+  size_t data_size;
+
+  /**
+   * Default response code. 0 for none provided.
+   */
+  unsigned int response_code;
+};
+
+
+/**
+ * The exchange's configuration (global)
+ */
+static const struct GNUNET_CONFIGURATION_Handle *TEKT_cfg;
+
+/**
+ * Handle to the HTTP server.
+ */
+static struct MHD_Daemon *mhd;
+
+/**
+ * Our currency.
+ */
+static char *TEKT_currency;
+
+/**
+ * Our base URL.
+ */
+static char *TEKT_base_url;
+
+/**
+ * Value to return from main()
+ */
+static int global_ret;
+
+/**
+ * Port to run the daemon on.
+ */
+static uint16_t serve_port;
+
+/**
+ * Context for all CURL operations (useful to the event loop)
+ */
+static struct GNUNET_CURL_Context *TEKT_curl_ctx;
+
+/**
+ * Context for integrating #TEKT_curl_ctx with the
+ * GNUnet event loop.
+ */
+static struct GNUNET_CURL_RescheduleContext *exchange_curl_rc;
+
+
+/**
+ * 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)
+{
+  return TALER_MHD_reply_with_error (connection,
+                                     MHD_HTTP_NOT_FOUND,
+                                     
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
+                                     details);
+}
+
+
+/**
+ * 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 TEKT_RequestContext *rc = *con_cls;
+
+  (void) cls;
+  if (NULL == rc)
+    return;
+  if (NULL != rc->rh_cleaner)
+    rc->rh_cleaner (rc);
+  {
+#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_free (rc);
+  *con_cls = NULL;
+}
+
+
+/**
+ * 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 TEKT_RequestContext *rc,
+                      const char *url,
+                      const char *upload_data,
+                      size_t *upload_data_size)
+{
+  const struct TEKT_RequestHandler *rh = rc->rh;
+  // FIXME: handle '-1 == rh->nargs'!!!
+  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 */
+    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 (NULL != root)
+      ret = rh->handler.post (rc,
+                              root,
+                              args);
+    else /* We also only have "POST" or "GET" in the API for at this point
+      (OPTIONS/HEAD are taken care of earlier) */
+      ret = rh->handler.get (rc,
+                             args);
+  }
+  json_decref (root);
+  return ret;
+}
+
+
+/**
+ * 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 TEKT_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 TEKT_RequestHandler handlers[] = {
+#if FIXME
+    /* KYC endpoints */
+    {
+      .url = "kyc-check",
+      .method = MHD_HTTP_METHOD_GET,
+      .handler.get = &TEKT_handler_kyc_check,
+      .nargs = 1
+    },
+    {
+      .url = "kyc-proof",
+      .method = MHD_HTTP_METHOD_GET,
+      .handler.get = &TEKT_handler_kyc_proof,
+      .nargs = 1
+    },
+    {
+      .url = "kyc-wallet",
+      .method = MHD_HTTP_METHOD_POST,
+      .handler.post = &TEKT_handler_kyc_wallet,
+      .nargs = 0
+    },
+    {
+      .url = "kyc-webhook",
+      .method = MHD_HTTP_METHOD_POST,
+      .handler.post = &TEKT_handler_kyc_webhook_post,
+      .nargs = -1
+    },
+    {
+      .url = "kyc-webhook",
+      .method = MHD_HTTP_METHOD_GET,
+      .handler.post = &TEKT_handler_kyc_webhook_get,
+      .nargs = -1
+    },
+#endif
+    /* mark end of list */
+    {
+      .url = NULL
+    }
+  };
+  struct TEKT_RequestContext *rc = *con_cls;
+
+  (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 TEKT_RequestContext);
+    rc->url = url;
+    rc->connection = connection;
+  }
+
+  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);
+    return ret;
+  }
+  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 TEKT_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))
+      {
+        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);
+        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 TEKT_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);
+    return ret;
+  }
+}
+
+
+/**
+ * Load configuration parameters for the exchange
+ * server into the corresponding global variables.
+ *
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+exchange_serve_process_config (void)
+{
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (TEKT_cfg,
+                                             "exchange",
+                                             "BASE_URL",
+                                             &TEKT_base_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "BASE_URL");
+    return GNUNET_SYSERR;
+  }
+  if (! TALER_url_valid_charset (TEKT_base_url))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "BASE_URL",
+                               "invalid URL");
+    return GNUNET_SYSERR;
+  }
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function run on shutdown.
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+  struct MHD_Daemon *mhd;
+  (void) cls;
+
+  mhd = TALER_MHD_daemon_stop ();
+  if (NULL != mhd)
+    MHD_stop_daemon (mhd);
+  if (NULL != TEKT_curl_ctx)
+  {
+    GNUNET_CURL_fini (TEKT_curl_ctx);
+    TEKT_curl_ctx = NULL;
+  }
+  if (NULL != exchange_curl_rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (exchange_curl_rc);
+    exchange_curl_rc = NULL;
+  }
+}
+
+
+/**
+ * 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)
+{
+  int fh;
+
+  (void) cls;
+  (void) args;
+  (void ) cfgfile;
+  TALER_MHD_setup (TALER_MHD_GO_NONE);
+  TEKT_cfg = config;
+
+  if (GNUNET_OK !=
+      exchange_serve_process_config ())
+  {
+    global_ret = EXIT_NOTCONFIGURED;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  TEKT_curl_ctx
+    = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                        &exchange_curl_rc);
+  if (NULL == TEKT_curl_ctx)
+  {
+    GNUNET_break (0);
+    global_ret = EXIT_FAILURE;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  exchange_curl_rc = GNUNET_CURL_gnunet_rc_create (TEKT_curl_ctx);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+                                 NULL);
+  fh = TALER_MHD_bind (TEKT_cfg,
+                       "exchange",
+                       &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_SOCKET,
+                          fh,
+                          MHD_OPTION_EXTERNAL_LOGGER,
+                          &TALER_MHD_handle_logs,
+                          NULL,
+                          MHD_OPTION_NOTIFY_COMPLETED,
+                          &handle_mhd_completion_callback,
+                          NULL,
+                          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);
+}
+
+
+/**
+ * The main function of the taler-exchange-httpd server ("the exchange").
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc,
+      char *const *argv)
+{
+  const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_help (
+      "tool to test KYC provider integrations"),
+    GNUNET_GETOPT_OPTION_END
+  };
+  enum GNUNET_GenericReturnValue ret;
+
+  TALER_OS_init ();
+  ret = GNUNET_PROGRAM_run (argc, argv,
+                            "taler-exchange-kyc-tester",
+                            "tool to test KYC provider integrations",
+                            options,
+                            &run, NULL);
+  if (GNUNET_SYSERR == ret)
+    return EXIT_INVALIDARGUMENT;
+  if (GNUNET_NO == ret)
+    return EXIT_SUCCESS;
+  return global_ret;
+}
+
+
+/* end of taler-exchange-kyc-tester.c */

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]