[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r5425 - in libmicrohttpd: . src/daemon
From: |
gnunet |
Subject: |
[GNUnet-SVN] r5425 - in libmicrohttpd: . src/daemon |
Date: |
Wed, 8 Aug 2007 14:03:13 -0600 (MDT) |
Author: grothoff
Date: 2007-08-08 14:03:11 -0600 (Wed, 08 Aug 2007)
New Revision: 5425
Added:
libmicrohttpd/src/daemon/daemontest_long_header.c
Modified:
libmicrohttpd/README
libmicrohttpd/src/daemon/Makefile.am
libmicrohttpd/src/daemon/connection.c
Log:
handling of long headers (#1222)
Modified: libmicrohttpd/README
===================================================================
--- libmicrohttpd/README 2007-08-08 08:55:18 UTC (rev 5424)
+++ libmicrohttpd/README 2007-08-08 20:03:11 UTC (rev 5425)
@@ -14,9 +14,7 @@
For http/1.1-compliance:
========================
connection.c:
-- send proper error code back if headers are too long
- (currently, we just close the connection) (#1222, ARCH, TEST)
-- support chunked requests from clients (#1260, TEST, TEST)
+- support chunked requests from clients (#1260, ARCH, TEST)
- send proper error code back if client forgot the "Host" header (#1264, TRIV)
- automatically add MHD_HTTP_HEADER_DATE if client "forgot" to add one (#1261,
TRIV)
- automatically drop body from responses to "HEAD" requests (#1262, TRIV)
Modified: libmicrohttpd/src/daemon/Makefile.am
===================================================================
--- libmicrohttpd/src/daemon/Makefile.am 2007-08-08 08:55:18 UTC (rev
5424)
+++ libmicrohttpd/src/daemon/Makefile.am 2007-08-08 20:03:11 UTC (rev
5425)
@@ -35,7 +35,8 @@
daemontest_put \
daemontest_get11 \
daemontest_post11 \
- daemontest_put11
+ daemontest_put11 \
+ daemontest_long_header
TESTS = $(check_PROGRAMS)
@@ -74,11 +75,16 @@
$(top_builddir)/src/daemon/libmicrohttpd.la \
@LIBCURL@
-
daemontest_put11_SOURCES = \
daemontest_put.c
daemontest_put11_LDADD = \
$(top_builddir)/src/daemon/libmicrohttpd.la \
@LIBCURL@
+daemontest_long_header_SOURCES = \
+ daemontest_long_header.c
+daemontest_long_header_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
endif
\ No newline at end of file
Modified: libmicrohttpd/src/daemon/connection.c
===================================================================
--- libmicrohttpd/src/daemon/connection.c 2007-08-08 08:55:18 UTC (rev
5424)
+++ libmicrohttpd/src/daemon/connection.c 2007-08-08 20:03:11 UTC (rev
5425)
@@ -41,6 +41,12 @@
#define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
/**
+ * Response used when the request (http header) is too big to
+ * be processed.
+ */
+#define REQUEST_TOO_BIG ""
+
+/**
* Get all of the headers from the request.
*
* @param iterator callback to call on each header;
@@ -146,16 +152,14 @@
fd = connection->socket_fd;
if (fd == -1)
return MHD_YES;
- if ( (connection->read_close == 0) &&
+ if ( (connection->read_close == MHD_NO) &&
( (connection->headersReceived == 0) ||
(connection->readLoc < connection->read_buffer_size) ) ) {
FD_SET(fd, read_fd_set);
if (fd > *max_fd)
*max_fd = fd;
} else {
-
-
- if ( (connection->read_close == 0) &&
+ if ( (connection->read_close == MHD_NO) &&
( (connection->headersReceived == 1) &&
(connection->post_processed == MHD_NO) &&
(connection->readLoc == connection->read_buffer_size) ) ) {
@@ -188,17 +192,32 @@
/**
* We ran out of memory processing the
- * header. Handle it properly.
+ * header. Handle it properly by stopping to read data
+ * and sending a HTTP 413 or HTTP 414 response.
+ *
+ * @param status_code the response code to send (413 or 414)
*/
static void
-MHD_excessive_header_handler(struct MHD_Connection * connection) {
+MHD_excessive_data_handler(struct MHD_Connection * connection,
+ unsigned int status_code) {
+ struct MHD_Response * response;
+
/* die, header far too long to be reasonable;
FIXME: send proper response to client
(stop reading, queue proper response) */
+ connection->read_close = MHD_YES;
+ connection->headersReceived = MHD_YES;
+ connection->bodyReceived = MHD_YES;
MHD_DLOG(connection->daemon,
- "Received excessively long header line, closing connection.\n");
- CLOSE(connection->socket_fd);
- connection->socket_fd = -1;
+ "Received excessively long header, closing connection.\n");
+ response = MHD_create_response_from_data(strlen(REQUEST_TOO_BIG),
+ REQUEST_TOO_BIG,
+ MHD_NO,
+ MHD_NO);
+ MHD_queue_response(connection,
+ status_code,
+ response);
+ MHD_destroy_response(response);
}
/**
@@ -230,7 +249,10 @@
connection->read_buffer_size,
connection->read_buffer_size * 2 +
MHD_BUF_INC_SIZE);
if (rbuf == NULL) {
- MHD_excessive_header_handler(connection);
+ MHD_excessive_data_handler(connection,
+ (connection->url != NULL)
+ ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
+ : MHD_HTTP_REQUEST_URI_TOO_LONG);
} else {
connection->read_buffer_size = connection->read_buffer_size * 2 +
MHD_BUF_INC_SIZE;
connection->read_buffer = rbuf;
@@ -265,7 +287,8 @@
if (hdr == NULL) {
MHD_DLOG(connection->daemon,
"Not enough memory to allocate header record!\n");
- MHD_excessive_header_handler(connection);
+ MHD_excessive_data_handler(connection,
+ MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
return MHD_NO;
}
hdr->next = connection->headers_received;
@@ -360,7 +383,8 @@
if (cpy == NULL) {
MHD_DLOG(connection->daemon,
"Not enough memory to parse cookies!\n");
- MHD_excessive_header_handler(connection);
+ MHD_excessive_data_handler(connection,
+ MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
return MHD_NO;
}
memcpy(cpy,
@@ -483,7 +507,8 @@
strlen(last)+1,
strlen(line) + strlen(last) + 1);
if (last == NULL) {
- MHD_excessive_header_handler(connection);
+ MHD_excessive_data_handler(connection,
+ MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
break;
}
tmp = line;
@@ -620,8 +645,10 @@
const char * encoding;
void * buf;
- if (0 != strcasecmp(connection->method,
- MHD_HTTP_METHOD_POST))
+ if ( (connection->method == NULL) ||
+ (connection->response != NULL) ||
+ (0 != strcasecmp(connection->method,
+ MHD_HTTP_METHOD_POST)) )
return MHD_NO;
encoding = MHD_lookup_connection_value(connection,
MHD_HEADER_KIND,
@@ -711,6 +738,8 @@
struct MHD_Access_Handler * ah;
unsigned int processed;
+ if (connection->response != NULL)
+ return; /* already queued a response */
if (connection->headersReceived == 0)
abort(); /* bad timing... */
ah = MHD_find_access_handler(connection);
@@ -778,7 +807,8 @@
if (tmp == NULL) {
MHD_DLOG(connection->daemon,
"Not enough memory for reading headers!\n");
- MHD_excessive_header_handler(connection);
+ MHD_excessive_data_handler(connection,
+ MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
return MHD_NO;
}
connection->read_buffer = tmp;
@@ -824,8 +854,9 @@
(connection->uploadSize == connection->readLoc) )
if (MHD_NO == MHD_parse_post_data(connection))
connection->post_processed = MHD_NO;
- if ( (connection->post_processed == MHD_NO) ||
- (connection->read_buffer_size == connection->readLoc) )
+ if ( ( (connection->post_processed == MHD_NO) ||
+ (connection->read_buffer_size == connection->readLoc) ) &&
+ (connection->method != NULL) )
MHD_call_connection_handler(connection);
}
return MHD_YES;
@@ -1065,7 +1096,7 @@
connection->messagePos = 0;
connection->method = NULL;
connection->url = NULL;
- if ( (connection->read_close != 0) ||
+ if ( (connection->read_close == MHD_YES) ||
(0 != strcasecmp(MHD_HTTP_VERSION_1_1,
connection->version)) ) {
/* closed for reading => close for good! */
Added: libmicrohttpd/src/daemon/daemontest_long_header.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest_long_header.c
(rev 0)
+++ libmicrohttpd/src/daemon/daemontest_long_header.c 2007-08-08 20:03:11 UTC
(rev 5425)
@@ -0,0 +1,287 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_long_header.c
+ * @brief Testcase for libmicrohttpd handling of very long headers
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+/**
+ * We will set the memory available per connection to
+ * half of this value, so the actual value does not have
+ * to be big at all...
+ */
+#define VERY_LONG (1024*10)
+
+static int oneone;
+
+static int apc_all(void * cls,
+ const struct sockaddr * addr,
+ socklen_t addrlen) {
+ return MHD_YES;
+}
+
+struct CBC {
+ char * buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t copyBuffer(void * ptr,
+ size_t size,
+ size_t nmemb,
+ void * ctx) {
+ return size * nmemb;
+}
+
+static int ahc_echo(void * cls,
+ struct MHD_Connection * connection,
+ const char * url,
+ const char * method,
+ const char * version,
+ const char * upload_data,
+ unsigned int * upload_data_size) {
+ const char * me = cls;
+ struct MHD_Response * response;
+ int ret;
+
+ if (0 != strcmp(me, method))
+ return MHD_NO; /* unexpected method */
+ response = MHD_create_response_from_data(strlen(url),
+ (void*) url,
+ MHD_NO,
+ MHD_YES);
+ ret = MHD_queue_response(connection,
+ MHD_HTTP_OK,
+ response);
+ MHD_destroy_response(response);
+ return ret;
+}
+
+
+static int testLongUrlGet() {
+ 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;
+ d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */,
+ 1080,
+ &apc_all,
+ NULL,
+ &ahc_echo,
+ "GET",
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ VERY_LONG / 2,
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init();
+ url = malloc(VERY_LONG);
+ memset(url,
+ 'a',
+ VERY_LONG);
+ url[VERY_LONG-1] = '\0';
+ memcpy(url,
+ "http://localhost:1080/",
+ strlen("http://localhost:1080/"));
+ curl_easy_setopt(c,
+ CURLOPT_URL,
+ url);
+ curl_easy_setopt(c,
+ CURLOPT_WRITEFUNCTION,
+ ©Buffer);
+ curl_easy_setopt(c,
+ CURLOPT_WRITEDATA,
+ &cbc);
+ curl_easy_setopt(c,
+ CURLOPT_FAILONERROR,
+ 1);
+ curl_easy_setopt(c,
+ CURLOPT_TIMEOUT,
+ 2L);
+ curl_easy_setopt(c,
+ CURLOPT_CONNECTTIMEOUT,
+ 2L);
+ 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,
+ 1);
+ if (CURLE_OK == curl_easy_perform(c)) {
+ curl_easy_cleanup(c);
+ MHD_stop_daemon(d);
+ free(url);
+ return 2;
+ }
+ if (CURLE_OK != curl_easy_getinfo(c,
+ CURLINFO_RESPONSE_CODE,
+ &code)) {
+ curl_easy_cleanup(c);
+ MHD_stop_daemon(d);
+ free(url);
+ return 4;
+ }
+ curl_easy_cleanup(c);
+ MHD_stop_daemon(d);
+ free(url);
+ if (code != MHD_HTTP_REQUEST_URI_TOO_LONG)
+ return 8;
+ return 0;
+}
+
+
+static int testLongHeaderGet() {
+ 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;
+ d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */,
+ 1080,
+ &apc_all,
+ NULL,
+ &ahc_echo,
+ "GET",
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ VERY_LONG / 2,
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init();
+ url = malloc(VERY_LONG);
+ 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://localhost:1080/hello_world");
+ curl_easy_setopt(c,
+ CURLOPT_WRITEFUNCTION,
+ ©Buffer);
+ curl_easy_setopt(c,
+ CURLOPT_WRITEDATA,
+ &cbc);
+ curl_easy_setopt(c,
+ CURLOPT_FAILONERROR,
+ 1);
+ curl_easy_setopt(c,
+ CURLOPT_TIMEOUT,
+ 2L);
+ curl_easy_setopt(c,
+ CURLOPT_CONNECTTIMEOUT,
+ 2L);
+ 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,
+ 1);
+ if (CURLE_OK == curl_easy_perform(c)) {
+ curl_easy_cleanup(c);
+ MHD_stop_daemon(d);
+ curl_slist_free_all(header);
+ free(url);
+ return 32;
+ }
+ if (CURLE_OK != curl_easy_getinfo(c,
+ CURLINFO_RESPONSE_CODE,
+ &code)) {
+ curl_slist_free_all(header);
+ curl_easy_cleanup(c);
+ MHD_stop_daemon(d);
+ free(url);
+ return 64;
+ }
+ curl_slist_free_all(header);
+ curl_easy_cleanup(c);
+ MHD_stop_daemon(d);
+ free(url);
+ if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE)
+ return 128;
+ return 0;
+}
+
+
+
+
+
+int main(int argc,
+ char * const * argv) {
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr(argv[0], "11");
+ if (0 != curl_global_init(CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testLongUrlGet();
+ errorCount += testLongHeaderGet();
+ if (errorCount != 0)
+ fprintf(stderr,
+ "Error (code: %u)\n",
+ errorCount);
+ curl_global_cleanup();
+ return errorCount != 0; /* 0 == pass */
+}
Property changes on: libmicrohttpd/src/daemon/daemontest_long_header.c
___________________________________________________________________
Name: svn:eol-style
+ native
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r5425 - in libmicrohttpd: . src/daemon,
gnunet <=