Merge branch 'bug-7276'

This commit is contained in:
Christian Grothoff 2022-11-20 21:55:12 +01:00
commit a400aa0fc1
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
13 changed files with 1129 additions and 1133 deletions

View File

@ -1469,92 +1469,92 @@ check_exchange_wire_out (struct WireAccount *wa)
* transactions). * transactions).
* *
* @param cls `struct WireAccount` with current wire account to process * @param cls `struct WireAccount` with current wire account to process
* @param http_status_code http status of the request * @param dhr HTTP response details
* @param ec error code in case something went wrong
* @param row_off identification of the position at which we are querying
* @param details details about the wire transfer
* @param json original response in JSON format
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/ */
static enum GNUNET_GenericReturnValue static void
history_debit_cb (void *cls, history_debit_cb (void *cls,
unsigned int http_status_code, const struct TALER_BANK_DebitHistoryResponse *dhr)
enum TALER_ErrorCode ec,
uint64_t row_off,
const struct TALER_BANK_DebitDetails *details,
const json_t *json)
{ {
struct WireAccount *wa = cls; struct WireAccount *wa = cls;
struct ReserveOutInfo *roi; struct ReserveOutInfo *roi;
size_t slen; size_t slen;
(void) json; wa->dhh = NULL;
if (NULL == details) switch (dhr->http_status)
{ {
wa->dhh = NULL; case MHD_HTTP_OK:
if ( (TALER_EC_NONE != ec) && for (unsigned int i = 0; i<dhr->details.success.details_length; i++)
( (! ignore_account_404) ||
(MHD_HTTP_NOT_FOUND != http_status_code) ) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, const struct TALER_BANK_DebitDetails *dd
"Error fetching debit history of account %s: %u/%u!\n", = &dhr->details.success.details[i];
wa->ai->section_name, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
http_status_code, "Analyzing bank DEBIT at %s of %s with WTID %s\n",
(unsigned int) ec); GNUNET_TIME_timestamp2s (dd->execution_date),
commit (GNUNET_DB_STATUS_HARD_ERROR); TALER_amount2s (&dd->amount),
global_ret = EXIT_FAILURE; TALER_B2S (&dd->wtid));
GNUNET_SCHEDULER_shutdown (); /* Update offset */
return GNUNET_SYSERR; wa->wire_off.out_wire_off = dd->serial_id;
slen = strlen (dd->credit_account_uri) + 1;
roi = GNUNET_malloc (sizeof (struct ReserveOutInfo)
+ slen);
GNUNET_CRYPTO_hash (&dd->wtid,
sizeof (dd->wtid),
&roi->subject_hash);
roi->details.amount = dd->amount;
roi->details.execution_date = dd->execution_date;
roi->details.wtid = dd->wtid;
roi->details.credit_account_uri = (const char *) &roi[1];
memcpy (&roi[1],
dd->credit_account_uri,
slen);
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (out_map,
&roi->subject_hash,
roi,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
char *diagnostic;
GNUNET_asprintf (&diagnostic,
"duplicate subject hash `%s'",
TALER_B2S (&roi->subject_hash));
TALER_ARL_amount_add (&total_wire_format_amount,
&total_wire_format_amount,
&dd->amount);
TALER_ARL_report (report_wire_format_inconsistencies,
GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("amount",
&dd->amount),
GNUNET_JSON_pack_uint64 ("wire_offset",
dd->serial_id),
GNUNET_JSON_pack_string ("diagnostic",
diagnostic)));
GNUNET_free (diagnostic);
}
} }
check_exchange_wire_out (wa); check_exchange_wire_out (wa);
return GNUNET_OK; return;
case MHD_HTTP_NO_CONTENT:
check_exchange_wire_out (wa);
return;
case MHD_HTTP_NOT_FOUND:
if (ignore_account_404)
{
check_exchange_wire_out (wa);
return;
}
break;
default:
break;
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Analyzing bank DEBIT at %s of %s with WTID %s\n", "Error fetching debit history of account %s: %u/%u!\n",
GNUNET_TIME_timestamp2s (details->execution_date), wa->ai->section_name,
TALER_amount2s (&details->amount), dhr->http_status,
TALER_B2S (&details->wtid)); (unsigned int) dhr->ec);
/* Update offset */ commit (GNUNET_DB_STATUS_HARD_ERROR);
wa->wire_off.out_wire_off = row_off; global_ret = EXIT_FAILURE;
slen = strlen (details->credit_account_uri) + 1; GNUNET_SCHEDULER_shutdown ();
roi = GNUNET_malloc (sizeof (struct ReserveOutInfo)
+ slen);
GNUNET_CRYPTO_hash (&details->wtid,
sizeof (details->wtid),
&roi->subject_hash);
roi->details.amount = details->amount;
roi->details.execution_date = details->execution_date;
roi->details.wtid = details->wtid;
roi->details.credit_account_uri = (const char *) &roi[1];
memcpy (&roi[1],
details->credit_account_uri,
slen);
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (out_map,
&roi->subject_hash,
roi,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
char *diagnostic;
GNUNET_asprintf (&diagnostic,
"duplicate subject hash `%s'",
TALER_B2S (&roi->subject_hash));
TALER_ARL_amount_add (&total_wire_format_amount,
&total_wire_format_amount,
&details->amount);
TALER_ARL_report (report_wire_format_inconsistencies,
GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("amount",
&details->amount),
GNUNET_JSON_pack_uint64 ("wire_offset",
row_off),
GNUNET_JSON_pack_string ("diagnostic",
diagnostic)));
GNUNET_free (diagnostic);
return GNUNET_OK;
}
return GNUNET_OK;
} }
@ -1764,69 +1764,49 @@ process_credits (void *cls);
/** /**
* This function is called for all transactions that * We got all of the incoming transactions for @a wa,
* are credited to the exchange's account (incoming * finish processing the account.
* transactions).
* *
* @param cls `struct WireAccount` we are processing * @param[in,out] wa wire account to process
* @param http_status HTTP status returned by the bank
* @param ec error code in case something went wrong
* @param row_off identification of the position at which we are querying
* @param details details about the wire transfer
* @param json raw response
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/ */
static enum GNUNET_GenericReturnValue static void
history_credit_cb (void *cls, conclude_account (struct WireAccount *wa)
unsigned int http_status, {
enum TALER_ErrorCode ec, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
uint64_t row_off, "Reconciling CREDIT processing of account `%s'\n",
const struct TALER_BANK_CreditDetails *details, wa->ai->section_name);
const json_t *json) GNUNET_CONTAINER_multihashmap_iterate (in_map,
&complain_in_not_found,
wa);
/* clean up before 2nd phase */
GNUNET_CONTAINER_multihashmap_iterate (in_map,
&free_rii,
NULL);
process_credits (wa->next);
}
/**
* Analyze credit transation @a details into @a wa.
*
* @param[in,out] wa account that received the transfer
* @param details transfer details
* @return true on success, false to stop loop at this point
*/
static bool
analyze_credit (struct WireAccount *wa,
const struct TALER_BANK_CreditDetails *details)
{ {
struct WireAccount *wa = cls;
struct ReserveInInfo *rii; struct ReserveInInfo *rii;
struct GNUNET_HashCode key; struct GNUNET_HashCode key;
(void) json;
if (NULL == details)
{
wa->chh = NULL;
if ( (TALER_EC_NONE != ec) &&
( (! ignore_account_404) ||
(MHD_HTTP_NOT_FOUND != http_status) ) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error fetching credit history of account %s: %u/%s!\n",
wa->ai->section_name,
http_status,
TALER_ErrorCode_get_hint (ec));
commit (GNUNET_DB_STATUS_HARD_ERROR);
global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_SYSERR;
}
/* end of operation */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Reconciling CREDIT processing of account `%s'\n",
wa->ai->section_name);
GNUNET_CONTAINER_multihashmap_iterate (in_map,
&complain_in_not_found,
wa);
/* clean up before 2nd phase */
GNUNET_CONTAINER_multihashmap_iterate (in_map,
&free_rii,
NULL);
process_credits (wa->next);
return GNUNET_OK;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Analyzing bank CREDIT at %s of %s with Reserve-pub %s\n", "Analyzing bank CREDIT at %s of %s with Reserve-pub %s\n",
GNUNET_TIME_timestamp2s (details->execution_date), GNUNET_TIME_timestamp2s (details->execution_date),
TALER_amount2s (&details->amount), TALER_amount2s (&details->amount),
TALER_B2S (&details->reserve_pub)); TALER_B2S (&details->reserve_pub));
GNUNET_CRYPTO_hash (&row_off, GNUNET_CRYPTO_hash (&details->serial_id,
sizeof (row_off), sizeof (details->serial_id),
&key); &key);
rii = GNUNET_CONTAINER_multihashmap_get (in_map, rii = GNUNET_CONTAINER_multihashmap_get (in_map,
&key); &key);
@ -1835,13 +1815,12 @@ history_credit_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Failed to find wire transfer at `%s' in exchange database. Audit ends at this point in time.\n", "Failed to find wire transfer at `%s' in exchange database. Audit ends at this point in time.\n",
GNUNET_TIME_timestamp2s (details->execution_date)); GNUNET_TIME_timestamp2s (details->execution_date));
wa->chh = NULL;
process_credits (wa->next); process_credits (wa->next);
return GNUNET_SYSERR; /* not an error, just end of processing */ return false; /* not an error, just end of processing */
} }
/* Update offset */ /* Update offset */
wa->wire_off.in_wire_off = row_off; wa->wire_off.in_wire_off = details->serial_id;
/* compare records with expected data */ /* compare records with expected data */
if (0 != GNUNET_memcmp (&details->reserve_pub, if (0 != GNUNET_memcmp (&details->reserve_pub,
&rii->details.reserve_pub)) &rii->details.reserve_pub))
@ -1852,7 +1831,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row", GNUNET_JSON_pack_uint64 ("row",
rii->rowid), rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row", GNUNET_JSON_pack_uint64 ("bank_row",
row_off), details->serial_id),
TALER_JSON_pack_amount ("amount_exchange_expected", TALER_JSON_pack_amount ("amount_exchange_expected",
&rii->details.amount), &rii->details.amount),
TALER_JSON_pack_amount ("amount_wired", TALER_JSON_pack_amount ("amount_wired",
@ -1872,7 +1851,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row", GNUNET_JSON_pack_uint64 ("row",
rii->rowid), rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row", GNUNET_JSON_pack_uint64 ("bank_row",
row_off), details->serial_id),
TALER_JSON_pack_amount ("amount_exchange_expected", TALER_JSON_pack_amount ("amount_exchange_expected",
&zero), &zero),
TALER_JSON_pack_amount ("amount_wired", TALER_JSON_pack_amount ("amount_wired",
@ -1898,7 +1877,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row", GNUNET_JSON_pack_uint64 ("row",
rii->rowid), rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row", GNUNET_JSON_pack_uint64 ("bank_row",
row_off), details->serial_id),
TALER_JSON_pack_amount ("amount_exchange_expected", TALER_JSON_pack_amount ("amount_exchange_expected",
&rii->details.amount), &rii->details.amount),
TALER_JSON_pack_amount ("amount_wired", TALER_JSON_pack_amount ("amount_wired",
@ -1946,7 +1925,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row", GNUNET_JSON_pack_uint64 ("row",
rii->rowid), rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row", GNUNET_JSON_pack_uint64 ("bank_row",
row_off), details->serial_id),
GNUNET_JSON_pack_data_auto ( GNUNET_JSON_pack_data_auto (
"reserve_pub", "reserve_pub",
&rii->details.reserve_pub))); &rii->details.reserve_pub)));
@ -1965,7 +1944,7 @@ history_credit_cb (void *cls,
GNUNET_JSON_pack_uint64 ("row", GNUNET_JSON_pack_uint64 ("row",
rii->rowid), rii->rowid),
GNUNET_JSON_pack_uint64 ("bank_row", GNUNET_JSON_pack_uint64 ("bank_row",
row_off), details->serial_id),
GNUNET_JSON_pack_string ("diagnostic", GNUNET_JSON_pack_string ("diagnostic",
"execution date mismatch"))); "execution date mismatch")));
} }
@ -1974,7 +1953,60 @@ cleanup:
free_rii (NULL, free_rii (NULL,
&key, &key,
rii)); rii));
return GNUNET_OK; return true;
}
/**
* This function is called for all transactions that
* are credited to the exchange's account (incoming
* transactions).
*
* @param cls `struct WireAccount` we are processing
* @param chr HTTP response returned by the bank
*/
static void
history_credit_cb (void *cls,
const struct TALER_BANK_CreditHistoryResponse *chr)
{
struct WireAccount *wa = cls;
wa->chh = NULL;
switch (chr->http_status)
{
case MHD_HTTP_OK:
for (unsigned int i = 0; i<chr->details.success.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd
= &chr->details.success.details[i];
if (! analyze_credit (wa,
cd))
break;
}
conclude_account (wa);
return;
case MHD_HTTP_NO_CONTENT:
conclude_account (wa);
return;
case MHD_HTTP_NOT_FOUND:
if (ignore_account_404)
{
conclude_account (wa);
return;
}
break;
default:
break;
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error fetching credit history of account %s: %u/%s!\n",
wa->ai->section_name,
chr->http_status,
TALER_ErrorCode_get_hint (chr->ec));
commit (GNUNET_DB_STATUS_HARD_ERROR);
global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
} }

View File

@ -77,6 +77,11 @@ static enum GNUNET_GenericReturnValue
parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh, parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
const json_t *history) const json_t *history)
{ {
struct TALER_BANK_CreditHistoryResponse chr = {
.http_status = MHD_HTTP_OK,
.ec = TALER_EC_NONE,
.response = history
};
json_t *history_array; json_t *history_array;
if (NULL == (history_array = json_object_get (history, if (NULL == (history_array = json_object_get (history,
@ -90,49 +95,45 @@ parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
for (unsigned int i = 0; i<json_array_size (history_array); i++)
{ {
struct TALER_BANK_CreditDetails td; size_t len = json_array_size (history_array);
uint64_t row_id; struct TALER_BANK_CreditDetails cd[len];
struct GNUNET_JSON_Specification hist_spec[] = {
TALER_JSON_spec_amount_any ("amount",
&td.amount),
GNUNET_JSON_spec_timestamp ("date",
&td.execution_date),
GNUNET_JSON_spec_uint64 ("row_id",
&row_id),
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
&td.reserve_pub),
GNUNET_JSON_spec_string ("debit_account",
&td.debit_account_uri),
GNUNET_JSON_spec_string ("credit_account",
&td.credit_account_uri),
GNUNET_JSON_spec_end ()
};
json_t *transaction = json_array_get (history_array,
i);
if (GNUNET_OK != for (unsigned int i = 0; i<json_array_size (history_array); i++)
GNUNET_JSON_parse (transaction,
hist_spec,
NULL, NULL))
{ {
GNUNET_break_op (0); struct TALER_BANK_CreditDetails *td = &cd[i];
return GNUNET_SYSERR; struct GNUNET_JSON_Specification hist_spec[] = {
TALER_JSON_spec_amount_any ("amount",
&td->amount),
GNUNET_JSON_spec_timestamp ("date",
&td->execution_date),
GNUNET_JSON_spec_uint64 ("row_id",
&td->serial_id),
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
&td->reserve_pub),
GNUNET_JSON_spec_string ("debit_account",
&td->debit_account_uri),
GNUNET_JSON_spec_string ("credit_account",
&td->credit_account_uri),
GNUNET_JSON_spec_end ()
};
json_t *transaction = json_array_get (history_array,
i);
if (GNUNET_OK !=
GNUNET_JSON_parse (transaction,
hist_spec,
NULL,
NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
} }
if (GNUNET_OK != chr.details.success.details_length = len;
hh->hcb (hh->hcb_cls, chr.details.success.details = cd;
MHD_HTTP_OK, hh->hcb (hh->hcb_cls,
TALER_EC_NONE, &chr);
row_id,
&td,
transaction))
{
hh->hcb = NULL;
GNUNET_JSON_parse_free (hist_spec);
return GNUNET_OK;
}
GNUNET_JSON_parse_free (hist_spec);
} }
return GNUNET_OK; return GNUNET_OK;
} }
@ -152,72 +153,67 @@ handle_credit_history_finished (void *cls,
const void *response) const void *response)
{ {
struct TALER_BANK_CreditHistoryHandle *hh = cls; struct TALER_BANK_CreditHistoryHandle *hh = cls;
const json_t *j = response; struct TALER_BANK_CreditHistoryResponse chr = {
enum TALER_ErrorCode ec; .http_status = MHD_HTTP_OK,
.response = response
};
hh->job = NULL; hh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_GENERIC_INVALID_RESPONSE; chr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
parse_account_history (hh, parse_account_history (hh,
j)) chr.response))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
json_dumpf (j, json_dumpf (chr.response,
stderr, stderr,
JSON_INDENT (2)); JSON_INDENT (2));
response_code = 0; chr.http_status = 0;
ec = TALER_EC_GENERIC_INVALID_RESPONSE; chr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break; break;
} }
response_code = MHD_HTTP_NO_CONTENT; /* signal end of list */ TALER_BANK_credit_history_cancel (hh);
ec = TALER_EC_NONE; return;
break;
case MHD_HTTP_NO_CONTENT: case MHD_HTTP_NO_CONTENT:
ec = TALER_EC_NONE;
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the bank is buggy /* This should never happen, either us or the bank is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
GNUNET_break_op (0); GNUNET_break_op (0);
ec = TALER_JSON_get_error_code (j); chr.ec = TALER_JSON_get_error_code (chr.response);
break; break;
case MHD_HTTP_UNAUTHORIZED: case MHD_HTTP_UNAUTHORIZED:
/* Nothing really to verify, bank says the HTTP Authentication /* Nothing really to verify, bank says the HTTP Authentication
failed. May happen if HTTP authentication is used and the failed. May happen if HTTP authentication is used and the
user supplied a wrong username/password combination. */ user supplied a wrong username/password combination. */
ec = TALER_JSON_get_error_code (j); chr.ec = TALER_JSON_get_error_code (chr.response);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify: the bank is either unaware /* Nothing really to verify: the bank is either unaware
of the endpoint (not a bank), or of the account. of the endpoint (not a bank), or of the account.
We should pass the JSON (?) reply to the application */ We should pass the JSON (?) reply to the application */
ec = TALER_JSON_get_error_code (j); chr.ec = TALER_JSON_get_error_code (chr.response);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); chr.ec = TALER_JSON_get_error_code (chr.response);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u\n",
(unsigned int) response_code); (unsigned int) response_code);
ec = TALER_JSON_get_error_code (j); chr.ec = TALER_JSON_get_error_code (chr.response);
break; break;
} }
if (NULL != hh->hcb) hh->hcb (hh->hcb_cls,
hh->hcb (hh->hcb_cls, &chr);
response_code,
ec,
0LLU,
NULL,
j);
TALER_BANK_credit_history_cancel (hh); TALER_BANK_credit_history_cancel (hh);
} }

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2017--2021 Taler Systems SA Copyright (C) 2017--2022 Taler Systems SA
TALER is free software; you can redistribute it and/or TALER is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
@ -77,6 +77,11 @@ static enum GNUNET_GenericReturnValue
parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh, parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
const json_t *history) const json_t *history)
{ {
struct TALER_BANK_DebitHistoryResponse dhr = {
.http_status = MHD_HTTP_OK,
.ec = TALER_EC_NONE,
.response = history
};
json_t *history_array; json_t *history_array;
if (NULL == (history_array = json_object_get (history, if (NULL == (history_array = json_object_get (history,
@ -90,51 +95,47 @@ parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
for (unsigned int i = 0; i<json_array_size (history_array); i++)
{ {
struct TALER_BANK_DebitDetails td; size_t len = json_array_size (history_array);
uint64_t row_id; struct TALER_BANK_DebitDetails dd[len];
struct GNUNET_JSON_Specification hist_spec[] = {
TALER_JSON_spec_amount_any ("amount",
&td.amount),
GNUNET_JSON_spec_timestamp ("date",
&td.execution_date),
GNUNET_JSON_spec_uint64 ("row_id",
&row_id),
GNUNET_JSON_spec_fixed_auto ("wtid",
&td.wtid),
GNUNET_JSON_spec_string ("credit_account",
&td.credit_account_uri),
GNUNET_JSON_spec_string ("debit_account",
&td.debit_account_uri),
GNUNET_JSON_spec_string ("exchange_base_url",
&td.exchange_base_url),
GNUNET_JSON_spec_end ()
};
json_t *transaction = json_array_get (history_array,
i);
if (GNUNET_OK != for (unsigned int i = 0; i<len; i++)
GNUNET_JSON_parse (transaction,
hist_spec,
NULL, NULL))
{ {
GNUNET_break_op (0); struct TALER_BANK_DebitDetails *td = &dd[i];
return GNUNET_SYSERR; struct GNUNET_JSON_Specification hist_spec[] = {
TALER_JSON_spec_amount_any ("amount",
&td->amount),
GNUNET_JSON_spec_timestamp ("date",
&td->execution_date),
GNUNET_JSON_spec_uint64 ("row_id",
&td->serial_id),
GNUNET_JSON_spec_fixed_auto ("wtid",
&td->wtid),
GNUNET_JSON_spec_string ("credit_account",
&td->credit_account_uri),
GNUNET_JSON_spec_string ("debit_account",
&td->debit_account_uri),
GNUNET_JSON_spec_string ("exchange_base_url",
&td->exchange_base_url),
GNUNET_JSON_spec_end ()
};
json_t *transaction = json_array_get (history_array,
i);
if (GNUNET_OK !=
GNUNET_JSON_parse (transaction,
hist_spec,
NULL,
NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
} }
if (GNUNET_OK != dhr.details.success.details_length = len;
hh->hcb (hh->hcb_cls, dhr.details.success.details = dd;
MHD_HTTP_OK, hh->hcb (hh->hcb_cls,
TALER_EC_NONE, &dhr);
row_id,
&td,
transaction))
{
hh->hcb = NULL;
GNUNET_JSON_parse_free (hist_spec);
return GNUNET_OK;
}
GNUNET_JSON_parse_free (hist_spec);
} }
return GNUNET_OK; return GNUNET_OK;
} }
@ -154,69 +155,64 @@ handle_debit_history_finished (void *cls,
const void *response) const void *response)
{ {
struct TALER_BANK_DebitHistoryHandle *hh = cls; struct TALER_BANK_DebitHistoryHandle *hh = cls;
const json_t *j = response; struct TALER_BANK_DebitHistoryResponse dhr = {
enum TALER_ErrorCode ec; .http_status = MHD_HTTP_OK,
.response = response
};
hh->job = NULL; hh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_GENERIC_INVALID_RESPONSE; dhr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
parse_account_history (hh, parse_account_history (hh,
j)) dhr.response))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; dhr.http_status = 0;
ec = TALER_EC_GENERIC_INVALID_RESPONSE; dhr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break; break;
} }
response_code = MHD_HTTP_NO_CONTENT; /* signal end of list */ TALER_BANK_debit_history_cancel (hh);
ec = TALER_EC_NONE; return;
break;
case MHD_HTTP_NO_CONTENT: case MHD_HTTP_NO_CONTENT:
ec = TALER_EC_NONE;
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the bank is buggy /* This should never happen, either us or the bank is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
GNUNET_break_op (0); GNUNET_break_op (0);
ec = TALER_JSON_get_error_code (j); dhr.ec = TALER_JSON_get_error_code (dhr.response);
break; break;
case MHD_HTTP_UNAUTHORIZED: case MHD_HTTP_UNAUTHORIZED:
/* Nothing really to verify, bank says the HTTP Authentication /* Nothing really to verify, bank says the HTTP Authentication
failed. May happen if HTTP authentication is used and the failed. May happen if HTTP authentication is used and the
user supplied a wrong username/password combination. */ user supplied a wrong username/password combination. */
ec = TALER_JSON_get_error_code (j); dhr.ec = TALER_JSON_get_error_code (dhr.response);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify: the bank is either unaware /* Nothing really to verify: the bank is either unaware
of the endpoint (not a bank), or of the account. of the endpoint (not a bank), or of the account.
We should pass the JSON (?) reply to the application */ We should pass the JSON (?) reply to the application */
ec = TALER_JSON_get_error_code (j); dhr.ec = TALER_JSON_get_error_code (dhr.response);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); dhr.ec = TALER_JSON_get_error_code (dhr.response);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u\n",
(unsigned int) response_code); (unsigned int) response_code);
ec = TALER_JSON_get_error_code (j); dhr.ec = TALER_JSON_get_error_code (dhr.response);
break; break;
} }
if (NULL != hh->hcb) hh->hcb (hh->hcb_cls,
hh->hcb (hh->hcb_cls, &dhr);
response_code,
ec,
0LLU,
NULL,
j);
TALER_BANK_debit_history_cancel (hh); TALER_BANK_debit_history_cancel (hh);
} }

View File

@ -152,83 +152,72 @@ do_shutdown (void *cls)
/** /**
* Callback used to process ONE entry in the transaction * Callback used to process the transaction
* history returned by the bank. * history returned by the bank.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP status code from server * @param reply response we got from the bank
* @param ec taler error code
* @param serial_id identification of the position at
* which we are returning data
* @param details details about the wire transfer
* @param json original full response from server
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to
* abort iteration
*/ */
static enum GNUNET_GenericReturnValue static void
credit_history_cb (void *cls, credit_history_cb (void *cls,
unsigned int http_status, const struct TALER_BANK_CreditHistoryResponse *reply)
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_CreditDetails *details,
const json_t *json)
{ {
(void) cls; (void) cls;
chh = NULL; chh = NULL;
if (MHD_HTTP_OK != http_status) switch (reply->http_status)
{ {
if ( (MHD_HTTP_NO_CONTENT != http_status) || case 0:
(TALER_EC_NONE != ec) ) fprintf (stderr,
{ "Failed to obtain HTTP reply from `%s'\n",
if (0 == http_status) auth.wire_gateway_url);
{ global_ret = 2;
fprintf (stderr, break;
"Failed to obtain HTTP reply from `%s'\n", case MHD_HTTP_NO_CONTENT:
auth.wire_gateway_url);
}
else
{
fprintf (stderr,
"Failed to obtain credit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
http_status,
TALER_ErrorCode_get_hint (ec));
}
if (NULL != json)
json_dumpf (json,
stderr,
JSON_INDENT (2));
global_ret = 2;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_NO;
}
fprintf (stdout, fprintf (stdout,
"End of transactions list.\n"); "No transactions.\n");
global_ret = 0; global_ret = 0;
GNUNET_SCHEDULER_shutdown (); break;
return GNUNET_NO; case MHD_HTTP_OK:
for (unsigned int i = 0; i<reply->details.success.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd =
&reply->details.success.details[i];
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&
(0 != strcasecmp (credit_account,
cd->credit_account_uri) ) )
continue;
if ( (NULL != debit_account) &&
(0 != strcasecmp (debit_account,
cd->debit_account_uri) ) )
continue;
fprintf (stdout,
"%llu: %s->%s (%s) over %s at %s\n",
(unsigned long long) cd->serial_id,
cd->debit_account_uri,
cd->credit_account_uri,
TALER_B2S (&cd->reserve_pub),
TALER_amount2s (&cd->amount),
GNUNET_TIME_timestamp2s (cd->execution_date));
}
global_ret = 0;
break;
default:
fprintf (stderr,
"Failed to obtain credit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
reply->http_status,
TALER_ErrorCode_get_hint (reply->ec));
if (NULL != reply->response)
json_dumpf (reply->response,
stderr,
JSON_INDENT (2));
global_ret = 2;
break;
} }
GNUNET_SCHEDULER_shutdown ();
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&
(0 != strcasecmp (credit_account,
details->credit_account_uri) ) )
return GNUNET_OK;
if ( (NULL != debit_account) &&
(0 != strcasecmp (debit_account,
details->debit_account_uri) ) )
return GNUNET_OK;
fprintf (stdout,
"%llu: %s->%s (%s) over %s at %s\n",
(unsigned long long) serial_id,
details->debit_account_uri,
details->credit_account_uri,
TALER_B2S (&details->reserve_pub),
TALER_amount2s (&details->amount),
GNUNET_TIME_timestamp2s (details->execution_date));
return GNUNET_OK;
} }
@ -264,84 +253,71 @@ execute_credit_history (void)
/** /**
* Function with the debit debit transaction history. * Function with the debit transaction history.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param reply response details
* 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 detailed error code
* @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
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/ */
static enum GNUNET_GenericReturnValue static void
debit_history_cb (void *cls, debit_history_cb (void *cls,
unsigned int http_status, const struct TALER_BANK_DebitHistoryResponse *reply)
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_DebitDetails *details,
const json_t *json)
{ {
(void) cls; (void) cls;
dhh = NULL; dhh = NULL;
if (MHD_HTTP_OK != http_status) switch (reply->http_status)
{ {
if ( (MHD_HTTP_NO_CONTENT != http_status) || case 0:
(TALER_EC_NONE != ec) ) fprintf (stderr,
{ "Failed to obtain HTTP reply from `%s'\n",
if (0 == http_status) auth.wire_gateway_url);
{ global_ret = 2;
fprintf (stderr, break;
"Failed to obtain HTTP reply from `%s'\n", case MHD_HTTP_NO_CONTENT:
auth.wire_gateway_url);
}
else
{
fprintf (stderr,
"Failed to obtain debit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
http_status,
TALER_ErrorCode_get_hint (ec));
}
if (NULL != json)
json_dumpf (json,
stderr,
JSON_INDENT (2));
global_ret = 2;
GNUNET_SCHEDULER_shutdown ();
return GNUNET_NO;
}
fprintf (stdout, fprintf (stdout,
"End of transactions list.\n"); "No transactions.\n");
global_ret = 0; global_ret = 0;
GNUNET_SCHEDULER_shutdown (); break;
return GNUNET_NO; case MHD_HTTP_OK:
for (unsigned int i = 0; i<reply->details.success.details_length; i++)
{
const struct TALER_BANK_DebitDetails *dd =
&reply->details.success.details[i];
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&
(0 != strcasecmp (credit_account,
dd->credit_account_uri) ) )
continue;
if ( (NULL != debit_account) &&
(0 != strcasecmp (debit_account,
dd->debit_account_uri) ) )
continue;
fprintf (stdout,
"%llu: %s->%s (%s) over %s at %s\n",
(unsigned long long) dd->serial_id,
dd->debit_account_uri,
dd->credit_account_uri,
TALER_B2S (&dd->wtid),
TALER_amount2s (&dd->amount),
GNUNET_TIME_timestamp2s (dd->execution_date));
}
global_ret = 0;
break;
default:
fprintf (stderr,
"Failed to obtain debit history from `%s': HTTP status %u (%s)\n",
auth.wire_gateway_url,
reply->http_status,
TALER_ErrorCode_get_hint (reply->ec));
if (NULL != reply->response)
json_dumpf (reply->response,
stderr,
JSON_INDENT (2));
global_ret = 2;
break;
} }
GNUNET_SCHEDULER_shutdown ();
/* If credit/debit accounts were specified, use as a filter */
if ( (NULL != credit_account) &&
(0 != strcasecmp (credit_account,
details->credit_account_uri) ) )
return GNUNET_OK;
if ( (NULL != debit_account) &&
(0 != strcasecmp (debit_account,
details->debit_account_uri) ) )
return GNUNET_OK;
fprintf (stdout,
"%llu: %s->%s (%s) over %s at %s\n",
(unsigned long long) serial_id,
details->debit_account_uri,
details->credit_account_uri,
TALER_B2S (&details->wtid),
TALER_amount2s (&details->amount),
GNUNET_TIME_timestamp2s (details->execution_date));
return GNUNET_OK;
} }

View File

@ -290,7 +290,6 @@ batch_deposit_transaction (void *cls,
mhd_ret); mhd_ret);
if (qs < 0) if (qs < 0)
return qs; return qs;
qs = TEH_plugin->do_deposit ( qs = TEH_plugin->do_deposit (
TEH_plugin->cls, TEH_plugin->cls,
deposit, deposit,

View File

@ -74,20 +74,20 @@ reply_deposit_success (
struct TALER_ExchangeSignatureP sig; struct TALER_ExchangeSignatureP sig;
enum TALER_ErrorCode ec; enum TALER_ErrorCode ec;
if (TALER_EC_NONE != ec = TALER_exchange_online_deposit_confirmation_sign (
(ec = TALER_exchange_online_deposit_confirmation_sign ( &TEH_keys_exchange_sign_,
&TEH_keys_exchange_sign_, h_contract_terms,
h_contract_terms, h_wire,
h_wire, h_policy,
h_policy, exchange_timestamp,
exchange_timestamp, wire_deadline,
wire_deadline, refund_deadline,
refund_deadline, amount_without_fee,
amount_without_fee, coin_pub,
coin_pub, merchant,
merchant, &pub,
&pub, &sig);
&sig))) if (TALER_EC_NONE != ec)
{ {
return TALER_MHD_reply_with_ec (connection, return TALER_MHD_reply_with_ec (connection,
ec, ec,
@ -187,8 +187,6 @@ deposit_transaction (void *cls,
mhd_ret); mhd_ret);
if (qs < 0) if (qs < 0)
return qs; return qs;
/* If the deposit has a policy associated to it, persist it. This will /* If the deposit has a policy associated to it, persist it. This will
* insert or update the record. */ * insert or update the record. */
if (dc->has_policy) if (dc->has_policy)
@ -203,16 +201,14 @@ deposit_transaction (void *cls,
if (qs < 0) if (qs < 0)
return qs; return qs;
} }
qs = TEH_plugin->do_deposit ( qs = TEH_plugin->do_deposit (
TEH_plugin->cls, TEH_plugin->cls,
dc->deposit, dc->deposit,
dc->known_coin_id, dc->known_coin_id,
&dc->h_payto, &dc->h_payto,
(dc->has_policy) (dc->has_policy)
? &dc->policy_details_serial_id ? &dc->policy_details_serial_id
: NULL, : NULL,
&dc->exchange_timestamp, &dc->exchange_timestamp,
&balance_ok, &balance_ok,
&in_conflict); &in_conflict);

File diff suppressed because it is too large Load Diff

View File

@ -26,18 +26,20 @@
#include "pg_helper.h" #include "pg_helper.h"
#include "pg_setup_wire_target.h" #include "pg_setup_wire_target.h"
#include "pg_compute_shard.h" #include "pg_compute_shard.h"
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
TEH_PG_insert_deposit (void *cls, TEH_PG_insert_deposit (void *cls,
struct GNUNET_TIME_Timestamp exchange_timestamp, struct GNUNET_TIME_Timestamp exchange_timestamp,
const struct TALER_EXCHANGEDB_Deposit *deposit) const struct TALER_EXCHANGEDB_Deposit *deposit)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct TALER_PaytoHashP h_payto; struct TALER_PaytoHashP h_payto;
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
qs = TEH_PG_setup_wire_target (pg, qs = TEH_PG_setup_wire_target (pg,
deposit->receiver_wire_account, deposit->receiver_wire_account,
&h_payto); &h_payto);
if (qs < 0) if (qs < 0)
return qs; return qs;
if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline, if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline,

View File

@ -260,6 +260,11 @@ struct TALER_BANK_CreditHistoryHandle;
*/ */
struct TALER_BANK_CreditDetails struct TALER_BANK_CreditDetails
{ {
/**
* Serial ID of the wire transfer.
*/
uint64_t serial_id;
/** /**
* Amount that was transferred * Amount that was transferred
*/ */
@ -271,49 +276,85 @@ struct TALER_BANK_CreditDetails
struct GNUNET_TIME_Timestamp execution_date; struct GNUNET_TIME_Timestamp execution_date;
/** /**
* Reserve public key encoded in the wire * Reserve public key encoded in the wire transfer subject.
* transfer subject.
*/ */
struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReservePublicKeyP reserve_pub;
/** /**
* payto://-URL of the source account that * payto://-URL of the source account that send the funds.
* send the funds.
*/ */
const char *debit_account_uri; const char *debit_account_uri;
/** /**
* payto://-URL of the target account that * payto://-URL of the target account that received the funds.
* received the funds.
*/ */
const char *credit_account_uri; const char *credit_account_uri;
}; };
/**
* Response details for a history request.
*/
struct TALER_BANK_CreditHistoryResponse
{
/**
* HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both
* successful replies, but @e details will only contain @e success information
* if this is set to #MHD_HTTP_OK.
*/
unsigned int http_status;
/**
* Taler error code, #TALER_EC_NONE on success.
*/
enum TALER_ErrorCode ec;
/**
* Full response, NULL if body was not in JSON format.
*/
const json_t *response;
/**
* Details returned depending on the @e http_status.
*/
union
{
/**
* Details if status was #MHD_HTTP_OK
*/
struct
{
/**
* Array of transactions recevied.
*/
const struct TALER_BANK_CreditDetails *details;
/**
* Length of the @e details array.
*/
unsigned int details_length;
} success;
} details;
};
/** /**
* Callbacks of this type are used to serve the result of asking * Callbacks of this type are used to serve the result of asking
* the bank for the credit transaction history. * the bank for the credit transaction history.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param reply details about the response
* 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 detailed error code
* @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
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/ */
typedef enum GNUNET_GenericReturnValue typedef void
(*TALER_BANK_CreditHistoryCallback)( (*TALER_BANK_CreditHistoryCallback)(
void *cls, void *cls,
unsigned int http_status, const struct TALER_BANK_CreditHistoryResponse *reply);
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_CreditDetails *details,
const json_t *json);
/** /**
@ -369,6 +410,11 @@ struct TALER_BANK_DebitHistoryHandle;
*/ */
struct TALER_BANK_DebitDetails struct TALER_BANK_DebitDetails
{ {
/**
* Serial ID of the wire transfer.
*/
uint64_t serial_id;
/** /**
* Amount that was transferred * Amount that was transferred
*/ */
@ -390,44 +436,81 @@ struct TALER_BANK_DebitDetails
const char *exchange_base_url; const char *exchange_base_url;
/** /**
* payto://-URI of the source account that * payto://-URI of the source account that send the funds.
* send the funds.
*/ */
const char *debit_account_uri; const char *debit_account_uri;
/** /**
* payto://-URI of the target account that * payto://-URI of the target account that received the funds.
* received the funds.
*/ */
const char *credit_account_uri; const char *credit_account_uri;
}; };
/**
* Response details for a history request.
*/
struct TALER_BANK_DebitHistoryResponse
{
/**
* HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both
* successful replies, but @e details will only contain @e success information
* if this is set to #MHD_HTTP_OK.
*/
unsigned int http_status;
/**
* Taler error code, #TALER_EC_NONE on success.
*/
enum TALER_ErrorCode ec;
/**
* Full response, NULL if body was not in JSON format.
*/
const json_t *response;
/**
* Details returned depending on the @e http_status.
*/
union
{
/**
* Details if status was #MHD_HTTP_OK
*/
struct
{
/**
* Array of transactions initiated.
*/
const struct TALER_BANK_DebitDetails *details;
/**
* Length of the @e details array.
*/
unsigned int details_length;
} success;
} details;
};
/** /**
* Callbacks of this type are used to serve the result of asking * Callbacks of this type are used to serve the result of asking
* the bank for the debit transaction history. * the bank for the debit transaction history.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param reply details about the response
* 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 detailed error code
* @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
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/ */
typedef enum GNUNET_GenericReturnValue typedef void
(*TALER_BANK_DebitHistoryCallback)( (*TALER_BANK_DebitHistoryCallback)(
void *cls, void *cls,
unsigned int http_status, const struct TALER_BANK_DebitHistoryResponse *reply);
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct TALER_BANK_DebitDetails *details,
const json_t *json);
/** /**

View File

@ -370,99 +370,86 @@ check_result (struct History *h,
* finally check it against what the bank returned. * finally check it against what the bank returned.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code, #MHD_HTTP_OK (200) * @param chr http response details
* 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 status code.
* @param row_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.
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/ */
static enum GNUNET_GenericReturnValue static void
history_cb (void *cls, history_cb (void *cls,
unsigned int http_status, const struct TALER_BANK_CreditHistoryResponse *chr)
enum TALER_ErrorCode ec,
uint64_t row_id,
const struct TALER_BANK_CreditDetails *details,
const json_t *json)
{ {
struct TALER_TESTING_Interpreter *is = cls; struct TALER_TESTING_Interpreter *is = cls;
struct HistoryState *hs = is->commands[is->ip].cls; struct HistoryState *hs = is->commands[is->ip].cls;
(void) row_id; hs->hh = NULL;
if (NULL == details) switch (chr->http_status)
{ {
hs->hh = NULL; case 0:
if ( (MHD_HTTP_NOT_FOUND == http_status) && GNUNET_break (0);
(0 == hs->total) ) goto error;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<chr->details.success.details_length; i++)
{
const struct TALER_BANK_CreditDetails *cd =
&chr->details.success.details[i];
/* check current element */
if (GNUNET_OK !=
check_result (hs->h,
hs->total,
hs->results_obtained,
cd))
{
GNUNET_break (0);
json_dumpf (chr->response,
stderr,
JSON_COMPACT);
hs->failed = true;
hs->hh = NULL;
TALER_TESTING_interpreter_fail (is);
return;
}
hs->results_obtained++;
}
TALER_TESTING_interpreter_next (is);
return;
case MHD_HTTP_NO_CONTENT:
if (0 == hs->total)
{ {
/* not found is OK for empty history */ /* not found is OK for empty history */
TALER_TESTING_interpreter_next (is); TALER_TESTING_interpreter_next (is);
return GNUNET_OK; return;
} }
if ( (hs->results_obtained != hs->total) || GNUNET_break (0);
(hs->failed) || goto error;
(MHD_HTTP_NO_CONTENT != http_status) ) case MHD_HTTP_NOT_FOUND:
if (0 == hs->total)
{ {
GNUNET_break (0); /* not found is OK for empty history */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, TALER_TESTING_interpreter_next (is);
"Expected history of length %u, got %llu;" return;
" HTTP status code: %u/%d, failed: %d\n",
hs->total,
(unsigned long long) hs->results_obtained,
http_status,
(int) ec,
hs->failed ? 1 : 0);
print_expected (hs->h,
hs->total,
UINT_MAX);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
} }
TALER_TESTING_interpreter_next (is); GNUNET_break (0);
return GNUNET_OK; goto error;
} default:
if (MHD_HTTP_OK != http_status)
{
hs->hh = NULL; hs->hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unwanted response code from /history/incoming: %u\n", "Unwanted response code from /history/incoming: %u\n",
http_status); chr->http_status);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR; return;
} }
error:
/* check current element */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
if (GNUNET_OK != "Expected history of length %u, got %llu;"
check_result (hs->h, " HTTP status code: %u/%d, failed: %d\n",
hs->total, hs->total,
hs->results_obtained, (unsigned long long) hs->results_obtained,
details)) chr->http_status,
{ (int) chr->ec,
char *acc; hs->failed ? 1 : 0);
print_expected (hs->h,
GNUNET_break (0); hs->total,
acc = json_dumps (json, UINT_MAX);
JSON_COMPACT); TALER_TESTING_interpreter_fail (is);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Result %u was `%s'\n",
(unsigned int) hs->results_obtained++,
acc);
if (NULL != acc)
free (acc);
hs->failed = true;
hs->hh = NULL;
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
hs->results_obtained++;
return GNUNET_OK;
} }

View File

@ -362,99 +362,86 @@ check_result (struct History *h,
* finally check it against what the bank returned. * finally check it against what the bank returned.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code, #MHD_HTTP_OK (200) * @param dhr http response details
* 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 status code.
* @param row_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.
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/ */
static enum GNUNET_GenericReturnValue static void
history_cb (void *cls, history_cb (void *cls,
unsigned int http_status, const struct TALER_BANK_DebitHistoryResponse *dhr)
enum TALER_ErrorCode ec,
uint64_t row_id,
const struct TALER_BANK_DebitDetails *details,
const json_t *json)
{ {
struct TALER_TESTING_Interpreter *is = cls; struct TALER_TESTING_Interpreter *is = cls;
struct HistoryState *hs = is->commands[is->ip].cls; struct HistoryState *hs = is->commands[is->ip].cls;
(void) row_id; hs->hh = NULL;
if (NULL == details) switch (dhr->http_status)
{ {
hs->hh = NULL; case 0:
if ( (MHD_HTTP_NOT_FOUND == http_status) && GNUNET_break (0);
(0 == hs->total) ) goto error;
case MHD_HTTP_OK:
for (unsigned int i = 0; i<dhr->details.success.details_length; i++)
{
const struct TALER_BANK_DebitDetails *dd =
&dhr->details.success.details[i];
/* check current element */
if (GNUNET_OK !=
check_result (hs->h,
hs->total,
hs->results_obtained,
dd))
{
GNUNET_break (0);
json_dumpf (dhr->response,
stderr,
JSON_COMPACT);
hs->failed = true;
hs->hh = NULL;
TALER_TESTING_interpreter_fail (is);
return;
}
hs->results_obtained++;
}
TALER_TESTING_interpreter_next (is);
return;
case MHD_HTTP_NO_CONTENT:
if (0 == hs->total)
{ {
/* not found is OK for empty history */ /* not found is OK for empty history */
TALER_TESTING_interpreter_next (is); TALER_TESTING_interpreter_next (is);
return GNUNET_OK; return;
} }
if ( (hs->results_obtained != hs->total) ||
(GNUNET_YES == hs->failed) ||
(MHD_HTTP_NO_CONTENT != http_status) )
{
GNUNET_break (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Expected history of length %u, got %llu;"
" HTTP status code: %u/%d, failed: %d\n",
hs->total,
(unsigned long long) hs->results_obtained,
http_status,
(int) ec,
hs->failed);
print_expected (hs->h,
hs->total,
UINT_MAX);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
TALER_TESTING_interpreter_next (is);
return GNUNET_OK;
}
if (MHD_HTTP_OK != http_status)
{
hs->hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unwanted response code from /history/outgoing: %u\n",
http_status);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
/* check current element */
if (GNUNET_OK !=
check_result (hs->h,
hs->total,
hs->results_obtained,
details))
{
char *acc;
GNUNET_break (0); GNUNET_break (0);
acc = json_dumps (json, goto error;
JSON_COMPACT); case MHD_HTTP_NOT_FOUND:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, if (0 == hs->total)
"Result %u was `%s'\n", {
(unsigned int) hs->results_obtained++, /* not found is OK for empty history */
acc); TALER_TESTING_interpreter_next (is);
if (NULL != acc) return;
free (acc); }
hs->failed = GNUNET_YES; GNUNET_break (0);
goto error;
default:
hs->hh = NULL; hs->hh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unwanted response code from /history/incoming: %u\n",
dhr->http_status);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR; return;
} }
hs->results_obtained++; error:
return GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Expected history of length %u, got %llu;"
" HTTP status code: %u/%d, failed: %d\n",
hs->total,
(unsigned long long) hs->results_obtained,
dhr->http_status,
(int) dhr->ec,
hs->failed ? 1 : 0);
print_expected (hs->h,
hs->total,
UINT_MAX);
TALER_TESTING_interpreter_fail (is);
} }

View File

@ -90,8 +90,7 @@ TALER_TESTING_history_entry_cmp (
(GNUNET_TIME_timestamp_cmp ( (GNUNET_TIME_timestamp_cmp (
h1->details.history_details.request_timestamp, h1->details.history_details.request_timestamp,
==, ==,
h2->details.history_details. h2->details.history_details.request_timestamp)) &&
request_timestamp)) &&
(0 == (0 ==
GNUNET_memcmp (&h1->details.history_details.reserve_sig, GNUNET_memcmp (&h1->details.history_details.reserve_sig,
&h2->details.history_details.reserve_sig)) ) &h2->details.history_details.reserve_sig)) )
@ -131,10 +130,42 @@ TALER_TESTING_history_entry_cmp (
return 0; return 0;
return 1; return 1;
case TALER_EXCHANGE_RTT_OPEN: case TALER_EXCHANGE_RTT_OPEN:
// FIXME: verify response... if ( (0 ==
TALER_amount_cmp (&h1->amount,
&h2->amount)) &&
(GNUNET_TIME_timestamp_cmp (
h1->details.open_request.request_timestamp,
==,
h2->details.open_request.request_timestamp)) &&
(GNUNET_TIME_timestamp_cmp (
h1->details.open_request.reserve_expiration,
==,
h2->details.open_request.reserve_expiration)) &&
(h1->details.open_request.purse_limit ==
h2->details.open_request.purse_limit) &&
(0 ==
TALER_amount_cmp (&h1->details.open_request.reserve_payment,
&h2->details.open_request.reserve_payment)) &&
(0 ==
GNUNET_memcmp (&h1->details.open_request.reserve_sig,
&h2->details.open_request.reserve_sig)) )
return 0;
return 1; return 1;
case TALER_EXCHANGE_RTT_CLOSE: case TALER_EXCHANGE_RTT_CLOSE:
// FIXME: verify response... if ( (0 ==
TALER_amount_cmp (&h1->amount,
&h2->amount)) &&
(GNUNET_TIME_timestamp_cmp (
h1->details.close_request.request_timestamp,
==,
h2->details.close_request.request_timestamp)) &&
(0 ==
GNUNET_memcmp (&h1->details.close_request.target_account_h_payto,
&h2->details.close_request.target_account_h_payto)) &&
(0 ==
GNUNET_memcmp (&h1->details.close_request.reserve_sig,
&h2->details.close_request.reserve_sig)) )
return 0;
return 1; return 1;
} }
GNUNET_assert (0); GNUNET_assert (0);

View File

@ -71,6 +71,7 @@ wirewatch_run (void *cls,
"-S", "1", "-S", "1",
"-w", "0", "-w", "0",
"-t", /* exit when done */ "-t", /* exit when done */
"-L", "DEBUG",
NULL); NULL);
if (NULL == ws->wirewatch_proc) if (NULL == ws->wirewatch_proc)
{ {