[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r31776 - in libmicrohttpd: . src/examples src/microhttpd
From: |
gnunet |
Subject: |
[GNUnet-SVN] r31776 - in libmicrohttpd: . src/examples src/microhttpd |
Date: |
Wed, 1 Jan 2014 21:43:45 +0100 |
Author: grothoff
Date: 2014-01-01 21:43:44 +0100 (Wed, 01 Jan 2014)
New Revision: 31776
Modified:
libmicrohttpd/ChangeLog
libmicrohttpd/src/examples/demo.c
libmicrohttpd/src/microhttpd/connection.c
Log:
enable use of keep-alive with http 1.0 if explicitly requested by the client
Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog 2013-12-29 22:52:48 UTC (rev 31775)
+++ libmicrohttpd/ChangeLog 2014-01-01 20:43:44 UTC (rev 31776)
@@ -1,3 +1,8 @@
+Wed Jan 1 21:38:18 CET 2014
+ Allow Keep-Alive with HTTP 1.0 (if explicitly requested),
+ and automatically set "Connection: Keep-Alive" in response
+ in this case as well. -CG
+
Tue Dec 24 12:27:39 CET 2013
Adding explicit annotations to hide symbols that are not for
export in the C code (gcc 4.0 or higher only). -CG
Modified: libmicrohttpd/src/examples/demo.c
===================================================================
--- libmicrohttpd/src/examples/demo.c 2013-12-29 22:52:48 UTC (rev 31775)
+++ libmicrohttpd/src/examples/demo.c 2014-01-01 20:43:44 UTC (rev 31776)
@@ -43,7 +43,7 @@
* Number of threads to run in the thread pool. Should (roughly) match
* the number of cores on your system.
*/
-#define NUMBER_OF_THREADS 4
+#define NUMBER_OF_THREADS 8
/**
* How many bytes of a file do we give to libmagic to determine the mime type?
@@ -362,9 +362,11 @@
rdc.buf,
MHD_RESPMEM_MUST_FREE);
mark_as_html (response);
+#if FORCE_CLOSE
(void) MHD_add_response_header (response,
MHD_HTTP_HEADER_CONNECTION,
"close");
+#endif
update_cached_response (response);
}
@@ -775,7 +777,9 @@
}
}
if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
+ {
return return_directory_response (connection);
+ }
/* unexpected request, refuse */
return MHD_queue_response (connection,
Modified: libmicrohttpd/src/microhttpd/connection.c
===================================================================
--- libmicrohttpd/src/microhttpd/connection.c 2013-12-29 22:52:48 UTC (rev
31775)
+++ libmicrohttpd/src/microhttpd/connection.c 2014-01-01 20:43:44 UTC (rev
31776)
@@ -484,8 +484,56 @@
/**
+ * Are we allowed to keep the given connection alive? We can use the
+ * TCP stream for a second request if the connection is HTTP 1.1 and
+ * the "Connection" header either does not exist or is not set to
+ * "close", or if the connection is HTTP 1.0 and the "Connection"
+ * header is explicitly set to "keep-alive". If no HTTP version is
+ * specified (or if it is not 1.0 or 1.1), we definitively close the
+ * connection. If the "Connection" header is not exactly "close" or
+ * "keep-alive", we proceed to use the default for the respective HTTP
+ * version (which is conservative for HTTP 1.0, but might be a bit
+ * optimistic for HTTP 1.1).
+ *
+ * @param connection the connection to check for keepalive
+ * @return #MHD_YES if (based on the request), a keepalive is
+ * legal
+ */
+static int
+keepalive_possible (struct MHD_Connection *connection)
+{
+ const char *end;
+
+ if (NULL == connection->version)
+ return MHD_NO;
+ end = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_CONNECTION);
+ if (0 == strcasecmp (connection->version,
+ MHD_HTTP_VERSION_1_1))
+ {
+ if (NULL == end)
+ return MHD_YES;
+ if (0 == strcasecmp (end, "close"))
+ return MHD_NO;
+ return MHD_YES;
+ }
+ if (0 == strcasecmp (connection->version,
+ MHD_HTTP_VERSION_1_0))
+ {
+ if (NULL == end)
+ return MHD_NO;
+ if (0 == strcasecmp (end, "Keep-Alive"))
+ return MHD_YES;
+ return MHD_NO;
+ }
+ return MHD_NO;
+}
+
+
+/**
* Check if we need to set some additional headers
- * for http-compiliance.
+ * for HTTP-compiliance.
*
* @param connection connection to check (and possibly modify)
*/
@@ -493,6 +541,7 @@
add_extra_headers (struct MHD_Connection *connection)
{
const char *have_close;
+ const char *have_keepalive;
const char *client_close;
const char *have_encoding;
char buf[128];
@@ -502,12 +551,18 @@
MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONNECTION);
/* we only care about 'close', everything else is ignored */
- if ( (NULL != client_close) && (0 != strcasecmp (client_close, "close")) )
+ if ( (NULL != client_close) &&
+ (0 != strcasecmp (client_close, "close")) )
client_close = NULL;
have_close = MHD_get_response_header (connection->response,
MHD_HTTP_HEADER_CONNECTION);
- if ( (NULL != have_close) && (0 != strcasecmp (have_close, "close")) )
+ have_keepalive = have_close;
+ if ( (NULL != have_close) &&
+ (0 != strcasecmp (have_close, "close")) )
have_close = NULL;
+ if ( (NULL != have_keepalive) &&
+ (0 != strcasecmp (have_keepalive, "keep-alive")) )
+ have_keepalive = NULL;
connection->have_chunked_upload = MHD_NO;
add_close = MHD_NO;
if (MHD_SIZE_UNKNOWN == connection->response->total_size)
@@ -518,9 +573,10 @@
{
/* 'close' header doesn't exist yet, see if we need to add one;
if the client asked for a close, no need to start chunk'ing */
- if ((NULL == client_close) &&
- (NULL != connection->version) &&
- (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
+ if ( (NULL == client_close) &&
+ (MHD_YES == keepalive_possible (connection)) &&
+ (0 == strcasecmp (connection->version,
+ MHD_HTTP_VERSION_1_1)) )
{
connection->have_chunked_upload = MHD_YES;
have_encoding = MHD_get_response_header (connection->response,
@@ -578,7 +634,15 @@
}
if (MHD_YES == add_close)
MHD_add_response_header (connection->response,
- MHD_HTTP_HEADER_CONNECTION, "close");
+ MHD_HTTP_HEADER_CONNECTION,
+ "close");
+ if ( (NULL == have_keepalive) &&
+ (NULL == have_close) &&
+ (MHD_NO == add_close) &&
+ (MHD_YES == keepalive_possible (connection)) )
+ MHD_add_response_header (connection->response,
+ MHD_HTTP_HEADER_CONNECTION,
+ "Keep-Alive");
}
@@ -669,6 +733,7 @@
const char *reason_phrase;
uint32_t rc;
int must_add_close;
+ const char *end;
EXTRA_CHECK (NULL != connection->version);
if (0 == strlen (connection->version))
@@ -709,16 +774,17 @@
}
else
{
+ /* 2 bytes for final CRLF of a Chunked-Body */
size = 2;
kind = MHD_FOOTER_KIND;
off = 0;
}
+ end = MHD_get_response_header (connection->response,
+ MHD_HTTP_HEADER_CONNECTION);
must_add_close = ( (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) &&
(MHD_YES == connection->read_closed) &&
- (0 == strcasecmp (connection->version,
- MHD_HTTP_VERSION_1_1)) &&
- (NULL == MHD_get_response_header (connection->response,
-
MHD_HTTP_HEADER_CONNECTION)) );
+ (MHD_YES == keepalive_possible (connection)) &&
+ (NULL == end) );
if (must_add_close)
size += strlen ("Connection: close\r\n");
for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
@@ -729,7 +795,8 @@
if (NULL == data)
{
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
+ MHD_DLOG (connection->daemon,
+ "Not enough memory for write!\n");
#endif
return MHD_NO;
}
@@ -834,8 +901,10 @@
while (1)
{
#if DEBUG_STATES
- MHD_DLOG (connection->daemon, "%s: state: %s\n",
- __FUNCTION__, MHD_state_to_string (connection->state));
+ MHD_DLOG (connection->daemon,
+ "%s: state: %s\n",
+ __FUNCTION__,
+ MHD_state_to_string (connection->state));
#endif
switch (connection->state)
{
@@ -1194,15 +1263,16 @@
equals = sce + 1;
quotes = 0;
semicolon = equals;
- while ((semicolon[0] != '\0') &&
- ((quotes != 0) ||
- ((semicolon[0] != ';') && (semicolon[0] != ','))))
+ while ( ('\0' != semicolon[0]) &&
+ ( (0 != quotes) ||
+ ( (';' != semicolon[0]) &&
+ (',' != semicolon[0]) ) ) )
{
- if (semicolon[0] == '"')
+ if ('"' == semicolon[0])
quotes = (quotes + 1) & 1;
semicolon++;
}
- if (semicolon[0] == '\0')
+ if ('\0' == semicolon[0])
semicolon = NULL;
if (NULL != semicolon)
{
@@ -1210,7 +1280,8 @@
semicolon++;
}
/* remove quotes */
- if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
+ if ( ('"' == equals[0]) &&
+ ('"' == equals[strlen (equals) - 1]) )
{
equals[strlen (equals) - 1] = '\0';
equals++;
@@ -1232,7 +1303,8 @@
* @return #MHD_YES if the line is ok, #MHD_NO if it is malformed
*/
static int
-parse_initial_message_line (struct MHD_Connection *connection, char *line)
+parse_initial_message_line (struct MHD_Connection *connection,
+ char *line)
{
char *uri;
char *http_version;
@@ -1243,7 +1315,7 @@
uri[0] = '\0';
connection->method = line;
uri++;
- while (uri[0] == ' ')
+ while (' ' == uri[0])
uri++;
http_version = strchr (uri, ' ');
if (NULL != http_version)
@@ -1292,9 +1364,9 @@
processed = 0;
connection->client_aware = MHD_YES;
if (MHD_NO ==
- connection->daemon->default_handler (connection->daemon->
- default_handler_cls,
- connection, connection->url,
+ connection->daemon->default_handler (connection->daemon->
default_handler_cls,
+ connection,
+ connection->url,
connection->method,
connection->version,
NULL, &processed,
@@ -1336,12 +1408,12 @@
do
{
instant_retry = MHD_NO;
- if ((connection->have_chunked_upload == MHD_YES) &&
- (connection->remaining_upload_size == MHD_SIZE_UNKNOWN))
+ if ( (MHD_YES == connection->have_chunked_upload) &&
+ (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
{
- if ((connection->current_chunk_offset ==
- connection->current_chunk_size)
- && (connection->current_chunk_offset != 0) && (available >= 2))
+ if ( (connection->current_chunk_offset ==
connection->current_chunk_size) &&
+ (0 != connection->current_chunk_offset) &&
+ (available >= 2) )
{
/* skip new line at the *end* of a chunk */
i = 0;
@@ -1448,12 +1520,13 @@
used = processed;
connection->client_aware = MHD_YES;
if (MHD_NO ==
- connection->daemon->default_handler (connection->daemon->
- default_handler_cls,
- connection, connection->url,
+ connection->daemon->default_handler
(connection->daemon->default_handler_cls,
+ connection,
+ connection->url,
connection->method,
connection->version,
- buffer_head, &processed,
+ buffer_head,
+ &processed,
&connection->client_context))
{
/* serious internal error, close connection */
@@ -1510,7 +1583,7 @@
connection->read_buffer_offset);
if (bytes_read < 0)
{
- if ((EINTR == errno) || (EAGAIN == errno))
+ if ((EINTR == errno) || (EAGAIN == errno) || (ECONNRESET == errno))
return MHD_NO;
#if HAVE_MESSAGES
#if HTTPS_SUPPORT
@@ -1521,7 +1594,8 @@
else
#endif
MHD_DLOG (connection->daemon,
- "Failed to receive data: %s\n", STRERROR (errno));
+ "Failed to receive data: %s\n",
+ STRERROR (errno));
#endif
CONNECTION_CLOSE_ERROR (connection, NULL);
return MHD_YES;
@@ -1539,6 +1613,7 @@
return MHD_YES;
}
+
/**
* Try writing data to the socket from the
* write buffer of the connection.
@@ -1750,12 +1825,13 @@
char *end;
parse_cookie_header (connection);
- if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
- && (NULL != connection->version)
- && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
- && (NULL ==
- MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
- MHD_HTTP_HEADER_HOST)))
+ if ( (0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options)) &&
+ (NULL != connection->version) &&
+ (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)) &&
+ (NULL ==
+ MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_HOST)) )
{
/* die, http 1.1 request without host and we are pedantic */
connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
@@ -1765,7 +1841,7 @@
"Received `%s' request without `%s' header.\n",
MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
#endif
- EXTRA_CHECK (connection->response == NULL);
+ EXTRA_CHECK (NULL == connection->response);
response =
MHD_create_response_from_buffer (strlen (REQUEST_LACKS_HOST),
REQUEST_LACKS_HOST,
@@ -1798,8 +1874,9 @@
{
#if HAVE_MESSAGES
MHD_DLOG (connection->daemon,
- "Failed to parse `%s' header `%s', closing connection.\n",
- MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
+ "Failed to parse `%s' header `%s', closing
connection.\n",
+ MHD_HTTP_HEADER_CONTENT_LENGTH,
+ clen);
#endif
CONNECTION_CLOSE_ERROR (connection, NULL);
return;
@@ -1868,7 +1945,8 @@
{
#if DEBUG_STATES
MHD_DLOG (connection->daemon, "%s: state: %s\n",
- __FUNCTION__, MHD_state_to_string (connection->state));
+ __FUNCTION__,
+ MHD_state_to_string (connection->state));
#endif
switch (connection->state)
{
@@ -1925,7 +2003,8 @@
{
#if DEBUG_STATES
MHD_DLOG (connection->daemon, "%s: state: %s\n",
- __FUNCTION__, MHD_state_to_string (connection->state));
+ __FUNCTION__,
+ MHD_state_to_string (connection->state));
#endif
switch (connection->state)
{
@@ -1949,7 +2028,8 @@
break;
#if HAVE_MESSAGES
MHD_DLOG (connection->daemon,
- "Failed to send data: %s\n", STRERROR (errno));
+ "Failed to send data: %s\n",
+ STRERROR (errno));
#endif
CONNECTION_CLOSE_ERROR (connection, NULL);
return MHD_YES;
@@ -1958,8 +2038,7 @@
FPRINTF (stderr,
"Sent 100 continue response: `%.*s'\n",
ret,
- &HTTP_100_CONTINUE
- [connection->continue_message_write_offset]);
+
&HTTP_100_CONTINUE[connection->continue_message_write_offset]);
#endif
connection->continue_message_write_offset += ret;
break;
@@ -2007,7 +2086,8 @@
return MHD_YES;
#if HAVE_MESSAGES
MHD_DLOG (connection->daemon,
- "Failed to send data: %s\n", STRERROR (errno));
+ "Failed to send data: %s\n",
+ STRERROR (errno));
#endif
CONNECTION_CLOSE_ERROR (connection, NULL);
return MHD_YES;
@@ -2015,7 +2095,7 @@
connection->response_write_position += ret;
if (connection->response_write_position ==
connection->response->total_size)
- connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no
footers... */
+ connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no
footers */
break;
case MHD_CONNECTION_NORMAL_BODY_UNREADY:
EXTRA_CHECK (0);
@@ -2050,7 +2130,8 @@
break;
default:
EXTRA_CHECK (0);
- CONNECTION_CLOSE_ERROR (connection, "Internal error\n");
+ CONNECTION_CLOSE_ERROR (connection,
+ "Internal error\n");
return MHD_YES;
}
break;
@@ -2121,15 +2202,16 @@
struct MHD_Daemon *daemon = connection->daemon;
unsigned int timeout;
const char *end;
- int rend;
char *line;
connection->in_idle = MHD_YES;
while (1)
{
#if DEBUG_STATES
- MHD_DLOG (daemon, "%s: state: %s\n",
- __FUNCTION__, MHD_state_to_string (connection->state));
+ MHD_DLOG (daemon,
+ "%s: state: %s\n",
+ __FUNCTION__,
+ MHD_state_to_string (connection->state));
#endif
switch (connection->state)
{
@@ -2241,15 +2323,15 @@
}
break;
case MHD_CONNECTION_CONTINUE_SENT:
- if (connection->read_buffer_offset != 0)
+ if (0 != connection->read_buffer_offset)
{
process_request_body (connection); /* loop call */
if (MHD_CONNECTION_CLOSED == connection->state)
continue;
}
- if ((connection->remaining_upload_size == 0) ||
+ if ((0 == connection->remaining_upload_size) ||
((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
- (connection->read_buffer_offset == 0) &&
+ (0 == connection->read_buffer_offset) &&
(MHD_YES == connection->read_closed)))
{
if ((MHD_YES == connection->have_chunked_upload) &&
@@ -2262,7 +2344,7 @@
break;
case MHD_CONNECTION_BODY_RECEIVED:
line = get_next_header_line (connection);
- if (line == NULL)
+ if (NULL == line)
{
if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
continue;
@@ -2274,7 +2356,7 @@
}
break;
}
- if (strlen (line) == 0)
+ if (0 == strlen (line))
{
connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
continue;
@@ -2290,7 +2372,7 @@
continue;
case MHD_CONNECTION_FOOTER_PART_RECEIVED:
line = get_next_header_line (connection);
- if (line == NULL)
+ if (NULL == line)
{
if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
continue;
@@ -2305,7 +2387,7 @@
if (MHD_NO ==
process_broken_line (connection, line, MHD_FOOTER_KIND))
continue;
- if (strlen (line) == 0)
+ if (0 == strlen (line))
{
connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
continue;
@@ -2315,7 +2397,7 @@
call_connection_handler (connection); /* "final" call */
if (connection->state == MHD_CONNECTION_CLOSED)
continue;
- if (connection->response == NULL)
+ if (NULL == connection->response)
break; /* try again next time */
if (MHD_NO == build_header_response (connection))
{
@@ -2412,44 +2494,29 @@
end =
MHD_get_response_header (connection->response,
MHD_HTTP_HEADER_CONNECTION);
- rend = ( (MHD_YES == connection->read_closed) ||
- ( (end != NULL) && (0 == strcasecmp (end, "close")) ) );
MHD_destroy_response (connection->response);
connection->response = NULL;
- if (daemon->notify_completed != NULL)
+ if (NULL != daemon->notify_completed)
daemon->notify_completed (daemon->notify_completed_cls,
connection,
&connection->client_context,
MHD_REQUEST_TERMINATED_COMPLETED_OK);
- connection->client_aware = MHD_NO;
end =
MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONNECTION);
- connection->client_context = NULL;
- connection->continue_message_write_offset = 0;
- connection->responseCode = 0;
- connection->headers_received = NULL;
- connection->headers_received_tail = NULL;
- connection->response_write_position = 0;
- connection->have_chunked_upload = MHD_NO;
- connection->method = NULL;
- connection->url = NULL;
- connection->write_buffer = NULL;
- connection->write_buffer_size = 0;
- connection->write_buffer_send_offset = 0;
- connection->write_buffer_append_offset = 0;
- if ( (rend) || ((end != NULL) && (0 == strcasecmp (end, "close"))) )
+ if ( (MHD_YES == connection->read_closed) ||
+ ((NULL != end) && (0 == strcasecmp (end, "close"))) )
{
connection->read_closed = MHD_YES;
connection->read_buffer_offset = 0;
}
if (((MHD_YES == connection->read_closed) &&
(0 == connection->read_buffer_offset)) ||
- (connection->version == NULL) ||
- (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
+ (MHD_NO == keepalive_possible (connection)))
{
- /* http 1.0, version-less requests cannot be pipelined */
- MHD_connection_close (connection,
MHD_REQUEST_TERMINATED_COMPLETED_OK);
+ /* have to close for some reason */
+ MHD_connection_close (connection,
+ MHD_REQUEST_TERMINATED_COMPLETED_OK);
MHD_pool_destroy (connection->pool);
connection->pool = NULL;
connection->read_buffer = NULL;
@@ -2458,6 +2525,7 @@
}
else
{
+ /* can try to keep-alive */
connection->version = NULL;
connection->state = MHD_CONNECTION_INIT;
connection->read_buffer
@@ -2465,6 +2533,20 @@
connection->read_buffer,
connection->read_buffer_size);
}
+ connection->client_aware = MHD_NO;
+ connection->client_context = NULL;
+ connection->continue_message_write_offset = 0;
+ connection->responseCode = 0;
+ connection->headers_received = NULL;
+ connection->headers_received_tail = NULL;
+ connection->response_write_position = 0;
+ connection->have_chunked_upload = MHD_NO;
+ connection->method = NULL;
+ connection->url = NULL;
+ connection->write_buffer = NULL;
+ connection->write_buffer_size = 0;
+ connection->write_buffer_send_offset = 0;
+ connection->write_buffer_append_offset = 0;
continue;
case MHD_CONNECTION_CLOSED:
cleanup_connection (connection);
@@ -2476,7 +2558,7 @@
break;
}
timeout = connection->connection_timeout;
- if ( (timeout != 0) &&
+ if ( (0 != timeout) &&
(timeout <= (MHD_monotonic_time() - connection->last_activity)) )
{
MHD_connection_close (connection,
MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r31776 - in libmicrohttpd: . src/examples src/microhttpd,
gnunet <=