gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant] branch master updated: prepare data structures and trig


From: gnunet
Subject: [taler-merchant] branch master updated: prepare data structures and trigger logic for long polling in check-payment processing
Date: Thu, 31 Oct 2019 20:17:27 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new 3e4fa16  prepare data structures and trigger logic for long polling in 
check-payment processing
3e4fa16 is described below

commit 3e4fa16134ff8a08a70c3041bb008a493760fad4
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Oct 31 20:17:23 2019 +0100

    prepare data structures and trigger logic for long polling in check-payment 
processing
---
 contrib/uncrustify.cfg                 |   2 +
 src/backend/taler-merchant-httpd.c     | 110 +++++++++++++++++++++++++++++++--
 src/backend/taler-merchant-httpd.h     |  49 +++++++++++++++
 src/backend/taler-merchant-httpd_pay.c |  60 +++++++++++++++++-
 4 files changed, 214 insertions(+), 7 deletions(-)

diff --git a/contrib/uncrustify.cfg b/contrib/uncrustify.cfg
index 8c9df2c..12dd62c 100644
--- a/contrib/uncrustify.cfg
+++ b/contrib/uncrustify.cfg
@@ -49,6 +49,8 @@ nl_assign_brace=remove
 
 # No extra newlines that cause noisy diffs
 nl_start_of_file=remove
+nl_before_func_body_proto = 2
+nl_before_func_body_def = 3
 nl_after_func_proto = 2
 nl_after_func_body = 3
 # If there's no new line, it's not a text file!
diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 42e15ea..db05c70 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -155,6 +155,18 @@ static char *serve_unixpath;
  */
 static mode_t unixpath_mode;
 
+/**
+ * MIN-Heap of suspended connections to resume when the timeout expires,
+ * ordered by timeout. Values are of type `struct MHD_Connection`
+ */
+struct GNUNET_CONTAINER_Heap *resume_timeout_heap;
+
+/**
+ * Hash map from H(order_id,merchant_pub) to `struct MHD_Connection`
+ * entries to resume when a payment is made for the given order.
+ */
+struct GNUNET_CONTAINER_MultiHashMap *payment_trigger_map;
+
 
 /**
  * Return #GNUNET_YES if given a valid correlation ID and
@@ -189,6 +201,8 @@ hashmap_free (void *cls,
   struct MerchantInstance *mi = value;
   struct WireMethod *wm;
 
+  (void) cls;
+  (void) key;
   while (NULL != (wm = (mi->wm_head)))
   {
     GNUNET_CONTAINER_DLL_remove (mi->wm_head,
@@ -208,6 +222,59 @@ hashmap_free (void *cls,
 }
 
 
+/**
+ * Callback that frees all the elements in the #payment_trigger_map.
+ * This function should actually never be called, as by the time we
+ * get to it, all payment triggers should have been cleaned up!
+ *
+ * @param cls closure, NULL
+ * @param key current key
+ * @param value a `struct TMH_SuspendedConnection`
+ * @return #GNUNET_OK
+ */
+static int
+payment_trigger_free (void *cls,
+                      const struct GNUNET_HashCode *key,
+                      void *value)
+{
+  struct TMH_SuspendedConnection *sc = value;
+
+  (void) cls;
+  (void) key;
+  (void) sc; /* cannot really 'clean up' */
+  GNUNET_break (0);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Compute @a key to use for @a order_id and @a mpub in our
+ * #payment_trigger_map.
+ *
+ * @param order_id an order ID
+ * @param mpub an instance public key
+ * @param key[out] set to the hash map key to use
+ */
+void
+TMH_compute_pay_key (const char *order_id,
+                     const struct TALER_MerchantPublicKeyP *mpub,
+                     struct GNUNET_HashCode *key)
+{
+  size_t olen = strlen (order_id);
+  char buf[sizeof (*mpub) + olen];
+
+  memcpy (buf,
+          mpub,
+          sizeof (*mpub));
+  memcpy (&buf[sizeof (*mpub)],
+          order_id,
+          olen);
+  GNUNET_CRYPTO_hash (buf,
+                      sizeof (buf),
+                      key);
+}
+
+
 /**
  * Shutdown task (magically invoked when the application is being
  * quit)
@@ -217,6 +284,8 @@ hashmap_free (void *cls,
 static void
 do_shutdown (void *cls)
 {
+  struct TMH_SuspendedConnection *sc;
+
   MH_force_pc_resume ();
   MH_force_trh_resume ();
   if (NULL != mhd_task)
@@ -224,6 +293,22 @@ do_shutdown (void *cls)
     GNUNET_SCHEDULER_cancel (mhd_task);
     mhd_task = NULL;
   }
+  /* resume all suspended connections, must be done before stopping #mhd */
+  if (NULL != resume_timeout_heap)
+  {
+    while (NULL != (sc = GNUNET_CONTAINER_heap_remove_root (
+                      resume_timeout_heap)))
+    {
+      sc->hn = NULL;
+      GNUNET_assert (GNUNET_YES ==
+                     GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
+                                                           &sc->key,
+                                                           sc));
+      MHD_resume_connection (sc->con);
+    }
+    GNUNET_CONTAINER_heap_destroy (resume_timeout_heap);
+    resume_timeout_heap = NULL;
+  }
   if (NULL != mhd)
   {
     MHD_stop_daemon (mhd);
@@ -236,12 +321,19 @@ do_shutdown (void *cls)
   }
   TMH_EXCHANGES_done ();
   TMH_AUDITORS_done ();
-
-  GNUNET_CONTAINER_multihashmap_iterate (by_id_map,
-                                         &hashmap_free,
-                                         NULL);
+  if (NULL != payment_trigger_map)
+  {
+    GNUNET_CONTAINER_multihashmap_iterate (payment_trigger_map,
+                                           &payment_trigger_free,
+                                           NULL);
+    GNUNET_CONTAINER_multihashmap_destroy (payment_trigger_map);
+    payment_trigger_map = NULL;
+  }
   if (NULL != by_id_map)
   {
+    GNUNET_CONTAINER_multihashmap_iterate (by_id_map,
+                                           &hashmap_free,
+                                           NULL);
     GNUNET_CONTAINER_multihashmap_destroy (by_id_map);
     by_id_map = NULL;
   }
@@ -291,6 +383,7 @@ handle_mhd_completion_callback (void *cls,
  * starts the task waiting for them.
  */
 static struct GNUNET_SCHEDULER_Task *
+
 prepare_daemon (void);
 
 
@@ -347,6 +440,8 @@ TMH_trigger_daemon ()
  * @param daemon_handle HTTP server to prepare to run
  */
 static struct GNUNET_SCHEDULER_Task *
+
+
 prepare_daemon ()
 {
   struct GNUNET_SCHEDULER_Task *ret;
@@ -938,6 +1033,8 @@ instances_iterator_cb (void *cls,
  * @return NULL if that instance is unknown to us
  */
 static struct MerchantInstance *
+
+
 lookup_instance (const char *instance_id)
 {
   struct GNUNET_HashCode h_instance;
@@ -1704,6 +1801,11 @@ run (void *cls,
       GNUNET_assert (0);
     }
   }
+  resume_timeout_heap
+    = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
+  payment_trigger_map
+    = GNUNET_CONTAINER_multihashmap_create (16,
+                                            GNUNET_YES);
   mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME | MHD_USE_DUAL_STACK,
                           port,
                           NULL, NULL,
diff --git a/src/backend/taler-merchant-httpd.h 
b/src/backend/taler-merchant-httpd.h
index 0deaf17..c166efb 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -266,6 +266,29 @@ struct TM_HandlerContext
 };
 
 
+/**
+ * Entry in a #resume_timeout_heap.
+ */
+struct TMH_SuspendedConnection
+{
+  /**
+   * Which connection was suspended.
+   */
+  struct MHD_Connection *con;
+
+  /**
+   * Key of this entry in the #payment_trigger_map
+   */
+  struct GNUNET_HashCode key;
+
+  /**
+   * Associated heap node.
+   */
+  struct GNUNET_CONTAINER_HeapNode *hn;
+
+};
+
+
 /**
  * Locations from the configuration.  Mapping from
  * label to location data.
@@ -290,6 +313,18 @@ extern struct TALER_Amount default_max_deposit_fee;
  */
 extern unsigned long long default_wire_fee_amortization;
 
+/**
+ * MIN-Heap of suspended connections to resume when the timeout expires,
+ * ordered by timeout. Values are of type `struct TMH_SuspendedConnection`
+ */
+extern struct GNUNET_CONTAINER_Heap *resume_timeout_heap;
+
+/**
+ * Hash map from H(order_id,merchant_pub) to `struct TMH_SuspendedConnection`
+ * entries to resume when a payment is made for the given order.
+ */
+extern struct GNUNET_CONTAINER_MultiHashMap *payment_trigger_map;
+
 /**
  * Which currency do we use?
  */
@@ -348,4 +383,18 @@ extern struct GNUNET_TIME_Relative default_pay_deadline;
 void
 TMH_trigger_daemon (void);
 
+/**
+ * Compute @a key to use for @a order_id and @a mpub in our
+ * #payment_trigger_map.
+ *
+ * @param order_id an order ID
+ * @param mpub an instance public key
+ * @param key[out] set to the hash map key to use
+ */
+void
+TMH_compute_pay_key (const char *order_id,
+                     const struct TALER_MerchantPublicKeyP *mpub,
+                     struct GNUNET_HashCode *key);
+
+
 #endif
diff --git a/src/backend/taler-merchant-httpd_pay.c 
b/src/backend/taler-merchant-httpd_pay.c
index 69b8e2d..4e19e6f 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -412,6 +412,57 @@ MH_force_pc_resume ()
 }
 
 
+/**
+ * Function called to resume suspended connections.
+ *
+ * @param cls NULL
+ * @param key key in the #payment_trigger_map
+ * @param value a `struct TMH_SuspendedConnection` to resume
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+resume_operation (void *cls,
+                  const struct GNUNET_HashCode *key,
+                  void *value)
+{
+  struct TMH_SuspendedConnection *sc = value;
+
+  (void) cls;
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
+                                                       key,
+                                                       sc));
+  GNUNET_assert (sc ==
+                 GNUNET_CONTAINER_heap_remove_node (sc->hn));
+  sc->hn = NULL;
+  MHD_resume_connection (sc->con);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Find out if we have any clients long-polling for @a order_id to be
+ * confirmed at merchant @a mpub, and if so, tell them to resume.
+ *
+ * @param order_id the order that was paid
+ * @param mpub the merchant's public key of the instance where the payment 
happened
+ */
+static void
+resume_suspended_payment_checks (const char *order_id,
+                                 const struct TALER_MerchantPublicKeyP *mpub)
+{
+  struct GNUNET_HashCode key;
+
+  TMH_compute_pay_key (order_id,
+                       mpub,
+                       &key);
+  GNUNET_CONTAINER_multihashmap_get_multiple (payment_trigger_map,
+                                              &key,
+                                              &resume_operation,
+                                              NULL);
+}
+
+
 /**
  * Resume the given pay context and send the given response.
  * Stores the response in the @a pc and signals MHD to resume
@@ -473,6 +524,8 @@ abort_deposit (struct PayContext *pc)
  * @return the mhd response
  */
 static struct MHD_Response *
+
+
 sign_success_response (struct PayContext *pc)
 {
   json_t *refunds;
@@ -609,6 +662,8 @@ pay_context_cleanup (struct TM_HandlerContext *hc)
  * @return taler error code, #TALER_EC_NONE if amount is sufficient
  */
 static enum TALER_ErrorCode
+
+
 check_payment_sufficient (struct PayContext *pc)
 {
   struct TALER_Amount acc_fee;
@@ -921,7 +976,6 @@ generate_error_response (struct PayContext *pc,
 static void
 find_next_exchange (struct PayContext *pc);
 
-
 /**
  * Begin of the DB transaction.  If required (from
  * soft/serialization errors), the transaction can be
@@ -2058,7 +2112,6 @@ begin_transaction (struct PayContext *pc)
     }
 
     /* Now commit! */
-
     if (0 <= qs)
       qs = db->commit (db->cls);
     else
@@ -2079,7 +2132,8 @@ begin_transaction (struct PayContext *pc)
       return;
     }
 
-
+    resume_suspended_payment_checks (pc->order_id,
+                                     &pc->mi->pubkey);
     resume_pay_with_response (pc,
                               MHD_HTTP_OK,
                               sign_success_response (pc));

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]