twister

HTTP fault injector for testing
Log | Files | Refs | README | LICENSE

commit 70b4d26fad5be9137e9938998c5e2ef450021aed
parent 01d82d833558e8c9079b1f30b95064a0b8989bcc
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat, 20 Jan 2018 17:55:03 +0100

proxy works

Diffstat:
Msrc/twister/taler-twister-service.c | 520++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/twister/twister.conf | 2+-
2 files changed, 277 insertions(+), 245 deletions(-)

diff --git a/src/twister/taler-twister-service.c b/src/twister/taler-twister-service.c @@ -22,7 +22,7 @@ * @author Martin Schanzenbach * @author Christian Grothoff * @author Marcello Stanisci - * @file src/twister/taler-twister.c + * @file src/twister/taler-twister-service.c * @brief HTTP proxy that acts as a man in the middle making changes to * requests or responses */ @@ -38,13 +38,6 @@ /** - * Size of the buffer for the data upload / download. Must be - * enough for curl, thus CURL_MAX_WRITE_SIZE is needed here (16k). - */ -#define IO_BUFFERSIZE CURL_MAX_WRITE_SIZE - - -/** * Log curl error. * * @param level log level @@ -73,11 +66,6 @@ enum RequestState REQUEST_STATE_UPLOAD_STARTED, /** - * We've finished receiving upload data from MHD. - */ - REQUEST_STATE_UPLOAD_DONE, - - /** * We've finished uploading data via CURL and can now download. */ REQUEST_STATE_DOWNLOAD_STARTED, @@ -136,7 +124,7 @@ struct HttpRequest /** * Buffer we use for moving data between MHD and curl (in both directions). */ - char io_buf[IO_BUFFERSIZE]; + char *io_buf; /** * MHD response object for this request. @@ -159,9 +147,14 @@ struct HttpRequest struct curl_slist *headers; /** - * HTTP response code to give to MHD for the response. + * Headers from response */ - unsigned int response_code; + struct HttpResponseHeader *header_head; + + /** + * Headers from response + */ + struct HttpResponseHeader *header_tail; /** * Number of bytes already in the IO buffer. @@ -169,14 +162,14 @@ struct HttpRequest size_t io_len; /** - * Headers from response + * HTTP response code to give to MHD for the response. */ - struct HttpResponseHeader *header_head; + unsigned int response_code; /** - * Headers from response + * Number of bytes allocated for the IO buffer. */ - struct HttpResponseHeader *header_tail; + unsigned int io_size; /** * Request processing state machine. @@ -248,75 +241,6 @@ run_mhd_now (void); /* ************************* HTTP handling with cURL *********************** */ -static void -curl_download_prepare (); - - -/** - * Callback for MHD response generation. This function is called from - * MHD whenever MHD expects to get data back. Copies data from the - * io_buf, if available. - * - * @param cls closure with our `struct HttpRequest` - * @param pos in buffer - * @param buf where to copy data - * @param max available space in @a buf - * @return number of bytes written to @a buf - */ -static ssize_t -mhd_content_cb (void *cls, - uint64_t pos, - char* buf, - size_t max) -{ - struct HttpRequest *hr = cls; - size_t bytes_to_copy; - - 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 MHD download, not yet ready for download\n"); - return 0; /* not yet ready for data download */ - } - bytes_to_copy = GNUNET_MIN (max, - hr->io_len); - if ( (0 == bytes_to_copy) && - (REQUEST_STATE_DOWNLOAD_DONE != hr->state) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Pausing MHD download, no data available\n"); - if (NULL != hr->curl) - { - curl_easy_pause (hr->curl, CURLPAUSE_CONT); - curl_download_prepare (); - } - return 0; /* more data later */ - } - if ( (0 == bytes_to_copy) && - (REQUEST_STATE_DOWNLOAD_DONE == hr->state) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Completed MHD download\n"); - return MHD_CONTENT_READER_END_OF_STREAM; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Writing %lu/%lu bytes\n", - (unsigned long) bytes_to_copy, - (unsigned long) hr->io_len); - GNUNET_memcpy (buf, hr->io_buf, bytes_to_copy); - memmove (hr->io_buf, - &hr->io_buf[bytes_to_copy], - hr->io_len - bytes_to_copy); - hr->io_len -= bytes_to_copy; - if (NULL != hr->curl) - curl_easy_pause (hr->curl, CURLPAUSE_CONT); - return bytes_to_copy; -} - /** * We're getting an HTTP response header from cURL. Convert it to the @@ -330,7 +254,10 @@ mhd_content_cb (void *cls, * @return size of processed bytes */ static size_t -curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) +curl_check_hdr (void *buffer, + size_t size, + size_t nmemb, + void *cls) { struct HttpRequest *hr = cls; struct HttpResponseHeader *header; @@ -356,6 +283,23 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) if (' ' == *hdr_val) hdr_val++; + /* Skip "Host:" header as it will be wrong, given + that we are man-in-the-middling the connection */ + if (0 == strcasecmp (hdr_type, + MHD_HTTP_HEADER_HOST)) + { + GNUNET_free (ndup); + return bytes; + } + /* Skip "Content-length:" header as it will be wrong, given + that we are man-in-the-middling the connection */ + if (0 == strcasecmp (hdr_type, + MHD_HTTP_HEADER_CONTENT_LENGTH)) + { + GNUNET_free (ndup); + return bytes; + } + /* custom logic for certain header types */ #if 0 char *new_location; @@ -449,8 +393,8 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) hdr_type, hdr_val); header = GNUNET_new (struct HttpResponseHeader); - header->type = GNUNET_strndup (hdr_type, strlen (hdr_type)); - header->value = GNUNET_strndup (hdr_val, strlen (hdr_val)); + header->type = GNUNET_strdup (hdr_type); + header->value = GNUNET_strdup (hdr_val); GNUNET_CONTAINER_DLL_insert (hr->header_head, hr->header_tail, header); @@ -460,11 +404,13 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) } +/** + * FIXME: document + */ static int create_mhd_response_from_hr (struct HttpRequest *hr) { long resp_code; - double content_length; struct HttpResponseHeader *header; if (NULL != hr->response) @@ -478,26 +424,23 @@ create_mhd_response_from_hr (struct HttpRequest *hr) curl_easy_getinfo (hr->curl, CURLINFO_RESPONSE_CODE, &resp_code)); - GNUNET_break (CURLE_OK == - curl_easy_getinfo (hr->curl, - CURLINFO_CONTENT_LENGTH_DOWNLOAD, - &content_length)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating MHD response with code %d and size %d\n", - (int) resp_code, (int) content_length); + "Creating MHD response with code %u\n", + (unsigned int) resp_code); hr->response_code = resp_code; - hr->response = MHD_create_response_from_callback ((-1 == content_length) ? MHD_SIZE_UNKNOWN : content_length, - IO_BUFFERSIZE, - &mhd_content_cb, - hr, - NULL); + hr->response = MHD_create_response_from_buffer (hr->io_len, + hr->io_buf, + MHD_RESPMEM_MUST_COPY); for (header = hr->header_head; NULL != header; header = header->next) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding MHD response header %s->%s\n", + header->type, + header->value); GNUNET_break (MHD_YES == MHD_add_response_header (hr->response, header->type, header->value)); - } #if 0 if (NULL != hr->leho) @@ -517,15 +460,10 @@ create_mhd_response_from_hr (struct HttpRequest *hr) GNUNET_free (cors_hdr); } #endif - /* force connection to be closed after each request, as we - do not support HTTP pipelining (yet, FIXME!) */ - /*GNUNET_break (MHD_YES == - MHD_add_response_header (hr->response, - MHD_HTTP_HEADER_CONNECTION, - "close"));*/ return GNUNET_OK; } + /** * Handle response payload data from cURL. Copies it into our `io_buf` to make * it available to MHD. @@ -537,46 +475,37 @@ create_mhd_response_from_hr (struct HttpRequest *hr) * @return number of bytes handled */ static size_t -curl_download_cb (void *ptr, size_t size, size_t nmemb, void* ctx) +curl_download_cb (void *ptr, + size_t size, + size_t nmemb, + void* ctx) { struct HttpRequest *hr = ctx; size_t total = size * nmemb; - if (NULL == hr->response) - GNUNET_assert (GNUNET_OK == create_mhd_response_from_hr (hr)); - - 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"); - return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */ - } - if (sizeof (hr->io_buf) - hr->io_len < total) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Curl download proceeding\n"); + GNUNET_assert (REQUEST_STATE_DOWNLOAD_STARTED == hr->state); + if (hr->io_size - hr->io_len < total) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Pausing CURL download, not enough space %lu %lu %lu\n", - (unsigned long) sizeof (hr->io_buf), - (unsigned long) hr->io_len, - (unsigned long) total); - return CURL_WRITEFUNC_PAUSE; /* not enough space */ + GNUNET_assert (total + hr->io_size >= total); + GNUNET_assert (hr->io_size * 2 + 1024 > hr->io_size); + GNUNET_array_grow (hr->io_buf, + hr->io_size, + GNUNET_MAX (total + hr->io_len, + hr->io_size * 2 + 1024)); } GNUNET_memcpy (&hr->io_buf[hr->io_len], ptr, total); hr->io_len += total; - if (hr->io_len == total) - run_mhd_now (); return total; } /** - * cURL callback for uploaded (PUT/POST) data. Copies it into our `io_buf` - * to make it available to MHD. + * cURL callback for uploaded (PUT/POST) data. Copies from our `io_buf` + * to make it available to curl. * * @param buf where to write the data * @param size number of bytes per member @@ -585,42 +514,42 @@ curl_download_cb (void *ptr, size_t size, size_t nmemb, void* ctx) * @return number of bytes copied to @a buf */ static size_t -curl_upload_cb (void *buf, size_t size, size_t nmemb, void *cls) +curl_upload_cb (void *buf, + size_t size, + size_t nmemb, + void *cls) { struct HttpRequest *hr = cls; size_t len = size * nmemb; size_t to_copy; - if ( (0 == hr->io_len) && - (REQUEST_STATE_UPLOAD_DONE != hr->state) ) + if (REQUEST_STATE_UPLOAD_STARTED != hr->state) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Pausing CURL UPLOAD, need more data\n"); - return CURL_READFUNC_PAUSE; + GNUNET_break (0); + return CURL_READFUNC_ABORT; } - if ( (0 == hr->io_len) && - (REQUEST_STATE_UPLOAD_DONE == hr->state) ) + if (0 == hr->io_len) { hr->state = REQUEST_STATE_DOWNLOAD_STARTED; 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, hr->io_buf, to_copy); + GNUNET_memcpy (buf, + hr->io_buf, + to_copy); memmove (hr->io_buf, &hr->io_buf[to_copy], hr->io_len - to_copy); hr->io_len -= to_copy; - if (hr->io_len + to_copy == sizeof (hr->io_buf)) - run_mhd_now (); /* got more space for upload now */ + if (0 == hr->io_len) + { + hr->state = REQUEST_STATE_DOWNLOAD_STARTED; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Completed CURL UPLOAD\n"); + } return to_copy; } @@ -663,16 +592,24 @@ curl_download_prepare () FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); - if (CURLM_OK != (mret = curl_multi_fdset (curl_multi, &rs, &ws, &es, &max))) + if (CURLM_OK != (mret = curl_multi_fdset (curl_multi, + &rs, + &ws, + &es, + &max))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s failed at %s:%d: `%s'\n", - "curl_multi_fdset", __FILE__, __LINE__, + "curl_multi_fdset", + __FILE__, + __LINE__, curl_multi_strerror (mret)); return; } to = -1; - GNUNET_break (CURLM_OK == curl_multi_timeout (curl_multi, &to)); + GNUNET_break (CURLM_OK == + curl_multi_timeout (curl_multi, + &to)); if (-1 == to) rtime = GNUNET_TIME_UNIT_FOREVER_REL; else @@ -681,12 +618,17 @@ curl_download_prepare () { grs = GNUNET_NETWORK_fdset_create (); gws = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); - GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); + GNUNET_NETWORK_fdset_copy_native (grs, + &rs, + max + 1); + GNUNET_NETWORK_fdset_copy_native (gws, + &ws, + max + 1); curl_download_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, rtime, grs, gws, - &curl_task_download, curl_multi); + &curl_task_download, + curl_multi); GNUNET_NETWORK_fdset_destroy (gws); GNUNET_NETWORK_fdset_destroy (grs); } @@ -713,12 +655,17 @@ curl_task_download (void *cls) CURLMcode mret; struct HttpRequest *hr; + (void) cls; curl_download_task = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Running curl interaction\n"); do { running = 0; - mret = curl_multi_perform (curl_multi, &running); - while (NULL != (msg = curl_multi_info_read (curl_multi, &msgnum))) + mret = curl_multi_perform (curl_multi, + &running); + while (NULL != (msg = curl_multi_info_read (curl_multi, + &msgnum))) { GNUNET_break (CURLE_OK == curl_easy_getinfo (msg->easy_handle, @@ -743,9 +690,9 @@ curl_task_download (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CURL download completed.\n"); if (NULL == hr->response) - GNUNET_assert (GNUNET_OK == create_mhd_response_from_hr (hr)); + GNUNET_assert (GNUNET_OK == + create_mhd_response_from_hr (hr)); hr->state = REQUEST_STATE_DOWNLOAD_DONE; - run_mhd_now (); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -753,11 +700,14 @@ curl_task_download (void *cls) curl_easy_strerror (msg->data.result)); /* FIXME: indicate error somehow? close MHD connection badly as well? */ hr->state = REQUEST_STATE_DOWNLOAD_DONE; - 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", + hr->url); + run_mhd_now (); break; case CURLMSG_LAST: /* documentation says this is not used */ @@ -773,7 +723,9 @@ curl_task_download (void *cls) if (CURLM_OK != mret) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s failed at %s:%d: `%s'\n", - "curl_multi_perform", __FILE__, __LINE__, + "curl_multi_perform", + __FILE__, + __LINE__, curl_multi_strerror (mret)); if (0 == running) { @@ -808,6 +760,7 @@ con_val_iter (void *cls, struct HttpRequest *hr = cls; char *hdr; + (void) kind; #if 0 if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST, key)) && (NULL != hr->leho) ) @@ -861,89 +814,170 @@ create_response (void *cls, void **con_cls) { struct HttpRequest *hr = *con_cls; - char *curlurl; - size_t left; + (void) cls; + (void) url; if (NULL == hr) { GNUNET_break (0); return MHD_NO; } - //Fresh connection. + if (REQUEST_STATE_WITH_MHD == hr->state) { - if (NULL == hr->curl) - hr->curl = curl_easy_init (); + hr->state = REQUEST_STATE_UPLOAD_STARTED; + /* TODO: hacks for 100 continue suppression would go here! */ + return MHD_YES; + } + + /* continuing to process request */ + if (0 != *upload_data_size) + { + GNUNET_assert (REQUEST_STATE_UPLOAD_STARTED == hr->state); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Processing %u bytes UPLOAD\n", + (unsigned int) *upload_data_size); + if (hr->io_size - hr->io_len < *upload_data_size) + { + GNUNET_assert (hr->io_size * 2 + 1024 > hr->io_size); + GNUNET_assert (*upload_data_size + hr->io_len > hr->io_len); + GNUNET_array_grow (hr->io_buf, + hr->io_size, + GNUNET_MAX (hr->io_size * 2 + 1024, + *upload_data_size + hr->io_len)); + } + GNUNET_memcpy (&hr->io_buf[hr->io_len], + upload_data, + *upload_data_size); + hr->io_len += *upload_data_size; + *upload_data_size = 0; + return MHD_YES; + } + + /* Upload finished, generate curl request */ + if (NULL == hr->curl) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Generating curl request\n"); + hr->curl = curl_easy_init (); if (NULL == hr->curl) return MHD_queue_response (con, MHD_HTTP_INTERNAL_SERVER_ERROR, curl_failure_response); + if (0 != hr->io_len) + curl_easy_setopt (hr->curl, + CURLOPT_POSTFIELDSIZE, + hr->io_len); curl_easy_setopt (hr->curl, CURLOPT_HEADERFUNCTION, &curl_check_hdr); - curl_easy_setopt (hr->curl, CURLOPT_HEADERDATA, hr); - curl_easy_setopt (hr->curl, CURLOPT_FOLLOWLOCATION, 0); - curl_easy_setopt (hr->curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - curl_easy_setopt (hr->curl, CURLOPT_CONNECTTIMEOUT, 600L); - curl_easy_setopt (hr->curl, CURLOPT_TIMEOUT, 600L); - curl_easy_setopt (hr->curl, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt (hr->curl, CURLOPT_HTTP_CONTENT_DECODING, 0); - curl_easy_setopt (hr->curl, CURLOPT_HTTP_TRANSFER_DECODING, 0); - curl_easy_setopt (hr->curl, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt (hr->curl, CURLOPT_PRIVATE, hr); - curl_easy_setopt (hr->curl, CURLOPT_VERBOSE, 0); - GNUNET_asprintf (&curlurl, - "%s%s", - target_server_base_url, - hr->url); curl_easy_setopt (hr->curl, - CURLOPT_URL, - curlurl); - GNUNET_free (curlurl); - if (0 == strcasecmp (meth, MHD_HTTP_METHOD_PUT)) + CURLOPT_HEADERDATA, + hr); + curl_easy_setopt (hr->curl, + CURLOPT_FOLLOWLOCATION, + 0); + curl_easy_setopt (hr->curl, + CURLOPT_CONNECTTIMEOUT, + 600L); + curl_easy_setopt (hr->curl, + CURLOPT_TIMEOUT, + 600L); + curl_easy_setopt (hr->curl, + CURLOPT_NOSIGNAL, + 1L); + curl_easy_setopt (hr->curl, + CURLOPT_HTTP_CONTENT_DECODING, + 0); + curl_easy_setopt (hr->curl, + CURLOPT_HTTP_TRANSFER_DECODING, + 0); + curl_easy_setopt (hr->curl, + CURLOPT_PRIVATE, + hr); + curl_easy_setopt (hr->curl, + CURLOPT_VERBOSE, + 0); { - hr->state = REQUEST_STATE_UPLOAD_STARTED; - curl_easy_setopt (hr->curl, CURLOPT_UPLOAD, 1); + char *curlurl; + + GNUNET_asprintf (&curlurl, + "%s%s", + target_server_base_url, + hr->url); curl_easy_setopt (hr->curl, - CURLOPT_WRITEFUNCTION, - &curl_download_cb); - curl_easy_setopt (hr->curl, CURLOPT_WRITEDATA, hr); + CURLOPT_URL, + curlurl); + GNUNET_free (curlurl); + } + if (0 == strcasecmp (meth, + MHD_HTTP_METHOD_PUT)) + { + curl_easy_setopt (hr->curl, + CURLOPT_UPLOAD, + 1L); curl_easy_setopt (hr->curl, CURLOPT_READFUNCTION, &curl_upload_cb); - curl_easy_setopt (hr->curl, CURLOPT_READDATA, hr); + curl_easy_setopt (hr->curl, + CURLOPT_READDATA, + hr); + curl_easy_setopt (hr->curl, + CURLOPT_WRITEFUNCTION, + &curl_download_cb); + curl_easy_setopt (hr->curl, + CURLOPT_WRITEDATA, + hr); } - else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) + else if (0 == strcasecmp (meth, + MHD_HTTP_METHOD_POST)) { hr->state = REQUEST_STATE_UPLOAD_STARTED; - curl_easy_setopt (hr->curl, CURLOPT_POST, 1L); curl_easy_setopt (hr->curl, - CURLOPT_WRITEFUNCTION, - &curl_download_cb); - curl_easy_setopt (hr->curl, CURLOPT_WRITEDATA, hr); + CURLOPT_POST, + 1L); curl_easy_setopt (hr->curl, CURLOPT_READFUNCTION, &curl_upload_cb); - curl_easy_setopt (hr->curl, CURLOPT_READDATA, hr); + curl_easy_setopt (hr->curl, + CURLOPT_READDATA, + hr); + curl_easy_setopt (hr->curl, + CURLOPT_WRITEFUNCTION, + &curl_download_cb); + curl_easy_setopt (hr->curl, + CURLOPT_WRITEDATA, + hr); } - else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD)) + else if (0 == strcasecmp (meth, + MHD_HTTP_METHOD_HEAD)) { hr->state = REQUEST_STATE_DOWNLOAD_STARTED; - curl_easy_setopt (hr->curl, CURLOPT_NOBODY, 1); + curl_easy_setopt (hr->curl, + CURLOPT_NOBODY, + 1L); } - else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_OPTIONS)) + else if (0 == strcasecmp (meth, + MHD_HTTP_METHOD_OPTIONS)) { hr->state = REQUEST_STATE_DOWNLOAD_STARTED; - curl_easy_setopt (hr->curl, CURLOPT_CUSTOMREQUEST, "OPTIONS"); + curl_easy_setopt (hr->curl, + CURLOPT_CUSTOMREQUEST, + "OPTIONS"); } - else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_GET)) + else if (0 == strcasecmp (meth, + MHD_HTTP_METHOD_GET)) { hr->state = REQUEST_STATE_DOWNLOAD_STARTED; - curl_easy_setopt (hr->curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt (hr->curl, + CURLOPT_HTTPGET, + 1L); curl_easy_setopt (hr->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); - curl_easy_setopt (hr->curl, CURLOPT_WRITEDATA, hr); + curl_easy_setopt (hr->curl, + CURLOPT_WRITEDATA, + hr); } else { @@ -955,20 +989,29 @@ create_response (void *cls, return MHD_NO; } - if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_0)) + if (0 == strcasecmp (ver, + MHD_HTTP_VERSION_1_0)) { - curl_easy_setopt (hr->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (hr->curl, + CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_1_0); } - else if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_1)) + else if (0 == strcasecmp (ver, + MHD_HTTP_VERSION_1_1)) { - curl_easy_setopt (hr->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_easy_setopt (hr->curl, + CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_1_1); } else { - curl_easy_setopt (hr->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE); + curl_easy_setopt (hr->curl, + CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_NONE); } - if (CURLM_OK != curl_multi_add_handle (curl_multi, hr->curl)) + if (CURLM_OK != curl_multi_add_handle (curl_multi, + hr->curl)) { GNUNET_break (0); curl_easy_cleanup (hr->curl); @@ -983,44 +1026,22 @@ create_response (void *cls, CURLOPT_HTTPHEADER, hr->headers); curl_download_prepare (); + if (0 == hr->io_len) + hr->state = REQUEST_STATE_DOWNLOAD_STARTED; return MHD_YES; } - /* continuing to process request */ - if (0 != *upload_data_size) + if (REQUEST_STATE_DOWNLOAD_DONE != hr->state) + return MHD_YES; /* wait for curl */ + + if (NULL == hr->response) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Processing %u bytes UPLOAD\n", - (unsigned int) *upload_data_size); - - /* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else - * upload callback is not called! - */ - curl_easy_setopt (hr->curl, CURLOPT_POSTFIELDSIZE, *upload_data_size); - - left = GNUNET_MIN (*upload_data_size, - sizeof (hr->io_buf) - hr->io_len); - GNUNET_memcpy (&hr->io_buf[hr->io_len], - upload_data, - left); - hr->io_len += left; - *upload_data_size -= left; - GNUNET_assert (NULL != hr->curl); - curl_easy_pause (hr->curl, CURLPAUSE_CONT); + "Still waiting for response to be ready\n"); return MHD_YES; } - if (REQUEST_STATE_UPLOAD_STARTED == hr->state) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Finished processing UPLOAD\n"); - hr->state = REQUEST_STATE_UPLOAD_DONE; - } - if (NULL == hr->response) - return MHD_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing response with MHD\n"); - run_mhd_now (); if (0 != hack_response_code) { hr->response_code = hack_response_code; @@ -1053,6 +1074,8 @@ mhd_completed_cb (void *cls, struct HttpRequest *hr = *con_cls; struct HttpResponseHeader *header; + (void) cls; + (void) connection; if (NULL == hr) return; if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe) @@ -1086,6 +1109,7 @@ mhd_completed_cb (void *cls, "Finished request for %s\n", hr->url); GNUNET_free (hr->url); + GNUNET_free_non_null (hr->io_buf); GNUNET_free (hr); *con_cls = NULL; } @@ -1112,6 +1136,7 @@ mhd_log_callback (void *cls, struct HttpRequest *hr; const union MHD_ConnectionInfo *ci; + (void) cls; ci = MHD_get_connection_info (connection, MHD_CONNECTION_INFO_SOCKET_CONTEXT); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1235,6 +1260,7 @@ schedule_httpd (void) static void do_httpd (void *cls) { + (void) cls; httpd_task = NULL; MHD_run (mhd_daemon); schedule_httpd (); @@ -1265,6 +1291,7 @@ run_mhd_now (void) static void do_shutdown (void *cls) { + (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n"); kill_httpd (); @@ -1386,6 +1413,8 @@ client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq) { + (void) cls; + (void) mq; return c; } @@ -1403,6 +1432,9 @@ client_disconnect_cb (void *cls, void *internal_cls) { /* intentionally empty */ + (void) cls; + (void) c; + (void) internal_cls; } @@ -1457,4 +1489,4 @@ GNUNET_SERVICE_MAIN GNUNET_MQ_handler_end ()); -/* end of taler-twister.c */ +/* end of taler-twister-service.c */ diff --git a/src/twister/twister.conf b/src/twister/twister.conf @@ -13,7 +13,7 @@ ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; # Control port for UNIX -UNIXPATH = $TALER_RUNTIME_DIR/taler-service-twister.sock +UNIXPATH = /tmp/taler-service-twister.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES