From 5ef1d5d7bc32522964aeea9e2969274f67449452 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 23 Jan 2023 14:21:08 +0100 Subject: webhook sketch --- src/backend/taler-merchant-webhook.c | 276 +++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/backend/taler-merchant-webhook.c (limited to 'src') diff --git a/src/backend/taler-merchant-webhook.c b/src/backend/taler-merchant-webhook.c new file mode 100644 index 00000000..f9aea28b --- /dev/null +++ b/src/backend/taler-merchant-webhook.c @@ -0,0 +1,276 @@ +/* + This file is part of TALER + Copyright (C) 2023 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see +*/ +/** + * @file taler-merchant-webhook.c + * @brief Process that runs webhooks triggered by the merchant backend + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include +#include +#include +#include "taler_merchantdb_lib.h" +#include "taler_merchantdb_plugin.h" +#include "taler_json_lib.h" + + +/** + * The exchange's configuration. + */ +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * Our database plugin. + */ +static struct TALER_MERCHANTDB_Plugin *db_plugin; + +/** + * Next task to run, if any. + */ +static struct GNUNET_SCHEDULER_Task *task; + +/** + * Handle to the context for interacting with the bank / wire gateway. + */ +static struct GNUNET_CURL_Context *ctx; + +/** + * Scheduler context for running the @e ctx. + */ +static struct GNUNET_CURL_RescheduleContext *rc; + +/** + * Value to return from main(). 0 on success, non-zero on errors. + */ +static int global_ret; + +/** + * #GNUNET_YES if we are in test mode and should exit when idle. + */ +static int test_mode; + + +/** + * We're being aborted with CTRL-C (or SIGTERM). Shut down. + * + * @param cls closure + */ +static void +shutdown_task (void *cls) +{ + (void) cls; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Running shutdown\n"); + if (NULL != task) + { + GNUNET_SCHEDULER_cancel (task); + task = NULL; + } + db_plugin->rollback (db_plugin->cls); /* just in case */ + TALER_MERCHANTDB_plugin_unload (db_plugin); + db_plugin = NULL; + cfg = NULL; + if (NULL != ctx) + { + GNUNET_CURL_fini (ctx); + ctx = NULL; + } + if (NULL != rc) + { + GNUNET_CURL_gnunet_rc_destroy (rc); + rc = NULL; + } +} + + +/** + * Select webhook to process. + * + * @param cls NULL + */ +static void +select_work (void *cls); + + +void +handle_webhook_response (void *cls) +{ + cls->webhook_serial; + // update DB status on the webhook! (delete or update webhook) + + task = GNUNET_SCHEDULER_add_now (&select_work, + NULL); +} + + +void +cb () +{ + CURL *eh; + + eh = curl_easy_new (); + + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_CUSTOMREQUEST, + method)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_URL, + url)); + // run the job + job = GNUNET_CURL_job_add2 (ctx, + eh, + ofh->post_ctx.headers, + &handle_webhook_response, + NULL /* pass struct with webhook ID for update!*/); +} + + +/** + * Select webhook to process. + * + * @param cls NULL + */ +static void +select_work (void *cls) +{ + enum GNUNET_DB_QueryStatus qs; + + (void) cls; + task = NULL; + if (GNUNET_SYSERR == + db_plugin->preflight (db_plugin->cls)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to obtain database connection!\n"); + global_ret = EXIT_FAILURE; + GNUNET_SCHEDULER_shutdown (); + return; + } + qs = db_plugin->lookup_pending_webhooks (db_plugin->cls, + &cb, + NULL); + switch (qs) + { + // FIXME: handle qs + case 1: + // wait for completion, then select more work. + case 0: + db_plugin->lookup_future_webhook (...); + case -1 / -2: + // shutdown. + } +} + + +/** + * First task. + * + * @param cls closure, NULL + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param c configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + (void) cls; + (void) args; + (void) cfgfile; + + cfg = c; + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + rc = GNUNET_CURL_gnunet_rc_create (ctx); + if (NULL == ctx) + { + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL == + (db_plugin = TALER_MERCHANTDB_plugin_load (cfg))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to initialize DB subsystem\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_SYSERR == + db_plugin->preflight (db_plugin->cls)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to obtain database connection!\n"); + global_ret = EXIT_FAILURE; + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_assert (NULL == task); + task = GNUNET_SCHEDULER_add_now (&select_work, + NULL); +} + + +/** + * The main function of the taler-exchange-transfer. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, + char *const *argv) +{ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_flag ('t', + "test", + "run in test mode and exit when idle", + &test_mode), + GNUNET_GETOPT_option_version (VERSION "-" VCS_VERSION), + GNUNET_GETOPT_OPTION_END + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_STRINGS_get_utf8_args (argc, argv, + &argc, &argv)) + return EXIT_INVALIDARGUMENT; + TALER_OS_init (); + ret = GNUNET_PROGRAM_run ( + argc, argv, + "taler-merchant-webhook", + gettext_noop ( + "background process that executes webhooks"), + options, + &run, NULL); + GNUNET_free_nz ((void *) argv); + if (GNUNET_SYSERR == ret) + return EXIT_INVALIDARGUMENT; + if (GNUNET_NO == ret) + return EXIT_SUCCESS; + return global_ret; +} + + +/* end of taler-exchange-transfer.c */ -- cgit v1.2.3