summaryrefslogtreecommitdiff
path: root/src/backend/anastasis-httpd_truth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/anastasis-httpd_truth.c')
-rw-r--r--src/backend/anastasis-httpd_truth.c102
1 files changed, 98 insertions, 4 deletions
diff --git a/src/backend/anastasis-httpd_truth.c b/src/backend/anastasis-httpd_truth.c
index b9c0382..f69ff7b 100644
--- a/src/backend/anastasis-httpd_truth.c
+++ b/src/backend/anastasis-httpd_truth.c
@@ -125,7 +125,13 @@ struct GetContext
struct MHD_Response *resp;
/**
- * How long do we wait at most for payment?
+ * Our entry in the #to_heap, or NULL.
+ */
+ struct GNUNET_CONTAINER_HeapNode *hn;
+
+ /**
+ * How long do we wait at most for payment or
+ * authorization?
*/
struct GNUNET_TIME_Absolute timeout;
@@ -218,6 +224,55 @@ static struct GetContext *gc_head;
*/
static struct GetContext *gc_tail;
+/**
+ * Heap for processing timeouts of requests.
+ */
+static struct GNUNET_CONTAINER_Heap *to_heap;
+
+/**
+ * Task running #do_timeout().
+ */
+static struct GNUNET_SCHEDULER_Task *to_task;
+
+
+/**
+ * Timeout requests that are past their due date.
+ *
+ * @param cls NULL
+ */
+static void
+do_timeout (void *cls)
+{
+ struct GetContext *gc;
+
+ (void) cls;
+ to_task = NULL;
+ while (NULL !=
+ (gc = GNUNET_CONTAINER_heap_peek (to_heap)))
+ {
+ if (GNUNET_TIME_absolute_is_future (gc->timeout))
+ break;
+ if (gc->suspended)
+ {
+ /* Test needed as we may have a "concurrent"
+ wakeup from another task that did not clear
+ this entry from the heap before the
+ response process concluded. */
+ gc->suspended = false;
+ MHD_resume_connection (gc->connection);
+ }
+ GNUNET_assert (NULL != gc->hn);
+ gc->hn = NULL;
+ GNUNET_assert (gc ==
+ GNUNET_CONTAINER_heap_remove_root (to_heap));
+ }
+ if (NULL == gc)
+ return;
+ to_task = GNUNET_SCHEDULER_add_at (gc->timeout,
+ &do_timeout,
+ NULL);
+}
+
void
AH_truth_shutdown (void)
@@ -271,6 +326,16 @@ AH_truth_shutdown (void)
}
}
ANASTASIS_authorization_plugin_shutdown ();
+ if (NULL != to_task)
+ {
+ GNUNET_SCHEDULER_cancel (to_task);
+ to_task = NULL;
+ }
+ if (NULL != to_heap)
+ {
+ GNUNET_CONTAINER_heap_destroy (to_heap);
+ to_heap = NULL;
+ }
}
@@ -401,6 +466,12 @@ request_done (struct TM_HandlerContext *hc)
gc);
gc->in_list = false;
}
+ if (NULL != gc->hn)
+ {
+ GNUNET_assert (gc ==
+ GNUNET_CONTAINER_heap_remove_node (gc->hn));
+ gc->hn = NULL;
+ }
if (NULL != gc->as)
{
gc->authorization->cleanup (gc->as);
@@ -829,6 +900,7 @@ run_authorization_process (struct MHD_Connection *connection,
enum GNUNET_DB_QueryStatus qs;
ret = gc->authorization->process (gc->as,
+ gc->timeout,
connection);
switch (ret)
{
@@ -853,7 +925,27 @@ run_authorization_process (struct MHD_Connection *connection,
gc->as = NULL;
return MHD_YES;
case ANASTASIS_AUTHORIZATION_RES_SUSPENDED:
- /* connection was suspended again, odd that this happens */
+ /* connection was suspended */
+ if (NULL == to_heap)
+ to_heap = GNUNET_CONTAINER_heap_create (
+ GNUNET_CONTAINER_HEAP_ORDER_MIN);
+ gc->hn = GNUNET_CONTAINER_heap_insert (to_heap,
+ gc,
+ gc->timeout.abs_value_us);
+ gc->suspended = true;
+ if (NULL != to_task)
+ {
+ GNUNET_SCHEDULER_cancel (to_task);
+ to_task = NULL;
+ }
+ {
+ struct GetContext *rn;
+
+ rn = GNUNET_CONTAINER_heap_peek (to_heap);
+ to_task = GNUNET_SCHEDULER_add_at (rn->timeout,
+ &do_timeout,
+ NULL);
+ }
return MHD_YES;
case ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED:
/* Challenge sent successfully */
@@ -987,10 +1079,12 @@ AH_handler_truth_get (
if (NULL != long_poll_timeout_ms)
{
unsigned int timeout;
+ char dummy;
if (1 != sscanf (long_poll_timeout_ms,
- "%u",
- &timeout))
+ "%u%c",
+ &timeout,
+ &dummy))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,