diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-11-17 00:13:00 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-11-17 00:13:00 +0100 |
commit | 8b1e276a316d29a752b26cdc070330e688aea221 (patch) | |
tree | 203a9de2a95edae1dae9979ec4296e63b3bb61e9 /src/sync/sync-httpd.c | |
parent | 9badf80eb4228a9c009839a4856710127efe8601 (diff) | |
download | sync-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.c | 227 |
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", |