add /history support to fakebank
This commit is contained in:
parent
57964b6ae9
commit
1ea22a37c6
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2015, 2016 GNUnet e.V.
|
Copyright (C) 2015, 2016, 2017 GNUnet e.V.
|
||||||
|
|
||||||
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
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "taler_fakebank_lib.h"
|
#include "taler_fakebank_lib.h"
|
||||||
|
#include "taler_bank_service.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum POST request size (for /admin/add/incoming)
|
* Maximum POST request size (for /admin/add/incoming)
|
||||||
@ -70,6 +71,16 @@ struct Transaction
|
|||||||
* Base URL of the exchange.
|
* Base URL of the exchange.
|
||||||
*/
|
*/
|
||||||
char *exchange_base_url;
|
char *exchange_base_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When did the transaction happen?
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Absolute date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of this transaction.
|
||||||
|
*/
|
||||||
|
unsigned long long serial_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -97,6 +108,11 @@ struct TALER_FAKEBANK_Handle
|
|||||||
* Task running HTTP server for the "test" bank.
|
* Task running HTTP server for the "test" bank.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_SCHEDULER_Task *mhd_task;
|
struct GNUNET_SCHEDULER_Task *mhd_task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of transactions.
|
||||||
|
*/
|
||||||
|
unsigned long long serial_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -257,43 +273,28 @@ handle_mhd_completion_callback (void *cls,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle incoming HTTP request.
|
* Handle incoming HTTP request for /admin/add/incoming.
|
||||||
*
|
*
|
||||||
* @param cls closure for MHD daemon (unused)
|
* @param h the fakebank handle
|
||||||
* @param connection the connection
|
* @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 request data
|
||||||
* @param upload_data_size size of @a upload_data in bytes
|
* @param upload_data_size size of @a upload_data in bytes
|
||||||
* @param con_cls closure for request (a `struct Buffer *`)
|
* @param con_cls closure for request (a `struct Buffer *`)
|
||||||
* @return MHD result code
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
handle_mhd_request (void *cls,
|
handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
|
||||||
struct MHD_Connection *connection,
|
struct MHD_Connection *connection,
|
||||||
const char *url,
|
const char *upload_data,
|
||||||
const char *method,
|
size_t *upload_data_size,
|
||||||
const char *version,
|
void **con_cls)
|
||||||
const char *upload_data,
|
|
||||||
size_t *upload_data_size,
|
|
||||||
void **con_cls)
|
|
||||||
{
|
{
|
||||||
struct TALER_FAKEBANK_Handle *h = cls;
|
|
||||||
enum GNUNET_JSON_PostResult pr;
|
enum GNUNET_JSON_PostResult pr;
|
||||||
json_t *json;
|
json_t *json;
|
||||||
struct Transaction *t;
|
struct Transaction *t;
|
||||||
struct MHD_Response *resp;
|
struct MHD_Response *resp;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (0 != strcasecmp (url,
|
|
||||||
"/admin/add/incoming"))
|
|
||||||
{
|
|
||||||
/* Unexpected URI path, just close the connection. */
|
|
||||||
/* we're rather impolite here, but it's a testcase. */
|
|
||||||
GNUNET_break_op (0);
|
|
||||||
return MHD_NO;
|
|
||||||
}
|
|
||||||
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
|
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
|
||||||
con_cls,
|
con_cls,
|
||||||
upload_data,
|
upload_data,
|
||||||
@ -336,6 +337,9 @@ handle_mhd_request (void *cls,
|
|||||||
return MHD_NO;
|
return MHD_NO;
|
||||||
}
|
}
|
||||||
t->exchange_base_url = GNUNET_strdup (base_url);
|
t->exchange_base_url = GNUNET_strdup (base_url);
|
||||||
|
t->serial_id = h->serial_counter++;
|
||||||
|
t->date = GNUNET_TIME_absolute_get ();
|
||||||
|
GNUNET_TIME_round_abs (&t->date);
|
||||||
GNUNET_CONTAINER_DLL_insert (h->transactions_head,
|
GNUNET_CONTAINER_DLL_insert (h->transactions_head,
|
||||||
h->transactions_tail,
|
h->transactions_tail,
|
||||||
t);
|
t);
|
||||||
@ -355,6 +359,246 @@ handle_mhd_request (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle incoming HTTP request for /history
|
||||||
|
*
|
||||||
|
* @param h the fakebank handle
|
||||||
|
* @param connection the connection
|
||||||
|
* @return MHD result code
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
handle_history (struct TALER_FAKEBANK_Handle *h,
|
||||||
|
struct MHD_Connection *connection,
|
||||||
|
void **con_cls)
|
||||||
|
{
|
||||||
|
const char *auth;
|
||||||
|
const char *delta;
|
||||||
|
const char *start;
|
||||||
|
const char *dir;
|
||||||
|
const char *acc;
|
||||||
|
unsigned long long account_number;
|
||||||
|
unsigned long long start_number;
|
||||||
|
long long count;
|
||||||
|
enum TALER_BANK_Direction direction;
|
||||||
|
struct Transaction *pos;
|
||||||
|
json_t *history;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
auth = MHD_lookup_connection_value (connection,
|
||||||
|
MHD_GET_ARGUMENT_KIND,
|
||||||
|
"auth");
|
||||||
|
delta = MHD_lookup_connection_value (connection,
|
||||||
|
MHD_GET_ARGUMENT_KIND,
|
||||||
|
"delta");
|
||||||
|
dir = MHD_lookup_connection_value (connection,
|
||||||
|
MHD_GET_ARGUMENT_KIND,
|
||||||
|
"direction");
|
||||||
|
start = MHD_lookup_connection_value (connection,
|
||||||
|
MHD_GET_ARGUMENT_KIND,
|
||||||
|
"start");
|
||||||
|
acc = MHD_lookup_connection_value (connection,
|
||||||
|
MHD_GET_ARGUMENT_KIND,
|
||||||
|
"account_number");
|
||||||
|
if ( (NULL == auth) ||
|
||||||
|
(NULL == acc) ||
|
||||||
|
(NULL == delta) )
|
||||||
|
{
|
||||||
|
/* Invalid request, given that this is fakebank we impolitely just
|
||||||
|
kill the connection instead of returning a nice error. */
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
if ( (1 != sscanf (delta,
|
||||||
|
"%lld",
|
||||||
|
&count)) ||
|
||||||
|
(1 != sscanf (acc,
|
||||||
|
"%llu",
|
||||||
|
&account_number)) ||
|
||||||
|
( (NULL != start) &&
|
||||||
|
(1 != sscanf (start,
|
||||||
|
"%llu",
|
||||||
|
&start_number)) ) ||
|
||||||
|
( (NULL != dir) &&
|
||||||
|
(0 != strcasecmp (dir,
|
||||||
|
"CREDIT")) &&
|
||||||
|
(0 != strcasecmp (dir,
|
||||||
|
"DEBIT")) ) )
|
||||||
|
{
|
||||||
|
/* Invalid request, given that this is fakebank we impolitely just
|
||||||
|
kill the connection instead of returning a nice error. */
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
if (NULL == dir)
|
||||||
|
direction = TALER_BANK_DIRECTION_BOTH;
|
||||||
|
else if (0 == strcasecmp (dir, "CREDIT"))
|
||||||
|
direction = TALER_BANK_DIRECTION_CREDIT;
|
||||||
|
else
|
||||||
|
direction = TALER_BANK_DIRECTION_DEBIT;
|
||||||
|
if (NULL == start)
|
||||||
|
start_number = (count > 0) ? 0 : UINT64_MAX;
|
||||||
|
if (UINT64_MAX == start_number)
|
||||||
|
{
|
||||||
|
pos = h->transactions_tail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned long long off = 0;
|
||||||
|
|
||||||
|
for (pos = h->transactions_head;
|
||||||
|
off < start_number;
|
||||||
|
off++)
|
||||||
|
{
|
||||||
|
if (NULL == pos)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
pos = pos->next;
|
||||||
|
}
|
||||||
|
GNUNET_assert (pos->serial_id == start_number);
|
||||||
|
}
|
||||||
|
history = json_array ();
|
||||||
|
while ( (NULL != pos) &&
|
||||||
|
(0 != count) )
|
||||||
|
{
|
||||||
|
json_t *trans;
|
||||||
|
char *subject;
|
||||||
|
|
||||||
|
if (! ( ( (account_number == pos->debit_account) &&
|
||||||
|
(0 != (direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
|
||||||
|
( (account_number == pos->credit_account) &&
|
||||||
|
(0 != (direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) )
|
||||||
|
{
|
||||||
|
if (count > 0)
|
||||||
|
pos = pos->next;
|
||||||
|
if (count < 0)
|
||||||
|
pos = pos->prev;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
subject = GNUNET_STRINGS_data_to_string_alloc (&pos->wtid,
|
||||||
|
sizeof (pos->wtid));
|
||||||
|
trans = json_pack ("{s:I, s:o, s:o, s:s, s:I, s:s}",
|
||||||
|
"row_id", (json_int_t) pos->serial_id,
|
||||||
|
"date", GNUNET_JSON_from_time_abs (pos->date),
|
||||||
|
"amount", TALER_JSON_from_amount (&pos->amount),
|
||||||
|
"sign", (account_number == pos->debit_account) ? "-" : "+",
|
||||||
|
"counterpart", (json_int_t) ( (account_number == pos->debit_account)
|
||||||
|
? pos->credit_account
|
||||||
|
: pos->debit_account),
|
||||||
|
"wt_subject", subject);
|
||||||
|
GNUNET_free (subject);
|
||||||
|
json_array_append (history,
|
||||||
|
trans);
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
pos = pos->next;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
pos = pos->prev;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == json_array_size (history))
|
||||||
|
{
|
||||||
|
struct MHD_Response *resp;
|
||||||
|
|
||||||
|
json_decref (history);
|
||||||
|
resp = MHD_create_response_from_buffer (0,
|
||||||
|
"",
|
||||||
|
MHD_RESPMEM_PERSISTENT);
|
||||||
|
ret = MHD_queue_response (connection,
|
||||||
|
MHD_HTTP_NO_CONTENT,
|
||||||
|
resp);
|
||||||
|
MHD_destroy_response (resp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally build response object */
|
||||||
|
{
|
||||||
|
struct MHD_Response *resp;
|
||||||
|
void *json_str;
|
||||||
|
size_t json_len;
|
||||||
|
|
||||||
|
json_str = json_dumps (history,
|
||||||
|
JSON_INDENT(2));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
ret = MHD_queue_response (connection,
|
||||||
|
MHD_HTTP_OK,
|
||||||
|
resp);
|
||||||
|
MHD_destroy_response (resp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
if ( (0 == strcasecmp (url,
|
||||||
|
"/admin/add/incoming")) &&
|
||||||
|
(0 == strcasecmp (method,
|
||||||
|
MHD_HTTP_METHOD_POST)) )
|
||||||
|
return handle_admin_add_incoming (h,
|
||||||
|
connection,
|
||||||
|
upload_data,
|
||||||
|
upload_data_size,
|
||||||
|
con_cls);
|
||||||
|
if ( (0 == strcasecmp (url,
|
||||||
|
"/history")) &&
|
||||||
|
(0 == strcasecmp (method,
|
||||||
|
MHD_HTTP_METHOD_GET)) )
|
||||||
|
return handle_history (h,
|
||||||
|
connection,
|
||||||
|
con_cls);
|
||||||
|
|
||||||
|
/* Unexpected URI path, just close the connection. */
|
||||||
|
/* we're rather impolite here, but it's a testcase. */
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Task run whenever HTTP server operations are pending.
|
* Task run whenever HTTP server operations are pending.
|
||||||
*
|
*
|
||||||
@ -466,3 +710,6 @@ TALER_FAKEBANK_start (uint16_t port)
|
|||||||
schedule_httpd (h);
|
schedule_httpd (h);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end of fakebank.c */
|
||||||
|
@ -1753,10 +1753,10 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
strlen (rrh->json_enc)));
|
strlen (rrh->json_enc)));
|
||||||
ctx = MAH_handle_to_context (rrh->exchange);
|
ctx = MAH_handle_to_context (rrh->exchange);
|
||||||
rrh->job = GNUNET_CURL_job_add (ctx,
|
rrh->job = GNUNET_CURL_job_add (ctx,
|
||||||
eh,
|
eh,
|
||||||
GNUNET_YES,
|
GNUNET_YES,
|
||||||
&handle_refresh_reveal_finished,
|
&handle_refresh_reveal_finished,
|
||||||
rrh);
|
rrh);
|
||||||
return rrh;
|
return rrh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user