summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-09-20 17:46:42 +0200
committerChristian Grothoff <christian@grothoff.org>2018-09-20 17:46:42 +0200
commitd4f3a2eed509d1719b58031a9fa74cd2e669327f (patch)
tree753ba9fcbf0eb17ff55e34f970458d059e3bd431
parent2f69f626b0e47a7affa206038c217cc0bb09e49c (diff)
downloadtwister-d4f3a2eed509d1719b58031a9fa74cd2e669327f.tar.gz
twister-d4f3a2eed509d1719b58031a9fa74cd2e669327f.tar.bz2
twister-d4f3a2eed509d1719b58031a9fa74cd2e669327f.zip
port state engine fixes from GNS proxy to twister service
-rw-r--r--m4/libtool.m412
-rw-r--r--src/twister/taler-twister-service.c200
2 files changed, 166 insertions, 46 deletions
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index ee80844..e67ed69 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -6438,7 +6438,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
else
GXX=no
@@ -6813,7 +6813,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
@@ -6878,7 +6878,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
@@ -7217,7 +7217,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
else
# FIXME: insert proper C++ library support
@@ -7301,7 +7301,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
else
# g++ 2.7 appears to require '-G' NOT '-shared' on this
# platform.
@@ -7312,7 +7312,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
- output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
diff --git a/src/twister/taler-twister-service.c b/src/twister/taler-twister-service.c
index d12bc67..071241d 100644
--- a/src/twister/taler-twister-service.c
+++ b/src/twister/taler-twister-service.c
@@ -40,12 +40,13 @@
#include <microhttpd.h>
#include <taler/taler_util.h>
-
-/**
- * We allow X runs of the progress callback before
- * declaring the upload callback dead.
+/**
+ * Keep logic of Marcello's fix for #5337? Unclear how it works, and
+ * may be superceeded by subsequent revisions, but kept for now to
+ * easily identify what might fix the issue (until CG can actually
+ * reproduce it nicely).
*/
-#define DOWNLOAD_PAUSED_TIMES_MAX 10
+#define MARCELLO_FIX 1
/**
* Log curl error.
@@ -76,6 +77,11 @@ enum RequestState
REQUEST_STATE_UPLOAD_STARTED,
/**
+ * We're done with the upload from MHD.
+ */
+ REQUEST_STATE_UPLOAD_DONE,
+
+ /**
* We've finished uploading data via CURL and can now download.
*/
REQUEST_STATE_DOWNLOAD_STARTED,
@@ -122,6 +128,21 @@ struct HttpRequest
{
/**
+ * Kept in DLL.
+ */
+ struct HttpRequest *prev;
+
+ /**
+ * Kept in DLL.
+ */
+ struct HttpRequest *next;
+
+ /**
+ * MHD request that triggered us.
+ */
+ struct MHD_Connection *con;
+
+ /**
* Client socket read task
*/
struct GNUNET_SCHEDULER_Task *rtask;
@@ -153,7 +174,7 @@ struct HttpRequest
char *url;
/**
- * JSON we use to parse payloads (in both directions).
+ * JSON we use to parse payloads (in both directions).
*/
json_t *json;
@@ -198,15 +219,22 @@ struct HttpRequest
enum RequestState state;
/**
- * Indicates that the download callback is sleeping.
+ * Did we suspend MHD processing?
*/
- int download_paused;
+ int suspended;
/**
+ * Did we pause CURL processing?
+ */
+ int curl_paused;
+
+#if MARCELLO_FIX
+ /**
* Indicates that the Web server returned a "Connection: close"
* header line.
*/
int connection_closed;
+#endif
};
@@ -216,7 +244,17 @@ struct HttpRequest
/**
* The cURL download task (curl multi API).
*/
-static struct GNUNET_SCHEDULER_Task * curl_download_task;
+static struct GNUNET_SCHEDULER_Task *curl_download_task;
+
+/**
+ * DLL of active HTTP requests.
+ */
+static struct HttpRequest *hr_head;
+
+/**
+ * DLL of active HTTP requests.
+ */
+static struct HttpRequest *hr_tail;
/**
* The cURL multi handle
@@ -395,17 +433,17 @@ curl_check_hdr (void *buffer,
*tok = '\0';
if (NULL != (tok = strchr (hdr_val, '\t')))
*tok = '\0';
-
- if (0 == strcasecmp (hdr_type,
- MHD_HTTP_HEADER_CONNECTION)
- && (0 == strcasecmp (hdr_val,
- "close")))
+#if MARCELLO_FIX
+ if ( (0 == strcasecmp (hdr_type,
+ MHD_HTTP_HEADER_CONNECTION) &&
+ (0 == strcasecmp (hdr_val,
+ "close")) ) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Server wants to close the TCP connection\n");
hr->connection_closed = GNUNET_YES;
}
-
+#endif
if (0 != strlen (hdr_val)) /* Rely in MHD to set those */
{
@@ -463,6 +501,9 @@ create_mhd_response_from_hr (struct HttpRequest *hr)
hr->io_len,
JSON_DECODE_ANY,
&error);
+ GNUNET_assert (GNUNET_YES == hr->suspended);
+ MHD_resume_connection (hr->con);
+ hr->suspended = GNUNET_NO;
return GNUNET_OK;
}
@@ -489,11 +530,23 @@ curl_download_cb (void *ptr,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Curl download proceeding\n");
- if (REQUEST_STATE_DOWNLOAD_STARTED != hr->state)
+ if ( (REQUEST_STATE_UPLOAD_STARTED == hr->state) ||
+ (REQUEST_STATE_UPLOAD_DONE == hr->state) )
+ {
+ /* we're still not done with the upload, do not yet
+ start the download, the IO buffer is still full
+ with upload data. */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Pausing CURL download, waiting for UPLOAD to finish\n");
+ hr->curl_paused = GNUNET_YES;
+ return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */
+ }
+
+ if (REQUEST_STATE_DOWNLOAD_STARTED != hr->state)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Download callback goes to sleep\n");
- hr->download_paused = GNUNET_YES;
+ hr->curl_paused = GNUNET_YES;
return CURL_WRITEFUNC_PAUSE;
}
@@ -509,7 +562,6 @@ curl_download_cb (void *ptr,
GNUNET_MAX (total + hr->io_len,
hr->io_size * 2 + 1024));
}
-
GNUNET_memcpy (&hr->io_buf[hr->io_len],
ptr,
total);
@@ -541,18 +593,33 @@ curl_upload_cb (void *buf,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Upload cb is working...\n");
- if (REQUEST_STATE_UPLOAD_STARTED != hr->state)
+ if ( (0 == hr->io_len) &&
+ (REQUEST_STATE_UPLOAD_DONE != hr->state) )
{
- GNUNET_break (0);
- return CURL_READFUNC_ABORT;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Pausing CURL UPLOAD, need more data\n");
+ return CURL_READFUNC_PAUSE;
}
- if (0 == hr->io_len)
+ if ( (0 == hr->io_len) &&
+ (REQUEST_STATE_UPLOAD_DONE == hr->state) )
{
hr->state = REQUEST_STATE_DOWNLOAD_STARTED;
+ if (GNUNET_YES == hr->curl_paused)
+ {
+ hr->curl_paused = GNUNET_NO;
+ curl_easy_pause (hr->curl,
+ CURLPAUSE_CONT);
+ }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Completed CURL UPLOAD\n");
return 0; /* upload finished, can now download */
}
+ if ( (REQUEST_STATE_UPLOAD_STARTED != hr->state) &&
+ (REQUEST_STATE_UPLOAD_DONE != hr->state) )
+ {
+ GNUNET_break (0);
+ return CURL_READFUNC_ABORT;
+ }
to_copy = GNUNET_MIN (hr->io_len,
len);
GNUNET_memcpy (buf,
@@ -697,7 +764,7 @@ curl_task_download (void *cls)
CURLINFO_PRIVATE,
(char **) &hr ));
- if (NULL == hr)
+ if (NULL == hr)
{
GNUNET_break (0);
continue;
@@ -719,6 +786,12 @@ curl_task_download (void *cls)
GNUNET_assert (GNUNET_OK ==
create_mhd_response_from_hr (hr));
hr->state = REQUEST_STATE_DOWNLOAD_DONE;
+ if (GNUNET_YES == hr->suspended)
+ {
+ MHD_resume_connection (hr->con);
+ hr->suspended = GNUNET_NO;
+ }
+ run_mhd_now ();
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -727,13 +800,18 @@ curl_task_download (void *cls)
/* FIXME: indicate error somehow?
* close MHD connection badly as well? */
hr->state = REQUEST_STATE_DOWNLOAD_DONE;
+ if (GNUNET_YES == hr->suspended)
+ {
+ MHD_resume_connection (hr->con);
+ hr->suspended = GNUNET_NO;
+ }
+ run_mhd_now ();
break;
}
if (NULL == hr->response)
hr->response = curl_failure_response;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Curl request for `%s' finished,"
- " response generated\n",
+ "Curl request for `%s' finished, response generated\n",
hr->url);
run_mhd_now ();
break;
@@ -765,6 +843,7 @@ curl_task_download (void *cls)
curl_download_prepare ();
}
+
static int
curl_progress_cb (void *clientp,
double dltotal,
@@ -776,21 +855,22 @@ curl_progress_cb (void *clientp,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Progress callback..\n");
-
- if ((GNUNET_YES == hr->download_paused)
- && (GNUNET_YES == hr->connection_closed))
+#if MARCELLO_FIX
+ if ( (GNUNET_YES == hr->curl_paused) &&
+ (GNUNET_YES == hr->connection_closed) )
{
hr->state = REQUEST_STATE_DOWNLOAD_STARTED;
- hr->download_paused = GNUNET_NO;
+ hr->curl_paused = GNUNET_NO;
hr->connection_closed = GNUNET_NO;
curl_easy_pause (hr->curl, CURLPAUSE_CONT);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Unpausing the download callback\n");
}
-
+#endif
return CURLE_OK;
}
+
/* *************** MHD response generation ******************* */
@@ -1173,8 +1253,8 @@ delete_object (struct MHD_Connection *con,
* value to the number of bytes NOT processed;
* @param con_cls pointer to location where we store the
* 'struct Request'
- * @return MHD_YES if the connection was handled successfully,
- * MHD_NO if the socket must be closed due to a serious
+ * @return #MHD_YES if the connection was handled successfully,
+ * #MHD_NO if the socket must be closed due to a serious
* error while handling the request
*/
static int
@@ -1238,11 +1318,24 @@ create_response (void *cls,
hr->io_len += *upload_data_size;
*upload_data_size = 0;
+ if (GNUNET_YES == hr->curl_paused)
+ {
+ hr->curl_paused = GNUNET_NO;
+ curl_easy_pause (hr->curl,
+ CURLPAUSE_CONT);
+ }
return MHD_YES;
}
- /* Upload (*from the client*) finished,
- * generate curl request to the proxied service. */
+ /* Upload (*from the client*) finished */
+ if (REQUEST_STATE_UPLOAD_STARTED == hr->state)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Finished processing UPLOAD\n");
+ hr->state = REQUEST_STATE_UPLOAD_DONE;
+ }
+
+ /* generate curl request to the proxied service. */
if (NULL == hr->curl)
{
/* Malform request body. Note, this flag will be
@@ -1273,7 +1366,7 @@ create_response (void *cls,
json_dumpb (hr->json,
hr->io_buf,
/* Existing io_len is enough to accomodate this encoding. */
- hr->io_len,
+ hr->io_len,
JSON_COMPACT);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1298,7 +1391,7 @@ create_response (void *cls,
json_dumpb (hr->json,
hr->io_buf,
/* Existing io_len is enough to accomodate this encoding. */
- hr->io_len,
+ hr->io_len,
JSON_COMPACT);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1549,7 +1642,11 @@ create_response (void *cls,
}
if (REQUEST_STATE_DOWNLOAD_DONE != hr->state)
+ {
+ MHD_suspend_connection (con);
+ hr->suspended = GNUNET_YES;
return MHD_YES; /* wait for curl */
+ }
if (0 != hack_response_code)
{
@@ -1570,7 +1667,8 @@ create_response (void *cls,
{
TALER_LOG_DEBUG ("Will delete path: %s\n",
delete_path);
- delete_object (con, hr);
+ delete_object (con,
+ hr);
}
if ('\0' != modify_path_dl[0])
@@ -1583,7 +1681,6 @@ create_response (void *cls,
modify_path_dl);
}
-
if (NULL != hr->json)
{
TALER_LOG_DEBUG ("Parsing final JSON.\n");
@@ -1623,6 +1720,7 @@ create_response (void *cls,
header->type,
header->value));
}
+ run_mhd_now ();
return MHD_queue_response (con,
hr->response_code,
hr->response);
@@ -1700,6 +1798,9 @@ mhd_completed_cb (void *cls,
GNUNET_free (hr->url);
GNUNET_free_non_null (hr->io_buf);
+ GNUNET_CONTAINER_DLL_remove (hr_head,
+ hr_tail,
+ hr);
GNUNET_free (hr);
*con_cls = NULL;
}
@@ -1739,7 +1840,11 @@ mhd_log_callback (void *cls,
}
hr = GNUNET_new (struct HttpRequest);
+ hr->con = connection;
hr->url = GNUNET_strdup (url);
+ GNUNET_CONTAINER_DLL_insert (hr_head,
+ hr_tail,
+ hr);
return hr;
}
@@ -1886,6 +1991,17 @@ do_shutdown (void *cls)
(void) cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Shutting down...\n");
+ /* MHD requires resuming before destroying the daemons */
+ for (struct HttpRequest *hr = hr_head;
+ NULL != hr;
+ hr = hr->next)
+ {
+ if (hr->suspended)
+ {
+ hr->suspended = GNUNET_NO;
+ MHD_resume_connection (hr->con);
+ }
+ }
kill_httpd ();
if (NULL != curl_multi)
{
@@ -2046,6 +2162,7 @@ send_acknowledgement (struct GNUNET_SERVICE_Client *c)
GNUNET_SERVICE_client_continue (c);
}
+
/**
* Control handler for malforming responses.
*
@@ -2063,6 +2180,7 @@ handle_malform (void *cls,
send_acknowledgement (c);
}
+
/**
* Control handler for malforming requests.
*
@@ -2080,6 +2198,7 @@ handle_malform_upload (void *cls,
send_acknowledgement (c);
}
+
/**
* Control handler for deleting JSON response objects
*
@@ -2094,7 +2213,6 @@ handle_modify_path_dl (void *cls,
strcpy (modify_path_dl, src->path);
strcpy (modify_value, src->value);
-
send_acknowledgement (c);
}
@@ -2114,10 +2232,10 @@ handle_modify_path_ul (void *cls,
strcpy (modify_path_ul, src->path);
strcpy (modify_value, src->value);
-
send_acknowledgement (c);
}
+
/**
* Control handler for flipping JSON strings into response objects
*
@@ -2151,6 +2269,7 @@ handle_flip_path_ul (void *cls,
send_acknowledgement (c);
}
+
/**
* Control handler for deleting JSON fields from response objects
*
@@ -2167,6 +2286,7 @@ handle_delete_path (void *cls,
send_acknowledgement (c);
}
+
/**
* Control handler for changing the response code
*