summaryrefslogtreecommitdiff
path: root/src/wire
diff options
context:
space:
mode:
Diffstat (limited to 'src/wire')
-rw-r--r--src/wire/Makefile.am103
-rw-r--r--src/wire/plugin_wire_sepa.c960
-rw-r--r--src/wire/plugin_wire_template.c346
-rw-r--r--src/wire/plugin_wire_test.c1302
-rw-r--r--src/wire/test_sepa_wireformat.c120
-rw-r--r--src/wire/test_wire_plugin.c269
-rw-r--r--src/wire/test_wire_plugin.conf21
-rw-r--r--src/wire/test_wire_plugin_key.priv1
-rw-r--r--src/wire/test_wire_plugin_sepa.json8
-rw-r--r--src/wire/test_wire_plugin_test.json7
-rw-r--r--src/wire/test_wire_plugin_transactions_test.c356
-rw-r--r--src/wire/test_wire_plugin_transactions_test.conf15
-rw-r--r--src/wire/wire-sepa.conf15
-rw-r--r--src/wire/wire-test.conf22
-rw-r--r--src/wire/wire.c76
-rw-r--r--src/wire/wire_helper.c57
16 files changed, 59 insertions, 3619 deletions
diff --git a/src/wire/Makefile.am b/src/wire/Makefile.am
index 5f651461e..9fcf877f9 100644
--- a/src/wire/Makefile.am
+++ b/src/wire/Makefile.am
@@ -8,114 +8,15 @@ endif
pkgcfgdir = $(prefix)/share/taler/config.d/
-pkgcfg_DATA = \
- wire-sepa.conf \
- wire-test.conf
-
-
-EXTRA_DIST = \
- wire-sepa.conf \
- wire-test.conf \
- test_wire_plugin.conf \
- test_wire_plugin_transactions_test.conf \
- test_wire_plugin_key.priv \
- test_wire_plugin_test.json \
- test_wire_plugin_sepa.json
-
-plugindir = $(libdir)/taler
-
-plugin_LTLIBRARIES = \
- libtaler_plugin_wire_sepa.la \
- libtaler_plugin_wire_test.la
-
-noinst_LTLIBRARIES = \
- libtaler_plugin_wire_template.la
-
lib_LTLIBRARIES = \
libtalerwire.la
-
-libtaler_plugin_wire_test_la_SOURCES = \
- plugin_wire_test.c
-libtaler_plugin_wire_test_la_LIBADD = \
- $(LTLIBINTL)
-libtaler_plugin_wire_test_la_LDFLAGS = \
- $(TALER_PLUGIN_LDFLAGS) \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetcurl \
- -lgnunetutil $(XLIB)
-
-
-libtaler_plugin_wire_sepa_la_SOURCES = \
- plugin_wire_sepa.c
-libtaler_plugin_wire_sepa_la_LIBADD = \
- $(LTLIBINTL)
-libtaler_plugin_wire_sepa_la_LDFLAGS = \
- $(TALER_PLUGIN_LDFLAGS) \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetjson \
- -lgnunetutil $(XLIB)
-
-
-libtaler_plugin_wire_template_la_SOURCES = \
- plugin_wire_template.c
-libtaler_plugin_wire_template_la_LIBADD = \
- $(LTLIBINTL)
-libtaler_plugin_wire_template_la_LDFLAGS = \
- $(TALER_PLUGIN_LDFLAGS) \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetutil $(XLIB)
-
-
libtalerwire_la_SOURCES = \
- wire.c
+ wire.c \
+ wire_helper.c
libtalerwire_la_LIBADD = \
-lgnunetutil \
$(XLIB)
libtalerwire_la_LDFLAGS = \
-version-info 1:0:0 \
-export-dynamic -no-undefined
-
-
-AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
-
-TESTS = \
- test_sepa_wireformat \
- test_wire_plugin
-
-check_PROGRAMS= \
- test_sepa_wireformat \
- test_wire_plugin \
- test_wire_plugin_transactions_test
-
-
-test_sepa_wireformat_SOURCES = \
- test_sepa_wireformat.c
-test_sepa_wireformat_LDADD = \
- -lgnunetutil \
- -ljansson \
- libtalerwire.la \
- $(top_builddir)/src/util/libtalerutil.la
-
-
-test_wire_plugin_SOURCES = \
- test_wire_plugin.c
-test_wire_plugin_LDADD = \
- -lgnunetjson \
- -lgnunetutil \
- -ljansson \
- libtalerwire.la \
- $(top_builddir)/src/util/libtalerutil.la
-
-
-test_wire_plugin_transactions_test_SOURCES = \
- test_wire_plugin_transactions_test.c
-test_wire_plugin_transactions_test_LDADD = \
- -lgnunetjson \
- -lgnunetutil \
- -ljansson \
- libtalerwire.la \
- $(top_builddir)/src/bank-lib/libtalerfakebank.la \
- $(top_builddir)/src/util/libtalerutil.la
diff --git a/src/wire/plugin_wire_sepa.c b/src/wire/plugin_wire_sepa.c
deleted file mode 100644
index 416acac7c..000000000
--- a/src/wire/plugin_wire_sepa.c
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2016, 2017 GNUnet e.V. & Inria
-
- 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 plugin_wire_sepa.c
- * @brief wire plugin for transfers using SEPA/EBICS
- * @author Florian Dold
- * @author Christian Grothoff
- * @author Sree Harsha Totakura
- */
-#include "platform.h"
-#include "taler_wire_plugin.h"
-#include "taler_signatures.h"
-#include <gnunet/gnunet_json_lib.h>
-
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct SepaClosure
-{
-
- /**
- * Which currency do we support?
- */
- char *currency;
-
-};
-
-
-/**
- * Round amount DOWN to the amount that can be transferred via the wire
- * method. For example, Taler may support 0.000001 EUR as a unit of
- * payment, but SEPA only supports 0.01 EUR. This function would
- * round 0.125 EUR to 0.12 EUR in this case.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param[in,out] amount amount to round down
- * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
- * #GNUNET_SYSERR if the amount or currency was invalid
- */
-static int
-sepa_amount_round (void *cls,
- struct TALER_Amount *amount)
-{
- struct SepaClosure *sc = cls;
- uint32_t delta;
-
- if (NULL == sc->currency)
- return GNUNET_SYSERR;
- if (0 != strcasecmp (amount->currency,
- sc->currency))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / 100);
- if (0 == delta)
- return GNUNET_NO;
- amount->fraction -= delta;
- return GNUNET_OK;
-}
-
-
-/* Taken from GNU gettext */
-
-/**
- * Entry in the country table.
- */
-struct table_entry
-{
- /**
- * 2-Character international country code.
- */
- const char *code;
-
- /**
- * Long English name of the country.
- */
- const char *english;
-};
-
-
-/* Keep the following table in sync with gettext.
- WARNING: the entries should stay sorted according to the code */
-/**
- * List of country codes.
- */
-static const struct table_entry country_table[] =
- {
- { "AE", "U.A.E." },
- { "AF", "Afghanistan" },
- { "AL", "Albania" },
- { "AM", "Armenia" },
- { "AN", "Netherlands Antilles" },
- { "AR", "Argentina" },
- { "AT", "Austria" },
- { "AU", "Australia" },
- { "AZ", "Azerbaijan" },
- { "BA", "Bosnia and Herzegovina" },
- { "BD", "Bangladesh" },
- { "BE", "Belgium" },
- { "BG", "Bulgaria" },
- { "BH", "Bahrain" },
- { "BN", "Brunei Darussalam" },
- { "BO", "Bolivia" },
- { "BR", "Brazil" },
- { "BT", "Bhutan" },
- { "BY", "Belarus" },
- { "BZ", "Belize" },
- { "CA", "Canada" },
- { "CG", "Congo" },
- { "CH", "Switzerland" },
- { "CI", "Cote d'Ivoire" },
- { "CL", "Chile" },
- { "CM", "Cameroon" },
- { "CN", "People's Republic of China" },
- { "CO", "Colombia" },
- { "CR", "Costa Rica" },
- { "CS", "Serbia and Montenegro" },
- { "CZ", "Czech Republic" },
- { "DE", "Germany" },
- { "DK", "Denmark" },
- { "DO", "Dominican Republic" },
- { "DZ", "Algeria" },
- { "EC", "Ecuador" },
- { "EE", "Estonia" },
- { "EG", "Egypt" },
- { "ER", "Eritrea" },
- { "ES", "Spain" },
- { "ET", "Ethiopia" },
- { "FI", "Finland" },
- { "FO", "Faroe Islands" },
- { "FR", "France" },
- { "GB", "United Kingdom" },
- { "GD", "Caribbean" },
- { "GE", "Georgia" },
- { "GL", "Greenland" },
- { "GR", "Greece" },
- { "GT", "Guatemala" },
- { "HK", "Hong Kong" },
- { "HK", "Hong Kong S.A.R." },
- { "HN", "Honduras" },
- { "HR", "Croatia" },
- { "HT", "Haiti" },
- { "HU", "Hungary" },
- { "ID", "Indonesia" },
- { "IE", "Ireland" },
- { "IL", "Israel" },
- { "IN", "India" },
- { "IQ", "Iraq" },
- { "IR", "Iran" },
- { "IS", "Iceland" },
- { "IT", "Italy" },
- { "JM", "Jamaica" },
- { "JO", "Jordan" },
- { "JP", "Japan" },
- { "KE", "Kenya" },
- { "KG", "Kyrgyzstan" },
- { "KH", "Cambodia" },
- { "KR", "South Korea" },
- { "KW", "Kuwait" },
- { "KZ", "Kazakhstan" },
- { "LA", "Laos" },
- { "LB", "Lebanon" },
- { "LI", "Liechtenstein" },
- { "LK", "Sri Lanka" },
- { "LT", "Lithuania" },
- { "LU", "Luxembourg" },
- { "LV", "Latvia" },
- { "LY", "Libya" },
- { "MA", "Morocco" },
- { "MC", "Principality of Monaco" },
- { "MD", "Moldava" },
- { "MD", "Moldova" },
- { "ME", "Montenegro" },
- { "MK", "Former Yugoslav Republic of Macedonia" },
- { "ML", "Mali" },
- { "MM", "Myanmar" },
- { "MN", "Mongolia" },
- { "MO", "Macau S.A.R." },
- { "MT", "Malta" },
- { "MV", "Maldives" },
- { "MX", "Mexico" },
- { "MY", "Malaysia" },
- { "NG", "Nigeria" },
- { "NI", "Nicaragua" },
- { "NL", "Netherlands" },
- { "NO", "Norway" },
- { "NP", "Nepal" },
- { "NZ", "New Zealand" },
- { "OM", "Oman" },
- { "PA", "Panama" },
- { "PE", "Peru" },
- { "PH", "Philippines" },
- { "PK", "Islamic Republic of Pakistan" },
- { "PL", "Poland" },
- { "PR", "Puerto Rico" },
- { "PT", "Portugal" },
- { "PY", "Paraguay" },
- { "QA", "Qatar" },
- { "RE", "Reunion" },
- { "RO", "Romania" },
- { "RS", "Serbia" },
- { "RU", "Russia" },
- { "RW", "Rwanda" },
- { "SA", "Saudi Arabia" },
- { "SE", "Sweden" },
- { "SG", "Singapore" },
- { "SI", "Slovenia" },
- { "SK", "Slovak" },
- { "SN", "Senegal" },
- { "SO", "Somalia" },
- { "SR", "Suriname" },
- { "SV", "El Salvador" },
- { "SY", "Syria" },
- { "TH", "Thailand" },
- { "TJ", "Tajikistan" },
- { "TM", "Turkmenistan" },
- { "TN", "Tunisia" },
- { "TR", "Turkey" },
- { "TT", "Trinidad and Tobago" },
- { "TW", "Taiwan" },
- { "TZ", "Tanzania" },
- { "UA", "Ukraine" },
- { "US", "United States" },
- { "UY", "Uruguay" },
- { "VA", "Vatican" },
- { "VE", "Venezuela" },
- { "VN", "Viet Nam" },
- { "YE", "Yemen" },
- { "ZA", "South Africa" },
- { "ZW", "Zimbabwe" }
- };
-
-
-/**
- * Country code comparator function, for binary search with bsearch().
- *
- * @param ptr1 pointer to a `struct table_entry`
- * @param ptr2 pointer to a `struct table_entry`
- * @return result of strncmp()'ing the 2-digit country codes of the entries
- */
-static int
-cmp_country_code (const void *ptr1,
- const void *ptr2)
-{
- const struct table_entry *cc1 = ptr1;
- const struct table_entry *cc2 = ptr2;
-
- return strncmp (cc1->code,
- cc2->code,
- 2);
-}
-
-
-/**
- * Validates given IBAN according to the European Banking Standards. See:
- * http://www.europeanpaymentscouncil.eu/documents/ECBS%20IBAN%20standard%20EBS204_V3.2.pdf
- *
- * @param iban the IBAN number to validate
- * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
- */
-static int
-validate_iban (const char *iban)
-{
- char cc[2];
- char ibancpy[35];
- struct table_entry cc_entry;
- unsigned int len;
- char *nbuf;
- unsigned int i;
- unsigned int j;
- unsigned long long dividend;
- unsigned long long remainder;
- int nread;
- int ret;
-
- len = strlen (iban);
- if (len > 34)
- {
- GNUNET_break_op (0);
- return GNUNET_NO;
- }
- strncpy (cc, iban, 2);
- strncpy (ibancpy, iban + 4, len - 4);
- strncpy (ibancpy + len - 4, iban, 4);
- ibancpy[len] = '\0';
- cc_entry.code = cc;
- cc_entry.english = NULL;
- if (NULL ==
- bsearch (&cc_entry,
- country_table,
- sizeof (country_table) / sizeof (struct table_entry),
- sizeof (struct table_entry),
- &cmp_country_code))
- {
- GNUNET_break_op (0);
- return GNUNET_NO;
- }
- nbuf = GNUNET_malloc ((len * 2) + 1);
- for (i=0, j=0; i < len; i++)
- {
- if (isalpha ((unsigned char) ibancpy[i]))
- {
- if (2 != snprintf(&nbuf[j],
- 3,
- "%2u",
- (ibancpy[i] - 'A' + 10)))
- {
- GNUNET_free (nbuf);
- return GNUNET_NO;
- }
- j += 2;
- continue;
- }
- nbuf[j] = ibancpy[i];
- j++;
- }
- for (j=0;'\0' != nbuf[j];j++)
- GNUNET_assert (isdigit( (unsigned char) nbuf[j]));
- GNUNET_assert (sizeof(dividend) >= 8);
- remainder = 0;
- for (i=0; i<j; i+=16)
- {
- if (1 !=
- (ret = sscanf (&nbuf[i],
- "%16llu %n",
- &dividend,
- &nread)))
- {
- GNUNET_free (nbuf);
- GNUNET_break_op (0);
- return GNUNET_NO;
- }
- if (0 != remainder)
- dividend += remainder * (pow (10, nread));
- remainder = dividend % 97;
- }
- GNUNET_free (nbuf);
- if (1 == remainder)
- return GNUNET_YES;
- GNUNET_break_op (0); /* checksum wrong */
- return GNUNET_NO;
-}
-
-
-/**
- * Compute purpose for signing.
- *
- * @param sepa_name name of the account holder
- * @param iban bank account number in IBAN format
- * @param bic bank identifier
- * @param[out] wsd purpose to be signed
- */
-static void
-compute_purpose (const char *sepa_name,
- const char *iban,
- const char *bic,
- struct TALER_MasterWireDetailsPS *wsd)
-{
- struct GNUNET_HashContext *hc;
-
- wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
- wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
- hc = GNUNET_CRYPTO_hash_context_start ();
- GNUNET_CRYPTO_hash_context_read (hc,
- "sepa",
- strlen ("sepa") + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- sepa_name,
- strlen (sepa_name) + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- iban,
- strlen (iban) + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- bic,
- strlen (bic) + 1);
- GNUNET_CRYPTO_hash_context_finish (hc,
- &wsd->h_sepa_details);
-}
-
-
-/**
- * Verify that the signature in the @a json for /wire/sepa is valid.
- *
- * @param json json reply with the signature
- * @param master_pub public key of the exchange to verify against
- * @return #GNUNET_SYSERR if @a json is invalid,
- * #GNUNET_NO if the method is unknown,
- * #GNUNET_OK if the json is valid
- */
-static int
-verify_wire_sepa_signature_ok (const json_t *json,
- const struct TALER_MasterPublicKeyP *master_pub)
-{
- struct TALER_MasterSignatureP exchange_sig;
- struct TALER_MasterWireDetailsPS mp;
- const char *name;
- const char *iban;
- const char *bic;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("sig", &exchange_sig),
- GNUNET_JSON_spec_string ("name", &name),
- GNUNET_JSON_spec_string ("iban", &iban),
- GNUNET_JSON_spec_string ("bic", &bic),
- GNUNET_JSON_spec_end()
- };
-
- if (NULL == master_pub)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Skipping signature check as master public key not given\n");
- return GNUNET_OK;
- }
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json, spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- compute_purpose (name,
- iban,
- bic,
- &mp);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS,
- &mp.purpose,
- &exchange_sig.eddsa_signature,
- &master_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
- * Check if the given wire format JSON object is correctly formatted
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire the JSON wire format object
- * @param master_pub public key of the exchange to verify against
- * @param[out] emsg set to an error message, unless we return #TALER_EC_NONE;
- * error message must be freed by the caller using GNUNET_free()
- * @return #TALER_EC_NONE if correctly formatted
- */
-static enum TALER_ErrorCode
-sepa_wire_validate (void *cls,
- const json_t *wire,
- const struct TALER_MasterPublicKeyP *master_pub,
- char **emsg)
-{
- json_error_t error;
- const char *type;
- const char *iban;
- const char *name;
- const char *bic;
-
- *emsg = NULL;
- if (0 != json_unpack_ex
- ((json_t *) wire,
- &error, 0,
- "{"
- "s:s," /* type: sepa */
- "s:s," /* iban: IBAN */
- "s:s," /* name: beneficiary name */
- "s:s" /* bic: beneficiary bank's BIC */
- "}",
- "type", &type,
- "iban", &iban,
- "name", &name,
- "bic", &bic))
- {
- char *dump;
-
- dump = json_dumps (wire, 0);
- GNUNET_asprintf (emsg,
- "JSON parsing failed at %s:%u: %s (%s): %s\n",
- __FILE__, __LINE__,
- error.text,
- error.source,
- dump);
- free (dump);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON;
- }
- if (0 != strcasecmp (type,
- "sepa"))
- {
- GNUNET_asprintf (emsg,
- "Transfer type `%s' invalid for SEPA wire plugin\n",
- type);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE;
- }
- if (1 != validate_iban (iban))
- {
- GNUNET_asprintf (emsg,
- "IBAN `%s' invalid\n",
- iban);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_ACCOUNT_NUMBER;
- }
- /* FIXME: don't parse again, integrate properly... */
- if (GNUNET_OK !=
- verify_wire_sepa_signature_ok (wire,
- master_pub))
- {
- GNUNET_asprintf (emsg,
- "Signature using public key `%s' invalid\n",
- TALER_B2S (master_pub));
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
- }
- return TALER_EC_NONE;
-}
-
-
-/**
- * Obtain wire transfer details in the plugin-specific format
- * from the configuration.
- *
- * @param cls closure
- * @param cfg configuration with details about wire accounts
- * @param account_name which section in the configuration should we parse
- * @return NULL if @a cfg fails to have valid wire details for @a account_name
- */
-static json_t *
-sepa_get_wire_details (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *account_name)
-{
- char *sepa_wire_file;
- json_error_t err;
- json_t *ret;
- char *emsg;
-
- /* Fetch reply */
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- account_name,
- "SEPA_RESPONSE_FILE",
- &sepa_wire_file))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- account_name,
- "SEPA_RESPONSE_FILE");
- return NULL;
- }
- ret = json_load_file (sepa_wire_file,
- JSON_REJECT_DUPLICATES,
- &err);
- if (NULL == ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse JSON in %s: %s (%s:%u)\n",
- sepa_wire_file,
- err.text,
- err.source,
- err.line);
- GNUNET_free (sepa_wire_file);
- return NULL;
- }
- if (TALER_EC_NONE !=
- sepa_wire_validate (cls,
- ret,
- NULL,
- &emsg))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to validate SEPA data in %s: %s\n",
- sepa_wire_file,
- emsg);
- GNUNET_free (emsg);
- GNUNET_free (sepa_wire_file);
- json_decref (ret);
- return NULL;
- }
- GNUNET_free (sepa_wire_file);
- return ret;
-}
-
-
-/**
- * Sign wire transfer details in the plugin-specific format.
- *
- * @param cls closure
- * @param in wire transfer details in JSON format
- * @param key private signing key to use
- * @param salt salt to add
- * @param[out] sig where to write the signature
- * @return #GNUNET_OK on success
- */
-static int
-sepa_sign_wire_details (void *cls,
- const json_t *in,
- const struct TALER_MasterPrivateKeyP *key,
- const struct GNUNET_HashCode *salt,
- struct TALER_MasterSignatureP *sig)
-{
- struct TALER_MasterWireDetailsPS wsd;
- const char *sepa_name;
- const char *iban;
- const char *bic;
- const char *type;
- json_error_t err;
-
- if (0 !=
- json_unpack_ex ((json_t *) in,
- &err,
- 0 /* flags */,
- "{s:s, s:s, s:s, s:s}",
- "type", &type,
- "name", &sepa_name,
- "iban", &iban,
- "bic", &bic))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to unpack JSON: %s (at %u)\n",
- err.text,
- err.position);
- return GNUNET_SYSERR;
- }
- if (0 != strcmp (type,
- "sepa"))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "`type' must be `sepa' for SEPA wire details\n");
- return GNUNET_SYSERR;
- }
- if (1 != validate_iban (iban))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "IBAN invalid in SEPA wire details\n");
- return GNUNET_SYSERR;
- }
- compute_purpose (sepa_name,
- iban,
- bic,
- &wsd);
- GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
- &wsd.purpose,
- &sig->eddsa_signature);
- return GNUNET_OK;
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire valid wire account information
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param wtid wire transfer identifier to use
- * @param psc function to call with the prepared data to persist
- * @param psc_cls closure for @a psc
- * @return NULL on failure
- */
-static struct TALER_WIRE_PrepareHandle *
-sepa_prepare_wire_transfer (void *cls,
- const json_t *wire,
- const struct TALER_Amount *amount,
- const char *exchange_base_url,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- TALER_WIRE_PrepareTransactionCallback psc,
- void *psc_cls)
-{
- GNUNET_break (0); // FIXME: not implemented
- return NULL;
-}
-
-
-/**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
-static void
-sepa_prepare_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_PrepareHandle *pth)
-{
- GNUNET_break (0); // FIXME: not implemented
-}
-
-
-/**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
-static struct TALER_WIRE_ExecuteHandle *
-sepa_execute_wire_transfer (void *cls,
- const char *buf,
- size_t buf_size,
- TALER_WIRE_ConfirmationCallback cc,
- void *cc_cls)
-{
- GNUNET_break (0); // FIXME: not implemented
- return NULL;
-}
-
-
-/**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down. Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
-static void
-sepa_execute_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_ExecuteHandle *eh)
-{
- GNUNET_break (0); // FIXME: not implemented
-}
-
-
-/**
- * Query transfer history of an account. We use the variable-size
- * @a start_off to indicate which transfers we are interested in as
- * different banking systems may have different ways to identify
- * transfers. The @a start_off value must thus match the value of
- * a `row_off` argument previously given to the @a hres_cb. Use
- * NULL to query transfers from the beginning of time (with
- * positive @a num_results) or from the latest committed transfers
- * (with negative @a num_results).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param direction what kinds of wire transfers should be returned
- * @param start_off from which row on do we want to get results, use NULL for the latest; exclusive
- * @param start_off_len number of bytes in @a start_off; must be `sizeof(uint64_t)`.
- * @param num_results how many results do we want; negative numbers to go into the past,
- * positive numbers to go into the future starting at @a start_row;
- * must not be zero.
- * @param hres_cb the callback to call with the transaction history
- * @param hres_cb_cls closure for the above callback
- */
-static struct TALER_WIRE_HistoryHandle *
-sepa_get_history (void *cls,
- enum TALER_BANK_Direction direction,
- const void *start_off,
- size_t start_off_len,
- int64_t num_results,
- TALER_WIRE_HistoryResultCallback hres_cb,
- void *hres_cb_cls)
-{
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Cancel going over the account's history.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param whh operation to cancel
- */
-static void
-sepa_get_history_cancel (void *cls,
- struct TALER_WIRE_HistoryHandle *whh)
-{
- GNUNET_break (0);
-}
-
-
-
-/**
- * Context for a rejection operation.
- */
-struct TALER_WIRE_RejectHandle
-{
- /**
- * Function to call with the result.
- */
- TALER_WIRE_RejectTransferCallback rej_cb;
-
- /**
- * Closure for @e rej_cb.
- */
- void *rej_cb_cls;
-
- /**
- * Handle to task for timeout of operation.
- */
- struct GNUNET_SCHEDULER_Task *timeout_task;
-};
-
-
-/**
- * Rejection operation failed with timeout, notify callback
- * and clean up.
- *
- * @param cls closure with `struct TALER_WIRE_RejectHandle`
- */
-static void
-timeout_reject (void *cls)
-{
- struct TALER_WIRE_RejectHandle *rh = cls;
-
- rh->timeout_task = NULL;
- rh->rej_cb (rh->rej_cb_cls,
- TALER_EC_NOT_IMPLEMENTED /* in the future: TALER_EC_TIMEOUT */);
- GNUNET_free (rh);
-}
-
-
-/**
- * Reject an incoming wire transfer that was obtained from the
- * history. This function can be used to transfer funds back to
- * the sender if the WTID was malformed (i.e. due to a typo).
- *
- * Calling `reject_transfer` twice on the same wire transfer should
- * be idempotent, i.e. not cause the funds to be wired back twice.
- * Furthermore, the transfer should henceforth be removed from the
- * results returned by @e get_history.
- *
- * @param cls plugin's closure
- * @param start_off offset of the wire transfer in plugin-specific format
- * @param start_off_len number of bytes in @a start_off
- * @param rej_cb function to call with the result of the operation
- * @param rej_cb_cls closure for @a rej_cb
- * @return handle to cancel the operation
- */
-static struct TALER_WIRE_RejectHandle *
-sepa_reject_transfer (void *cls,
- const void *start_off,
- size_t start_off_len,
- TALER_WIRE_RejectTransferCallback rej_cb,
- void *rej_cb_cls)
-{
- struct TALER_WIRE_RejectHandle *rh;
-
- GNUNET_break (0); /* not implemented, just a stub! */
- rh = GNUNET_new (struct TALER_WIRE_RejectHandle);
- rh->rej_cb = rej_cb;
- rh->rej_cb_cls = rej_cb_cls;
- rh->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_reject,
- rh);
- return rh;
-}
-
-
-/**
- * Cancel ongoing reject operation. Note that the rejection may still
- * proceed. Basically, if this function is called, the rejection may
- * have happened or not. This function is usually used during shutdown
- * or system upgrades. At a later point, the application must call
- * @e reject_transfer again for this wire transfer, unless the
- * @e get_history shows that the wire transfer no longer exists.
- *
- * @param cls plugins' closure
- * @param rh operation to cancel
- * @return closure of the callback of the operation
- */
-static void *
-sepa_reject_transfer_cancel (void *cls,
- struct TALER_WIRE_RejectHandle *rh)
-{
- void *ret = rh->rej_cb_cls;
-
- GNUNET_SCHEDULER_cancel (rh->timeout_task);
- GNUNET_free (rh);
- return ret;
-}
-
-
-/**
- * Initialize sepa-wire subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
- */
-void *
-libtaler_plugin_wire_sepa_init (void *cls)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct SepaClosure *sc;
- struct TALER_WIRE_Plugin *plugin;
-
- sc = GNUNET_new (struct SepaClosure);
- if (NULL != cfg)
- {
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "taler",
- "CURRENCY",
- &sc->currency))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler",
- "CURRENCY");
- GNUNET_free (sc);
- return NULL;
- }
- }
- plugin = GNUNET_new (struct TALER_WIRE_Plugin);
- plugin->cls = sc;
- plugin->amount_round = &sepa_amount_round;
- plugin->get_wire_details = &sepa_get_wire_details;
- plugin->sign_wire_details = &sepa_sign_wire_details;
- plugin->wire_validate = &sepa_wire_validate;
- plugin->prepare_wire_transfer = &sepa_prepare_wire_transfer;
- plugin->prepare_wire_transfer_cancel = &sepa_prepare_wire_transfer_cancel;
- plugin->execute_wire_transfer = &sepa_execute_wire_transfer;
- plugin->execute_wire_transfer_cancel = &sepa_execute_wire_transfer_cancel;
- plugin->get_history = &sepa_get_history;
- plugin->get_history_cancel = &sepa_get_history_cancel;
- plugin->reject_transfer = &sepa_reject_transfer;
- plugin->reject_transfer_cancel = &sepa_reject_transfer_cancel;
- return plugin;
-}
-
-
-/**
- * Shutdown Sepa wire subsystem.
- *
- * @param cls a `struct TALER_WIRE_Plugin`
- * @return NULL (always)
- */
-void *
-libtaler_plugin_wire_sepa_done (void *cls)
-{
- struct TALER_WIRE_Plugin *plugin = cls;
- struct SepaClosure *sc = plugin->cls;
-
- GNUNET_free_non_null (sc->currency);
- GNUNET_free (sc);
- GNUNET_free (plugin);
- return NULL;
-}
-
-/* end of plugin_wire_sepa.c */
diff --git a/src/wire/plugin_wire_template.c b/src/wire/plugin_wire_template.c
deleted file mode 100644
index 06e70c2a8..000000000
--- a/src/wire/plugin_wire_template.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2016 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 plugin_wire_template.c
- * @brief template for wire plugins; replace "template" with real plugin name!
- * @author Florian Dold
- * @author Christian Grothoff
- * @author Sree Harsha Totakura
- */
-#include "platform.h"
-#include "taler_wire_plugin.h"
-
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct TemplateClosure
-{
-
- /**
- * URL of the bank for sending funds to the bank.
- */
- char *bank_url;
-
- /**
- * Which currency do we support?
- */
- char *currency;
-
-};
-
-
-/**
- * Round amount DOWN to the amount that can be transferred via the wire
- * method. For example, Taler may support 0.000001 EUR as a unit of
- * payment, but SEPA only supports 0.01 EUR. This function would
- * round 0.125 EUR to 0.12 EUR in this case.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param[in,out] amount amount to round down
- * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
- * #GNUNET_SYSERR if the amount or currency was invalid
- */
-static int
-template_amount_round (void *cls,
- struct TALER_Amount *amount)
-{
- struct TemplateClosure *tc = cls;
-
- if (0 != strcasecmp (amount->currency,
- tc->currency))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- GNUNET_break (0); // not implemented
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Obtain wire transfer details in the plugin-specific format
- * from the configuration.
- *
- * @param cls closure
- * @param cfg configuration with details about wire accounts
- * @param account_name which section in the configuration should we parse
- * @return NULL if @a cfg fails to have valid wire details for @a account_name
- */
-static json_t *
-template_get_wire_details (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *account_name)
-{
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Check if the given wire format JSON object is correctly formatted
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire the JSON wire format object
- * @param master_pub public key of the exchange to verify against
- * @param[out] emsg set to an error message, unless we return #TALER_EC_NONE;
- * error message must be freed by the caller using GNUNET_free()
- * @return #TALER_EC_NONE if correctly formatted
- */
-static enum TALER_ErrorCode
-template_wire_validate (void *cls,
- const json_t *wire,
- const struct TALER_MasterPublicKeyP *master_pub,
- char **emsg)
-{
- GNUNET_asprintf (emsg,
- "Not implemented");
- return TALER_EC_NOT_IMPLEMENTED;
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire valid wire account information
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param wtid wire transfer identifier to use
- * @param ptc function to call with the prepared data to persist
- * @param ptc_cls closure for @a ptc
- * @return NULL on failure
- */
-static struct TALER_WIRE_PrepareHandle *
-template_prepare_wire_transfer (void *cls,
- const json_t *wire,
- const struct TALER_Amount *amount,
- const char *exchange_base_url,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- TALER_WIRE_PrepareTransactionCallback ptc,
- void *ptc_cls)
-{
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
-static void
-template_prepare_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_PrepareHandle *pth)
-{
- GNUNET_break (0);
-}
-
-
-/**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
-static struct TALER_WIRE_ExecuteHandle *
-template_execute_wire_transfer (void *cls,
- const char *buf,
- size_t buf_size,
- TALER_WIRE_ConfirmationCallback cc,
- void *cc_cls)
-{
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Sign wire transfer details in the plugin-specific format.
- *
- * @param cls closure
- * @param in wire transfer details in JSON format
- * @param key private signing key to use
- * @param salt salt to add
- * @param[out] sig where to write the signature
- * @return #GNUNET_OK on success
- */
-static int
-template_sign_wire_details (void *cls,
- const json_t *in,
- const struct TALER_MasterPrivateKeyP *key,
- const struct GNUNET_HashCode *salt,
- struct TALER_MasterSignatureP *sig)
-{
- GNUNET_break (0);
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down. Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
-static void
-template_execute_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_ExecuteHandle *eh)
-{
- GNUNET_break (0);
-}
-
-
-/**
- * Query transfer history of an account. We use the variable-size
- * @a start_off to indicate which transfers we are interested in as
- * different banking systems may have different ways to identify
- * transfers. The @a start_off value must thus match the value of
- * a `row_off` argument previously given to the @a hres_cb. Use
- * NULL to query transfers from the beginning of time (with
- * positive @a num_results) or from the latest committed transfers
- * (with negative @a num_results).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param direction what kinds of wire transfers should be returned
- * @param start_off from which row on do we want to get results, use NULL for the latest; exclusive
- * @param start_off_len number of bytes in @a start_off; must be `sizeof(uint64_t)`.
- * @param num_results how many results do we want; negative numbers to go into the past,
- * positive numbers to go into the future starting at @a start_row;
- * must not be zero.
- * @param hres_cb the callback to call with the transaction history
- * @param hres_cb_cls closure for the above callback
- */
-static struct TALER_WIRE_HistoryHandle *
-template_get_history (void *cls,
- enum TALER_BANK_Direction direction,
- const void *start_off,
- size_t start_off_len,
- int64_t num_results,
- TALER_WIRE_HistoryResultCallback hres_cb,
- void *hres_cb_cls)
-{
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Cancel going over the account's history.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param whh operation to cancel
- */
-static void
-template_get_history_cancel (void *cls,
- struct TALER_WIRE_HistoryHandle *whh)
-{
- GNUNET_break (0);
-}
-
-
-/**
- * Initialize template-wire subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
- */
-void *
-libtaler_plugin_wire_template_init (void *cls)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct TemplateClosure *tc;
- struct TALER_WIRE_Plugin *plugin;
-
- tc = GNUNET_new (struct TemplateClosure);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange-wire-template",
- "bank_url",
- &tc->bank_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange-wire-template",
- "bank_url");
- GNUNET_free (tc);
- return NULL;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "taler",
- "CURRENCY",
- &tc->currency))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler",
- "CURRENCY");
- GNUNET_free (tc->bank_url);
- GNUNET_free (tc);
- return NULL;
- }
-
- plugin = GNUNET_new (struct TALER_WIRE_Plugin);
- plugin->cls = tc;
- plugin->amount_round = &template_amount_round;
- plugin->get_wire_details = &template_get_wire_details;
- plugin->sign_wire_details = &template_sign_wire_details;
- plugin->wire_validate = &template_wire_validate;
- plugin->prepare_wire_transfer = &template_prepare_wire_transfer;
- plugin->prepare_wire_transfer_cancel = &template_prepare_wire_transfer_cancel;
- plugin->execute_wire_transfer = &template_execute_wire_transfer;
- plugin->execute_wire_transfer_cancel = &template_execute_wire_transfer_cancel;
- plugin->get_history = &template_get_history;
- plugin->get_history_cancel = &template_get_history_cancel;
- return plugin;
-}
-
-
-/**
- * Shutdown Template wire subsystem.
- *
- * @param cls a `struct TALER_WIRE_Plugin`
- * @return NULL (always)
- */
-void *
-libtaler_plugin_wire_template_done (void *cls)
-{
- struct TALER_WIRE_Plugin *plugin = cls;
- struct TemplateClosure *tc = plugin->cls;
-
- GNUNET_free (tc->bank_url);
- GNUNET_free (tc->currency);
- GNUNET_free (tc);
- GNUNET_free (plugin);
- return NULL;
-}
-
-/* end of plugin_wire_template.c */
diff --git a/src/wire/plugin_wire_test.c b/src/wire/plugin_wire_test.c
deleted file mode 100644
index 11feaea7e..000000000
--- a/src/wire/plugin_wire_test.c
+++ /dev/null
@@ -1,1302 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 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 plugin_wire_test.c
- * @brief plugin for the "test" wire method
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_wire_plugin.h"
-#include "taler_bank_service.h"
-#include "taler_signatures.h"
-#include <gnunet/gnunet_curl_lib.h>
-
-/* only for HTTP status codes */
-#include <microhttpd.h>
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct TestClosure
-{
-
- /**
- * Which currency do we support?
- */
- char *currency;
-
- /**
- * URL of our bank.
- */
- char *bank_url;
-
- /**
- * Authentication information.
- */
- struct TALER_BANK_AuthenticationData auth;
-
- /**
- * Handle to the context for sending funds to the bank.
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * Scheduler context for running the @e ctx.
- */
- struct GNUNET_CURL_RescheduleContext *rc;
-
- /**
- * Number of the account that the exchange has at the bank for
- * transfers.
- */
- unsigned long long exchange_account_no;
-
-};
-
-
-/**
- * Handle returned by #test_prepare_wire_transfer.
- */
-struct TALER_WIRE_PrepareHandle
-{
-
- /**
- * Task we use for async execution.
- */
- struct GNUNET_SCHEDULER_Task *task;
-
- /**
- * Test closure we run in.
- */
- struct TestClosure *tc;
-
- /**
- * Wire data for the transfer.
- */
- json_t *wire;
-
- /**
- * Base URL to use for the exchange.
- */
- char *exchange_base_url;
-
- /**
- * Function to call with the serialized data.
- */
- TALER_WIRE_PrepareTransactionCallback ptc;
-
- /**
- * Closure for @e ptc.
- */
- void *ptc_cls;
-
- /**
- * Amount to transfer.
- */
- struct TALER_Amount amount;
-
- /**
- * Subject of the wire transfer.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
-
-};
-
-
-/**
- * Handle returned by #test_execute_wire_transfer.
- */
-struct TALER_WIRE_ExecuteHandle
-{
-
- /**
- * Handle to the HTTP request to the bank.
- */
- struct TALER_BANK_AdminAddIncomingHandle *aaih;
-
- /**
- * Function to call with the result.
- */
- TALER_WIRE_ConfirmationCallback cc;
-
- /**
- * Closure for @e cc.
- */
- void *cc_cls;
-};
-
-
-
-/**
- * Round amount DOWN to the amount that can be transferred via the wire
- * method. For example, Taler may support 0.000001 EUR as a unit of
- * payment, but SEPA only supports 0.01 EUR. This function would
- * round 0.125 EUR to 0.12 EUR in this case.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param[in,out] amount amount to round down
- * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
- * #GNUNET_SYSERR if the amount or currency was invalid
- */
-static int
-test_amount_round (void *cls,
- struct TALER_Amount *amount)
-{
- struct TestClosure *tc = cls;
- uint32_t delta;
-
- if (NULL == tc->currency)
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler",
- "CURRENCY");
- return GNUNET_SYSERR; /* not configured with currency */
- }
- if (0 != strcasecmp (amount->currency,
- tc->currency))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- /* 'test' method supports 1/100 of the unit currency, i.e. 0.01 CUR */
- delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / 100);
- if (0 == delta)
- return GNUNET_NO;
- amount->fraction -= delta;
- return GNUNET_OK;
-}
-
-
-/**
- * Compute purpose for signing.
- *
- * @param account number of the account
- * @param bank_url URL of the bank
- * @param[out] wsd purpose to be signed
- */
-static void
-compute_purpose (uint64_t account,
- const char *bank_url,
- struct TALER_MasterWireDetailsPS *wsd)
-{
- struct GNUNET_HashContext *hc;
- uint64_t n = GNUNET_htonll (account);
-
- wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
- wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_TEST_DETAILS);
- hc = GNUNET_CRYPTO_hash_context_start ();
- GNUNET_CRYPTO_hash_context_read (hc,
- "test",
- strlen ("test") + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- &n,
- sizeof (n));
- GNUNET_CRYPTO_hash_context_read (hc,
- bank_url,
- strlen (bank_url) + 1);
- GNUNET_CRYPTO_hash_context_finish (hc,
- &wsd->h_sepa_details);
-}
-
-
-/**
- * Check if the given wire format JSON object is correctly formatted.
- * Right now, the only thing we require is a field
- * "account_number" which must contain a positive 53-bit integer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire the JSON wire format object
- * @param master_pub public key of the exchange to verify against
- * @param[out] emsg set to an error message, unless we return #TALER_EC_NONE;
- * error message must be freed by the caller using GNUNET_free()
- * @return #TALER_EC_NONE if correctly formatted
- */
-static enum TALER_ErrorCode
-test_wire_validate (void *cls,
- const json_t *wire,
- const struct TALER_MasterPublicKeyP *master_pub,
- char **emsg)
-{
- struct TestClosure *tc = cls;
- json_error_t error;
- json_int_t account_no;
- const char *bank_url;
- const char *sig_s;
- struct TALER_MasterWireDetailsPS wsd;
- struct TALER_MasterSignatureP sig;
-
- *emsg = NULL;
- if (0 !=
- json_unpack_ex ((json_t *) wire,
- &error,
- 0,
- "{s:I, s:s}",
- "account_number", &account_no,
- "bank_url", &bank_url))
- {
- char *dump;
-
- dump = json_dumps (wire, 0);
- GNUNET_asprintf (emsg,
- "JSON parsing failed at %s:%u: %s (%s): %s\n",
- __FILE__, __LINE__,
- error.text,
- error.source,
- dump);
- free (dump);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON;
- }
- if ( (account_no < 0) ||
- (account_no > (1LL << 53)) )
- {
- GNUNET_asprintf (emsg,
- "Account number %llu outside of permitted range\n",
- account_no);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_ACCOUNT_NUMBER;
- }
- if ( (NULL != tc->bank_url) &&
- (0 != strcmp (bank_url,
- tc->bank_url)) )
- {
- GNUNET_asprintf (emsg,
- "Wire specifies bank URL `%s', but this exchange only supports `%s'\n",
- bank_url,
- tc->bank_url);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_BANK;
- }
- if (NULL == master_pub)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Skipping signature check as master public key not given\n");
- return TALER_EC_NONE;
- }
- if (0 !=
- json_unpack_ex ((json_t *) wire,
- &error,
- 0,
- "{s:s}",
- "sig", &sig_s))
- {
- GNUNET_asprintf (emsg,
- "Signature check required, but signature is missing\n");
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
- }
- compute_purpose (account_no,
- bank_url,
- &wsd);
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (sig_s,
- strlen (sig_s),
- &sig,
- sizeof (sig)))
- {
- GNUNET_break (0);
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_TEST_DETAILS,
- &wsd.purpose,
- &sig.eddsa_signature,
- &master_pub->eddsa_pub))
- {
- GNUNET_asprintf (emsg,
- "Signature using public key `%s' invalid\n",
- TALER_B2S (master_pub));
- return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
- }
- return TALER_EC_NONE;
-}
-
-
-/**
- * Obtain wire transfer details in the plugin-specific format
- * from the configuration.
- *
- * @param cls closure
- * @param cfg configuration with details about wire accounts
- * @param account_name which section in the configuration should we parse
- * @return NULL if @a cfg fails to have valid wire details for @a account_name
- */
-static json_t *
-test_get_wire_details (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *account_name)
-{
- struct TestClosure *tc = cls;
- char *test_wire_file;
- json_error_t err;
- json_t *ret;
- char *emsg;
-
- /* Fetch reply */
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- account_name,
- "TEST_RESPONSE_FILE",
- &test_wire_file))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- account_name,
- "TEST_RESPONSE_FILE");
- return NULL;
- }
- ret = json_load_file (test_wire_file,
- JSON_REJECT_DUPLICATES,
- &err);
- if (NULL == ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse JSON in %s: %s (%s:%u)\n",
- test_wire_file,
- err.text,
- err.source,
- err.line);
- GNUNET_free (test_wire_file);
- return NULL;
- }
- if (TALER_EC_NONE !=
- test_wire_validate (tc,
- ret,
- NULL,
- &emsg))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to validate TEST wire data in %s: %s\n",
- test_wire_file,
- emsg);
- GNUNET_free (emsg);
- GNUNET_free (test_wire_file);
- json_decref (ret);
- return NULL;
- }
- GNUNET_free (test_wire_file);
- return ret;
-}
-
-
-GNUNET_NETWORK_STRUCT_BEGIN
-/**
- * Format we used for serialized transaction data.
- */
-struct BufFormatP
-{
-
- /**
- * The wire transfer identifier.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * The amount.
- */
- struct TALER_AmountNBO amount;
-
- /* followed by serialized 'wire' JSON data (0-terminated) */
-
- /* followed by 0-terminated base URL */
-
-};
-GNUNET_NETWORK_STRUCT_END
-
-
-/**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
-static void
-test_prepare_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_PrepareHandle *pth)
-{
- if (NULL != pth->task)
- GNUNET_SCHEDULER_cancel (pth->task);
- json_decref (pth->wire);
- GNUNET_free (pth->exchange_base_url);
- GNUNET_free (pth);
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer. Calls the
- * callback with the serialized state.
- *
- * @param cls the `struct TALER_WIRE_PrepareHandle`
- */
-static void
-do_prepare (void *cls)
-{
- struct TALER_WIRE_PrepareHandle *pth = cls;
- char *wire_enc;
- size_t len_w;
- size_t len_b;
- struct BufFormatP bf;
-
- pth->task = NULL;
- /* serialize the state into a 'buf' */
- wire_enc = json_dumps (pth->wire,
- JSON_COMPACT | JSON_SORT_KEYS);
- if (NULL == wire_enc)
- {
- GNUNET_break (0);
- pth->ptc (pth->ptc_cls,
- NULL,
- 0);
- test_prepare_wire_transfer_cancel (NULL,
- pth);
- return;
- }
- len_w = strlen (wire_enc) + 1;
- len_b = strlen (pth->exchange_base_url) + 1;
- bf.wtid = pth->wtid;
- TALER_amount_hton (&bf.amount,
- &pth->amount);
- {
- char buf[sizeof (struct BufFormatP) + len_w + len_b];
-
- memcpy (buf,
- &bf,
- sizeof (struct BufFormatP));
- memcpy (&buf[sizeof (struct BufFormatP)],
- wire_enc,
- len_w);
- memcpy (&buf[sizeof (struct BufFormatP) + len_w],
- pth->exchange_base_url,
- len_b);
-
- /* finally give the state back */
- pth->ptc (pth->ptc_cls,
- buf,
- sizeof (buf));
- }
- free (wire_enc); /* not using GNUNET_free(),
- as this one is allocated by libjansson */
- test_prepare_wire_transfer_cancel (NULL,
- pth);
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer. Note that we should call
- * @a ptc asynchronously (as that is what the API requires, because
- * some transfer methods need it). So while we could immediately call
- * @a ptc, we first bundle up all the data and schedule a task to do
- * the work.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire valid wire account information
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of this exchange
- * @param wtid wire transfer identifier to use
- * @param ptc function to call with the prepared data to persist
- * @param ptc_cls closure for @a ptc
- * @return NULL on failure
- */
-static struct TALER_WIRE_PrepareHandle *
-test_prepare_wire_transfer (void *cls,
- const json_t *wire,
- const struct TALER_Amount *amount,
- const char *exchange_base_url,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- TALER_WIRE_PrepareTransactionCallback ptc,
- void *ptc_cls)
-{
- struct TestClosure *tc = cls;
- struct TALER_WIRE_PrepareHandle *pth;
- char *emsg;
-
- if (TALER_EC_NONE !=
- test_wire_validate (tc,
- wire,
- NULL,
- &emsg))
- {
- GNUNET_break_op (0);
- GNUNET_free (emsg);
- return NULL;
- }
- pth = GNUNET_new (struct TALER_WIRE_PrepareHandle);
- pth->tc = tc;
- pth->wire = json_incref ((json_t *) wire);
- pth->exchange_base_url = GNUNET_strdup (exchange_base_url);
- pth->wtid = *wtid;
- pth->ptc = ptc;
- pth->ptc_cls = ptc_cls;
- pth->amount = *amount;
- pth->task = GNUNET_SCHEDULER_add_now (&do_prepare,
- pth);
- return pth;
-}
-
-
-/**
- * Called with the result of submitting information about an incoming
- * transaction to a bank.
- *
- * @param cls closure with the `struct TALER_WIRE_ExecuteHandle`
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the bank's reply is bogus (fails to follow the protocol)
- * @param ec error code from the bank
- * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
- * @param json detailed response from the HTTPD, or NULL if reply was not JSON
- */
-static void
-execute_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- uint64_t serial_id,
- const json_t *json)
-{
- struct TALER_WIRE_ExecuteHandle *eh = cls;
- json_t *reason;
- const char *emsg;
- char *s;
-
- eh->aaih = NULL;
- emsg = NULL;
- if (NULL != json)
- {
- reason = json_object_get (json,
- "reason");
- if (NULL != reason)
- emsg = json_string_value (reason);
- }
- if (NULL != emsg)
- GNUNET_asprintf (&s,
- "%u/%u (%s)",
- http_status,
- (unsigned int) ec,
- emsg);
- else
- GNUNET_asprintf (&s,
- "%u/%u",
- http_status,
- (unsigned int) ec);
- eh->cc (eh->cc_cls,
- (MHD_HTTP_OK == http_status) ? GNUNET_OK : GNUNET_SYSERR,
- serial_id,
- (MHD_HTTP_OK == http_status) ? NULL : s);
- GNUNET_free (s);
- GNUNET_free (eh);
-}
-
-
-/**
- * Sign wire transfer details in the plugin-specific format.
- *
- * @param cls closure
- * @param in wire transfer details in JSON format
- * @param key private signing key to use
- * @param salt salt to add
- * @param[out] sig where to write the signature
- * @return #GNUNET_OK on success
- */
-static int
-test_sign_wire_details (void *cls,
- const json_t *in,
- const struct TALER_MasterPrivateKeyP *key,
- const struct GNUNET_HashCode *salt,
- struct TALER_MasterSignatureP *sig)
-{
- struct TALER_MasterWireDetailsPS wsd;
- const char *bank_url;
- const char *type;
- json_int_t account;
- json_error_t err;
-
- if (0 !=
- json_unpack_ex ((json_t *) in,
- &err,
- 0 /* flags */,
- "{s:s, s:s, s:I}",
- "type", &type,
- "bank_url", &bank_url,
- "account_number", &account))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to unpack JSON: %s (at %u)\n",
- err.text,
- err.position);
- return GNUNET_SYSERR;
- }
- if (0 != strcmp (type,
- "test"))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "`type' must be `test' for test wire details\n");
- return GNUNET_SYSERR;
- }
- compute_purpose (account,
- bank_url,
- &wsd);
- GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
- &wsd.purpose,
- &sig->eddsa_signature);
- return GNUNET_OK;
-}
-
-
-/**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
-static struct TALER_WIRE_ExecuteHandle *
-test_execute_wire_transfer (void *cls,
- const char *buf,
- size_t buf_size,
- TALER_WIRE_ConfirmationCallback cc,
- void *cc_cls)
-{
- struct TestClosure *tc = cls;
- struct TALER_WIRE_ExecuteHandle *eh;
- json_t *wire;
- json_error_t error;
- struct TALER_Amount amount;
- json_int_t account_no;
- struct BufFormatP bf;
- char *emsg;
- const char *json_s;
- const char *exchange_base_url;
- char *wire_s;
-
- if (NULL == tc->ctx)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bank not initialized, cannot do transfers!\n");
- return NULL; /* not initialized with configuration, cannot do transfers */
- }
- if ( (buf_size <= sizeof (struct BufFormatP)) ||
- ('\0' != buf[buf_size - 1]) )
- {
- GNUNET_break (0);
- return NULL;
- }
- json_s = &buf[sizeof (struct BufFormatP)];
- exchange_base_url = &json_s[strlen (json_s) + 1];
- if (exchange_base_url > &buf[buf_size - 1])
- {
- GNUNET_break (0);
- return NULL;
- }
- memcpy (&bf,
- buf,
- sizeof (bf));
- TALER_amount_ntoh (&amount,
- &bf.amount);
- wire = json_loads (json_s,
- JSON_REJECT_DUPLICATES,
- NULL);
- if (NULL == wire)
- {
- GNUNET_break (0);
- return NULL;
- }
- GNUNET_assert (TALER_EC_NONE ==
- test_wire_validate (tc,
- wire,
- NULL,
- &emsg));
- if (0 !=
- json_unpack_ex (wire,
- &error,
- 0,
- "{s:I}",
- "account_number", &account_no))
- {
- GNUNET_break (0);
- return NULL;
- }
-
- eh = GNUNET_new (struct TALER_WIRE_ExecuteHandle);
- eh->cc = cc;
- eh->cc_cls = cc_cls;
- wire_s = GNUNET_STRINGS_data_to_string_alloc (&bf.wtid,
- sizeof (bf.wtid));
- eh->aaih = TALER_BANK_admin_add_incoming (tc->ctx,
- tc->bank_url,
- &tc->auth,
- exchange_base_url,
- wire_s,
- &amount,
- (uint64_t) tc->exchange_account_no,
- (uint64_t) account_no,
- &execute_cb,
- eh);
- GNUNET_free (wire_s);
- json_decref (wire);
- if (NULL == eh->aaih)
- {
- GNUNET_break (0);
- GNUNET_free (eh);
- return NULL;
- }
- return eh;
-}
-
-
-/**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down. Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
-static void
-test_execute_wire_transfer_cancel (void *cls,
- struct TALER_WIRE_ExecuteHandle *eh)
-{
- TALER_BANK_admin_add_incoming_cancel (eh->aaih);
- GNUNET_free (eh);
-}
-
-
-/**
- * Handle for a #test_get_history() request.
- */
-struct TALER_WIRE_HistoryHandle
-{
-
- /**
- * Function to call with results.
- */
- TALER_WIRE_HistoryResultCallback hres_cb;
-
- /**
- * Closure for @e hres_cb.
- */
- void *hres_cb_cls;
-
- /**
- * Request to the bank.
- */
- struct TALER_BANK_HistoryHandle *hh;
-
-};
-
-
-/**
- * Function called with results from the bank about the transaction history.
- *
- * @param cls the `struct TALER_WIRE_HistoryHandle`
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the bank's reply is bogus (fails to follow the protocol),
- * #MHD_HTTP_NO_CONTENT if there are no more results; on success the
- * last callback is always of this status (even if `abs(num_results)` were
- * already returned).
- * @param ec taler error code
- * @param dir direction of the transfer
- * @param serial_id monotonically increasing counter corresponding to the transaction
- * @param details details about the wire transfer
- * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
- */
-static void
-bhist_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- uint64_t serial_id,
- const struct TALER_BANK_TransferDetails *details,
- const json_t *json)
-{
- struct TALER_WIRE_HistoryHandle *whh = cls;
- uint64_t bserial_id = GNUNET_htonll (serial_id);
- struct TALER_WIRE_TransferDetails wd;
-
- switch (http_status) {
- case MHD_HTTP_OK:
- {
- char *subject;
- char *space;
-
- wd.amount = details->amount;
- wd.execution_date = details->execution_date;
- subject = GNUNET_strdup (details->wire_transfer_subject);
- space = strchr (subject, (int) ' ');
- if (NULL != space)
- {
- /* Space separates the actual wire transfer subject from the
- exchange base URL (if present, expected only for outgoing
- transactions). So we cut the string off at the space. */
- *space = '\0';
- }
- /* NOTE: For a real bank, the subject should include a checksum! */
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (subject,
- strlen (subject),
- &wd.wtid,
- sizeof (wd.wtid)))
- {
- /* Ill-formed wire subject, set binary version to all zeros
- and pass as a string, this time including the part after
- the space. */
- memset (&wd.wtid,
- 0,
- sizeof (wd.wtid));
- wd.wtid_s = details->wire_transfer_subject;
- }
- else
- {
- wd.wtid_s = NULL;
- }
- GNUNET_free (subject);
- wd.account_details = details->account_details;
-
- if ( (NULL != whh->hres_cb) &&
- (GNUNET_OK !=
- whh->hres_cb (whh->hres_cb_cls,
- TALER_EC_NONE,
- dir,
- &bserial_id,
- sizeof (bserial_id),
- &wd)) )
- whh->hres_cb = NULL;
- break;
- }
- case MHD_HTTP_NO_CONTENT:
- if (NULL != whh->hres_cb)
- (void) whh->hres_cb (whh->hres_cb_cls,
- ec,
- TALER_BANK_DIRECTION_NONE,
- NULL,
- 0,
- NULL);
- GNUNET_free (whh);
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bank failed with HTTP status %u (EC: %u)\n",
- http_status,
- ec);
- if (NULL != whh->hres_cb)
- (void) whh->hres_cb (whh->hres_cb_cls,
- ec,
- TALER_BANK_DIRECTION_NONE,
- NULL,
- 0,
- NULL);
- GNUNET_free (whh);
- break;
- }
-}
-
-
-/**
- * Query transfer history of an account. We use the variable-size
- * @a start_off to indicate which transfers we are interested in as
- * different banking systems may have different ways to identify
- * transfers. The @a start_off value must thus match the value of
- * a `row_off` argument previously given to the @a hres_cb. Use
- * NULL to query transfers from the beginning of time (with
- * positive @a num_results) or from the latest committed transfers
- * (with negative @a num_results).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param direction what kinds of wire transfers should be returned
- * @param start_off from which row on do we want to get results, use NULL for the latest; exclusive
- * @param start_off_len number of bytes in @a start_off; must be `sizeof(uint64_t)`.
- * @param num_results how many results do we want; negative numbers to go into the past,
- * positive numbers to go into the future starting at @a start_row;
- * must not be zero.
- * @param hres_cb the callback to call with the transaction history
- * @param hres_cb_cls closure for the above callback
- */
-static struct TALER_WIRE_HistoryHandle *
-test_get_history (void *cls,
- enum TALER_BANK_Direction direction,
- const void *start_off,
- size_t start_off_len,
- int64_t num_results,
- TALER_WIRE_HistoryResultCallback hres_cb,
- void *hres_cb_cls)
-{
- struct TestClosure *tc = cls;
- struct TALER_WIRE_HistoryHandle *whh;
- const uint64_t *start_off_b64;
- uint64_t start_row;
-
- if (0 == num_results)
- {
- GNUNET_break (0);
- return NULL;
- }
- if (TALER_BANK_DIRECTION_NONE == direction)
- {
- GNUNET_break (0);
- return NULL;
- }
- if ( (NULL != start_off) &&
- (sizeof (uint64_t) != start_off_len) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire plugin 'test' got start offset of wrong size (%llu instead of %llu)\n",
- (unsigned long long) start_off_len, (unsigned long long) sizeof (uint64_t));
- GNUNET_break (0);
- /* Probably something is wrong with the DB, some other component
- * wrote a wrong value to it. Instead of completely stopping to work,
- * we just scan from the beginning. */
- start_off = NULL;
- }
- if (NULL == start_off)
- {
- start_row = UINT64_MAX; /* no start row */
- }
- else
- {
- start_off_b64 = start_off;
- start_row = GNUNET_ntohll (*start_off_b64);
- }
-
- whh = GNUNET_new (struct TALER_WIRE_HistoryHandle);
- whh->hres_cb = hres_cb;
- whh->hres_cb_cls = hres_cb_cls;
- whh->hh = TALER_BANK_history (tc->ctx,
- tc->bank_url,
- &tc->auth,
- (uint64_t) tc->exchange_account_no,
- direction,
- start_row,
- num_results,
- &bhist_cb,
- whh);
- if (NULL == whh->hh)
- {
- GNUNET_break (0);
- GNUNET_free (whh);
- return NULL;
- }
-
- return whh;
-}
-
-
-/**
- * Cancel going over the account's history.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param whh operation to cancel
- */
-static void
-test_get_history_cancel (void *cls,
- struct TALER_WIRE_HistoryHandle *whh)
-{
- TALER_BANK_history_cancel (whh->hh);
- GNUNET_free (whh);
-}
-
-
-/**
- * Context for a rejection operation.
- */
-struct TALER_WIRE_RejectHandle
-{
- /**
- * Function to call with the result.
- */
- TALER_WIRE_RejectTransferCallback rej_cb;
-
- /**
- * Closure for @e rej_cb.
- */
- void *rej_cb_cls;
-
- /**
- * Handle for the reject operation.
- */
- struct TALER_BANK_RejectHandle *brh;
-};
-
-
-/**
- * Callbacks of this type are used to serve the result of asking
- * the bank to reject an incoming wire transfer.
- *
- * @param cls closure
- * @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for successful status request;
- * #MHD_HTTP_NOT_FOUND if the rowid is unknown;
- * 0 if the bank's reply is bogus (fails to follow the protocol),
- * @param ec detailed error code
- */
-static void
-reject_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec)
-{
- struct TALER_WIRE_RejectHandle *rh = cls;
-
- rh->brh = NULL;
- rh->rej_cb (rh->rej_cb_cls,
- ec);
- GNUNET_free (rh);
-}
-
-
-/**
- * Reject an incoming wire transfer that was obtained from the
- * history. This function can be used to transfer funds back to
- * the sender if the WTID was malformed (i.e. due to a typo).
- *
- * Calling `reject_transfer` twice on the same wire transfer should
- * be idempotent, i.e. not cause the funds to be wired back twice.
- * Furthermore, the transfer should henceforth be removed from the
- * results returned by @e get_history.
- *
- * @param cls plugin's closure
- * @param start_off offset of the wire transfer in plugin-specific format
- * @param start_off_len number of bytes in @a start_off
- * @param rej_cb function to call with the result of the operation
- * @param rej_cb_cls closure for @a rej_cb
- * @return handle to cancel the operation
- */
-static struct TALER_WIRE_RejectHandle *
-test_reject_transfer (void *cls,
- const void *start_off,
- size_t start_off_len,
- TALER_WIRE_RejectTransferCallback rej_cb,
- void *rej_cb_cls)
-{
- struct TestClosure *tc = cls;
- const uint64_t *rowid_b64 = start_off;
- struct TALER_WIRE_RejectHandle *rh;
-
- if (sizeof (uint64_t) != start_off_len)
- {
- GNUNET_break (0);
- return NULL;
- }
- rh = GNUNET_new (struct TALER_WIRE_RejectHandle);
- rh->rej_cb = rej_cb;
- rh->rej_cb_cls = rej_cb_cls;
- rh->brh = TALER_BANK_reject (tc->ctx,
- tc->bank_url,
- &tc->auth,
- (uint64_t) tc->exchange_account_no,
- GNUNET_ntohll (*rowid_b64),
- &reject_cb,
- rh);
- if (NULL == rh->brh)
- {
- GNUNET_free (rh);
- return NULL;
- }
- return rh;
-}
-
-
-/**
- * Cancel ongoing reject operation. Note that the rejection may still
- * proceed. Basically, if this function is called, the rejection may
- * have happened or not. This function is usually used during shutdown
- * or system upgrades. At a later point, the application must call
- * @e reject_transfer again for this wire transfer, unless the
- * @e get_history shows that the wire transfer no longer exists.
- *
- * @param cls plugins' closure
- * @param rh operation to cancel
- * @return closure of the callback of the operation
- */
-static void *
-test_reject_transfer_cancel (void *cls,
- struct TALER_WIRE_RejectHandle *rh)
-{
- void *ret = rh->rej_cb_cls;
-
- if (NULL != rh->brh)
- TALER_BANK_reject_cancel (rh->brh);
- GNUNET_free (rh);
- return ret;
-}
-
-
-/**
- * Initialize test-wire subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
- */
-void *
-libtaler_plugin_wire_test_init (void *cls)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct TestClosure *tc;
- struct TALER_WIRE_Plugin *plugin;
- char *user;
- char *pass;
-
- tc = GNUNET_new (struct TestClosure);
- if (NULL != cfg)
- {
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange-wire-test",
- "BANK_URL",
- &tc->bank_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange-wire-test",
- "BANK_URL");
- GNUNET_free (tc);
- return NULL;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
- "exchange-wire-test",
- "EXCHANGE_ACCOUNT_NUMBER",
- &tc->exchange_account_no))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange-wire-test",
- "EXCHANGE_ACCOUNT_NUMBER");
- GNUNET_free (tc->bank_url);
- GNUNET_free (tc);
- return NULL;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "taler",
- "CURRENCY",
- &tc->currency))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler",
- "CURRENCY");
- GNUNET_free (tc->bank_url);
- GNUNET_free (tc);
- return NULL;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange-wire-test",
- "USERNAME",
- &user))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange-wire-test",
- "USERNAME");
- GNUNET_free (tc->bank_url);
- GNUNET_free (tc);
- return NULL;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange-wire-test",
- "PASSWORD",
- &pass))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange-wire-test",
- "PASSWORD");
- GNUNET_free (tc->bank_url);
- GNUNET_free (tc);
- GNUNET_free (user);
- return NULL;
- }
- tc->auth.method = TALER_BANK_AUTH_BASIC;
- tc->auth.details.basic.username = user;
- tc->auth.details.basic.password = pass;
- tc->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
- &tc->rc);
- tc->rc = GNUNET_CURL_gnunet_rc_create (tc->ctx);
- if (NULL == tc->ctx)
- {
- GNUNET_break (0);
- GNUNET_free (tc->currency);
- GNUNET_free (tc->bank_url);
- GNUNET_free (tc->auth.details.basic.username);
- GNUNET_free (tc->auth.details.basic.password);
- GNUNET_free (tc);
- return NULL;
- }
- }
- plugin = GNUNET_new (struct TALER_WIRE_Plugin);
- plugin->cls = tc;
- plugin->amount_round = &test_amount_round;
- plugin->get_wire_details = &test_get_wire_details;
- plugin->sign_wire_details = &test_sign_wire_details;
- plugin->wire_validate = &test_wire_validate;
- plugin->prepare_wire_transfer = &test_prepare_wire_transfer;
- plugin->prepare_wire_transfer_cancel = &test_prepare_wire_transfer_cancel;
- plugin->execute_wire_transfer = &test_execute_wire_transfer;
- plugin->execute_wire_transfer_cancel = &test_execute_wire_transfer_cancel;
- plugin->get_history = &test_get_history;
- plugin->get_history_cancel = &test_get_history_cancel;
- plugin->reject_transfer = &test_reject_transfer;
- plugin->reject_transfer_cancel = &test_reject_transfer_cancel;
- return plugin;
-}
-
-
-/**
- * Shutdown Test wire subsystem.
- *
- * @param cls a `struct TALER_WIRE_Plugin`
- * @return NULL (always)
- */
-void *
-libtaler_plugin_wire_test_done (void *cls)
-{
- struct TALER_WIRE_Plugin *plugin = cls;
- struct TestClosure *tc = plugin->cls;
-
- if (NULL != tc->ctx)
- {
- GNUNET_CURL_fini (tc->ctx);
- tc->ctx = NULL;
- }
- if (NULL != tc->rc)
- {
- GNUNET_CURL_gnunet_rc_destroy (tc->rc);
- tc->rc = NULL;
- }
- switch (tc->auth.method)
- {
- case TALER_BANK_AUTH_NONE:
- break;
- case TALER_BANK_AUTH_BASIC:
- if (NULL != tc->auth.details.basic.username)
- {
- GNUNET_free (tc->auth.details.basic.username);
- tc->auth.details.basic.username = NULL;
- }
- if (NULL != tc->auth.details.basic.password)
- {
- GNUNET_free (tc->auth.details.basic.password);
- tc->auth.details.basic.password = NULL;
- }
- break;
- }
- GNUNET_free_non_null (tc->currency);
- GNUNET_free_non_null (tc->bank_url);
- GNUNET_free (tc);
- GNUNET_free (plugin);
- return NULL;
-}
-
-/* end of plugin_wire_test.c */
diff --git a/src/wire/test_sepa_wireformat.c b/src/wire/test_sepa_wireformat.c
deleted file mode 100644
index 07a3784c6..000000000
--- a/src/wire/test_sepa_wireformat.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015, 2016 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 wire/test_sepa_wireformat.c
- * @brief Tests for JSON SEPA format validation
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- */
-
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-
-
-/* Valid SEPA data */
-static const char * const valid_wire_str =
- "{ \"type\":\"SEPA\", \
-\"iban\":\"DE67830654080004822650\", \
-\"name\":\"GNUnet e.V.\", \
-\"bic\":\"GENODEF1SLR\", \
-\"salt\":\"123456789\", \
-\"address\": \"foobar\"}";
-
-/* IBAN has wrong country code */
-static const char * const invalid_wire_str =
- "{ \"type\":\"SEPA\", \
-\"iban\":\"XX67830654080004822650\", \
-\"name\":\"GNUnet e.V.\", \
-\"bic\":\"GENODEF1SLR\", \
-\"salt\":\"123456789\", \
-\"address\": \"foobar\"}";
-
-/* IBAN has wrong checksum */
-static const char * const invalid_wire_str2 =
- "{ \"type\":\"SEPA\", \
-\"iban\":\"DE67830654080004822651\", \
-\"name\":\"GNUnet e.V.\", \
-\"bic\":\"GENODEF1SLR\", \
-\"salt\":\"123456789\", \
-\"address\": \"foobar\"}";
-
-/* Unsupported wireformat type */
-static const char * const unsupported_wire_str =
- "{ \"type\":\"unsupported\", \
-\"iban\":\"DE67830654080004822650\", \
-\"name\":\"GNUnet e.V.\", \
-\"bic\":\"GENODEF1SLR\", \
-\"salt\":\"123456789\", \
-\"address\": \"foobar\"}";
-
-
-int
-main(int argc,
- const char *const argv[])
-{
- json_t *wire;
- char *emsg;
- json_error_t error;
- int ret;
- struct GNUNET_CONFIGURATION_Handle *cfg;
- struct TALER_WIRE_Plugin *plugin;
-
- GNUNET_log_setup ("test-sepa-wireformats",
- "WARNING",
- NULL);
- cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_CONFIGURATION_set_value_string (cfg,
- "taler",
- "currency",
- "EUR");
- plugin = TALER_WIRE_plugin_load (cfg,
- "sepa");
- GNUNET_assert (NULL != plugin);
- (void) memset(&error, 0, sizeof(error));
- GNUNET_assert (NULL != (wire = json_loads (unsupported_wire_str, 0, NULL)));
- GNUNET_assert (TALER_EC_NONE != plugin->wire_validate (NULL,
- wire,
- NULL,
- &emsg));
- GNUNET_free (emsg);
- json_decref (wire);
- GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str, 0, NULL)));
- GNUNET_assert (TALER_EC_NONE != plugin->wire_validate (NULL,
- wire,
- NULL,
- &emsg));
- GNUNET_free (emsg);
- json_decref (wire);
- GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str2, 0, NULL)));
- GNUNET_assert (TALER_EC_NONE != plugin->wire_validate (NULL,
- wire,
- NULL,
- &emsg));
- GNUNET_free (emsg);
- json_decref (wire);
- GNUNET_assert (NULL != (wire = json_loads (valid_wire_str, 0, &error)));
- ret = plugin->wire_validate (NULL,
- wire,
- NULL,
- &emsg);
- json_decref (wire);
- TALER_WIRE_plugin_unload (plugin);
- GNUNET_CONFIGURATION_destroy (cfg);
- if (TALER_EC_NONE != ret)
- return 1;
- return 0;
-}
diff --git a/src/wire/test_wire_plugin.c b/src/wire/test_wire_plugin.c
deleted file mode 100644
index f5dba01aa..000000000
--- a/src/wire/test_wire_plugin.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015, 2016, 2017 GNUnet e.V. and Inria
-
- 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 wire/test_wire_plugin.c
- * @brief Tests for wire plugins
- * @author Christian Grothoff
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-#include "taler_wire_plugin.h"
-#include <gnunet/gnunet_json_lib.h>
-#include <jansson.h>
-
-
-/**
- * Definitions for a test with a plugin.
- */
-struct TestBlock {
-
- /**
- * Name of the plugin to test.
- */
- const char *plugin_name;
-
- /**
- * JSON template expected by the plugin for an account definition.
- */
- const char *json_proto;
-
- /**
- * Amount to give to the rounding function.
- */
- const char *round_in;
-
- /**
- * Expected result from rounding.
- */
- const char *round_out;
-
- /**
- * Currency to give to the plugin.
- */
- const char *currency;
-};
-
-
-/**
- * List of plugins and (unsigned) JSON account definitions
- * to use for the tests.
- */
-static struct TestBlock tests[] = {
- {
- .plugin_name = "sepa",
- .json_proto = "{ \"type\":\"sepa\", \"iban\":\"DE67830654080004822650\", \"name\":\"GNUnet e.V.\", \"bic\":\"GENODEF1SLR\" }",
- .round_in = "EUR:0.123456",
- .round_out = "EUR:0.12",
- .currency = "EUR"
- },
- {
- .plugin_name = "test",
- .json_proto = "{ \"type\":\"test\", \"bank_url\":\"http://localhost/\", \"account_number\":42 }",
- .round_in = "KUDOS:0.123456",
- .round_out = "KUDOS:0.12",
- .currency = "KUDOS"
- },
- {
- NULL, NULL, NULL, NULL, NULL
- }
-};
-
-
-/**
- * Private key used to sign wire details.
- */
-static struct TALER_MasterPrivateKeyP priv_key;
-
-/**
- * Public key matching #priv_key.
- */
-static struct TALER_MasterPublicKeyP pub_key;
-
-/**
- * Our configuration.
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-
-/**
- * Run the test.
- *
- * @param test details of the test
- * @param plugin plugin to test
- * @param wire wire details for testing
- * @return #GNUNET_OK on success
- */
-static int
-run_test (const struct TestBlock *test,
- struct TALER_WIRE_Plugin *plugin,
- json_t *wire)
-{
- struct GNUNET_HashCode salt;
- struct TALER_MasterSignatureP sig;
- json_t *lwire;
- struct TALER_Amount in;
- struct TALER_Amount expect;
- char *emsg;
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &salt,
- sizeof (salt));
- if (GNUNET_OK !=
- plugin->sign_wire_details (plugin->cls,
- wire,
- &priv_key,
- &salt,
- &sig))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- json_object_set_new (wire,
- "salt",
- GNUNET_JSON_from_data (&salt,
- sizeof (salt)));
- json_object_set_new (wire,
- "sig",
- GNUNET_JSON_from_data (&sig,
- sizeof (sig)));
- if (TALER_EC_NONE !=
- plugin->wire_validate (plugin->cls,
- wire,
- &pub_key,
- &emsg))
- {
- GNUNET_break (0);
- GNUNET_free (emsg);
- return GNUNET_SYSERR;
- }
- /* load wire details from file */
- lwire = plugin->get_wire_details (plugin->cls,
- cfg,
- test->plugin_name);
- if (NULL == lwire)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (TALER_EC_NONE !=
- plugin->wire_validate (plugin->cls,
- lwire,
- &pub_key,
- &emsg))
- {
- GNUNET_break (0);
- GNUNET_free (emsg);
- json_decref (lwire);
- return GNUNET_SYSERR;
- }
- json_decref (lwire);
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (test->round_in,
- &in));
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (test->round_out,
- &expect));
- if (GNUNET_OK !=
- plugin->amount_round (plugin->cls,
- &in))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (0 != TALER_amount_cmp (&in, &expect))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_NO !=
- plugin->amount_round (plugin->cls,
- &in))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- memset (&in, 0, sizeof (in));
- GNUNET_log_skip (GNUNET_ERROR_TYPE_ERROR, 1);
- if (GNUNET_SYSERR !=
- plugin->amount_round (plugin->cls,
- &in))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-int
-main (int argc,
- const char *const argv[])
-{
- json_t *wire;
- int ret;
- struct TALER_WIRE_Plugin *plugin;
- const struct TestBlock *test;
- unsigned int i;
- struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
-
- GNUNET_log_setup ("test-wire-plugin",
- "WARNING",
- NULL);
- cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONFIGURATION_load (cfg,
- "test_wire_plugin.conf"));
- pk = GNUNET_CRYPTO_eddsa_key_create_from_file ("test_wire_plugin_key.priv");
- priv_key.eddsa_priv = *pk;
- GNUNET_free (pk);
- GNUNET_CRYPTO_eddsa_key_get_public (&priv_key.eddsa_priv,
- &pub_key.eddsa_pub);
- ret = GNUNET_OK;
- for (i=0;NULL != (test = &tests[i])->plugin_name;i++)
- {
- GNUNET_CONFIGURATION_set_value_string (cfg,
- "taler",
- "CURRENCY",
- test->currency);
- plugin = TALER_WIRE_plugin_load (cfg,
- test->plugin_name);
- GNUNET_assert (NULL != plugin);
- wire = json_loads (test->json_proto, 0, NULL);
- GNUNET_assert (NULL != wire);
- ret = run_test (test, plugin, wire);
- json_decref (wire);
- TALER_WIRE_plugin_unload (plugin);
- if (GNUNET_OK != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "%s FAILED\n",
- test->plugin_name);
- break;
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- "%s PASS\n",
- test->plugin_name);
- }
- }
- GNUNET_CONFIGURATION_destroy (cfg);
- if (GNUNET_OK != ret)
- return 1;
- return 0;
-}
diff --git a/src/wire/test_wire_plugin.conf b/src/wire/test_wire_plugin.conf
deleted file mode 100644
index 90b4f0749..000000000
--- a/src/wire/test_wire_plugin.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-# This file is in the public domain.
-#
-[test]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = test_wire_plugin_test.json
-
-[sepa]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-SEPA_RESPONSE_FILE = test_wire_plugin_sepa.json
-
-
-[exchange-wire-test]
-# For transfers made by the exchange, we need to know
-# the URL of the bank (where the /admin/add/incoming API
-# is avaialble).
-BANK_URL = http://localhost/
-
-[taler]
-CURRENCY = "EUR"
diff --git a/src/wire/test_wire_plugin_key.priv b/src/wire/test_wire_plugin_key.priv
deleted file mode 100644
index 26b4f26f6..000000000
--- a/src/wire/test_wire_plugin_key.priv
+++ /dev/null
@@ -1 +0,0 @@
-?Sgb@Js; %aKȉs_Hў \ No newline at end of file
diff --git a/src/wire/test_wire_plugin_sepa.json b/src/wire/test_wire_plugin_sepa.json
deleted file mode 100644
index 175345f0c..000000000
--- a/src/wire/test_wire_plugin_sepa.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "salt": "32V01R7K4T02S74PZZMVXRQ1K7FR948RBNB9BJ5Z101HEQFH7CW7J82006GY3BPTGQ4FM775PSSRD3K9MY97HSNVVCGEVBPVSAQ2710",
- "type": "sepa",
- "iban": "DE67830654080004822650",
- "sig": "K48GPPM715ZXX0DC597WESD5ECT3R0B3TAFQMB68SBF4K5CZ5KCE9NESN1JX412SPZ82PSV7JAPVJFXDDTZ63YV4295S5RC28E4221G",
- "name": "GNUnet e.V.",
- "bic": "GENODEF1SLR"
-} \ No newline at end of file
diff --git a/src/wire/test_wire_plugin_test.json b/src/wire/test_wire_plugin_test.json
deleted file mode 100644
index e5a0c3329..000000000
--- a/src/wire/test_wire_plugin_test.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "type": "test",
- "bank_url": "http://localhost/",
- "sig": "KX1CMHNFH1WE10244AEF07AXHJCF9PZDZVNZBC9P4EJEQ1MH1Y3C2TWF08VTQMK4N5TCV0V1VTGWSV0WB8TB9YQRZW87F5A6KCEZ81R",
- "account_number": 42,
- "salt": "EZV905MQPVAZEMGC6SEZQF2Z75P6ZKTN8TX00JHN11S7J81DQ78G8Z551K6TGR9WHPP0JW1X9J9X9CVRY48JTHBCP6Q4XKJ6R2G18G0"
-}
diff --git a/src/wire/test_wire_plugin_transactions_test.c b/src/wire/test_wire_plugin_transactions_test.c
deleted file mode 100644
index ccfde1b40..000000000
--- a/src/wire/test_wire_plugin_transactions_test.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015, 2016, 2017 GNUnet e.V. and Inria
-
- 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 wire/test_wire_plugin_transactions_test.c
- * @brief Tests performing actual transactions with the TEST wire plugin against FAKEBANK
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-#include "taler_wire_plugin.h"
-#include "taler_fakebank_lib.h"
-#include <gnunet/gnunet_json_lib.h>
-#include <jansson.h>
-
-
-/**
- * When does the test timeout? Right now, we expect this to be very
- * fast.
- */
-#define TIMEOUT GNUNET_TIME_UNIT_SECONDS
-
-
-/**
- * Input for the wire transfer details.
- */
-static const char *json_proto =
- "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8088/\", \"account_number\":42 }";
-
-
-/**
- * Private key used to sign wire details.
- */
-static struct TALER_MasterPrivateKeyP priv_key;
-
-/**
- * Public key matching #priv_key.
- */
-static struct TALER_MasterPublicKeyP pub_key;
-
-/**
- * Our configuration.
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Set to #GNUNET_SYSERR if the test failed.
- */
-static int global_ret;
-
-/**
- * The 'test' plugin that we are using for the test.
- */
-static struct TALER_WIRE_Plugin *plugin;
-
-/**
- * Active preparation handle, or NULL if not active.
- */
-static struct TALER_WIRE_PrepareHandle *ph;
-
-/**
- * Active execution handle, or NULL if not active.
- */
-static struct TALER_WIRE_ExecuteHandle *eh;
-
-/**
- * Handle to the bank.
- */
-static struct TALER_FAKEBANK_Handle *fb;
-
-/**
- * Handle to the history request.
- */
-static struct TALER_WIRE_HistoryHandle *hh;
-
-/**
- * Handle for the timeout task.
- */
-static struct GNUNET_SCHEDULER_Task *tt;
-
-/**
- * Which serial ID do we expect to get from /history?
- */
-static uint64_t serial_target;
-
-/**
- * Wire transfer identifier we are using.
- */
-static struct TALER_WireTransferIdentifierRawP wtid;
-
-
-/**
- * Function called on shutdown (regular, error or CTRL-C).
- *
- * @param cls NULL
- */
-static void
-do_shutdown (void *cls)
-{
- TALER_FAKEBANK_stop (fb);
- fb = NULL;
- if (NULL != eh)
- {
- plugin->execute_wire_transfer_cancel (plugin->cls,
- eh);
- eh = NULL;
- }
- if (NULL != ph)
- {
- plugin->prepare_wire_transfer_cancel (plugin->cls,
- ph);
- ph = NULL;
- }
- if (NULL != hh)
- {
- plugin->get_history_cancel (plugin->cls,
- hh);
- hh = NULL;
- }
- if (NULL != tt)
- {
- GNUNET_SCHEDULER_cancel (tt);
- tt = NULL;
- }
- TALER_WIRE_plugin_unload (plugin);
-}
-
-
-/**
- * Function called on timeout.
- *
- * @param cls NULL
- */
-static void
-timeout_cb (void *cls)
-{
- tt = NULL;
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Callbacks of this type are used to serve the result of asking
- * the bank for the transaction history.
- *
- * @param cls closure
- * @param ec taler status code
- * @param dir direction of the transfer
- * @param row_off identification of the position at which we are querying
- * @param row_off_size number of bytes in @a row_off
- * @param details details about the wire transfer
- * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
- */
-static int
-history_result_cb (void *cls,
- enum TALER_ErrorCode ec,
- enum TALER_BANK_Direction dir,
- const void *row_off,
- size_t row_off_size,
- const struct TALER_WIRE_TransferDetails *details)
-{
- uint64_t *serialp;
- uint64_t serialh;
- struct TALER_Amount amount;
-
- hh = NULL;
- if ( (TALER_BANK_DIRECTION_NONE == dir) &&
- (GNUNET_OK == global_ret) )
- {
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_OK;
- }
- if (sizeof (uint64_t) != row_off_size)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- serialp = (uint64_t *) row_off;
- serialh = GNUNET_ntohll (*serialp);
- if (serialh != serial_target)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount ("KUDOS:5.01",
- &amount));
- if (0 != TALER_amount_cmp (&amount,
- &details->amount))
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- if (0 != memcmp (&wtid,
- &details->wtid,
- sizeof (struct TALER_WireTransferIdentifierRawP)))
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- global_ret = GNUNET_OK;
- return GNUNET_OK;
-}
-
-
-/**
- * Function called with the result from the execute step.
- *
- * @param cls closure
- * @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure
- * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-confirmation_cb (void *cls,
- int success,
- uint64_t serial_id,
- const char *emsg)
-{
- eh = NULL;
- if (GNUNET_OK != success)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- serial_target = serial_id;
- hh = plugin->get_history (plugin->cls,
- TALER_BANK_DIRECTION_BOTH,
- NULL, 0,
- 5,
- &history_result_cb,
- NULL);
-}
-
-
-/**
- * Callback with prepared transaction.
- *
- * @param cls closure
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
- const char *buf,
- size_t buf_size)
-{
- ph = NULL;
- if (NULL == buf)
- {
- GNUNET_break (0);
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- plugin->execute_wire_transfer (plugin->cls,
- buf,
- buf_size,
- &confirmation_cb,
- NULL);
-}
-
-
-/**
- * Run the test.
- *
- * @param cls NULL
- */
-static void
-run (void *cls)
-{
- json_t *wire;
- struct TALER_Amount amount;
-
- GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
- NULL);
- tt = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
- &timeout_cb,
- NULL);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
- &wtid,
- sizeof (wtid));
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount ("KUDOS:5.01",
- &amount));
- wire = json_loads (json_proto,
- 0,
- NULL);
- fb = TALER_FAKEBANK_start (8088);
- ph = plugin->prepare_wire_transfer (plugin->cls,
- wire,
- &amount,
- "https://exchange.net/",
- &wtid,
- &prepare_cb,
- NULL);
- json_decref (wire);
-}
-
-
-int
-main (int argc,
- const char *const argv[])
-{
- struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
-
- GNUNET_log_setup ("test-wire-plugin-transactions-test",
- "WARNING",
- NULL);
- cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONFIGURATION_load (cfg,
- "test_wire_plugin_transactions_test.conf"));
- pk = GNUNET_CRYPTO_eddsa_key_create_from_file ("test_wire_plugin_key.priv");
- priv_key.eddsa_priv = *pk;
- GNUNET_free (pk);
- GNUNET_CRYPTO_eddsa_key_get_public (&priv_key.eddsa_priv,
- &pub_key.eddsa_pub);
- global_ret = GNUNET_OK;
- plugin = TALER_WIRE_plugin_load (cfg,
- "test");
- GNUNET_assert (NULL != plugin);
- GNUNET_SCHEDULER_run (&run,
- NULL);
- GNUNET_CONFIGURATION_destroy (cfg);
- if (GNUNET_OK != global_ret)
- return 1;
- return 0;
-}
-
-/* end of test_wire_plugin_transactions_test.c */
diff --git a/src/wire/test_wire_plugin_transactions_test.conf b/src/wire/test_wire_plugin_transactions_test.conf
deleted file mode 100644
index 42fb51b79..000000000
--- a/src/wire/test_wire_plugin_transactions_test.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is in the public domain.
-#
-[test]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = test_wire_plugin_test.json
-
-[exchange-wire-test]
-# For transfers made by the exchange, we need to know
-# the URL of the bank (where the /admin/add/incoming API
-# is avaialble).
-BANK_URL= http://localhost:8088/
-
-[taler]
-CURRENCY = "KUDOS"
diff --git a/src/wire/wire-sepa.conf b/src/wire/wire-sepa.conf
deleted file mode 100644
index eb43d3dcc..000000000
--- a/src/wire/wire-sepa.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is in the public domain.
-#
-# Configuration for SEPA wire plugin.
-
-[exchange-wire-sepa]
-# Set to "YES" to activate the 'sepa' plugin.
-ENABLE = NO
-
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/exchange/wire/sepa.json
-
-[exchange-wire-outgoing-sepa]
-# This section should contain the options required for making outgoing
-# SEPA transfers. Not yet supported (need libebics).
diff --git a/src/wire/wire-test.conf b/src/wire/wire-test.conf
deleted file mode 100644
index 7ee217ee1..000000000
--- a/src/wire/wire-test.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file is in the public domain.
-#
-# Configuration for TEST wire plugin.
-#
-[exchange-wire-test]
-# Set to "YES" to activate the 'test' plugin.
-ENABLE = NO
-
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/exchange/wire/test.json
-
-# We need to know the exchange's account number at the bank.
-EXCHANGE_ACCOUNT_NUMBER = 2
-
-# For accessing transfers, we need to know
-# the URL of the bank (where the /history API is available).
-# BANK_URL = https://bank.demo.taler.net/
-
-# Authentication information for basic authentication
-USERNAME = user
-PASSWORD = pass
diff --git a/src/wire/wire.c b/src/wire/wire.c
index 58180b7b1..aeb8689e6 100644
--- a/src/wire/wire.c
+++ b/src/wire/wire.c
@@ -146,80 +146,4 @@ TALER_WIRE_plugin_unload (struct TALER_WIRE_Plugin *plugin)
}
-/**
- * Closure of #check_for_wire.
- */
-struct FindEnabledWireContext
-{
- /**
- * Configuration we are usign.
- */
- const struct GNUNET_CONFIGURATION_Handle *cfg;
-
- /**
- * Callback to invoke.
- */
- TALER_WIRE_EnabledCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-};
-
-
-/**
- * Check if @a section begins with "exchange-wire-", and if
- * so if the "ENABLE" option is set to "YES". If both are
- * true, call the callback from the context with the
- * rest of the section name.
- *
- * @param cls our `struct FindEnabledWireContext`
- * @param section name of a section in the configuration
- */
-static void
-check_for_wire (void *cls,
- const char *section)
-{
- struct FindEnabledWireContext *ctx = cls;
- const char *name;
-
- if (0 != strncasecmp (section,
- "exchange-wire-",
- strlen ("exchange-wire-")))
- return;
- if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (ctx->cfg,
- section,
- "ENABLE"))
- return;
- name = &section[strlen ("exchange-wire-")];
- ctx->cb (ctx->cb_cls,
- name);
-}
-
-
-/**
- * Check which wire plugins are enabled in @a cfg and call @a cb for each one.
- *
- * @param cfg configuration to use
- * @param cb callback to invoke
- * @param cb_cls closure for @a cb
- */
-void
-TALER_WIRE_find_enabled (const struct GNUNET_CONFIGURATION_Handle *cfg,
- TALER_WIRE_EnabledCallback cb,
- void *cb_cls)
-{
- struct FindEnabledWireContext ctx;
-
- ctx.cfg = cfg;
- ctx.cb = cb;
- ctx.cb_cls = cb_cls;
- GNUNET_CONFIGURATION_iterate_sections (cfg,
- &check_for_wire,
- &ctx);
-}
-
-
/* end of wire.c */
diff --git a/src/wire/wire_helper.c b/src/wire/wire_helper.c
new file mode 100644
index 000000000..34d40e11e
--- /dev/null
+++ b/src/wire/wire_helper.c
@@ -0,0 +1,57 @@
+/*
+ This file is part of TALER
+ (C) 2018 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 wire/wire_helper.c
+ * @brief Helper functions for dealing with wire formats
+ * @author Christian Grothoff <christian@grothoff.org>
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_wire_lib.h"
+
+/**
+ * Prefix of PAYTO URLs.
+ */
+#define PAYTO "payto://"
+
+
+/**
+ * Obtain the payment method from a @a payto_url
+ *
+ * @param payto_url the URL to parse
+ * @return NULL on error (malformed @a payto_url)
+ */
+char *
+TALER_WIRE_payto_get_method (const char *payto_url)
+{
+ const char *start;
+ const char *end;
+
+ if (0 != strncmp (payto_url,
+ PAYTO,
+ strlen (PAYTO)))
+ return NULL;
+ start = &payto_url[strlen(PAYTO)];
+ end = strchr (start,
+ (unsigned char) '/');
+ if (NULL == end)
+ return NULL;
+ return GNUNET_strndup (start,
+ end - start);
+}
+
+/* end of wire_helper.c */