summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd.c')
-rw-r--r--src/backend/taler-merchant-httpd.c1335
1 files changed, 295 insertions, 1040 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 86b36306..60979d2e 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2014-2018 Taler Systems SA
+ (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -32,23 +32,8 @@
#include "taler_merchantdb_lib.h"
#include "taler-merchant-httpd.h"
#include "taler-merchant-httpd_auditors.h"
-#include "taler-merchant-httpd_check-payment.h"
#include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_history.h"
#include "taler-merchant-httpd_mhd.h"
-#include "taler-merchant-httpd_order.h"
-#include "taler-merchant-httpd_pay.h"
-#include "taler-merchant-httpd_poll-payment.h"
-#include "taler-merchant-httpd_proposal.h"
-#include "taler-merchant-httpd_refund.h"
-#include "taler-merchant-httpd_refund_increase.h"
-#include "taler-merchant-httpd_refund_lookup.h"
-#include "taler-merchant-httpd_track-transaction.h"
-#include "taler-merchant-httpd_track-transfer.h"
-#include "taler-merchant-httpd_tip-authorize.h"
-#include "taler-merchant-httpd_tip-pickup.h"
-#include "taler-merchant-httpd_tip-query.h"
-#include "taler-merchant-httpd_tip-reserve-helper.h"
#include "taler-merchant-httpd_config.h"
/**
@@ -58,45 +43,26 @@
/**
- * Used by the iterator of the various merchant's instances given
- * in configuration
+ * Which currency do we use?
*/
-struct IterateInstancesCls
-{
-
- /**
- * Current index in the global array of #MerchantInstance
- * types. Used by the callback in order to know which index
- * is associated to the element being processed.
- */
- unsigned int current_index;
-
- /**
- * Flag indicating whether config contains a default instance
- */
- unsigned int default_instance;
+char *TMH_currency;
- /**
- * Tells if the parsing encountered any error. We need this
- * field since the iterator must return void
- */
- unsigned int ret;
-};
+/**
+ * Inform the auditor for all deposit confirmations (global option)
+ */
+int TMH_force_audit;
+/**
+ * Connection handle to the our database
+ */
+struct TALER_MERCHANTDB_Plugin *TMH_db;
/**
* Hashmap pointing at merchant instances by 'id'. An 'id' is
* just a string that identifies a merchant instance. When a frontend
* needs to specify an instance to the backend, it does so by 'id'
*/
-struct GNUNET_CONTAINER_MultiHashMap *by_id_map;
-
-/**
- * Hashmap pointing at merchant instances by public key. This map
- * is mainly used to check whether there is more than one instance
- * using the same key
- */
-struct GNUNET_CONTAINER_MultiHashMap *by_kpub_map;
+static struct GNUNET_CONTAINER_MultiHashMap *by_id_map;
/**
* The port we are running on
@@ -104,55 +70,9 @@ struct GNUNET_CONTAINER_MultiHashMap *by_kpub_map;
static uint16_t port;
/**
- * This value tells the exchange by which date this merchant would like
- * to receive the funds for a deposited payment
- */
-struct GNUNET_TIME_Relative default_wire_transfer_delay;
-
-/**
- * Locations from the configuration. Mapping from
- * label to location data.
- */
-json_t *default_locations;
-
-/**
- * If the frontend does NOT specify a payment deadline, how long should
- * offers we make be valid by default?
- */
-struct GNUNET_TIME_Relative default_pay_deadline;
-
-/**
- * Default maximum wire fee to assume, unless stated differently in the proposal
- * already.
- */
-struct TALER_Amount default_max_wire_fee;
-
-/**
- * Default max deposit fee that the merchant is willing to
- * pay; if deposit costs more, then the customer will cover
- * the difference.
- */
-struct TALER_Amount default_max_deposit_fee;
-
-/**
- * Default factor for wire fee amortization.
- */
-unsigned long long default_wire_fee_amortization;
-
-/**
* Should a "Connection: close" header be added to each HTTP response?
*/
-static int TMH_merchant_connection_close;
-
-/**
- * Which currency do we use?
- */
-char *TMH_currency;
-
-/**
- * Inform the auditor for all deposit confirmations (global option)
- */
-int TMH_force_audit;
+static int merchant_connection_close;
/**
* Task running the HTTP server.
@@ -165,11 +85,6 @@ static struct GNUNET_SCHEDULER_Task *mhd_task;
static int result;
/**
- * Connection handle to the our database
- */
-struct TALER_MERCHANTDB_Plugin *db;
-
-/**
* The MHD Daemon
*/
static struct MHD_Daemon *mhd;
@@ -178,39 +93,39 @@ static struct MHD_Daemon *mhd;
* MIN-Heap of suspended connections to resume when the timeout expires,
* ordered by timeout. Values are of type `struct MHD_Connection`
*/
-struct GNUNET_CONTAINER_Heap *resume_timeout_heap;
+static struct GNUNET_CONTAINER_Heap *resume_timeout_heap;
/**
* Hash map from H(order_id,merchant_pub) to `struct MHD_Connection`
* entries to resume when a payment is made for the given order.
*/
-struct GNUNET_CONTAINER_MultiHashMap *payment_trigger_map;
+static struct GNUNET_CONTAINER_MultiHashMap *payment_trigger_map;
/**
* Task responsible for timeouts in the #resume_timeout_heap.
*/
-struct GNUNET_SCHEDULER_Task *resume_timeout_task;
+static struct GNUNET_SCHEDULER_Task *resume_timeout_task;
/**
* Our configuration.
*/
-static struct GNUNET_CONFIGURATION_Handle *cfg;
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
/**
- * Callback that frees all the elements in the hashmap
+ * Callback that frees all the instances in the hashmap
*
* @param cls closure, NULL
* @param key current key
- * @param value a `struct MerchantInstance`
+ * @param value a `struct TMH_MerchantInstance`
*/
static int
-hashmap_free (void *cls,
- const struct GNUNET_HashCode *key,
- void *value)
+instance_free (void *cls,
+ const struct GNUNET_HashCode *key,
+ void *value)
{
- struct MerchantInstance *mi = value;
- struct WireMethod *wm;
+ struct TMH_MerchantInstance *mi = value;
+ struct TMH_WireMethod *wm;
(void) cls;
(void) key;
@@ -266,10 +181,10 @@ payment_trigger_free (void *cls,
* @param mpub an instance public key
* @param key[out] set to the hash map key to use
*/
-void
-TMH_compute_pay_key (const char *order_id,
- const struct TALER_MerchantPublicKeyP *mpub,
- struct GNUNET_HashCode *key)
+static void
+compute_pay_key (const char *order_id,
+ const struct TALER_MerchantPublicKeyP *mpub,
+ struct GNUNET_HashCode *key)
{
size_t olen = strlen (order_id);
char buf[sizeof (*mpub) + olen];
@@ -287,7 +202,6 @@ TMH_compute_pay_key (const char *order_id,
"Pay key for %s is %s\n",
order_id,
GNUNET_h2s (key));
-
}
@@ -332,14 +246,21 @@ do_resume (void *cls)
/**
* Suspend connection from @a sc until payment has been received.
*
+ * @param order_id the order that we are waiting on
+ * @param mi the merchant instance we are waiting on
* @param sc connection to suspend
* @param min_refund refund amount we are waiting on to be exceeded before resuming,
* NULL if we are not waiting for refunds
*/
void
-TMH_long_poll_suspend (struct TMH_SuspendedConnection *sc,
+TMH_long_poll_suspend (const char *order_id,
+ const struct TMH_MerchantInstance *mi,
+ struct TMH_SuspendedConnection *sc,
const struct TALER_Amount *min_refund)
{
+ compute_pay_key (order_id,
+ &mi->pubkey,
+ &sc->key);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Suspending operation on key %s\n",
GNUNET_h2s (&sc->key));
@@ -350,7 +271,7 @@ TMH_long_poll_suspend (struct TMH_SuspendedConnection *sc,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
if (NULL != min_refund)
{
- sc->awaiting_refund = GNUNET_YES;
+ sc->awaiting_refund = true;
sc->refund_expected = *min_refund;
}
sc->hn = GNUNET_CONTAINER_heap_insert (resume_timeout_heap,
@@ -385,7 +306,7 @@ resume_operation (void *cls,
const struct TALER_Amount *have_refund = cls;
struct TMH_SuspendedConnection *sc = value;
- if ( (GNUNET_YES == sc->awaiting_refund) &&
+ if ( (sc->awaiting_refund) &&
( (NULL == have_refund) ||
(1 != TALER_amount_cmp (have_refund,
&sc->refund_expected)) ) )
@@ -415,20 +336,20 @@ resume_operation (void *cls,
* Find out if we have any clients long-polling for @a order_id to be
* confirmed at merchant @a mpub, and if so, tell them to resume.
*
- * @param order_id the order that was paid
- * @param mpub the merchant's public key of the instance where the payment happened
+ * @param order_id the order that was paid or refunded
+ * @param mi the merchant instance where the payment or refund happened
* @param have_refund refunded amount, NULL if there was no refund
*/
void
TMH_long_poll_resume (const char *order_id,
- const struct TALER_MerchantPublicKeyP *mpub,
+ const struct TMH_MerchantInstance *mi,
const struct TALER_Amount *have_refund)
{
struct GNUNET_HashCode key;
- TMH_compute_pay_key (order_id,
- mpub,
- &key);
+ compute_pay_key (order_id,
+ &mi->pubkey,
+ &key);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Resuming operations suspended pending payment on key %s\n",
GNUNET_h2s (&key));
@@ -443,73 +364,6 @@ TMH_long_poll_resume (const char *order_id,
/**
- * Create a taler://pay/ URI for the given @a con and @a order_id
- * and @a session_id and @a instance_id.
- *
- * @param con HTTP connection
- * @param order_id the order id
- * @param session_id session, may be NULL
- * @param instance_id instance, may be "default"
- * @return corresponding taler://pay/ URI, or NULL on missing "host"
- */
-char *
-TMH_make_taler_pay_uri (struct MHD_Connection *con,
- const char *order_id,
- const char *session_id,
- const char *instance_id)
-{
- const char *host;
- const char *forwarded_host;
- const char *uri_path;
- const char *uri_instance_id;
- const char *query;
- char *result;
-
- host = MHD_lookup_connection_value (con,
- MHD_HEADER_KIND,
- "Host");
- forwarded_host = MHD_lookup_connection_value (con,
- MHD_HEADER_KIND,
- "X-Forwarded-Host");
-
- uri_path = MHD_lookup_connection_value (con,
- MHD_HEADER_KIND,
- "X-Forwarded-Prefix");
- if (NULL == uri_path)
- uri_path = "-";
- if (NULL != forwarded_host)
- host = forwarded_host;
- if (0 == strcmp (instance_id,
- "default"))
- uri_instance_id = "-";
- else
- uri_instance_id = instance_id;
- if (NULL == host)
- {
- /* Should never happen, at least the host header should be defined */
- GNUNET_break (0);
- return NULL;
- }
-
- if (GNUNET_YES == TALER_mhd_is_https (con))
- query = "";
- else
- query = "?insecure=1";
- GNUNET_assert (NULL != order_id);
- GNUNET_assert (0 < GNUNET_asprintf (&result,
- "taler://pay/%s/%s/%s/%s%s%s%s",
- host,
- uri_path,
- uri_instance_id,
- order_id,
- (NULL == session_id) ? "" : "/",
- (NULL == session_id) ? "" : session_id,
- query));
- return result;
-}
-
-
-/**
* Shutdown task (magically invoked when the application is being
* quit)
*
@@ -521,10 +375,12 @@ do_shutdown (void *cls)
struct TMH_SuspendedConnection *sc;
(void) cls;
- MH_force_pc_resume ();
- MH_force_trh_resume ();
- MH_force_refund_resume ();
- MH_force_tip_pickup_resume ();
+#if 0
+ TMH_force_pc_resume ();
+ TMH_force_trh_resume ();
+ TMH_force_refund_resume ();
+ TMH_force_tip_pickup_resume ();
+#endif
if (NULL != mhd_task)
{
GNUNET_SCHEDULER_cancel (mhd_task);
@@ -556,10 +412,10 @@ do_shutdown (void *cls)
MHD_stop_daemon (mhd);
mhd = NULL;
}
- if (NULL != db)
+ if (NULL != TMH_db)
{
- TALER_MERCHANTDB_plugin_unload (db);
- db = NULL;
+ TALER_MERCHANTDB_plugin_unload (TMH_db);
+ TMH_db = NULL;
}
TMH_EXCHANGES_done ();
TMH_AUDITORS_done ();
@@ -574,16 +430,11 @@ do_shutdown (void *cls)
if (NULL != by_id_map)
{
GNUNET_CONTAINER_multihashmap_iterate (by_id_map,
- &hashmap_free,
+ &instance_free,
NULL);
GNUNET_CONTAINER_multihashmap_destroy (by_id_map);
by_id_map = NULL;
}
- if (NULL != by_kpub_map)
- {
- GNUNET_CONTAINER_multihashmap_destroy (by_kpub_map);
- by_kpub_map = NULL;
- }
}
@@ -607,15 +458,21 @@ handle_mhd_completion_callback (void *cls,
void **con_cls,
enum MHD_RequestTerminationCode toe)
{
- struct TM_HandlerContext *hc = *con_cls;
+ struct TMH_HandlerContext *hc = *con_cls;
if (NULL == hc)
return;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Finished handling request for `%s' with status %d\n",
- hc->rh->url,
+ hc->url,
(int) toe);
- hc->cc (hc);
+ if (NULL != hc->cc)
+ hc->cc (hc->ctx);
+ TALER_MHD_parse_post_cleanup_callback (hc->json_parse_context);
+ GNUNET_free_non_null (hc->infix);
+ if (NULL != hc->json)
+ json_decref (hc->json);
+ GNUNET_free (hc);
*con_cls = NULL;
}
@@ -625,7 +482,6 @@ handle_mhd_completion_callback (void *cls,
* starts the task waiting for them.
*/
static struct GNUNET_SCHEDULER_Task *
-
prepare_daemon (void);
@@ -729,504 +585,18 @@ prepare_daemon (void)
/**
- * Callback that looks for 'merchant-location-*' sections,
- * and populates @a default_locations.
- *
- * @param cls closure
- * @section section name this callback gets
- */
-static void
-locations_iterator_cb (void *cls,
- const char *section)
-{
- static const char *keys[] = {
- "country",
- "city",
- "state",
- "region",
- "province",
- "zip_code",
- "street",
- "street_number",
- NULL,
- };
- const char *prefix = "merchant-location-";
- const char *substr = strstr (section, prefix);
- const char *locname;
- json_t *loc;
-
- (void) cls;
- if ( (NULL == substr) || (substr != section) )
- return;
- locname = section + strlen (prefix);
- if (0 == strlen (locname))
- return;
- GNUNET_assert (json_is_object (default_locations));
-
- loc = json_object ();
- json_object_set_new (default_locations,
- locname,
- loc);
- for (unsigned int pos = 0; NULL != keys[pos]; pos++)
- {
- char *val;
-
- if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_string (cfg,
- section,
- keys[pos],
- &val))
- {
- json_object_set_new (loc,
- keys[pos],
- json_string (val));
- GNUNET_free (val);
- }
- }
-}
-
-
-/**
- * Closure for the #wireformat_iterator_cb().
- */
-struct WireFormatIteratorContext
-{
- /**
- * The global iteration context.
- */
- struct IterateInstancesCls *iic;
-
- /**
- * The merchant instance we are currently building.
- */
- struct MerchantInstance *mi;
-
- /**
- * Set to #GNUNET_YES if the default instance was found.
- */
- int default_instance;
-};
-
-
-/**
- * Callback that looks for 'merchant-account-*' sections,
- * and populates our wire method according to the data
- *
- * @param cls closure with a `struct WireFormatIteratorContext *`
- * @section section name this callback gets
- */
-static void
-wireformat_iterator_cb (void *cls,
- const char *section)
-{
- struct WireFormatIteratorContext *wfic = cls;
- struct MerchantInstance *mi = wfic->mi;
- struct IterateInstancesCls *iic = wfic->iic;
- char *instance_option;
- struct WireMethod *wm;
- char *payto;
- char *fn;
- json_t *j;
- struct GNUNET_HashCode jh_wire;
- char *wire_file_mode;
-
- if (0 != strncasecmp (section,
- "merchant-account-",
- strlen ("merchant-account-")))
- return;
- GNUNET_asprintf (&instance_option,
- "HONOR_%s",
- mi->id);
- if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (cfg,
- section,
- instance_option))
- {
- GNUNET_free (instance_option);
- return;
- }
- GNUNET_free (instance_option);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- section,
- "PAYTO_URI",
- &payto))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "PAYTO_URI");
- iic->ret = GNUNET_SYSERR;
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- section,
- "WIRE_RESPONSE",
- &fn))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "WIRE_RESPONSE");
- GNUNET_free (payto);
- iic->ret = GNUNET_SYSERR;
- return;
- }
-
- /* Try loading existing JSON from file */
- if (GNUNET_YES ==
- GNUNET_DISK_file_test (fn))
- {
- json_error_t err;
- char *url;
-
- if (NULL ==
- (j = json_load_file (fn,
- JSON_REJECT_DUPLICATES,
- &err)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to load JSON from `%s': %s at %d:%d\n",
- fn,
- err.text,
- err.line,
- err.column);
- GNUNET_free (fn);
- GNUNET_free (payto);
- iic->ret = GNUNET_SYSERR;
- return;
- }
- url = TALER_JSON_wire_to_payto (j);
- if (NULL == url)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "URL missing in `%s', disabling account `%s'\n",
- fn,
- section);
- GNUNET_free (fn);
- GNUNET_free (payto);
- iic->ret = GNUNET_SYSERR;
- return;
- }
- if (0 != strcasecmp (url,
- payto))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "URL `%s' does not match configuration `%s', disabling account `%s'\n",
- url,
- payto,
- section);
- GNUNET_free (fn);
- GNUNET_free (payto);
- GNUNET_free (url);
- iic->ret = GNUNET_SYSERR;
- return;
- }
- GNUNET_free (url);
- }
- else /* need to generate JSON */
- {
- struct GNUNET_HashCode salt;
- char *salt_str;
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &salt,
- sizeof (salt));
- salt_str = GNUNET_STRINGS_data_to_string_alloc (&salt,
- sizeof (salt));
- j = json_pack ("{s:s, s:s}",
- "payto_uri", payto,
- "salt", salt_str);
- GNUNET_free (salt_str);
-
- /* Make sure every path component exists. */
- if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
- "mkdir",
- fn);
- GNUNET_free (fn);
- GNUNET_free (payto);
- json_decref (j);
- iic->ret = GNUNET_SYSERR;
- return;
- }
-
- if (0 != json_dump_file (j,
- fn,
- JSON_COMPACT | JSON_SORT_KEYS))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to write hashed wire details to `%s'\n",
- fn);
- GNUNET_free (fn);
- GNUNET_free (payto);
- json_decref (j);
- iic->ret = GNUNET_SYSERR;
- return;
- }
-
- if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_string (cfg,
- section,
- "WIRE_FILE_MODE",
- &wire_file_mode))
- {
- errno = 0;
- mode_t mode = (mode_t) strtoul (wire_file_mode,
- NULL,
- 8);
- if (0 != errno)
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "WIRE_FILE_MODE",
- "Must be octal number\n");
- iic->ret = GNUNET_SYSERR;
- GNUNET_free (fn);
- return;
- }
- if (0 != chmod (fn, mode))
- {
- TALER_LOG_ERROR ("chmod failed on %s\n", fn);
- iic->ret = GNUNET_SYSERR;
- GNUNET_free (fn);
- return;
- }
- }
- }
-
- GNUNET_free (fn);
-
- if (GNUNET_OK !=
- TALER_JSON_merchant_wire_signature_hash (j,
- &jh_wire))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to hash wire input\n");
- GNUNET_free (fn);
- GNUNET_free (payto);
- json_decref (j);
- iic->ret = GNUNET_SYSERR;
- return;
- }
-
- wm = GNUNET_new (struct WireMethod);
- wm->wire_method = TALER_payto_get_method (payto);
- GNUNET_free (payto);
- GNUNET_asprintf (&instance_option,
- "ACTIVE_%s",
- mi->id);
- wm->active = GNUNET_CONFIGURATION_get_value_yesno (cfg,
- section,
- instance_option);
- GNUNET_free (instance_option);
- if (GNUNET_YES == wm->active)
- GNUNET_CONTAINER_DLL_insert (mi->wm_head,
- mi->wm_tail,
- wm);
- else
- GNUNET_CONTAINER_DLL_insert_tail (mi->wm_head,
- mi->wm_tail,
- wm);
- wm->j_wire = j;
- wm->h_wire = jh_wire;
-}
-
-
-/**
- * Callback that looks for 'instance-*' sections,
- * and populates accordingly each instance's data
- *
- * @param cls closure of type `struct IterateInstancesCls`
- * @section section name this callback gets
- */
-static void
-instances_iterator_cb (void *cls,
- const char *section)
-{
- struct IterateInstancesCls *iic = cls;
- char *token;
- struct MerchantInstance *mi;
- /* used as hashmap keys */
- struct GNUNET_HashCode h_pk;
- struct GNUNET_HashCode h_id;
-
- if (0 != strncasecmp (section,
- "instance-",
- strlen ("instance-")))
- return;
- /** Get id **/
- token = strrchr (section, '-');
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Extracted token: %s\n",
- token + 1);
- mi = GNUNET_new (struct MerchantInstance);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- section,
- "NAME",
- &mi->name))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "NAME");
- GNUNET_free (mi);
- iic->ret = GNUNET_SYSERR;
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- section,
- "KEYFILE",
- &mi->keyfile))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "KEYFILE");
- GNUNET_free (mi->name);
- GNUNET_free (mi);
- iic->ret = GNUNET_SYSERR;
- return;
- }
- if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_string (cfg,
- section,
- "TIP_EXCHANGE",
- &mi->tip_exchange))
- {
- char *tip_reserves;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- section,
- "TIP_RESERVE_PRIV_FILENAME",
- &tip_reserves))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "TIP_RESERVE_PRIV_FILENAME");
- GNUNET_free (mi->keyfile);
- GNUNET_free (mi->name);
- GNUNET_free (mi);
- iic->ret = GNUNET_SYSERR;
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_key_from_file (tip_reserves,
- GNUNET_NO,
- &mi->tip_reserve.eddsa_priv))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "TIP_RESERVE_PRIV_FILENAME",
- "Failed to read private key");
- GNUNET_free (tip_reserves);
- GNUNET_free (mi->keyfile);
- GNUNET_free (mi->name);
- GNUNET_free (mi);
- iic->ret = GNUNET_SYSERR;
- return;
- }
- GNUNET_free (tip_reserves);
- }
-
- if (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_key_from_file (mi->keyfile,
- GNUNET_YES,
- &mi->privkey.eddsa_priv))
- {
- GNUNET_break (0);
- GNUNET_free (mi->keyfile);
- GNUNET_free (mi->name);
- GNUNET_free (mi);
- iic->ret = GNUNET_SYSERR;
- return;
- }
- GNUNET_CRYPTO_eddsa_key_get_public (&mi->privkey.eddsa_priv,
- &mi->pubkey.eddsa_pub);
-
- mi->id = GNUNET_strdup (token + 1);
- if (0 == strcasecmp ("default",
- mi->id))
- iic->default_instance = GNUNET_YES;
-
- GNUNET_CRYPTO_hash (mi->id,
- strlen (mi->id),
- &h_id);
- if (GNUNET_OK !=
- GNUNET_CONTAINER_multihashmap_put (by_id_map,
- &h_id,
- mi,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to put an entry into the 'by_id' hashmap\n");
- iic->ret = GNUNET_SYSERR;
- GNUNET_free (mi->keyfile);
- GNUNET_free (mi->name);
- GNUNET_free (mi);
- return;
- }
- GNUNET_CRYPTO_hash (&mi->pubkey.eddsa_pub,
- sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
- &h_pk);
- if (GNUNET_OK !=
- GNUNET_CONTAINER_multihashmap_put (by_kpub_map,
- &h_pk,
- mi,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to put an entry into the 'by_kpub_map' hashmap\n");
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (by_id_map,
- &h_id,
- mi));
- iic->ret = GNUNET_SYSERR;
- GNUNET_free (mi->keyfile);
- GNUNET_free (mi->name);
- GNUNET_free (mi);
- return;
- }
-
- /* Initialize wireformats */
- {
- struct WireFormatIteratorContext wfic = {
- .iic = iic,
- .mi = mi
- };
-
- GNUNET_CONFIGURATION_iterate_sections (cfg,
- &wireformat_iterator_cb,
- &wfic);
- }
- if (NULL == mi->wm_head)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to load wire formats for instance `%s'\n",
- mi->id);
- iic->ret = GNUNET_SYSERR;
- }
-
-}
-
-
-/**
* Lookup a merchant instance by its instance ID.
*
* @param instance_id identifier of the instance to resolve
* @return NULL if that instance is unknown to us
*/
-static struct MerchantInstance *
+static struct TMH_MerchantInstance *
lookup_instance (const char *instance_id)
{
struct GNUNET_HashCode h_instance;
if (NULL == instance_id)
instance_id = "default";
-
GNUNET_CRYPTO_hash (instance_id,
strlen (instance_id),
&h_instance);
@@ -1242,57 +612,6 @@ lookup_instance (const char *instance_id)
/**
- * Iterate over locations in config in order to populate
- * the location data.
- *
- * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors
- */
-static void
-iterate_locations (void)
-{
- GNUNET_assert (NULL == default_locations);
- default_locations = json_object ();
- GNUNET_CONFIGURATION_iterate_sections (cfg,
- &locations_iterator_cb,
- NULL);
-}
-
-
-/**
- * Iterate over each merchant instance, in order to populate
- * each instance's own data
- *
- * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors
- * (for example, if no "default" instance is defined)
- */
-static int
-iterate_instances (void)
-{
- struct IterateInstancesCls iic;
-
- iic.default_instance = GNUNET_NO;
- iic.ret = GNUNET_OK;
- GNUNET_CONFIGURATION_iterate_sections (cfg,
- &instances_iterator_cb,
- &iic);
-
- if (GNUNET_NO == iic.default_instance)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "No default merchant instance found\n");
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK != iic.ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "At least one instance was not successfully parsed\n");
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
* A client has requested the given url using the given method
* (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT,
* #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc). The callback
@@ -1341,158 +660,143 @@ url_handler (void *cls,
size_t *upload_data_size,
void **con_cls)
{
- static struct TMH_RequestHandler handlers[] = {
- /* Landing page, tell humans to go away. */
- { "/", MHD_HTTP_METHOD_GET, "text/plain",
- "Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.\n",
- 0,
- &TMH_MHD_handler_static_response, MHD_HTTP_OK },
- { "/agpl", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &TMH_MHD_handler_agpl_redirect, MHD_HTTP_FOUND },
- { "/track/transfer", MHD_HTTP_METHOD_GET, "application/json",
- NULL, 0,
- &MH_handler_track_transfer, MHD_HTTP_OK},
- { "/track/transfer", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TMH_MHD_handler_static_response, MHD_HTTP_OK},
- { "/track/transaction", MHD_HTTP_METHOD_GET, "application/json",
- NULL, 0,
- &MH_handler_track_transaction, MHD_HTTP_OK},
- { "/track/transaction", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TMH_MHD_handler_static_response, MHD_HTTP_OK},
- { "/history", MHD_HTTP_METHOD_GET, "text/plain",
- "Only GET is allowed", 0,
- &MH_handler_history, MHD_HTTP_OK},
- { "/order", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &MH_handler_order_post, MHD_HTTP_OK },
- { "/refund", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &MH_handler_refund_increase, MHD_HTTP_OK},
- { "/tip-authorize", MHD_HTTP_METHOD_POST, "text/plain",
- NULL, 0,
- &MH_handler_tip_authorize, MHD_HTTP_OK},
- { "/tip-query", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_tip_query, MHD_HTTP_OK},
- { "/check-payment", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_check_payment, MHD_HTTP_OK},
- { "/config", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_config, MHD_HTTP_OK},
- {NULL, NULL, NULL, NULL, 0, 0 }
+ static struct TMH_RequestHandler private_handlers[] = {
+ {
+ .url_prefix = "/",
+ .method = MHD_HTTP_METHOD_GET,
+ .mime_type = "text/plain",
+ .skip_instance = true,
+ .data = "This is a GNU Taler merchant backend. See https://taler.net/.\n",
+ .data_size = strlen (
+ "This is a GNU Taler merchant backend. See https://taler.net/.\n"),
+ .handler = &TMH_MHD_handler_static_response,
+ .response_code = MHD_HTTP_OK
+ },
+ {
+ .url_prefix = "/agpl",
+ .method = MHD_HTTP_METHOD_GET,
+ .skip_instance = true,
+ .handler = &TMH_MHD_handler_agpl_redirect
+ },
+ {
+ NULL
+ }
};
static struct TMH_RequestHandler public_handlers[] = {
- { "/pay", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &MH_handler_pay, MHD_HTTP_OK },
- { "/proposal", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_proposal_lookup, MHD_HTTP_OK },
- { "/tip-pickup", MHD_HTTP_METHOD_POST, "text/plain",
- NULL, 0,
- &MH_handler_tip_pickup, MHD_HTTP_OK },
- { "/refund", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_refund_lookup, MHD_HTTP_OK },
- { "/tip-pickup", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_tip_pickup_get, MHD_HTTP_OK },
- { "/poll-payment", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_poll_payment, MHD_HTTP_OK},
- { "/config", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &MH_handler_config, MHD_HTTP_OK},
- {NULL, NULL, NULL, NULL, 0, 0 }
+ {
+ .url_prefix = "/",
+ .method = MHD_HTTP_METHOD_GET,
+ .mime_type = "text/plain",
+ .skip_instance = true,
+ .data = "This is a GNU Taler merchant backend. See https://taler.net/.\n",
+ .data_size = strlen (
+ "This is a GNU Taler merchant backend. See https://taler.net/.\n"),
+ .handler = &TMH_MHD_handler_static_response,
+ .response_code = MHD_HTTP_OK
+ },
+ {
+ .url_prefix = "/agpl",
+ .method = MHD_HTTP_METHOD_GET,
+ .skip_instance = true,
+ .handler = &TMH_MHD_handler_agpl_redirect
+ },
+ {
+ .url_prefix = "/config",
+ .method = MHD_HTTP_METHOD_GET,
+ .skip_instance = true,
+ .handler = &MH_handler_config
+ },
+ {
+ NULL
+ }
};
static struct TMH_RequestHandler h404 = {
- "", NULL, "text/html",
- "<html><title>404: not found</title><body>404: not found</body></html>", 0,
- &TMH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND
+ .mime_type = "text/html",
+ .data = "<html><title>404: not found</title>"
+ "<body>404: not found</body></html>",
+ .data_size = strlen ("<html><title>404: not found</title>"
+ "<body>404: not found</body></html>"),
+ .handler = &TMH_MHD_handler_static_response,
+ .response_code = MHD_HTTP_NOT_FOUND
};
-
- struct TM_HandlerContext *hc = *con_cls;
- struct GNUNET_AsyncScopeId aid;
- const char *correlation_id = NULL;
- struct MerchantInstance *instance;
- const char *effective_url;
- /* Is a publicly facing endpoint being requested? */
- int is_public;
- /* Matching URL found, but maybe method doesn't match */
- int url_found = GNUNET_NO;
- MHD_RESULT ret;
- struct TMH_RequestHandler *selected_handler = NULL;
+ struct TMH_HandlerContext *hc = *con_cls;
+ struct TMH_RequestHandler *handlers;
(void) cls;
(void) version;
- if (NULL == hc)
+ if (NULL != hc)
{
- GNUNET_async_scope_fresh (&aid);
- /* We only read the correlation ID on the first callback for every client */
+ GNUNET_assert (NULL != hc->rh);
+ GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id);
+ if ( (hc->is_post) &&
+ (NULL == hc->json) )
+ {
+ int res;
+
+ res = TALER_MHD_parse_post_json (connection,
+ &hc->json_parse_context,
+ upload_data,
+ upload_data_size,
+ &hc->json);
+ if (GNUNET_SYSERR == res)
+ return MHD_NO;
+ /* A error response was already generated */
+ if ( (GNUNET_NO == res) ||
+ /* or, need more data to accomplish parsing */
+ (NULL == hc->json) )
+ return MHD_YES;
+ }
+ return hc->rh->handler (hc->rh,
+ connection,
+ hc);
+ }
+ hc = GNUNET_new (struct TMH_HandlerContext);
+ *con_cls = hc;
+ GNUNET_async_scope_fresh (&hc->async_scope_id);
+ GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id);
+ hc->url = url;
+ {
+ const char *correlation_id;
+
correlation_id = MHD_lookup_connection_value (connection,
MHD_HEADER_KIND,
"Taler-Correlation-Id");
- if ((NULL != correlation_id) &&
- (GNUNET_YES != GNUNET_CURL_is_valid_scope_id (correlation_id)))
+ if ( (NULL != correlation_id) &&
+ (GNUNET_YES != GNUNET_CURL_is_valid_scope_id (correlation_id)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"illegal incoming correlation ID\n");
correlation_id = NULL;
}
- }
- else
- {
- aid = hc->async_scope_id;
- }
-
- GNUNET_SCHEDULER_begin_async_scope (&aid);
-
- if (NULL != correlation_id)
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Handling request for (%s) URL '%s', correlation_id=%s\n",
- method,
- url,
- correlation_id);
- else
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Handling request (%s) for URL '%s'\n",
- method,
- url);
-
- effective_url = url;
-
- {
- const char *public_prefix = "/public/";
-
- if (0 == strncmp (effective_url,
- public_prefix,
- strlen (public_prefix)))
- {
- is_public = GNUNET_YES;
- effective_url = effective_url + strlen (public_prefix) - 1;
- }
+ if (NULL != correlation_id)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling request for (%s) URL '%s', correlation_id=%s\n",
+ method,
+ url,
+ correlation_id);
else
- {
- is_public = GNUNET_NO;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling request (%s) for URL '%s'\n",
+ method,
+ url);
}
+ if (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_HEAD))
+ method = MHD_HTTP_METHOD_GET; /* MHD will deal with the rest */
+
/* Find out the merchant backend instance for the request.
* If there is an instance, remove the instance specification
* from the beginning of the request URL. */
{
const char *instance_prefix = "/instances/";
- if (0 == strncmp (effective_url,
+ if (0 == strncmp (url,
instance_prefix,
strlen (instance_prefix)))
{
/* url starts with "/instances/" */
- const char *istart = effective_url + strlen (instance_prefix);
+ const char *istart = url + strlen (instance_prefix);
const char *slash = strchr (istart, '/');
char *instance_id;
@@ -1500,114 +804,149 @@ url_handler (void *cls,
{
return TMH_MHD_handler_static_response (&h404,
connection,
- con_cls,
- upload_data,
- upload_data_size,
- NULL);
+ hc);
}
instance_id = GNUNET_strndup (istart,
slash - istart);
- instance = lookup_instance (instance_id);
+ hc->instance = lookup_instance (instance_id);
GNUNET_free (instance_id);
- effective_url = slash;
+ url = slash;
}
else
{
- instance = lookup_instance (NULL);
+ /* use 'default' */
+ hc->instance = lookup_instance (NULL);
}
}
- if (NULL == instance)
- return TALER_MHD_reply_json_pack (connection,
- MHD_HTTP_NOT_FOUND,
- "{s:I, s:s}",
- "code",
- (json_int_t) TALER_EC_INSTANCE_UNKNOWN,
- "error",
- "merchant instance unknown");
- if (GNUNET_NO == is_public)
{
- for (unsigned int i = 0; NULL != handlers[i].url; i++)
- {
- struct TMH_RequestHandler *rh = &handlers[i];
+ const char *private_prefix = "/private/";
- if ( (0 != strcasecmp (effective_url, rh->url)) )
- continue;
- url_found = GNUNET_YES;
- if (0 == strcasecmp (method,
- MHD_HTTP_METHOD_OPTIONS))
- {
- return TALER_MHD_reply_cors_preflight (connection);
- }
- if ( (rh->method != NULL) &&
- (0 != strcasecmp (method, rh->method)) )
- continue;
- selected_handler = rh;
- break;
+ if (0 == strncmp (url,
+ private_prefix,
+ strlen (private_prefix)))
+ {
+ handlers = private_handlers;
+ url += strlen (private_prefix) - 1;
+ }
+ else
+ {
+ handlers = public_handlers;
}
}
+ if (strcmp (url,
+ ""))
+ url = "/"; /* code below does not like empty string */
- if (NULL == selected_handler)
{
- for (unsigned int i = 0; NULL != public_handlers[i].url; i++)
+ /* Matching URL found, but maybe method doesn't match */
+ size_t prefix_strlen; /* i.e. 8 for "/orders/", or 7 for "/config" */
+ const char *infix_url = NULL; /* i.e. "$ORDER_ID", no '/'-es */
+ size_t infix_strlen = 0; /* number of characters in infix_url */
+ const char *suffix_url = NULL; /* i.e. "/refund", includes '/' at the beginning */
+ size_t suffix_strlen = 0; /* number of characters in suffix_url */
+
{
- struct TMH_RequestHandler *rh = &public_handlers[i];
+ const char *slash;
- if ( (0 != strcasecmp (effective_url, rh->url)) )
- continue;
- url_found = GNUNET_YES;
- if (0 == strcasecmp (method,
- MHD_HTTP_METHOD_OPTIONS))
+ slash = strchr (&url[1], '/');
+ if (NULL == slash)
{
- return TALER_MHD_reply_cors_preflight (connection);
+ prefix_strlen = strlen (url);
+ }
+ else
+ {
+ prefix_strlen = slash - url + 1; /* includes both '/'-es if present! */
+ infix_url = slash + 1;
+ slash = strchr (&infix_url[1], '/');
+ if (NULL == slash)
+ {
+ infix_strlen = strlen (infix_url);
+ }
+ else
+ {
+ infix_strlen = slash - infix_url;
+ suffix_url = slash;
+ suffix_strlen = strlen (suffix_url);
+ }
+ hc->infix = GNUNET_strndup (infix_url,
+ infix_strlen);
}
- if ( (rh->method != NULL) && (0 != strcasecmp (method, rh->method)) )
- continue;
- selected_handler = rh;
- break;
}
- }
- if (NULL == selected_handler)
- {
- if (GNUNET_YES == url_found)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "invalid request: method '%s' for '%s' not allowed\n",
- method,
- url);
- return TALER_MHD_reply_json_pack (connection,
- MHD_HTTP_METHOD_NOT_ALLOWED,
- "{s:s}",
- "error",
- "method not allowed");
+ bool url_found = false;
+
+ for (unsigned int i = 0; NULL != handlers[i].url_prefix; i++)
+ {
+ struct TMH_RequestHandler *rh = &handlers[i];
+
+ if ( (prefix_strlen != strlen (rh->url_prefix)) ||
+ (0 != memcmp (url,
+ rh->url_prefix,
+ prefix_strlen)) )
+ continue;
+ if ( (NULL == infix_url)
+ ^ (GNUNET_NO == rh->have_id_segment) )
+ continue; /* infix existence missmatch */
+ if ( (NULL == suffix_url)
+ ^ (NULL != rh->url_suffix) )
+ continue; /* suffix existence missmatch */
+ if ( (NULL != suffix_url) &&
+ ( (suffix_strlen != strlen (rh->url_suffix)) ||
+ (0 != memcmp (suffix_url,
+ rh->url_suffix,
+ suffix_strlen)) ) )
+ continue; /* suffix content missmatch */
+ url_found = true;
+ if (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_OPTIONS))
+ {
+ return TALER_MHD_reply_cors_preflight (connection);
+ }
+ if ( (rh->method != NULL) &&
+ (0 != strcasecmp (method, rh->method)) )
+ continue;
+ hc->rh = rh;
+ break;
+ }
+ if ( (NULL == hc->rh) &&
+ (url_found) )
+ return TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_METHOD_NOT_ALLOWED,
+ "{s:s}",
+ "error",
+ "method not allowed");
+ if (NULL == hc->rh)
+ return TMH_MHD_handler_static_response (&h404,
+ connection,
+ hc);
}
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "invalid request: URL '%s' not handled\n",
- url);
- return TMH_MHD_handler_static_response (&h404,
- connection,
- con_cls,
- upload_data,
- upload_data_size,
- instance);
}
-
- ret = selected_handler->handler (selected_handler,
- connection,
- con_cls,
- upload_data,
- upload_data_size,
- instance);
- hc = *con_cls;
- if (NULL != hc)
+ /* At this point, we must have found a handler */
+ GNUNET_assert (NULL != hc->rh);
+ if ( (NULL == hc->instance) &&
+ (GNUNET_YES != hc->rh->skip_instance) )
+ return TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_NOT_FOUND,
+ "{s:I, s:s}",
+ "code",
+ (json_int_t) TALER_EC_INSTANCE_UNKNOWN,
+ "error",
+ "merchant instance unknown");
+ hc->is_post = (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_POST));
+ if (hc->is_post)
{
- hc->rh = selected_handler;
- /* Store the async context ID, so we can restore it if
- * we get another callback for this request. */
- hc->async_scope_id = aid;
+ /* FIXME: Maybe check for maximum upload size here
+ and refuse if it is too big? */
+
+ GNUNET_break (NULL == hc->json); /* can't have it already */
+ return MHD_YES; /* proceed with upload */
}
- return ret;
+ return hc->rh->handler (hc->rh,
+ connection,
+ hc);
}
@@ -1632,10 +971,11 @@ run (void *cls,
(void) cls;
(void) args;
(void) cfgfile;
+ cfg = config;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Starting taler-merchant-httpd\n");
go = TALER_MHD_GO_NONE;
- if (TMH_merchant_connection_close)
+ if (merchant_connection_close)
go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE;
TALER_MHD_setup (go);
@@ -1643,14 +983,14 @@ run (void *cls,
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
if (GNUNET_OK !=
- TALER_config_get_currency (config,
+ TALER_config_get_currency (cfg,
&TMH_currency))
{
GNUNET_SCHEDULER_shutdown ();
return;
}
if (GNUNET_YES ==
- GNUNET_CONFIGURATION_get_value_yesno (config,
+ GNUNET_CONFIGURATION_get_value_yesno (cfg,
"merchant",
"FORCE_AUDIT"))
TMH_force_audit = GNUNET_YES;
@@ -1666,7 +1006,6 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
-
if (NULL ==
(by_id_map = GNUNET_CONTAINER_multihashmap_create (1,
GNUNET_NO)))
@@ -1674,97 +1013,14 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
-
if (NULL ==
- (by_kpub_map = GNUNET_CONTAINER_multihashmap_create (1,
- GNUNET_NO)))
- {
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_time (config,
- "merchant",
- "WIRE_TRANSFER_DELAY",
- &default_wire_transfer_delay))
+ (TMH_db = TALER_MERCHANTDB_plugin_load (cfg)))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "merchant",
- "WIRE_TRANSFER_DELAY");
GNUNET_SCHEDULER_shutdown ();
return;
}
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_time (config,
- "merchant",
- "DEFAULT_PAY_DEADLINE",
- &default_pay_deadline))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "merchant",
- "DEFAULT_PAY_DEADLINE");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- if (GNUNET_OK !=
- TALER_config_get_amount (config,
- "merchant",
- "DEFAULT_MAX_WIRE_FEE",
- &default_max_wire_fee))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "merchant",
- "DEFAULT_MAX_WIRE_FEE");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- if (GNUNET_OK !=
- TALER_config_get_amount (config,
- "merchant",
- "DEFAULT_MAX_DEPOSIT_FEE",
- &default_max_deposit_fee))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "merchant",
- "DEFAULT_MAX_DEPOSIT_FEE");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (config,
- "merchant",
- "DEFAULT_WIRE_FEE_AMORTIZATION",
- &default_wire_fee_amortization))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "merchant",
- "DEFAULT_WIRE_FEE_AMORTIZATION");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- cfg = GNUNET_CONFIGURATION_dup (config);
- if (GNUNET_OK !=
- iterate_instances ())
- {
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- iterate_locations ();
-
- if (NULL ==
- (db = TALER_MERCHANTDB_plugin_load (cfg)))
- {
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- fh = TALER_MHD_bind (config,
+ fh = TALER_MHD_bind (cfg,
"merchant",
&port);
if ( (0 == port) &&
@@ -1805,7 +1061,7 @@ run (void *cls,
*
* @param argc number of arguments from the command line
* @param argv command line arguments
- * @return 0 ok, 1 on error
+ * @return 0 ok, non-zero on error
*/
int
main (int argc,
@@ -1815,12 +1071,11 @@ main (int argc,
GNUNET_GETOPT_option_flag ('C',
"connection-close",
"force HTTP connections to be closed after each request",
- &TMH_merchant_connection_close),
+ &merchant_connection_close),
GNUNET_GETOPT_option_timetravel ('T',
"timetravel"),
GNUNET_GETOPT_OPTION_END
};
-
if (GNUNET_OK !=
GNUNET_PROGRAM_run (argc, argv,
"taler-merchant-httpd",