largely fix #5077
This commit is contained in:
parent
5540747ca2
commit
042616899f
@ -830,6 +830,7 @@ check_exchange_wire_out ()
|
|||||||
* transactions).
|
* transactions).
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param ec error code in case something went wrong
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param row_off identification of the position at which we are querying
|
* @param row_off identification of the position at which we are querying
|
||||||
* @param row_off_size number of bytes in @a row_off
|
* @param row_off_size number of bytes in @a row_off
|
||||||
@ -838,6 +839,7 @@ check_exchange_wire_out ()
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
history_debit_cb (void *cls,
|
history_debit_cb (void *cls,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
const void *row_off,
|
const void *row_off,
|
||||||
size_t row_off_size,
|
size_t row_off_size,
|
||||||
@ -848,6 +850,13 @@ history_debit_cb (void *cls,
|
|||||||
|
|
||||||
if (TALER_BANK_DIRECTION_NONE == dir)
|
if (TALER_BANK_DIRECTION_NONE == dir)
|
||||||
{
|
{
|
||||||
|
if (TALER_EC_NONE != ec)
|
||||||
|
{
|
||||||
|
/* FIXME: log properly to audit report! */
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Error fetching history: %u!\n",
|
||||||
|
(unsigned int) ec);
|
||||||
|
}
|
||||||
/* end of iteration, now check wire_out to see
|
/* end of iteration, now check wire_out to see
|
||||||
if it matches #out_map */
|
if it matches #out_map */
|
||||||
hh = NULL;
|
hh = NULL;
|
||||||
@ -1069,6 +1078,7 @@ conclude_credit_history ()
|
|||||||
* transactions).
|
* transactions).
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param ec error code in case something went wrong
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param row_off identification of the position at which we are querying
|
* @param row_off identification of the position at which we are querying
|
||||||
* @param row_off_size number of bytes in @a row_off
|
* @param row_off_size number of bytes in @a row_off
|
||||||
@ -1077,6 +1087,7 @@ conclude_credit_history ()
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
history_credit_cb (void *cls,
|
history_credit_cb (void *cls,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
const void *row_off,
|
const void *row_off,
|
||||||
size_t row_off_size,
|
size_t row_off_size,
|
||||||
@ -1087,6 +1098,13 @@ history_credit_cb (void *cls,
|
|||||||
|
|
||||||
if (TALER_BANK_DIRECTION_NONE == dir)
|
if (TALER_BANK_DIRECTION_NONE == dir)
|
||||||
{
|
{
|
||||||
|
if (TALER_EC_NONE != ec)
|
||||||
|
{
|
||||||
|
/* FIXME: log properly to audit report! */
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Error fetching history: %u!\n",
|
||||||
|
(unsigned int) ec);
|
||||||
|
}
|
||||||
/* end of operation */
|
/* end of operation */
|
||||||
hh = NULL;
|
hh = NULL;
|
||||||
conclude_credit_history ();
|
conclude_credit_history ();
|
||||||
|
@ -17,7 +17,8 @@ libtalerbank_la_LDFLAGS = \
|
|||||||
libtalerbank_la_SOURCES = \
|
libtalerbank_la_SOURCES = \
|
||||||
bank_api_admin.c \
|
bank_api_admin.c \
|
||||||
bank_api_common.c bank_api_common.h \
|
bank_api_common.c bank_api_common.h \
|
||||||
bank_api_history.c
|
bank_api_history.c \
|
||||||
|
bank_api_reject.c
|
||||||
|
|
||||||
libtalerbank_la_LIBADD = \
|
libtalerbank_la_LIBADD = \
|
||||||
$(top_builddir)/src/json/libtalerjson.la \
|
$(top_builddir)/src/json/libtalerjson.la \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2015, 2016, 2017 GNUnet e.V.
|
Copyright (C) 2015, 2016, 2017 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the GNU General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -79,11 +79,13 @@ handle_admin_add_incoming_finished (void *cls,
|
|||||||
{
|
{
|
||||||
struct TALER_BANK_AdminAddIncomingHandle *aai = cls;
|
struct TALER_BANK_AdminAddIncomingHandle *aai = cls;
|
||||||
uint64_t serial_id = UINT64_MAX;
|
uint64_t serial_id = UINT64_MAX;
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
aai->job = NULL;
|
aai->job = NULL;
|
||||||
switch (response_code)
|
switch (response_code)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
ec = TALER_EC_INVALID_RESPONSE;
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
{
|
{
|
||||||
@ -100,29 +102,36 @@ handle_admin_add_incoming_finished (void *cls,
|
|||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
response_code = 0;
|
response_code = 0;
|
||||||
|
ec = TALER_EC_INVALID_RESPONSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
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 */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_FORBIDDEN:
|
case MHD_HTTP_FORBIDDEN:
|
||||||
/* Access denied */
|
/* Access denied */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_UNAUTHORIZED:
|
case MHD_HTTP_UNAUTHORIZED:
|
||||||
/* Nothing really to verify, bank says one of the signatures is
|
/* Nothing really to verify, bank says one of the signatures is
|
||||||
invalid; as we checked them, this should never happen, we
|
invalid; as we checked them, this should never happen, we
|
||||||
should pass the JSON reply to the application */
|
should pass the JSON reply to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_NOT_FOUND:
|
case MHD_HTTP_NOT_FOUND:
|
||||||
/* Nothing really to verify, this should never
|
/* Nothing really to verify, this should never
|
||||||
happen, we should pass the JSON reply to the application */
|
happen, we should pass the JSON reply to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
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_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* unexpected response code */
|
/* unexpected response code */
|
||||||
@ -130,11 +139,13 @@ handle_admin_add_incoming_finished (void *cls,
|
|||||||
"Unexpected response code %u\n",
|
"Unexpected response code %u\n",
|
||||||
(unsigned int) response_code);
|
(unsigned int) response_code);
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
response_code = 0;
|
response_code = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
aai->cb (aai->cb_cls,
|
aai->cb (aai->cb_cls,
|
||||||
response_code,
|
response_code,
|
||||||
|
ec,
|
||||||
serial_id,
|
serial_id,
|
||||||
json);
|
json);
|
||||||
TALER_BANK_admin_add_incoming_cancel (aai);
|
TALER_BANK_admin_add_incoming_cancel (aai);
|
||||||
@ -151,7 +162,7 @@ handle_admin_add_incoming_finished (void *cls,
|
|||||||
* @param bank_base_url URL of the bank (used to execute this request)
|
* @param bank_base_url URL of the bank (used to execute this request)
|
||||||
* @param auth authentication data to send to the bank
|
* @param auth authentication data to send to the bank
|
||||||
* @param exchange_base_url base URL of the exchange (for tracking)
|
* @param exchange_base_url base URL of the exchange (for tracking)
|
||||||
* @param wtid wire transfer identifier for the transfer
|
* @param subject wire transfer subject for the transfer
|
||||||
* @param amount amount that was deposited
|
* @param amount amount that was deposited
|
||||||
* @param debit_account_no account number to withdraw from (53 bits at most)
|
* @param debit_account_no account number to withdraw from (53 bits at most)
|
||||||
* @param credit_account_no account number to deposit into (53 bits at most)
|
* @param credit_account_no account number to deposit into (53 bits at most)
|
||||||
@ -166,7 +177,7 @@ TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
|
|||||||
const char *bank_base_url,
|
const char *bank_base_url,
|
||||||
const struct TALER_BANK_AuthenticationData *auth,
|
const struct TALER_BANK_AuthenticationData *auth,
|
||||||
const char *exchange_base_url,
|
const char *exchange_base_url,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const char *subject,
|
||||||
const struct TALER_Amount *amount,
|
const struct TALER_Amount *amount,
|
||||||
uint64_t debit_account_no,
|
uint64_t debit_account_no,
|
||||||
uint64_t credit_account_no,
|
uint64_t credit_account_no,
|
||||||
@ -182,10 +193,10 @@ TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
|
|||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
admin_obj = json_pack ("{s:{s:s}, s:s, s:o, s:o, s:I, s:I}",
|
admin_obj = json_pack ("{s:{s:s}, s:s, s:s, s:o, s:I, s:I}",
|
||||||
"auth", "type", "basic",
|
"auth", "type", "basic",
|
||||||
"exchange_url", exchange_base_url,
|
"exchange_url", exchange_base_url,
|
||||||
"wtid", GNUNET_JSON_from_data_auto (wtid),
|
"subject", subject,
|
||||||
"amount", TALER_JSON_from_amount (amount),
|
"amount", TALER_JSON_from_amount (amount),
|
||||||
"debit_account", (json_int_t) debit_account_no,
|
"debit_account", (json_int_t) debit_account_no,
|
||||||
"credit_account", (json_int_t) credit_account_no);
|
"credit_account", (json_int_t) credit_account_no);
|
||||||
|
@ -111,5 +111,33 @@ TALER_BANK_path_to_url_ (const char *u,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse error code given in @a json.
|
||||||
|
*
|
||||||
|
* @param json the json to parse
|
||||||
|
* @return error code, or #TALER_EC_INVALID if not found
|
||||||
|
*/
|
||||||
|
enum TALER_ErrorCode
|
||||||
|
TALER_BANK_parse_ec_ (const json_t *json)
|
||||||
|
{
|
||||||
|
uint32_t ec;
|
||||||
|
|
||||||
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
|
GNUNET_JSON_spec_uint32 ("ec",
|
||||||
|
&ec),
|
||||||
|
GNUNET_JSON_spec_end()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_JSON_parse (json,
|
||||||
|
spec,
|
||||||
|
NULL, NULL))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return TALER_EC_INVALID;
|
||||||
|
}
|
||||||
|
return (enum TALER_ErrorCode) ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of bank_api_common.c */
|
/* end of bank_api_common.c */
|
||||||
|
@ -51,4 +51,14 @@ TALER_BANK_path_to_url_ (const char *u,
|
|||||||
const char *path);
|
const char *path);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse error code given in @a json.
|
||||||
|
*
|
||||||
|
* @param json the json to parse
|
||||||
|
* @return error code, or #TALER_EC_INVALID if not found
|
||||||
|
*/
|
||||||
|
enum TALER_ErrorCode
|
||||||
|
TALER_BANK_parse_ec_ (const json_t *json);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -118,22 +118,37 @@ parse_account_history (struct TALER_BANK_HistoryHandle *hh,
|
|||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 == strcasecmp (sign,
|
||||||
|
"+"))
|
||||||
|
direction = TALER_BANK_DIRECTION_CREDIT;
|
||||||
|
else if (0 == strcasecmp (sign,
|
||||||
|
"-"))
|
||||||
|
direction = TALER_BANK_DIRECTION_DEBIT;
|
||||||
|
else if (0 == strcasecmp (sign,
|
||||||
|
"cancel+"))
|
||||||
|
direction = TALER_BANK_DIRECTION_CREDIT | TALER_BANK_DIRECTION_CANCEL;
|
||||||
|
else if (0 == strcasecmp (sign,
|
||||||
|
"cancel-"))
|
||||||
|
direction = TALER_BANK_DIRECTION_DEBIT | TALER_BANK_DIRECTION_CANCEL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_JSON_parse_free (hist_spec);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
td.account_details = json_pack ("{s:s, s:s, s:I}",
|
td.account_details = json_pack ("{s:s, s:s, s:I}",
|
||||||
"type", "test",
|
"type", "test",
|
||||||
"bank_uri", hh->bank_base_url,
|
"bank_uri", hh->bank_base_url,
|
||||||
"account_number", (json_int_t) other_account);
|
"account_number", (json_int_t) other_account);
|
||||||
direction = (0 == strcasecmp (sign,
|
|
||||||
"+"))
|
|
||||||
? TALER_BANK_DIRECTION_CREDIT
|
|
||||||
: TALER_BANK_DIRECTION_DEBIT;
|
|
||||||
hh->hcb (hh->hcb_cls,
|
hh->hcb (hh->hcb_cls,
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
|
TALER_EC_NONE,
|
||||||
direction,
|
direction,
|
||||||
serial_id,
|
serial_id,
|
||||||
&td,
|
&td,
|
||||||
transaction);
|
transaction);
|
||||||
GNUNET_JSON_parse_free (hist_spec);
|
|
||||||
json_decref (td.account_details);
|
json_decref (td.account_details);
|
||||||
|
GNUNET_JSON_parse_free (hist_spec);
|
||||||
}
|
}
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
@ -153,6 +168,7 @@ handle_history_finished (void *cls,
|
|||||||
const json_t *json)
|
const json_t *json)
|
||||||
{
|
{
|
||||||
struct TALER_BANK_HistoryHandle *hh = cls;
|
struct TALER_BANK_HistoryHandle *hh = cls;
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
hh->job = NULL;
|
hh->job = NULL;
|
||||||
switch (response_code)
|
switch (response_code)
|
||||||
@ -166,31 +182,38 @@ handle_history_finished (void *cls,
|
|||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
response_code = 0;
|
response_code = 0;
|
||||||
|
ec = TALER_EC_INVALID_RESPONSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
response_code = MHD_HTTP_NO_CONTENT; /* signal end of list */
|
response_code = MHD_HTTP_NO_CONTENT; /* signal end of list */
|
||||||
break;
|
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 */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_FORBIDDEN:
|
case MHD_HTTP_FORBIDDEN:
|
||||||
/* Access denied */
|
/* Access denied */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_UNAUTHORIZED:
|
case MHD_HTTP_UNAUTHORIZED:
|
||||||
/* Nothing really to verify, bank says one of the signatures is
|
/* Nothing really to verify, bank says one of the signatures is
|
||||||
invalid; as we checked them, this should never happen, we
|
invalid; as we checked them, this should never happen, we
|
||||||
should pass the JSON reply to the application */
|
should pass the JSON reply to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_NOT_FOUND:
|
case MHD_HTTP_NOT_FOUND:
|
||||||
/* Nothing really to verify, this should never
|
/* Nothing really to verify, this should never
|
||||||
happen, we should pass the JSON reply to the application */
|
happen, we should pass the JSON reply to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
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_BANK_parse_ec_ (json);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* unexpected response code */
|
/* unexpected response code */
|
||||||
@ -198,11 +221,13 @@ handle_history_finished (void *cls,
|
|||||||
"Unexpected response code %u\n",
|
"Unexpected response code %u\n",
|
||||||
(unsigned int) response_code);
|
(unsigned int) response_code);
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
response_code = 0;
|
response_code = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hh->hcb (hh->hcb_cls,
|
hh->hcb (hh->hcb_cls,
|
||||||
response_code,
|
response_code,
|
||||||
|
ec,
|
||||||
TALER_BANK_DIRECTION_NONE,
|
TALER_BANK_DIRECTION_NONE,
|
||||||
0LLU,
|
0LLU,
|
||||||
NULL,
|
NULL,
|
||||||
@ -243,6 +268,8 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
|
|||||||
struct TALER_BANK_HistoryHandle *hh;
|
struct TALER_BANK_HistoryHandle *hh;
|
||||||
CURL *eh;
|
CURL *eh;
|
||||||
char *url;
|
char *url;
|
||||||
|
const char *dir;
|
||||||
|
const char *can;
|
||||||
|
|
||||||
if (0 == num_results)
|
if (0 == num_results)
|
||||||
{
|
{
|
||||||
@ -254,36 +281,42 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
|
|||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dir = NULL;
|
||||||
|
if (TALER_BANK_DIRECTION_BOTH == (TALER_BANK_DIRECTION_BOTH & direction))
|
||||||
|
dir = "both";
|
||||||
|
else if (TALER_BANK_DIRECTION_CREDIT == (TALER_BANK_DIRECTION_CREDIT & direction))
|
||||||
|
dir = "credit";
|
||||||
|
else if (TALER_BANK_DIRECTION_DEBIT == (TALER_BANK_DIRECTION_BOTH & direction))
|
||||||
|
dir = "debit";
|
||||||
|
if (NULL == dir)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (TALER_BANK_DIRECTION_CANCEL == (TALER_BANK_DIRECTION_CANCEL & direction))
|
||||||
|
can = "show";
|
||||||
|
else
|
||||||
|
can = "omit";
|
||||||
if (UINT64_MAX == start_row)
|
if (UINT64_MAX == start_row)
|
||||||
{
|
{
|
||||||
if (TALER_BANK_DIRECTION_BOTH == direction)
|
|
||||||
GNUNET_asprintf (&url,
|
GNUNET_asprintf (&url,
|
||||||
"/history?auth=basic&account_number=%llu&delta=%lld",
|
"/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s",
|
||||||
(unsigned long long) account_number,
|
|
||||||
(long long) num_results);
|
|
||||||
else
|
|
||||||
GNUNET_asprintf (&url,
|
|
||||||
"/history?auth=basic&account_number=%llu&delta=%lld&direction=%s",
|
|
||||||
(unsigned long long) account_number,
|
(unsigned long long) account_number,
|
||||||
(long long) num_results,
|
(long long) num_results,
|
||||||
(TALER_BANK_DIRECTION_CREDIT == direction) ? "credit" : "debit");
|
dir,
|
||||||
|
can);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (TALER_BANK_DIRECTION_BOTH == direction)
|
|
||||||
GNUNET_asprintf (&url,
|
GNUNET_asprintf (&url,
|
||||||
"/history?auth=basic&account_number=%llu&delta=%lld&start=%llu",
|
"/history?auth=basic&account_number=%llu&delta=%lld&start=%llu&direction=%s&cancelled=%s",
|
||||||
(unsigned long long) account_number,
|
|
||||||
(long long) num_results,
|
|
||||||
(unsigned long long) start_row);
|
|
||||||
else
|
|
||||||
GNUNET_asprintf (&url,
|
|
||||||
"/history?auth=basic&account_number=%llu&delta=%lld&start=%llu&direction=%s",
|
|
||||||
(unsigned long long) account_number,
|
(unsigned long long) account_number,
|
||||||
(long long) num_results,
|
(long long) num_results,
|
||||||
(unsigned long long) start_row,
|
(unsigned long long) start_row,
|
||||||
(TALER_BANK_DIRECTION_CREDIT == direction) ? "credit" : "debit");
|
dir,
|
||||||
|
can);
|
||||||
}
|
}
|
||||||
|
|
||||||
hh = GNUNET_new (struct TALER_BANK_HistoryHandle);
|
hh = GNUNET_new (struct TALER_BANK_HistoryHandle);
|
||||||
|
245
src/bank-lib/bank_api_reject.c
Normal file
245
src/bank-lib/bank_api_reject.c
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
Copyright (C) 2015, 2016, 2017 Taler Systems SA
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
TALER; see the file COPYING. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file bank-lib/bank_api_reject.c
|
||||||
|
* @brief Implementation of the /reject request of the bank's HTTP API
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#include "platform.h"
|
||||||
|
#include "bank_api_common.h"
|
||||||
|
#include <microhttpd.h> /* just for HTTP status codes */
|
||||||
|
#include "taler_signatures.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A /reject Handle
|
||||||
|
*/
|
||||||
|
struct TALER_BANK_RejectHandle
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The url for this request.
|
||||||
|
*/
|
||||||
|
char *request_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON encoding of the request to POST.
|
||||||
|
*/
|
||||||
|
char *json_enc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for the request.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CURL_Job *job;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP authentication-related headers for the request.
|
||||||
|
*/
|
||||||
|
struct curl_slist *authh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to call with the result.
|
||||||
|
*/
|
||||||
|
TALER_BANK_RejectResultCallback cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for @a cb.
|
||||||
|
*/
|
||||||
|
void *cb_cls;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when we're done processing the
|
||||||
|
* HTTP /reject request.
|
||||||
|
*
|
||||||
|
* @param cls the `struct TALER_BANK_RejectHandle`
|
||||||
|
* @param response_code HTTP response code, 0 on error
|
||||||
|
* @param json parsed JSON result, NULL on error
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
handle_reject_finished (void *cls,
|
||||||
|
long response_code,
|
||||||
|
const json_t *json)
|
||||||
|
{
|
||||||
|
struct TALER_BANK_RejectHandle *rh = cls;
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
|
rh->job = NULL;
|
||||||
|
switch (response_code)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ec = TALER_EC_INVALID_RESPONSE;
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_OK:
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
response_code = 0;
|
||||||
|
ec = TALER_EC_INVALID_RESPONSE;
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_NO_CONTENT:
|
||||||
|
ec = TALER_EC_NONE;
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_BAD_REQUEST:
|
||||||
|
/* This should never happen, either us or the bank is buggy
|
||||||
|
(or API version conflict); just pass JSON reply to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_FORBIDDEN:
|
||||||
|
/* Access denied */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_UNAUTHORIZED:
|
||||||
|
/* Nothing really to verify, bank says one of the signatures is
|
||||||
|
invalid; as we checked them, this should never happen, we
|
||||||
|
should pass the JSON reply to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_NOT_FOUND:
|
||||||
|
/* Nothing really to verify, this should never
|
||||||
|
happen, we should pass the JSON reply to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||||
|
/* Server had an internal issue; we should retry, but this API
|
||||||
|
leaves this to the application */
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unexpected response code */
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Unexpected response code %u\n",
|
||||||
|
(unsigned int) response_code);
|
||||||
|
GNUNET_break (0);
|
||||||
|
ec = TALER_BANK_parse_ec_ (json);
|
||||||
|
response_code = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rh->cb (rh->cb_cls,
|
||||||
|
response_code,
|
||||||
|
ec);
|
||||||
|
TALER_BANK_reject_cancel (rh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request rejection of a wire transfer, marking it as cancelled and voiding
|
||||||
|
* its effects.
|
||||||
|
*
|
||||||
|
* @param ctx curl context for the event loop
|
||||||
|
* @param bank_base_url URL of the bank (used to execute this request)
|
||||||
|
* @param auth authentication data to use
|
||||||
|
* @param account_number which account number should we query
|
||||||
|
* @param rowid transfer to reject
|
||||||
|
* @param rcb the callback to call with the operation result
|
||||||
|
* @param rcb_cls closure for @a rcb
|
||||||
|
* @return NULL
|
||||||
|
* if the inputs are invalid.
|
||||||
|
* In this case, the callback is not called.
|
||||||
|
*/
|
||||||
|
struct TALER_BANK_RejectHandle *
|
||||||
|
TALER_BANK_reject (struct GNUNET_CURL_Context *ctx,
|
||||||
|
const char *bank_base_url,
|
||||||
|
const struct TALER_BANK_AuthenticationData *auth,
|
||||||
|
uint64_t account_number,
|
||||||
|
uint64_t rowid,
|
||||||
|
TALER_BANK_RejectResultCallback rcb,
|
||||||
|
void *rcb_cls)
|
||||||
|
{
|
||||||
|
struct TALER_BANK_RejectHandle *rh;
|
||||||
|
json_t *reject_obj;
|
||||||
|
CURL *eh;
|
||||||
|
|
||||||
|
reject_obj = json_pack ("{s:{s:s}, s:I, s:I}",
|
||||||
|
"auth", "type", "basic",
|
||||||
|
"row_id", (json_int_t) rowid,
|
||||||
|
"credit_account", (json_int_t) account_number);
|
||||||
|
if (NULL == reject_obj)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
rh = GNUNET_new (struct TALER_BANK_RejectHandle);
|
||||||
|
rh->cb = rcb;
|
||||||
|
rh->cb_cls = rcb_cls;
|
||||||
|
rh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
|
||||||
|
"/reject");
|
||||||
|
rh->authh = TALER_BANK_make_auth_header_ (auth);
|
||||||
|
/* Append content type header here, can't do it in GNUNET_CURL_job_add
|
||||||
|
as that would override the CURLOPT_HTTPHEADER instead of appending. */
|
||||||
|
{
|
||||||
|
struct curl_slist *ext;
|
||||||
|
|
||||||
|
ext = curl_slist_append (rh->authh,
|
||||||
|
"Content-Type: application/json");
|
||||||
|
if (NULL == ext)
|
||||||
|
GNUNET_break (0);
|
||||||
|
else
|
||||||
|
rh->authh = ext;
|
||||||
|
}
|
||||||
|
eh = curl_easy_init ();
|
||||||
|
GNUNET_assert (NULL != (rh->json_enc =
|
||||||
|
json_dumps (reject_obj,
|
||||||
|
JSON_COMPACT)));
|
||||||
|
json_decref (reject_obj);
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_HTTPHEADER,
|
||||||
|
rh->authh));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_URL,
|
||||||
|
rh->request_url));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_POSTFIELDS,
|
||||||
|
rh->json_enc));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_POSTFIELDSIZE,
|
||||||
|
strlen (rh->json_enc)));
|
||||||
|
rh->job = GNUNET_CURL_job_add (ctx,
|
||||||
|
eh,
|
||||||
|
GNUNET_NO,
|
||||||
|
&handle_reject_finished,
|
||||||
|
rh);
|
||||||
|
return rh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel an reject request. This function cannot be used on a request
|
||||||
|
* handle if the response was is already served for it.
|
||||||
|
*
|
||||||
|
* @param rh the reject request handle
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_BANK_reject_cancel (struct TALER_BANK_RejectHandle *rh)
|
||||||
|
{
|
||||||
|
if (NULL != rh->job)
|
||||||
|
{
|
||||||
|
GNUNET_CURL_job_cancel (rh->job);
|
||||||
|
rh->job = NULL;
|
||||||
|
}
|
||||||
|
curl_slist_free_all (rh->authh);
|
||||||
|
GNUNET_free (rh->request_url);
|
||||||
|
GNUNET_free (rh->json_enc);
|
||||||
|
GNUNET_free (rh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end of bank_api_reject.c */
|
@ -81,6 +81,11 @@ struct Transaction
|
|||||||
* Number of this transaction.
|
* Number of this transaction.
|
||||||
*/
|
*/
|
||||||
uint64_t serial_id;
|
uint64_t serial_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag set if the transfer was rejected.
|
||||||
|
*/
|
||||||
|
int rejected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -219,6 +224,31 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject incoming wire transfer to account @a credit_account
|
||||||
|
* as identified by @a rowid.
|
||||||
|
*
|
||||||
|
* @param h fake bank handle
|
||||||
|
* @param rowid identifies transfer to reject
|
||||||
|
* @param credit_account account number of owner of credited account
|
||||||
|
* @return #GNUNET_YES on success, #GNUNET_NO if the wire transfer was not found
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TALER_FAKEBANK_reject_transfer (struct TALER_FAKEBANK_Handle *h,
|
||||||
|
uint64_t rowid,
|
||||||
|
uint64_t credit_account)
|
||||||
|
{
|
||||||
|
for (struct Transaction *t = h->transactions_head; NULL != t; t = t->next)
|
||||||
|
if ( (t->serial_id == rowid) &&
|
||||||
|
(t->credit_account == credit_account) )
|
||||||
|
{
|
||||||
|
t->rejected = GNUNET_YES;
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that no wire transfers were ordered (or at least none
|
* Check that no wire transfers were ordered (or at least none
|
||||||
* that have not been taken care of via #TALER_FAKEBANK_check()).
|
* that have not been taken care of via #TALER_FAKEBANK_check()).
|
||||||
@ -287,6 +317,62 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and queue a bank error message with the HTTP response
|
||||||
|
* code @a response_code on connection @a connection.
|
||||||
|
*
|
||||||
|
* @param connection where to queue the reply
|
||||||
|
* @param response_code http status code to use
|
||||||
|
* @param ec taler error code to use
|
||||||
|
* @param message human readable error message
|
||||||
|
* @return MHD status code
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
create_bank_error (struct MHD_Connection *connection,
|
||||||
|
unsigned int response_code,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
json_t *json;
|
||||||
|
struct MHD_Response *resp;
|
||||||
|
void *json_str;
|
||||||
|
size_t json_len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
json = json_pack ("{s:s, s:I}",
|
||||||
|
"error",
|
||||||
|
message,
|
||||||
|
"ec",
|
||||||
|
(json_int_t) ec);
|
||||||
|
json_str = json_dumps (json,
|
||||||
|
JSON_INDENT(2));
|
||||||
|
json_decref (json);
|
||||||
|
if (NULL == json_str)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
json_len = strlen (json_str);
|
||||||
|
resp = MHD_create_response_from_buffer (json_len,
|
||||||
|
json_str,
|
||||||
|
MHD_RESPMEM_MUST_FREE);
|
||||||
|
if (NULL == resp)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
free (json_str);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
(void) MHD_add_response_header (resp,
|
||||||
|
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||||
|
"application/json");
|
||||||
|
ret = MHD_queue_response (connection,
|
||||||
|
response_code,
|
||||||
|
resp);
|
||||||
|
MHD_destroy_response (resp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called whenever MHD is done with a request. If the
|
* Function called whenever MHD is done with a request. If the
|
||||||
* request was a POST, we may have stored a `struct Buffer *` in the
|
* request was a POST, we may have stored a `struct Buffer *` in the
|
||||||
@ -359,13 +445,13 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const char *wtid;
|
const char *subject;
|
||||||
uint64_t debit_account;
|
uint64_t debit_account;
|
||||||
uint64_t credit_account;
|
uint64_t credit_account;
|
||||||
const char *base_url;
|
const char *base_url;
|
||||||
struct TALER_Amount amount;
|
struct TALER_Amount amount;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_string ("wtid", &wtid),
|
GNUNET_JSON_spec_string ("subject", &subject),
|
||||||
GNUNET_JSON_spec_uint64 ("debit_account", &debit_account),
|
GNUNET_JSON_spec_uint64 ("debit_account", &debit_account),
|
||||||
GNUNET_JSON_spec_uint64 ("credit_account", &credit_account),
|
GNUNET_JSON_spec_uint64 ("credit_account", &credit_account),
|
||||||
TALER_JSON_spec_amount ("amount", &amount),
|
TALER_JSON_spec_amount ("amount", &amount),
|
||||||
@ -385,7 +471,7 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
|
|||||||
debit_account,
|
debit_account,
|
||||||
credit_account,
|
credit_account,
|
||||||
&amount,
|
&amount,
|
||||||
wtid,
|
subject,
|
||||||
base_url);
|
base_url);
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Receiving incoming wire transfer: %llu->%llu from %s\n",
|
"Receiving incoming wire transfer: %llu->%llu from %s\n",
|
||||||
@ -433,6 +519,94 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle incoming HTTP request for /reject.
|
||||||
|
*
|
||||||
|
* @param h the fakebank handle
|
||||||
|
* @param connection the connection
|
||||||
|
* @param upload_data request data
|
||||||
|
* @param upload_data_size size of @a upload_data in bytes
|
||||||
|
* @param con_cls closure for request (a `struct Buffer *`)
|
||||||
|
* @return MHD result code
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
handle_reject (struct TALER_FAKEBANK_Handle *h,
|
||||||
|
struct MHD_Connection *connection,
|
||||||
|
const char *upload_data,
|
||||||
|
size_t *upload_data_size,
|
||||||
|
void **con_cls)
|
||||||
|
{
|
||||||
|
enum GNUNET_JSON_PostResult pr;
|
||||||
|
json_t *json;
|
||||||
|
struct MHD_Response *resp;
|
||||||
|
int ret;
|
||||||
|
int found;
|
||||||
|
|
||||||
|
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
|
||||||
|
con_cls,
|
||||||
|
upload_data,
|
||||||
|
upload_data_size,
|
||||||
|
&json);
|
||||||
|
switch (pr)
|
||||||
|
{
|
||||||
|
case GNUNET_JSON_PR_OUT_OF_MEMORY:
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
case GNUNET_JSON_PR_CONTINUE:
|
||||||
|
return MHD_YES;
|
||||||
|
case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
case GNUNET_JSON_PR_JSON_INVALID:
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
case GNUNET_JSON_PR_SUCCESS:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
uint64_t serial_id;
|
||||||
|
uint64_t credit_account;
|
||||||
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
|
GNUNET_JSON_spec_uint64 ("row_id", &serial_id),
|
||||||
|
GNUNET_JSON_spec_uint64 ("credit_account", &credit_account),
|
||||||
|
GNUNET_JSON_spec_end ()
|
||||||
|
};
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_JSON_parse (json,
|
||||||
|
spec,
|
||||||
|
NULL, NULL))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
json_decref (json);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
found = TALER_FAKEBANK_reject_transfer (h,
|
||||||
|
serial_id,
|
||||||
|
credit_account);
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Rejected wire transfer #%llu (to %llu)\n",
|
||||||
|
(unsigned long long) serial_id,
|
||||||
|
(unsigned long long) credit_account);
|
||||||
|
}
|
||||||
|
json_decref (json);
|
||||||
|
|
||||||
|
if (GNUNET_OK != found)
|
||||||
|
return create_bank_error (connection,
|
||||||
|
MHD_HTTP_NOT_FOUND,
|
||||||
|
TALER_EC_BANK_REJECT_NOT_FOUND,
|
||||||
|
"transaction unknown");
|
||||||
|
/* finally build regular response */
|
||||||
|
resp = MHD_create_response_from_buffer (0,
|
||||||
|
NULL,
|
||||||
|
MHD_RESPMEM_PERSISTENT);
|
||||||
|
ret = MHD_queue_response (connection,
|
||||||
|
MHD_HTTP_NO_CONTENT,
|
||||||
|
resp);
|
||||||
|
MHD_destroy_response (resp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle incoming HTTP request for /history
|
* Handle incoming HTTP request for /history
|
||||||
*
|
*
|
||||||
@ -451,6 +625,7 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
|
|||||||
const char *start;
|
const char *start;
|
||||||
const char *dir;
|
const char *dir;
|
||||||
const char *acc;
|
const char *acc;
|
||||||
|
const char *cancelled;
|
||||||
unsigned long long account_number;
|
unsigned long long account_number;
|
||||||
unsigned long long start_number;
|
unsigned long long start_number;
|
||||||
long long count;
|
long long count;
|
||||||
@ -469,6 +644,9 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
|
|||||||
dir = MHD_lookup_connection_value (connection,
|
dir = MHD_lookup_connection_value (connection,
|
||||||
MHD_GET_ARGUMENT_KIND,
|
MHD_GET_ARGUMENT_KIND,
|
||||||
"direction");
|
"direction");
|
||||||
|
cancelled = MHD_lookup_connection_value (connection,
|
||||||
|
MHD_GET_ARGUMENT_KIND,
|
||||||
|
"cancelled");
|
||||||
start = MHD_lookup_connection_value (connection,
|
start = MHD_lookup_connection_value (connection,
|
||||||
MHD_GET_ARGUMENT_KIND,
|
MHD_GET_ARGUMENT_KIND,
|
||||||
"start");
|
"start");
|
||||||
@ -496,7 +674,14 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
|
|||||||
(1 != sscanf (start,
|
(1 != sscanf (start,
|
||||||
"%llu",
|
"%llu",
|
||||||
&start_number)) ) ||
|
&start_number)) ) ||
|
||||||
( (NULL != dir) &&
|
(NULL == dir) ||
|
||||||
|
(NULL == cancelled) ||
|
||||||
|
( (0 != strcasecmp (cancelled,
|
||||||
|
"OMIT")) &&
|
||||||
|
(0 != strcasecmp (cancelled,
|
||||||
|
"SHOW")) ) ||
|
||||||
|
( (0 != strcasecmp (dir,
|
||||||
|
"BOTH")) &&
|
||||||
(0 != strcasecmp (dir,
|
(0 != strcasecmp (dir,
|
||||||
"CREDIT")) &&
|
"CREDIT")) &&
|
||||||
(0 != strcasecmp (dir,
|
(0 != strcasecmp (dir,
|
||||||
@ -513,13 +698,40 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
|
|||||||
dir,
|
dir,
|
||||||
(unsigned long long) account_number,
|
(unsigned long long) account_number,
|
||||||
start);
|
start);
|
||||||
if (NULL == dir)
|
if (0 == strcasecmp (dir,
|
||||||
direction = TALER_BANK_DIRECTION_BOTH;
|
|
||||||
else if (0 == strcasecmp (dir,
|
|
||||||
"CREDIT"))
|
"CREDIT"))
|
||||||
|
{
|
||||||
direction = TALER_BANK_DIRECTION_CREDIT;
|
direction = TALER_BANK_DIRECTION_CREDIT;
|
||||||
else
|
}
|
||||||
|
else if (0 == strcasecmp (dir,
|
||||||
|
"DEBIT"))
|
||||||
|
{
|
||||||
direction = TALER_BANK_DIRECTION_DEBIT;
|
direction = TALER_BANK_DIRECTION_DEBIT;
|
||||||
|
}
|
||||||
|
else if (0 == strcasecmp (dir,
|
||||||
|
"BOTH"))
|
||||||
|
{
|
||||||
|
direction = TALER_BANK_DIRECTION_BOTH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_assert (0);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
if (0 == strcasecmp (cancelled,
|
||||||
|
"OMIT"))
|
||||||
|
{
|
||||||
|
/* nothing */
|
||||||
|
} else if (0 == strcasecmp (cancelled,
|
||||||
|
"SHOW"))
|
||||||
|
{
|
||||||
|
direction |= TALER_BANK_DIRECTION_CANCEL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_assert (0);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
if (NULL == start)
|
if (NULL == start)
|
||||||
{
|
{
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
@ -557,6 +769,7 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
|
|||||||
{
|
{
|
||||||
json_t *trans;
|
json_t *trans;
|
||||||
char *subject;
|
char *subject;
|
||||||
|
const char *sign;
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Found transaction over %s from %llu to %llu\n",
|
"Found transaction over %s from %llu to %llu\n",
|
||||||
@ -564,10 +777,12 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
|
|||||||
(unsigned long long) pos->debit_account,
|
(unsigned long long) pos->debit_account,
|
||||||
(unsigned long long) pos->credit_account);
|
(unsigned long long) pos->credit_account);
|
||||||
|
|
||||||
if (! ( ( (account_number == pos->debit_account) &&
|
if ( (! ( ( (account_number == pos->debit_account) &&
|
||||||
(0 != (direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
|
(0 != (direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
|
||||||
( (account_number == pos->credit_account) &&
|
( (account_number == pos->credit_account) &&
|
||||||
(0 != (direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) )
|
(0 != (direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) ) ||
|
||||||
|
( (0 == (direction & TALER_BANK_DIRECTION_CANCEL)) &&
|
||||||
|
(GNUNET_YES == pos->rejected) ) )
|
||||||
{
|
{
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
pos = pos->next;
|
pos = pos->next;
|
||||||
@ -580,11 +795,15 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
|
|||||||
"%s %s",
|
"%s %s",
|
||||||
pos->subject,
|
pos->subject,
|
||||||
pos->exchange_base_url);
|
pos->exchange_base_url);
|
||||||
|
sign =
|
||||||
|
(account_number == pos->debit_account)
|
||||||
|
? (pos->rejected ? "cancel-" : "-")
|
||||||
|
: (pos->rejected ? "cancel+" : "+");
|
||||||
trans = json_pack ("{s:I, s:o, s:o, s:s, s:I, s:s}",
|
trans = json_pack ("{s:I, s:o, s:o, s:s, s:I, s:s}",
|
||||||
"row_id", (json_int_t) pos->serial_id,
|
"row_id", (json_int_t) pos->serial_id,
|
||||||
"date", GNUNET_JSON_from_time_abs (pos->date),
|
"date", GNUNET_JSON_from_time_abs (pos->date),
|
||||||
"amount", TALER_JSON_from_amount (&pos->amount),
|
"amount", TALER_JSON_from_amount (&pos->amount),
|
||||||
"sign", (account_number == pos->debit_account) ? "-" : "+",
|
"sign", sign,
|
||||||
"counterpart", (json_int_t) ( (account_number == pos->debit_account)
|
"counterpart", (json_int_t) ( (account_number == pos->debit_account)
|
||||||
? pos->credit_account
|
? pos->credit_account
|
||||||
: pos->debit_account),
|
: pos->debit_account),
|
||||||
@ -698,6 +917,15 @@ handle_mhd_request (void *cls,
|
|||||||
upload_data,
|
upload_data,
|
||||||
upload_data_size,
|
upload_data_size,
|
||||||
con_cls);
|
con_cls);
|
||||||
|
if ( (0 == strcasecmp (url,
|
||||||
|
"/reject")) &&
|
||||||
|
(0 == strcasecmp (method,
|
||||||
|
MHD_HTTP_METHOD_POST)) )
|
||||||
|
return handle_reject (h,
|
||||||
|
connection,
|
||||||
|
upload_data,
|
||||||
|
upload_data_size,
|
||||||
|
con_cls);
|
||||||
if ( (0 == strcasecmp (url,
|
if ( (0 == strcasecmp (url,
|
||||||
"/history")) &&
|
"/history")) &&
|
||||||
(0 == strcasecmp (method,
|
(0 == strcasecmp (method,
|
||||||
|
@ -50,6 +50,7 @@ run (void *cls)
|
|||||||
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
||||||
.label = "deposit-1",
|
.label = "deposit-1",
|
||||||
.details.admin_add_incoming.exchange_base_url = "https://exchange.net/", /* bogus */
|
.details.admin_add_incoming.exchange_base_url = "https://exchange.net/", /* bogus */
|
||||||
|
.details.admin_add_incoming.subject = "subject 1",
|
||||||
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
||||||
.details.admin_add_incoming.credit_account_no = 1,
|
.details.admin_add_incoming.credit_account_no = 1,
|
||||||
.details.admin_add_incoming.debit_account_no = 2, /* Ignored */
|
.details.admin_add_incoming.debit_account_no = 2, /* Ignored */
|
||||||
@ -58,6 +59,7 @@ run (void *cls)
|
|||||||
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
||||||
.label = "deposit-2",
|
.label = "deposit-2",
|
||||||
.details.admin_add_incoming.exchange_base_url = "https://exchange.net/", /* bogus */
|
.details.admin_add_incoming.exchange_base_url = "https://exchange.net/", /* bogus */
|
||||||
|
.details.admin_add_incoming.subject = "subject 2",
|
||||||
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
||||||
.details.admin_add_incoming.credit_account_no = 1,
|
.details.admin_add_incoming.credit_account_no = 1,
|
||||||
.details.admin_add_incoming.debit_account_no = 2, /* Ignored */
|
.details.admin_add_incoming.debit_account_no = 2, /* Ignored */
|
||||||
@ -89,6 +91,27 @@ run (void *cls)
|
|||||||
.details.history.direction = TALER_BANK_DIRECTION_DEBIT,
|
.details.history.direction = TALER_BANK_DIRECTION_DEBIT,
|
||||||
.details.history.start_row_ref = "deposit-1",
|
.details.history.start_row_ref = "deposit-1",
|
||||||
.details.history.num_results = 5 },
|
.details.history.num_results = 5 },
|
||||||
|
{ .oc = TBI_OC_REJECT,
|
||||||
|
.label = "reject-1",
|
||||||
|
.details.reject.cmd_ref = "deposit-1" },
|
||||||
|
{ .oc = TBI_OC_HISTORY,
|
||||||
|
.label = "history-r1",
|
||||||
|
.details.history.account_number = 2,
|
||||||
|
.details.history.direction = TALER_BANK_DIRECTION_CREDIT,
|
||||||
|
.details.history.start_row_ref = NULL,
|
||||||
|
.details.history.num_results = 5 },
|
||||||
|
{ .oc = TBI_OC_HISTORY,
|
||||||
|
.label = "history-r2",
|
||||||
|
.details.history.account_number = 2,
|
||||||
|
.details.history.direction = TALER_BANK_DIRECTION_DEBIT,
|
||||||
|
.details.history.start_row_ref = NULL,
|
||||||
|
.details.history.num_results = 5 },
|
||||||
|
{ .oc = TBI_OC_HISTORY,
|
||||||
|
.label = "history-r3",
|
||||||
|
.details.history.account_number = 2,
|
||||||
|
.details.history.direction = TALER_BANK_DIRECTION_BOTH | TALER_BANK_DIRECTION_CANCEL,
|
||||||
|
.details.history.start_row_ref = NULL,
|
||||||
|
.details.history.num_results = 5 },
|
||||||
{ .oc = TBI_OC_END }
|
{ .oc = TBI_OC_END }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ run (void *cls)
|
|||||||
/* Add EUR:5.01 to account 1 */
|
/* Add EUR:5.01 to account 1 */
|
||||||
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
||||||
.label = "debit-1",
|
.label = "debit-1",
|
||||||
|
.details.admin_add_incoming.subject = "subject 1",
|
||||||
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
||||||
.details.admin_add_incoming.credit_account_no = 1,
|
.details.admin_add_incoming.credit_account_no = 1,
|
||||||
.details.admin_add_incoming.debit_account_no = 2,
|
.details.admin_add_incoming.debit_account_no = 2,
|
||||||
@ -68,6 +69,7 @@ run (void *cls)
|
|||||||
.details.history.num_results = 5 },
|
.details.history.num_results = 5 },
|
||||||
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
||||||
.label = "debit-2",
|
.label = "debit-2",
|
||||||
|
.details.admin_add_incoming.subject = "subject 2",
|
||||||
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
||||||
.details.admin_add_incoming.credit_account_no = 3,
|
.details.admin_add_incoming.credit_account_no = 3,
|
||||||
.details.admin_add_incoming.debit_account_no = 2,
|
.details.admin_add_incoming.debit_account_no = 2,
|
||||||
@ -75,6 +77,7 @@ run (void *cls)
|
|||||||
.details.admin_add_incoming.amount = "KUDOS:3.21" },
|
.details.admin_add_incoming.amount = "KUDOS:3.21" },
|
||||||
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
||||||
.label = "credit-2",
|
.label = "credit-2",
|
||||||
|
.details.admin_add_incoming.subject = "credit 2",
|
||||||
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
||||||
.details.admin_add_incoming.credit_account_no = 2,
|
.details.admin_add_incoming.credit_account_no = 2,
|
||||||
.details.admin_add_incoming.debit_account_no = 3,
|
.details.admin_add_incoming.debit_account_no = 3,
|
||||||
@ -105,6 +108,40 @@ run (void *cls)
|
|||||||
/* check transfer list is now empty */
|
/* check transfer list is now empty */
|
||||||
{ .oc = TBI_OC_EXPECT_TRANSFERS_EMPTY,
|
{ .oc = TBI_OC_EXPECT_TRANSFERS_EMPTY,
|
||||||
.label = "expect-empty" },
|
.label = "expect-empty" },
|
||||||
|
/* Add EUR:5.01 to account 1 */
|
||||||
|
{ .oc = TBI_OC_ADMIN_ADD_INCOMING,
|
||||||
|
.label = "credit-for-reject-1",
|
||||||
|
.details.admin_add_incoming.subject = "subject 3",
|
||||||
|
.details.admin_add_incoming.expected_response_code = MHD_HTTP_OK,
|
||||||
|
.details.admin_add_incoming.credit_account_no = 1,
|
||||||
|
.details.admin_add_incoming.debit_account_no = 2,
|
||||||
|
.details.admin_add_incoming.exchange_base_url = "https://exchange.net/",
|
||||||
|
.details.admin_add_incoming.amount = "KUDOS:5.01" },
|
||||||
|
{ .oc = TBI_OC_REJECT,
|
||||||
|
.label = "reject-1",
|
||||||
|
.details.reject.cmd_ref = "credit-for-reject-1" },
|
||||||
|
{ .oc = TBI_OC_HISTORY,
|
||||||
|
.label = "history-r1",
|
||||||
|
.details.history.account_number = 1,
|
||||||
|
.details.history.direction = TALER_BANK_DIRECTION_BOTH,
|
||||||
|
/* range is exclusive, and everything up to and including "credit-2"
|
||||||
|
was already killed via TBI_OC_EXPECT_TRANSFER and thus won't show
|
||||||
|
in the history. So to see the rejected transfer, we need to start
|
||||||
|
looking after "credit-2" */
|
||||||
|
.details.history.start_row_ref = NULL,
|
||||||
|
.details.history.num_results = 5 },
|
||||||
|
{ .oc = TBI_OC_HISTORY,
|
||||||
|
.label = "history-r1c",
|
||||||
|
.details.history.account_number = 1,
|
||||||
|
.details.history.direction = TALER_BANK_DIRECTION_BOTH | TALER_BANK_DIRECTION_CANCEL,
|
||||||
|
.details.history.start_row_ref = NULL,
|
||||||
|
.details.history.num_results = 5 },
|
||||||
|
{ .oc = TBI_OC_EXPECT_TRANSFER,
|
||||||
|
.label = "expect-credit-reject-1",
|
||||||
|
.details.expect_transfer.cmd_ref = "credit-for-reject-1" },
|
||||||
|
/* check transfer list is now empty */
|
||||||
|
{ .oc = TBI_OC_EXPECT_TRANSFERS_EMPTY,
|
||||||
|
.label = "expect-empty-2" },
|
||||||
{ .oc = TBI_OC_END }
|
{ .oc = TBI_OC_END }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -110,7 +110,6 @@ static const struct TBI_Command *
|
|||||||
find_command (const struct InterpreterState *is,
|
find_command (const struct InterpreterState *is,
|
||||||
const char *label)
|
const char *label)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
|
||||||
const struct TBI_Command *cmd;
|
const struct TBI_Command *cmd;
|
||||||
|
|
||||||
if (NULL == label)
|
if (NULL == label)
|
||||||
@ -119,7 +118,7 @@ find_command (const struct InterpreterState *is,
|
|||||||
"Attempt to lookup command for empty label\n");
|
"Attempt to lookup command for empty label\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++)
|
for (unsigned int i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++)
|
||||||
if ( (NULL != cmd->label) &&
|
if ( (NULL != cmd->label) &&
|
||||||
(0 == strcmp (cmd->label,
|
(0 == strcmp (cmd->label,
|
||||||
label)) )
|
label)) )
|
||||||
@ -131,6 +130,63 @@ find_command (const struct InterpreterState *is,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the /admin/add/incoming transaction at offset @a off
|
||||||
|
* has been /rejected.
|
||||||
|
*
|
||||||
|
* @param is interpreter state (where we are right now)
|
||||||
|
* @param off offset of the command to test for rejection
|
||||||
|
* @return #GNUNET_YES if the command at @a off was cancelled
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
test_cancelled (struct InterpreterState *is,
|
||||||
|
unsigned int off)
|
||||||
|
{
|
||||||
|
const struct TBI_Command *cmd = &is->commands[off];
|
||||||
|
|
||||||
|
for (unsigned int i=0;i<is->ip;i++)
|
||||||
|
{
|
||||||
|
const struct TBI_Command *c = &is->commands[i];
|
||||||
|
|
||||||
|
if (TBI_OC_REJECT != c->oc)
|
||||||
|
continue;
|
||||||
|
if (0 == strcmp (c->details.reject.cmd_ref,
|
||||||
|
cmd->label))
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the /admin/add/incoming transaction at offset @a off
|
||||||
|
* has been #TBI_OC_EXPECT_TRANSFER treated, and thus been
|
||||||
|
* forgotten by the fakebank.
|
||||||
|
*
|
||||||
|
* @param is interpreter state (where we are right now)
|
||||||
|
* @param off offset of the command to test for rejection
|
||||||
|
* @return #GNUNET_YES if the command at @a off was cancelled
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
test_deleted_by_expected (struct InterpreterState *is,
|
||||||
|
unsigned int off)
|
||||||
|
{
|
||||||
|
const struct TBI_Command *cmd = &is->commands[off];
|
||||||
|
|
||||||
|
for (unsigned int i=0;i<is->ip;i++)
|
||||||
|
{
|
||||||
|
const struct TBI_Command *c = &is->commands[i];
|
||||||
|
|
||||||
|
if (TBI_OC_EXPECT_TRANSFER != c->oc)
|
||||||
|
continue;
|
||||||
|
if (0 == strcmp (c->details.expect_transfer.cmd_ref,
|
||||||
|
cmd->label))
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item in the transaction history, as reconstructed from the
|
* Item in the transaction history, as reconstructed from the
|
||||||
* command history.
|
* command history.
|
||||||
@ -214,6 +270,7 @@ build_history (struct InterpreterState *is,
|
|||||||
for (unsigned int off = start;off != end + inc; off += inc)
|
for (unsigned int off = start;off != end + inc; off += inc)
|
||||||
{
|
{
|
||||||
const struct TBI_Command *pos = &is->commands[off];
|
const struct TBI_Command *pos = &is->commands[off];
|
||||||
|
int cancelled;
|
||||||
|
|
||||||
if (TBI_OC_ADMIN_ADD_INCOMING != pos->oc)
|
if (TBI_OC_ADMIN_ADD_INCOMING != pos->oc)
|
||||||
continue;
|
continue;
|
||||||
@ -229,6 +286,15 @@ build_history (struct InterpreterState *is,
|
|||||||
continue; /* skip until we find the marker */
|
continue; /* skip until we find the marker */
|
||||||
if (total >= cmd->details.history.num_results * inc)
|
if (total >= cmd->details.history.num_results * inc)
|
||||||
break; /* hit limit specified by command */
|
break; /* hit limit specified by command */
|
||||||
|
if (GNUNET_YES ==
|
||||||
|
test_deleted_by_expected (is,
|
||||||
|
off))
|
||||||
|
continue;
|
||||||
|
cancelled = test_cancelled (is,
|
||||||
|
off);
|
||||||
|
if ( (GNUNET_YES == cancelled) &&
|
||||||
|
(0 == (cmd->details.history.direction & TALER_BANK_DIRECTION_CANCEL)) )
|
||||||
|
continue;
|
||||||
if ( ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
|
if ( ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
|
||||||
(cmd->details.history.account_number ==
|
(cmd->details.history.account_number ==
|
||||||
pos->details.admin_add_incoming.credit_account_no)) ||
|
pos->details.admin_add_incoming.credit_account_no)) ||
|
||||||
@ -253,6 +319,7 @@ build_history (struct InterpreterState *is,
|
|||||||
for (unsigned int off = start;off != end + inc; off += inc)
|
for (unsigned int off = start;off != end + inc; off += inc)
|
||||||
{
|
{
|
||||||
const struct TBI_Command *pos = &is->commands[off];
|
const struct TBI_Command *pos = &is->commands[off];
|
||||||
|
int cancelled;
|
||||||
|
|
||||||
if (TBI_OC_ADMIN_ADD_INCOMING != pos->oc)
|
if (TBI_OC_ADMIN_ADD_INCOMING != pos->oc)
|
||||||
continue;
|
continue;
|
||||||
@ -268,6 +335,10 @@ build_history (struct InterpreterState *is,
|
|||||||
continue; /* skip until we find the marker */
|
continue; /* skip until we find the marker */
|
||||||
if (total >= cmd->details.history.num_results * inc)
|
if (total >= cmd->details.history.num_results * inc)
|
||||||
break; /* hit limit specified by command */
|
break; /* hit limit specified by command */
|
||||||
|
if (GNUNET_YES ==
|
||||||
|
test_deleted_by_expected (is,
|
||||||
|
off))
|
||||||
|
continue;
|
||||||
|
|
||||||
if ( ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
|
if ( ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
|
||||||
(cmd->details.history.account_number ==
|
(cmd->details.history.account_number ==
|
||||||
@ -280,11 +351,19 @@ build_history (struct InterpreterState *is,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelled = test_cancelled (is,
|
||||||
|
off);
|
||||||
|
if ( (GNUNET_YES == cancelled) &&
|
||||||
|
(0 == (cmd->details.history.direction & TALER_BANK_DIRECTION_CANCEL)) )
|
||||||
|
continue;
|
||||||
|
|
||||||
if ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
|
if ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_CREDIT)) &&
|
||||||
(cmd->details.history.account_number ==
|
(cmd->details.history.account_number ==
|
||||||
pos->details.admin_add_incoming.credit_account_no))
|
pos->details.admin_add_incoming.credit_account_no))
|
||||||
{
|
{
|
||||||
h[total].direction = TALER_BANK_DIRECTION_CREDIT;
|
h[total].direction = TALER_BANK_DIRECTION_CREDIT;
|
||||||
|
if (GNUNET_YES == cancelled)
|
||||||
|
h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
|
||||||
h[total].details.account_details
|
h[total].details.account_details
|
||||||
= json_pack ("{s:s, s:s, s:I}",
|
= json_pack ("{s:s, s:s, s:I}",
|
||||||
"type",
|
"type",
|
||||||
@ -300,6 +379,8 @@ build_history (struct InterpreterState *is,
|
|||||||
pos->details.admin_add_incoming.debit_account_no))
|
pos->details.admin_add_incoming.debit_account_no))
|
||||||
{
|
{
|
||||||
h[total].direction = TALER_BANK_DIRECTION_DEBIT;
|
h[total].direction = TALER_BANK_DIRECTION_DEBIT;
|
||||||
|
if (GNUNET_YES == cancelled)
|
||||||
|
h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
|
||||||
h[total].details.account_details
|
h[total].details.account_details
|
||||||
= json_pack ("{s:s, s:s, s:I}",
|
= json_pack ("{s:s, s:s, s:I}",
|
||||||
"type",
|
"type",
|
||||||
@ -323,17 +404,10 @@ build_history (struct InterpreterState *is,
|
|||||||
/* h[total].execution_date; // unknown here */
|
/* h[total].execution_date; // unknown here */
|
||||||
h[total].serial_id
|
h[total].serial_id
|
||||||
= pos->details.admin_add_incoming.serial_id;
|
= pos->details.admin_add_incoming.serial_id;
|
||||||
{
|
|
||||||
char *ws;
|
|
||||||
|
|
||||||
ws = GNUNET_STRINGS_data_to_string_alloc (&pos->details.admin_add_incoming.wtid,
|
|
||||||
sizeof (struct TALER_WireTransferIdentifierRawP));
|
|
||||||
GNUNET_asprintf (&h[total].details.wire_transfer_subject,
|
GNUNET_asprintf (&h[total].details.wire_transfer_subject,
|
||||||
"%s %s",
|
"%s %s",
|
||||||
ws,
|
pos->details.admin_add_incoming.subject,
|
||||||
pos->details.admin_add_incoming.exchange_base_url);
|
pos->details.admin_add_incoming.exchange_base_url);
|
||||||
GNUNET_free (ws);
|
|
||||||
}
|
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,18 +562,34 @@ static void
|
|||||||
interpreter_run (void *cls);
|
interpreter_run (void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the next command.
|
||||||
|
*
|
||||||
|
* @param is interpreter to progress
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
next (struct InterpreterState *is)
|
||||||
|
{
|
||||||
|
is->ip++;
|
||||||
|
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||||
|
is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called upon completion of our /admin/add/incoming request.
|
* Function called upon completion of our /admin/add/incoming request.
|
||||||
*
|
*
|
||||||
* @param cls closure with the interpreter state
|
* @param cls closure with the interpreter state
|
||||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||||
* 0 if the bank's reply is bogus (fails to follow the protocol)
|
* 0 if the bank's reply is bogus (fails to follow the protocol)
|
||||||
|
* @param ec taler status code
|
||||||
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
|
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
|
||||||
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
|
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
add_incoming_cb (void *cls,
|
add_incoming_cb (void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
uint64_t serial_id,
|
uint64_t serial_id,
|
||||||
const json_t *json)
|
const json_t *json)
|
||||||
{
|
{
|
||||||
@ -522,9 +612,7 @@ add_incoming_cb (void *cls,
|
|||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
is->ip++;
|
next (is);
|
||||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
|
||||||
is);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -538,6 +626,7 @@ add_incoming_cb (void *cls,
|
|||||||
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
|
* #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
|
* last callback is always of this status (even if `abs(num_results)` were
|
||||||
* already returned).
|
* already returned).
|
||||||
|
* @param ec taler status code
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param serial_id monotonically increasing counter corresponding to the transaction
|
* @param serial_id monotonically increasing counter corresponding to the transaction
|
||||||
* @param details details about the wire transfer
|
* @param details details about the wire transfer
|
||||||
@ -546,6 +635,7 @@ add_incoming_cb (void *cls,
|
|||||||
static void
|
static void
|
||||||
history_cb (void *cls,
|
history_cb (void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
uint64_t serial_id,
|
uint64_t serial_id,
|
||||||
const struct TALER_BANK_TransferDetails *details,
|
const struct TALER_BANK_TransferDetails *details,
|
||||||
@ -580,9 +670,7 @@ history_cb (void *cls,
|
|||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
is->ip++;
|
next (is);
|
||||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
|
||||||
is);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -612,6 +700,38 @@ history_cb (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callbacks of this type are used to serve the result of asking
|
||||||
|
* the bank to reject an incoming wire transfer.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for successful status request;
|
||||||
|
* #MHD_HTTP_NOT_FOUND if the rowid is unknown;
|
||||||
|
* 0 if the bank's reply is bogus (fails to follow the protocol),
|
||||||
|
* @param ec detailed error code
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
reject_cb (void *cls,
|
||||||
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec)
|
||||||
|
{
|
||||||
|
struct InterpreterState *is = cls;
|
||||||
|
struct TBI_Command *cmd = &is->commands[is->ip];
|
||||||
|
|
||||||
|
cmd->details.reject.rh = NULL;
|
||||||
|
if (MHD_HTTP_NO_CONTENT != http_status)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
fprintf (stderr,
|
||||||
|
"Unexpected response code %u:\n",
|
||||||
|
http_status);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next (is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the main interpreter loop that performs bank operations.
|
* Run the main interpreter loop that performs bank operations.
|
||||||
*
|
*
|
||||||
@ -658,15 +778,13 @@ interpreter_run (void *cls)
|
|||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
GNUNET_break (NULL != cmd->details.admin_add_incoming.subject);
|
||||||
&cmd->details.admin_add_incoming.wtid,
|
|
||||||
sizeof (cmd->details.admin_add_incoming.wtid));
|
|
||||||
cmd->details.admin_add_incoming.aih
|
cmd->details.admin_add_incoming.aih
|
||||||
= TALER_BANK_admin_add_incoming (is->ctx,
|
= TALER_BANK_admin_add_incoming (is->ctx,
|
||||||
"http://localhost:8080",
|
"http://localhost:8080",
|
||||||
&auth,
|
&auth,
|
||||||
cmd->details.admin_add_incoming.exchange_base_url,
|
cmd->details.admin_add_incoming.exchange_base_url,
|
||||||
&cmd->details.admin_add_incoming.wtid,
|
cmd->details.admin_add_incoming.subject,
|
||||||
&amount,
|
&amount,
|
||||||
cmd->details.admin_add_incoming.debit_account_no,
|
cmd->details.admin_add_incoming.debit_account_no,
|
||||||
cmd->details.admin_add_incoming.credit_account_no,
|
cmd->details.admin_add_incoming.credit_account_no,
|
||||||
@ -722,7 +840,6 @@ interpreter_run (void *cls)
|
|||||||
&amount));
|
&amount));
|
||||||
{
|
{
|
||||||
char *subject;
|
char *subject;
|
||||||
char *expect;
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_FAKEBANK_check (is->fakebank,
|
TALER_FAKEBANK_check (is->fakebank,
|
||||||
@ -736,22 +853,17 @@ interpreter_run (void *cls)
|
|||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
expect = GNUNET_STRINGS_data_to_string_alloc (&ref->details.admin_add_incoming.wtid,
|
if (0 != strcmp (ref->details.admin_add_incoming.subject,
|
||||||
sizeof (ref->details.admin_add_incoming.wtid));
|
subject))
|
||||||
if (0 != strcmp (subject, expect))
|
|
||||||
{
|
{
|
||||||
GNUNET_free (expect);
|
|
||||||
GNUNET_free (subject);
|
GNUNET_free (subject);
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GNUNET_free (subject);
|
GNUNET_free (subject);
|
||||||
GNUNET_free (expect);
|
|
||||||
}
|
}
|
||||||
is->ip++;
|
next (is);
|
||||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
|
||||||
is);
|
|
||||||
return;
|
return;
|
||||||
case TBI_OC_EXPECT_TRANSFERS_EMPTY:
|
case TBI_OC_EXPECT_TRANSFERS_EMPTY:
|
||||||
if (GNUNET_OK != TALER_FAKEBANK_check_empty (is->fakebank))
|
if (GNUNET_OK != TALER_FAKEBANK_check_empty (is->fakebank))
|
||||||
@ -760,9 +872,27 @@ interpreter_run (void *cls)
|
|||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
is->ip++;
|
next (is);
|
||||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
return;
|
||||||
|
case TBI_OC_REJECT:
|
||||||
|
ref = find_command (is,
|
||||||
|
cmd->details.reject.cmd_ref);
|
||||||
|
GNUNET_assert (NULL != ref);
|
||||||
|
GNUNET_assert (TBI_OC_ADMIN_ADD_INCOMING == ref->oc);
|
||||||
|
cmd->details.reject.rh
|
||||||
|
= TALER_BANK_reject (is->ctx,
|
||||||
|
"http://localhost:8080",
|
||||||
|
&auth,
|
||||||
|
ref->details.admin_add_incoming.credit_account_no,
|
||||||
|
ref->details.admin_add_incoming.serial_id,
|
||||||
|
&reject_cb,
|
||||||
is);
|
is);
|
||||||
|
if (NULL == cmd->details.reject.rh)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
@ -802,7 +932,6 @@ do_shutdown (void *cls)
|
|||||||
{
|
{
|
||||||
struct InterpreterState *is = cls;
|
struct InterpreterState *is = cls;
|
||||||
struct TBI_Command *cmd;
|
struct TBI_Command *cmd;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (NULL != is->timeout_task)
|
if (NULL != is->timeout_task)
|
||||||
{
|
{
|
||||||
@ -810,7 +939,7 @@ do_shutdown (void *cls)
|
|||||||
is->timeout_task = NULL;
|
is->timeout_task = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++)
|
for (unsigned int i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++)
|
||||||
{
|
{
|
||||||
switch (cmd->oc)
|
switch (cmd->oc)
|
||||||
{
|
{
|
||||||
@ -843,6 +972,17 @@ do_shutdown (void *cls)
|
|||||||
break;
|
break;
|
||||||
case TBI_OC_EXPECT_TRANSFERS_EMPTY:
|
case TBI_OC_EXPECT_TRANSFERS_EMPTY:
|
||||||
break;
|
break;
|
||||||
|
case TBI_OC_REJECT:
|
||||||
|
if (NULL != cmd->details.reject.rh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Command %u (%s) did not complete\n",
|
||||||
|
i,
|
||||||
|
cmd->label);
|
||||||
|
TALER_BANK_reject_cancel (cmd->details.reject.rh);
|
||||||
|
cmd->details.reject.rh = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unknown instruction %d at %u (%s)\n",
|
"Unknown instruction %d at %u (%s)\n",
|
||||||
|
@ -57,7 +57,12 @@ enum TBI_OpCode
|
|||||||
/**
|
/**
|
||||||
* Expect that we have exhaustively gone over all transfers at fakebank.
|
* Expect that we have exhaustively gone over all transfers at fakebank.
|
||||||
*/
|
*/
|
||||||
TBI_OC_EXPECT_TRANSFERS_EMPTY
|
TBI_OC_EXPECT_TRANSFERS_EMPTY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject incoming transfer.
|
||||||
|
*/
|
||||||
|
TBI_OC_REJECT
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -110,10 +115,9 @@ struct TBI_Command
|
|||||||
const char *exchange_base_url;
|
const char *exchange_base_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wire transfer identifier to use. Initialized to
|
* Wire transfer subject to use.
|
||||||
* a random value.
|
|
||||||
*/
|
*/
|
||||||
struct TALER_WireTransferIdentifierRawP wtid;
|
const char *subject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Which response code do we expect for this command?
|
* Which response code do we expect for this command?
|
||||||
@ -186,6 +190,23 @@ struct TBI_Command
|
|||||||
|
|
||||||
} expect_transfer;
|
} expect_transfer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute /reject operation.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the matching transfer that is now to be rejected.
|
||||||
|
*/
|
||||||
|
const char *cmd_ref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to the API's handle during the operation.
|
||||||
|
*/
|
||||||
|
struct TALER_BANK_RejectHandle *rh;
|
||||||
|
|
||||||
|
} reject;
|
||||||
|
|
||||||
} details;
|
} details;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -282,6 +282,7 @@ reject_cb (void *cls,
|
|||||||
* the bank for the transaction history.
|
* the bank for the transaction history.
|
||||||
*
|
*
|
||||||
* @param cls closure with the `struct TALER_EXCHANGEDB_Session *`
|
* @param cls closure with the `struct TALER_EXCHANGEDB_Session *`
|
||||||
|
* @param ec taler error code
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param row_off identification of the position at which we are querying
|
* @param row_off identification of the position at which we are querying
|
||||||
* @param row_off_size number of bytes in @a row_off
|
* @param row_off_size number of bytes in @a row_off
|
||||||
@ -290,6 +291,7 @@ reject_cb (void *cls,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
history_cb (void *cls,
|
history_cb (void *cls,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
const void *row_off,
|
const void *row_off,
|
||||||
size_t row_off_size,
|
size_t row_off_size,
|
||||||
@ -303,6 +305,12 @@ history_cb (void *cls,
|
|||||||
{
|
{
|
||||||
hh = NULL;
|
hh = NULL;
|
||||||
|
|
||||||
|
if (TALER_EC_NONE != ec)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Error fetching history: %u!\n",
|
||||||
|
(unsigned int) ec);
|
||||||
|
}
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"End of list. Committing progress!\n");
|
"End of list. Committing progress!\n");
|
||||||
qs = db_plugin->commit (db_plugin->cls,
|
qs = db_plugin->commit (db_plugin->cls,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2015, 2016, 2017 GNUnet e.V. & Inria
|
Copyright (C) 2015, 2016, 2017 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU Affero General Public License as published by the Free Software
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <gnunet/gnunet_curl_lib.h>
|
#include <gnunet/gnunet_curl_lib.h>
|
||||||
#include "taler_util.h"
|
#include "taler_util.h"
|
||||||
|
#include "taler_error_codes.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,12 +99,14 @@ struct TALER_BANK_AdminAddIncomingHandle;
|
|||||||
* @param cls closure
|
* @param cls closure
|
||||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||||
* 0 if the bank's reply is bogus (fails to follow the protocol)
|
* 0 if the bank's reply is bogus (fails to follow the protocol)
|
||||||
|
* @param ec detailed error code
|
||||||
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
|
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
|
||||||
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
|
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
|
||||||
*/
|
*/
|
||||||
typedef void
|
typedef void
|
||||||
(*TALER_BANK_AdminAddIncomingResultCallback) (void *cls,
|
(*TALER_BANK_AdminAddIncomingResultCallback) (void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
uint64_t serial_id,
|
uint64_t serial_id,
|
||||||
const json_t *json);
|
const json_t *json);
|
||||||
|
|
||||||
@ -118,7 +121,7 @@ typedef void
|
|||||||
* @param bank_base_url URL of the bank (used to execute this request)
|
* @param bank_base_url URL of the bank (used to execute this request)
|
||||||
* @param auth authentication data to use
|
* @param auth authentication data to use
|
||||||
* @param exchange_base_url base URL of the exchange (for tracking)
|
* @param exchange_base_url base URL of the exchange (for tracking)
|
||||||
* @param wtid wire transfer identifier for the transfer
|
* @param subject wire transfer subject for the transfer
|
||||||
* @param amount amount that was deposited
|
* @param amount amount that was deposited
|
||||||
* @param debit_account_no account number to withdraw from (53 bits at most)
|
* @param debit_account_no account number to withdraw from (53 bits at most)
|
||||||
* @param credit_account_no account number to deposit into (53 bits at most)
|
* @param credit_account_no account number to deposit into (53 bits at most)
|
||||||
@ -133,7 +136,7 @@ TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
|
|||||||
const char *bank_base_url,
|
const char *bank_base_url,
|
||||||
const struct TALER_BANK_AuthenticationData *auth,
|
const struct TALER_BANK_AuthenticationData *auth,
|
||||||
const char *exchange_base_url,
|
const char *exchange_base_url,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const char *subject,
|
||||||
const struct TALER_Amount *amount,
|
const struct TALER_Amount *amount,
|
||||||
uint64_t debit_account_no,
|
uint64_t debit_account_no,
|
||||||
uint64_t credit_account_no,
|
uint64_t credit_account_no,
|
||||||
@ -174,7 +177,15 @@ enum TALER_BANK_Direction {
|
|||||||
/**
|
/**
|
||||||
* Return both types of transactions.
|
* Return both types of transactions.
|
||||||
*/
|
*/
|
||||||
TALER_BANK_DIRECTION_BOTH = (TALER_BANK_DIRECTION_CREDIT | TALER_BANK_DIRECTION_DEBIT)
|
TALER_BANK_DIRECTION_BOTH = (TALER_BANK_DIRECTION_CREDIT | TALER_BANK_DIRECTION_DEBIT),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bit mask that is applied to view transactions that have been
|
||||||
|
* cancelled. The bit is set for cancelled transactions that are
|
||||||
|
* returned from /history, and must also be set in order for
|
||||||
|
* cancelled transactions to show up in the /history.
|
||||||
|
*/
|
||||||
|
TALER_BANK_DIRECTION_CANCEL = 4
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -222,6 +233,7 @@ struct TALER_BANK_TransferDetails
|
|||||||
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
|
* #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
|
* last callback is always of this status (even if `abs(num_results)` were
|
||||||
* already returned).
|
* already returned).
|
||||||
|
* @param ec detailed error code
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param serial_id monotonically increasing counter corresponding to the transaction
|
* @param serial_id monotonically increasing counter corresponding to the transaction
|
||||||
* @param details details about the wire transfer
|
* @param details details about the wire transfer
|
||||||
@ -230,6 +242,7 @@ struct TALER_BANK_TransferDetails
|
|||||||
typedef void
|
typedef void
|
||||||
(*TALER_BANK_HistoryResultCallback) (void *cls,
|
(*TALER_BANK_HistoryResultCallback) (void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
uint64_t serial_id,
|
uint64_t serial_id,
|
||||||
const struct TALER_BANK_TransferDetails *details,
|
const struct TALER_BANK_TransferDetails *details,
|
||||||
@ -277,5 +290,61 @@ void
|
|||||||
TALER_BANK_history_cancel (struct TALER_BANK_HistoryHandle *hh);
|
TALER_BANK_history_cancel (struct TALER_BANK_HistoryHandle *hh);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for #TALER_BANK_reject() operation.
|
||||||
|
*/
|
||||||
|
struct TALER_BANK_RejectHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callbacks of this type are used to serve the result of asking
|
||||||
|
* the bank to reject an incoming wire transfer.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for successful status request;
|
||||||
|
* #MHD_HTTP_NOT_FOUND if the rowid is unknown;
|
||||||
|
* 0 if the bank's reply is bogus (fails to follow the protocol),
|
||||||
|
* @param ec detailed error code
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*TALER_BANK_RejectResultCallback) (void *cls,
|
||||||
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request rejection of a wire transfer, marking it as cancelled and voiding
|
||||||
|
* its effects.
|
||||||
|
*
|
||||||
|
* @param ctx curl context for the event loop
|
||||||
|
* @param bank_base_url URL of the bank (used to execute this request)
|
||||||
|
* @param auth authentication data to use
|
||||||
|
* @param account_number which account number should we query
|
||||||
|
* @param rowid transfer to reject
|
||||||
|
* @param rcb the callback to call with the operation result
|
||||||
|
* @param rcb_cls closure for @a rcb
|
||||||
|
* @return NULL
|
||||||
|
* if the inputs are invalid.
|
||||||
|
* In this case, the callback is not called.
|
||||||
|
*/
|
||||||
|
struct TALER_BANK_RejectHandle *
|
||||||
|
TALER_BANK_reject (struct GNUNET_CURL_Context *ctx,
|
||||||
|
const char *bank_base_url,
|
||||||
|
const struct TALER_BANK_AuthenticationData *auth,
|
||||||
|
uint64_t account_number,
|
||||||
|
uint64_t rowid,
|
||||||
|
TALER_BANK_RejectResultCallback rcb,
|
||||||
|
void *rcb_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel an reject request. This function cannot be used on a request
|
||||||
|
* handle if the response was is already served for it.
|
||||||
|
*
|
||||||
|
* @param rh the reject request handle
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_BANK_reject_cancel (struct TALER_BANK_RejectHandle *rh);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _TALER_BANK_SERVICE_H */
|
#endif /* _TALER_BANK_SERVICE_H */
|
||||||
|
@ -1488,6 +1488,34 @@ enum TALER_ErrorCode
|
|||||||
*/
|
*/
|
||||||
TALER_EC_TEST_RSA_SIGN_ERROR = 4005,
|
TALER_EC_TEST_RSA_SIGN_ERROR = 4005,
|
||||||
|
|
||||||
|
/* *************** Taler BANK/FAKEBANK error codes *************** */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication failed for the /admin/add/incoming request.
|
||||||
|
* Returned with a status code of MHD_HTTP_FORBIDDEN.
|
||||||
|
*/
|
||||||
|
TALER_EC_BANK_TRANSFER_NOT_AUHTORIZED = 4101,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication failed for the /history request.
|
||||||
|
* Returned with a status code of MHD_HTTP_FORBIDDEN.
|
||||||
|
*/
|
||||||
|
TALER_EC_BANK_HISTORY_NOT_AUHTORIZED = 4151,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bank could not find the wire transfer that was supposed to
|
||||||
|
* be rejected.
|
||||||
|
* Returned with a status code of MHD_HTTP_NOT_FOUND.
|
||||||
|
*/
|
||||||
|
TALER_EC_BANK_REJECT_NOT_FOUND = 4250,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication failed for the /reject request.
|
||||||
|
* Returned with a status code of MHD_HTTP_FORBIDDEN.
|
||||||
|
*/
|
||||||
|
TALER_EC_BANK_REJECT_NOT_AUHTORIZED = 4251,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End of error code range.
|
* End of error code range.
|
||||||
|
@ -88,6 +88,8 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
|
|||||||
* to the transfer identifier and remove the transaction from the
|
* to the transfer identifier and remove the transaction from the
|
||||||
* list. If the transaction was not recorded, return #GNUNET_SYSERR.
|
* list. If the transaction was not recorded, return #GNUNET_SYSERR.
|
||||||
*
|
*
|
||||||
|
* Rejected transfers do NOT show with "check".
|
||||||
|
*
|
||||||
* @param h bank instance
|
* @param h bank instance
|
||||||
* @param want_amount transfer amount desired
|
* @param want_amount transfer amount desired
|
||||||
* @param want_debit account that should have been debited
|
* @param want_debit account that should have been debited
|
||||||
@ -106,6 +108,21 @@ TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
|
|||||||
char **subject);
|
char **subject);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject incoming wire transfer to account @a credit_account
|
||||||
|
* as identified by @a rowid.
|
||||||
|
*
|
||||||
|
* @param h fake bank handle
|
||||||
|
* @param rowid identifies transfer to reject
|
||||||
|
* @param credit_account account number of owner of credited account
|
||||||
|
* @return #GNUNET_YES on success, #GNUNET_NO if the wire transfer was not found
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TALER_FAKEBANK_reject_transfer (struct TALER_FAKEBANK_Handle *h,
|
||||||
|
uint64_t rowid,
|
||||||
|
uint64_t credit_account);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop running the fake bank.
|
* Stop running the fake bank.
|
||||||
*
|
*
|
||||||
|
@ -83,6 +83,7 @@ struct TALER_WIRE_TransferDetails
|
|||||||
* the bank for the transaction history.
|
* the bank for the transaction history.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param ec taler error code
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param row_off identification of the position at which we are querying
|
* @param row_off identification of the position at which we are querying
|
||||||
* @param row_off_size number of bytes in @a row_off
|
* @param row_off_size number of bytes in @a row_off
|
||||||
@ -91,6 +92,7 @@ struct TALER_WIRE_TransferDetails
|
|||||||
*/
|
*/
|
||||||
typedef int
|
typedef int
|
||||||
(*TALER_WIRE_HistoryResultCallback) (void *cls,
|
(*TALER_WIRE_HistoryResultCallback) (void *cls,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
const void *row_off,
|
const void *row_off,
|
||||||
size_t row_off_size,
|
size_t row_off_size,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2016 GNUnet e.V. & Inria
|
Copyright (C) 2017 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the GNU General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -553,12 +553,14 @@ test_prepare_wire_transfer (void *cls,
|
|||||||
* @param cls closure with the `struct TALER_WIRE_ExecuteHandle`
|
* @param cls closure with the `struct TALER_WIRE_ExecuteHandle`
|
||||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||||
* 0 if the bank's reply is bogus (fails to follow the protocol)
|
* 0 if the bank's reply is bogus (fails to follow the protocol)
|
||||||
|
* @param ec error code from the bank
|
||||||
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
|
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
|
||||||
* @param json detailed response from the HTTPD, or NULL if reply was not JSON
|
* @param json detailed response from the HTTPD, or NULL if reply was not JSON
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
execute_cb (void *cls,
|
execute_cb (void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
uint64_t serial_id,
|
uint64_t serial_id,
|
||||||
const json_t *json)
|
const json_t *json)
|
||||||
{
|
{
|
||||||
@ -578,13 +580,15 @@ execute_cb (void *cls,
|
|||||||
}
|
}
|
||||||
if (NULL != emsg)
|
if (NULL != emsg)
|
||||||
GNUNET_asprintf (&s,
|
GNUNET_asprintf (&s,
|
||||||
"%u (%s)",
|
"%u/%u (%s)",
|
||||||
http_status,
|
http_status,
|
||||||
|
(unsigned int) ec,
|
||||||
emsg);
|
emsg);
|
||||||
else
|
else
|
||||||
GNUNET_asprintf (&s,
|
GNUNET_asprintf (&s,
|
||||||
"%u",
|
"%u/%u",
|
||||||
http_status);
|
http_status,
|
||||||
|
(unsigned int) ec);
|
||||||
eh->cc (eh->cc_cls,
|
eh->cc (eh->cc_cls,
|
||||||
(MHD_HTTP_OK == http_status) ? GNUNET_OK : GNUNET_SYSERR,
|
(MHD_HTTP_OK == http_status) ? GNUNET_OK : GNUNET_SYSERR,
|
||||||
serial_id,
|
serial_id,
|
||||||
@ -676,6 +680,7 @@ test_execute_wire_transfer (void *cls,
|
|||||||
char *emsg;
|
char *emsg;
|
||||||
const char *json_s;
|
const char *json_s;
|
||||||
const char *exchange_base_url;
|
const char *exchange_base_url;
|
||||||
|
char *wire_s;
|
||||||
|
|
||||||
if (NULL == tc->ctx)
|
if (NULL == tc->ctx)
|
||||||
{
|
{
|
||||||
@ -728,16 +733,19 @@ test_execute_wire_transfer (void *cls,
|
|||||||
eh = GNUNET_new (struct TALER_WIRE_ExecuteHandle);
|
eh = GNUNET_new (struct TALER_WIRE_ExecuteHandle);
|
||||||
eh->cc = cc;
|
eh->cc = cc;
|
||||||
eh->cc_cls = cc_cls;
|
eh->cc_cls = cc_cls;
|
||||||
|
wire_s = GNUNET_STRINGS_data_to_string_alloc (&bf.wtid,
|
||||||
|
sizeof (bf.wtid));
|
||||||
eh->aaih = TALER_BANK_admin_add_incoming (tc->ctx,
|
eh->aaih = TALER_BANK_admin_add_incoming (tc->ctx,
|
||||||
tc->bank_uri,
|
tc->bank_uri,
|
||||||
&tc->auth,
|
&tc->auth,
|
||||||
exchange_base_url,
|
exchange_base_url,
|
||||||
&bf.wtid,
|
wire_s,
|
||||||
&amount,
|
&amount,
|
||||||
(uint64_t) tc->exchange_account_no,
|
(uint64_t) tc->exchange_account_no,
|
||||||
(uint64_t) account_no,
|
(uint64_t) account_no,
|
||||||
&execute_cb,
|
&execute_cb,
|
||||||
eh);
|
eh);
|
||||||
|
GNUNET_free (wire_s);
|
||||||
json_decref (wire);
|
json_decref (wire);
|
||||||
if (NULL == eh->aaih)
|
if (NULL == eh->aaih)
|
||||||
{
|
{
|
||||||
@ -803,6 +811,7 @@ struct TALER_WIRE_HistoryHandle
|
|||||||
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
|
* #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
|
* last callback is always of this status (even if `abs(num_results)` were
|
||||||
* already returned).
|
* already returned).
|
||||||
|
* @param ec taler error code
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param serial_id monotonically increasing counter corresponding to the transaction
|
* @param serial_id monotonically increasing counter corresponding to the transaction
|
||||||
* @param details details about the wire transfer
|
* @param details details about the wire transfer
|
||||||
@ -811,6 +820,7 @@ struct TALER_WIRE_HistoryHandle
|
|||||||
static void
|
static void
|
||||||
bhist_cb (void *cls,
|
bhist_cb (void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
uint64_t serial_id,
|
uint64_t serial_id,
|
||||||
const struct TALER_BANK_TransferDetails *details,
|
const struct TALER_BANK_TransferDetails *details,
|
||||||
@ -852,12 +862,17 @@ bhist_cb (void *cls,
|
|||||||
sizeof (wd.wtid));
|
sizeof (wd.wtid));
|
||||||
wd.wtid_s = details->wire_transfer_subject;
|
wd.wtid_s = details->wire_transfer_subject;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wd.wtid_s = NULL;
|
||||||
|
}
|
||||||
GNUNET_free (subject);
|
GNUNET_free (subject);
|
||||||
wd.account_details = details->account_details;
|
wd.account_details = details->account_details;
|
||||||
|
|
||||||
if ( (NULL != whh->hres_cb) &&
|
if ( (NULL != whh->hres_cb) &&
|
||||||
(GNUNET_OK !=
|
(GNUNET_OK !=
|
||||||
whh->hres_cb (whh->hres_cb_cls,
|
whh->hres_cb (whh->hres_cb_cls,
|
||||||
|
TALER_EC_NONE,
|
||||||
dir,
|
dir,
|
||||||
&bserial_id,
|
&bserial_id,
|
||||||
sizeof (bserial_id),
|
sizeof (bserial_id),
|
||||||
@ -868,6 +883,7 @@ bhist_cb (void *cls,
|
|||||||
case MHD_HTTP_NO_CONTENT:
|
case MHD_HTTP_NO_CONTENT:
|
||||||
if (NULL != whh->hres_cb)
|
if (NULL != whh->hres_cb)
|
||||||
(void) whh->hres_cb (whh->hres_cb_cls,
|
(void) whh->hres_cb (whh->hres_cb_cls,
|
||||||
|
ec,
|
||||||
TALER_BANK_DIRECTION_NONE,
|
TALER_BANK_DIRECTION_NONE,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
@ -880,6 +896,7 @@ bhist_cb (void *cls,
|
|||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
if (NULL != whh->hres_cb)
|
if (NULL != whh->hres_cb)
|
||||||
(void) whh->hres_cb (whh->hres_cb_cls,
|
(void) whh->hres_cb (whh->hres_cb_cls,
|
||||||
|
ec,
|
||||||
TALER_BANK_DIRECTION_NONE,
|
TALER_BANK_DIRECTION_NONE,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
@ -1004,26 +1021,32 @@ struct TALER_WIRE_RejectHandle
|
|||||||
void *rej_cb_cls;
|
void *rej_cb_cls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle to task for timeout of operation.
|
* Handle for the reject operation.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_SCHEDULER_Task *timeout_task;
|
struct TALER_BANK_RejectHandle *brh;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rejection operation failed with timeout, notify callback
|
* Callbacks of this type are used to serve the result of asking
|
||||||
* and clean up.
|
* the bank to reject an incoming wire transfer.
|
||||||
*
|
*
|
||||||
* @param cls closure with `struct TALER_WIRE_RejectHandle`
|
* @param cls closure
|
||||||
|
* @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for successful status request;
|
||||||
|
* #MHD_HTTP_NOT_FOUND if the rowid is unknown;
|
||||||
|
* 0 if the bank's reply is bogus (fails to follow the protocol),
|
||||||
|
* @param ec detailed error code
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
timeout_reject (void *cls)
|
reject_cb (void *cls,
|
||||||
|
unsigned int http_status,
|
||||||
|
enum TALER_ErrorCode ec)
|
||||||
{
|
{
|
||||||
struct TALER_WIRE_RejectHandle *rh = cls;
|
struct TALER_WIRE_RejectHandle *rh = cls;
|
||||||
|
|
||||||
rh->timeout_task = NULL;
|
rh->brh = NULL;
|
||||||
rh->rej_cb (rh->rej_cb_cls,
|
rh->rej_cb (rh->rej_cb_cls,
|
||||||
TALER_EC_NOT_IMPLEMENTED /* in the future: TALER_EC_TIMEOUT */);
|
ec);
|
||||||
GNUNET_free (rh);
|
GNUNET_free (rh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1052,14 +1075,30 @@ test_reject_transfer (void *cls,
|
|||||||
TALER_WIRE_RejectTransferCallback rej_cb,
|
TALER_WIRE_RejectTransferCallback rej_cb,
|
||||||
void *rej_cb_cls)
|
void *rej_cb_cls)
|
||||||
{
|
{
|
||||||
|
struct TestClosure *tc = cls;
|
||||||
|
const uint64_t *rowid_b64 = start_off;
|
||||||
struct TALER_WIRE_RejectHandle *rh;
|
struct TALER_WIRE_RejectHandle *rh;
|
||||||
|
|
||||||
GNUNET_break (0); /* not implemented, just a stub! */
|
if (sizeof (uint64_t) != start_off_len)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
rh = GNUNET_new (struct TALER_WIRE_RejectHandle);
|
rh = GNUNET_new (struct TALER_WIRE_RejectHandle);
|
||||||
rh->rej_cb = rej_cb;
|
rh->rej_cb = rej_cb;
|
||||||
rh->rej_cb_cls = rej_cb_cls;
|
rh->rej_cb_cls = rej_cb_cls;
|
||||||
rh->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_reject,
|
rh->brh = TALER_BANK_reject (tc->ctx,
|
||||||
|
tc->bank_uri,
|
||||||
|
&tc->auth,
|
||||||
|
(uint64_t) tc->exchange_account_no,
|
||||||
|
GNUNET_ntohll (*rowid_b64),
|
||||||
|
&reject_cb,
|
||||||
rh);
|
rh);
|
||||||
|
if (NULL == rh->brh)
|
||||||
|
{
|
||||||
|
GNUNET_free (rh);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return rh;
|
return rh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,7 +1121,8 @@ test_reject_transfer_cancel (void *cls,
|
|||||||
{
|
{
|
||||||
void *ret = rh->rej_cb_cls;
|
void *ret = rh->rej_cb_cls;
|
||||||
|
|
||||||
GNUNET_SCHEDULER_cancel (rh->timeout_task);
|
if (NULL != rh->brh)
|
||||||
|
TALER_BANK_reject_cancel (rh->brh);
|
||||||
GNUNET_free (rh);
|
GNUNET_free (rh);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,7 @@ timeout_cb (void *cls)
|
|||||||
* the bank for the transaction history.
|
* the bank for the transaction history.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param ec taler status code
|
||||||
* @param dir direction of the transfer
|
* @param dir direction of the transfer
|
||||||
* @param row_off identification of the position at which we are querying
|
* @param row_off identification of the position at which we are querying
|
||||||
* @param row_off_size number of bytes in @a row_off
|
* @param row_off_size number of bytes in @a row_off
|
||||||
@ -167,6 +168,7 @@ timeout_cb (void *cls)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
history_result_cb (void *cls,
|
history_result_cb (void *cls,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
enum TALER_BANK_Direction dir,
|
enum TALER_BANK_Direction dir,
|
||||||
const void *row_off,
|
const void *row_off,
|
||||||
size_t row_off_size,
|
size_t row_off_size,
|
||||||
|
Loading…
Reference in New Issue
Block a user