34 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
35 #include "mhd_locks.h"
40 #ifdef MHD_LINUX_SOLARIS_SENDFILE
41 #include <sys/sendfile.h>
43 #if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
44 #include <sys/types.h>
45 #include <sys/socket.h>
51 #ifdef HAVE_SYS_PARAM_H
53 #include <sys/param.h>
60 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
70 #define REQUEST_TOO_BIG \
71 "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
73 #define REQUEST_TOO_BIG ""
84 #define REQUEST_LACKS_HOST \
85 "<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>"
87 #define REQUEST_LACKS_HOST ""
98 #define REQUEST_MALFORMED \
99 "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
101 #define REQUEST_MALFORMED ""
111 #define INTERNAL_ERROR \
112 "<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>"
114 #define INTERNAL_ERROR ""
121 #define MHD_SENFILE_CHUNK_ (0x20000)
126 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
135 str_conn_error_ (ssize_t mhd_err_code)
137 switch (mhd_err_code)
140 return _ (
"The operation would block, retry later");
142 return _ (
"The connection was forcibly closed by remote peer");
144 return _ (
"The socket is not connected");
146 return _ (
"Not enough system resources to serve the request");
148 return _ (
"Bad FD value");
150 return _ (
"Argument value is invalid");
152 return _ (
"Argument value is not supported");
154 return _ (
"The socket is no longer available for sending");
156 return _ (
"TLS encryption or decryption error");
160 if (0 <= mhd_err_code)
161 return _ (
"Not an error code");
164 return _ (
"Wrong error code value");
226 else if (i > (
size_t) ret)
254 if (
NULL == connection)
261 if ( (
NULL != iterator) &&
262 (
MHD_NO == iterator (iterator_cls,
293 if (
NULL == connection)
297 if (
NULL == iterator)
308 if (
MHD_NO == iterator (iterator_cls,
352 pos->
header = (
char *) key;
407 ( ((key ? strlen (key) : 0) != key_size) ||
485 (
NULL == key) ? 0 : strlen (key),
516 const char **value_ptr,
517 size_t *value_size_ptr)
521 if (
NULL == connection)
550 if (
NULL != value_ptr)
551 *value_ptr = pos->
value;
553 if (
NULL != value_size_ptr)
618 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
619 MHD_lookup_header_token_ci ((c),(h),MHD_STATICSTR_LEN_ (h), \
620 (tkn),MHD_STATICSTR_LEN_ (tkn))
701 #ifdef MHD_USE_THREADS
703 MHD_thread_ID_match_current_ (connection->
pid) );
722 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
737 struct MHD_UpgradeResponseHandle *urh = connection->urh;
739 #ifdef MHD_USE_THREADS
742 MHD_thread_ID_match_current_ (daemon->
pid) );
754 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
759 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
761 if (urh->in_eready_list)
764 daemon->eready_urh_tail,
766 urh->in_eready_list =
false;
773 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
778 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
783 shutdown (urh->mhd.socket, SHUT_RDWR);
809 MHD_DLOG (connection->
daemon,
825 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
827 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
868 _ (
"Closing connection (out of memory)."));
885 #if defined(_MHD_HAVE_SENDFILE)
886 if (MHD_resp_sender_sendfile == connection->resp_sender)
904 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
913 "Closing connection (application reported error generating data)."));
921 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
957 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
962 _ (
"Closing connection (out of memory)."));
965 if ( (2 * (0xFFFFFF +
sizeof(cbuf) + 2)) < size)
966 size = 2 * (0xFFFFFF +
sizeof(cbuf) + 2);
983 const size_t data_write_offset
986 ret = response->
data_size - data_write_offset;
990 &response->
data[data_write_offset],
1005 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1010 "Closing connection (application error generating response)."));
1028 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1035 cblen = MHD_snprintf_ (cbuf,
1038 (
unsigned int) ret);
1041 memcpy (&connection->
write_buffer[sizeof (cbuf) - cblen],
1044 memcpy (&connection->
write_buffer[sizeof (cbuf) + ret],
1124 static const char *
const days[] = {
1125 "Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
1127 static const char *
const mons[] = {
1128 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
1129 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
1133 #if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1134 ! defined(HAVE_GMTIME_R)
1140 #if defined(HAVE_C11_GMTIME_S)
1141 if (
NULL == gmtime_s (&t,
1144 #elif defined(HAVE_W32_GMTIME_S)
1145 if (0 != gmtime_s (&now,
1148 #elif defined(HAVE_GMTIME_R)
1149 if (
NULL == gmtime_r (&t,
1158 MHD_snprintf_ (date,
1160 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1161 days[now.tm_wday % 7],
1162 (
unsigned int) now.tm_mday,
1163 mons[now.tm_mon % 12],
1164 (
unsigned int) (1900 + now.tm_year),
1165 (
unsigned int) now.tm_hour,
1166 (
unsigned int) now.tm_min,
1167 (
unsigned int) now.tm_sec);
1192 if (0 == avail_size)
1195 new_size = avail_size / 2;
1200 grow_size = avail_size / 8;
1209 if (small_inc < avail_size)
1210 grow_size = small_inc;
1212 grow_size = avail_size;
1259 char content_length_buf[128];
1260 size_t content_length_len;
1263 const char *reason_phrase;
1265 bool client_requested_close;
1266 bool response_has_close;
1267 bool response_has_keepalive;
1268 const char *have_encoding;
1269 bool must_add_close;
1270 bool must_add_chunked_encoding;
1271 bool must_add_keep_alive;
1272 bool must_add_content_length;
1273 bool may_add_content_length;
1276 if (0 == connection->
version[0])
1291 off = MHD_snprintf_ (code,
1315 datelen = strlen (date);
1329 must_add_close =
false;
1330 must_add_chunked_encoding =
false;
1331 must_add_keep_alive =
false;
1332 must_add_content_length =
false;
1333 content_length_len = 0;
1334 response_has_close =
false;
1335 switch (connection->
state)
1350 #ifdef UPGRADE_SUPPORT
1351 else if (
NULL != response->upgrade_handler)
1360 if (
NULL == have_encoding)
1361 may_add_content_length =
true;
1363 may_add_content_length =
false;
1365 #ifdef UPGRADE_SUPPORT
1366 (
NULL == response->upgrade_handler) &&
1368 (! response_has_close) &&
1369 (! client_requested_close) )
1380 if (
NULL == have_encoding)
1382 must_add_chunked_encoding =
true;
1391 must_add_close =
true;
1404 must_add_close =
true;
1409 if ( ( (client_requested_close) ||
1412 (! response_has_close) &&
1413 #ifdef UPGRADE_SUPPORT
1414 (
NULL == response->upgrade_handler) &&
1417 must_add_close =
true;
1421 if ( (! may_add_content_length) &&
1423 (! response_has_close) )
1424 must_add_close =
true;
1437 (may_add_content_length) &&
1458 = MHD_snprintf_ (content_length_buf,
1459 sizeof (content_length_buf),
1463 must_add_content_length =
true;
1467 if ( (! response_has_keepalive) &&
1468 (! response_has_close) &&
1469 (! must_add_close) &&
1471 #ifdef UPGRADE_SUPPORT
1472 (
NULL == response->upgrade_handler) &&
1475 must_add_keep_alive =
true;
1478 response_has_keepalive =
false;
1487 if ( (must_add_close) || (response_has_close) )
1489 else if ( (must_add_keep_alive) || (response_has_keepalive) )
1495 if (must_add_keep_alive)
1497 if (must_add_chunked_encoding)
1499 if (must_add_content_length)
1500 size += content_length_len;
1501 mhd_assert (! (must_add_close && must_add_keep_alive) );
1502 mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1508 (! ( (must_add_close) &&
1509 (response_has_keepalive) &&
1517 "Keep-Alive")) ) ) )
1526 #ifdef HAVE_MESSAGES
1527 MHD_DLOG (connection->
daemon,
1528 "Not enough memory for write!\n");
1542 "Connection: close\r\n",
1546 if (must_add_keep_alive)
1550 "Connection: Keep-Alive\r\n",
1554 if (must_add_chunked_encoding)
1558 "Transfer-Encoding: chunked\r\n",
1562 if (must_add_content_length)
1567 content_length_len);
1568 off += content_length_len;
1574 (! ( (must_add_close) &&
1575 (response_has_keepalive) &&
1583 "Keep-Alive")) ) ) )
1584 off += MHD_snprintf_ (&
data[off],
1626 unsigned int status_code,
1627 const char *message)
1650 #ifdef HAVE_MESSAGES
1651 MHD_DLOG (connection->
daemon,
1653 "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1665 if (
NULL == response)
1680 "Closing connection (failed to queue response)."));
1691 "Closing connection (failed to create response header)."));
1714 #ifdef HTTPS_SUPPORT
1717 switch (connection->tls_state)
1723 if (0 == gnutls_record_get_direction (connection->tls_session))
1736 MHD_DLOG (connection->
daemon,
1737 _ (
"In function %s handling connection at state: %s\n"),
1739 MHD_state_to_string (connection->
state));
1741 switch (connection->
state)
1775 const bool internal_poll = (0 != (connection->
daemon->
options
1851 #ifdef UPGRADE_SUPPORT
1852 case MHD_CONNECTION_UPGRADE:
1888 while ( (pos < connection->read_buffer_offset - 1) &&
1889 (
'\r' != rbuf[pos]) &&
1890 (
'\n' != rbuf[pos]) )
1893 (
'\n' != rbuf[pos]) )
1913 if ( (
'\r' == rbuf[pos]) &&
1914 (
'\n' == rbuf[pos + 1]) )
1953 #ifdef HAVE_MESSAGES
1954 MHD_DLOG (connection->
daemon,
1955 _ (
"Not enough memory in pool to allocate header record!\n"));
2000 #ifdef HAVE_MESSAGES
2001 MHD_DLOG (connection->
daemon,
2002 _ (
"Not enough memory in pool to parse cookies!\n"));
2012 cpy[hdr_len] =
'\0';
2020 while ( ((*sce) !=
'\0') &&
2027 while ( (*ekill ==
' ') &&
2051 while ( (
'\0' != semicolon[0]) &&
2053 ( (
';' != semicolon[0]) &&
2054 (
',' != semicolon[0]) ) ) )
2056 if (
'"' == semicolon[0])
2057 quotes = (quotes + 1) & 1;
2061 if (
'\0' == semicolon[0])
2063 if (
NULL != semicolon)
2065 semicolon[0] =
'\0';
2069 if ( (
'"' == equals[0]) &&
2108 unsigned int unused_num_headers;
2110 if (
NULL == (uri = memchr (line,
2115 connection->
method = line;
2119 while ( (
' ' == uri[0]) &&
2120 ( (
size_t) (uri - line) < line_len) )
2122 if ((
size_t) (uri - line) == line_len)
2135 http_version = line + line_len - 1;
2137 while ( (
' ' == http_version[0]) &&
2138 (http_version > uri) )
2141 while ( (
' ' != http_version[0]) &&
2142 (http_version > uri) )
2144 if (http_version > uri)
2147 http_version[0] =
'\0';
2148 connection->
version = http_version + 1;
2149 uri_len = http_version - uri;
2154 uri_len = line_len - (uri - line);
2158 (
NULL != memchr (uri,
2190 &unused_num_headers);
2198 connection->
url = curi;
2233 "Application reported internal error, closing connection."));
2275 size_t to_be_processed;
2276 size_t left_unprocessed;
2277 size_t processed_size;
2291 if ( (
'\r' == buffer_head[i]) ||
2292 (
'\n' == buffer_head[i]) )
2294 if ( (
'\r' == buffer_head[i]) ||
2295 (
'\n' == buffer_head[i]) )
2302 "Received malformed HTTP request (bad chunked encoding). Closing connection."));
2313 uint64_t cur_chunk_left;
2319 if (cur_chunk_left > available)
2320 to_be_processed = available;
2323 to_be_processed = (size_t) cur_chunk_left;
2324 if (available > to_be_processed)
2336 while (i < available)
2338 if ( (
'\r' == buffer_head[i]) ||
2339 (
'\n' == buffer_head[i]) ||
2340 (
';' == buffer_head[i]) )
2348 if (
';' == buffer_head[i])
2350 while (i < available)
2352 if ( (
'\r' == buffer_head[i]) ||
2353 (
'\n' == buffer_head[i]) )
2361 if ( (i + 1 >= available) &&
2364 (
'0' == buffer_head[0]) ) )
2367 malformed = (end_size >= 16);
2373 current_chunk_size);
2374 malformed = (end_size != num_dig);
2381 "Received malformed HTTP request (bad chunked encoding). Closing connection."));
2385 if ( (i < available) &&
2386 ( (
'\r' == buffer_head[i]) ||
2387 (
'\n' == buffer_head[i]) ) )
2419 to_be_processed = available;
2422 left_unprocessed = to_be_processed;
2437 "Application reported internal error, closing connection."));
2440 if (left_unprocessed > to_be_processed)
2444 #ifdef HAVE_MESSAGES
2445 ,
_ (
"libmicrohttpd API violation.\n")
2450 if (0 != left_unprocessed)
2453 #ifdef HAVE_MESSAGES
2461 "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2464 processed_size = to_be_processed - left_unprocessed;
2468 buffer_head += processed_size;
2469 available -= processed_size;
2473 while (
MHD_NO != instant_retry);
2474 if ( (available > 0) &&
2502 connection->
state = next_state;
2529 colon = strchr (line,
':');
2535 "Received malformed line (no colon). Closing connection."));
2545 white = strchr (line,
' ');
2546 if ( (
NULL != white) &&
2549 white = strchr (line,
'\t');
2550 if ( (
NULL != white) &&
2557 while ( (
'\0' != colon[0]) &&
2558 ( (
' ' == colon[0]) ||
2559 (
'\t' == colon[0]) ) )
2566 connection->
last = line;
2567 connection->
colon = colon;
2592 last = connection->
last;
2593 if ( (
' ' == line[0]) ||
2598 last_len = strlen (last);
2601 while ( (
' ' == tmp[0]) ||
2604 tmp_len = strlen (tmp);
2617 last_len + tmp_len + 1);
2625 memcpy (&last[last_len],
2628 connection->
last = last;
2638 strlen (connection->
colon),
2696 #ifdef HAVE_MESSAGES
2697 MHD_DLOG (connection->
daemon,
2698 _ (
"Received HTTP 1.1 request without `Host' header.\n"));
2705 if (
NULL == response)
2710 "Closing connection (failed to create response)."));
2722 "Closing connection (failed to queue response)."));
2753 if ( (clen == end) ||
2757 #ifdef HAVE_MESSAGES
2758 MHD_DLOG (connection->
daemon,
2760 "Failed to parse `Content-Length' header. Closing connection.\n"));
2795 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2805 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2825 #ifdef HTTPS_SUPPORT
2846 bytes_read = connection->
recv_cls (connection,
2861 "Socket disconnected while reading request."));
2865 #ifdef HAVE_MESSAGES
2867 MHD_DLOG (connection->
daemon,
2868 _ (
"Connection socket is closed when reading " \
2869 "request due to the error: %s\n"),
2870 str_conn_error_ (bytes_read));
2877 if (0 == bytes_read)
2887 MHD_DLOG (connection->
daemon,
2888 _ (
"In function %s handling connection at state: %s\n"),
2890 MHD_state_to_string (connection->
state));
2892 switch (connection->
state)
2912 #ifdef UPGRADE_SUPPORT
2913 case MHD_CONNECTION_UPGRADE:
2943 #ifdef HTTPS_SUPPORT
2955 MHD_DLOG (connection->
daemon,
2956 _ (
"In function %s handling connection at state: %s\n"),
2958 MHD_state_to_string (connection->
state));
2960 switch (connection->
state)
2981 #ifdef HAVE_MESSAGES
2982 MHD_DLOG (connection->
daemon,
2983 _ (
"Failed to send data in request for %s.\n"),
2990 #if _MHD_DEBUG_SEND_DATA
2992 _ (
"Sent 100 continue response: `%.*s'\n"),
3061 #ifdef HAVE_MESSAGES
3062 MHD_DLOG (connection->
daemon,
3063 _ (
"Failed to send the response headers for the " \
3064 "request for `%s'. Error: %s\n"),
3066 str_conn_error_ (ret));
3073 if (((
size_t) ret) > wb_ready)
3098 uint64_t data_write_offset;
3100 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3109 #if defined(_MHD_HAVE_SENDFILE)
3110 if (MHD_resp_sender_sendfile == connection->resp_sender)
3113 ret = MHD_send_sendfile_ (connection);
3127 if (data_write_offset > (uint64_t)
SIZE_MAX)
3128 MHD_PANIC (
_ (
"Data offset exceeds limit.\n"));
3131 [(
size_t) data_write_offset],
3133 - (
size_t) data_write_offset,
3135 #if _MHD_DEBUG_SEND_DATA
3138 _ (
"Sent %d-byte DATA response: `%.*s'\n"),
3145 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3153 #ifdef HAVE_MESSAGES
3154 MHD_DLOG (connection->
daemon,
3155 _ (
"Failed to send the response body for the " \
3156 "request for `%s'. Error: %s\n"),
3158 str_conn_error_ (ret));
3185 #ifdef HAVE_MESSAGES
3186 MHD_DLOG (connection->
daemon,
3187 _ (
"Failed to send the chunked response body for the " \
3188 "request for `%s'. Error: %s\n"),
3190 str_conn_error_ (ret));
3221 #ifdef HAVE_MESSAGES
3222 MHD_DLOG (connection->
daemon,
3223 _ (
"Failed to send the footers for the " \
3224 "request for `%s'. Error: %s\n"),
3226 str_conn_error_ (ret));
3244 #ifdef UPGRADE_SUPPORT
3245 case MHD_CONNECTION_UPGRADE:
3252 _ (
"Internal error.\n"));
3271 #ifdef MHD_USE_THREADS
3273 MHD_thread_ID_match_current_ (connection->
pid) );
3284 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3316 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3324 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3325 (! MHD_itc_activate_ (daemon->
itc,
"c")) )
3327 #ifdef HAVE_MESSAGES
3330 "Failed to signal end of connection via inter-thread communication channel.\n"));
3354 #ifdef MHD_USE_THREADS
3356 MHD_thread_ID_match_current_ (connection->
pid) );
3362 #ifdef HTTPS_SUPPORT
3365 if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3372 _ (
"In function %s handling connection at state: %s\n"),
3374 MHD_state_to_string (connection->
state));
3376 switch (connection->
state)
3385 if ( (
NULL == line) ||
3599 "Closing connection (failed to create response header).\n"));
3609 #ifdef UPGRADE_SUPPORT
3612 connection->
state = MHD_CONNECTION_UPGRADE;
3643 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3649 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3658 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3674 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3682 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3691 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3708 "Closing connection (failed to create response header)."));
3796 #ifdef UPGRADE_SUPPORT
3797 case MHD_CONNECTION_UPGRADE:
3811 if ( (0 != timeout) &&
3823 #ifdef EPOLL_SUPPORT
3827 ret = MHD_connection_epoll_update_ (connection);
3835 #ifdef EPOLL_SUPPORT
3858 struct epoll_event event;
3860 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3861 event.data.ptr = connection;
3862 if (0 != epoll_ctl (daemon->epoll_fd,
3867 #ifdef HAVE_MESSAGES
3870 _ (
"Call to epoll_ctl failed: %s\n"),
3915 #ifdef HTTPS_SUPPORT
3917 if (
NULL == connection->tls_session)
3919 connection->cipher = gnutls_cipher_get (connection->tls_session);
3922 if (
NULL == connection->tls_session)
3924 connection->protocol = gnutls_protocol_get_version (
3925 connection->tls_session);
3928 if (
NULL == connection->tls_session)
3947 connection_timeout_dummy;
3976 daemon = connection->
daemon;
3982 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3997 va_start (ap, option);
4013 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4036 unsigned int status_code,
4041 if ( (
NULL == connection) ||
4042 (
NULL == response) ||
4047 daemon = connection->
daemon;
4053 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4056 (! MHD_thread_ID_match_current_ (connection->
pid)) )
4058 #ifdef HAVE_MESSAGES
4060 _ (
"Attempted to queue response on wrong thread!\n"));
4065 #ifdef UPGRADE_SUPPORT
4066 if ( (
NULL != response->upgrade_handler) &&
4069 #ifdef HAVE_MESSAGES
4072 "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
4077 (
NULL != response->upgrade_handler) )
4079 #ifdef HAVE_MESSAGES
4082 "Application used invalid status code for 'upgrade' response!\n"));
4090 #if defined(_MHD_HAVE_SENDFILE)
4091 if ( (response->
fd == -1) ||
4095 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE)
4100 connection->resp_sender = MHD_resp_sender_std;
4102 connection->resp_sender = MHD_resp_sender_sendfile;
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
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)
#define MHD_lookup_header_s_token_ci(c, h, tkn)
void MHD_connection_handle_read(struct MHD_Connection *connection)
void MHD_connection_handle_write(struct MHD_Connection *connection)
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
static enum MHD_Result try_ready_normal_body(struct MHD_Connection *connection)
static void call_connection_handler(struct MHD_Connection *connection)
static void process_request_body(struct MHD_Connection *connection)
#define HTTP_100_CONTINUE
static enum MHD_Result keepalive_possible(struct MHD_Connection *connection)
static enum MHD_Result parse_cookie_header(struct MHD_Connection *connection)
#define REQUEST_MALFORMED
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
#define REQUEST_LACKS_HOST
static bool try_grow_read_buffer(struct MHD_Connection *connection, bool required)
static bool need_100_continue(struct MHD_Connection *connection)
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
static void cleanup_connection(struct MHD_Connection *connection)
static enum MHD_Result try_ready_chunked_body(struct MHD_Connection *connection)
static enum MHD_Result process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
static void parse_connection_headers(struct MHD_Connection *connection)
void MHD_update_last_activity_(struct MHD_Connection *connection)
static enum MHD_Result parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
static void get_date_string(char *date, size_t date_len)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
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 enum MHD_Result check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
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_ERR_OPNOTSUPP_
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
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_NOT_MODIFIED
#define MHD_HTTP_NO_CONTENT
#define MHD_HTTP_BAD_REQUEST
#define MHD_HTTP_METHOD_HEAD
#define MHD_HTTP_METHOD_CONNECT
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_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 char * MHD_get_response_header(struct MHD_Response *response, const char *key)
_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_destroy(struct MemoryPool *pool)
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
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)
time_t MHD_monotonic_sec_counter(void)
#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_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
#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.
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_CHUNKED_BODY_READY
@ MHD_CONNECTION_FOOTER_PART_RECEIVED
@ MHD_CONNECTION_CONTINUE_SENT
@ MHD_CONNECTION_FOOTERS_SENT
@ MHD_CONNECTION_CHUNKED_BODY_UNREADY
@ MHD_CONNECTION_BODY_SENT
@ MHD_CONNECTION_CONTINUE_SENDING
@ MHD_CONNECTION_URL_RECEIVED
#define MHD_check_response_header_s_token_ci(r, k, tkn)
@ 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_
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
internal monotonic clock functions implementations
#define MHD_SEND_SPIPE_SUPPRESS_NEEDED
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Header for string manipulating helpers.
void MHD_increment_response_rc(struct MHD_Response *response)
#define MHD_CONTENT_READER_END_OF_STREAM
#define MHD_UNSIGNED_LONG_LONG
#define MHD_UNSIGNED_LONG_LONG_PRINTF
#define MHD_INVALID_SOCKET
#define MHD_CONTENT_READER_END_WITH_ERROR
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
@ MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_SUPPRESS_DATE_NO_CLOCK
@ MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_RF_HTTP_VERSION_1_0_RESPONSE
@ MHD_RF_HTTP_VERSION_1_0_ONLY
@ MHD_CONNECTION_OPTION_TIMEOUT
Methods for managing response objects.
enum MHD_Result MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t write_buffer_send_offset
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
time_t connection_timeout
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
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
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
time_t connection_timeout
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
struct MHD_HTTP_Header * first_header
enum MHD_HTTP_StatusCode status_code
MHD_ContentReaderCallback crc
enum MHD_ResponseFlags flags