[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] branch master updated: test_long_header: improved, fixed
From: |
gnunet |
Subject: |
[libmicrohttpd] branch master updated: test_long_header: improved, fixed, added error reporting |
Date: |
Wed, 27 Sep 2023 16:44:45 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
The following commit(s) were added to refs/heads/master by this push:
new 78e28ecc test_long_header: improved, fixed, added error reporting
78e28ecc is described below
commit 78e28ecca82bafbe4569c8e9c5307853a4a8dbdf
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Wed Sep 27 17:44:21 2023 +0300
test_long_header: improved, fixed, added error reporting
---
src/testcurl/test_long_header.c | 470 +++++++++++++++++++++++++++++-----------
1 file changed, 339 insertions(+), 131 deletions(-)
diff --git a/src/testcurl/test_long_header.c b/src/testcurl/test_long_header.c
index 30744934..15469147 100644
--- a/src/testcurl/test_long_header.c
+++ b/src/testcurl/test_long_header.c
@@ -1,7 +1,7 @@
/*
This file is part of libmicrohttpd
Copyright (C) 2007 Christian Grothoff
- Copyright (C) 2016-2022 Evgeny Grin (Karlson2k)
+ Copyright (C) 2016-2023 Evgeny Grin (Karlson2k)
libmicrohttpd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -26,11 +26,12 @@
* @author Karlson2k (Evgeny Grin)
*/
-#include "MHD_config.h"
+#include "mhd_options.h"
#include "platform.h"
#include <curl/curl.h>
#include <microhttpd.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mhd_has_in_name.h"
@@ -39,6 +40,21 @@
#include <unistd.h>
#endif
+#ifndef MHD_STATICSTR_LEN_
+/**
+ * Determine length of static string / macro strings at compile time.
+ */
+#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
+#endif /* ! MHD_STATICSTR_LEN_ */
+
+#ifndef CURL_VERSION_BITS
+#define CURL_VERSION_BITS(x,y,z) ((x) << 16 | (y) << 8 | (z))
+#endif /* ! CURL_VERSION_BITS */
+#ifndef CURL_AT_LEAST_VERSION
+#define CURL_AT_LEAST_VERSION(x,y,z) \
+ (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS (x, y, z))
+#endif /* ! CURL_AT_LEAST_VERSION */
+
/**
* We will set the memory available per connection to
* half of this value, so the actual value does not have
@@ -46,17 +62,24 @@
*/
#define VERY_LONG (1024 * 8)
+/* Could be increased to facilitate debugging */
+#define TIMEOUTS_VAL 5
+
+#define EXPECTED_URI_BASE_PATH "/"
+
+#define URL_SCHEME "http:/" "/"
+
+#define URL_HOST "127.0.0.1"
+
+#define URL_SCHEME_HOST_PATH URL_SCHEME URL_HOST EXPECTED_URI_BASE_PATH
+
+
static int oneone;
static uint16_t daemon_port;
-static enum MHD_Result
-apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
-{
- (void) cls; (void) addr; (void) addrlen; /* Unused. Silent compiler
warning. */
- return MHD_YES;
-}
+static char libcurl_err_buf[CURL_ERROR_SIZE];
struct CBC
{
@@ -73,6 +96,132 @@ copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
}
+/* Return non-zero on success, zero on failure */
+static int
+setup_easy_handler_params (CURL *c, struct CBC *pcbc, const char *url,
+ struct curl_slist *header)
+{
+ libcurl_err_buf[0] = 0; /* Reset error message */
+
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_ERRORBUFFER, libcurl_err_buf))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_ERRORBUFFER option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_NOSIGNAL option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEFUNCTION,
+ ©Buffer))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_WRITEFUNCTION option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEDATA, pcbc))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_WRITEDATA option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT,
+ ((long) TIMEOUTS_VAL)))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_CONNECTTIMEOUT option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_TIMEOUT,
+ ((long) TIMEOUTS_VAL)))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_TIMEOUT option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTP_VERSION,
+ (oneone) ?
+ CURL_HTTP_VERSION_1_1 :
+ CURL_HTTP_VERSION_1_0))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_HTTP_VERSION option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_FAILONERROR, 0L))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_FAILONERROR option.\n");
+ return 0;
+ }
+#ifdef _DEBUG
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_VERBOSE, 1L))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_VERBOSE option.\n");
+ return 0;
+ }
+#endif /* _DEBUG */
+#if CURL_AT_LEAST_VERSION (7, 45, 0)
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_DEFAULT_PROTOCOL, "http"))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_DEFAULT_PROTOCOL option.\n");
+ return 0;
+ }
+#endif /* CURL_AT_LEAST_VERSION (7, 45, 0) */
+#if CURL_AT_LEAST_VERSION (7, 85, 0)
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_PROTOCOLS_STR, "http"))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_PROTOCOLS_STR option.\n");
+ return 0;
+ }
+#elif CURL_AT_LEAST_VERSION (7, 19, 4)
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_PROTOCOLS option.\n");
+ return 0;
+ }
+#endif /* CURL_AT_LEAST_VERSION (7, 19, 4) */
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_URL,
+ (NULL != url) ?
+ url : URL_SCHEME_HOST_PATH))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_PROTOCOLS option.\n");
+ return 0;
+ }
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_PORT, ((long) daemon_port)))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_PROTOCOLS option.\n");
+ return 0;
+ }
+
+ if (NULL != header)
+ {
+ if (CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTPHEADER, header))
+ {
+ fprintf (stderr, "Failed to set CURLOPT_HTTPHEADER option.\n");
+ return 0;
+ }
+ }
+ return ! 0;
+}
+
+
+static CURL *
+setup_easy_handler (struct CBC *pcbc, const char *url, struct
+ curl_slist *header)
+{
+ CURL *c;
+
+ c = curl_easy_init ();
+ if (NULL == c)
+ {
+ fprintf (stderr, "curl_easy_init() error.\n");
+ return NULL;
+ }
+ if (setup_easy_handler_params (c, pcbc, url, header))
+ {
+ return c; /* Success exit point */
+ }
+ curl_easy_cleanup (c);
+ return NULL;
+}
+
+
static enum MHD_Result
ahc_echo (void *cls,
struct MHD_Connection *connection,
@@ -84,10 +233,17 @@ ahc_echo (void *cls,
{
struct MHD_Response *response;
enum MHD_Result ret;
+ static int marker;
+
(void) cls;
(void) version; (void) upload_data; /* Unused. Silent compiler warning.
*/
(void) upload_data_size; (void) req_cls; /* Unused. Silent compiler warning.
*/
+ if (&marker != *req_cls)
+ {
+ *req_cls = ▮
+ return MHD_YES;
+ }
if (0 != strcmp (MHD_HTTP_METHOD_GET, method))
return MHD_NO; /* unexpected method */
response = MHD_create_response_from_buffer_copy (strlen (url),
@@ -102,81 +258,106 @@ static unsigned int
testLongUrlGet (size_t buff_size)
{
struct MHD_Daemon *d;
- CURL *c;
- char buf[2048];
- struct CBC cbc;
- char *url;
- long code;
-
- cbc.buf = buf;
- cbc.size = 2048;
- cbc.pos = 0;
+ unsigned int ret;
+
+ ret = 1; /* Error value, shall be reset to zero if succeed */
d =
MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
daemon_port,
- &apc_all,
+ NULL,
NULL,
&ahc_echo, NULL,
MHD_OPTION_CONNECTION_MEMORY_LIMIT,
(size_t) buff_size, MHD_OPTION_END);
if (d == NULL)
- return 1;
+ {
+ fprintf (stderr, "MHD_start_daemon() failed.\n");
+ return 16;
+ }
if (0 == daemon_port)
{
const union MHD_DaemonInfo *dinfo;
dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
if ((NULL == dinfo) || (0 == dinfo->port) )
- {
- MHD_stop_daemon (d); return 32;
- }
- daemon_port = dinfo->port;
- }
- c = curl_easy_init ();
- url = malloc (VERY_LONG);
- if (NULL == url)
- {
- curl_easy_cleanup (c);
- MHD_stop_daemon (d);
- return 1;
- }
- memset (url, 'a', VERY_LONG);
- url[VERY_LONG - 1] = '\0';
- memcpy (url, "http://127.0.0.1/", strlen ("http://127.0.0.1/"));
- curl_easy_setopt (c, CURLOPT_URL, url);
- curl_easy_setopt (c, CURLOPT_PORT, (long) daemon_port);
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 0L);
- curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
- curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
- if (oneone)
- curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
- else
- curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
- /* NOTE: use of CONNECTTIMEOUT without also
- setting NOSIGNAL results in really weird
- crashes on my system! */
- curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
- if (CURLE_OK != curl_easy_perform (c))
- {
- curl_easy_cleanup (c);
- MHD_stop_daemon (d);
- free (url);
- return 2;
+ fprintf (stderr, "MHD_get_daemon_info(d, MHD_DAEMON_INFO_BIND_PORT) " \
+ "failed.\n");
+ else
+ daemon_port = dinfo->port;
}
- if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+ if (0 != daemon_port)
{
- curl_easy_cleanup (c);
- MHD_stop_daemon (d);
- free (url);
- return 4;
+ char *url_str;
+ url_str = malloc (VERY_LONG);
+ if (NULL == url_str)
+ fprintf (stderr, "malloc (VERY_LONG) failed.\n");
+ else
+ {
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+
+ memset (url_str, 'a', VERY_LONG);
+ url_str[VERY_LONG - 1] = '\0';
+ memcpy (url_str, URL_SCHEME_HOST_PATH,
+ MHD_STATICSTR_LEN_ (URL_SCHEME_HOST_PATH));
+
+ cbc.buf = buf;
+ cbc.size = sizeof (buf);
+ cbc.pos = 0;
+
+ c = setup_easy_handler (&cbc, url_str, NULL);
+ if (NULL != c)
+ {
+ CURLcode r;
+ r = curl_easy_perform (c);
+ if (CURLE_OK != r)
+ {
+ fprintf (stderr, "curl_easy_perform() failed. Error message: %s\n",
+ curl_easy_strerror (r));
+ if (0 != libcurl_err_buf[0])
+ fprintf (stderr, "Detailed error message: %s\n", libcurl_err_buf);
+ }
+ else
+ {
+ long code;
+
+ r = curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code);
+ if (CURLE_OK != r)
+ {
+ fprintf (stderr, "curl_easy_getinfo() failed. "
+ "Error message: %s\n",
+ curl_easy_strerror (r));
+ if (0 != libcurl_err_buf[0])
+ fprintf (stderr, "Detailed error message: %s\n",
+ libcurl_err_buf);
+ }
+ else
+ {
+ if (code != MHD_HTTP_URI_TOO_LONG)
+ {
+ fprintf (stderr, "testLongHeaderGet(%lu) failed. HTTP "
+ "response code is %ld, while it should be %ld.\n",
+ (unsigned long) buff_size,
+ code,
+ (long) MHD_HTTP_URI_TOO_LONG);
+ }
+ else
+ {
+ printf ("testLongHeaderGet(%lu) succeed. HTTP "
+ "response code is %ld, as expected.\n",
+ (unsigned long) buff_size,
+ (long) MHD_HTTP_URI_TOO_LONG);
+ ret = 0; /* Success */
+ }
+ }
+ }
+ curl_easy_cleanup (c);
+ }
+ free (url_str);
+ }
}
- curl_easy_cleanup (c);
MHD_stop_daemon (d);
- free (url);
- if (code != MHD_HTTP_URI_TOO_LONG)
- return 8;
- return 0;
+ return ret;
}
@@ -184,89 +365,115 @@ static unsigned int
testLongHeaderGet (size_t buff_size)
{
struct MHD_Daemon *d;
- CURL *c;
- char buf[2048];
- struct CBC cbc;
- char *url;
- long code;
- struct curl_slist *header = NULL;
-
- cbc.buf = buf;
- cbc.size = 2048;
- cbc.pos = 0;
+ unsigned int ret;
+
+ ret = 1; /* Error value, shall be reset to zero if succeed */
d =
MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG
*/,
daemon_port,
- &apc_all,
+ NULL,
NULL,
&ahc_echo, NULL,
MHD_OPTION_CONNECTION_MEMORY_LIMIT,
(size_t) buff_size, MHD_OPTION_END);
if (d == NULL)
+ {
+ fprintf (stderr, "MHD_start_daemon() failed.\n");
return 16;
+ }
if (0 == daemon_port)
{
const union MHD_DaemonInfo *dinfo;
dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
if ((NULL == dinfo) || (0 == dinfo->port) )
- {
- MHD_stop_daemon (d); return 32;
- }
- daemon_port = dinfo->port;
- }
- c = curl_easy_init ();
- url = malloc (VERY_LONG);
- if (NULL == url)
- {
- curl_easy_cleanup (c);
- MHD_stop_daemon (d);
- return 16;
- }
- memset (url, 'a', VERY_LONG);
- url[VERY_LONG - 1] = '\0';
- url[VERY_LONG / 2] = ':';
- url[VERY_LONG / 2 + 1] = ' ';
- header = curl_slist_append (header, url);
-
- curl_easy_setopt (c, CURLOPT_HTTPHEADER, header);
- curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world");
- curl_easy_setopt (c, CURLOPT_PORT, (long) daemon_port);
- curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
- curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
- curl_easy_setopt (c, CURLOPT_FAILONERROR, 0L);
- curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
- curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
- if (oneone)
- curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
- else
- curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
- /* NOTE: use of CONNECTTIMEOUT without also
- setting NOSIGNAL results in really weird
- crashes on my system! */
- curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
- if (CURLE_OK != curl_easy_perform (c))
- {
- curl_easy_cleanup (c);
- MHD_stop_daemon (d);
- curl_slist_free_all (header);
- free (url);
- return 32;
+ fprintf (stderr, "MHD_get_daemon_info(d, MHD_DAEMON_INFO_BIND_PORT) " \
+ "failed.\n");
+ else
+ daemon_port = dinfo->port;
}
- if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+ if (0 != daemon_port)
{
- curl_slist_free_all (header);
- curl_easy_cleanup (c);
- MHD_stop_daemon (d);
- free (url);
- return 64;
+ char *header_str;
+ header_str = malloc (VERY_LONG);
+ if (NULL == header_str)
+ fprintf (stderr, "malloc (VERY_LONG) failed.\n");
+ else
+ {
+ struct curl_slist *header = NULL;
+
+ memset (header_str, 'a', VERY_LONG);
+ header_str[VERY_LONG - 1] = '\0';
+ header_str[VERY_LONG / 2] = ':';
+ header_str[VERY_LONG / 2 + 1] = ' ';
+
+ header = curl_slist_append (header, header_str);
+ if (NULL == header)
+ fprintf (stderr, "curl_slist_append () failed.\n");
+ else
+ {
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+
+ cbc.buf = buf;
+ cbc.size = sizeof (buf);
+ cbc.pos = 0;
+
+ c = setup_easy_handler (&cbc, NULL, header);
+ if (NULL != c)
+ {
+ CURLcode r;
+ r = curl_easy_perform (c);
+ if (CURLE_OK != r)
+ {
+ fprintf (stderr, "curl_easy_perform() failed. Error message: %s\n",
+ curl_easy_strerror (r));
+ if (0 != libcurl_err_buf[0])
+ fprintf (stderr, "Detailed error message: %s\n",
libcurl_err_buf);
+ }
+ else
+ {
+ long code;
+
+ r = curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code);
+ if (CURLE_OK != r)
+ {
+ fprintf (stderr, "curl_easy_getinfo() failed. "
+ "Error message: %s\n",
+ curl_easy_strerror (r));
+ if (0 != libcurl_err_buf[0])
+ fprintf (stderr, "Detailed error message: %s\n",
+ libcurl_err_buf);
+ }
+ else
+ {
+ if (code != MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE)
+ {
+ fprintf (stderr, "testLongHeaderGet(%lu) failed. HTTP "
+ "response code is %ld, while it should be %ld.\n",
+ (unsigned long) buff_size,
+ code,
+ (long) MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
+ }
+ else
+ {
+ printf ("testLongHeaderGet(%lu) succeed. HTTP "
+ "response code is %ld, as expected.\n",
+ (unsigned long) buff_size,
+ (long) MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
+ ret = 0; /* Success */
+ }
+ }
+ }
+ curl_easy_cleanup (c);
+ }
+ curl_slist_free_all (header);
+ }
+ free (header_str);
+ }
}
- curl_slist_free_all (header);
- curl_easy_cleanup (c);
MHD_stop_daemon (d);
- free (url);
- if (code != MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE)
- return 128;
- return 0;
+ return ret;
}
@@ -285,6 +492,7 @@ main (int argc, char *const *argv)
daemon_port = 0;
else
daemon_port = oneone ? 1336 : 1331;
+
errorCount += testLongUrlGet (VERY_LONG / 2);
errorCount += testLongUrlGet (VERY_LONG / 2 + 978);
errorCount += testLongHeaderGet (VERY_LONG / 2);
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libmicrohttpd] branch master updated: test_long_header: improved, fixed, added error reporting,
gnunet <=