summaryrefslogtreecommitdiff
path: root/src/sync/sync-httpd.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-11-17 00:13:00 +0100
committerChristian Grothoff <christian@grothoff.org>2019-11-17 00:13:00 +0100
commit8b1e276a316d29a752b26cdc070330e688aea221 (patch)
tree203a9de2a95edae1dae9979ec4296e63b3bb61e9 /src/sync/sync-httpd.c
parent9badf80eb4228a9c009839a4856710127efe8601 (diff)
downloadsync-8b1e276a316d29a752b26cdc070330e688aea221.tar.gz
sync-8b1e276a316d29a752b26cdc070330e688aea221.tar.bz2
sync-8b1e276a316d29a752b26cdc070330e688aea221.zip
breaking the build badly, big hacking
Diffstat (limited to 'src/sync/sync-httpd.c')
-rw-r--r--src/sync/sync-httpd.c227
1 files changed, 225 insertions, 2 deletions
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
@@ -35,6 +35,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
*/
static long long unsigned port;
@@ -55,6 +107,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.
*/
static struct GNUNET_SCHEDULER_Task *mhd_task;
@@ -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;
@@ -387,6 +484,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",