sync

Backup service to store encrypted wallet databases (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit e628a34bc8c697a655050bf12360f5a1c113c52b
parent c12ae1f5fd5a32883c210c196bb4e9a731d2bfd5
Author: Iván Ávalos <avalos@disroot.org>
Date:   Thu,  1 Oct 2026 17:07:09 +0200

remove libmicrohttpd1 dependency

Diffstat:
Mmeson.build | 28----------------------------
Msrc/include/taler/taler_mhd2_lib.h | 29++++++++---------------------
Msrc/lib/meson.build | 1+
Msrc/lib/sync_api_block_list.c | 12++++++------
Msrc/lib/sync_api_block_operation_common.c | 14+++++++-------
Msrc/lib/sync_api_block_operation_common.h | 2+-
Msrc/lib/sync_api_block_reconcile.c | 12++++++------
Msrc/lib/sync_api_object_fetch.c | 10+++++-----
Msrc/mhd2/meson.build | 1+
Asrc/mhd2/mhd2_config.c | 474+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/sync/meson.build | 1-
Msrc/sync/sync-httpd2.c | 8++++----
12 files changed, 513 insertions(+), 79 deletions(-)

diff --git a/meson.build b/meson.build @@ -68,11 +68,6 @@ if not get_option('only-doc') endforeach - mhd_dep = dependency('libmicrohttpd', required: false) - if not mhd_dep.found() - mhd_dep = cc.find_library('microhttpd', required: true) - endif - # sync-httpd2 is the only daemon we build, so MHD2 is mandatory. mhd2_dep = dependency('libmicrohttpd2', required: false) if not mhd2_dep.found() @@ -113,17 +108,6 @@ if not get_option('only-doc') gnunetjson_dep = cc.find_library('gnunetjson', required: true) endif - gnunetmhd_dep = dependency('gnunetmhd', required: false) - if not gnunetmhd_dep.found() - gnunetmhd_dep = cc.find_library('gnunetmhd', required: true) - endif - cc.has_header_symbol( - 'gnunet/gnunet_mhd_lib.h', - 'GNUNET_MHD_post_parser', - dependencies: [gnunetmhd_dep], - required: true, - ) - curl_dep = dependency('libcurl', version: '>=7.34.0', required: false) if not curl_dep.found() curl_dep = cc.find_library('curl', required: true) @@ -221,18 +205,6 @@ if not get_option('only-doc') ) private_config.set10('HAVE_TALEREXCHANGE', talerexchange_dep.found()) - talermhd_dep = dependency('talermhd', required: false) - if not talermhd_dep.found() - talermhd_dep = cc.find_library('talermhd', required: true) - endif - cc.has_header_symbol( - 'taler/taler_mhd_lib.h', - 'TALER_MHD_parse_request_arg_rel_time', - required: true, - dependencies: [talermhd_dep], - ) - private_config.set10('HAVE_TALERMHD', talermhd_dep.found()) - talerjson_dep = dependency('talerjson', required: false) if not talerjson_dep.found() talerjson_dep = cc.find_library('talerjson', required: true) diff --git a/src/include/taler/taler_mhd2_lib.h b/src/include/taler/taler_mhd2_lib.h @@ -91,7 +91,7 @@ TALER_MHD2_arg_to_yna (struct MHD_Request *request, /** - * Set global options for response generation within libtalermhd. + * Set global options for response generation within libtalermhd2. * * @param go global options to use */ @@ -887,29 +887,16 @@ TALER_MHD2_check_content_length_ (struct MHD_Request *request, /** - * Function called for logging by MHD. - * - * @param cls closure, NULL - * @param fm format string (`printf()`-style) - * @param ap arguments to @a fm - */ -void -TALER_MHD_handle_logs (void *cls, - const char *fm, - va_list ap); - - -/** * Function called on each successfully bound listen - * socket by #TALER_MHD_listen_bind(). + * socket by #TALER_MHD2_listen_bind(). * * @param cls closure * @param fd bound listen socket (must be used and eventually * closed by the callee). Never -1. */ typedef void -(*TALER_MHD_ListenSocketCallback)(void *cls, - int fd); +(*TALER_MHD2_ListenSocketCallback)(void *cls, + int fd); /** @@ -929,10 +916,10 @@ typedef void * #GNUNET_SYSERR if the configuration is invalid */ enum GNUNET_GenericReturnValue -TALER_MHD_listen_bind (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section, - TALER_MHD_ListenSocketCallback cb, - void *cb_cls); +TALER_MHD2_listen_bind (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + TALER_MHD2_ListenSocketCallback cb, + void *cb_cls); /** diff --git a/src/lib/meson.build b/src/lib/meson.build @@ -26,6 +26,7 @@ libsync = library( gnunetutil_dep, gnunetjson_dep, gnunetcurl_dep, + mhd2_dep, json_dep, curl_dep, ], diff --git a/src/lib/sync_api_block_list.c b/src/lib/sync_api_block_list.c @@ -24,7 +24,7 @@ #include "platform.h" #include <curl/curl.h> #include <jansson.h> -#include <microhttpd.h> +#include <microhttpd2.h> #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_curl_lib.h> #include <gnunet/gnunet_json_lib.h> @@ -94,7 +94,7 @@ handle_block_list_finished (void *cls, { case 0: break; - case MHD_HTTP_OK: + case MHD_HTTP_STATUS_OK: if (NULL != json) { unsigned int idx; @@ -123,10 +123,10 @@ handle_block_list_finished (void *cls, ld.ec = TALER_EC_GENERIC_INVALID_RESPONSE; } break; - case MHD_HTTP_BAD_REQUEST: - case MHD_HTTP_NOT_FOUND: - case MHD_HTTP_PAYMENT_REQUIRED: - case MHD_HTTP_INTERNAL_SERVER_ERROR: + case MHD_HTTP_STATUS_BAD_REQUEST: + case MHD_HTTP_STATUS_NOT_FOUND: + case MHD_HTTP_STATUS_PAYMENT_REQUIRED: + case MHD_HTTP_STATUS_INTERNAL_SERVER_ERROR: default: if ( (response_code >= 400) && (response_code < 500) ) diff --git a/src/lib/sync_api_block_operation_common.c b/src/lib/sync_api_block_operation_common.c @@ -170,31 +170,31 @@ SYNC_block_operation_handle_finished_ (void *cls, { case 0: break; - case MHD_HTTP_NO_CONTENT: + case MHD_HTTP_STATUS_NO_CONTENT: ud.bos = SYNC_BOS_SUCCESS; ud.ec = TALER_EC_NONE; break; - case MHD_HTTP_NOT_MODIFIED: + case MHD_HTTP_STATUS_NOT_MODIFIED: ud.bos = SYNC_BOS_NOT_MODIFIED; ud.ec = TALER_EC_NONE; break; - case MHD_HTTP_PAYMENT_REQUIRED: + case MHD_HTTP_STATUS_PAYMENT_REQUIRED: ud.bos = SYNC_BOS_PAYMENT_REQUIRED; ud.pay_uri = op->pay_uri; ud.ec = TALER_EC_NONE; break; - case MHD_HTTP_BAD_REQUEST: + case MHD_HTTP_STATUS_BAD_REQUEST: ud.ec = (NULL != json) ? TALER_JSON_get_error_code (json) : TALER_EC_GENERIC_PARAMETER_MALFORMED; break; - case MHD_HTTP_FORBIDDEN: + case MHD_HTTP_STATUS_FORBIDDEN: ud.ec = (NULL != json) ? TALER_JSON_get_error_code (json) : TALER_EC_SYNC_INVALID_SIGNATURE; break; - case MHD_HTTP_CONTENT_TOO_LARGE: - case MHD_HTTP_INTERNAL_SERVER_ERROR: + case MHD_HTTP_STATUS_CONTENT_TOO_LARGE: + case MHD_HTTP_STATUS_INTERNAL_SERVER_ERROR: default: if ( (response_code >= 400) && (response_code < 500) ) diff --git a/src/lib/sync_api_block_operation_common.h b/src/lib/sync_api_block_operation_common.h @@ -28,7 +28,7 @@ #include "platform.h" #include <curl/curl.h> #include <jansson.h> -#include <microhttpd.h> +#include <microhttpd2.h> #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_curl_lib.h> #include <gnunet/gnunet_json_lib.h> diff --git a/src/lib/sync_api_block_reconcile.c b/src/lib/sync_api_block_reconcile.c @@ -24,7 +24,7 @@ #include "platform.h" #include <curl/curl.h> #include <jansson.h> -#include <microhttpd.h> +#include <microhttpd2.h> #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_curl_lib.h> #include <gnunet/gnunet_json_lib.h> @@ -101,7 +101,7 @@ handle_reconcile_finished (void *cls, { case 0: break; - case MHD_HTTP_OK: + case MHD_HTTP_STATUS_OK: if (NULL != json) { const json_t *j; @@ -221,10 +221,10 @@ handle_reconcile_finished (void *cls, rd.ec = TALER_EC_GENERIC_INVALID_RESPONSE; } break; - case MHD_HTTP_BAD_REQUEST: - case MHD_HTTP_NOT_FOUND: - case MHD_HTTP_PAYMENT_REQUIRED: - case MHD_HTTP_INTERNAL_SERVER_ERROR: + case MHD_HTTP_STATUS_BAD_REQUEST: + case MHD_HTTP_STATUS_NOT_FOUND: + case MHD_HTTP_STATUS_PAYMENT_REQUIRED: + case MHD_HTTP_STATUS_INTERNAL_SERVER_ERROR: default: if ( (response_code >= 400) && (response_code < 500) ) diff --git a/src/lib/sync_api_object_fetch.c b/src/lib/sync_api_object_fetch.c @@ -24,7 +24,7 @@ #include "platform.h" #include <curl/curl.h> #include <jansson.h> -#include <microhttpd.h> +#include <microhttpd2.h> #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_curl_lib.h> #include <gnunet/gnunet_json_lib.h> @@ -93,7 +93,7 @@ handle_object_fetch_finished (void *cls, { case 0: break; - case MHD_HTTP_OK: + case MHD_HTTP_STATUS_OK: if (NULL != json) { if (GNUNET_OK != @@ -111,9 +111,9 @@ handle_object_fetch_finished (void *cls, ec = TALER_EC_GENERIC_INVALID_RESPONSE; } break; - case MHD_HTTP_BAD_REQUEST: - case MHD_HTTP_NOT_FOUND: - case MHD_HTTP_INTERNAL_SERVER_ERROR: + case MHD_HTTP_STATUS_BAD_REQUEST: + case MHD_HTTP_STATUS_NOT_FOUND: + case MHD_HTTP_STATUS_INTERNAL_SERVER_ERROR: default: if ( (response_code >= 400) && (response_code < 500) ) diff --git a/src/mhd2/meson.build b/src/mhd2/meson.build @@ -4,6 +4,7 @@ libtalermhd2 = static_library( 'talermhd2', [ 'mhd2.c', + 'mhd2_config.c', 'mhd2_legal.c', 'mhd2_responses.c', 'mhd2_run.c', diff --git a/src/mhd2/mhd2_config.c b/src/mhd2/mhd2_config.c @@ -0,0 +1,474 @@ +/* + This file is part of TALER + Copyright (C) 2014--2025 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 <http://www.gnu.org/licenses/> +*/ +/** + * @file mhd2_config.c + * @brief functions to bind listen sockets for MHD2 daemons + * @author Florian Dold + * @author Benedikt Mueller + * @author Christian Grothoff + */ +#include "platform.h" /* UNNECESSARY? */ +#include <gnunet/gnunet_util_lib.h> +#include "taler/taler_mhd2_lib.h" + + +/** + * Backlog for listen operation. + */ +#define LISTEN_BACKLOG 500 + + +/** + * Open UNIX domain socket for listining at @a unix_path with + * permissions @a unix_mode. + * + * @param unix_path where to listen + * @param unix_mode access permissions to set + * @return -1 on error, otherwise the listen socket + */ +static int +open_unix_path (const char *unix_path, + mode_t unix_mode) +{ + struct GNUNET_NETWORK_Handle *nh; + struct sockaddr_un *un; + + if (sizeof (un->sun_path) <= strlen (unix_path)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "unixpath `%s' is too long\n", + unix_path); + return -1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Creating listen socket '%s' with mode %o\n", + unix_path, + unix_mode); + + if (GNUNET_OK != + GNUNET_DISK_directory_create_for_file (unix_path)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "mkdir", + unix_path); + } + + un = GNUNET_new (struct sockaddr_un); + un->sun_family = AF_UNIX; + strncpy (un->sun_path, + unix_path, + sizeof (un->sun_path) - 1); + GNUNET_NETWORK_unix_precheck (un); + + if (NULL == (nh = GNUNET_NETWORK_socket_create (AF_UNIX, + SOCK_STREAM, + 0))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "socket"); + GNUNET_free (un); + return -1; + } + + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (nh, + (void *) un, + sizeof (struct sockaddr_un))) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "bind", + unix_path); + GNUNET_free (un); + GNUNET_NETWORK_socket_close (nh); + return -1; + } + GNUNET_free (un); + if (GNUNET_OK != + GNUNET_NETWORK_socket_listen (nh, + LISTEN_BACKLOG)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "listen"); + GNUNET_NETWORK_socket_close (nh); + return -1; + } + + if (0 != chmod (unix_path, + unix_mode)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "chmod"); + GNUNET_NETWORK_socket_close (nh); + return -1; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "set socket '%s' to mode %o\n", + unix_path, + unix_mode); + + /* extract and return actual socket handle from 'nh' */ + { + int fd; + + fd = GNUNET_NETWORK_get_fd (nh); + GNUNET_NETWORK_socket_free_memory_only_ (nh); + return fd; + } +} + + +enum GNUNET_GenericReturnValue +TALER_MHD2_listen_bind (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + TALER_MHD2_ListenSocketCallback cb, + void *cb_cls) +{ + const char *choices[] = { + "tcp", + "unix", + "systemd", + NULL + }; + const char *serve_type; + enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_choice (cfg, + section, + "SERVE", + choices, + &serve_type)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "SERVE", + "serve type (tcp, unix or systemd) required"); + return GNUNET_SYSERR; + } + + + /* try systemd passing always first */ + { + const char *listen_pid; + const char *listen_fds; + const char *listen_fdn; + + /* check for systemd-style FD passing */ + if ( (NULL != (listen_pid = getenv ("LISTEN_PID"))) && + (getpid () == + strtol (listen_pid, + NULL, + 10)) && + (NULL != (listen_fds = getenv ("LISTEN_FDS"))) && + (NULL != (listen_fdn = getenv ("LISTEN_FDNAMES"))) ) + { + int off = 3; + unsigned int cnt; + char dummy; + + if (0 != strcmp (serve_type, + "systemd")) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Using systemd activation due to environment variables. Set SERVE=systemd to disable this warning!\n"); + } + else + { + ret = GNUNET_NO; + } + if (1 != sscanf (listen_fds, + "%u%c", + &cnt, + &dummy)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Invalid number `%s' of systemd sockets specified\n", + listen_fds); + } + else + { + char *fdns; + + fdns = GNUNET_strdup (listen_fdn); + for (const char *tok = strtok (fdns, + ":"); + cnt-- > 0; + tok = strtok (NULL, + ":")) + { + int fh = off++; + int flags; + + flags = fcntl (fh, + F_GETFD); + if ( (-1 == flags) && + (EBADF == errno) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Bad listen socket %s (%d) passed, ignored\n", + tok, + fh); + continue; + } + flags |= FD_CLOEXEC; + if (0 != fcntl (fh, + F_SETFD, + flags)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "fcntl"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Successfully obtained listen socket %s (#%d) from hypervisor\n", + tok, + fh); + cb (cb_cls, + fh); + ret = GNUNET_OK; + } + GNUNET_free (fdns); + } + } + } + + /* now try configuration file */ + if (0 == strcmp (serve_type, + "unix")) + { + char *serve_unixpath; + mode_t unixpath_mode; + struct sockaddr_un s_un; + char *modestring; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, + section, + "UNIXPATH", + &serve_unixpath)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "UNIXPATH", + "UNIXPATH value required"); + return GNUNET_SYSERR; + } + if (strlen (serve_unixpath) >= sizeof (s_un.sun_path)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "unixpath `%s' is too long\n", + serve_unixpath); + GNUNET_free (serve_unixpath); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + section, + "UNIXPATH_MODE", + &modestring)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + section, + "UNIXPATH_MODE"); + GNUNET_free (serve_unixpath); + return GNUNET_SYSERR; + } + { + char *endp; + unsigned long mode; + + errno = 0; + mode = strtoul (modestring, + &endp, + 8); + /* strtoul() only sets errno on overflow, so we must + also check that we actually consumed the entire value */ + if ( (0 != errno) || + (endp == modestring) || + ('\0' != *endp) || + (mode != (unsigned long) (mode_t) mode) ) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "UNIXPATH_MODE", + "must be octal number"); + GNUNET_free (modestring); + GNUNET_free (serve_unixpath); + return GNUNET_SYSERR; + } + unixpath_mode = (mode_t) mode; + } + GNUNET_free (modestring); + + { + int fd; + + fd = open_unix_path (serve_unixpath, + unixpath_mode); + GNUNET_free (serve_unixpath); + if (-1 == fd) + return GNUNET_NO; + cb (cb_cls, + fd); + return GNUNET_OK; + } + } + + if (0 == strcasecmp (serve_type, + "tcp")) + { + unsigned long long lport; + struct GNUNET_NETWORK_Handle *nh; + char *bind_to; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + section, + "PORT", + &lport)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "PORT", + "port number required"); + return GNUNET_SYSERR; + } + + if ( (0 == lport) || + (lport > UINT16_MAX) ) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "PORT", + "port number not in [1,65535]"); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + section, + "BIND_TO", + &bind_to)) + bind_to = NULL; + + /* let's have fun binding... */ + { + char port_str[6]; + struct addrinfo hints; + struct addrinfo *res; + int ec; + + GNUNET_snprintf (port_str, + sizeof (port_str), + "%u", + (unsigned int) lport); + memset (&hints, + 0, + sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE +#ifdef AI_IDN + | AI_IDN +#endif + ; + + if (0 != + (ec = getaddrinfo (bind_to, + port_str, + &hints, + &res))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to resolve BIND_TO address `%s': %s\n", + bind_to, + gai_strerror (ec)); + GNUNET_free (bind_to); + return GNUNET_SYSERR; + } + GNUNET_free (bind_to); + for (struct addrinfo *ai = res; + NULL != ai; + ai = ai->ai_next) + { + if (NULL == (nh = GNUNET_NETWORK_socket_create (ai->ai_family, + ai->ai_socktype, + ai->ai_protocol))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "socket"); + freeaddrinfo (res); + return GNUNET_NO; + } + { + const int on = 1; + + if (GNUNET_OK != + GNUNET_NETWORK_socket_setsockopt (nh, + SOL_SOCKET, + SO_REUSEPORT, + &on, + sizeof(on))) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "setsockopt"); + } + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (nh, + ai->ai_addr, + ai->ai_addrlen)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "bind"); + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (nh)); + freeaddrinfo (res); + return GNUNET_NO; + } + + if (GNUNET_OK != + GNUNET_NETWORK_socket_listen (nh, + LISTEN_BACKLOG)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "listen"); + GNUNET_SCHEDULER_shutdown (); + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (nh)); + freeaddrinfo (res); + return GNUNET_NO; + } + + /* extract and return actual socket handle from 'nh' */ + { + int fh; + + fh = GNUNET_NETWORK_get_fd (nh); + GNUNET_NETWORK_socket_free_memory_only_ (nh); + if (-1 == fh) + { + GNUNET_break (0); + freeaddrinfo (res); + return GNUNET_NO; + } + cb (cb_cls, + fh); + } + } /* for all addrinfos */ + freeaddrinfo (res); + return GNUNET_OK; + } /* bind data scope */ + } /* tcp */ + return ret; +} diff --git a/src/sync/meson.build b/src/sync/meson.build @@ -21,7 +21,6 @@ executable( talerutil_dep, talerjson_dep, talermerchant_dep, - talermhd_dep, libtalermhd2_dep, gnunetutil_dep, gnunetjson_dep, diff --git a/src/sync/sync-httpd2.c b/src/sync/sync-httpd2.c @@ -880,10 +880,10 @@ run (void *cls, { enum GNUNET_GenericReturnValue ret; - ret = TALER_MHD_listen_bind (config, - "sync", - &start_daemon, - NULL); + ret = TALER_MHD2_listen_bind (config, + "sync", + &start_daemon, + NULL); switch (ret) { case GNUNET_SYSERR: