gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated: likely fix for #6581, still need


From: gnunet
Subject: [taler-merchant] branch master updated: likely fix for #6581, still needs testcase
Date: Wed, 09 Sep 2020 23:11:53 +0200

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 e12f64d  likely fix for #6581, still needs testcase
e12f64d is described below

commit e12f64d45b2f58b716497aab6fd6273b8f92b740
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Sep 9 23:11:51 2020 +0200

    likely fix for #6581, still needs testcase
---
 src/backend/taler-merchant-httpd.c                 | 136 +++++++++++++++++++++
 src/backend/taler-merchant-httpd.h                 |  29 ++++-
 src/backend/taler-merchant-httpd_get-orders-ID.c   |   2 +
 .../taler-merchant-httpd_post-orders-ID-paid.c     |  13 +-
 .../taler-merchant-httpd_post-orders-ID-pay.c      |  22 +++-
 .../taler-merchant-httpd_private-get-orders-ID.c   |   2 +
 6 files changed, 196 insertions(+), 8 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 22e11d7..a6a4592 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -290,6 +290,40 @@ compute_pay_key (const char *order_id,
 }
 
 
+/**
+ * Compute @a key to use for @a session_id and @a fulfillment_url in our
+ * #payment_trigger_map.
+ *
+ * @param session_id the session for which @a fulfillment_url matters
+ * @param fulfillment_url fullfillment URL of an order
+ * @param key[out] set to the hash map key to use
+ */
+static void
+compute_pay_key2 (const char *session_id,
+                  const char *fulfillment_url,
+                  struct GNUNET_HashCode *key)
+{
+  size_t slen = strlen (session_id) + 1;
+  size_t ulen = strlen (fulfillment_url) + 1;
+  char buf[slen + ulen];
+
+  memcpy (buf,
+          session_id,
+          slen);
+  memcpy (&buf[slen],
+          fulfillment_url,
+          ulen);
+  GNUNET_CRYPTO_hash (buf,
+                      sizeof (buf),
+                      key);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Pay key for %s/%s is %s\n",
+              session_id,
+              fulfillment_url,
+              GNUNET_h2s (key));
+}
+
+
 /**
  * Resume processing all suspended connections past timeout.
  *
@@ -318,6 +352,11 @@ do_resume (void *cls)
                    GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
                                                          &sc->key,
                                                          sc));
+    if (sc->has_key2)
+      GNUNET_assert (GNUNET_YES ==
+                     GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
+                                                           &sc->key2,
+                                                           sc));
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Resuming long polled job due to timeout\n");
     MHD_resume_connection (sc->con);
@@ -333,6 +372,8 @@ do_resume (void *cls)
  * Suspend connection from @a sc until payment has been received.
  *
  * @param order_id the order that we are waiting on
+ * @param session_id session ID of the requester
+ * @param fulfillment_url fulfillment URL of the contract
  * @param mi the merchant instance we are waiting on
  * @param sc connection to suspend
  * @param min_refund refund amount we are waiting on to be exceeded before 
resuming,
@@ -340,6 +381,8 @@ do_resume (void *cls)
  */
 void
 TMH_long_poll_suspend (const char *order_id,
+                       const char *session_id,
+                       const char *fulfillment_url,
                        const struct TMH_MerchantInstance *mi,
                        struct TMH_SuspendedConnection *sc,
                        const struct TALER_Amount *min_refund)
@@ -355,6 +398,22 @@ TMH_long_poll_suspend (const char *order_id,
                                                     &sc->key,
                                                     sc,
                                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
+  if ( (NULL != session_id) &&
+       (NULL != fulfillment_url) )
+  {
+    sc->has_key2 = true;
+    compute_pay_key (order_id,
+                     &mi->merchant_pub,
+                     &sc->key2);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Suspending operation on key2 %s\n",
+                GNUNET_h2s (&sc->key2));
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_CONTAINER_multihashmap_put (payment_trigger_map,
+                                                      &sc->key2,
+                                                      sc,
+                                                      
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
+  }
   if (NULL != min_refund)
   {
     sc->awaiting_refund = true;
@@ -392,6 +451,9 @@ resume_operation (void *cls,
   const struct ResumeData *rd = cls;
   struct TMH_SuspendedConnection *sc = value;
 
+  GNUNET_assert (0 ==
+                 GNUNET_memcmp (key,
+                                &sc->key));
   /* If the conditions are satisfied partially, turn them off for future
      calls. */
   if ( (sc->awaiting_refund_obtained) &&
@@ -427,6 +489,11 @@ resume_operation (void *cls,
                  GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
                                                        key,
                                                        sc));
+  if (sc->has_key2)
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
+                                                         &sc->key2,
+                                                         sc));
   GNUNET_assert (sc ==
                  GNUNET_CONTAINER_heap_remove_node (sc->hn));
   sc->hn = NULL;
@@ -475,6 +542,75 @@ TMH_long_poll_resume (const char *order_id,
 }
 
 
+/**
+ * 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_operation2 (void *cls,
+                   const struct GNUNET_HashCode *key,
+                   void *value)
+{
+  struct TMH_SuspendedConnection *sc = value;
+
+  GNUNET_assert (sc->has_key2);
+  GNUNET_assert (0 == GNUNET_memcmp (key,
+                                     &sc->key2));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Resuming operation suspended pending payment on key %s\n",
+              GNUNET_h2s (key));
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
+                                                       &sc->key,
+                                                       sc));
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map,
+                                                       &sc->key2,
+                                                       sc));
+  GNUNET_assert (sc ==
+                 GNUNET_CONTAINER_heap_remove_node (sc->hn));
+  sc->hn = NULL;
+  MHD_resume_connection (sc->con);
+  TMH_trigger_daemon ();
+  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 session_id the session for which @a fulfillment_url became paid
+ * @param fulfillment_url fullfillment URL of which an order was paid
+ */
+void
+TMH_long_poll_resume2 (const char *session_id,
+                       const char *fulfillment_url)
+{
+  struct GNUNET_HashCode key;
+  int ret;
+
+  compute_pay_key2 (session_id,
+                    fulfillment_url,
+                    &key);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Resuming operations suspended pending payment on key %s\n",
+              GNUNET_h2s (&key));
+  ret = GNUNET_CONTAINER_multihashmap_get_multiple (payment_trigger_map,
+                                                    &key,
+                                                    &resume_operation2,
+                                                    NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "%u operations remain suspended pending payment (%d)\n",
+              GNUNET_CONTAINER_multihashmap_size (payment_trigger_map),
+              ret);
+}
+
+
 /**
  * Shutdown task (magically invoked when the application is being
  * quit)
diff --git a/src/backend/taler-merchant-httpd.h 
b/src/backend/taler-merchant-httpd.h
index 0d78312..c631729 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -343,6 +343,13 @@ struct TMH_SuspendedConnection
    */
   struct GNUNET_HashCode key;
 
+  /**
+   * Optional session/fulfillment URI-based key
+   * of this entry in the #payment_trigger_map.  Used internally by
+   * TMH_long_poll_resume2().
+   */
+  struct GNUNET_HashCode key2;
+
   /**
    * At what time does this request expire? If set in the future, we
    * may wait this long for a payment to arrive before responding.
@@ -355,7 +362,7 @@ struct TMH_SuspendedConnection
   struct TALER_Amount refund_expected;
 
   /**
-   * #GNUNET_YES if we are waiting for a refund.
+   * true if we are waiting for a refund.
    */
   bool awaiting_refund;
 
@@ -364,6 +371,10 @@ struct TMH_SuspendedConnection
    */
   bool awaiting_refund_obtained;
 
+  /**
+   * True if @a key2 is set.
+   */
+  bool has_key2;
 };
 
 
@@ -411,6 +422,8 @@ TMH_trigger_daemon (void);
  * Suspend connection from @a sc until payment has been received.
  *
  * @param order_id the order that we are waiting on
+ * @param session_id session ID of the requester
+ * @param fulfillment_url fulfillment URL of the contract
  * @param mi the merchant instance we are waiting on
  * @param sc connection to suspend
  * @param min_refund refund amount we are waiting on to be exceeded before 
resuming,
@@ -418,6 +431,8 @@ TMH_trigger_daemon (void);
  */
 void
 TMH_long_poll_suspend (const char *order_id,
+                       const char *session_id,
+                       const char *fulfillment_url,
                        const struct TMH_MerchantInstance *mi,
                        struct TMH_SuspendedConnection *sc,
                        const struct TALER_Amount *min_refund);
@@ -439,6 +454,18 @@ TMH_long_poll_resume (const char *order_id,
                       bool obtained);
 
 
+/**
+ * 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 session_id the session for which @a fulfillment_url became paid
+ * @param fulfillment_url fullfillment URL of which an order was paid
+ */
+void
+TMH_long_poll_resume2 (const char *session_id,
+                       const char *fulfillment_url);
+
+
 /**
  * Decrement reference counter of @a mi, and free if it hits zero.
  *
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c 
b/src/backend/taler-merchant-httpd_get-orders-ID.c
index 82d74f4..e875a3b 100644
--- a/src/backend/taler-merchant-httpd_get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_get-orders-ID.c
@@ -192,6 +192,8 @@ suspend_god (struct GetOrderData *god)
               "Suspending GET /orders/%s\n",
               god->order_id);
   TMH_long_poll_suspend (god->order_id,
+                         god->session_id,
+                         god->fulfillment_url,
                          god->hc->instance,
                          &god->sc,
                          god->sc.awaiting_refund
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-paid.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-paid.c
index bcb9aa0..bd2c555 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-paid.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-paid.c
@@ -180,11 +180,16 @@ TMH_post_orders_ID_paid (const struct TMH_RequestHandler 
*rh,
                                          NULL);
     }
   }
+  if (NULL != session_id)
   {
-    // FIXME-#6581: extract fulfillment_url from contract_terms.
-    // IF present, *ALSO* resume long-polling clients for the
-    // same fulfillment URL + session_id!
-    // NOTE: also should do the same in the pay handler!
+    const char *fulfillment_url;
+
+    fulfillment_url
+      = json_string_value (json_object_get (contract_terms,
+                                            "fulfillment_url"));
+    if (NULL != fulfillment_url)
+      TMH_long_poll_resume2 (session_id,
+                             fulfillment_url);
   }
 
   json_decref (contract_terms);
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index 9c75e48..fd6cc7a 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -198,6 +198,11 @@ struct PayContext
    */
   char *order_id;
 
+  /**
+   * Fulfillment URL from the contract, or NULL if we don't have one.
+   */
+  char *fulfillment_url;
+
   /**
    * Serial number of this order in the database (set once we did the lookup).
    */
@@ -521,6 +526,7 @@ pay_context_cleanup (void *cls)
     pc->response = NULL;
   }
   GNUNET_free (pc->order_id);
+  GNUNET_free (pc->fulfillment_url);
   GNUNET_free (pc->session_id);
   GNUNET_CONTAINER_DLL_remove (pc_head,
                                pc_tail,
@@ -1443,6 +1449,10 @@ begin_transaction (struct PayContext *pc)
   }
 
   /* Notify clients that have been waiting for the payment to succeed */
+  if ( (NULL != pc->session_id) &&
+       (NULL != pc->fulfillment_url) )
+    TMH_long_poll_resume2 (pc->session_id,
+                           pc->fulfillment_url);
   TMH_long_poll_resume (pc->order_id,
                         hc->instance,
                         NULL,
@@ -1729,10 +1739,16 @@ parse_pay (struct MHD_Connection *connection,
         GNUNET_JSON_spec_end ()
       };
       enum GNUNET_GenericReturnValue res;
+      const char *fulfillment_url;
 
       res = TALER_MHD_parse_internal_json_data (connection,
                                                 contract_terms,
                                                 espec);
+      fulfillment_url
+        = json_string_value (json_object_get (contract_terms,
+                                              "fulfillment_url"));
+      if (NULL != fulfillment_url)
+        pc->fulfillment_url = GNUNET_strdup (fulfillment_url);
       json_decref (contract_terms);
       if (GNUNET_YES != res)
       {
@@ -1884,9 +1900,9 @@ TMH_post_orders_ID_pay (const struct TMH_RequestHandler 
*rh,
               "Suspending pay handling while working with the exchange\n");
   GNUNET_assert (NULL == pc->timeout_task);
   pc->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (get_pay_timeout (pc->coins_cnt),
-                                    &handle_pay_timeout,
-                                    pc);
+    GNUNET_SCHEDULER_add_delayed (get_pay_timeout (pc->coins_cnt),
+                                  &handle_pay_timeout,
+                                  pc);
   begin_transaction (pc);
   return MHD_YES;
 }
diff --git a/src/backend/taler-merchant-httpd_private-get-orders-ID.c 
b/src/backend/taler-merchant-httpd_private-get-orders-ID.c
index 5c43416..d341361 100644
--- a/src/backend/taler-merchant-httpd_private-get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-orders-ID.c
@@ -1035,6 +1035,8 @@ TMH_private_get_orders_ID (const struct 
TMH_RequestHandler *rh,
                 "Suspending GET /private/orders/%s\n",
                 hc->infix);
     TMH_long_poll_suspend (hc->infix,
+                           gorc->session_id,
+                           gorc->fulfillment_url,
                            hc->instance,
                            &gorc->sc,
                            NULL);

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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