summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-11-10 15:23:09 +0100
committerChristian Grothoff <christian@grothoff.org>2015-11-10 15:23:09 +0100
commit4a6da71b506b52fa68873038882dd88333ff5308 (patch)
tree094841ae0c1cb12789e97bee2751ef92999ce052
parent09ef5506b295d3882e384a098719dee66bdd7455 (diff)
downloadmerchant-4a6da71b506b52fa68873038882dd88333ff5308.tar.gz
merchant-4a6da71b506b52fa68873038882dd88333ff5308.tar.bz2
merchant-4a6da71b506b52fa68873038882dd88333ff5308.zip
run MHD in the main thread
-rw-r--r--src/backend/taler-merchant-httpd.c123
1 files changed, 105 insertions, 18 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 9914d157..43ffb639 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -63,7 +63,7 @@ char *keyfile;
static struct TALER_MINT_Context *mctx;
/**
- * This value tells the mint by which date this merchant would like
+ * This value tells the mint by which date this merchant would like
* to receive the funds for a deposited payment
*/
struct GNUNET_TIME_Relative edate_delay;
@@ -89,6 +89,11 @@ struct MERCHANT_Auditor *auditors;
static struct GNUNET_SCHEDULER_Task *shutdown_task;
/**
+ * Task running the HTTP server.
+ */
+static struct GNUNET_SCHEDULER_Task *mhd_task;
+
+/**
* Context "poller" identifier
*/
struct GNUNET_SCHEDULER_Task *poller_task;
@@ -306,29 +311,33 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
if (NULL != mints[cnt].conn)
TALER_MINT_disconnect (mints[cnt].conn);
-
+
}
if (NULL != poller_task)
{
GNUNET_SCHEDULER_cancel (poller_task);
poller_task = NULL;
}
-
+ if (NULL != mhd_task)
+ {
+ GNUNET_SCHEDULER_cancel (mhd_task);
+ mhd_task = NULL;
+ }
if (NULL != mhd)
- {
- MHD_stop_daemon (mhd);
- mhd = NULL;
- }
-
+ {
+ MHD_stop_daemon (mhd);
+ mhd = NULL;
+ }
if (NULL != db_conn)
- {
- MERCHANT_DB_disconnect (db_conn);
- db_conn = NULL;
- }
+ {
+ MERCHANT_DB_disconnect (db_conn);
+ db_conn = NULL;
+ }
if (NULL != keyfile)
GNUNET_free (privkey);
}
+
/**
* Task that runs the context's event loop using the GNUnet scheduler.
*
@@ -388,6 +397,7 @@ context_task (void *cls,
GNUNET_NETWORK_fdset_destroy (ws);
}
+
/**
* Function called whenever MHD is done with a request. If the
* request was a POST, we may have stored a `struct Buffer *` in the
@@ -414,6 +424,83 @@ handle_mhd_completion_callback (void *cls,
*con_cls = NULL;
}
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ */
+static struct GNUNET_SCHEDULER_Task *
+prepare_daemon (void);
+
+
+/**
+ * Call MHD to process pending requests and then go back
+ * and schedule the next run.
+ *
+ * @param cls the `struct MHD_Daemon` of the HTTP server to run
+ * @param tc scheduler context
+ */
+static void
+run_daemon (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ mhd_task = NULL;
+ GNUNET_assert (MHD_YES == MHD_run (mhd));
+ mhd_task = prepare_daemon ();
+}
+
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ *
+ * @param daemon_handle HTTP server to prepare to run
+ */
+static struct GNUNET_SCHEDULER_Task *
+prepare_daemon ()
+{
+ struct GNUNET_SCHEDULER_Task * ret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ struct GNUNET_NETWORK_FDSet *wrs;
+ struct GNUNET_NETWORK_FDSet *wws;
+ int max;
+ MHD_UNSIGNED_LONG_LONG timeout;
+ int haveto;
+ struct GNUNET_TIME_Relative tv;
+
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ wrs = GNUNET_NETWORK_fdset_create ();
+ wws = GNUNET_NETWORK_fdset_create ();
+ max = -1;
+ GNUNET_assert (MHD_YES ==
+ MHD_get_fdset (mhd,
+ &rs,
+ &ws,
+ &es,
+ &max));
+ haveto = MHD_get_timeout (mhd, &timeout);
+ if (haveto == MHD_YES)
+ tv.rel_value_us = (uint64_t) timeout * 1000LL;
+ else
+ tv = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+ ret =
+ GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
+ tv, wrs, wws,
+ &run_daemon,
+ NULL);
+ GNUNET_NETWORK_fdset_destroy (wrs);
+ GNUNET_NETWORK_fdset_destroy (wws);
+ return ret;
+}
+
+
+
/**
* Main function that will be run by the scheduler.
*
@@ -485,7 +572,7 @@ run (void *cls, char *const *args, const char *cfgfile,
&edate_delay));
salt = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
- UINT64_MAX);
+ UINT64_MAX);
for (cnt = 0; cnt < nmints; cnt++)
{
@@ -494,22 +581,22 @@ run (void *cls, char *const *args, const char *cfgfile,
mints[cnt].conn = TALER_MINT_connect (mints[cnt].ctx,
mints[cnt].hostname,
&keys_mgmt_cb,
- &mints[cnt]);
+ &mints[cnt]);
EXITIF (NULL == mints[cnt].conn);
poller_task =
GNUNET_SCHEDULER_add_now (&context_task, mints[cnt].ctx);
}
- mhd = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SUSPEND_RESUME,
+ mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME,
port,
NULL, NULL,
&url_handler, NULL,
MHD_OPTION_NOTIFY_COMPLETED,
&handle_mhd_completion_callback, NULL,
MHD_OPTION_END);
-
EXITIF (NULL == mhd);
result = GNUNET_OK;
+ mhd_task = prepare_daemon ();
EXITIF_exit:
if (GNUNET_OK != result)
@@ -530,14 +617,14 @@ run (void *cls, char *const *args, const char *cfgfile,
int
main (int argc, char *const *argv)
{
-
+
static const struct GNUNET_GETOPT_CommandLineOption options[] = {
{'t', "temp", NULL,
gettext_noop ("Use temporary database tables"), GNUNET_NO,
&GNUNET_GETOPT_set_one, &dry},
GNUNET_GETOPT_OPTION_END
};
-
+
if (GNUNET_OK !=
GNUNET_PROGRAM_run (argc, argv,