35#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
41#ifdef MHD_LINUX_SOLARIS_SENDFILE
42#include <sys/sendfile.h>
44#if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
46#include <sys/socket.h>
52#ifdef HAVE_SYS_PARAM_H
62#define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
72#define REQUEST_TOO_BIG \
73 "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
75#define REQUEST_TOO_BIG ""
86#define REQUEST_LACKS_HOST \
87 "<html><head><title>"Host:" header required</title></head><body>In HTTP 1.1, requests must include a "Host:" header, and your HTTP 1.1 request lacked such a header.</body></html>"
89#define REQUEST_LACKS_HOST ""
100#define REQUEST_MALFORMED \
101 "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
103#define REQUEST_MALFORMED ""
111#define REQUEST_CHUNKED_MALFORMED \
112 "<html><head><title>Request malformed</title></head><body>Your HTTP chunked encoding was syntactically incorrect.</body></html>"
114#define REQUEST_CHUNKED_MALFORMED ""
121#define REQUEST_CHUNK_TOO_LARGE \
122 "<html><head><title>Request content too large</title></head><body>The chunk size used in your HTTP chunked encoded request is too large.</body></html>"
124#define REQUEST_CHUNK_TOO_LARGE ""
131#define REQUEST_CONTENTLENGTH_TOOLARGE \
132 "<html><head><title>Request content too large</title></head>" \
133 "<body>Your HTTP request has too large value for <b>Content-Length</b> header.</body></html>"
135#define REQUEST_CONTENTLENGTH_TOOLARGE ""
143#define REQUEST_CONTENTLENGTH_MALFORMED \
144 "<html><head><title>Request malformed</title></head>" \
145 "<body>Your HTTP request has wrong value for <b>Content-Length</b> header.</body></html>"
147#define REQUEST_CONTENTLENGTH_MALFORMED ""
157#define INTERNAL_ERROR \
158 "<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>"
160#define INTERNAL_ERROR ""
167#define REQ_HTTP_VER_IS_TOO_OLD \
168 "<html><head><title>Requested HTTP version is not supported</title></head><body>Requested HTTP version is too old and not supported.</body></html>"
170#define REQ_HTTP_VER_IS_TOO_OLD ""
177#define REQ_HTTP_VER_IS_NOT_SUPPORTED \
178 "<html><head><title>Requested HTTP version is not supported</title></head><body>Requested HTTP version is not supported.</body></html>"
180#define REQ_HTTP_VER_IS_NOT_SUPPORTED ""
187#define MHD_SENFILE_CHUNK_ (0x20000)
192#define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
201str_conn_error_ (ssize_t mhd_err_code)
203 switch (mhd_err_code)
206 return _ (
"The operation would block, retry later");
208 return _ (
"The connection was forcibly closed by remote peer");
210 return _ (
"The socket is not connected");
212 return _ (
"Not enough system resources to serve the request");
214 return _ (
"Bad FD value");
216 return _ (
"Argument value is invalid");
218 return _ (
"Argument value is not supported");
220 return _ (
"The socket is no longer available for sending");
222 return _ (
"TLS encryption or decryption error");
226 if (0 <= mhd_err_code)
227 return _ (
"Not an error code");
230 return _ (
"Wrong error code value");
250 struct MemoryPool *
const pool = c->
pool;
260 mhd_assert (MHD_CONNECTION_START_REPLY <= c->state);
340 connection->epoll_state &=
363 else if (i > (
size_t) ret)
364 connection->epoll_state &=
392 if (
NULL == connection)
399 if ( (
NULL != iterator) &&
400 (
MHD_NO == iterator (iterator_cls,
431 if (
NULL == connection)
435 if (
NULL == iterator)
446 if (
MHD_NO == iterator (iterator_cls,
489 pos->
header = (
char *) key;
544 ( ((key ? strlen (key) : 0) != key_size) ||
622 (
NULL == key) ? 0 : strlen (key),
653 const char **value_ptr,
654 size_t *value_size_ptr)
658 if (
NULL == connection)
687 if (
NULL != value_ptr)
688 *value_ptr = pos->
value;
690 if (
NULL != value_size_ptr)
755#define MHD_lookup_header_s_token_ci(c,h,tkn) \
756 MHD_lookup_header_token_ci ((c),(h),MHD_STATICSTR_LEN_ (h), \
757 (tkn),MHD_STATICSTR_LEN_ (tkn))
837#ifdef MHD_USE_THREADS
839 MHD_thread_ID_match_current_ (connection->
pid) );
863#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
878 struct MHD_UpgradeResponseHandle *urh = connection->urh;
880#ifdef MHD_USE_THREADS
883 MHD_thread_ID_match_current_ (daemon->
pid) );
895 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
900 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
902 if (urh->in_eready_list)
905 daemon->eready_urh_tail,
907 urh->in_eready_list =
false;
914 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
919 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
924 shutdown (urh->mhd.socket, SHUT_RDWR);
952 MHD_DLOG (connection->
daemon,
968#define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
970#define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
1001#define CONNECTION_CLOSE_ERROR_CHECK(c, emsg) \
1002 connection_close_error_check (c, emsg)
1004#define CONNECTION_CLOSE_ERROR_CHECK(c, emsg) \
1005 connection_close_error_check (c, NULL)
1048 _ (
"Closing connection (out of memory)."));
1065#if defined(_MHD_HAVE_SENDFILE)
1066 if (MHD_resp_sender_sendfile == connection->resp_sender)
1085#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1094 "Closing connection (application reported error generating data)."));
1102#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1129 static const size_t max_chunk = 0xFFFFFF;
1132 static const size_t max_chunk_hdr_len =
sizeof(chunk_hdr) + 2;
1134 static const size_t max_chunk_overhead =
sizeof(chunk_hdr) + 2 + 2;
1135 size_t chunk_hdr_len;
1136 uint64_t left_to_send;
1137 size_t size_to_fill;
1152#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1157 _ (
"Closing connection (out of memory)."));
1161 if ( (max_chunk + max_chunk_overhead) < size)
1162 size = max_chunk + max_chunk_overhead;
1166 write_buffer_size, size);
1170 mhd_assert (max_chunk_overhead < connection->write_buffer_size);
1179 if (max_chunk < size_to_fill)
1180 size_to_fill = max_chunk;
1181 if (left_to_send < size_to_fill)
1182 size_to_fill = (size_t) left_to_send;
1184 if (0 == left_to_send)
1194 const size_t data_write_offset
1197 ret = response->
data_size - data_write_offset;
1198 if ( ((
size_t) ret) > size_to_fill)
1199 ret = (ssize_t) size_to_fill;
1201 &response->
data[data_write_offset],
1208#if defined(MHD_USE_THREADS)
1212 _ (
"No callback for the chunked data."));
1225#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1230 "Closing connection (application error generating response)."));
1243#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1248 if (size_to_fill < (
size_t) ret)
1250#if defined(MHD_USE_THREADS)
1254 _ (
"Closing connection (application returned " \
1255 "more data than requested)."));
1261 mhd_assert (chunk_hdr_len <
sizeof(chunk_hdr));
1262 *p_finished =
false;
1264 (max_chunk_hdr_len - (chunk_hdr_len + 2));
1268 connection->
write_buffer[max_chunk_hdr_len - 2] =
'\r';
1269 connection->
write_buffer[max_chunk_hdr_len - 1] =
'\n';
1270 connection->
write_buffer[max_chunk_hdr_len + ret] =
'\r';
1271 connection->
write_buffer[max_chunk_hdr_len + ret + 1] =
'\n';
1310#ifdef UPGRADE_SUPPORT
1313 if (
NULL != r->upgrade_handler)
1371 static const char *
const days[] = {
1372 "Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
1374 static const char *
const mons[] = {
1375 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
1376 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
1378 static const size_t buf_len = 29;
1382#if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1383 ! defined(HAVE_GMTIME_R)
1387 if ((time_t) -1 == time (&t))
1389#if defined(HAVE_C11_GMTIME_S)
1390 if (
NULL == gmtime_s (&t,
1393#elif defined(HAVE_W32_GMTIME_S)
1394 if (0 != gmtime_s (&now,
1397#elif defined(HAVE_GMTIME_R)
1398 if (
NULL == gmtime_r (&t,
1409 src = days[now.tm_wday % 7];
1417 date + 5, buf_len - 5))
1421 src = mons[now.tm_mon % 12];
1495 if (0 == avail_size)
1498 new_size = avail_size / 2;
1503 grow_size = avail_size / 8;
1512 if (small_inc < avail_size)
1513 grow_size = small_inc;
1515 grow_size = avail_size;
1580 struct MemoryPool *
const pool = connection->
pool;
1626connection_shrink_write_buffer (
struct MHD_Connection *connection)
1629 struct MemoryPool *
const pool = connection->
pool;
1707#ifdef UPGRADE_SUPPORT
1713 (2 == rcode / 100) )
1788 use_chunked =
false;
1792 use_chunked =
false;
1802 use_chunked =
false;
1811 use_chunked =
false;
1837 if (buf_size < *ppos + append_size)
1839 memcpy (buf + *ppos, append, append_size);
1840 *ppos += append_size;
1855#define buffer_append_s(buf,ppos,buf_size,str) \
1856 buffer_append(buf,ppos,buf_size,str, MHD_STATICSTR_LEN_(str))
1884 bool filter_transf_enc,
1886 bool add_keep_alive)
1895 mhd_assert (! add_close || ! add_keep_alive);
1898 filter_transf_enc =
false;
1902 add_keep_alive =
false;
1909 size_t initial_pos = *ppos;
1912 if (filter_transf_enc)
1919 filter_transf_enc =
false;
1926 if (buf_size < *ppos + el_size)
1930 buf[(*ppos)++] =
':';
1931 buf[(*ppos)++] =
' ';
1932 if (add_close || add_keep_alive)
1942 if (buf_size < initial_pos + el_size)
1944 memcpy (buf + *ppos,
"close, ",
1951 if (buf_size < initial_pos + el_size)
1953 memcpy (buf + *ppos,
"Keep-Alive, ",
1958 add_keep_alive =
false;
1963 buf[(*ppos)++] =
'\r';
1964 buf[(*ppos)++] =
'\n';
1965 mhd_assert (initial_pos + el_size == (*ppos));
1989 bool use_conn_close;
1990 bool use_conn_k_alive;
2002#ifdef UPGRADE_SUPPORT
2011#ifdef UPGRADE_SUPPORT
2021 use_conn_close =
true;
2022 use_conn_k_alive =
false;
2026 use_conn_close =
false;
2034 use_conn_k_alive =
true;
2036 use_conn_k_alive =
false;
2040 use_conn_close =
false;
2041 use_conn_k_alive =
false;
2080 if (buf_size < pos + 5)
2100 if (buf_size < pos + 2)
2114 if (buf_size < pos + 38)
2120 mhd_assert (! use_conn_close || ! use_conn_k_alive);
2121 mhd_assert (! use_conn_k_alive || ! use_conn_close);
2130 else if (use_conn_k_alive)
2174 if (buf_size < pos + 2)
2183 if (buf_size < pos + 2)
2225 buf[used_size++] =
'0';
2226 buf[used_size++] =
'\r';
2227 buf[used_size++] =
'\n';
2233 size_t new_used_size;
2236 if (new_used_size > buf_size)
2240 buf[used_size++] =
':';
2241 buf[used_size++] =
' ';
2244 buf[used_size++] =
'\r';
2245 buf[used_size++] =
'\n';
2249 if (used_size + 2 > buf_size)
2251 buf[used_size++] =
'\r';
2252 buf[used_size++] =
'\n';
2273 unsigned int status_code,
2274 const char *message,
2291 MHD_DLOG (connection->
daemon,
2292 _ (
"Error processing request (HTTP response code is %u ('%s')). " \
2293 "Closing connection.\n"),
2297 if (MHD_CONNECTION_START_REPLY < connection->state)
2300 MHD_DLOG (connection->
daemon,
2301 _ (
"Too late to send an error response, " \
2302 "response is being sent already.\n"),
2307 _ (
"Too late for error response."));
2331 if (
NULL == response)
2334 MHD_DLOG (connection->
daemon,
2335 _ (
"Failed to create error response.\n"),
2351 _ (
"Closing connection " \
2352 "(failed to queue error response)."));
2383 _ (
"Closing connection " \
2384 "(failed to create error response header)."));
2395#define transmit_error_response_static(c, code, msg) \
2396 transmit_error_response_len (c, code, msg, MHD_STATICSTR_LEN_ (msg))
2415 switch (connection->tls_state)
2421 if (0 == gnutls_record_get_direction (connection->tls_session))
2434 MHD_DLOG (connection->
daemon,
2435 _ (
"In function %s handling connection at state: %s\n"),
2437 MHD_state_to_string (connection->
state));
2439 switch (connection->
state)
2477 const bool internal_poll = (0 != (connection->
daemon->
options
2559#ifdef UPGRADE_SUPPORT
2560 case MHD_CONNECTION_UPGRADE:
2600 const char c = rbuf[pos];
2603 if ( (
'\r' == c) && (pos < connection->read_buffer_offset - 1) &&
2604 (
'\n' == rbuf[pos + 1]) )
2626 }
while (++pos < connection->read_buffer_offset);
2677 MHD_DLOG (connection->
daemon,
2678 _ (
"Not enough memory in pool to allocate header record!\n"));
2723 MHD_DLOG (connection->
daemon,
2724 _ (
"Not enough memory in pool to parse cookies!\n"));
2734 cpy[hdr_len] =
'\0';
2742 while ( ((*sce) !=
'\0') &&
2749 while ( (*ekill ==
' ') &&
2773 while ( (
'\0' != semicolon[0]) &&
2775 ( (
';' != semicolon[0]) &&
2776 (
',' != semicolon[0]) ) ) )
2778 if (
'"' == semicolon[0])
2779 quotes = (quotes + 1) & 1;
2783 if (
'\0' == semicolon[0])
2785 if (
NULL != semicolon)
2787 semicolon[0] =
'\0';
2791 if ( (
'"' == equals[0]) &&
2823 const char *http_string,
2826 const char *
const h = http_string;
2832 (h[0] !=
'H') || (h[1] !=
'T') || (h[2] !=
'T') || (h[3] !=
'P') ||
2835 ((h[5] <
'0') || (h[5] >
'9')) ||
2836 ((h[7] <
'0') || (h[7] >
'9')))
2844 if (1 == h[5] -
'0')
2847 if (1 == h[7] -
'0')
2849 else if (0 == h[7] -
'0')
2857 if (0 == h[5] -
'0')
2889 const char *
const m = method;
2945 unsigned int unused_num_headers;
2947 if (
NULL == (uri = memchr (line,
2952 connection->
method = line;
2954 (
size_t) (uri - line)))
2960 while ( (
' ' == uri[0]) &&
2961 ( (
size_t) (uri - line) < line_len) )
2963 if ((
size_t) (uri - line) == line_len)
2978 http_version = line + line_len - 1;
2981 while ( (
' ' == http_version[0]) &&
2982 (http_version > uri) )
2985 while ( (
' ' != http_version[0]) &&
2986 (http_version > uri) )
2988 if (http_version > uri)
2991 http_version[0] =
'\0';
2992 connection->
version = http_version + 1;
2995 - (connection->
version - line)))
2997 uri_len = http_version - uri;
3004 uri_len = line_len - (uri - line);
3008 (
NULL != memchr (uri,
3040 &unused_num_headers);
3048 connection->
url = curi;
3083 "Application reported internal error, closing connection."));
3127 size_t to_be_processed;
3128 size_t left_unprocessed;
3129 size_t processed_size;
3131 instant_retry =
false;
3143 if ( (2 <= available) &&
3144 (
'\r' == buffer_head[0]) &&
3145 (
'\n' == buffer_head[1]) )
3147 else if (
'\n' == buffer_head[0])
3149 else if (2 > available)
3168 uint64_t cur_chunk_left;
3176 if (cur_chunk_left > available)
3177 to_be_processed = available;
3180 to_be_processed = (size_t) cur_chunk_left;
3181 if (available > to_be_processed)
3182 instant_retry =
true;
3189 size_t chunk_size_len;
3190 bool found_chunk_size_str;
3195 found_chunk_size_str =
false;
3200 if (
'\n' == buffer_head[i])
3202 if ((0 < i) && (
'\r' == buffer_head[i - 1]))
3204 if (! found_chunk_size_str)
3205 chunk_size_len = i - 1;
3210 if (! found_chunk_size_str)
3213 found_chunk_size_str =
true;
3216 else if (! found_chunk_size_str && (
';' == buffer_head[i]))
3219 found_chunk_size_str =
true;
3221 }
while (available > ++i);
3222 mhd_assert ((i == available) || found_chunk_size_str);
3223 mhd_assert ((0 == chunk_size_len) || found_chunk_size_str);
3224 malformed = ((0 == chunk_size_len) && found_chunk_size_str);
3230 uint64_t chunk_size;
3232 if (! found_chunk_size_str)
3238 if (
'\r' == buffer_head[i - 1])
3241 malformed = (0 == chunk_size_len);
3247 malformed = malformed || (chunk_size_len != num_dig);
3249 if ((available != i) && ! malformed)
3267 instant_retry =
true;
3271 if ((0 == num_dig) && (0 != chunk_size_len))
3275 const char d = buffer_head[0];
3276 if (((
'0' <= d) && (
'9' >= d)) ||
3277 ((
'A' <= d) && (
'F' >= d)) ||
3278 ((
'a' <= d) && (
'f' >= d)))
3306 to_be_processed = available;
3308 left_unprocessed = to_be_processed;
3322 _ (
"Application reported internal error, " \
3323 "closing connection."));
3326 if (left_unprocessed > to_be_processed)
3331 ,
_ (
"libmicrohttpd API violation.\n")
3336 if (0 != left_unprocessed)
3338 instant_retry =
false;
3346 _ (
"WARNING: incomplete upload processing and connection " \
3347 "not suspended may result in hung connection.\n"));
3350 processed_size = to_be_processed - left_unprocessed;
3354 buffer_head += processed_size;
3355 available -= processed_size;
3363 }
while (instant_retry);
3365 if ( (available > 0) &&
3396 connection->
state = next_state;
3417 colon = strchr (line,
':');
3430 white = strchr (line,
' ');
3431 if ( (
NULL != white) &&
3434 white = strchr (line,
'\t');
3435 if ( (
NULL != white) &&
3442 while ( (
'\0' != colon[0]) &&
3443 ( (
' ' == colon[0]) ||
3444 (
'\t' == colon[0]) ) )
3451 connection->
last = line;
3452 connection->
colon = colon;
3472 char *
const last_value = connection->
colon;
3473 const size_t last_value_len = strlen (last_value);
3477 if ( (
' ' == line[0]) ||
3482 size_t num_to_replace = ((size_t) (line - last_value)) - last_value_len;
3485 mhd_assert ((2 == num_to_replace) || (1 == num_to_replace));
3487 last_value[last_value_len] =
' ';
3488 if (0 != --num_to_replace)
3489 last_value[last_value_len + 1] =
' ';
3495 strlen (connection->
last),
3546 MHD_DLOG (connection->
daemon,
3547 _ (
"Received HTTP/1.1 request without `Host' header.\n"));
3584 if ( (val_len != num_digits) ||
3588 if ((0 == num_digits) &&
3590 (
'0' <= clen[0]) && (
'9' >= clen[0]))
3593 MHD_DLOG (connection->
daemon,
3594 _ (
"Too large value of 'Content-Length' header. " \
3595 "Closing connection.\n"));
3604 MHD_DLOG (connection->
daemon,
3605 _ (
"Failed to parse `Content-Length' header. " \
3606 "Closing connection.\n"));
3642#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3652#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3697 bytes_read = connection->
recv_cls (connection,
3702 if ((bytes_read < 0) || socket_error)
3706 if ((bytes_read > 0) && connection->
sk_nonblck)
3709 bytes_read = connection->
recv_cls (connection, &dummy,
sizeof (dummy));
3713 if ( (MHD_CONNECTION_INIT < connection->state) &&
3717 MHD_DLOG (connection->
daemon,
3718 _ (
"Socket has been disconnected when reading request.\n"));
3729 MHD_DLOG (connection->
daemon,
3730 _ (
"Connection socket is closed when reading " \
3731 "request due to the error: %s\n"),
3732 (bytes_read < 0) ? str_conn_error_ (bytes_read) :
3733 "detected connection closure");
3740 if (0 == bytes_read)
3743 if ( (MHD_CONNECTION_INIT < connection->state) &&
3747 MHD_DLOG (connection->
daemon,
3748 _ (
"Connection was closed by remote side with incomplete "
3768 MHD_DLOG (connection->
daemon,
3769 _ (
"In function %s handling connection at state: %s\n"),
3771 MHD_state_to_string (connection->
state));
3773 switch (connection->
state)
3795#ifdef UPGRADE_SUPPORT
3796 case MHD_CONNECTION_UPGRADE:
3845 MHD_DLOG (connection->
daemon,
3846 _ (
"In function %s handling connection at state: %s\n"),
3848 MHD_state_to_string (connection->
state));
3850 switch (connection->
state)
3873 MHD_DLOG (connection->
daemon,
3874 _ (
"Failed to send data in request for %s.\n"),
3881#if _MHD_DEBUG_SEND_DATA
3883 _ (
"Sent 100 continue response: `%.*s'\n"),
3959 MHD_DLOG (connection->
daemon,
3960 _ (
"Failed to send the response headers for the " \
3961 "request for `%s'. Error: %s\n"),
3963 str_conn_error_ (ret));
3970 if (((
size_t) ret) > wb_ready)
3996 uint64_t data_write_offset;
3998#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4007#if defined(_MHD_HAVE_SENDFILE)
4008 if (MHD_resp_sender_sendfile == connection->resp_sender)
4011 ret = MHD_send_sendfile_ (connection);
4025 if (data_write_offset > (uint64_t)
SIZE_MAX)
4026 MHD_PANIC (
_ (
"Data offset exceeds limit.\n"));
4029 [(
size_t) data_write_offset],
4031 - (
size_t) data_write_offset,
4033#if _MHD_DEBUG_SEND_DATA
4036 _ (
"Sent %d-byte DATA response: `%.*s'\n"),
4043#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4052 MHD_DLOG (connection->
daemon,
4053 _ (
"Failed to send the response body for the " \
4054 "request for `%s'. Error: %s\n"),
4056 str_conn_error_ (ret));
4084 MHD_DLOG (connection->
daemon,
4085 _ (
"Failed to send the chunked response body for the " \
4086 "request for `%s'. Error: %s\n"),
4088 str_conn_error_ (ret));
4120 MHD_DLOG (connection->
daemon,
4121 _ (
"Failed to send the footers for the " \
4122 "request for `%s'. Error: %s\n"),
4124 str_conn_error_ (ret));
4142#ifdef UPGRADE_SUPPORT
4143 case MHD_CONNECTION_UPGRADE:
4150 _ (
"Internal error.\n"));
4168 uint64_t since_actv;
4178 if (timeout < since_actv)
4185 if (5000 >= jump_back)
4189 _ (
"Detected system clock %u milliseconds jump back.\n"),
4190 (
unsigned int) jump_back);
4196 _ (
"Detected too large system clock %" PRIu64 " milliseconds "
4219#ifdef MHD_USE_THREADS
4221 MHD_thread_ID_match_current_ (connection->
pid) );
4232#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4264#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4272 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4273 (! MHD_itc_activate_ (daemon->
itc,
"c")) )
4278 "Failed to signal end of connection via inter-thread communication channel.\n"));
4317 size_t new_read_buf_size;
4391#ifdef MHD_USE_THREADS
4393 MHD_thread_ID_match_current_ (connection->
pid) );
4404 if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
4411 _ (
"In function %s handling connection at state: %s\n"),
4413 MHD_state_to_string (connection->
state));
4415 switch (connection->
state)
4662 _ (
"Closing connection (failed to create "
4663 "response header).\n"));
4674#ifdef UPGRADE_SUPPORT
4677 connection->
state = MHD_CONNECTION_UPGRADE;
4713#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4719#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4731#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4747#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4755#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4767#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4786 "Closing connection (failed to create response footer)."));
4820#ifdef UPGRADE_SUPPORT
4821 case MHD_CONNECTION_UPGRADE:
4844 ret = MHD_connection_epoll_update_ (connection);
4875 struct epoll_event event;
4877 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
4878 event.data.ptr = connection;
4879 if (0 != epoll_ctl (daemon->epoll_fd,
4887 _ (
"Call to epoll_ctl failed: %s\n"),
4934 if (
NULL == connection->tls_session)
4936 connection->cipher = gnutls_cipher_get (connection->tls_session);
4939 if (
NULL == connection->tls_session)
4941 connection->protocol = gnutls_protocol_get_version (
4942 connection->tls_session);
4945 if (
NULL == connection->tls_session)
4964 connection_timeout_dummy;
4996 unsigned int ui_val;
4998 daemon = connection->
daemon;
5004#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5019 va_start (ap, option);
5020 ui_val = va_arg (ap,
unsigned int);
5022#if (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT
5026 MHD_DLOG (connection->
daemon,
5027 _ (
"The specified connection timeout (%u) is too " \
5028 "large. Maximum allowed value (%" PRIu64 ") will be used " \
5050#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5079 unsigned int status_code,
5084 if ((
NULL == connection) || (
NULL == response))
5087 daemon = connection->
daemon;
5089#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5092 (! MHD_thread_ID_match_current_ (connection->
pid)) )
5096 _ (
"Attempted to queue response on wrong thread!\n"));
5111#ifdef UPGRADE_SUPPORT
5112 if (
NULL != response->upgrade_handler)
5119 _ (
"Attempted 'upgrade' connection on daemon without" \
5120 " MHD_ALLOW_UPGRADE option!\n"));
5128 _ (
"Application used invalid status code for" \
5129 " 'upgrade' response!\n"));
5137 _ (
"Application used invalid response" \
5138 " without \"Connection\" header!\n"));
5151 _ (
"Application used invalid response" \
5152 " without \"upgrade\" token in" \
5153 " \"Connection\" header!\n"));
5161 _ (
"Connection \"Upgrade\" can be used " \
5162 "with HTTP/1.1 connections!\n"));
5173 _ (
"Refused wrong status code (%u). " \
5174 "HTTP requires three digits status code!\n"),
5185 _ (
"Wrong status code (%u) refused. " \
5186 "HTTP/1.0 clients do not support 1xx status codes!\n"),
5196 _ (
"Wrong status code (%u) refused. " \
5197 "HTTP/1.0 reply mode does not support 1xx status codes!\n"),
5207#if defined(_MHD_HAVE_SENDFILE)
5208 if ( (response->
fd == -1) ||
5212 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE)
5217 connection->resp_sender = MHD_resp_sender_std;
5219 connection->resp_sender = MHD_resp_sender_sendfile;
#define REQUEST_CONTENTLENGTH_TOOLARGE
static void connection_close_error_check(struct MHD_Connection *connection, const char *emsg)
static enum MHD_Result build_connection_chunked_response_footer(struct MHD_Connection *connection)
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
static bool is_reply_body_headers_needed(struct MHD_Connection *connection)
static enum MHD_Result build_header_response(struct MHD_Connection *connection)
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
static enum MHD_Result process_header_line(struct MHD_Connection *connection, char *line)
static void * connection_alloc_memory(struct MHD_Connection *connection, size_t size)
#define MHD_lookup_header_s_token_ci(c, h, tkn)
#define REQUEST_CHUNK_TOO_LARGE
void MHD_connection_handle_write(struct MHD_Connection *connection)
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
#define buffer_append_s(buf, ppos, buf_size, str)
static bool add_user_headers(char *buf, size_t *ppos, size_t buf_size, struct MHD_Response *response, enum MHD_ValueKind kind, bool filter_transf_enc, bool add_close, bool add_keep_alive)
static enum MHD_Result try_ready_normal_body(struct MHD_Connection *connection)
#define REQUEST_CHUNKED_MALFORMED
#define REQ_HTTP_VER_IS_NOT_SUPPORTED
static void call_connection_handler(struct MHD_Connection *connection)
static void process_request_body(struct MHD_Connection *connection)
static void setup_reply_properties(struct MHD_Connection *connection)
#define HTTP_100_CONTINUE
static enum MHD_Result parse_cookie_header(struct MHD_Connection *connection)
#define transmit_error_response_static(c, code, msg)
#define REQUEST_MALFORMED
static void connection_shrink_read_buffer(struct MHD_Connection *connection)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
#define REQ_HTTP_VER_IS_TOO_OLD
static bool connection_check_timedout(struct MHD_Connection *c)
static enum MHD_ConnKeepAlive keepalive_possible(struct MHD_Connection *connection)
#define REQUEST_LACKS_HOST
static bool try_grow_read_buffer(struct MHD_Connection *connection, bool required)
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
static enum MHD_Result parse_http_std_method(struct MHD_Connection *connection, const char *method, size_t len)
static bool need_100_continue(struct MHD_Connection *connection)
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
#define CONNECTION_CLOSE_ERROR_CHECK(c, emsg)
static void cleanup_connection(struct MHD_Connection *connection)
static bool is_reply_body_needed(struct MHD_Connection *connection)
static enum MHD_Result process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
static enum MHD_Result try_ready_chunked_body(struct MHD_Connection *connection, bool *p_finished)
static bool get_date_str(char *date)
static void connection_reset(struct MHD_Connection *connection, bool reuse)
void MHD_connection_handle_read(struct MHD_Connection *connection, bool socket_error)
static void transmit_error_response_len(struct MHD_Connection *connection, unsigned int status_code, const char *message, size_t message_len)
static void connection_switch_from_recv_to_send(struct MHD_Connection *connection)
static void parse_connection_headers(struct MHD_Connection *connection)
void MHD_update_last_activity_(struct MHD_Connection *connection)
#define REQUEST_CONTENTLENGTH_MALFORMED
static enum MHD_Result parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
static size_t connection_maximize_write_buffer(struct MHD_Connection *connection)
static enum MHD_Result connection_add_header(struct MHD_Connection *connection, const char *key, size_t key_size, const char *value, size_t value_size, enum MHD_ValueKind kind)
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
#define CONNECTION_CLOSE_ERROR(c, emsg)
static bool buffer_append(char *buf, size_t *ppos, size_t buf_size, const char *append, size_t append_size)
static enum MHD_Result check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
static enum MHD_Result parse_http_version(struct MHD_Connection *connection, const char *http_string, size_t len)
static bool get_date_header(char *header)
static bool MHD_lookup_header_token_ci(const struct MHD_Connection *connection, const char *header, size_t header_len, const char *token, size_t token_len)
Methods for managing connections.
#define MHD_connection_finish_forward_(conn)
#define MHD_ERR_OPNOTSUPP_
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
Methods for managing connections.
#define MHD_HTTP_INTERNAL_SERVER_ERROR
#define MHD_HTTP_URI_TOO_LONG
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
#define MHD_HTTP_PROCESSING
#define MHD_HTTP_SWITCHING_PROTOCOLS
#define MHD_HTTP_HTTP_VERSION_NOT_SUPPORTED
#define MHD_HTTP_CONTENT_TOO_LARGE
#define MHD_HTTP_NOT_MODIFIED
#define MHD_HTTP_NO_CONTENT
#define MHD_HTTP_BAD_REQUEST
#define MHD_HTTP_METHOD_TRACE
#define MHD_HTTP_METHOD_OPTIONS
#define MHD_HTTP_METHOD_GET
#define MHD_HTTP_METHOD_HEAD
#define MHD_HTTP_METHOD_POST
#define MHD_HTTP_METHOD_PUT
#define MHD_HTTP_METHOD_CONNECT
#define MHD_HTTP_METHOD_DELETE
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
_MHD_EXTERN int MHD_get_connection_values_n(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIteratorN iterator, void *iterator_cls)
_MHD_EXTERN enum MHD_Result MHD_set_connection_value_n(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, size_t key_size, const char *value, size_t value_size)
enum MHD_Result(* MHD_KeyValueIteratorN)(void *cls, enum MHD_ValueKind kind, const char *key, size_t key_size, const char *value, size_t value_size)
static enum MHD_Result MHD_set_connection_value_n_nocheck_(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, size_t key_size, const char *value, size_t value_size)
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
_MHD_EXTERN enum MHD_Result MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
_MHD_EXTERN enum MHD_Result MHD_lookup_connection_value_n(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, size_t key_size, const char **value_ptr, size_t *value_size_ptr)
MHD_RequestTerminationCode
@ MHD_CONNECTION_INFO_CONNECTION_TIMEOUT
@ MHD_CONNECTION_INFO_SOCKET_CONTEXT
@ MHD_CONNECTION_INFO_GNUTLS_SESSION
@ MHD_CONNECTION_INFO_REQUEST_HEADER_SIZE
@ MHD_CONNECTION_INFO_CIPHER_ALGO
@ MHD_CONNECTION_INFO_CONNECTION_SUSPENDED
@ MHD_CONNECTION_INFO_CLIENT_ADDRESS
@ MHD_CONNECTION_INFO_DAEMON
@ MHD_CONNECTION_INFO_HTTP_STATUS
@ MHD_CONNECTION_INFO_CONNECTION_FD
@ MHD_CONNECTION_INFO_PROTOCOL
@ MHD_REQUEST_TERMINATED_TIMEOUT_REACHED
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
@ MHD_REQUEST_TERMINATED_WITH_ERROR
@ MHD_REQUEST_TERMINATED_READ_ERROR
@ MHD_REQUEST_TERMINATED_CLIENT_ABORT
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
_MHD_EXTERN enum MHD_Result MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
_MHD_EXTERN enum MHD_Result MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
#define MHD_HTTP_VERSION_1_0
#define MHD_HTTP_VERSION_1_1
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
#define MHD_ERR_CONNRESET_
#define XDLL_insert(head, tail, element)
MHD_PanicCallback mhd_panic
@ MHD_EPOLL_STATE_SUSPENDED
@ MHD_EPOLL_STATE_READ_READY
@ MHD_EPOLL_STATE_IN_EPOLL_SET
@ MHD_EPOLL_STATE_WRITE_READY
#define DLL_insert(head, tail, element)
@ MHD_CONN_KEEPALIVE_UNKOWN
#define EDLL_remove(head, tail, element)
#define XDLL_remove(head, tail, element)
#define DLL_remove(head, tail, element)
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
void MHD_pool_destroy(struct MemoryPool *pool)
size_t MHD_pool_get_free(struct MemoryPool *pool)
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
#define MHD_mutex_unlock_chk_(pmutex)
#define MHD_mutex_lock_chk_(pmutex)
#define MHD_SCKT_ERR_IS_(err, code)
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
#define MHD_socket_last_strerr_()
#define MHD_SCKT_EOPNOTSUPP_
#define MHD_socket_get_error_()
#define MHD_SCKT_ERR_IS_REMOTE_DISCNN_(err)
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MHD_SCKT_ENOTCONN_
#define MHD_recv_(s, b, l)
int MHD_str_equal_caseless_(const char *str1, const char *str2)
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
#define MHD_str_has_s_token_caseless_(str, tkn)
#define MHD_STATICSTR_LEN_(macro)
ssize_t MHD_send_hdr_and_body_(struct MHD_Connection *connection, const char *header, size_t header_size, bool never_push_hdr, const char *body, size_t body_size, bool complete_response)
ssize_t MHD_send_iovec_(struct MHD_Connection *connection, struct MHD_iovec_track_ *const r_iov, bool push_data)
ssize_t MHD_send_data_(struct MHD_Connection *connection, const char *buffer, size_t buffer_size, bool push_data)
Declarations of send() wrappers.
MHD internal shared structures.
@ MHD_CONNECTION_BODY_RECEIVED
@ MHD_CONNECTION_HEADER_PART_RECEIVED
@ MHD_CONNECTION_HEADERS_SENDING
@ MHD_CONNECTION_FOOTERS_SENDING
@ MHD_CONNECTION_FOOTERS_RECEIVED
@ MHD_CONNECTION_HEADERS_SENT
@ MHD_CONNECTION_HEADERS_PROCESSED
@ MHD_CONNECTION_NORMAL_BODY_UNREADY
@ MHD_CONNECTION_HEADERS_RECEIVED
@ MHD_CONNECTION_NORMAL_BODY_READY
@ MHD_CONNECTION_START_REPLY
@ MHD_CONNECTION_CHUNKED_BODY_READY
@ MHD_CONNECTION_FOOTER_PART_RECEIVED
@ MHD_CONNECTION_CONTINUE_SENT
@ MHD_CONNECTION_FOOTERS_SENT
@ MHD_CONNECTION_FULL_REQ_RECEIVED
@ MHD_CONNECTION_CHUNKED_BODY_UNREADY
@ MHD_CONNECTION_BODY_SENT
@ MHD_CONNECTION_CONTINUE_SENDING
@ MHD_CONNECTION_URL_RECEIVED
@ MHD_CONNECTION_REQ_LINE_RECEIVING
@ MHD_TLS_CONN_HANDSHAKING
@ MHD_EVENT_LOOP_INFO_READ
@ MHD_EVENT_LOOP_INFO_WRITE
@ MHD_EVENT_LOOP_INFO_CLEANUP
@ MHD_EVENT_LOOP_INFO_BLOCK
struct MHD_IoVec MHD_iovec_
#define MHD_IS_HTTP_VER_SUPPORTED(ver)
@ MHD_RAF_HAS_CONNECTION_CLOSE
@ MHD_RAF_HAS_TRANS_ENC_CHUNKED
@ MHD_RAF_HAS_CONNECTION_HDR
#define MHD_IS_HTTP_VER_1_1_COMPAT(ver)
@ MHD_HTTP_MTHD_NO_METHOD
void * MHD_pool_try_alloc(struct MemoryPool *pool, size_t size, size_t *required_bytes)
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
Header for platform missing functions.
Header for platform-independent inter-thread communication.
limits values definitions
uint64_t MHD_monotonic_msec_counter(void)
internal monotonic clock functions implementations
#define MHD_SEND_SPIPE_SUPPRESS_NEEDED
size_t MHD_uint8_to_str_pad(uint8_t val, uint8_t min_digits, char *buf, size_t buf_size)
size_t MHD_uint16_to_str(uint16_t val, char *buf, size_t buf_size)
size_t MHD_uint64_to_str(uint64_t val, char *buf, size_t buf_size)
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
size_t MHD_uint32_to_strx(uint32_t val, char *buf, size_t buf_size)
Header for string manipulating helpers.
void MHD_increment_response_rc(struct MHD_Response *response)
#define MHD_CONTENT_READER_END_OF_STREAM
_MHD_EXTERN size_t MHD_get_reason_phrase_len_for(unsigned int code)
#define MHD_INVALID_SOCKET
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_CONTENT_READER_END_WITH_ERROR
@ MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_SUPPRESS_DATE_NO_CLOCK
@ MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_RF_SEND_KEEP_ALIVE_HEADER
@ MHD_RF_HTTP_1_0_COMPATIBLE_STRICT
@ MHD_CONNECTION_OPTION_TIMEOUT
Methods for managing response objects.
enum MHD_Result MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
enum MHD_HTTP_Method http_mthd
size_t write_buffer_send_offset
struct MHD_Reply_Properties rp_props
enum MHD_HTTP_Version http_ver
enum MHD_ConnectionEventLoopInfo event_loop_info
size_t write_buffer_append_offset
uint64_t remaining_upload_size
struct MHD_Response * response
enum MHD_ConnKeepAlive keepalive
struct MHD_HTTP_Header * headers_received
size_t continue_message_write_offset
uint64_t response_write_position
struct sockaddr_storage addr
struct MHD_HTTP_Header * headers_received_tail
uint64_t current_chunk_offset
size_t read_buffer_offset
uint64_t current_chunk_size
struct MHD_iovec_track_ resp_iov
unsigned int responseCode
MHD_thread_handle_ID_ pid
enum MHD_CONNECTION_STATE state
struct MHD_Daemon * daemon
unsigned int connection_timeout_dummy
uint64_t connection_timeout_ms
MHD_AccessHandlerCallback default_handler
LogCallback uri_log_callback
void * unescape_callback_cls
MHD_mutex_ cleanup_connection_mutex
struct MHD_Connection * connections_head
MHD_RequestCompletedCallback notify_completed
uint64_t connection_timeout_ms
struct MHD_Connection * manual_timeout_tail
UnescapeCallback unescape_callback
void * notify_completed_cls
struct MHD_Connection * cleanup_tail
MHD_thread_handle_ID_ pid
struct MHD_Connection * manual_timeout_head
void * default_handler_cls
struct MHD_Connection * suspended_connections_tail
struct MHD_Connection * cleanup_head
struct MHD_Connection * normal_timeout_head
struct MHD_Connection * normal_timeout_tail
void * uri_log_callback_cls
struct MHD_Connection * suspended_connections_head
struct MHD_Connection * connections_tail
bool use_reply_body_headers
struct MHD_HTTP_Header * first_header
enum MHD_HTTP_StatusCode status_code
MHD_ContentReaderCallback crc
enum MHD_ResponseAutoFlags flags_auto
enum MHD_ResponseFlags flags