summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/merchant.conf6
-rw-r--r--src/backend/taler-merchant-httpd.c53
-rw-r--r--src/backend/taler-merchant-httpd.h23
-rw-r--r--src/backend/taler-merchant-httpd_exchanges.c14
-rw-r--r--src/backend/taler-merchant-httpd_history.c68
-rw-r--r--src/backend/taler-merchant-httpd_parsing.c5
-rw-r--r--src/backend/taler-merchant-httpd_pay.c143
-rw-r--r--src/backend/taler-merchant-httpd_proposal.c79
-rw-r--r--src/backend/taler-merchant-httpd_refund.c217
-rw-r--r--src/backend/taler-merchant-httpd_responses.c50
-rw-r--r--src/backend/taler-merchant-httpd_responses.h16
-rw-r--r--src/backend/taler-merchant-httpd_track-transaction.c79
-rw-r--r--src/backend/taler-merchant-httpd_track-transfer.c9
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c2
14 files changed, 441 insertions, 323 deletions
diff --git a/src/backend/merchant.conf b/src/backend/merchant.conf
index 55117874..5e16ef17 100644
--- a/src/backend/merchant.conf
+++ b/src/backend/merchant.conf
@@ -45,8 +45,14 @@ WIREFORMAT = test
# Determines which wire plugin will be used. We currently only
# support one wire plugin at a time!
+# How long do we want the exchange to sit on wire transfers
+# for aggregation?
WIRE_TRANSFER_DELAY = 3 week
+# How fast do we want customers to pay, i.e. how long will our
+# proposal be valid?
+DEFAULT_PAY_DEADLINE = 1 day
+
# Configuration for postgres database.
[merchantdb-postgres]
CONFIG = postgres:///talermerchant
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 9f0da2b0..437537d5 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -73,6 +73,12 @@ static long long unsigned port;
struct GNUNET_TIME_Relative wire_transfer_delay;
/**
+ * 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.
*/
@@ -222,28 +228,27 @@ url_handler (void *cls,
"<html><title>404: not found</title></html>", 0,
&TMH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND
};
- struct TM_HandlerContext *hc;
- struct TMH_RequestHandler *rh;
- unsigned int i;
- int ret;
-
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Handling request for URL `%s'\n",
url);
- for (i=0;NULL != handlers[i].url;i++)
+ for (unsigned int i=0;NULL != handlers[i].url;i++)
{
- rh = &handlers[i];
+ struct TMH_RequestHandler *rh = &handlers[i];
+
if ( (0 == strcasecmp (url,
rh->url)) &&
( (NULL == rh->method) ||
(0 == strcasecmp (method,
rh->method)) ) )
{
+ struct TM_HandlerContext *hc;
+ int ret;
+
ret = rh->handler (rh,
- connection,
- con_cls,
- upload_data,
- upload_data_size);
+ connection,
+ con_cls,
+ upload_data,
+ upload_data_size);
hc = *con_cls;
if (NULL != hc)
hc->rh = rh;
@@ -435,11 +440,12 @@ prepare_daemon ()
GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Adding run_daemon select task\n");
- ret =
- GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
- tv, wrs, wws,
- &run_daemon,
- NULL);
+ ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
+ tv,
+ wrs,
+ wws,
+ &run_daemon,
+ NULL);
GNUNET_NETWORK_fdset_destroy (wrs);
GNUNET_NETWORK_fdset_destroy (wws);
return ret;
@@ -641,7 +647,7 @@ TMH_lookup_instance (const char *name)
* a wrong instance
*/
struct MerchantInstance *
-get_instance (struct json_t *json)
+TMH_lookup_instance_json (struct json_t *json)
{
struct json_t *instance;
const char *instance_str;
@@ -789,6 +795,19 @@ run (void *cls,
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_denom (config,
"merchant",
diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h
index 0526ad20..c67a9713 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -269,6 +269,12 @@ extern struct TALER_MERCHANTDB_Plugin *db;
extern struct GNUNET_TIME_Relative wire_transfer_delay;
/**
+ * If the frontend does NOT specify a payment deadline, how long should
+ * offers we make be valid by default?
+ */
+extern struct GNUNET_TIME_Relative default_pay_deadline;
+
+/**
* Kick MHD to run now, to be called after MHD_resume_connection().
* Basically, we need to explicitly resume MHD's event loop whenever
* we made progress serving a request. This function re-schedules
@@ -287,4 +293,21 @@ struct MerchantInstance *
TMH_lookup_instance (const char *name);
+/**
+ * Extract merchant instance from the given JSON
+ *
+ * @param json the JSON to inspect; it is not required to
+ * comply with any particular format. It will only be checked
+ * if the field "instance" is there.
+ * @return a pointer to a #struct MerchantInstance. This will be
+ * the 'default' merchant if the frontend did not specif any
+ * "instance" field. The user should not care to free the returned
+ * value, as it is taken from a global array that will be freed
+ * by the general shutdown routine. NULL if the frontend specified
+ * a wrong instance
+ */
+struct MerchantInstance *
+TMH_lookup_instance_json (struct json_t *json);
+
+
#endif
diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c
index 8799fa20..ea84e6bd 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -398,14 +398,15 @@ get_wire_fees (struct Exchange *exchange,
static int
process_find_operations (struct Exchange *exchange)
{
- struct TMH_EXCHANGES_FindOperation *fo;
struct TMH_EXCHANGES_FindOperation *fn;
struct GNUNET_TIME_Absolute now;
int need_wire;
now = GNUNET_TIME_absolute_get ();
need_wire = GNUNET_NO;
- for (fo = exchange->fo_head; NULL != fo; fo = fn)
+ for (struct TMH_EXCHANGES_FindOperation *fo = exchange->fo_head;
+ NULL != fo;
+ fo = fn)
{
const struct TALER_Amount *wire_fee;
@@ -887,9 +888,6 @@ accept_exchanges (void *cls,
int
TMH_EXCHANGES_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- struct Exchange *exchange;
- json_t *j_exchange;
-
merchant_curl_ctx
= GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
&merchant_curl_rc);
@@ -905,8 +903,12 @@ TMH_EXCHANGES_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
(void *) cfg);
/* build JSON with list of trusted exchanges (will be included in contracts) */
trusted_exchanges = json_array ();
- for (exchange = exchange_head; NULL != exchange; exchange = exchange->next)
+ for (struct Exchange *exchange = exchange_head;
+ NULL != exchange;
+ exchange = exchange->next)
{
+ json_t *j_exchange;
+
if (GNUNET_YES != exchange->trusted)
continue;
j_exchange = json_pack ("{s:s, s:o}",
diff --git a/src/backend/taler-merchant-httpd_history.c b/src/backend/taler-merchant-httpd_history.c
index e4058722..9d6459ef 100644
--- a/src/backend/taler-merchant-httpd_history.c
+++ b/src/backend/taler-merchant-httpd_history.c
@@ -93,11 +93,12 @@ MH_handler_history (struct TMH_RequestHandler *rh,
const char *str;
struct GNUNET_TIME_Absolute date;
json_t *response;
- unsigned int ret;
+ int ret;
unsigned long long seconds;
struct MerchantInstance *mi;
int start = -1;
unsigned int delta;
+ enum GNUNET_DB_QueryStatus qs;
response = json_array ();
str = MHD_lookup_connection_value (connection,
@@ -107,7 +108,9 @@ MH_handler_history (struct TMH_RequestHandler *rh,
if (NULL != str)
{
- if (1 != sscanf (str, "%llu", &seconds))
+ if (1 != sscanf (str,
+ "%llu",
+ &seconds))
{
json_decref (response);
return TMH_RESPONSE_reply_arg_invalid (connection,
@@ -147,13 +150,17 @@ MH_handler_history (struct TMH_RequestHandler *rh,
if (NULL != str)
{
-
- ret = db->find_contract_terms_history (db->cls,
- str,
- &mi->pubkey,
- &pd_cb,
- response);
- if (GNUNET_SYSERR == ret)
+ qs = db->find_contract_terms_history (db->cls,
+ str,
+ &mi->pubkey,
+ &pd_cb,
+ response);
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ if (0 > qs)
{
json_decref (response);
return TMH_RESPONSE_reply_internal_error (connection,
@@ -174,7 +181,9 @@ MH_handler_history (struct TMH_RequestHandler *rh,
"start");
if (NULL != str)
{
- if ( (1 != sscanf (str, "%d", &start)) ||
+ if ( (1 != sscanf (str,
+ "%d",
+ &start)) ||
(0 > start) )
{
json_decref (response);
@@ -190,7 +199,9 @@ MH_handler_history (struct TMH_RequestHandler *rh,
if (NULL != str)
{
- if (1 != sscanf (str, "%u", &delta))
+ if (1 != sscanf (str,
+ "%u",
+ &delta))
return TMH_RESPONSE_reply_arg_invalid (connection,
TALER_EC_PARAMETER_MALFORMED,
"delta");
@@ -202,23 +213,28 @@ MH_handler_history (struct TMH_RequestHandler *rh,
delta);
if (0 > start)
- ret = db->find_contract_terms_by_date (db->cls,
- date,
- &mi->pubkey,
- delta,
- &pd_cb,
- response);
+ qs = db->find_contract_terms_by_date (db->cls,
+ date,
+ &mi->pubkey,
+ delta,
+ &pd_cb,
+ response);
else
- ret = db->find_contract_terms_by_date_and_range (db->cls,
- date,
- &mi->pubkey,
- (unsigned int) start,
- delta,
- GNUNET_NO,
- &pd_cb,
- response);
- if (GNUNET_SYSERR == ret)
+ qs = db->find_contract_terms_by_date_and_range (db->cls,
+ date,
+ &mi->pubkey,
+ (unsigned int) start,
+ delta,
+ GNUNET_NO,
+ &pd_cb,
+ response);
+ if (0 > qs)
{
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
json_decref (response);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_HISTORY_DB_FETCH_ERROR,
diff --git a/src/backend/taler-merchant-httpd_parsing.c b/src/backend/taler-merchant-httpd_parsing.c
index 6dc91ac1..f04313a6 100644
--- a/src/backend/taler-merchant-httpd_parsing.c
+++ b/src/backend/taler-merchant-httpd_parsing.c
@@ -133,6 +133,7 @@ buffer_append (struct Buffer *buf,
{
char *new_buf;
size_t new_size = buf->alloc ? buf->alloc : 1;
+
while (new_size < buf->fill + data_size)
new_size *= 2;
if (new_size > max_size)
@@ -143,7 +144,9 @@ buffer_append (struct Buffer *buf,
buf->data = new_buf;
buf->alloc = new_size;
}
- memcpy (buf->data + buf->fill, data, data_size);
+ memcpy (buf->data + buf->fill,
+ data,
+ data_size);
buf->fill += data_size;
return GNUNET_OK;
}
diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c
index 902a7dc8..2e3767be 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -38,6 +38,10 @@
*/
#define PAY_TIMEOUT (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30))
+/**
+ * How often do we retry the simple INSERT database transaction?
+ */
+#define MAX_RETRIES 3
/**
* Information we keep for an individual call to the /pay handler.
@@ -325,7 +329,9 @@ static struct PayContext *pc_tail;
void
MH_force_pc_resume ()
{
- for (struct PayContext *pc = pc_head; NULL != pc; pc = pc->next)
+ for (struct PayContext *pc = pc_head;
+ NULL != pc;
+ pc = pc->next)
{
if (GNUNET_YES == pc->suspended)
{
@@ -375,11 +381,9 @@ resume_pay_with_response (struct PayContext *pc,
static void
abort_deposit (struct PayContext *pc)
{
- unsigned int i;
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Aborting pending /deposit operations\n");
- for (i=0;i<pc->coins_cnt;i++)
+ for (unsigned int i;i<pc->coins_cnt;i++)
{
struct DepositConfirmation *dci = &pc->dc[i];
@@ -449,6 +453,7 @@ deposit_cb (void *cls,
{
struct DepositConfirmation *dc = cls;
struct PayContext *pc = dc->pc;
+ enum GNUNET_DB_QueryStatus qs;
dc->dh = NULL;
pc->pending--;
@@ -493,19 +498,26 @@ deposit_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Storing successful payment for h_contract_terms '%s'\n",
GNUNET_h2s (&pc->h_contract_terms));
-
- if (GNUNET_OK !=
- db->store_deposit (db->cls,
- &pc->h_contract_terms,
- &pc->mi->pubkey,
- &dc->coin_pub,
- &dc->amount_with_fee,
- &dc->deposit_fee,
- &dc->refund_fee,
- sign_key,
- proof))
+ for (unsigned int i=0;i<MAX_RETRIES;i++)
{
- GNUNET_break (0);
+ qs = db->store_deposit (db->cls,
+ &pc->h_contract_terms,
+ &pc->mi->pubkey,
+ &dc->coin_pub,
+ &dc->amount_with_fee,
+ &dc->deposit_fee,
+ &dc->refund_fee,
+ sign_key,
+ proof);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+ if (0 > qs)
+ {
+ /* Special report if retries insufficient */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
/* internal error */
abort_deposit (pc);
/* Forward error including 'proof' for the body */
@@ -929,7 +941,6 @@ check_coin_paid (void *cls,
const json_t *exchange_proof)
{
struct PayContext *pc = cls;
- unsigned int i;
if (0 != memcmp (&pc->h_contract_terms,
h_contract_terms,
@@ -938,7 +949,7 @@ check_coin_paid (void *cls,
GNUNET_break (0);
return;
}
- for (i=0;i<pc->coins_cnt;i++)
+ for (unsigned int i=0;i<pc->coins_cnt;i++)
{
struct DepositConfirmation *dc = &pc->dc[i];
/* Get matching coin from results*/
@@ -1009,11 +1020,6 @@ check_transaction_exists (void *cls,
}
-// FIXME: declare in proper header!
-extern struct MerchantInstance *
-get_instance (struct json_t *json);
-
-
/**
* Try to parse the pay request into the given pay context.
* Schedules an error response in the connection on failure.
@@ -1046,6 +1052,7 @@ parse_pay (struct MHD_Connection *connection,
GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
GNUNET_JSON_spec_end()
};
+ enum GNUNET_DB_QueryStatus qs;
res = TMH_PARSE_json_data (connection,
root,
@@ -1055,11 +1062,23 @@ parse_pay (struct MHD_Connection *connection,
GNUNET_break (0);
return res;
}
- res = db->find_contract_terms (db->cls,
+ qs = db->find_contract_terms (db->cls,
&pc->contract_terms,
order_id,
&merchant_pub);
- if (GNUNET_OK != res)
+ if (0 > qs)
+ {
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ return TMH_RESPONSE_reply_internal_error (connection,
+ TALER_EC_PAY_DB_FETCH_PAY_ERROR,
+ "db error to previous /pay data");
+
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
GNUNET_JSON_parse_free (spec);
if (MHD_YES !=
@@ -1106,15 +1125,16 @@ parse_pay (struct MHD_Connection *connection,
}
return GNUNET_NO;
}
- pc->mi = get_instance (merchant);
+ pc->mi = TMH_lookup_instance_json (merchant);
if (NULL == pc->mi)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unable to find the specified instance\n");
GNUNET_JSON_parse_free (spec);
- if (MHD_NO == TMH_RESPONSE_reply_not_found (connection,
- TALER_EC_PAY_INSTANCE_UNKNOWN,
- "Unknown instance given"))
+ if (MHD_NO ==
+ TMH_RESPONSE_reply_not_found (connection,
+ TALER_EC_PAY_INSTANCE_UNKNOWN,
+ "Unknown instance given"))
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -1296,6 +1316,7 @@ handler_pay_json (struct MHD_Connection *connection,
struct PayContext *pc)
{
int ret;
+ enum GNUNET_DB_QueryStatus qs;
ret = parse_pay (connection,
root,
@@ -1304,14 +1325,18 @@ handler_pay_json (struct MHD_Connection *connection,
return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
/* Check if this payment attempt has already succeeded */
- if (GNUNET_SYSERR ==
- db->find_payments (db->cls,
- &pc->h_contract_terms,
- &pc->mi->pubkey,
- &check_coin_paid,
- pc))
+ qs = db->find_payments (db->cls,
+ &pc->h_contract_terms,
+ &pc->mi->pubkey,
+ &check_coin_paid,
+ pc);
+ if (0 > qs)
{
- GNUNET_break (0);
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR,
"Merchant database error");
@@ -1333,14 +1358,18 @@ handler_pay_json (struct MHD_Connection *connection,
return ret;
}
/* Check if transaction is already known, if not store it. */
- if (GNUNET_SYSERR ==
- db->find_transaction (db->cls,
- &pc->h_contract_terms,
- &pc->mi->pubkey,
- &check_transaction_exists,
- pc))
+ qs = db->find_transaction (db->cls,
+ &pc->h_contract_terms,
+ &pc->mi->pubkey,
+ &check_transaction_exists,
+ pc);
+ if (0 > qs)
{
- GNUNET_break (0);
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR,
"Merchant database error");
@@ -1378,17 +1407,25 @@ handler_pay_json (struct MHD_Connection *connection,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Storing transaction '%s'\n",
GNUNET_h2s (&pc->h_contract_terms));
- if (GNUNET_OK !=
- db->store_transaction (db->cls,
- &pc->h_contract_terms,
- &pc->mi->pubkey,
- pc->chosen_exchange,
- &pc->mi->h_wire,
- pc->timestamp,
- pc->refund_deadline,
- &pc->amount))
+ for (unsigned int i=0;i<MAX_RETRIES;i++)
{
- GNUNET_break (0);
+ qs = db->store_transaction (db->cls,
+ &pc->h_contract_terms,
+ &pc->mi->pubkey,
+ pc->chosen_exchange,
+ &pc->mi->h_wire,
+ pc->timestamp,
+ pc->refund_deadline,
+ &pc->amount);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+ if (0 > qs)
+ {
+ /* Special report if retries insufficient */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR,
"Merchant database error");
diff --git a/src/backend/taler-merchant-httpd_proposal.c b/src/backend/taler-merchant-httpd_proposal.c
index a4311795..ae0c3dcc 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -30,6 +30,12 @@
/**
+ * How often do we retry the simple INSERT database transaction?
+ */
+#define MAX_RETRIES 3
+
+
+/**
* Check that the given JSON array of products is well-formed.
*
* @param products JSON array to check
@@ -115,10 +121,6 @@ json_parse_cleanup (struct TM_HandlerContext *hc)
}
-extern struct MerchantInstance *
-get_instance (struct json_t *json);
-
-
/**
* Transform an order into a proposal and store it in the database.
* Write the resulting proposal or an error message ot a MHD connection
@@ -156,12 +158,12 @@ proposal_put (struct MHD_Connection *connection,
GNUNET_JSON_spec_absolute_time ("pay_deadline", &pay_deadline),
GNUNET_JSON_spec_end ()
};
-
+ enum GNUNET_DB_QueryStatus qs;
/* Add order_id if it doesn't exist. */
-
- if (NULL == json_string_value (json_object_get (order,
- "order_id")))
+ if (NULL ==
+ json_string_value (json_object_get (order,
+ "order_id")))
{
char buf[256];
time_t timer;
@@ -175,7 +177,8 @@ proposal_put (struct MHD_Connection *connection,
sizeof (buf),
"%H:%M:%S",
tm_info);
- snprintf (buf + off, sizeof (buf) - off,
+ snprintf (buf + off,
+ sizeof (buf) - off,
"-%llX",
(long long unsigned) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
UINT64_MAX));
@@ -210,8 +213,7 @@ proposal_put (struct MHD_Connection *connection,
{
struct GNUNET_TIME_Absolute t;
- /* FIXME: read the delay for pay_deadline from config */
- t = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS);
+ t = GNUNET_TIME_relative_to_absolute (default_pay_deadline);
(void) GNUNET_TIME_round_abs (&t);
json_object_set_new (order,
"pay_deadline",
@@ -258,7 +260,7 @@ proposal_put (struct MHD_Connection *connection,
"order:products");
}
- mi = get_instance (merchant);
+ mi = TMH_lookup_instance_json (merchant);
if (NULL == mi)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -299,22 +301,28 @@ proposal_put (struct MHD_Connection *connection,
&pdps.purpose,
&merchant_sig);
- /* fetch timestamp from order */
-
- if (GNUNET_OK !=
- db->insert_contract_terms (db->cls,
- order_id,
- &mi->pubkey,
- timestamp,
- order))
+ for (unsigned int i=0;i<MAX_RETRIES;i++)
+ {
+ qs = db->insert_contract_terms (db->cls,
+ order_id,
+ &mi->pubkey,
+ timestamp,
+ order);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+ if (0 > qs)
{
+ /* Special report if retries insufficient */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
GNUNET_JSON_parse_free (spec);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_PROPOSAL_STORE_DB_ERROR,
"db error: could not store this proposal's data into db");
}
-
res = TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_OK,
"{s:O, s:o s:o}",
@@ -369,7 +377,8 @@ MH_handler_proposal_put (struct TMH_RequestHandler *rh,
if (GNUNET_SYSERR == res)
return MHD_NO;
/* the POST's body has to be further fetched */
- if ((GNUNET_NO == res) || (NULL == root))
+ if ( (GNUNET_NO == res) ||
+ (NULL == root) )
return MHD_YES;
order = json_object_get (root,
@@ -412,6 +421,7 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
const char *order_id;
const char *instance;
int res;
+ enum GNUNET_DB_QueryStatus qs;
json_t *contract_terms;
struct MerchantInstance *mi;
@@ -434,18 +444,25 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
TALER_EC_PARAMETER_MISSING,
"order_id");
- res = db->find_contract_terms (db->cls,
- &contract_terms,
- order_id,
- &mi->pubkey);
- if (GNUNET_NO == res)
- return TMH_RESPONSE_reply_not_found (connection,
- TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
- "unknown transaction id");
- if (GNUNET_SYSERR == res)
+ qs = db->find_contract_terms (db->cls,
+ &contract_terms,
+ order_id,
+ &mi->pubkey);
+ if (0 > qs)
+ {
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_PROPOSAL_LOOKUP_DB_ERROR,
"An error occurred while retrieving proposal data from db");
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ return TMH_RESPONSE_reply_not_found (connection,
+ TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
+ "unknown transaction id");
res = TMH_RESPONSE_reply_json (connection,
contract_terms,
diff --git a/src/backend/taler-merchant-httpd_refund.c b/src/backend/taler-merchant-httpd_refund.c
index 0dc23efe..b196870f 100644
--- a/src/backend/taler-merchant-httpd_refund.c
+++ b/src/backend/taler-merchant-httpd_refund.c
@@ -28,6 +28,14 @@
#define REFUND_CONFIRMATION 0
+
+/**
+ * How often do we retry the non-trivial refund INSERT database
+ * transaction?
+ */
+#define MAX_RETRIES 5
+
+
/**
* We confirm with a signature that the refund has been successfully
* done. Even though the frontend doesn't usually do crypto, this signature
@@ -67,9 +75,9 @@ struct ProcessRefundData
struct MerchantInstance *merchant;
/**
- * Return code: GNUNET_OK if successful, GNUNET_SYSERR otherwise
+ * Return code: #TALER_EC_NONE if successful.
*/
- int ret;
+ enum TALER_ErrorCode ec;
};
/**
@@ -107,10 +115,6 @@ json_parse_cleanup (struct TM_HandlerContext *hc)
}
-extern struct MerchantInstance *
-get_instance (struct json_t *json);
-
-
/**
* Handle request for increasing the refund associated with
* a contract.
@@ -140,7 +144,6 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
struct GNUNET_HashCode h_contract_terms;
struct RefundConfirmationP confirmation;
struct GNUNET_CRYPTO_EddsaSignature sig;
-
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount ("refund", &refund),
GNUNET_JSON_spec_string ("order_id", &order_id),
@@ -148,7 +151,7 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
GNUNET_JSON_spec_string ("instance", &merchant),
GNUNET_JSON_spec_end ()
};
-
+ enum GNUNET_DB_QueryStatus qs;
if (NULL == *connection_cls)
{
@@ -169,7 +172,8 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
if (GNUNET_SYSERR == res)
return MHD_NO;
/* the POST's body has to be further fetched */
- if ((GNUNET_NO == res) || (NULL == root))
+ if ( (GNUNET_NO == res) ||
+ (NULL == root) )
return MHD_YES;
res = TMH_PARSE_json_data (connection,
@@ -196,14 +200,26 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
GNUNET_JSON_parse_free (spec);
return TMH_RESPONSE_reply_not_found (connection,
TALER_EC_REFUND_INSTANCE_UNKNOWN,
- "Unknown instance given");
+ "Unknown instance given");
}
/* Convert order id to h_contract_terms */
- if (GNUNET_OK != db->find_contract_terms (db->cls,
- &contract_terms,
- order_id,
- &mi->pubkey))
+ qs = db->find_contract_terms (db->cls,
+ &contract_terms,
+ order_id,
+ &mi->pubkey);
+ if (0 > qs)
+ {
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ return TMH_RESPONSE_reply_internal_error (connection,
+ TALER_EC_REFUND_LOOKUP_DB_ERROR,
+ "An error occurred while retrieving payment data from db");
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unknown order id given: %s\n",
@@ -220,45 +236,40 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
GNUNET_JSON_parse_free (spec);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not hash contract terms\n");
- /**
- * Do we really need a error code for failing to hash something?
- * The HTTP 500 Internal server error sufficies for now.
- */
return TMH_RESPONSE_reply_internal_error (connection,
- TALER_EC_NONE,
+ TALER_EC_INTERNAL_LOGIC_ERROR,
"Could not hash contract terms");
}
-
- res = db->increase_refund_for_contract (db->cls,
- &h_contract_terms,
- &mi->pubkey,
- &refund,
- reason);
- if (GNUNET_NO == res)
+ for (unsigned int i=0;i<MAX_RETRIES;i++)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Inconsistent refund amount: %s\n",
- TALER_amount_to_string (&refund));
- GNUNET_JSON_parse_free (spec);
- /**
- * FIXME: should the db function distinguish between a refund amount
- * lower than the previous one and a one which is too big to be paid back?
- */
- return TMH_RESPONSE_reply_external_error (connection,
- TALER_EC_REFUND_INCONSISTENT_AMOUNT,
- "Amount incorrect: either not bigger"
- " than the previous one or too big to"
- " be paid back");
+ qs = db->increase_refund_for_contract (db->cls,
+ &h_contract_terms,
+ &mi->pubkey,
+ &refund,
+ reason);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
}
-
- if (GNUNET_SYSERR == res)
+ if (0 > qs)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not commit refund increase\n");
+ /* Special report if retries insufficient */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
GNUNET_JSON_parse_free (spec);
return TMH_RESPONSE_reply_internal_error (connection,
- TALER_EC_NONE,
- "Internal hard db error");
+ TALER_EC_REFUND_MERCHANT_DB_COMMIT_ERROR,
+ "Internal database error or refund amount too big");
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Refunded amount lower or equal to previous refund: %s\n",
+ TALER_amount2s (&refund));
+ GNUNET_JSON_parse_free (spec);
+ return TMH_RESPONSE_reply_external_error (connection,
+ TALER_EC_REFUND_INCONSISTENT_AMOUNT,
+ "Amount incorrect: not larger than the previous one");
}
/**
@@ -278,9 +289,10 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
confirmation.purpose.purpose = REFUND_CONFIRMATION;
confirmation.purpose.size = htonl (sizeof (struct RefundConfirmationP));
- if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
- &confirmation.purpose,
- &sig))
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
+ &confirmation.purpose,
+ &sig))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to sign successful refund confirmation\n");
@@ -308,7 +320,7 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
* @param refund_amount refund amount which is being taken from coin_pub
* @param refund_fee cost of this refund operation
*/
-void
+static void
process_refunds_cb (void *cls,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
uint64_t rtransaction_id,
@@ -332,13 +344,14 @@ process_refunds_cb (void *cls,
TALER_amount_hton (&rr.refund_fee,
refund_fee);
- if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&prd->merchant->privkey.eddsa_priv,
- &rr.purpose,
- &sig))
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_sign (&prd->merchant->privkey.eddsa_priv,
+ &rr.purpose,
+ &sig))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not sign refund request\n");
- prd->ret = GNUNET_SYSERR;
+ prd->ec = TALER_EC_INTERNAL_LOGIC_ERROR;
return;
}
@@ -354,7 +367,7 @@ process_refunds_cb (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not pack a response's element up\n");
- prd->ret = GNUNET_SYSERR;
+ prd->ec = TALER_EC_PARSER_OUT_OF_MEMORY;
return;
}
@@ -363,7 +376,7 @@ process_refunds_cb (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not append a response's element\n");
- prd->ret = GNUNET_SYSERR;
+ prd->ec = TALER_EC_PARSER_OUT_OF_MEMORY;
return;
}
}
@@ -389,8 +402,9 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh,
const char *instance;
struct GNUNET_HashCode h_contract_terms;
json_t *contract_terms;
- int res;
struct MerchantInstance *mi;
+ enum GNUNET_DB_QueryStatus qs;
+ struct ProcessRefundData prd;
instance = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND,
@@ -429,11 +443,23 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh,
}
/* Convert order id to h_contract_terms */
- res = db->find_contract_terms (db->cls,
- &contract_terms,
- order_id,
- &mi->pubkey);
- if (GNUNET_NO == res)
+ qs = db->find_contract_terms (db->cls,
+ &contract_terms,
+ order_id,
+ &mi->pubkey);
+ if (0 > qs)
+ {
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ return TMH_RESPONSE_reply_internal_error (connection,
+ TALER_EC_REFUND_LOOKUP_DB_ERROR,
+ "database error looking up order_id from merchant_contract_terms table");
+ }
+
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unknown order id given: %s\n",
@@ -442,18 +468,6 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh,
TALER_EC_REFUND_ORDER_ID_UNKNOWN,
"Order id not found in database");
}
- if (GNUNET_SYSERR == res)
- {
-
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "database hard error on order_id lookup: %s\n",
- order_id);
-
- return TMH_RESPONSE_reply_internal_error (connection,
- TALER_EC_NONE,
- "database hard error: looking up"
- " oder_id from merchant_contract_terms table");
- }
if (GNUNET_OK !=
TALER_JSON_hash (contract_terms,
@@ -461,57 +475,46 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh,
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not hash contract terms\n");
- /**
- * Do we really need a error code for failing to hash something?
- * The HTTP 500 Internal server error sufficies for now.
- */
return TMH_RESPONSE_reply_internal_error (connection,
- TALER_EC_NONE,
+ TALER_EC_INTERNAL_LOGIC_ERROR,
"Could not hash contract terms");
}
- struct ProcessRefundData cb_cls;
- cb_cls.response = json_array ();
- cb_cls.h_contract_terms = &h_contract_terms;
- cb_cls.merchant = mi;
- res = db->get_refunds_from_contract_terms_hash (db->cls,
- &mi->pubkey,
- &h_contract_terms,
- process_refunds_cb,
- &cb_cls);
-
- if (GNUNET_NO == res)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Contract terms hash not found in database\n");
- /*This is very odd, as the unhashed version *was* found earlier*/
- return TMH_RESPONSE_reply_not_found (connection,
- TALER_EC_REFUND_H_CONTRACT_TERMS_UNKNOWN,
- "h_contract_terms not found among granted refunds");
+ prd.response = json_array ();
+ prd.h_contract_terms = &h_contract_terms;
+ prd.merchant = mi;
+ prd.ec = TALER_EC_NONE;
+ for (unsigned int i=0;i<MAX_RETRIES;i++)
+ {
+ qs = db->get_refunds_from_contract_terms_hash (db->cls,
+ &mi->pubkey,
+ &h_contract_terms,
+ &process_refunds_cb,
+ &prd);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
}
-
- if (GNUNET_SYSERR == res)
+ if (0 > qs)
{
-
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"database hard error on order_id lookup: %s\n",
order_id);
-
+ json_decref (prd.response);
return TMH_RESPONSE_reply_internal_error (connection,
- TALER_EC_NONE,
+ TALER_EC_REFUND_LOOKUP_DB_ERROR,
"database hard error: looking for "
"h_contract_terms in merchant_refunds table");
}
- if (GNUNET_SYSERR == cb_cls.ret)
+ if (TALER_EC_NONE != prd.ec)
{
+ json_decref (prd.response);
/* NOTE: error already logged by the callback */
return TMH_RESPONSE_reply_internal_error (connection,
- TALER_EC_NONE,
+ prd.ec,
"Could not generate a response");
}
-
- return TMH_RESPONSE_reply_json (connection,
- cb_cls.response,
- MHD_HTTP_OK);
+ return TMH_RESPONSE_reply_json (connection,
+ prd.response,
+ MHD_HTTP_OK);
}
diff --git a/src/backend/taler-merchant-httpd_responses.c b/src/backend/taler-merchant-httpd_responses.c
index 8cbdf6b0..1ea2600e 100644
--- a/src/backend/taler-merchant-httpd_responses.c
+++ b/src/backend/taler-merchant-httpd_responses.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+ Copyright (C) 2014-2017 GNUnet e.V.
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
@@ -395,52 +395,4 @@ TMH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection,
}
-/**
- * Generate /track/transaction response.
- *
- * @param num_transfers how many wire transfers make up the transaction
- * @param transfers data on each wire transfer
- * @param exchange_uri URI of the exchange that made the transfer
- * @return MHD response object
- */
-struct MHD_Response *
-TMH_RESPONSE_make_track_transaction_ok (unsigned int num_transfers,
- const struct TALER_MERCHANT_TransactionWireTransfer *transfers,
- const char *exchange_uri)
-{
- struct MHD_Response *ret;
- unsigned int i;
- json_t *j_transfers;
- struct TALER_Amount sum;
-
- j_transfers = json_array ();
- for (i=0;i<num_transfers;i++)
- {
- const struct TALER_MERCHANT_TransactionWireTransfer *transfer = &transfers[i];
- unsigned int j;
-
- sum = transfer->coins[0].amount_with_fee;
- for (j=1;j<transfer->num_coins;j++)
- {
- const struct TALER_MERCHANT_CoinWireTransfer *coin = &transfer->coins[j];
-
- GNUNET_assert (GNUNET_SYSERR != TALER_amount_add (&sum,
- &sum,
- &coin->amount_with_fee));
- }
-
- GNUNET_assert (0 ==
- json_array_append_new (j_transfers,
- json_pack ("{s:s, s:o, s:o, s:o}",
- "exchange", exchange_uri,
- "wtid", GNUNET_JSON_from_data_auto (&transfer->wtid),
- "execution_time", GNUNET_JSON_from_time_abs (transfer->execution_time),
- "amount", TALER_JSON_from_amount (&sum))));
- }
- ret = TMH_RESPONSE_make_json (j_transfers);
- json_decref (j_transfers);
- return ret;
-}
-
-
/* end of taler-exchange-httpd_responses.c */
diff --git a/src/backend/taler-merchant-httpd_responses.h b/src/backend/taler-merchant-httpd_responses.h
index 0b552fdd..ea290c5f 100644
--- a/src/backend/taler-merchant-httpd_responses.h
+++ b/src/backend/taler-merchant-httpd_responses.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+ Copyright (C) 2014-2017 GNUnet e.V.
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
@@ -70,20 +70,6 @@ TMH_RESPONSE_make_json_pack (const char *fmt,
/**
- * Generate /track/transaction response.
- *
- * @param num_transfers how many wire transfers make up the transaction
- * @param transfers data on each wire transfer
- * @param exchange_uri URI of the exchange that made the transfer
- * @return MHD response object
- */
-struct MHD_Response *
-TMH_RESPONSE_make_track_transaction_ok (unsigned int num_transfers,
- const struct TALER_MERCHANT_TransactionWireTransfer *transfers,
- const char *exchange_uri);
-
-
-/**
* Function to call to handle the request by building a JSON
* reply from a format string and varargs.
*
diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c
index 9d8768f7..67bfb47b 100644
--- a/src/backend/taler-merchant-httpd_track-transaction.c
+++ b/src/backend/taler-merchant-httpd_track-transaction.c
@@ -44,6 +44,53 @@ extern struct GNUNET_CONTAINER_MultiHashMap *by_id_map;
/**
+ * Generate /track/transaction response.
+ *
+ * @param num_transfers how many wire transfers make up the transaction
+ * @param transfers data on each wire transfer
+ * @param exchange_uri URI of the exchange that made the transfer
+ * @return MHD response object
+ */
+static struct MHD_Response *
+make_track_transaction_ok (unsigned int num_transfers,
+ const struct TALER_MERCHANT_TransactionWireTransfer *transfers,
+ const char *exchange_uri)
+{
+ struct MHD_Response *ret;
+ json_t *j_transfers;
+ struct TALER_Amount sum;
+
+ j_transfers = json_array ();
+ for (unsigned int i=0;i<num_transfers;i++)
+ {
+ const struct TALER_MERCHANT_TransactionWireTransfer *transfer = &transfers[i];
+
+ sum = transfer->coins[0].amount_with_fee;
+ for (unsigned int j=1;j<transfer->num_coins;j++)
+ {
+ const struct TALER_MERCHANT_CoinWireTransfer *coin = &transfer->coins[j];
+
+ GNUNET_assert (GNUNET_SYSERR != TALER_amount_add (&sum,
+ &sum,
+ &coin->amount_with_fee));
+ }
+
+ GNUNET_assert (0 ==
+ json_array_append_new (j_transfers,
+ json_pack ("{s:s, s:o, s:o, s:o}",
+ "exchange", exchange_uri,
+ "wtid", GNUNET_JSON_from_data_auto (&transfer->wtid),
+ "execution_time", GNUNET_JSON_from_time_abs (transfer->execution_time),
+ "amount", TALER_JSON_from_amount (&sum))));
+ }
+ ret = TMH_RESPONSE_make_json (j_transfers);
+ json_decref (j_transfers);
+ return ret;
+}
+
+
+
+/**
* Context for a /track/transaction operation.
*/
struct TrackTransactionContext;
@@ -358,8 +405,6 @@ wire_deposits_cb (void *cls,
const struct TALER_TrackTransferDetails *details)
{
struct TrackTransactionContext *tctx = cls;
- struct TrackCoinContext *tcc;
- unsigned int i;
tctx->wdh = NULL;
if (MHD_HTTP_OK != http_status)
@@ -387,11 +432,13 @@ wire_deposits_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to store transfer-to-proof mapping in DB\n");
}
- for (tcc=tctx->tcc_head;NULL != tcc;tcc=tcc->next)
+ for (struct TrackCoinContext *tcc=tctx->tcc_head;
+ NULL != tcc;
+ tcc=tcc->next)
{
if (GNUNET_YES == tcc->have_wtid)
continue;
- for (i=0;i<details_length;i++)
+ for (unsigned int i=0;i<details_length;i++)
{
if (0 == memcmp (&details[i].coin_pub,
@@ -574,10 +621,11 @@ trace_coins (struct TrackTransactionContext *tctx)
is worst-case O(n^2), in pracitce this is O(n) */
for (tcc = tctx->tcc_head; NULL != tcc; tcc = tcc->next)
{
- struct TrackCoinContext *tcc2;
int found = GNUNET_NO;
- for (tcc2 = tctx->tcc_head; tcc2 != tcc; tcc2 = tcc2->next)
+ for (struct TrackCoinContext *tcc2 = tctx->tcc_head;
+ tcc2 != tcc;
+ tcc2 = tcc2->next)
{
if (0 == memcmp (&tcc->wtid,
&tcc2->wtid,
@@ -601,10 +649,11 @@ trace_coins (struct TrackTransactionContext *tctx)
wtid_off = 0;
for (tcc = tctx->tcc_head; NULL != tcc; tcc = tcc->next)
{
- struct TrackCoinContext *tcc2;
int found = GNUNET_NO;
- for (tcc2 = tctx->tcc_head; tcc2 != tcc; tcc2 = tcc2->next)
+ for (struct TrackCoinContext *tcc2 = tctx->tcc_head;
+ tcc2 != tcc;
+ tcc2 = tcc2->next)
{
if (0 == memcmp (&tcc->wtid,
&tcc2->wtid,
@@ -624,7 +673,9 @@ trace_coins (struct TrackTransactionContext *tctx)
wt->execution_time = tcc->execution_time;
/* count number of coins with this wtid */
num_coins = 0;
- for (tcc2 = tctx->tcc_head; NULL != tcc2; tcc2 = tcc2->next)
+ for (struct TrackCoinContext *tcc2 = tctx->tcc_head;
+ NULL != tcc2;
+ tcc2 = tcc2->next)
{
if (0 == memcmp (&wt->wtid,
&tcc2->wtid,
@@ -636,7 +687,9 @@ trace_coins (struct TrackTransactionContext *tctx)
wt->coins = GNUNET_new_array (num_coins,
struct TALER_MERCHANT_CoinWireTransfer);
num_coins = 0;
- for (tcc2 = tctx->tcc_head; NULL != tcc2; tcc2 = tcc2->next)
+ for (struct TrackCoinContext *tcc2 = tctx->tcc_head;
+ NULL != tcc2;
+ tcc2 = tcc2->next)
{
if (0 == memcmp (&wt->wtid,
&tcc2->wtid,
@@ -653,9 +706,9 @@ trace_coins (struct TrackTransactionContext *tctx)
} /* for all tcc */
GNUNET_assert (wtid_off == num_wtid);
- resp = TMH_RESPONSE_make_track_transaction_ok (num_wtid,
- wts,
- tctx->exchange_uri);
+ resp = make_track_transaction_ok (num_wtid,
+ wts,
+ tctx->exchange_uri);
for (wtid_off=0;wtid_off < num_wtid; wtid_off++)
GNUNET_free (wts[wtid_off].coins);
resume_track_transaction_with_response (tctx,
diff --git a/src/backend/taler-merchant-httpd_track-transfer.c b/src/backend/taler-merchant-httpd_track-transfer.c
index b8644be9..71fdda4e 100644
--- a/src/backend/taler-merchant-httpd_track-transfer.c
+++ b/src/backend/taler-merchant-httpd_track-transfer.c
@@ -130,11 +130,13 @@ struct TrackTransferContext
int check_transfer_result;
};
+
/**
* Represents an entry in the table used to sum up
* individual deposits for each h_contract_terms.
*/
-struct Entry {
+struct Entry
+{
/**
* Sum accumulator for deposited value.
@@ -195,8 +197,8 @@ hashmap_free (void *cls,
void *value)
{
struct TALER_Amount *amount = value;
+
GNUNET_free (amount);
- /*NOTE: how to find out when iteration should stop?*/
return GNUNET_YES;
}
@@ -494,7 +496,6 @@ wire_transfer_cb (void *cls,
const struct TALER_TrackTransferDetails *details)
{
struct TrackTransferContext *rctx = cls;
- unsigned int i;
int ret;
json_t *jresponse;
@@ -534,7 +535,7 @@ wire_transfer_cb (void *cls,
return;
}
rctx->original_response = json;
- for (i=0;i<details_length;i++)
+ for (unsigned int i=0;i<details_length;i++)
{
rctx->current_offset = i;
rctx->current_detail = &details[i];
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 20c49607..bb1f286f 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -1686,7 +1686,7 @@ postgres_get_refunds_from_contract_terms_hash (void *cls,
&grc);
if (0 >= qs)
return qs;
- return grc.qs; /*FIXME: who sets this?*/
+ return grc.qs;
}