|
|
@@ -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);
|