Half-baking #5666.

This commit is contained in:
Marcello Stanisci 2019-04-05 19:31:01 +02:00
parent a19baaccf3
commit 8655a40ad7
No known key found for this signature in database
GPG Key ID: 8D526861953F4C0F

View File

@ -159,12 +159,13 @@ struct HistoryRangeIds
/** /**
* How many transactions we want in the result set. If * How many transactions we want in the result set. If
* negative/positive, @a start_number will be strictly * negative/positive, @a start will be strictly younger/older
* younger/older of any element in the result set. * of any element in the result set.
*/ */
long long count; long long count;
}; };
/** /**
* This is the "base" structure for both the /history and the * This is the "base" structure for both the /history and the
* /history-range API calls. * /history-range API calls.
@ -238,6 +239,17 @@ struct TALER_FAKEBANK_Handle
#endif #endif
}; };
typedef int (*CheckAdvance)(const struct HistoryArgs *ha,
struct Transaction *pos);
typedef struct Transaction * (*Step)
(const struct HistoryArgs *ha,
const struct Transaction *pos);
typedef struct Transaction * (*Skip)
(const struct HistoryArgs *ha,
const struct Transaction *pos);
/** /**
* Check that the @a want_amount was transferred from * Check that the @a want_amount was transferred from
@ -756,9 +768,8 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
* @return GNUNET_OK only if the parsing succeedes. * @return GNUNET_OK only if the parsing succeedes.
*/ */
static int static int
parse_history_args_ (struct MHD_Connection *connection, parse_history_common_args (struct MHD_Connection *connection,
struct HistoryArgs *ha, struct HistoryArgs *ha)
const char *function_name)
{ {
/** /**
* @variable * @variable
@ -865,13 +876,34 @@ parse_history_args_ (struct MHD_Connection *connection,
else else
ha->ascending = GNUNET_NO; ha->ascending = GNUNET_NO;
/* To be removed from here, and put within the dedicate method */ return GNUNET_OK;
if (0 == strcmp ("handle_history", }
function_name))
{ /**
* Handle incoming HTTP request for /history
*
* @param h the fakebank handle
* @param connection the connection
* @param con_cls place to store state, not used
* @return MHD result code
*/
static int
handle_history_new (struct TALER_FAKEBANK_Handle *h,
struct MHD_Connection *connection,
void **con_cls)
{
struct HistoryArgs ha;
struct HistoryRangeIds hri;
const char *start; const char *start;
const char *delta; const char *delta;
struct HistoryRangeIds *hi = ha->range; struct Transaction *pos;
if (GNUNET_OK != parse_history_common_args (connection,
&ha))
{
GNUNET_break (0);
return MHD_NO;
}
start = MHD_lookup_connection_value (connection, start = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
@ -879,28 +911,77 @@ parse_history_args_ (struct MHD_Connection *connection,
delta = MHD_lookup_connection_value (connection, delta = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
"delta"); "delta");
if ( (NULL == start) || (1 != sscanf (start, if ( ((NULL != start) && (1 != sscanf (start,
"%llu", "%llu",
&hi->start)) || &hri.start))) ||
(NULL == delta) || (1 != sscanf (delta, (NULL == delta) || (1 != sscanf (delta,
"%lld", "%lld",
&hi->count)) ) &hri.count)) )
{ {
GNUNET_break (0); GNUNET_break (0);
return GNUNET_NO; return MHD_NO;
}
} }
/* To be removed from here, and put within the dedicate method */ if (NULL == start)
else if (0 == strcmp ("handle_history_range", pos = 0 > hri.count ?
function_name)) 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)
break;
if (NULL == pos)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid range specified,"
" transaction %llu not known!\n",
(unsigned long long) hri.start);
return MHD_NO;
}
/* range is exclusive, skip the matching entry */
if (hri.count > 0)
pos = pos->next;
if (hri.count < 0)
pos = pos->prev;
}
else
{
/* list is empty */
pos = NULL;
}
}
/**
* Handle incoming HTTP request for /history-range.
*
* @param h the fakebank handle
* @param connection the connection
* @param con_cls place to store state, not used
* @return MHD result code
*/
static int
handle_history_range (struct TALER_FAKEBANK_Handle *h,
struct MHD_Connection *connection,
void **con_cls)
{
struct HistoryArgs ha;
struct HistoryRangeDates hrd;
const char *start; const char *start;
const char *end; const char *end;
long long unsigned int start_stamp; long long unsigned int start_stamp;
long long unsigned int end_stamp; long long unsigned int end_stamp;
struct HistoryRangeDates *hr = ha->range;;
if (GNUNET_OK != parse_history_common_args (connection,
&ha))
{
GNUNET_break (0);
return MHD_NO;
}
start = MHD_lookup_connection_value (connection, start = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
"start"); "start");
@ -919,40 +1000,198 @@ parse_history_args_ (struct MHD_Connection *connection,
return GNUNET_NO; return GNUNET_NO;
} }
hr->start.abs_value_us = start_stamp * 1000LL * 1000LL; hrd.start.abs_value_us = start_stamp * 1000LL * 1000LL;
hr->end.abs_value_us = end_stamp * 1000LL * 1000LL; hrd.end.abs_value_us = end_stamp * 1000LL * 1000LL;
} }
/* Unknown caller. */
else /**
* Decides whether the history builder will advance or not
* to the next element.
*
* @param ha history args
* @return GNUNET_YES/NO to advance/not-advance.
*/
static int
handle_history_advance (const struct HistoryArgs *ha,
struct Transaction *pos)
{
const struct HistoryRangeIds *hri = ha->range;
return (NULL != pos) && (0 != hri->count);
}
/**
* Iterates on the "next" element to be processed. To
* be used when the current element does not get inserted in
* the result.
*
* @param ha history arguments.
* @param pos current element being processed.
* @return the next element to be processed.
*/
static struct Transaction *
handle_history_skip (const struct HistoryArgs *ha,
const struct Transaction *pos)
{
const struct HistoryRangeIds *hri = ha->range;
if (hri->count > 0)
return pos->next;
if (hri->count < 0)
return pos->prev;
}
/**
* Iterates on the "next" element to be processed. To
* be used when the current element _gets_ inserted in the result.
*
* @param ha history arguments.
* @param pos current element being processed.
* @return the next element to be processed.
*/
static struct Transaction *
handle_history_step (struct HistoryArgs *ha,
const struct Transaction *pos)
{
struct HistoryRangeIds *hri = ha->range;
if (hri->count > 0)
{ {
GNUNET_break (0); hri->count--;
return GNUNET_NO; return pos->next;
} }
if (hri->count < 0)
{
hri->count++;
return pos->prev;
}
}
return GNUNET_OK; /**
* Decides whether the history builder will advance or not
* to the next element.
*
* @param ha history args
* @return GNUNET_YES/NO to advance/not-advance.
*/
static int
handle_history_range_advance (const struct HistoryArgs *ha)
{
const struct HistoryRangeDates *hrd = ha->range;
}
/**
* Iterates towards the "next" element to be processed. To
* be used when the current element does not get inserted in
* the result.
*
* @param ha history arguments.
* @param pos current element being processed.
* @return the next element to be processed.
*/
static struct Transaction *
handle_history_range_skip (const struct HistoryArgs *ha)
{
const struct HistoryRangeDates *hrd = ha->range;
} }
/** /**
* Handle incoming HTTP request for /history * Iterates on the "next" element to be processed. To
* be used when the current element _gets_ inserted in the result.
* *
* @param h the fakebank handle * @param ha history arguments.
* @param connection the connection * @param pos current element being processed.
* @param con_cls place to store state, not used * @return the next element to be processed.
* @return MHD result code
*/ */
static int static struct Transaction *
handle_history_new (struct TALER_FAKEBANK_Handle *h, handle_history_range_step (const struct HistoryArgs *ha)
struct MHD_Connection *connection,
void **con_cls)
{ {
struct HistoryArgs ha; const struct HistoryRangeDates *hrd = ha->range;
}
GNUNET_assert (GNUNET_OK == PARSE_HISTORY_ARGS (connection, /**
&ha)); * Actual history response builder.
*
* @param pos first (included) element in the result set.
* @param ha history arguments.
* @param caller_name which function is building the history.
* @return MHD response object, or NULL if any error occurs.
*/
static struct MHD_response *
build_history_response (struct Transaction *pos,
struct HistoryArgs *ha,
Skip skip,
Step step,
CheckAdvance advance)
{
struct HistoryElement *history_results_head = NULL;
struct HistoryElement *history_results_tail = NULL;
struct HistoryElement *history_element = NULL;
while (GNUNET_YES == advance (ha,
pos))
{
json_t *trans;
char *subject;
const char *sign;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Found transaction over %s from %llu to %llu\n",
TALER_amount2s (&pos->amount),
(unsigned long long) pos->debit_account,
(unsigned long long) pos->credit_account);
if ( (! ( ( (ha->account_number == pos->debit_account) &&
(0 != (ha->direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
( (ha->account_number == pos->credit_account) &&
(0 != (ha->direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) ) ||
( (0 == (ha->direction & TALER_BANK_DIRECTION_CANCEL)) &&
(GNUNET_YES == pos->rejected) ) )
{
pos = skip (ha,
pos);
continue;
}
GNUNET_asprintf (&subject,
"%s %s",
pos->subject,
pos->exchange_base_url);
sign =
(ha->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}",
"row_id", (json_int_t) pos->row_id,
"date", GNUNET_JSON_from_time_abs (pos->date),
"amount", TALER_JSON_from_amount (&pos->amount),
"sign", sign,
"counterpart", (json_int_t)
( (ha->account_number == pos->debit_account)
? pos->credit_account
: pos->debit_account),
"wt_subject", subject);
GNUNET_assert (NULL != trans);
GNUNET_free (subject);
history_element = GNUNET_new (struct HistoryElement);
history_element->element = trans;
/* XXX: the ordering feature is missing. */
GNUNET_CONTAINER_DLL_insert_tail (history_results_head,
history_results_tail,
history_element);
pos = step (ha, pos);
}
} }