gnunet-svn
[Top][All Lists]
Advanced

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

[taler-sync] branch master updated: breaking the build badly, big hackin


From: gnunet
Subject: [taler-sync] branch master updated: breaking the build badly, big hacking
Date: Sun, 17 Nov 2019 00:13:02 +0100

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

grothoff pushed a commit to branch master
in repository sync.

The following commit(s) were added to refs/heads/master by this push:
     new 8b1e276  breaking the build badly, big hacking
8b1e276 is described below

commit 8b1e276a316d29a752b26cdc070330e688aea221
Author: Christian Grothoff <address@hidden>
AuthorDate: Sun Nov 17 00:13:00 2019 +0100

    breaking the build badly, big hacking
---
 configure.ac                        |  25 ++++
 src/include/sync_database_plugin.h  |  80 ++++++++++++-
 src/include/sync_service.h          |  30 +++++
 src/sync/Makefile.am                |   2 +
 src/sync/sync-httpd.c               | 227 +++++++++++++++++++++++++++++++++++-
 src/sync/sync-httpd.h               |  21 +++-
 src/sync/sync-httpd_backup.c        | 144 ++++++++++++-----------
 src/sync/sync-httpd_backup.h        |  30 ++++-
 src/sync/sync-httpd_responses.h     |  14 ---
 src/sync/sync.conf                  |  11 +-
 src/syncdb/plugin_syncdb_postgres.c | 195 +++++++++++++++++++++++++++----
 11 files changed, 665 insertions(+), 114 deletions(-)

diff --git a/configure.ac b/configure.ac
index 37784fb..cf38528 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,28 @@ CFLAGS="-Wall $CFLAGS"
 # Checks for header files.
 AC_CHECK_HEADERS([stdint.h stdlib.h string.h unistd.h])
 
+
+# Check for Taler's libtalermerchant
+libtalermerchant=0
+AC_MSG_CHECKING([for libtalermerchant])
+AC_ARG_WITH(merchant,
+            [AS_HELP_STRING([--with-merchant=PFX], [base of Taler MERCHANT 
installation])],
+            [AC_MSG_RESULT([given as $with_merchant])],
+            [AC_MSG_RESULT(not given)
+             with_merchant=yes])
+AS_CASE([$with_merchant],
+        [yes], [],
+        [no], [AC_MSG_ERROR([--with-merchant is required])],
+        [LDFLAGS="-L$with_merchant/lib $LDFLAGS"
+         CPPFLAGS="-I$with_merchant/include $CPPFLAGS $POSTGRESQL_CPPFLAGS"])
+
+AC_CHECK_HEADERS([taler/taler_merchant_service.h],
+ [AC_CHECK_LIB([talermerchant], [TALER_MERCHANT_poll_payment], 
libtalermerchant=1)],
+   [], [#ifdef HAVE_TALER_PLATFORM_H
+        #include <taler/platform.h>
+       #endif])
+
+
 # Check for GNUnet's libgnunetutil.
 libgnunetutil=0
 AC_MSG_CHECKING([for libgnunetutil])
@@ -102,6 +124,9 @@ AC_CHECK_HEADERS([gnunet/gnunet_pq_lib.h],
        #endif])
 AM_CONDITIONAL(HAVE_GNUNETPQ, test x$libgnunetpq = x1)
 
+
+
+
 # check for libmicrohttpd
 microhttpd=0
 AC_MSG_CHECKING([for microhttpd])
diff --git a/src/include/sync_database_plugin.h 
b/src/include/sync_database_plugin.h
index d5759ee..ac88828 100644
--- a/src/include/sync_database_plugin.h
+++ b/src/include/sync_database_plugin.h
@@ -64,6 +64,24 @@ enum SYNC_DB_QueryStatus
 };
 
 
+/**
+ * Function called on all pending payments.
+ *
+ * @param cls closure
+ * @param account_pub which account is the order for
+ * @param timestamp for how long have we been waiting
+ * @param order_id order id in the backend
+ * @param amount how much is the order for
+ */
+typedef void
+(*SYNC_DB_PaymentPendingIterator)(void *cls,
+                                  const struct
+                                  SYNC_AccountPublicKeyP *account_pub,
+                                  struct GNUNET_TIME_Absolute timestamp,
+                                  const char *order_id,
+                                  const struct TALER_Amount *amount);
+
+
 /**
  * Handle to interact with the database.
  *
@@ -104,12 +122,16 @@ struct SYNC_DatabasePlugin
    * truth and financial records older than @a fin_expire.
    *
    * @param cls closure
-   * @param expire backups older than the given time stamp should be garbage 
collected
+   * @param expire_backups backups older than the given time stamp should be 
garbage collected
+   * @param expire_pending_payments payments still pending from since before
+   *            this value should be garbage collected
    * @return transaction status
    */
   enum SYNC_DB_QueryStatus
   (*gc)(void *cls,
-        struct GNUNET_TIME_Absolute expire);
+        struct GNUNET_TIME_Absolute expire,
+        struct GNUNET_TIME_Absolute expire_pending_payments);
+
 
   /**
    * Store backup. Only applicable for the FIRST backup under
@@ -132,6 +154,55 @@ struct SYNC_DatabasePlugin
                      size_t backup_size,
                      const void *backup);
 
+
+  /**
+   * Store payment. Used to begin a payment, not indicative
+   * that the payment actually was made. (That is done
+   * when we increment the account's lifetime.)
+   *
+   * @param cls closure
+   * @param account_pub account to store @a backup under
+   * @param order_id order we created
+   * @param amount how much we asked for
+   * @return transaction status
+   */
+  enum SYNC_DB_QueryStatus
+  (*store_payment_TR)(void *cls,
+                      const struct SYNC_AccountPublicKeyP *account_pub,
+                      const char *order_id,
+                      const struct TALER_Amount *amount);
+
+
+  /**
+   * Lookup pending payments.
+   *
+   * @param cls closure
+   * @param it iterator to call on all pending payments
+   * @param it_cls closure for @a it
+   * @return transaction status
+   */
+  enum SYNC_DB_QueryStatus
+  (*lookup_pending_payments_TR)(void *cls,
+                                SYNC_DB_PaymentPendingIterator it,
+                                void *it_cls);
+
+
+  /**
+   * Lookup pending payments by account.
+   *
+   * @param cls closure
+   * @param account_pub account to look for pending payments under
+   * @param it iterator to call on all pending payments
+   * @param it_cls closure for @a it
+   * @return transaction status
+   */
+  enum SYNC_DB_QueryStatus
+  (*lookup_pending_payments_by_account_TR)(void *cls,
+                                           const struct
+                                           SYNC_AccountPublicKeyP *account_pub,
+                                           SYNC_DB_PaymentPendingIterator it,
+                                           void *it_cls);
+
   /**
    * Update backup.
    *
@@ -189,16 +260,19 @@ struct SYNC_DatabasePlugin
                       void **backup);
 
   /**
-   * Increment account lifetime.
+   * Increment account lifetime and mark the associated payment
+   * as successful.
    *
    * @param cls closure
    * @param account_pub which account received a payment
+   * @param order_id order which was paid, must be unique and match pending 
payment
    * @param lifetime for how long is the account now paid (increment)
    * @return transaction status
    */
   enum SYNC_DB_QueryStatus
   (*increment_lifetime_TR)(void *cls,
                            const struct SYNC_AccountPublicKeyP *account_pub,
+                           const char *order_id,
                            struct GNUNET_TIME_Relative lifetime);
 
 };
diff --git a/src/include/sync_service.h b/src/include/sync_service.h
index 20bbe67..595df3c 100644
--- a/src/include/sync_service.h
+++ b/src/include/sync_service.h
@@ -50,6 +50,36 @@ struct SYNC_AccountPublicKeyP
 };
 
 
+GNUNET_NETWORK_STRUCT_BEGIN
+
+
+/**
+ * Data signed by the account public key of a sync client to
+ * authorize the upload of the backup.
+ */
+struct SYNC_UploadSignaturePS
+{
+  /**
+   * Set to #TALER_SIGNATURE_SYNC_BACKUP_UPLOAD.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Hash of the previous backup, all zeros for none.
+   */
+  struct GNUNET_HashCode old_backup_hash GNUNET_PACKED;
+
+  /**
+   * Hash of the new backup.
+   */
+  struct GNUNET_HashCode new_backup_hash GNUNET_PACKED;
+
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+
 /**
  * Signature made with an account's public key.
  */
diff --git a/src/sync/Makefile.am b/src/sync/Makefile.am
index 0bb6703..40c8aba 100644
--- a/src/sync/Makefile.am
+++ b/src/sync/Makefile.am
@@ -12,6 +12,7 @@ bin_PROGRAMS = \
 sync_httpd_SOURCES = \
   sync-httpd.c sync-httpd.h \
   sync-httpd_backup.c sync-httpd_backup.h \
+  sync-httpd_backup_post.c \
   sync-httpd_mhd.c sync-httpd_mhd.h \
   sync-httpd_parsing.c sync-httpd_parsing.h \
   sync-httpd_responses.c sync-httpd_responses.h \
@@ -20,6 +21,7 @@ sync_httpd_LDADD = \
   $(top_builddir)/src/syncdb/libsyncdb.la \
   -lmicrohttpd \
   -ljansson \
+  -ltalermerchant \
   -ltalerjson \
   -ltalerutil \
   -lgnunetcurl \
diff --git a/src/sync/sync-httpd.c b/src/sync/sync-httpd.c
index 98a2b24..a0bd692 100644
--- a/src/sync/sync-httpd.c
+++ b/src/sync/sync-httpd.c
@@ -34,6 +34,58 @@
  */
 #define UNIX_BACKLOG 500
 
+/**
+ * How long do we hold an BACKEND connection if
+ * we are awaiting payment before giving up (only
+ * used when resuming).
+ */
+#define CHECK_BACKEND_PAYMENT_TIMEOUT GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_SECONDS, 15)
+
+
+/**
+ * Context we use to check for payments outside of HTTP requests.
+ */
+struct PaymentContext
+{
+  /**
+   * The asyncronous operation.
+   */
+  struct TALER_MERCHANT_CheckPaymentOperation *cpo;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct PaymentContext *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct PaymentContext *prev;
+
+  /**
+   * Order ID of the payment.
+   */
+  char *order_id;
+
+  /**
+   * Account the payment is about.
+   */
+  struct SYNC_AccountPublicKeyP account_pub;
+};
+
+
+/**
+ * Head of active payments.
+ */
+static struct PaymentContext *pc_head;
+
+/**
+ * Tail of active payments.
+ */
+static struct PaymentContext *pc_tail;
+
+
 /**
  * The port we are running on
  */
@@ -54,6 +106,26 @@ unsigned long long int SH_upload_limit_mb;
  */
 struct TALER_Amount SH_annual_fee;
 
+/**
+ * Our Taler backend to process payments.
+ */
+char *MH_backend_url;
+
+/**
+ * Our own base URL
+ */
+char *MH_my_base_url;
+
+/**
+ * Our context for making HTTP requests.
+ */
+struct GNUNET_CURL_Context *MH_ctx;
+
+/**
+ * Reschedule context for #MH_ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
 /**
  * Task running the HTTP server.
  */
@@ -223,8 +295,7 @@ url_handler (void *cls,
                          MHD_HTTP_METHOD_GET))
     {
       return sync_handler_backup_get (connection,
-                                      &account_pub,
-                                      con_cls);
+                                      &account_pub);
     }
     if (0 == strcasecmp (method,
                          MHD_HTTP_METHOD_POST))
@@ -281,6 +352,29 @@ url_handler (void *cls,
 static void
 do_shutdown (void *cls)
 {
+  struct PaymentContext *pc;
+
+  (void) cls;
+  while (NULL != (pc = pc_head))
+  {
+    TALER_MERCHANT_check_payment_cancel (pc->cpo);
+    GNUNET_CONTAINER_DLL_remove (pc_head,
+                                 pc_tail,
+                                 pc);
+    GNUNET_free (pc->order_id);
+    GNUNET_free (pc);
+  }
+  if (NULL != SH_ctx)
+  {
+    GNUNET_CURL_fini (SH_ctx);
+    SH_ctx = NULL;
+  }
+  if (NULL != rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (rc);
+    rc = NULL;
+  }
+  SH_resume_all_bc ();
   if (NULL != mhd_task)
   {
     GNUNET_SCHEDULER_cancel (mhd_task);
@@ -321,6 +415,8 @@ handle_mhd_completion_callback (void *cls,
 {
   struct TM_HandlerContext *hc = *con_cls;
 
+  (void) cls;
+  (void) connection;
   if (NULL == hc)
     return;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -355,6 +451,7 @@ static int triggered;
 static void
 run_daemon (void *cls)
 {
+  (void) cls;
   mhd_task = NULL;
   do {
     triggered = 0;
@@ -386,6 +483,89 @@ SH_trigger_daemon ()
 }
 
 
+/**
+ * Callback to process a GET /check-payment request
+ *
+ * @param cls our `struct PaymentContext`
+ * @param http_status HTTP status code for this request
+ * @param obj raw response body
+ * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not
+ *        settled, $GNUNET_SYSERR on error
+ *        (note that refunded payments are returned as paid!)
+ * @param refunded #GNUNET_YES if there is at least on refund on this payment,
+ *        #GNUNET_NO if refunded, #GNUNET_SYSERR or error
+ * @param refunded_amount amount that was refunded, NULL if there
+ *        was no refund
+ * @param taler_pay_uri the URI that instructs the wallets to process
+ *                      the payment
+ */
+static void
+check_payment_cb (void *cls,
+                  unsigned int http_status,
+                  const json_t *obj,
+                  int paid,
+                  int refunded,
+                  struct TALER_Amount *refund_amount,
+                  const char *taler_pay_uri)
+{
+  struct PaymentContext *pc = cls;
+
+  /* refunds are not supported, verify */
+  pc->cpo = NULL;
+  if (paid)
+  {
+    enum SYNC_DB_QueryStatus qs;
+
+    qs = db->increment_lifetime_TR (db->cls,
+                                    &pc->account,
+                                    pc->order_id,
+                                    GNUNET_TIME_UNIT_YEARS); /* always annual 
*/
+    GNUNET_break (0 > qs);
+  }
+  GNUNET_CONTAINER_DLL_remove (pc_head,
+                               pc_tail,
+                               pc);
+  GNUNET_free (pc->order_id);
+  GNUNET_free (pc);
+}
+
+
+/**
+ * Function called on all pending payments.  Talks to our
+ * backend to see if any of them are done yet.
+ *
+ * @param cls closure
+ * @param account_pub which account is the order for
+ * @param timestamp for how long have we been waiting
+ * @param order_id order id in the backend
+ * @param amount how much is the order for
+ */
+static void
+check_on_payments_cb (void *cls,
+                      const struct SYNC_AccountPublicKeyP *account_pub,
+                      struct GNUNET_TIME_Absolute timestamp,
+                      const char *order_id,
+                      const struct TALER_Amount *amount)
+{
+  struct PaymentContext *pc;
+
+  (void) amount;
+  pc = GNUNET_new (struct PaymentContext);
+  pc->account_pub = *account_pub;
+  pc->order_id = GNUNET_strdup (order_id);
+  GNUNET_CONTAINER_DLL_insert (pc_head,
+                               pc_tail,
+                               pc);
+  pc->cpo = TALER_MERCHANT_check_payment (MH_ctx,
+                                          MH_backend_url,
+                                          order_id,
+                                          NULL /* our payments are NOT 
session-bound */,
+                                          CHECK_BACKEND_PAYMENT_TIMEOUT,
+                                          &check_payment_cb,
+                                          pc);
+}
+
+
 /**
  * Function that queries MHD's select sets and
  * starts the task waiting for them.
@@ -489,6 +669,36 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (config,
+                                             "sync",
+                                             "PAYMENT_BACKEND_URL",
+                                             &MH_backend_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "sync",
+                               "PAYMENT_BACKEND_URL");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (config,
+                                             "sync",
+                                             "BASE_URL",
+                                             &MH_my_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "sync",
+                               "BASE_URL");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  /* setup HTTP client event loop */
+  MH_ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                             &rc);
+  rc = GNUNET_CURL_gnunet_rc_create (MH_ctx);
+
 
   if (NULL ==
       (db = SYNC_DB_plugin_load (config)))
@@ -497,6 +707,19 @@ run (void *cls,
     return;
   }
 
+  /* TODO: maybe make this conditional on a command-line option?
+     Might be expensive, and is strictly speaking not required. */
+  {
+    /* we might have been down for a while, catch up on
+       all payments that happened in the meantime */
+    enum SYNC_DB_QueryStatus qs;
+
+    db->lookup_pending_payments_TR (db->cls,
+                                    &check_on_payments_cb,
+                                    NULL);
+    GNUNET_break (qs >= 0);
+  }
+
   {
     const char *choices[] = {"tcp",
                              "unix",
diff --git a/src/sync/sync-httpd.h b/src/sync/sync-httpd.h
index c2e76a3..c000075 100644
--- a/src/sync/sync-httpd.h
+++ b/src/sync/sync-httpd.h
@@ -114,11 +114,6 @@ struct TM_HandlerContext
    */
   TM_ContextCleanup cc;
 
-  /**
-   * Which request handler is handling this request?
-   */
-  const struct SH_RequestHandler *rh;
-
   /**
    * Asynchronous request context id.
    */
@@ -146,6 +141,21 @@ extern unsigned long long SH_upload_limit_mb;
  */
 extern struct TALER_Amount SH_annual_fee;
 
+/**
+ * Our Taler backend to process payments.
+ */
+extern char *MH_backend_url;
+
+/**
+ * Our own base URL
+ */
+extern char *MH_my_base_url;
+
+/**
+ * Our context for making HTTP requests.
+ */
+extern struct GNUNET_CURL_Context *MH_ctx;
+
 /**
  * Kick MHD to run now, to be called after MHD_resume_connection().
  * Basically, we need to explicitly resume MHD's event loop whenever
@@ -155,4 +165,5 @@ extern struct TALER_Amount SH_annual_fee;
 void
 SH_trigger_daemon (void);
 
+
 #endif
diff --git a/src/sync/sync-httpd_backup.c b/src/sync/sync-httpd_backup.c
index 61d9151..65506da 100644
--- a/src/sync/sync-httpd_backup.c
+++ b/src/sync/sync-httpd_backup.c
@@ -25,30 +25,21 @@
 #include "sync-httpd_responses.h"
 
 /**
+ * Handle request on @a connection for retrieval of the latest
+ * backup of @a account.
+ *
  * @param connection the MHD connection to handle
  * @param account public key of the account the request is for
- * @param[in,out] con_cls the connection's closure (can be updated)
  * @return MHD result code
  */
 int
 sync_handler_backup_get (struct MHD_Connection *connection,
-                         const struct SYNC_AccountPublicKeyP *account,
-                         void **con_cls)
+                         const struct SYNC_AccountPublicKeyP *account)
 {
-  struct SYNC_AccountSignatureP account_sig;
   struct GNUNET_HashCode backup_hash;
-  struct GNUNET_HashCode prev_hash;
-  size_t backup_size;
-  void *backup;
   enum SYNC_DB_QueryStatus qs;
-  struct MHD_Response *resp;
-  const char *inm;
-  struct GNUNET_HashCode inm_h;
   int ret;
 
-  inm = MHD_lookup_connection_value (connection,
-                                     MHD_HEADER_KIND,
-                                     MHD_HTTP_HEADER_IF_NONE_MATCH);
   qs = db->lookup_account_TR (db->cls,
                               account,
                               &backup_hash);
@@ -74,44 +65,86 @@ sync_handler_backup_get (struct MHD_Connection *connection,
                                              TALER_EC_SYNC_DB_FETCH_ERROR,
                                              "soft database failure");
   case SYNC_DB_NO_RESULTS:
-    resp = MHD_create_response_from_buffer (0,
-                                            NULL,
-                                            MHD_RESPMEM_PERSISTENT);
-    ret = MHD_queue_response (connection,
-                              MHD_HTTP_NO_CONTENT,
-                              resp);
-    MHD_destroy_response (resp);
+    {
+      struct MHD_Response *resp;
+
+      resp = MHD_create_response_from_buffer (0,
+                                              NULL,
+                                              MHD_RESPMEM_PERSISTENT);
+      ret = MHD_queue_response (connection,
+                                MHD_HTTP_NO_CONTENT,
+                                resp);
+      MHD_destroy_response (resp);
+    }
     return ret;
   case SYNC_DB_ONE_RESULT:
-    if (NULL != inm)
     {
-      if (GNUNET_OK !=
-          GNUNET_STRINGS_string_to_data (inm,
-                                         strlen (inm),
-                                         &inm_h,
-                                         sizeof (inm_h)))
-      {
-        GNUNET_break_op (0);
-        return SH_RESPONSE_reply_bad_request (connection,
-                                              TALER_EC_SYNC_BAD_ETAG,
-                                              "Etag is not a base32-encoded 
SHA-512 hash");
-      }
-      if (0 == GNUNET_memcmp (&inm_h,
-                              &backup_hash))
+      const char *inm;
+
+      inm = MHD_lookup_connection_value (connection,
+                                         MHD_HEADER_KIND,
+                                         MHD_HTTP_HEADER_IF_NONE_MATCH);
+      if (NULL != inm)
       {
-        resp = MHD_create_response_from_buffer (0,
-                                                NULL,
-                                                MHD_RESPMEM_PERSISTENT);
-        ret = MHD_queue_response (connection,
-                                  MHD_HTTP_NOT_MODIFIED,
-                                  resp);
-        MHD_destroy_response (resp);
-        return ret;
+        struct GNUNET_HashCode inm_h;
+
+        if (GNUNET_OK !=
+            GNUNET_STRINGS_string_to_data (inm,
+                                           strlen (inm),
+                                           &inm_h,
+                                           sizeof (inm_h)))
+        {
+          GNUNET_break_op (0);
+          return SH_RESPONSE_reply_bad_request (connection,
+                                                TALER_EC_SYNC_IF_NONE_MATCH,
+                                                "Etag does not include a 
base32-encoded SHA-512 hash");
+        }
+        if (0 == GNUNET_memcmp (&inm_h,
+                                &backup_hash))
+        {
+          resp = MHD_create_response_from_buffer (0,
+                                                  NULL,
+                                                  MHD_RESPMEM_PERSISTENT);
+          ret = MHD_queue_response (connection,
+                                    MHD_HTTP_NOT_MODIFIED,
+                                    resp);
+          MHD_destroy_response (resp);
+          return ret;
+        }
       }
     }
     /* We have a result, should fetch and return it! */
     break;
   }
+  return SH_return_backup (connection,
+                           account,
+                           MHD_HTTP_OK);
+}
+
+
+/**
+ * Return the current backup of @a account on @a connection
+ * using @a default_http_status on success.
+ *
+ * @param connection MHD connection to use
+ * @param account account to query
+ * @param default_http_status HTTP status to queue response
+ *  with on success (#MHD_HTTP_OK or #MHD_HTTP_CONFLICT)
+ * @return MHD result code
+ */
+int
+SH_return_backup (struct MHD_Connection *connection,
+                  const struct SYNC_AccountPublicKeyP *account,
+                  unsigned int default_http_status)
+{
+  enum SYNC_DB_QueryStatus qs;
+  struct MHD_Response *resp;
+  int ret;
+  struct SYNC_AccountSignatureP account_sig;
+  struct GNUNET_HashCode backup_hash;
+  struct GNUNET_HashCode prev_hash;
+  size_t backup_size;
+  void *backup;
 
   qs = db->lookup_backup_TR (db->cls,
                              account,
@@ -171,11 +204,11 @@ sync_handler_backup_get (struct MHD_Connection 
*connection,
                                                 sizeof (backup_hash));
     GNUNET_break (MHD_YES ==
                   MHD_add_response_header (resp,
-                                           "X-Sync-Signature",
+                                           "Sync-Signature",
                                            sig_s));
     GNUNET_break (MHD_YES ==
                   MHD_add_response_header (resp,
-                                           "X-Sync-Previous",
+                                           "Sync-Previous",
                                            prev_s));
     GNUNET_break (MHD_YES ==
                   MHD_add_response_header (resp,
@@ -186,29 +219,8 @@ sync_handler_backup_get (struct MHD_Connection *connection,
     GNUNET_free (sig_s);
   }
   ret = MHD_queue_response (connection,
-                            MHD_HTTP_NOT_MODIFIED,
+                            default_http_status,
                             resp);
   MHD_destroy_response (resp);
   return ret;
 }
-
-
-/**
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param account public key of the account the request is for
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-sync_handler_backup_post (struct MHD_Connection *connection,
-                          void **con_cls,
-                          const struct SYNC_AccountPublicKeyP *account,
-                          const char *upload_data,
-                          size_t *upload_data_size)
-{
-  struct SYNC_AccountSignatureP account_sig;
-
-  return MHD_NO;
-}
diff --git a/src/sync/sync-httpd_backup.h b/src/sync/sync-httpd_backup.h
index 02f31be..6326266 100644
--- a/src/sync/sync-httpd_backup.h
+++ b/src/sync/sync-httpd_backup.h
@@ -23,15 +23,39 @@
 #include <microhttpd.h>
 
 /**
+ * Service is shutting down, resume all MHD connections NOW.
+ */
+void
+SH_resume_all_bc (void);
+
+
+/**
+ * Return the current backup of @a account on @a connection
+ * using @a default_http_status on success.
+ *
+ * @param connection MHD connection to use
+ * @param account account to query
+ * @param default_http_status HTTP status to queue response
+ *  with on success (#MHD_HTTP_OK or #MHD_HTTP_CONFLICT)
+ * @return MHD result code
+ */
+int
+SH_return_backup (struct MHD_Connection *connection,
+                  const struct SYNC_AccountPublicKeyP *account,
+                  unsigned int default_http_status);
+
+
+/**
+ * Handle request on @a connection for retrieval of the latest
+ * backup of @a account.
+ *
  * @param connection the MHD connection to handle
  * @param account public key of the account the request is for
- * @param[in,out] con_cls the connection's closure (can be updated)
  * @return MHD result code
  */
 int
 sync_handler_backup_get (struct MHD_Connection *connection,
-                         const struct SYNC_AccountPublicKeyP *account,
-                         void **con_cls);
+                         const struct SYNC_AccountPublicKeyP *account);
 
 
 /**
diff --git a/src/sync/sync-httpd_responses.h b/src/sync/sync-httpd_responses.h
index c072590..4ff4002 100644
--- a/src/sync/sync-httpd_responses.h
+++ b/src/sync/sync-httpd_responses.h
@@ -30,7 +30,6 @@
 #include <gnunet/gnunet_util_lib.h>
 
 
-
 /**
  * Make JSON response object.
  *
@@ -67,8 +66,6 @@ SH_RESPONSE_make_json_pack (const char *fmt,
                             ...);
 
 
-
-
 /**
  * Function to call to handle the request by building a JSON
  * reply from a format string and varargs.
@@ -112,8 +109,6 @@ SH_RESPONSE_reply_internal_error (struct MHD_Connection 
*connection,
                                   const char *hint);
 
 
-
-
 /**
  * Send a response indicating that the request was too big.
  *
@@ -124,7 +119,6 @@ int
 SH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection);
 
 
-
 /**
  * Send a response indicating that we did not find the @a object
  * needed for the reply.
@@ -142,7 +136,6 @@ SH_RESPONSE_reply_rc (struct MHD_Connection *connection,
                       const char *msg);
 
 
-
 /**
  * Send a response indicating that the JSON was malformed.
  *
@@ -153,7 +146,6 @@ int
 SH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection);
 
 
-
 /**
  * Send a response indicating that we did not find the @a object
  * needed for the reply.
@@ -169,7 +161,6 @@ SH_RESPONSE_reply_not_found (struct MHD_Connection 
*connection,
                              const char *object);
 
 
-
 /**
  * Send a response indicating that the request was malformed.
  *
@@ -184,8 +175,6 @@ SH_RESPONSE_reply_bad_request (struct MHD_Connection 
*connection,
                                const char *issue);
 
 
-
-
 /**
  * Add headers we want to return in every response.
  * Useful for testing, like if we want to always close
@@ -197,7 +186,6 @@ void
 SH_RESPONSE_add_global_headers (struct MHD_Response *response);
 
 
-
 /**
  * Send a response indicating an external error.
  *
@@ -212,8 +200,6 @@ SH_RESPONSE_reply_external_error (struct MHD_Connection 
*connection,
                                   const char *hint);
 
 
-
-
 /**
  * Send a response indicating a missing argument.
  *
diff --git a/src/sync/sync.conf b/src/sync/sync.conf
index 601241e..459c5c6 100644
--- a/src/sync/sync.conf
+++ b/src/sync/sync.conf
@@ -10,7 +10,7 @@
 SERVE = tcp
 
 # Which HTTP port does the backend listen on?  Only used if "SERVE" is 'tcp'.
-PORT = 9966
+PORT = 9967
 
 # Which IP address should we bind to? i.e. 127.0.0.1 or ::1 for loopback.
 # Can also be given as a hostname.  We will bind to the wildcard (dual-stack)
@@ -31,6 +31,15 @@ ANNUAL_FEE = TESTKUDOS:0.1
 # Upload limit per backup, in megabytes
 UPLOAD_LIMIT_MB = 16
 
+# Public base URL of the SYNC service itself. Used for the
+# fulfillment URL.
+BASE_URL = https://localhost:9967/
+
+# Base URL of our payment backend
+PAYMENT_BACKEND_URL = http://localhost:9966/
+
+
+
 # Configuration for postgres database.
 [syncdb-postgres]
 CONFIG = postgres:///sync
diff --git a/src/syncdb/plugin_syncdb_postgres.c 
b/src/syncdb/plugin_syncdb_postgres.c
index aba58d8..68d5461 100644
--- a/src/syncdb/plugin_syncdb_postgres.c
+++ b/src/syncdb/plugin_syncdb_postgres.c
@@ -63,6 +63,7 @@ postgres_drop_tables (void *cls)
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_ExecuteStatement es[] = {
     GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS accounts CASCADE;"),
+    GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS payments;"),
     GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS backups;"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
   };
@@ -212,25 +213,95 @@ commit_transaction (void *cls)
  * truth and financial records older than @a fin_expire.
  *
  * @param cls closure
- * @param expire backups older than the given time stamp should be garbage 
collected
+ * @param expire_backups backups older than the given time stamp should be 
garbage collected
+ * @param expire_pending_payments payments still pending from since before
+ *            this value should be garbage collected
  * @return transaction status
  */
 static enum SYNC_DB_QueryStatus
 postgres_gc (void *cls,
-             struct GNUNET_TIME_Absolute expire)
+             struct GNUNET_TIME_Absolute expire_backups,
+             struct GNUNET_TIME_Absolute expire_pending_payments)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_absolute_time (&expire),
+    TALER_PQ_query_param_absolute_time (&expire_backups),
     GNUNET_PQ_query_param_end
   };
+  struct GNUNET_PQ_QueryParam params2[] = {
+    TALER_PQ_query_param_absolute_time (&expire_pending_payments),
+    GNUNET_PQ_query_param_end
+  };
+  enum SYNC_DB_QueryStatus qs;
 
   check_connection (pg);
   postgres_preflight (pg);
-  return (enum SYNC_DB_QueryStatus)
-         GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "gc",
-                                             params);
+  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                           "gc_accounts",
+                                           params);
+  if (qs < 0)
+    return qs;
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "gc_pending_payments",
+                                             params2);
+}
+
+
+/**
+ * Store payment. Used to begin a payment, not indicative
+ * that the payment actually was made. (That is done
+ * when we increment the account's lifetime.)
+ *
+ * @param cls closure
+ * @param account_pub account to store @a backup under
+ * @param order_id order we created
+ * @param amount how much we asked for
+ * @return transaction status
+ */
+static enum SYNC_DB_QueryStatus
+postgres_store_payment (void *cls,
+                        const struct SYNC_AccountPublicKeyP *account_pub,
+                        const char *order_id,
+                        const struct TALER_Amount *amount)
+{
+  // FIXME: use payment_insert
+}
+
+
+/**
+ * Lookup pending payments.
+ *
+ * @param cls closure
+ * @param it iterator to call on all pending payments
+ * @param it_cls closure for @a it
+ * @return transaction status
+ */
+static enum SYNC_DB_QueryStatus
+postgres_lookup_pending_payments (void *cls,
+                                  SYNC_DB_PaymentPendingIterator it,
+                                  void *it_cls)
+{
+  // FIXME: use payments_select
+}
+
+
+/**
+ * Lookup pending payments by account.
+ *
+ * @param cls closure
+ * @param account_pub account to look for pending payments under
+ * @param it iterator to call on all pending payments
+ * @param it_cls closure for @a it
+ * @return transaction status
+ */
+static enum SYNC_DB_QueryStatus
+postgres_lookup_pending_payments_by_account (void *cls,
+                                             const struct
+                                             SYNC_AccountPublicKeyP 
*account_pub,
+                                             SYNC_DB_PaymentPendingIterator it,
+                                             void *it_cls)
+{
+  // FIXME: use payments_select_by_account
 }
 
 
@@ -674,12 +745,14 @@ postgres_lookup_backup (void *cls,
  *
  * @param cls closure
  * @param account_pub which account received a payment
+ * @param order_id order which was paid, must be unique and match pending 
payment
  * @param lifetime for how long is the account now paid (increment)
  * @return transaction status
  */
 static enum SYNC_DB_QueryStatus
 postgres_increment_lifetime (void *cls,
                              const struct SYNC_AccountPublicKeyP *account_pub,
+                             const char *order_id,
                              struct GNUNET_TIME_Relative lifetime)
 {
   struct PostgresClosure *pg = cls;
@@ -694,6 +767,25 @@ postgres_increment_lifetime (void *cls,
     GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
+
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_string (order_id),
+      GNUNET_PQ_query_param_auto_from_type (account_pub),
+      GNUNET_PQ_query_param_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "payment_done",
+                                             params);
+    if (0 >= qs)
+    {
+      /* payment made before, or unknown, or error => no further action! */
+      rollback (pg);
+      return qs;
+    }
+  }
+
   {
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (account_pub),
@@ -807,33 +899,62 @@ libsync_plugin_db_postgres_init (void *cls)
        The contract terms will change (nonce will be added) when moved to the
        contract terms table */
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS accounts"
-                            "("
-                            "account_pub BYTEA PRIMARY KEY CHECK 
(length(account_pub)=32),"
-                            "expiration_date INT8 NOT NULL"
+                            "(account_pub BYTEA PRIMARY KEY CHECK 
(length(account_pub)=32)"
+                            ",expiration_date INT8 NOT NULL"
+                            ");"),
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS payments"
+                            "(account_pub BYTEA CHECK 
(length(account_pub)=32),"
+                            ",order_id VARCHAR PRIMARY KEY"
+                            ",timestamp INT8 NOT NULL"
+                            ",amount_val INT8 NOT NULL" /* amount we were paid 
*/
+                            ",amount_frac INT4 NOT NULL"
+                            ",paid BOOLEAN NOT NULL DEFAULT FALSE"
                             ");"),
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS backups"
-                            "("
-                            "account_pub BYTEA PRIMARY KEY REFERENCES accounts 
(account_pub),"
-                            "account_sig BYTEA NOT NULL CHECK 
(length(account_sig)=64),"
-                            "prev_hash BYTEA NOT NULL CHECK 
(length(prev_hash)=64),"
-                            "backup_hash BYTEA NOT NULL CHECK 
(length(backup_hash)=64),"
-                            "data BYTEA NOT NULL"
+                            "(account_pub BYTEA PRIMARY KEY REFERENCES 
accounts (account_pub)"
+                            ",account_sig BYTEA NOT NULL CHECK 
(length(account_sig)=64)"
+                            ",prev_hash BYTEA NOT NULL CHECK 
(length(prev_hash)=64)"
+                            ",backup_hash BYTEA NOT NULL CHECK 
(length(backup_hash)=64)"
+                            ",data BYTEA NOT NULL"
                             ");"),
     /* index for gc */
     GNUNET_PQ_make_try_execute (
       "CREATE INDEX accounts_expire ON "
       "accounts (expiration_date);"),
+    GNUNET_PQ_make_try_execute (
+      "CREATE INDEX payments_timestamp ON "
+      "payments (paid,timestamp);"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
   };
   struct GNUNET_PQ_PreparedStatement ps[] = {
     GNUNET_PQ_make_prepare ("account_insert",
                             "INSERT INTO accounts "
-                            "("
-                            "account_pub,"
-                            "expiration_date"
+                            "(account_pub,"
+                            ",expiration_date"
                             ") VALUES "
                             "($1,$2);",
                             2),
+    GNUNET_PQ_make_prepare ("payment_insert",
+                            "INSERT INTO payments "
+                            "(account_pub"
+                            ",order_id"
+                            ",timestamp"
+                            ",amount_val"
+                            ",amount_frac"
+                            ") VALUES "
+                            "($1,$2,$3,$4,$5);",
+                            5),
+    GNUNET_PQ_make_prepare ("payment_done",
+                            "UPDATE payments "
+                            "SET"
+                            " paid=TRUE "
+                            "WHERE"
+                            "  order_id=$1"
+                            " AND"
+                            "  account_pub=$2"
+                            " AND"
+                            "  paid=FALSE;",
+                            2),
     GNUNET_PQ_make_prepare ("account_update",
                             "UPDATE accounts "
                             "SET"
@@ -849,11 +970,41 @@ libsync_plugin_db_postgres_init (void *cls)
                             "WHERE"
                             " account_pub=$1;",
                             1),
-    GNUNET_PQ_make_prepare ("gc",
+    GNUNET_PQ_make_prepare ("payments_select",
+                            "SELECT"
+                            " account_pub"
+                            ",order_id"
+                            ",amount_val"
+                            ",amount_frac"
+                            "FROM"
+                            " payments "
+                            "WHERE"
+                            " paid=FALSE;",
+                            0),
+    GNUNET_PQ_make_prepare ("payments_select_by_account",
+                            "SELECT"
+                            " order_id"
+                            ",amount_val"
+                            ",amount_frac"
+                            "FROM"
+                            " payments "
+                            "WHERE"
+                            "  paid=FALSE"
+                            " AND"
+                            "  account_pub=$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("gc_accounts",
                             "DELETE FROM accounts "
                             "WHERE"
                             " expiration_date < $1;",
                             1),
+    GNUNET_PQ_make_prepare ("gc_accounts",
+                            "DELETE FROM payments "
+                            "WHERE"
+                            "  paid=FALSE"
+                            " AND"
+                            "  timestamp < $1;",
+                            1),
     GNUNET_PQ_make_prepare ("backup_insert",
                             "INSERT INTO backups "
                             "(account_pub"
@@ -916,6 +1067,10 @@ libsync_plugin_db_postgres_init (void *cls)
   plugin->cls = pg;
   plugin->drop_tables = &postgres_drop_tables;
   plugin->gc = &postgres_gc;
+  plugin->store_payment_TR = &postgres_store_payment;
+  plugin->lookup_pending_payments_TR = &postgres_lookup_pending_payments;
+  plugin->lookup_pending_payments_by_account_TR =
+    &postgres_lookup_pending_payments_by_account;
   plugin->store_backup_TR = &postgres_store_backup;
   plugin->lookup_account_TR = &postgres_lookup_account;
   plugin->lookup_backup_TR = &postgres_lookup_backup;

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



reply via email to

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