gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated: skeleton for libtal


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: skeleton for libtalerauditor
Date: Mon, 22 Oct 2018 16:00:11 +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 e83964ba skeleton for libtalerauditor
e83964ba is described below

commit e83964badb5c266992f5b1312b31aa6a14d392e5
Author: Christian Grothoff <address@hidden>
AuthorDate: Mon Oct 22 16:00:06 2018 +0200

    skeleton for libtalerauditor
---
 src/auditor-lib/Makefile.am                        |  36 ++
 src/auditor-lib/auditor_api_common.c               | 328 ++++++++++++
 src/auditor-lib/auditor_api_deposit_confirmation.c | 365 +++++++++++++
 src/auditor-lib/auditor_api_handle.c               | 570 +++++++++++++++++++++
 src/auditor-lib/auditor_api_handle.h               |  71 +++
 src/auditor-lib/curl_defaults.c                    |  74 +++
 6 files changed, 1444 insertions(+)

diff --git a/src/auditor-lib/Makefile.am b/src/auditor-lib/Makefile.am
new file mode 100644
index 00000000..de239996
--- /dev/null
+++ b/src/auditor-lib/Makefile.am
@@ -0,0 +1,36 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include 
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIB = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+  libtalerauditor
+
+libtalerauditor_la_LDFLAGS = \
+  -version-info 0:0:0 \
+  -no-undefined
+libtalerauditor_la_SOURCES = \
+  curl_defaults.c \
+  auditor_api_common.c \
+  auditor_api_handle.c auditor_api_handle.h \
+  auditor_api_deposit_confirmation.c
+libtalerauditor_la_LIBADD = \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  -lgnunetcurl \
+  -lgnunetjson \
+  -lgnunetutil \
+  -ljansson \
+  $(XLIB)
+
+if HAVE_LIBCURL
+libtalerauditor_la_LIBADD += -lcurl
+else
+if HAVE_LIBGNURL
+libtalerauditor_la_LIBADD += -lgnurl
+endif
+endif
+
diff --git a/src/auditor-lib/auditor_api_common.c 
b/src/auditor-lib/auditor_api_common.c
new file mode 100644
index 00000000..de05348f
--- /dev/null
+++ b/src/auditor-lib/auditor_api_common.c
@@ -0,0 +1,328 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2015-2017 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file exchange-lib/exchange_api_common.c
+ * @brief common functions for the exchange API
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "exchange_api_handle.h"
+#include "taler_signatures.h"
+
+
+/**
+ * Verify a coins transaction history as returned by the exchange.
+ *
+ * @param currency expected currency for the coin
+ * @param coin_pub public key of the coin
+ * @param history history of the coin in json encoding
+ * @param[out] total how much of the coin has been spent according to @a 
history
+ * @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
+ */
+int
+TALER_EXCHANGE_verify_coin_history (const char *currency,
+                                   const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
+                                   json_t *history,
+                                    struct TALER_Amount *total)
+{
+  size_t len;
+  int add;
+  struct TALER_Amount rtotal;
+
+  if (NULL == history)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  len = json_array_size (history);
+  if (0 == len)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        total));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        &rtotal));
+  for (size_t off=0;off<len;off++)
+  {
+    json_t *transaction;
+    struct TALER_Amount amount;
+    const char *type;
+    struct GNUNET_JSON_Specification spec_glob[] = {
+      TALER_JSON_spec_amount ("amount",
+                              &amount),
+      GNUNET_JSON_spec_string ("type",
+                               &type),
+      GNUNET_JSON_spec_end()
+    };
+
+    transaction = json_array_get (history,
+                                  off);
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (transaction,
+                           spec_glob,
+                           NULL, NULL))
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    add = GNUNET_SYSERR;
+    if (0 == strcasecmp (type,
+                         "DEPOSIT"))
+    {
+      struct TALER_DepositRequestPS dr;
+      struct TALER_CoinSpendSignatureP sig;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_fixed_auto ("coin_sig",
+                                     &sig),
+        GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
+                                     &dr.h_contract_terms),
+        GNUNET_JSON_spec_fixed_auto ("h_wire",
+                                     &dr.h_wire),
+        GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
+                                           &dr.timestamp),
+        GNUNET_JSON_spec_absolute_time_nbo ("refund_deadline",
+                                           &dr.refund_deadline),
+        TALER_JSON_spec_amount_nbo ("deposit_fee",
+                                   &dr.deposit_fee),
+        GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+                                     &dr.merchant),
+        GNUNET_JSON_spec_end()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (transaction,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      dr.purpose.size = htonl (sizeof (dr));
+      dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
+      TALER_amount_hton (&dr.amount_with_fee,
+                        &amount);
+      dr.coin_pub = *coin_pub;
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
+                                      &dr.purpose,
+                                      &sig.eddsa_signature,
+                                      &coin_pub->eddsa_pub))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      /* TODO: check that deposit fee and coin value match
+        our expectations from /keys! */
+      add = GNUNET_YES;
+    }
+    else if (0 == strcasecmp (type,
+                              "MELT"))
+    {
+      struct TALER_RefreshMeltCoinAffirmationPS rm;
+      struct TALER_CoinSpendSignatureP sig;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_fixed_auto ("coin_sig",
+                                     &sig),
+        GNUNET_JSON_spec_fixed_auto ("rc",
+                                     &rm.rc),
+        TALER_JSON_spec_amount_nbo ("melt_fee",
+                                   &rm.melt_fee),
+        GNUNET_JSON_spec_end()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (transaction,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      rm.purpose.size = htonl (sizeof (rm));
+      rm.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
+      TALER_amount_hton (&rm.amount_with_fee,
+                        &amount);
+      rm.coin_pub = *coin_pub;
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
+                                      &rm.purpose,
+                                      &sig.eddsa_signature,
+                                      &coin_pub->eddsa_pub))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      /* TODO: check that deposit fee and coin value match
+        our expectations from /keys! */
+      add = GNUNET_YES;
+    }
+    else if (0 == strcasecmp (type,
+                              "REFUND"))
+    {
+      struct TALER_RefundRequestPS rr;
+      struct TALER_MerchantSignatureP sig;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_fixed_auto ("merchant_sig",
+                                     &sig),
+        GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
+                                     &rr.h_contract_terms),
+        GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+                                     &rr.merchant),
+        GNUNET_JSON_spec_uint64 ("rtransaction_id",
+                                &rr.rtransaction_id),
+        TALER_JSON_spec_amount_nbo ("refund_fee",
+                                   &rr.refund_fee),
+        GNUNET_JSON_spec_end()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (transaction,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      rr.purpose.size = htonl (sizeof (rr));
+      rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
+      rr.coin_pub = *coin_pub;
+      TALER_amount_hton (&rr.refund_amount,
+                        &amount);
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
+                                      &rr.purpose,
+                                      &sig.eddsa_sig,
+                                      &rr.merchant.eddsa_pub))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      /* NOTE: theoretically, we could also check that the given
+         merchant_pub and h_contract_terms appear in the
+         history under deposits.  However, there is really no benefit
+         for the exchange to lie here, so not checking is probably OK
+         (an auditor ought to check, though). Then again, we similarly
+         had no reason to check the merchant's signature (other than a
+         well-formendess check). */
+      /* TODO: check that deposit fee and coin value match
+        our expectations from /keys! */
+      add = GNUNET_NO;
+    }
+    else if (0 == strcasecmp (type,
+                              "PAYBACK"))
+    {
+      struct TALER_PaybackConfirmationPS pc;
+      struct TALER_ExchangePublicKeyP exchange_pub;
+      struct TALER_ExchangeSignatureP exchange_sig;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_fixed_auto ("exchange_sig",
+                                     &exchange_sig),
+        GNUNET_JSON_spec_fixed_auto ("exchange_pub",
+                                     &exchange_pub),
+        GNUNET_JSON_spec_fixed_auto ("reserve_pub",
+                                     &pc.reserve_pub),
+       GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
+                                           &pc.timestamp),
+        GNUNET_JSON_spec_end()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (transaction,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      pc.purpose.size = htonl (sizeof (pc));
+      pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
+      pc.coin_pub = *coin_pub;
+      TALER_amount_hton (&pc.payback_amount,
+                        &amount);
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK,
+                                      &pc.purpose,
+                                      &exchange_sig.eddsa_signature,
+                                      &exchange_pub.eddsa_pub))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      add = GNUNET_YES;
+    }
+    else
+    {
+      /* signature not supported, new version on server? */
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    if (GNUNET_YES == add)
+    {
+      /* This amount should be added to the total */
+      if (GNUNET_OK !=
+          TALER_amount_add (total,
+                            total,
+                            &amount))
+      {
+        /* overflow in history already!? inconceivable! Bad exchange! */
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+    }
+    else
+    {
+      /* This amount should be subtracted from the total.
+
+         However, for the implementation, we first *add* up all of
+         these negative amounts, as we might get refunds before
+         deposits from a semi-evil exchange.  Then, at the end, we do
+         the subtraction by calculating "total = total - rtotal" */
+      GNUNET_assert (GNUNET_NO == add);
+      if (GNUNET_OK !=
+          TALER_amount_add (&rtotal,
+                            &rtotal,
+                            &amount))
+      {
+        /* overflow in refund history? inconceivable! Bad exchange! */
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+    }
+  }
+
+  /* Finally, subtract 'rtotal' from total to handle the subtractions */
+  if (GNUNET_OK !=
+      TALER_amount_subtract (total,
+                             total,
+                             &rtotal))
+  {
+    /* underflow in history? inconceivable! Bad exchange! */
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+
+  return GNUNET_OK;
+}
+
+
+/* end of exchange_api_common.c */
diff --git a/src/auditor-lib/auditor_api_deposit_confirmation.c 
b/src/auditor-lib/auditor_api_deposit_confirmation.c
new file mode 100644
index 00000000..c5d41c45
--- /dev/null
+++ b/src/auditor-lib/auditor_api_deposit_confirmation.c
@@ -0,0 +1,365 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2018 GNUnet e.V.
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file auditor-lib/auditor_api_deposit.c
+ * @brief Implementation of the /deposit request of the auditor's HTTP API
+ * @author Sree Harsha Totakura <address@hidden>
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_json_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_json_lib.h"
+#include "taler_auditor_service.h"
+#include "auditor_api_handle.h"
+#include "taler_signatures.h"
+#include "curl_defaults.h"
+
+
+/**
+ * @brief A DepositConfirmation Handle
+ */
+struct TALER_AUDITOR_DepositConfirmationHandle
+{
+
+  /**
+   * The connection to auditor this request handle will use
+   */
+  struct TALER_AUDITOR_Handle *auditor;
+
+  /**
+   * The url for this request.
+   */
+  char *url;
+
+  /**
+   * JSON encoding of the request to POST.
+   */
+  char *json_enc;
+
+  /**
+   * Handle for the request.
+   */
+  struct GNUNET_CURL_Job *job;
+
+  /**
+   * Function to call with the result.
+   */
+  TALER_AUDITOR_DepositConfirmationResultCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /deposit-confirmation request.
+ *
+ * @param cls the `struct TALER_AUDITOR_DepositConfirmationHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param json parsed JSON result, NULL on error
+ */
+static void
+handle_deposit_confirmation_finished (void *cls,
+                                     long response_code,
+                                     const json_t *json)
+{
+  struct TALER_AUDITOR_DepositConfirmationHandle *dh = cls;
+  struct TALER_AuditorPublicKeyP auditor_pub;
+  struct TALER_AuditorPublicKeyP *ep = NULL;
+
+  dh->job = NULL;
+  switch (response_code)
+  {
+  case 0:
+    break;
+  case MHD_HTTP_OK:
+    break;
+  case MHD_HTTP_NOT_FOUND:
+    break;
+  case MHD_HTTP_BAD_REQUEST:
+    /* This should never happen, either us or the auditor is buggy
+       (or API version conflict); just pass JSON reply to the application */
+    break;
+  case MHD_HTTP_UNAUTHORIZED:
+    /* Nothing really to verify, auditor says one of the signatures is
+       invalid; as we checked them, this should never happen, we
+       should pass the JSON reply to the application */
+    break;
+  case MHD_HTTP_NOT_FOUND:
+    /* Nothing really to verify, this should never
+       happen, we should pass the JSON reply to the application */
+    break;
+  case MHD_HTTP_INTERNAL_SERVER_ERROR:
+    /* Server had an internal issue; we should retry, but this API
+       leaves this to the application */
+    break;
+  default:
+    /* unexpected response code */
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u\n",
+                (unsigned int) response_code);
+    GNUNET_break (0);
+    response_code = 0;
+    break;
+  }
+  dh->cb (dh->cb_cls,
+          response_code,
+         TALER_JSON_get_error_code (json),
+          json);
+  TALER_AUDITOR_deposit_confirmation_cancel (dh);
+}
+
+
+/**
+ * Verify signature information about the deposit-confirmation.
+ *
+ * @param dki public key information
+ * @param amount the amount to be deposit-confirmationed
+ * @param h_wire hash of the merchant’s account details
+ * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the auditor)
+ * @param coin_pub coin’s public key
+ * @param timestamp timestamp when the deposit-confirmation was finalized
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the auditor (can be zero if refunds are not allowed)
+ * @param coin_sig the signature made with purpose 
#TALER_SIGNATURE_WALLET_COIN_DEPOSIT_CONFIRMATION made by the customer with the 
coin’s private key.
+ * @return #GNUNET_OK if signatures are OK, #GNUNET_SYSERR if not
+ */
+static int
+verify_signatures (const struct TALER_Amount *amount,
+                   const struct GNUNET_HashCode *h_wire,
+                   const struct GNUNET_HashCode *h_contract_terms,
+                   const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                   struct GNUNET_TIME_Absolute timestamp,
+                   const struct TALER_MerchantPublicKeyP *merchant_pub,
+                   struct GNUNET_TIME_Absolute refund_deadline,
+                   const struct TALER_CoinSpendSignatureP *coin_sig)
+{
+  struct TALER_DepositConfirmationRequestPS dr;
+  struct TALER_CoinPublicInfo coin_info;
+
+  dr.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_DEPOSIT_CONFIRMATION);
+  dr.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationRequestPS));
+  dr.h_contract_terms = *h_contract_terms;
+  dr.h_wire = *h_wire;
+  dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
+  dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
+  TALER_amount_hton (&dr.amount_with_fee,
+                     amount);
+  TALER_amount_hton (&dr.deposit_confirmation_fee,
+                     &dki->fee_deposit_confirmation);
+  dr.merchant = *merchant_pub;
+  dr.coin_pub = *coin_pub;
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_eddsa_verify 
(TALER_SIGNATURE_WALLET_COIN_DEPOSIT_CONFIRMATION,
+                                  &dr.purpose,
+                                  &coin_sig->eddsa_signature,
+                                  &coin_pub->eddsa_pub))
+  {
+    GNUNET_break_op (0);
+    TALER_LOG_WARNING ("Invalid coin signature on /deposit-confirmation 
request!\n");
+    {
+      TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
+                       TALER_amount2s (amount));
+      TALER_LOG_DEBUG ("... deposit-confirmation_fee was %s\n",
+                       TALER_amount2s (&dki->fee_deposit_confirmation));
+    }
+
+    return GNUNET_SYSERR;
+  }
+
+  /* check coin signature */
+  coin_info.coin_pub = *coin_pub;
+  coin_info.denom_pub = *denom_pub;
+  coin_info.denom_sig = *denom_sig;
+  if (GNUNET_YES !=
+      TALER_test_coin_valid (&coin_info))
+  {
+    GNUNET_break_op (0);
+    TALER_LOG_WARNING ("Invalid coin passed for /deposit-confirmation\n");
+    return GNUNET_SYSERR;
+  }
+  if (0 < TALER_amount_cmp (&dki->fee_deposit_confirmation,
+                            amount))
+  {
+    GNUNET_break_op (0);
+    TALER_LOG_WARNING ("DepositConfirmation amount smaller than fee\n");
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Submit a deposit-confirmation permission to the auditor and get the
+ * auditor's response.  Note that while we return the response
+ * verbatim to the caller for further processing, we do already verify
+ * that the response is well-formed.  If the auditor's reply is not
+ * well-formed, we return an HTTP status code of zero to @a cb.
+ *
+ * We also verify that the @a exchange_sig is valid for this 
deposit-confirmation
+ * request, and that the @a master_sig is a valid signature for @a
+ * exchange_pub.  Also, the @a auditor must be ready to operate (i.e.  have
+ * finished processing the /version reply).  If either check fails, we do
+ * NOT initiate the transaction with the auditor and instead return NULL.
+ *
+ * @param auditor the auditor handle; the auditor must be ready to operate
+ * @param amount the amount to be deposit-confirmationed
+ * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the auditor)
+ * @param coin_pub coin’s public key
+ * @param timestamp timestamp when the contract was finalized, must not be too 
far in the future
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the auditor (can be zero if refunds are not allowed); must not 
be after the @a wire_deadline
+ * @param coin_sig the signature made with purpose 
#TALER_SIGNATURE_WALLET_COIN_DEPOSIT-CONFIRMATION made by the customer with the 
coin’s private key.
+ * @param cb the callback to call when a reply for this request is available
+ * @param cb_cls closure for the above callback
+ * @return a handle for this request; NULL if the inputs are invalid (i.e.
+ *         signatures fail to verify).  In this case, the callback is not 
called.
+ */
+struct TALER_AUDITOR_DepositConfirmationHandle *
+TALER_AUDITOR_deposit_confirmation (struct TALER_AUDITOR_Handle *auditor,
+                                   const struct GNUNET_HashCode *h_wire,
+                                   const struct TALER_Amount 
*amount_without_fees,
+                                   const struct GNUNET_HashCode 
*h_contract_terms,
+                                   const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
+                                   struct GNUNET_TIME_Absolute timestamp,
+                                   const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                   struct GNUNET_TIME_Absolute refund_deadline,
+                                   
TALER_AUDITOR_DepositConfirmationResultCallback cb,
+                                   void *cb_cls)
+{
+  struct TALER_AUDITOR_DepositConfirmationHandle *dh;
+  struct GNUNET_CURL_Context *ctx;
+  json_t *deposit_confirmation_obj;
+  CURL *eh;
+  struct TALER_Amount amount_without_fee;
+
+  (void) GNUNET_TIME_round_abs (&wire_deadline);
+  (void) GNUNET_TIME_round_abs (&refund_deadline);
+  GNUNET_assert (refund_deadline.abs_value_us <= wire_deadline.abs_value_us);
+  GNUNET_assert (GNUNET_YES ==
+                MAH_handle_is_ready (auditor));
+  if (GNUNET_OK !=
+      verify_signatures (amount,
+                         &h_wire,
+                         h_contract_terms,
+                         coin_pub,
+                         timestamp,
+                         merchant_pub,
+                         refund_deadline,
+                         coin_sig))
+  {
+    GNUNET_break_op (0);
+    return NULL;
+  }
+
+  deposit_confirmation_obj
+    = json_pack ("{s:o, s:o," /* f/wire */
+                " s:o, s:o," /* H_wire, h_contract_terms */
+                " s:o, s:o," /* coin_pub, denom_pub */
+                " s:o, s:o," /* ub_sig, timestamp */
+                " s:o," /* merchant_pub */
+                " s:o, s:o," /* refund_deadline, wire_deadline */
+                " s:o}",     /* coin_sig */
+                "contribution", TALER_JSON_from_amount (amount),
+                "H_wire", GNUNET_JSON_from_data_auto (&h_wire),
+                "h_contract_terms", GNUNET_JSON_from_data_auto 
(h_contract_terms),
+                "coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
+                "timestamp", GNUNET_JSON_from_time_abs (timestamp),
+                "merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub),
+                "refund_deadline", GNUNET_JSON_from_time_abs (refund_deadline),
+                "wire_transfer_deadline", GNUNET_JSON_from_time_abs 
(wire_deadline),
+                "coin_sig", GNUNET_JSON_from_data_auto (coin_sig)
+                );
+  if (NULL == deposit_confirmation_obj)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  dh = GNUNET_new (struct TALER_AUDITOR_DepositConfirmationHandle);
+  dh->auditor = auditor;
+  dh->cb = cb;
+  dh->cb_cls = cb_cls;
+  dh->url = MAH_path_to_url (auditor, "/deposit-confirmation");
+  dh->depconf.purpose.size = htonl (sizeof (struct 
TALER_DepositConfirmationConfirmationPS));
+  dh->depconf.purpose.purpose = htonl 
(TALER_SIGNATURE_EXCHANGE_DEPOSIT_CONFIRMATION);
+  dh->depconf.h_contract_terms = *h_contract_terms;
+  dh->depconf.h_wire = h_wire;
+  dh->depconf.timestamp = GNUNET_TIME_absolute_hton (timestamp);
+  dh->depconf.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
+  TALER_amount_hton (&dh->depconf.amount_without_fee,
+                     &amount_without_fee);
+  dh->depconf.coin_pub = *coin_pub;
+  dh->depconf.merchant = *merchant_pub;
+  dh->amount_with_fee = *amount;
+  dh->coin_value = dki->value;
+
+  eh = TEL_curl_easy_get (dh->url);
+  GNUNET_assert (NULL != (dh->json_enc =
+                          json_dumps (deposit_confirmation_obj,
+                                      JSON_COMPACT)));
+  json_decref (deposit_confirmation_obj);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "URL for deposit-confirmation: `%s'\n",
+              dh->url);
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_POSTFIELDS,
+                                   dh->json_enc));
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_POSTFIELDSIZE,
+                                   strlen (dh->json_enc)));
+  ctx = MAH_handle_to_context (auditor);
+  dh->job = GNUNET_CURL_job_add (ctx,
+                                eh,
+                                GNUNET_YES,
+                                (GC_JCC) &handle_deposit_confirmation_finished,
+                                dh);
+  return dh;
+}
+
+
+/**
+ * Cancel a deposit-confirmation permission request.  This function cannot be 
used
+ * on a request handle if a response is already served for it.
+ *
+ * @param deposit-confirmation the deposit-confirmation permission request 
handle
+ */
+void
+TALER_AUDITOR_deposit_confirmation_cancel (struct 
TALER_AUDITOR_DepositConfirmationHandle *deposit_confirmation)
+{
+  if (NULL != deposit_confirmation->job)
+  {
+    GNUNET_CURL_job_cancel (deposit_confirmation->job);
+    deposit_confirmation->job = NULL;
+  }
+  GNUNET_free (deposit_confirmation->url);
+  GNUNET_free (deposit_confirmation->json_enc);
+  GNUNET_free (deposit_confirmation);
+}
+
+
+/* end of auditor_api_deposit_confirmation.c */
diff --git a/src/auditor-lib/auditor_api_handle.c 
b/src/auditor-lib/auditor_api_handle.c
new file mode 100644
index 00000000..4db528a3
--- /dev/null
+++ b/src/auditor-lib/auditor_api_handle.c
@@ -0,0 +1,570 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2018 GNUnet e.V.
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file auditor-lib/auditor_api_handle.c
+ * @brief Implementation of the "handle" component of the auditor's HTTP API
+ * @author Sree Harsha Totakura <address@hidden>
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <microhttpd.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_json_lib.h"
+#include "taler_auditor_service.h"
+#include "taler_signatures.h"
+#include "auditor_api_handle.h"
+#include "curl_defaults.h"
+#include "backoff.h"
+
+/**
+ * Which revision of the Taler auditor protocol is implemented
+ * by this library?  Used to determine compatibility.
+ */
+#define TALER_PROTOCOL_CURRENT 0
+
+/**
+ * How many revisions back are we compatible to?
+ */
+#define TALER_PROTOCOL_AGE 0
+
+
+/**
+ * Log error related to CURL operations.
+ *
+ * @param type log level
+ * @param function which function failed to run
+ * @param code what was the curl error code
+ */
+#define CURL_STRERROR(type, function, code)      \
+ GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
+             function, __FILE__, __LINE__, curl_easy_strerror (code));
+
+/**
+ * Stages of initialization for the `struct TALER_AUDITOR_Handle`
+ */
+enum AuditorHandleState
+{
+  /**
+   * Just allocated.
+   */
+  MHS_INIT = 0,
+
+  /**
+   * Obtained the auditor's versioning data and version.
+   */
+  MHS_VERSION = 1,
+
+  /**
+   * Failed to initialize (fatal).
+   */
+  MHS_FAILED = 2
+};
+
+
+/**
+ * Data for the request to get the /version of a auditor.
+ */
+struct VersionRequest;
+
+
+/**
+ * Handle to the auditor
+ */
+struct TALER_AUDITOR_Handle
+{
+  /**
+   * The context of this handle
+   */
+  struct GNUNET_CURL_Context *ctx;
+
+  /**
+   * The URL of the auditor (i.e. "http://auditor.taler.net/";)
+   */
+  char *url;
+
+  /**
+   * Function to call with the auditor's certification data,
+   * NULL if this has already been done.
+   */
+  TALER_AUDITOR_VersionCallback version_cb;
+
+  /**
+   * Closure to pass to @e version_cb.
+   */
+  void *version_cb_cls;
+
+  /**
+   * Data for the request to get the /version of a auditor,
+   * NULL once we are past stage #MHS_INIT.
+   */
+  struct VersionRequest *kr;
+
+  /**
+   * Task for retrying /version request.
+   */
+  struct GNUNET_SCHEDULER_Task *retry_task;
+
+  /**
+   * Key data of the auditor, only valid if
+   * @e handshake_complete is past stage #MHS_VERSION.
+   */
+  struct TALER_AUDITOR_Version key_data;
+
+  /**
+   * Retry /version frequency.
+   */
+  struct GNUNET_TIME_Relative retry_delay;
+
+  /**
+   * Stage of the auditor's initialization routines.
+   */
+  enum AuditorHandleState state;
+
+};
+
+
+/* ***************** Internal /version fetching ************* */
+
+/**
+ * Data for the request to get the /version of a auditor.
+ */
+struct VersionRequest
+{
+  /**
+   * The connection to auditor this request handle will use
+   */
+  struct TALER_AUDITOR_Handle *auditor;
+
+  /**
+   * The url for this handle
+   */
+  char *url;
+
+  /**
+   * Entry for this request with the `struct GNUNET_CURL_Context`.
+   */
+  struct GNUNET_CURL_Job *job;
+
+};
+
+
+/**
+ * Release memory occupied by a version request.
+ * Note that this does not cancel the request
+ * itself.
+ *
+ * @param kr request to free
+ */
+static void
+free_version_request (struct VersionRequest *kr)
+{
+  GNUNET_free (kr->url);
+  GNUNET_free (kr);
+}
+
+
+/**
+ * Parse a auditor's auditor information encoded in JSON.
+ *
+ * @param[out] auditor where to return the result
+ * @param check_sig should we check signatures
+ * @param[in] auditor_obj json to parse
+ * @param key_data information about denomination version
+ * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
+ *        invalid or the json malformed.
+ */
+static int
+parse_json_auditor (struct TALER_AUDITOR_AuditorInformation *auditor,
+                   int check_sigs,
+                    json_t *auditor_obj,
+                    const struct TALER_AUDITOR_Version *key_data)
+{
+  const char *auditor_url;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_fixed_auto ("auditor_pub",
+                                 &auditor->auditor_pub),
+    GNUNET_JSON_spec_string ("auditor_url",
+                             &auditor_url),
+    GNUNET_JSON_spec_json ("denomination_version",
+                           &version),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (auditor_obj,
+                         spec,
+                         NULL, NULL))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  auditor->auditor_url = GNUNET_strdup (auditor_url);
+  GNUNET_JSON_parse_free (spec);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Decode the JSON in @a resp_obj from the /version response and store the data
+ * in the @a key_data.
+ *
+ * @param[in] resp_obj JSON object to parse
+ * @param check_sig #GNUNET_YES if we should check the signature
+ * @param[out] key_data where to store the results we decoded
+ * @param[out] where to store version compatibility data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (malformed JSON)
+ */
+static int
+decode_version_json (const json_t *resp_obj,
+                 int check_sig,
+                  struct TALER_AUDITOR_Version *key_data,
+                 enum TALER_AUDITOR_VersionCompatibility *vc)
+{
+  struct TALER_AuditorPublicKeyP pub;
+  unsigned int age;
+  unsigned int revision;
+  unsigned int current;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("version",
+                            &ver),
+    GNUNET_JSON_spec_fixed_auto ("master_public_key",
+                                &key_data->master_pub),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (JSON_OBJECT != json_typeof (resp_obj))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  /* check the version */
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (resp_obj,
+                        spec,
+                        NULL, NULL))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (3 != sscanf (ver,
+                  "%u:%u:%u",
+                  &current,
+                  &revision,
+                  &age))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  *vc = TALER_AUDITOR_VC_MATCH;
+  if (TALER_PROTOCOL_CURRENT < current)
+  {
+    *vc |= TALER_AUDITOR_VC_NEWER;
+    if (TALER_PROTOCOL_CURRENT < current - age)
+      *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
+  }
+  if (TALER_PROTOCOL_CURRENT > current)
+  {
+    *vc |= TALER_AUDITOR_VC_OLDER;
+    if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
+      *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
+  }
+  key_data->version = GNUNET_strdup (ver);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Free key data object.
+ *
+ * @param key_data data to free (pointer itself excluded)
+ */
+static void
+free_key_data (struct TALER_AUDITOR_Keys *key_data)
+{
+  GNUNET_free_non_null (key_data->version);
+  key_data->version = NULL;
+}
+
+
+/**
+ * Initiate download of /version from the auditor.
+ *
+ * @param cls auditor where to download /version from
+ */
+static void
+request_version (void *cls);
+
+
+/**
+ * Callback used when downloading the reply to a /version request
+ * is complete.
+ *
+ * @param cls the `struct VersionRequest`
+ * @param response_code HTTP response code, 0 on error
+ * @param resp_obj parsed JSON result, NULL on error
+ */
+static void
+version_completed_cb (void *cls,
+                     long response_code,
+                     const json_t *resp_obj)
+{
+  struct VersionRequest *kr = cls;
+  struct TALER_AUDITOR_Handle *auditor = kr->auditor;
+  enum TALER_AUDITOR_VersionCompatibility vc;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Received version from URL `%s' with status %ld.\n",
+              kr->url,
+              response_code);
+  vc = TALER_AUDITOR_VC_PROTOCOL_ERROR;
+  switch (response_code)
+  {
+  case 0:
+    free_version_request (kr);
+    auditor->kr = NULL;
+    GNUNET_assert (NULL == auditor->retry_task);
+    auditor->retry_delay = AUDITOR_LIB_BACKOFF (auditor->retry_delay);
+    auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay,
+                                                         &request_version,
+                                                         auditor);
+    return;
+  case MHD_HTTP_OK:
+    if (NULL == resp_obj)
+    {
+      response_code = 0;
+      break;
+    }
+    /* We keep the denomination version and auditor signatures from the
+       previous iteration (/version cherry picking) */
+    if (GNUNET_OK !=
+        decode_version_json (resp_obj,
+                         GNUNET_YES,
+                          &kd,
+                         &vc))
+    {
+      response_code = 0;
+      break;
+    }
+    auditor->retry_delay = GNUNET_TIME_UNIT_ZERO;
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u\n",
+                (unsigned int) response_code);
+    break;
+  }
+  auditor->key_data = kd;
+
+  if (MHD_HTTP_OK != response_code)
+  {
+    auditor->kr = NULL;
+    free_version_request (kr);
+    auditor->state = MHS_FAILED;
+    free_key_data (&kd_old);
+    /* notify application that we failed */
+    auditor->version_cb (auditor->version_cb_cls,
+                        NULL,
+                        vc);
+    return;
+  }
+
+  auditor->kr = NULL;
+  free_version_request (kr);
+  auditor->state = MHS_VERSION;
+  /* notify application about the key information */
+  auditor->version_cb (auditor->version_cb_cls,
+                     &auditor->key_data,
+                    vc);
+  free_key_data (&kd_old);
+}
+
+
+/* ********************* library internal API ********* */
+
+
+/**
+ * Get the context of a auditor.
+ *
+ * @param h the auditor handle to query
+ * @return ctx context to execute jobs in
+ */
+struct GNUNET_CURL_Context *
+MAH_handle_to_context (struct TALER_AUDITOR_Handle *h)
+{
+  return h->ctx;
+}
+
+
+/**
+ * Check if the handle is ready to process requests.
+ *
+ * @param h the auditor handle to query
+ * @return #GNUNET_YES if we are ready, #GNUNET_NO if not
+ */
+int
+MAH_handle_is_ready (struct TALER_AUDITOR_Handle *h)
+{
+  return (MHS_VERSION == h->state) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Obtain the URL to use for an API request.
+ *
+ * @param h handle for the auditor
+ * @param path Taler API path (i.e. "/reserve/withdraw")
+ * @return the full URL to use with cURL
+ */
+char *
+MAH_path_to_url (struct TALER_AUDITOR_Handle *h,
+                 const char *path)
+{
+  return MAH_path_to_url2 (h->url,
+                           path);
+}
+
+
+/**
+ * Obtain the URL to use for an API request.
+ *
+ * @param base_url base URL of the auditor (i.e. "http://auditor/";)
+ * @param path Taler API path (i.e. "/reserve/withdraw")
+ * @return the full URL to use with cURL
+ */
+char *
+MAH_path_to_url2 (const char *base_url,
+                  const char *path)
+{
+  char *url;
+
+  if ( ('/' == path[0]) &&
+       (0 < strlen (base_url)) &&
+       ('/' == base_url[strlen (base_url) - 1]) )
+    path++; /* avoid generating URL with "//" from concat */
+  GNUNET_asprintf (&url,
+                   "%s%s",
+                   base_url,
+                   path);
+  return url;
+}
+
+
+/* ********************* public API ******************* */
+
+
+/**
+ * Initialise a connection to the auditor. Will connect to the
+ * auditor and obtain information about the auditor's master public
+ * key and the auditor's auditor.  The respective information will
+ * be passed to the @a version_cb once available, and all future
+ * interactions with the auditor will be checked to be signed
+ * (where appropriate) by the respective master key.
+ *
+ * @param ctx the context
+ * @param url HTTP base URL for the auditor
+ * @param version_cb function to call with the auditor's versionification 
information
+ * @param version_cb_cls closure for @a version_cb
+ * @return the auditor handle; NULL upon error
+ */
+struct TALER_AUDITOR_Handle *
+TALER_AUDITOR_connect (struct GNUNET_CURL_Context *ctx,
+                      const char *url,
+                      TALER_AUDITOR_VersionificationCallback version_cb,
+                      void *version_cb_cls)
+{
+  struct TALER_AUDITOR_Handle *auditor;
+
+  auditor = GNUNET_new (struct TALER_AUDITOR_Handle);
+  auditor->ctx = ctx;
+  auditor->url = GNUNET_strdup (url);
+  auditor->version_cb = version_cb;
+  auditor->version_cb_cls = version_cb_cls;
+  auditor->retry_task = GNUNET_SCHEDULER_add_now (&request_version,
+                                                 auditor);
+  return auditor;
+}
+
+
+/**
+ * Initiate download of /version from the auditor.
+ *
+ * @param cls auditor where to download /version from
+ */
+static void
+request_version (void *cls)
+{
+  struct TALER_AUDITOR_Handle *auditor = cls;
+  struct VersionRequest *kr;
+  CURL *eh;
+
+  auditor->retry_task = NULL;
+  GNUNET_assert (NULL == auditor->kr);
+  kr = GNUNET_new (struct VersionRequest);
+  kr->auditor = auditor;
+  kr->url = MAH_path_to_url (auditor,
+                            "/version");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Requesting version with URL `%s'.\n",
+              kr->url);
+  eh = TEL_curl_easy_get (kr->url);
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_VERBOSE,
+                                   0));
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_TIMEOUT,
+                                   (long) 300));
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_HEADERDATA,
+                                   kr));
+  kr->job = GNUNET_CURL_job_add (auditor->ctx,
+                                 eh,
+                                 GNUNET_NO,
+                                 (GC_JCC) &version_completed_cb,
+                                 kr);
+  auditor->kr = kr;
+}
+
+
+/**
+ * Disconnect from the auditor
+ *
+ * @param auditor the auditor handle
+ */
+void
+TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor)
+{
+  if (NULL != auditor->kr)
+  {
+    GNUNET_CURL_job_cancel (auditor->kr->job);
+    free_version_request (auditor->kr);
+    auditor->kr = NULL;
+  }
+  free_key_data (&auditor->key_data);
+  if (NULL != auditor->retry_task)
+  {
+    GNUNET_SCHEDULER_cancel (auditor->retry_task);
+    auditor->retry_task = NULL;
+  }
+  GNUNET_free (auditor->url);
+  GNUNET_free (auditor);
+}
+
+
+/* end of auditor_api_handle.c */
diff --git a/src/auditor-lib/auditor_api_handle.h 
b/src/auditor-lib/auditor_api_handle.h
new file mode 100644
index 00000000..6d7f4cf8
--- /dev/null
+++ b/src/auditor-lib/auditor_api_handle.h
@@ -0,0 +1,71 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014, 2015 GNUnet e.V.
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file auditor-lib/auditor_api_handle.h
+ * @brief Internal interface to the handle part of the auditor's HTTP API
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_auditor_service.h"
+
+
+/**
+ * Get the context of a auditor.
+ *
+ * @param h the auditor handle to query
+ * @return ctx context to execute jobs in
+ */
+struct GNUNET_CURL_Context *
+MAH_handle_to_context (struct TALER_AUDITOR_Handle *h);
+
+
+/**
+ * Check if the handle is ready to process requests.
+ *
+ * @param h the auditor handle to query
+ * @return #GNUNET_YES if we are ready, #GNUNET_NO if not
+ */
+int
+MAH_handle_is_ready (struct TALER_AUDITOR_Handle *h);
+
+
+/**
+ * Obtain the URL to use for an API request.
+ *
+ * @param h the auditor handle to query
+ * @param path Taler API path (i.e. "/reserve/withdraw")
+ * @return the full URL to use with cURL
+ */
+char *
+MAH_path_to_url (struct TALER_AUDITOR_Handle *h,
+                 const char *path);
+
+
+/**
+ * Obtain the URL to use for an API request.
+ *
+ * @param base_url base URL of the auditor (i.e. "http://auditor/";)
+ * @param path Taler API path (i.e. "/reserve/withdraw")
+ * @return the full URL to use with cURL
+ */
+char *
+MAH_path_to_url2 (const char *base_url,
+                  const char *path);
+
+
+/* end of auditor_api_handle.h */
diff --git a/src/auditor-lib/curl_defaults.c b/src/auditor-lib/curl_defaults.c
new file mode 100644
index 00000000..8117fc44
--- /dev/null
+++ b/src/auditor-lib/curl_defaults.c
@@ -0,0 +1,74 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2018 GNUnet e.V.
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file auditor-lib/curl_defaults.c
+ * @brief curl easy handle defaults
+ * @author Florian Dold
+ */
+
+#include "curl_defaults.h"
+
+
+/**
+ * Get a curl handle with the right defaults
+ * for the exchange lib.  In the future, we might manage a pool of connections 
here.
+ *
+ * @param url URL to query
+ */
+CURL *
+TEL_curl_easy_get (char *url)
+{
+  CURL *eh;
+  
+  eh = curl_easy_init ();
+
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_URL,
+                                   url));
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_ENCODING,
+                                   "deflate"));
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_TCP_FASTOPEN,
+                                   1L));
+
+  {
+    /* Unfortunately libcurl needs chunk to be alive until after
+    curl_easy_perform.  To avoid manual cleanup, we keep
+    one static list here.  */
+    static struct curl_slist *chunk = NULL;
+    if (NULL == chunk)
+    {
+      /* With POST requests, we do not want to wait for the
+      "100 Continue" response, as our request bodies are usually
+      small and directy sending them saves us a round trip.
+
+      Clearing the expect header like this disables libcurl's
+      default processing of the header.
+
+      Disabling this header is safe for other HTTP methods, thus
+      we don't distinguish further before setting it.  */
+      chunk = curl_slist_append (chunk, "Expect:");
+    }
+    GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_HTTPHEADER, 
chunk));
+  }
+
+  return eh;
+}

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



reply via email to

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