summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bank-lib/fakebank.c371
1 files changed, 305 insertions, 66 deletions
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index 5734caab..3eea5f8b 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -159,12 +159,13 @@ struct HistoryRangeIds
/**
* How many transactions we want in the result set. If
- * negative/positive, @a start_number will be strictly
- * younger/older of any element in the result set.
+ * negative/positive, @a start will be strictly younger/older
+ * of any element in the result set.
*/
long long count;
};
+
/**
* This is the "base" structure for both the /history and the
* /history-range API calls.
@@ -238,6 +239,17 @@ struct TALER_FAKEBANK_Handle
#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
@@ -756,9 +768,8 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
* @return GNUNET_OK only if the parsing succeedes.
*/
static int
-parse_history_args_ (struct MHD_Connection *connection,
- struct HistoryArgs *ha,
- const char *function_name)
+parse_history_common_args (struct MHD_Connection *connection,
+ struct HistoryArgs *ha)
{
/**
* @variable
@@ -865,77 +876,87 @@ parse_history_args_ (struct MHD_Connection *connection,
else
ha->ascending = GNUNET_NO;
- /* To be removed from here, and put within the dedicate method */
- if (0 == strcmp ("handle_history",
- function_name))
+ return GNUNET_OK;
+}
+
+/**
+ * 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 *delta;
+ struct Transaction *pos;
+
+ if (GNUNET_OK != parse_history_common_args (connection,
+ &ha))
{
- const char *start;
- const char *delta;
- struct HistoryRangeIds *hi = ha->range;
-
- 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",
- &hi->start)) ||
- (NULL == delta) || (1 != sscanf (delta,
- "%lld",
- &hi->count)) )
- {
- GNUNET_break (0);
- return GNUNET_NO;
- }
+ GNUNET_break (0);
+ return MHD_NO;
}
- /* To be removed from here, and put within the dedicate method */
- else if (0 == strcmp ("handle_history_range",
- function_name))
- {
- const char *start;
- const char *end;
- long long unsigned int start_stamp;
- long long unsigned int end_stamp;
- struct HistoryRangeDates *hr = ha->range;;
-
- start = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "start");
- end = MHD_lookup_connection_value (connection,
+ start = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND,
- "end");
-
- if ( (NULL == start) || (1 != sscanf (start,
- "%llu",
- &start_stamp)) ||
- (NULL == end) || (1 != sscanf (end,
+ "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",
- &end_stamp)) )
+ &hri.count)) )
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+
+ if (NULL == start)
+ pos = 0 > hri.count ?
+ 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_break (0);
- return GNUNET_NO;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid range specified,"
+ " transaction %llu not known!\n",
+ (unsigned long long) hri.start);
+ return MHD_NO;
}
-
- hr->start.abs_value_us = start_stamp * 1000LL * 1000LL;
- hr->end.abs_value_us = end_stamp * 1000LL * 1000LL;
+ /* range is exclusive, skip the matching entry */
+ if (hri.count > 0)
+ pos = pos->next;
+ if (hri.count < 0)
+ pos = pos->prev;
}
-
- /* Unknown caller. */
else
{
- GNUNET_break (0);
- return GNUNET_NO;
+ /* list is empty */
+ pos = NULL;
}
-
- return GNUNET_OK;
}
/**
- * Handle incoming HTTP request for /history
+ * Handle incoming HTTP request for /history-range.
*
* @param h the fakebank handle
* @param connection the connection
@@ -943,16 +964,234 @@ parse_history_args_ (struct MHD_Connection *connection,
* @return MHD result code
*/
static int
-handle_history_new (struct TALER_FAKEBANK_Handle *h,
- struct MHD_Connection *connection,
- void **con_cls)
+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 *end;
+ long long unsigned int start_stamp;
+ long long unsigned int end_stamp;
+
+ if (GNUNET_OK != parse_history_common_args (connection,
+ &ha))
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ start = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "start");
+ end = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "end");
+
+ if ( (NULL == start) || (1 != sscanf (start,
+ "%llu",
+ &start_stamp)) ||
+ (NULL == end) || (1 != sscanf (end,
+ "%lld",
+ &end_stamp)) )
+ {
+ GNUNET_break (0);
+ return GNUNET_NO;
+ }
+
+ hrd.start.abs_value_us = start_stamp * 1000LL * 1000LL;
+ hrd.end.abs_value_us = end_stamp * 1000LL * 1000LL;
+}
+
+
+/**
+ * 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);
+}
- GNUNET_assert (GNUNET_OK == PARSE_HISTORY_ARGS (connection,
- &ha));
+/**
+ * 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)
+ {
+ hri->count--;
+ return pos->next;
+ }
+ if (hri->count < 0)
+ {
+ hri->count++;
+ return pos->prev;
+ }
+}
+
+
+/**
+ * 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;
+}
+
+/**
+ * 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_range_step (const struct HistoryArgs *ha)
+{
+ const struct HistoryRangeDates *hrd = ha->range;
+}
+/**
+ * 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);
+ }
}