summaryrefslogtreecommitdiff
path: root/src/bank-lib/fakebank.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-01-11 15:19:56 +0100
committerChristian Grothoff <christian@grothoff.org>2020-01-11 15:20:17 +0100
commit9443c10d7feb0d91323869dd08ec61ca781564f4 (patch)
treefd617ea56cc1d2ea370ce7e5467574a536b52d28 /src/bank-lib/fakebank.c
parent554da10133eb491b352a106b98ebeaed797133bb (diff)
downloadexchange-9443c10d7feb0d91323869dd08ec61ca781564f4.tar.gz
exchange-9443c10d7feb0d91323869dd08ec61ca781564f4.tar.bz2
exchange-9443c10d7feb0d91323869dd08ec61ca781564f4.zip
major refactoring, eliminating wire-plugins and moving towards new bank API. main code compiles, testcases known to fail, code sure not to fully work yet
Diffstat (limited to 'src/bank-lib/fakebank.c')
-rw-r--r--src/bank-lib/fakebank.c728
1 files changed, 474 insertions, 254 deletions
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index d8ea392b5..1706ca8fb 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+ (C) 2016-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -25,7 +25,7 @@
#include "platform.h"
#include "taler_fakebank_lib.h"
#include "taler_bank_service.h"
-#include "fakebank.h"
+#include "taler_mhd_lib.h"
/**
* Maximum POST request size (for /admin/add/incoming)
@@ -34,6 +34,65 @@
/**
+ * Details about a transcation we (as the simulated bank) received.
+ */
+struct Transaction
+{
+ /**
+ * We store transactions in a DLL.
+ */
+ struct Transaction *next;
+
+ /**
+ * We store transactions in a DLL.
+ */
+ struct Transaction *prev;
+
+ /**
+ * Amount to be transferred.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Account to debit.
+ */
+ char *debit_account;
+
+ /**
+ * Account to credit.
+ */
+ char *credit_account;
+
+ /**
+ * Subject of the transfer.
+ */
+ char *subject;
+
+ /**
+ * Base URL of the exchange.
+ */
+ char *exchange_base_url;
+
+ /**
+ * When did the transaction happen?
+ */
+ struct GNUNET_TIME_Absolute date;
+
+ /**
+ * Number of this transaction.
+ */
+ uint64_t row_id;
+
+ /**
+ * Has this transaction been subjected to #TALER_FAKEBANK_check()
+ * and should thus no longer be counted in
+ * #TALER_FAKEBANK_check_empty()?
+ */
+ int checked;
+};
+
+
+/**
* Handle for the fake bank.
*/
struct TALER_FAKEBANK_Handle
@@ -63,6 +122,11 @@ struct TALER_FAKEBANK_Handle
*/
uint64_t serial_counter;
+ /**
+ * Our port number.
+ */
+ uint16_t port;
+
#if EPOLL_SUPPORT
/**
* Boxed @e mhd_fd.
@@ -95,8 +159,8 @@ struct TALER_FAKEBANK_Handle
int
TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
const struct TALER_Amount *want_amount,
- uint64_t want_debit,
- uint64_t want_credit,
+ const char *want_debit,
+ const char *want_credit,
const char *exchange_base_url,
char **subject)
{
@@ -151,8 +215,8 @@ TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
*/
uint64_t
TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
- uint64_t debit_account,
- uint64_t credit_account,
+ const char *debit_account,
+ const char *credit_account,
const struct TALER_Amount *amount,
const char *subject,
const char *exchange_base_url)
@@ -160,15 +224,15 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
struct Transaction *t;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Making transfer from %llu to %llu over %s and subject %s; for exchange: %s\n",
- (unsigned long long) debit_account,
- (unsigned long long) credit_account,
+ "Making transfer from %s to %s over %s and subject %s; for exchange: %s\n",
+ debit_account,
+ credit_account,
TALER_amount2s (amount),
subject,
exchange_base_url);
t = GNUNET_new (struct Transaction);
- t->debit_account = debit_account;
- t->credit_account = credit_account;
+ t->debit_account = GNUNET_strdup (debit_account);
+ t->credit_account = GNUNET_strdup (credit_account);
t->amount = *amount;
t->exchange_base_url = GNUNET_strdup (exchange_base_url);
t->row_id = ++h->serial_counter;
@@ -183,31 +247,6 @@ 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->row_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
* that have not been taken care of via #TALER_FAKEBANK_check()).
* If any transactions are onrecord, return #GNUNET_SYSERR.
@@ -223,8 +262,7 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h)
t = h->transactions_head;
while (NULL != t)
{
- if ( (GNUNET_YES != t->checked) &&
- (GNUNET_YES != t->rejected) )
+ if (GNUNET_YES != t->checked)
break;
t = t->next;
}
@@ -234,16 +272,15 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h)
"Expected empty transaction set, but I have:\n");
while (NULL != t)
{
- if ( (GNUNET_YES != t->checked) &&
- (GNUNET_YES != t->rejected) )
+ if (GNUNET_YES != t->checked)
{
char *s;
s = TALER_amount_to_string (&t->amount);
fprintf (stderr,
- "%llu -> %llu (%s) from %s\n",
- (unsigned long long) t->debit_account,
- (unsigned long long) t->credit_account,
+ "%s -> %s (%s) from %s\n",
+ t->debit_account,
+ t->credit_account,
s,
t->exchange_base_url);
GNUNET_free (s);
@@ -270,6 +307,8 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
h->transactions_tail,
t);
GNUNET_free (t->subject);
+ GNUNET_free (t->debit_account);
+ GNUNET_free (t->credit_account);
GNUNET_free (t->exchange_base_url);
GNUNET_free (t);
}
@@ -291,62 +330,6 @@ 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
* request was a POST, we may have stored a `struct Buffer *` in the
* @a con_cls that might still need to be cleaned up. Call the
@@ -394,8 +377,6 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
{
enum GNUNET_JSON_PostResult pr;
json_t *json;
- struct MHD_Response *resp;
- int ret;
uint64_t row_id;
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
@@ -422,15 +403,14 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
}
{
const char *subject;
- uint64_t debit_account;
- uint64_t credit_account;
+ const char *debit_account;
+ const char *credit_account;
const char *base_url;
struct TALER_Amount amount;
- char *amount_s;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("subject", &subject),
- GNUNET_JSON_spec_uint64 ("debit_account", &debit_account),
- GNUNET_JSON_spec_uint64 ("credit_account", &credit_account),
+ GNUNET_JSON_spec_string ("debit_account", &debit_account),
+ GNUNET_JSON_spec_string ("credit_account", &credit_account),
TALER_JSON_spec_amount ("amount", &amount),
GNUNET_JSON_spec_string ("exchange_url", &base_url),
GNUNET_JSON_spec_end ()
@@ -450,80 +430,49 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
&amount,
subject,
base_url);
- amount_s = TALER_amount_to_string (&amount);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Receiving incoming wire transfer: %llu->%llu, subject: %s, amount: %s, from %s\n",
- (unsigned long long) debit_account,
- (unsigned long long) credit_account,
+ "Receiving incoming wire transfer: %s->%s, subject: %s, amount: %s, from %s\n",
+ debit_account,
+ credit_account,
subject,
- amount_s,
+ TALER_amount2s (&amount),
base_url);
- GNUNET_free (amount_s);
}
json_decref (json);
/* Finally build response object */
- {
- void *json_str;
- size_t json_len;
-
- json = json_pack ("{s:I, s:o}",
- "row_id",
- (json_int_t) row_id,
- "timestamp", GNUNET_JSON_from_time_abs (GNUNET_TIME_UNIT_ZERO_ABS)); /*dummy tmp */
-
- 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,
- MHD_HTTP_OK,
- resp);
- MHD_destroy_response (resp);
- return ret;
+ return TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:I, s:o}",
+ "row_id",
+ (json_int_t) row_id,
+ "timestamp", GNUNET_JSON_from_time_abs (
+ GNUNET_TIME_UNIT_ZERO_ABS)); /*dummy tmp */
}
/**
- * Handle incoming HTTP request for /reject.
+ * Handle incoming HTTP request for /transaction.
*
* @param h the fakebank handle
* @param connection the connection
+ * @param account account making the transaction
* @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)
+handle_transaction (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account,
+ 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;
+ uint64_t row_id;
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
connection,
@@ -548,13 +497,25 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
break;
}
{
- uint64_t row_id;
- uint64_t credit_account;
+ struct GNUNET_HashCode uuid;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ const char *credit_account;
+ const char *base_url;
+ struct TALER_Amount amount;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint64 ("row_id", &row_id),
- GNUNET_JSON_spec_uint64 ("account_number", &credit_account),
+ GNUNET_JSON_spec_fixed_auto ("request_uid",
+ &uuid),
+ TALER_JSON_spec_amount ("amount",
+ &amount),
+ GNUNET_JSON_spec_string ("exchange_base_url",
+ &base_url),
+ GNUNET_JSON_spec_fixed_auto ("wtid",
+ &wtid),
+ GNUNET_JSON_spec_string ("credit_account",
+ &credit_account),
GNUNET_JSON_spec_end ()
};
+
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
spec,
@@ -564,31 +525,38 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
json_decref (json);
return MHD_NO;
}
- found = TALER_FAKEBANK_reject_transfer (h,
- row_id,
- credit_account);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Rejected wire transfer #%llu (to %llu)\n",
- (unsigned long long) row_id,
- (unsigned long long) credit_account);
+ {
+ char *subject;
+
+ subject = GNUNET_STRINGS_data_to_string_alloc (&wtid,
+ sizeof (wtid));
+ // FIXME: use uuid here!!!
+ row_id = TALER_FAKEBANK_make_transfer (h,
+ account,
+ credit_account,
+ &amount,
+ subject,
+ base_url);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Receiving incoming wire transfer: %s->%s, subject: %s, amount: %s, from %s\n",
+ account,
+ credit_account,
+ subject,
+ TALER_amount2s (&amount),
+ base_url);
+ GNUNET_free (subject);
+ }
}
json_decref (json);
- if (GNUNET_OK != found)
- return create_bank_error
- (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_BANK_TRANSACTION_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;
+ /* Finally build response object */
+ return TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:I, s:o}",
+ "row_id",
+ (json_int_t) row_id,
+ "timestamp", GNUNET_JSON_from_time_abs (
+ GNUNET_TIME_UNIT_ZERO_ABS)); /*dummy tmp */
}
@@ -626,75 +594,245 @@ handle_home_page (struct TALER_FAKEBANK_Handle *h,
/**
- * Handle incoming HTTP request for /history
+ * This is the "base" structure for both the /history and the
+ * /history-range API calls.
+ */
+struct HistoryArgs
+{
+
+ /**
+ * Bank account number of the requesting client.
+ */
+ uint64_t account_number;
+
+ /**
+ * Index of the starting transaction.
+ */
+ uint64_t start_idx;
+
+ /**
+ * Requested number of results and order
+ * (positive: ascending, negative: descending)
+ */
+ int64_t delta;
+
+ /**
+ * Timeout for long polling.
+ */
+ struct GNUNET_TIME_Relative lp_timeout;
+
+ /**
+ * #GNUNET_YES if starting point was given.
+ */
+ int have_start;
+
+};
+
+
+/**
+ * Parse URL history arguments, of _both_ APIs:
+ * /history/incoming and /history/outgoing.
+ *
+ * @param connection MHD connection.
+ * @param function_name name of the caller.
+ * @param ha[out] will contain the parsed values.
+ * @return GNUNET_OK only if the parsing succeedes.
+ */
+static int
+parse_history_common_args (struct MHD_Connection *connection,
+ struct HistoryArgs *ha)
+{
+ const char *start;
+ const char *delta;
+ const char *long_poll_ms;
+ unsigned long long lp_timeout;
+ unsigned long long sval;
+ long long d;
+
+ start = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "start");
+ ha->have_start = (NULL != start);
+ delta = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "delta");
+ long_poll_ms = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "long_poll_ms");
+ lp_timeout = 0;
+ if ( (NULL == delta) ||
+ (1 != sscanf (delta,
+ "%lld",
+ &d)) ||
+ ( (NULL != long_poll_ms) &&
+ (1 != sscanf (long_poll_ms,
+ "%llu",
+ &lp_timeout)) ) ||
+ ( (NULL != start) &&
+ (1 != sscanf (start,
+ "%llu",
+ &sval)) ) )
+ {
+ /* Fail if one of the above failed. */
+ /* Invalid request, given that this is fakebank we impolitely
+ * just kill the connection instead of returning a nice error.
+ */
+ GNUNET_break (0);
+ return GNUNET_NO;
+ }
+ if (NULL == start)
+ ha->start_idx = (d > 0) ? 0 : UINT64_MAX;
+ else
+ ha->start_idx = (uint64_t) sval;
+ ha->delta = (int64_t) d;
+ ha->lp_timeout
+ = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+ lp_timeout);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle incoming HTTP request for /history/incoming
*
* @param h the fakebank handle
* @param connection the connection
- * @param con_cls place to store state, not used
+ * @param account which account the request is about
* @return MHD result code
*/
static int
-handle_history (struct TALER_FAKEBANK_Handle *h,
- struct MHD_Connection *connection,
- void **con_cls)
+handle_credit_history (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account)
{
struct HistoryArgs ha;
- struct HistoryRangeIds hri;
- const char *start;
- const char *delta;
struct Transaction *pos;
+ json_t *history;
- (void) con_cls;
if (GNUNET_OK !=
- TFH_parse_history_common_args (connection,
- &ha))
+ parse_history_common_args (connection,
+ &ha))
{
GNUNET_break (0);
return MHD_NO;
}
- start = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "start");
- delta = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "delta");
- if ( ((NULL != start) && (1 != sscanf (start,
- "%llu",
- &hri.start))) ||
- (NULL == delta) || (1 != sscanf (delta,
- "%lld",
- &hri.count)) )
+ if (! ha.have_start)
+ {
+ pos = (0 > ha.delta)
+ ? h->transactions_tail
+ : h->transactions_head;
+ }
+ else if (NULL != h->transactions_head)
+ {
+ for (pos = h->transactions_head;
+ NULL != pos;
+ pos = pos->next)
+ if (pos->row_id == ha.start_idx)
+ break;
+ if (NULL == pos)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid start specified, transaction %llu not known!\n",
+ (unsigned long long) ha.start_idx);
+ return MHD_NO;
+ }
+ /* range is exclusive, skip the matching entry */
+ if (ha.delta > 0)
+ pos = pos->next;
+ if (ha.delta < 0)
+ pos = pos->prev;
+ }
+ else
+ {
+ /* list is empty */
+ pos = NULL;
+ }
+ history = json_array ();
+ while ( (0 != ha.delta) &&
+ (NULL != pos) )
+ {
+ if (0 == strcasecmp (pos->credit_account,
+ account))
+ {
+ json_t *trans;
+
+ trans = json_pack
+ ("{s:I, s:o, s:o, s:s, s:s, s:s}",
+ "row_id", (json_int_t) pos->row_id,
+ "date", GNUNET_JSON_from_time_abs (pos->date),
+ "amount", TALER_JSON_from_amount (&pos->amount),
+ "credit_account", account,
+ "debit_account", pos->debit_account,
+ "wtid", pos->subject /* we "know" it is OK */);
+ GNUNET_assert (0 ==
+ json_array_append_new (history,
+ trans));
+ if (ha.delta > 0)
+ ha.delta--;
+ else
+ ha.delta++;
+ }
+ if (ha.delta > 0)
+ pos = pos->prev;
+ else
+ pos = pos->next;
+ }
+ return TALER_MHD_reply_json (connection,
+ history,
+ MHD_HTTP_OK);
+}
+
+
+/**
+ * Handle incoming HTTP request for /history/incoming
+ *
+ * @param h the fakebank handle
+ * @param connection the connection
+ * @param account which account the request is about
+ * @return MHD result code
+ */
+static int
+handle_debit_history (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account)
+{
+ struct HistoryArgs ha;
+ struct Transaction *pos;
+ json_t *history;
+
+ if (GNUNET_OK !=
+ parse_history_common_args (connection,
+ &ha))
{
GNUNET_break (0);
return MHD_NO;
}
- ha.range = &hri;
- if (NULL == start)
+ if (! ha.have_start)
{
- pos = 0 > hri.count ?
- h->transactions_tail : h->transactions_head;
+ pos = (0 > ha.delta)
+ ? h->transactions_tail
+ : h->transactions_head;
}
else if (NULL != h->transactions_head)
{
for (pos = h->transactions_head;
NULL != pos;
pos = pos->next)
- if (pos->row_id == hri.start)
+ if (pos->row_id == ha.start_idx)
break;
if (NULL == pos)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid range specified,"
- " transaction %llu not known!\n",
- (unsigned long long) hri.start);
+ "Invalid start specified, transaction %llu not known!\n",
+ (unsigned long long) ha.start_idx);
return MHD_NO;
}
/* range is exclusive, skip the matching entry */
- if (hri.count > 0)
+ if (ha.delta > 0)
pos = pos->next;
- if (hri.count < 0)
+ if (ha.delta < 0)
pos = pos->prev;
}
else
@@ -702,56 +840,77 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
/* list is empty */
pos = NULL;
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "/history, start row (0 == no transactions exist): %llu\n",
- NULL != pos ? pos->row_id : 0LL);
- return TFH_build_history_response (connection,
- pos,
- &ha,
- &TFH_handle_history_skip,
- &TFH_handle_history_step,
- &TFH_handle_history_advance);
+ history = json_array ();
+ while ( (0 != ha.delta) &&
+ (NULL != pos) )
+ {
+ if (0 == strcasecmp (pos->debit_account,
+ account))
+ {
+ json_t *trans;
+
+ trans = json_pack
+ ("{s:I, s:o, s:o, s:s, s:s, s:s}",
+ "row_id", (json_int_t) pos->row_id,
+ "date", GNUNET_JSON_from_time_abs (pos->date),
+ "amount", TALER_JSON_from_amount (&pos->amount),
+ "credit_account", pos->credit_account,
+ "debit_account", account,
+ "reserve_pub", pos->subject /* we "know" it is OK */);
+ GNUNET_assert (0 ==
+ json_array_append_new (history,
+ trans));
+ if (ha.delta > 0)
+ ha.delta--;
+ else
+ ha.delta++;
+ }
+ if (ha.delta > 0)
+ pos = pos->prev;
+ else
+ pos = pos->next;
+ }
+ return TALER_MHD_reply_json (connection,
+ history,
+ MHD_HTTP_OK);
}
/**
* Handle incoming HTTP request.
*
- * @param cls a `struct TALER_FAKEBANK_Handle`
+ * @param h our handle
* @param connection the connection
* @param url the requested url
* @param method the method (POST, GET, ...)
- * @param version HTTP version (ignored)
+ * @param account which account should process the request
* @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_mhd_request (void *cls,
- struct MHD_Connection *connection,
- const char *url,
- const char *method,
- const char *version,
- const char *upload_data,
- size_t *upload_data_size,
- void **con_cls)
+serve (struct TALER_FAKEBANK_Handle *h,
+ struct MHD_Connection *connection,
+ const char *account,
+ const char *url,
+ const char *method,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
{
- struct TALER_FAKEBANK_Handle *h = cls;
-
- (void) version;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Fakebank, serving: %s\n",
url);
- if ( (0 == strcasecmp (url,
- "/")) &&
+ if ( (0 == strcmp (url,
+ "/")) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_GET)) )
return handle_home_page (h,
connection,
con_cls);
- if ( (0 == strcasecmp (url,
- "/admin/add/incoming")) &&
+ if ( (0 == strcmp (url,
+ "/admin/add/incoming")) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_POST)) )
return handle_admin_add_incoming (h,
@@ -759,22 +918,33 @@ handle_mhd_request (void *cls,
upload_data,
upload_data_size,
con_cls);
- if ( (0 == strcasecmp (url,
- "/reject")) &&
+ if ( (0 == strcmp (url,
+ "/transaction")) &&
+ (NULL != account) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_POST)) )
- return handle_reject (h,
- connection,
- upload_data,
- upload_data_size,
- con_cls);
- if ( (0 == strcasecmp (url,
- "/history")) &&
+ return handle_transaction (h,
+ connection,
+ account,
+ upload_data,
+ upload_data_size,
+ con_cls);
+ if ( (0 == strcmp (url,
+ "/history/incoming")) &&
+ (NULL != account) &&
+ (0 == strcasecmp (method,
+ MHD_HTTP_METHOD_GET)) )
+ return handle_credit_history (h,
+ connection,
+ account);
+ if ( (0 == strcmp (url,
+ "/history/outgoing")) &&
+ (NULL != account) &&
(0 == strcasecmp (method,
MHD_HTTP_METHOD_GET)) )
- return handle_history (h,
- connection,
- con_cls);
+ return handle_debit_history (h,
+ connection,
+ account);
/* Unexpected URL path, just close the connection. */
/* we're rather impolite here, but it's a testcase. */
@@ -786,6 +956,55 @@ handle_mhd_request (void *cls,
/**
+ * Handle incoming HTTP request.
+ *
+ * @param cls a `struct TALER_FAKEBANK_Handle`
+ * @param connection the connection
+ * @param url the requested url
+ * @param method the method (POST, GET, ...)
+ * @param version HTTP version (ignored)
+ * @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_mhd_request (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
+{
+ struct TALER_FAKEBANK_Handle *h = cls;
+ char *account = NULL;
+ char *end;
+ int ret;
+
+ (void) version;
+ if ( (strlen (url) > 1) &&
+ (NULL != (end = strchr (url + 1, '/'))) )
+ {
+ account = GNUNET_strndup (url + 1,
+ end - url - 1);
+ url = end;
+ }
+ ret = serve (h,
+ connection,
+ account,
+ url,
+ method,
+ upload_data,
+ upload_data_size,
+ con_cls);
+ GNUNET_free_non_null (account);
+ return ret;
+}
+
+
+/**
* Task run whenever HTTP server operations are pending.
*
* @param cls the `struct TALER_FAKEBANK_Handle`
@@ -918,6 +1137,7 @@ TALER_FAKEBANK_start (uint16_t port)
struct TALER_FAKEBANK_Handle *h;
h = GNUNET_new (struct TALER_FAKEBANK_Handle);
+ h->port = port;
h->mhd_bank = MHD_start_daemon (MHD_USE_DEBUG
#if EPOLL_SUPPORT
| MHD_USE_EPOLL_INTERNAL_THREAD