gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated: implement /config API


From: gnunet
Subject: [taler-merchant] branch master updated: implement /config API
Date: Tue, 07 Apr 2020 13:22:17 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new 75e07c7  implement /config API
75e07c7 is described below

commit 75e07c707c5d8ec98666b6929c41402855dfd004
Author: Christian Grothoff <address@hidden>
AuthorDate: Tue Apr 7 13:22:15 2020 +0200

    implement /config API
---
 src/include/taler_merchant_service.h | 169 ++++++++++++++++++
 src/lib/Makefile.am                  |   1 +
 src/lib/merchant_api_config.c        | 327 +++++++++++++++++++++++++++++++++++
 src/lib/merchant_api_tip_query.c     |   9 -
 4 files changed, 497 insertions(+), 9 deletions(-)

diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index d8d51d4..c99f18b 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -121,6 +121,175 @@ TALER_MERCHANT_parse_error_details_ (const json_t 
*response,
                                      struct TALER_MERCHANT_HttpResponse *hr);
 
 
+/* ********************* /public/config ****************** */
+
+
+/**
+ * How compatible are the protocol version of the auditor and this
+ * client?  The bits (1,2,4) can be used to test if the auditor's
+ * version is incompatible, older or newer respectively.
+ */
+enum TALER_MERCHANT_VersionCompatibility
+{
+
+  /**
+   * The auditor runs exactly the same protocol version.
+   */
+  TALER_MERCHANT_VC_MATCH = 0,
+
+  /**
+   * The auditor is too old or too new to be compatible with this
+   * implementation (bit)
+   */
+  TALER_MERCHANT_VC_INCOMPATIBLE = 1,
+
+  /**
+   * The auditor is older than this implementation (bit)
+   */
+  TALER_MERCHANT_VC_OLDER = 2,
+
+  /**
+   * The auditor is too old to be compatible with
+   * this implementation.
+   */
+  TALER_MERCHANT_VC_INCOMPATIBLE_OUTDATED
+    = TALER_MERCHANT_VC_INCOMPATIBLE
+      | TALER_MERCHANT_VC_OLDER,
+
+  /**
+   * The auditor is more recent than this implementation (bit).
+   */
+  TALER_MERCHANT_VC_NEWER = 4,
+
+  /**
+   * The auditor is too recent for this implementation.
+   */
+  TALER_MERCHANT_VC_INCOMPATIBLE_NEWER
+    = TALER_MERCHANT_VC_INCOMPATIBLE
+      | TALER_MERCHANT_VC_NEWER,
+
+  /**
+   * We could not even parse the version data.
+   */
+  TALER_MERCHANT_VC_PROTOCOL_ERROR = 8
+
+};
+
+
+/**
+ * @brief Information about a merchant instance.
+ */
+struct TALER_MERCHANT_InstanceInformation
+{
+  /**
+   * URL of this instance.  The URL can be relative to the current domain
+   * (i.e. "/PizzaShop/") or include a schema and fully qualified domain name
+   * (i.e. "https://backend.example.com/";). The latter can be used to redirect
+   * clients to a different server in case the deployment location changes.
+   */
+  const char *instance_baseurl;
+
+  /**
+   * Legal name of the merchant/instance.
+   */
+  const char *name;
+
+  /**
+   * Base URL of the exchange this instance uses for tipping, or NULL if this
+   * instance does not support tipping.
+   */
+  const char *tipping_exchange_baseurl;
+
+  /**
+   * Public key of the instance.
+   */
+  struct TALER_MerchantPublicKeyP merchant_pub;
+
+};
+
+
+/**
+ * @brief Config information we get from the backend.
+ */
+struct TALER_MERCHANT_ConfigInformation
+{
+  /**
+   * Currency used/supported by the merchant.
+   */
+  const char *currency;
+
+  /**
+   * Supported Taler protocol version by the merchant.
+   * String in the format current:revision:age using the
+   * semantics of GNU libtool.  See
+   * 
https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+   */
+  const char *version;
+
+  /**
+   * Array with information about the merchant's instances.
+   */
+  struct TALER_MERCHANT_InstanceInformation *iis;
+
+  /**
+   * Length of the @e iis array.
+   */
+  unsigned int iis_len;
+
+};
+
+
+/**
+ * Function called with information about the merchant.
+ *
+ * @param cls closure
+ * @param hr HTTP response data
+ * @param ci basic information about the merchant
+ * @param compat protocol compatibility information
+ */
+typedef void
+(*TALER_MERCHANT_ConfigCallback) (
+  void *cls,
+  const struct TALER_MERCHANT_HttpResponse *hr,
+  const struct TALER_MERCHANT_ConfigInformation *ci,
+  enum TALER_MERCHANT_VersionCompatibility compat);
+
+
+/**
+ * Handle for a #TALER_MERCHANT_config_get() operation.
+ */
+struct TALER_MERCHANT_ConfigGetHandle;
+
+
+/**
+ * Get the config data of a merchant. Will connect to the merchant backend
+ * and obtain information about the backend.  The respective information will
+ * be passed to the @a config_cb once available.
+ *
+ * @param ctx the context
+ * @param backend_url HTTP base URL for the backend
+ * @param config_cb function to call with the
+ *        backend's config information
+ * @param config_cb_cls closure for @a config_cb
+ * @return the config check handle; NULL upon error
+ */
+struct TALER_MERCHANT_ConfigGetHandle *
+TALER_MERCHANT_config_get (struct GNUNET_CURL_Context *ctx,
+                           const char *backend_url,
+                           TALER_MERCHANT_ConfigCallback config_cb,
+                           void *config_cb_cls);
+
+
+/**
+ * Cancel /config request.  Must not be called by clients after
+ * the callback was invoked.
+ *
+ * @param vgh request to cancel.
+ */
+void
+TALER_MERCHANT_config_get_cancel (struct TALER_MERCHANT_ConfigGetHandle *vgh);
+
+
 /* ********************* /refund ************************** */
 
 /**
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 308d649..02fd2a4 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -21,6 +21,7 @@ libtalermerchanttesting_la_LDFLAGS = \
 libtalermerchant_la_SOURCES = \
   merchant_api_check_payment.c \
   merchant_api_common.c \
+  merchant_api_config.c \
   merchant_api_history.c \
   merchant_api_proposal.c \
   merchant_api_proposal_lookup.c \
diff --git a/src/lib/merchant_api_config.c b/src/lib/merchant_api_config.c
new file mode 100644
index 0000000..16c2014
--- /dev/null
+++ b/src/lib/merchant_api_config.c
@@ -0,0 +1,327 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2018, 2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free 
Software
+  Foundation; either version 2.1, 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 Lesser General Public License for more 
details.
+
+  You should have received a copy of the GNU Lesser General Public License 
along with
+  TALER; see the file COPYING.LGPL.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/merchant_api_config.c
+ * @brief Implementation of the /config request of the merchant's HTTP API
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_merchant_service.h"
+#include <taler/taler_json_lib.h>
+#include <taler/taler_signatures.h>
+
+/**
+ * Which version of the Taler protocol is implemented
+ * by this library?  Used to determine compatibility.
+ */
+#define MERCHANT_PROTOCOL_CURRENT 0
+
+/**
+ * How many configs are we backwards compatible with?
+ */
+#define MERCHANT_PROTOCOL_AGE 0
+
+
+/**
+ * @brief A handle for /config operations
+ */
+struct TALER_MERCHANT_ConfigGetHandle
+{
+  /**
+   * The url for this request.
+   */
+  char *url;
+
+  /**
+   * Handle for the request.
+   */
+  struct GNUNET_CURL_Job *job;
+
+  /**
+   * Function to call with the result.
+   */
+  TALER_MERCHANT_ConfigCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Reference to the execution context.
+   */
+  struct GNUNET_CURL_Context *ctx;
+
+};
+
+
+/**
+ * Parse instance information from @a ia.
+ *
+ * @param ia JSON array (or NULL!) with instance data
+ * @param[in,out] ci config information to update
+ * @return #GNUNET_OK on success
+ */
+static int
+parse_instances (const json_t *ia,
+                 struct TALER_MERCHANT_ConfigInformation *ci)
+{
+  size_t index;
+  json_t *value;
+  int ret;
+
+  if (NULL == ia)
+    return GNUNET_OK; /* permit not disclosing instances for now */
+  if (! json_is_array (ia))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_array_grow (ci->iis,
+                     ci->iis_len,
+                     json_array_size (ia));
+  ret = GNUNET_OK;
+  json_array_foreach (ia, index, value) {
+    struct TALER_MERCHANT_InstanceInformation *ii = &ci->iis[index];
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+                                   &ii->merchant_pub),
+      GNUNET_JSON_spec_string ("instance_baseurl",
+                               &ii->instance_baseurl),
+      GNUNET_JSON_spec_string ("name",
+                               &ii->name),
+      GNUNET_JSON_spec_string ("tipping_exchange_baseurl",
+                               &ii->tipping_exchange_baseurl),
+      GNUNET_JSON_spec_end ()
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (value,
+                           spec,
+                           NULL, NULL))
+    {
+      GNUNET_break_op (0);
+      ret = GNUNET_SYSERR;
+    }
+  }
+  return ret;
+}
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /track/transaction request.
+ *
+ * @param cls the `struct TALER_MERCHANT_ConfigGetHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param json response body, NULL if not in JSON
+ */
+static void
+handle_config_finished (void *cls,
+                        long response_code,
+                        const void *response)
+{
+  struct TALER_MERCHANT_ConfigGetHandle *vgh = cls;
+  const json_t *json = response;
+  struct TALER_MERCHANT_HttpResponse hr = {
+    .http_status = (unsigned int) response_code,
+    .reply = json
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got /config response with status code %u\n",
+              (unsigned int) response_code);
+
+  vgh->job = NULL;
+  switch (response_code)
+  {
+  case MHD_HTTP_OK:
+    {
+      struct TALER_MERCHANT_ConfigInformation vi = {
+        .iis = NULL,
+        .iis_len = 0
+      };
+      enum TALER_MERCHANT_VersionCompatibility vc =
+        TALER_MERCHANT_VC_PROTOCOL_ERROR;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_string ("currency",
+                                 &vi.currency),
+        GNUNET_JSON_spec_string ("version",
+                                 &vi.version),
+        GNUNET_JSON_spec_end ()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (json,
+                             spec,
+                             NULL, NULL))
+      {
+        hr.http_status = 0;
+        hr.ec = TALER_EC_INVALID_RESPONSE;
+      }
+      else
+      {
+        unsigned int age;
+        unsigned int revision;
+        unsigned int current;
+
+        if (3 != sscanf (vi.version,
+                         "%u:%u:%u",
+                         &current,
+                         &revision,
+                         &age))
+        {
+          hr.http_status = 0;
+          hr.ec = TALER_EC_INVALID_RESPONSE;
+        }
+        else
+        {
+          vc = TALER_MERCHANT_VC_MATCH;
+          if (MERCHANT_PROTOCOL_CURRENT < current)
+          {
+            vc |= TALER_MERCHANT_VC_NEWER;
+            if (MERCHANT_PROTOCOL_CURRENT < current - age)
+              vc |= TALER_MERCHANT_VC_INCOMPATIBLE;
+          }
+          if (MERCHANT_PROTOCOL_CURRENT > current)
+          {
+            vc |= TALER_MERCHANT_VC_OLDER;
+            if (MERCHANT_PROTOCOL_CURRENT - MERCHANT_PROTOCOL_AGE > current)
+              vc |= TALER_MERCHANT_VC_INCOMPATIBLE;
+          }
+        }
+      }
+      if (0 == (vc & (TALER_MERCHANT_VC_INCOMPATIBLE
+                      | TALER_MERCHANT_VC_PROTOCOL_ERROR)))
+      {
+        if (GNUNET_OK !=
+            parse_instances (json_object_get (json,
+                                              "instances"),
+                             &vi))
+        {
+          /* Let's keep the 200 OK, as we got at least the version data */
+          hr.ec = TALER_EC_INVALID_RESPONSE;
+        }
+      }
+      vgh->cb (vgh->cb_cls,
+               &hr,
+               &vi,
+               vc);
+      GNUNET_array_grow (vi.iis,
+                         vi.iis_len,
+                         0);
+      TALER_MERCHANT_config_get_cancel (vgh);
+      return;
+    }
+  default:
+    /* unexpected response code */
+    hr.ec = TALER_JSON_get_error_code (json);
+    hr.hint = TALER_JSON_get_error_hint (json);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u/%d\n",
+                (unsigned int) response_code,
+                (int) hr.ec);
+    vgh->cb (vgh->cb_cls,
+             &hr,
+             NULL,
+             TALER_MERCHANT_VC_PROTOCOL_ERROR);
+    break;
+  }
+  TALER_MERCHANT_config_get_cancel (vgh);
+}
+
+
+/**
+ * Get the config data of a merchant. Will connect to the merchant backend
+ * and obtain information about the backend.  The respective information will
+ * be passed to the @a config_cb once available.
+ *
+ * @param ctx the context
+ * @param backend_url HTTP base URL for the backend
+ * @param config_cb function to call with the
+ *        backend's config information
+ * @param config_cb_cls closure for @a config_cb
+ * @return the config check handle; NULL upon error
+ */
+struct TALER_MERCHANT_ConfigGetHandle *
+TALER_MERCHANT_config_get (struct GNUNET_CURL_Context *ctx,
+                           const char *backend_url,
+                           TALER_MERCHANT_ConfigCallback config_cb,
+                           void *config_cb_cls)
+{
+  struct TALER_MERCHANT_ConfigGetHandle *vgh;
+  CURL *eh;
+
+  vgh = GNUNET_new (struct TALER_MERCHANT_ConfigGetHandle);
+  vgh->ctx = ctx;
+  vgh->cb = config_cb;
+  vgh->cb_cls = config_cb_cls;
+  vgh->url = TALER_url_join (backend_url,
+                             "config",
+                             NULL);
+  if (NULL == vgh->url)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not construct request URL.\n");
+    GNUNET_free (vgh);
+    return NULL;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Requesting URL '%s'\n",
+              vgh->url);
+
+  eh = curl_easy_init ();
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_URL,
+                                   vgh->url));
+
+  vgh->job = GNUNET_CURL_job_add (ctx,
+                                  eh,
+                                  GNUNET_YES,
+                                  &handle_config_finished,
+                                  vgh);
+  return vgh;
+}
+
+
+/**
+ * Cancel /config request.  Must not be called by clients after
+ * the callback was invoked.
+ *
+ * @param vgh request to cancel.
+ */
+void
+TALER_MERCHANT_config_get_cancel (struct TALER_MERCHANT_ConfigGetHandle *vgh)
+{
+  if (NULL != vgh->job)
+  {
+    GNUNET_CURL_job_cancel (vgh->job);
+    vgh->job = NULL;
+  }
+  GNUNET_free (vgh->url);
+  GNUNET_free (vgh);
+}
+
+
+/* end of merchant_api_config.c */
diff --git a/src/lib/merchant_api_tip_query.c b/src/lib/merchant_api_tip_query.c
index 12633c8..250d26d 100644
--- a/src/lib/merchant_api_tip_query.c
+++ b/src/lib/merchant_api_tip_query.c
@@ -40,11 +40,6 @@ struct TALER_MERCHANT_TipQueryOperation
    */
   char *url;
 
-  /**
-   * JSON encoding of the request to POST.
-   */
-  char *json_enc;
-
   /**
    * Handle for the request.
    */
@@ -65,10 +60,6 @@ struct TALER_MERCHANT_TipQueryOperation
    */
   struct GNUNET_CURL_Context *ctx;
 
-  /**
-   * Expected number of planchets.
-   */
-  unsigned int num_planchets;
 };
 
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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