aboutsummaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-webhook.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-webhook.c')
-rw-r--r--src/backend/taler-merchant-webhook.c181
1 files changed, 162 insertions, 19 deletions
diff --git a/src/backend/taler-merchant-webhook.c b/src/backend/taler-merchant-webhook.c
index 7df1ad8e..42600a5a 100644
--- a/src/backend/taler-merchant-webhook.c
+++ b/src/backend/taler-merchant-webhook.c
@@ -28,6 +28,21 @@
#include "taler_json_lib.h"
+struct Work_response
+{
+ struct Work_response *next;
+ struct Work_response *prev;
+ struct GNUNET_CURL_Job *job;
+ uint64_t webhook_serial;
+ char *body;
+ struct curl_slist *job_headers;
+};
+
+
+static struct Work_response *w_head;
+
+static struct Work_response *w_tail;
+
/**
* The exchange's configuration.
*/
@@ -72,6 +87,8 @@ static int test_mode;
static void
shutdown_task (void *cls)
{
+ struct Work_response *w;
+
(void) cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Running shutdown\n");
@@ -80,6 +97,16 @@ shutdown_task (void *cls)
GNUNET_SCHEDULER_cancel (task);
task = NULL;
}
+ while (NULL != (w = w_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (w_head,
+ w_tail,
+ w);
+ GNUNET_CURL_job_cancel (w->job);
+ curl_slist_free (w->job_headers);
+ GNUNET_free (w->body);
+ GNUNET_free (w);
+ }
db_plugin->rollback (db_plugin->cls); /* just in case */
TALER_MERCHANTDB_plugin_unload (db_plugin);
db_plugin = NULL;
@@ -105,15 +132,61 @@ shutdown_task (void *cls)
static void
select_work (void *cls);
+//http request and delete or update in function of the http. And do select work again
-void
-handle_webhook_response (void *cls)
+/**
+ * Function to call upon completion of a raw job.
+ *
+ * @param cls closure
+ * @param response_code HTTP response code from server, 0 on hard error
+ * @param body http body of the response
+ * @param body_size number of bytes in @a body
+ */
+static void
+handle_webhook_response (void *cls,
+ long response_code,
+ const void *body,
+ size_t body_size)
{
- cls->webhook_serial;
- // update DB status on the webhook! (delete or update webhook)
+ struct Work_response *w = cls;
+ struct GNUNET_TIME_Relative next_attempt;
- task = GNUNET_SCHEDULER_add_now (&select_work,
- NULL);
+ (void) body;
+ (void) body_size;
+ job = NULL;
+ // update DB status on the webhook! (delete or update webhook)
+ if (2 == response_code / 100) /* any 2xx http status code is OK! */
+ {
+ db_plugib->delete_pending_webhook (db_plugin->cls,
+ w->webhook_serial);
+ }
+ else
+ {
+ switch (response_code)
+ {
+ case MHD_HTTP_BAD_REQUEST:
+ next_attempt = GNUNET_TIME_UNIT_FOREVER_REL; // never try again
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ next_attempt = GNUNET_TIME_UNIT_MINUTES;
+ break;
+ default:
+ next_attempt = GNUNET_TIME_UNIT_HOURS;
+ break;
+ }
+ db_plugin->update_pending_webhook (db_plugin->cls,
+ w->webhook_serial,
+ GNUNET_TIME_relative_to_absolute (next_attempt));
+ }
+ GNUNET_CONTAINER_DLL_remove (w_head,
+ w_tail,
+ w);
+ GNUNET_free (w->body);
+ curl_slist_free_all (w->job_headers);
+ GNUNET_free (w);
+ if (NULL == w_head)
+ task = GNUNET_SCHEDULER_add_now (&select_work,
+ NULL);
}
@@ -129,35 +202,93 @@ handle_webhook_response (void *cls)
* @param header of the webhook
* @param body of the webhook
*/
+// initialisation curl, and do the job
static void
cb (void *cls,
uint64_t webhook_serial,
- struct GNUNET_TIME_Absolute
- next_attempt,
+ struct GNUNET_TIME_Absolute next_attempt,
uint32_t retries,
const char *url,
const char *http_method,
const char *header,
const char *body)
{
+ struct Work_response *w = GNUNET_new (struct Work_response);
CURL *eh;
+ struct curl_slist *job_headers = NULL;
+ GNUNET_CONTAINER_DLL_insert (w_head,
+ w_tail,
+ w);
+ w->webhook_serial = webhook_serial;
eh = curl_easy_new ();
-
+ GNUNET_assert (NULL != eh);
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_CUSTOMREQUEST,
- method));
+ http_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!*/);
+ // FIXME: convert header to job_headers!
+
+ w->body = GNUNET_strdup (body);
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_POSTFIELDS,
+ w->body));
+ w->job_headers = job_headers;
+ w->job = GNUNET_CURL_job_add_raw (ctx,
+ eh,
+ job_headers,
+ &handle_webhook_response,
+ w);
+ if (NULL == w->job)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to start the curl job for webhook #%llu\n",
+ (unsigned long long) webhook_serial);
+ curl_slist_free_all (w->job_headers);
+ GNUNET_free (w->body);
+ GNUNET_CONTAINER_DLL_remove (w_head,
+ w_tail,
+ w);
+ GNUNET_free (w);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+}
+
+
+/**
+ * Typically called by `lookup_pending_webhooks`.
+ *
+ * @param cls a `json_t *` JSON array to build
+ * @param webhook_serial reference to the configured webhook template.
+ * @param next_attempt is the time we should make the next request to the webhook.
+ * @param retries how often have we tried this request to the webhook.
+ * @param url to make request to
+ * @param http_method use for the webhook
+ * @param header of the webhook
+ * @param body of the webhook
+ */
+// initialisation curl, and do the job
+static void
+cb_future (void *cls,
+ uint64_t webhook_serial,
+ struct GNUNET_TIME_Absolute next_attempt,
+ uint32_t retries,
+ const char *url,
+ const char *http_method,
+ const char *header,
+ const char *body)
+{
+ (void) webhook_serial;
+
+ task = GNUNET_SCHEDULER_add_at (next_attempt,
+ &select_work,
+ NULL);
}
@@ -166,6 +297,7 @@ cb (void *cls,
*
* @param cls NULL
*/
+// do the action of the pending webhook
static void
select_work (void *cls)
{
@@ -188,12 +320,23 @@ select_work (void *cls)
switch (qs)
{
// FIXME: handle qs
- case 1:
- // wait for completion, then select more work.
case 0:
- db_plugin->lookup_future_webhook (...);
+ qs = db_plugin->lookup_future_webhook (db_plugin->cls,
+ &cb_future,
+ NULL);
+ switch (qs) {
+ // ...
+ }
+ return;
case -1 / -2:
// shutdown.
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed!\n");
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ default:
+ return; // wait for completion, then select more work.
}
}