30 #ifdef MHD_LINUX_SOLARIS_SENDFILE
31 #include <sys/sendfile.h>
33 #if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
34 #include <sys/types.h>
35 #include <sys/socket.h>
43 #define MHD_SENFILE_CHUNK_ (0x20000)
48 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
59 #define REQUEST_TOO_BIG \
60 "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
62 #define REQUEST_TOO_BIG ""
73 #define REQUEST_LACKS_HOST \
74 "<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>"
76 #define REQUEST_LACKS_HOST ""
87 #define REQUEST_MALFORMED \
88 "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
90 #define REQUEST_MALFORMED ""
100 #define INTERNAL_ERROR \
101 "<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>"
103 #define INTERNAL_ERROR ""
107 #ifdef HAVE_FREEBSD_SENDFILE
112 static int freebsd_sendfile_flags_;
117 static int freebsd_sendfile_flags_thd_p_c_;
127 MHD_conn_init_static_ (
void)
133 long sys_page_size = sysconf (_SC_PAGESIZE);
134 if (0 > sys_page_size)
136 freebsd_sendfile_flags_ = SF_NODISKIO;
137 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
141 freebsd_sendfile_flags_ =
143 freebsd_sendfile_flags_thd_p_c_ =
157 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
170 enum MHD_StatusCode sc,
175 MHD_DLOG (connection->
daemon,
192 #define CONNECTION_CLOSE_ERROR(c, sc, emsg) connection_close_error (c, sc, emsg)
194 #define CONNECTION_CLOSE_ERROR(c, sc, emsg) connection_close_error (c, sc, NULL)
253 if ( (
NULL != (tls = daemon->tls_api)) &&
255 connection->tls_cs)) )
269 bytes_read = connection->
recv_cls (connection,
282 ? MHD_SC_CONNECTION_CLOSED
283 : MHD_SC_CONNECTION_RESET_CLOSED,
287 "Socket disconnected while reading request.\n"));
292 ? MHD_SC_CONNECTION_CLOSED
293 : MHD_SC_CONNECTION_READ_FAIL_CLOSED,
297 "Connection socket is closed due to error when reading request.\n"));
312 MHD_SC_STATE_MACHINE_STATUS_REPORT,
313 _ (
"In function %s handling connection at state: %s\n"),
315 MHD_state_to_string (request->
state));
317 switch (request->
state)
337 #ifdef UPGRADE_SUPPORT
338 case MHD_REQUEST_UPGRADE:
354 #if defined(_MHD_HAVE_SENDFILE)
368 const int file_fd = response->
fd;
371 #ifndef HAVE_SENDFILE64
372 const uint64_t max_off_t = (uint64_t)
OFF_T_MAX;
374 const uint64_t max_off_t = (uint64_t) OFF64_T_MAX;
376 #ifdef MHD_LINUX_SOLARIS_SENDFILE
377 #ifndef HAVE_SENDFILE64
383 #ifdef HAVE_FREEBSD_SENDFILE
387 #ifdef HAVE_DARWIN_SENDFILE
390 const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION ==
394 size_t send_size = 0;
396 mhd_assert (MHD_resp_sender_sendfile == request->resp_sender);
401 send_size = (left > chunk_size) ? chunk_size : (
size_t) left;
402 if (max_off_t < offsetu64)
404 request->resp_sender = MHD_resp_sender_std;
407 #ifdef MHD_LINUX_SOLARIS_SENDFILE
408 #ifndef HAVE_SENDFILE64
409 offset = (off_t) offsetu64;
415 offset = (off64_t) offsetu64;
435 #ifdef HAVE_LINUX_SENDFILE
443 request->resp_sender = MHD_resp_sender_std;
446 if ( (EAFNOSUPPORT == err) ||
448 (EOPNOTSUPP == err) )
450 request->resp_sender = MHD_resp_sender_std;
453 if ( (ENOTCONN == err) ||
462 else if (send_size > (
size_t) ret)
465 #elif defined(HAVE_FREEBSD_SENDFILE)
467 flags = used_thr_p_c ?
468 freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
470 if (0 != sendfile (file_fd,
485 return (ssize_t) sent_bytes;
491 request->resp_sender = MHD_resp_sender_std;
496 ret = (ssize_t) sent_bytes;
497 #elif defined(HAVE_DARWIN_SENDFILE)
498 len = (off_t) send_size;
499 if (0 != sendfile (file_fd,
514 return (ssize_t) len;
518 if ((ENOTCONN == err) ||
521 if ((ENOTSUP == err) ||
522 (EOPNOTSUPP == err) )
525 request->resp_sender = MHD_resp_sender_std;
559 request->
state = next_state;
597 #if defined(_MHD_HAVE_SENDFILE)
598 if (MHD_resp_sender_sendfile ==
request->resp_sender)
622 MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
624 "Closing connection (application reported error generating data).\n"));
664 2 * (0xFFFFFF +
sizeof(cbuf) + 2));
673 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
674 _ (
"Closing connection (out of memory).\n"));
695 const size_t data_write_offset
698 ret = response->
data_size - data_write_offset;
702 &response->
data[data_write_offset],
719 MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
721 "Closing connection (application error generating response).\n"));
744 cblen = MHD_snprintf_ (cbuf,
783 if ( (
NULL != (tls = daemon->tls_api)) &&
785 connection->tls_cs)) )
792 MHD_SC_STATE_MACHINE_STATUS_REPORT,
793 _ (
"In function %s handling connection at state: %s\n"),
795 MHD_state_to_string (request->
state));
797 switch (request->
state)
808 ret = connection->
send_cls (connection,
819 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
820 _ (
"Failed to send data in request for %s.\n"),
824 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
838 ret = connection->
send_cls (connection,
848 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
850 "Connection was closed while sending response headers.\n"));
867 uint64_t data_write_offset;
876 #if defined(_MHD_HAVE_SENDFILE)
877 if (MHD_resp_sender_sendfile == request->resp_sender)
879 ret = sendfile_adapter (connection);
888 if (data_write_offset > (uint64_t)
SIZE_MAX)
889 MHD_PANIC (
_ (
"Data offset exceeds limit.\n"));
890 ret = connection->
send_cls (connection,
892 [(
size_t) data_write_offset],
894 - (
size_t) data_write_offset);
898 _ (
"Sent %d-byte DATA response: `%.*s'\n"),
913 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
914 _ (
"Failed to send data in request for `%s'.\n"),
918 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
933 ret = connection->
send_cls (connection,
943 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
945 "Connection was closed while sending response body.\n"));
963 ret = connection->
send_cls (connection,
973 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
975 "Connection was closed while sending response body.\n"));
990 #ifdef UPGRADE_SUPPORT
991 case MHD_REQUEST_UPGRADE:
998 MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED,
999 _ (
"Internal error.\n"));
1026 if ( (
NULL == request) ||
1058 #define MHD_lookup_header_s_token_ci(r,h,tkn) \
1059 MHD_lookup_header_token_ci ((r),(h),(tkn),MHD_STATICSTR_LEN_ (tkn))
1126 static const char *
const days[] = {
1127 "Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
1129 static const char *
const mons[] = {
1130 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
1131 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
1135 #if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1136 ! defined(HAVE_GMTIME_R)
1142 #if defined(HAVE_C11_GMTIME_S)
1143 if (
NULL == gmtime_s (&t,
1146 #elif defined(HAVE_W32_GMTIME_S)
1147 if (0 != gmtime_s (&now,
1150 #elif defined(HAVE_GMTIME_R)
1151 if (
NULL == gmtime_r (&t,
1160 MHD_snprintf_ (date,
1162 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1163 days[now.tm_wday % 7],
1164 (
unsigned int) now.tm_mday,
1165 mons[now.tm_mon % 12],
1166 (
unsigned int) (1900 + now.tm_year),
1167 (
unsigned int) now.tm_hour,
1168 (
unsigned int) now.tm_min,
1169 (
unsigned int) now.tm_sec);
1194 if ( (
NULL == key) ||
1197 (
'\0' == token[0]) )
1227 #define check_response_header_s_token_ci(r,k,tkn) \
1228 check_response_header_token_ci ((r),(k),(tkn),MHD_STATICSTR_LEN_ (tkn))
1252 char content_length_buf[128];
1253 size_t content_length_len;
1256 bool client_requested_close;
1257 bool response_has_close;
1258 bool response_has_keepalive;
1259 const char *have_encoding;
1260 const char *have_content_length;
1261 bool must_add_close;
1262 bool must_add_chunked_encoding;
1263 bool must_add_keep_alive;
1264 bool must_add_content_length;
1280 const char *reason_phrase;
1281 const char *version;
1292 MHD_snprintf_ (code,
1298 off = strlen (code);
1309 datelen = strlen (date);
1323 must_add_close =
false;
1324 must_add_chunked_encoding =
false;
1325 must_add_keep_alive =
false;
1326 must_add_content_length =
false;
1327 response_has_close =
false;
1328 switch (request->
state)
1335 response_has_keepalive
1339 client_requested_close
1346 #ifdef UPGRADE_SUPPORT
1347 else if (
NULL != response->upgrade_handler)
1356 #ifdef UPGRADE_SUPPORT
1357 (
NULL == response->upgrade_handler) &&
1359 (! response_has_close) &&
1360 (! client_requested_close) )
1374 if (
NULL == have_encoding)
1376 must_add_chunked_encoding =
true;
1383 must_add_close =
true;
1394 if (! response_has_close)
1395 must_add_close =
true;
1400 if ( ( (client_requested_close) ||
1403 (! response_has_close) &&
1404 #ifdef UPGRADE_SUPPORT
1405 (
NULL == response->upgrade_handler) &&
1408 must_add_close =
true;
1421 (MHD_HTTP_OK <= response->status_code) &&
1422 (
NULL == have_content_length) &&
1423 (request->
method != MHD_METHOD_CONNECT) )
1440 = MHD_snprintf_ (content_length_buf,
1441 sizeof (content_length_buf),
1445 must_add_content_length =
true;
1449 if ( (! response_has_keepalive) &&
1450 (! response_has_close) &&
1451 (! must_add_close) &&
1453 #ifdef UPGRADE_SUPPORT
1454 (
NULL == response->upgrade_handler) &&
1457 must_add_keep_alive =
true;
1460 response_has_keepalive =
false;
1469 if ( (must_add_close) ||
1470 (response_has_close) )
1472 else if ( (must_add_keep_alive) ||
1473 (response_has_keepalive) )
1479 if (must_add_keep_alive)
1481 if (must_add_chunked_encoding)
1483 if (must_add_content_length)
1484 size += content_length_len;
1485 mhd_assert (! (must_add_close && must_add_keep_alive) );
1486 mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1492 (! ( (must_add_close) &&
1493 (response_has_keepalive) &&
1497 "Keep-Alive")) ) ) )
1498 size += strlen (pos->
header) + strlen (pos->
value) + 4;
1506 #ifdef HAVE_MESSAGES
1508 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
1509 "Not enough memory for write!\n");
1523 "Connection: close\r\n",
1527 if (must_add_keep_alive)
1531 "Connection: Keep-Alive\r\n",
1535 if (must_add_chunked_encoding)
1539 "Transfer-Encoding: chunked\r\n",
1543 if (must_add_content_length)
1548 content_length_len);
1549 off += content_length_len;
1555 (! ( (must_add_close) &&
1556 (response_has_keepalive) &&
1560 "Keep-Alive")) ) ) )
1561 off += MHD_snprintf_ (&
data[off],
1604 enum MHD_StatusCode ec,
1605 enum MHD_HTTP_StatusCode status_code,
1606 const char *message)
1618 #ifdef HAVE_MESSAGES
1619 MHD_DLOG (request->
daemon,
1622 "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1644 "Closing connection (failed to create response header).\n"));
1659 static enum MHD_Method
1665 enum MHD_Method value;
1667 {
"OPTIONS", MHD_METHOD_OPTIONS },
1668 {
"GET", MHD_METHOD_GET },
1669 {
"HEAD", MHD_METHOD_HEAD },
1670 {
"POST", MHD_METHOD_POST },
1671 {
"PUT", MHD_METHOD_PUT },
1672 {
"DELETE", MHD_METHOD_DELETE },
1673 {
"TRACE", MHD_METHOD_TRACE },
1674 {
"CONNECT", MHD_METHOD_CONNECT },
1675 {
"ACL", MHD_METHOD_ACL },
1676 {
"BASELINE_CONTROL", MHD_METHOD_BASELINE_CONTROL },
1677 {
"BIND", MHD_METHOD_BIND },
1678 {
"CHECKIN", MHD_METHOD_CHECKIN },
1679 {
"CHECKOUT", MHD_METHOD_CHECKOUT },
1680 {
"COPY", MHD_METHOD_COPY },
1681 {
"LABEL", MHD_METHOD_LABEL },
1682 {
"LINK", MHD_METHOD_LINK },
1683 {
"LOCK", MHD_METHOD_LOCK },
1684 {
"MERGE", MHD_METHOD_MERGE },
1685 {
"MKACTIVITY", MHD_METHOD_MKACTIVITY },
1686 {
"MKCOL", MHD_METHOD_MKCOL },
1687 {
"MKREDIRECTREF", MHD_METHOD_MKREDIRECTREF },
1688 {
"MKWORKSPACE", MHD_METHOD_MKWORKSPACE },
1689 {
"MOVE", MHD_METHOD_MOVE },
1690 {
"ORDERPATCH", MHD_METHOD_ORDERPATCH },
1691 {
"PRI", MHD_METHOD_PRI },
1692 {
"PROPFIND", MHD_METHOD_PROPFIND },
1693 {
"PROPPATCH", MHD_METHOD_PROPPATCH },
1694 {
"REBIND", MHD_METHOD_REBIND },
1695 {
"REPORT", MHD_METHOD_REPORT },
1696 {
"SEARCH", MHD_METHOD_SEARCH },
1697 {
"UNBIND", MHD_METHOD_UNBIND },
1698 {
"UNCHECKOUT", MHD_METHOD_UNCHECKOUT },
1699 {
"UNLINK", MHD_METHOD_UNLINK },
1700 {
"UNLOCK", MHD_METHOD_UNLOCK },
1701 {
"UPDATE", MHD_METHOD_UPDATE },
1702 {
"UPDATEDIRECTREF", MHD_METHOD_UPDATEDIRECTREF },
1703 {
"VERSION-CONTROL", MHD_METHOD_VERSION_CONTROL },
1704 {
NULL, MHD_METHOD_UNKNOWN }
1708 for (i = 0;
NULL != methods[i].key; i++)
1712 return methods[i].value;
1713 return MHD_METHOD_UNKNOWN;
1739 #ifdef HAVE_MESSAGES
1740 MHD_DLOG (request->
daemon,
1741 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
1742 _ (
"Not enough memory in pool to allocate header record!\n"));
1745 MHD_SC_CLIENT_HEADER_TOO_BIG,
1772 unsigned int unused_num_headers;
1775 if (
NULL == (uri = memchr (line,
1785 while ( (
' ' == uri[0]) &&
1786 ( (
size_t) (uri - line) < line_len) )
1788 if ((
size_t) (uri - line) == line_len)
1794 url_end = line_len - (line - uri);
1800 http_version = line + line_len - 1;
1802 while ( (
' ' == http_version[0]) &&
1803 (http_version > uri) )
1806 while ( (
' ' != http_version[0]) &&
1807 (http_version > uri) )
1809 if (http_version > uri)
1811 http_version[0] =
'\0';
1815 http_version - uri);
1822 line_len - (uri - line));
1824 url_end = http_version - uri;
1827 (
NULL != memchr (curi,
1850 &unused_num_headers);
1856 request->
url = curi;
1878 colon = strchr (line,
1884 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1886 "Received malformed line (no colon). Closing connection.\n"));
1896 white = strchr (line,
1897 (
unsigned char)
' ');
1898 if ( (
NULL != white) &&
1902 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1904 "Whitespace before colon forbidden by RFC 7230. Closing connection.\n"));
1907 white = strchr (line,
1908 (
unsigned char)
'\t');
1909 if ( (
NULL != white) &&
1913 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1915 "Tab before colon forbidden by RFC 7230. Closing connection.\n"));
1922 while ( (
'\0' !=
colon[0]) &&
1923 ( (
' ' ==
colon[0]) ||
1924 (
'\t' ==
colon[0]) ) )
1958 if ( (
' ' == line[0]) ||
1963 last_len = strlen (
last);
1966 while ( (
' ' == tmp[0]) ||
1969 tmp_len = strlen (tmp);
1981 last_len + tmp_len + 1);
1985 MHD_SC_CLIENT_HEADER_TOO_BIG,
1990 memcpy (&
last[last_len],
2004 MHD_SC_CLIENT_HEADER_TOO_BIG,
2010 if (
'\0' != line[0])
2016 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
2051 (
'\r' != rbuf[pos]) &&
2052 (
'\n' != rbuf[pos]) )
2055 (
'\n' != rbuf[pos]) )
2062 MHD_SC_CLIENT_HEADER_TOO_BIG,
2076 if ( (
'\r' == rbuf[pos]) &&
2077 (
'\n' == rbuf[pos + 1]) )
2110 #if defined(TCP_CORK) || defined(TCP_PUSH)
2130 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
2132 #if defined(TCP_NODELAY)
2136 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2138 res = (0 == setsockopt (connection->
socket_fd,
2141 (
const void *) &on_val,
2144 #if defined(TCP_NODELAY)
2147 res &= (0 == setsockopt (connection->
socket_fd,
2150 (
const void *) &off_val,
2155 #if defined(TCP_NODELAY)
2159 (void) setsockopt (connection->
socket_fd,
2162 (
const void *) &off_val,
2166 res = (0 == setsockopt (connection->
socket_fd,
2169 (
const void *) &on_val,
2187 #if defined(TCP_NODELAY)
2190 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
2196 #if defined(TCP_CORK)
2198 res &= (0 == setsockopt (connection->
socket_fd,
2201 (
const void *) &off_val,
2205 #if defined(TCP_NODELAY)
2207 res &= (0 == setsockopt (connection->
socket_fd,
2210 (
const void *) &on_val,
2214 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2216 res &= (0 == setsockopt (connection->
socket_fd,
2219 (
const void *) &off_val,
2241 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2242 const int dummy = 0;
2245 if (
NULL == connection)
2248 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2270 #if defined(TCP_NODELAY)
2273 #if defined(TCP_CORK)
2275 socklen_t param_size =
sizeof (cork_val);
2279 #if defined(TCP_CORK)
2283 if ( (0 != getsockopt (connection->
socket_fd,
2289 res &= (0 == setsockopt (connection->
socket_fd,
2292 (
const void *) &off_val,
2295 #elif defined(TCP_NOPUSH)
2299 res &= (0 == setsockopt (connection->
socket_fd,
2302 (
const void *) &off_val,
2307 res &= (0 == setsockopt (connection->
socket_fd,
2310 (
const void *) &off_val,
2376 #ifdef HAVE_MESSAGES
2378 MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
2379 _ (
"Not enough memory in pool to parse cookies!\n"));
2382 MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
2397 while ( ((*sce) !=
'\0') &&
2404 while ( (*ekill ==
' ') &&
2425 while ( (
'\0' != semicolon[0]) &&
2427 ( (
';' != semicolon[0]) &&
2428 (
',' != semicolon[0]) ) ) )
2430 if (
'"' == semicolon[0])
2431 quotes = (quotes + 1) & 1;
2434 if (
'\0' == semicolon[0])
2436 if (
NULL != semicolon)
2438 semicolon[0] =
'\0';
2442 if ( (
'"' == equals[0]) &&
2443 (
'"' == equals[strlen (equals) - 1]) )
2445 equals[strlen (equals) - 1] =
'\0';
2489 #ifdef HAVE_MESSAGES
2491 MHD_SC_HOST_HEADER_MISSING,
2492 _ (
"Received HTTP 1.1 request without `Host' header.\n"));
2524 if ( (clen == end) ||
2528 #ifdef HAVE_MESSAGES
2529 MHD_DLOG (request->
daemon,
2530 MHD_SC_CONTENT_LENGTH_MALFORMED,
2531 "Failed to parse `Content-Length' header. Closing connection.\n");
2534 MHD_SC_CONTENT_LENGTH_MALFORMED,
2563 MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
2565 "Application reported internal error, closing connection.\n"));
2595 size_t to_be_processed;
2596 size_t left_unprocessed;
2597 size_t processed_size;
2599 instant_retry =
false;
2611 if ( (
'\r' == buffer_head[i]) ||
2612 (
'\n' == buffer_head[i]) )
2614 if ( (
'\r' == buffer_head[i]) ||
2615 (
'\n' == buffer_head[i]) )
2621 MHD_SC_CHUNKED_ENCODING_MALFORMED,
2623 "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2634 uint64_t cur_chunk_left;
2641 if (cur_chunk_left > available)
2643 to_be_processed = available;
2647 to_be_processed = (size_t) cur_chunk_left;
2648 if (available > to_be_processed)
2649 instant_retry =
true;
2660 while (i < available)
2662 if ( (
'\r' == buffer_head[i]) ||
2663 (
'\n' == buffer_head[i]) ||
2664 (
';' == buffer_head[i]) )
2672 if (
';' == buffer_head[i])
2674 while (i < available)
2676 if ( (
'\r' == buffer_head[i]) ||
2677 (
'\n' == buffer_head[i]) )
2685 if ( (i + 1 >= available) &&
2688 (
'0' == buffer_head[0]) ) )
2691 malformed = (end_size >= 16);
2697 malformed = (end_size != num_dig);
2703 MHD_SC_CHUNKED_ENCODING_MALFORMED,
2705 "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2709 if ( (i < available) &&
2710 ( (
'\r' == buffer_head[i]) ||
2711 (
'\n' == buffer_head[i]) ) )
2719 instant_retry =
true;
2743 to_be_processed = available;
2746 left_unprocessed = to_be_processed;
2760 MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
2762 "Application reported internal error, closing connection.\n"));
2766 if (left_unprocessed > to_be_processed)
2770 #ifdef HAVE_MESSAGES
2771 ,
_ (
"libmicrohttpd API violation.\n")
2776 if (0 != left_unprocessed)
2778 instant_retry =
false;
2779 #ifdef HAVE_MESSAGES
2786 MHD_SC_APPLICATION_HUNG_CONNECTION,
2788 "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2791 processed_size = to_be_processed - left_unprocessed;
2795 buffer_head += processed_size;
2796 available -= processed_size;
2800 while (instant_retry);
2867 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2868 (! MHD_itc_activate_ (daemon->
itc,
2871 #ifdef HAVE_MESSAGES
2873 MHD_SC_ITC_USE_FAILED,
2875 "Failed to signal end of connection via inter-thread communication channel.\n"));
2882 #ifdef EPOLL_SUPPORT
2905 struct epoll_event event;
2907 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2908 event.data.ptr = connection;
2909 if (0 != epoll_ctl (daemon->epoll_fd,
2914 #ifdef HAVE_MESSAGES
2916 MHD_SC_EPOLL_CTL_ADD_FAILED,
2917 _ (
"Call to epoll_ctl failed: %s\n"),
2950 #ifdef HTTPS_SUPPORT
2954 if ( (
NULL != (tls = daemon->tls_api)) &&
2965 MHD_SC_STATE_MACHINE_STATUS_REPORT,
2966 _ (
"In function %s handling connection at state: %s\n"),
2968 MHD_state_to_string (request->
state));
2970 switch (request->
state)
2981 MHD_SC_CLIENT_HEADER_TOO_BIG,
3019 MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED,
3038 MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3080 #ifdef UPGRADE_SUPPORT
3081 case MHD_REQUEST_UPGRADE:
3115 #ifdef HTTPS_SUPPORT
3118 if ( (
NULL != (tls = daemon->tls_api)) &&
3120 connection->tls_cs)) )
3125 MHD_SC_STATE_MACHINE_STATUS_REPORT,
3126 _ (
"In function %s handling connection at state: %s\n"),
3128 MHD_state_to_string (request->
state));
3130 switch (request->
state)
3139 if ( (
NULL == line) ||
3147 MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3158 MHD_SC_CONNECTION_CLOSED,
3173 MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3189 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
3206 MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3246 ( (MHD_METHOD_POST == request->
method) ||
3247 (MHD_METHOD_PUT == request->
method) ) )
3304 MHD_SC_CONNECTION_CLOSED,
3321 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
3338 MHD_SC_CONNECTION_CLOSED,
3367 MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
3369 "Closing connection (failed to create response header).\n"));
3387 #ifdef UPGRADE_SUPPORT
3391 request->
state = MHD_REQUEST_UPGRADE;
3392 #if FIXME_LEGACY_STYLE
3399 MHD_SC_CONNECTION_CLOSED,
3482 MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
3484 "Closing connection (failed to create response header).\n"));
3562 request->
daemon = daemon;
3569 #ifdef UPGRADE_SUPPORT
3570 case MHD_REQUEST_UPGRADE:
3584 if ( (0 != timeout) &&
3596 #ifdef EPOLL_SUPPORT
3600 ret = connection_epoll_update_ (connection);
3630 bool states_info_processed =
false;
3634 #ifdef HTTPS_SUPPORT
3646 states_info_processed =
true;
3656 states_info_processed =
true;
3666 if (! states_info_processed)
3679 else if (on_fasttrack &&
3713 #ifdef HTTPS_SUPPORT
#define MHD_SENFILE_CHUNK_THR_P_C_
static bool socket_flush_possible(struct MHD_Connection *connection)
static void process_request_body(struct MHD_Request *request)
static void connection_close_error(struct MHD_Connection *connection, enum MHD_StatusCode sc, const char *emsg)
static bool parse_initial_message_line(struct MHD_Request *request, char *line, size_t line_len)
static bool MHD_lookup_header_token_ci(const struct MHD_Request *request, const char *header, const char *token, size_t token_len)
static bool socket_start_normal_buffering(struct MHD_Connection *connection)
static void MHD_request_handle_write_(struct MHD_Request *request)
static char * get_next_header_line(struct MHD_Request *request, size_t *line_len)
int MHD_connection_call_handlers_(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
static bool need_100_continue(struct MHD_Request *request)
#define HTTP_100_CONTINUE
bool MHD_request_handle_idle_(struct MHD_Request *request)
#define REQUEST_MALFORMED
static bool try_ready_chunked_body(struct MHD_Request *request)
static void connection_update_event_loop_info(struct MHD_Connection *connection)
#define MHD_lookup_header_s_token_ci(r, h, tkn)
static bool process_header_line(struct MHD_Request *request, char *line)
static bool check_write_done(struct MHD_Request *request, enum MHD_REQUEST_STATE next_state)
#define REQUEST_LACKS_HOST
static bool request_add_header(struct MHD_Request *request, const char *key, const char *value, enum MHD_ValueKind kind)
static void parse_request_headers(struct MHD_Request *request)
static bool keepalive_possible(struct MHD_Request *request)
static bool check_response_header_token_ci(const struct MHD_Response *response, const char *key, const char *token, size_t token_len)
static void cleanup_connection(struct MHD_Connection *connection)
static bool process_broken_line(struct MHD_Request *request, char *line, enum MHD_ValueKind kind)
#define CONNECTION_CLOSE_ERROR(c, sc, emsg)
static bool socket_start_extra_buffering(struct MHD_Connection *connection)
static bool socket_start_no_buffering_flush(struct MHD_Connection *connection)
static enum MHD_Method method_string_to_enum(const char *method)
static bool try_ready_normal_body(struct MHD_Request *request)
static bool build_header_response(struct MHD_Request *request)
static void get_date_string(char *date, size_t date_len)
static bool try_grow_read_buffer(struct MHD_Request *request)
static void call_request_handler(struct MHD_Request *request)
static void MHD_request_handle_read_(struct MHD_Request *request)
static void transmit_error_response(struct MHD_Request *request, enum MHD_StatusCode ec, enum MHD_HTTP_StatusCode status_code, const char *message)
static bool socket_start_no_buffering(struct MHD_Connection *connection)
#define check_response_header_s_token_ci(r, k, tkn)
#define MHD_SENFILE_CHUNK_
static int parse_cookie_header(struct MHD_Request *request)
function to call event handlers based on event mask
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
functions to close connection
void MHD_connection_update_last_activity_(struct MHD_Connection *connection)
function to update last activity of a connection
#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_NOT_MODIFIED
#define MHD_HTTP_NO_CONTENT
#define MHD_HTTP_BAD_REQUEST
enum MHD_Bool MHD_request_set_value(struct MHD_Request *request, enum MHD_ValueKind kind, const char *key, const char *value)
const char * MHD_request_lookup_value(struct MHD_Request *request, enum MHD_ValueKind kind, const char *key)
@ 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
const char * MHD_response_get_header(struct MHD_Response *response, const char *key)
void MHD_response_queue_for_destroy(struct MHD_Response *response)
struct MHD_Response * MHD_response_from_buffer(enum MHD_HTTP_StatusCode sc, size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
#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_
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
@ MHD_REQUEST_CHUNKED_BODY_UNREADY
@ MHD_REQUEST_CONTINUE_SENDING
@ MHD_REQUEST_NORMAL_BODY_READY
@ MHD_REQUEST_FOOTER_PART_RECEIVED
@ MHD_REQUEST_HEADER_PART_RECEIVED
@ MHD_REQUEST_FOOTERS_SENDING
@ MHD_REQUEST_HEADERS_SENDING
@ MHD_REQUEST_HEADERS_SENT
@ MHD_REQUEST_BODY_RECEIVED
@ MHD_REQUEST_CHUNKED_BODY_READY
@ MHD_REQUEST_HEADERS_RECEIVED
@ MHD_REQUEST_FOOTERS_RECEIVED
@ MHD_REQUEST_HEADERS_PROCESSED
@ MHD_REQUEST_FOOTERS_SENT
@ MHD_REQUEST_URL_RECEIVED
@ MHD_REQUEST_CONTINUE_SENT
@ MHD_REQUEST_NORMAL_BODY_UNREADY
#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)
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_socket_last_strerr_()
#define MHD_socket_get_error_()
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_send_(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)
internal shared structures
@ MHD_EVENT_LOOP_INFO_READ
@ MHD_EVENT_LOOP_INFO_WRITE
@ MHD_EVENT_LOOP_INFO_CLEANUP
@ MHD_EVENT_LOOP_INFO_BLOCK
#define MHD_CONTENT_READER_END_OF_STREAM
#define MHD_UNSIGNED_LONG_LONG
#define MHD_UNSIGNED_LONG_LONG_PRINTF
#define MHD_CONTENT_READER_END_WITH_ERROR
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
enum MHD_Result MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
struct MHD_Response * response
struct MHD_Request request
time_t connection_timeout
TransmitCallback send_cls
size_t read_buffer_offset
struct MHD_Daemon * daemon
bool data_already_pending
MHD_EarlyUriLogCallback early_uri_logger_cb
MHD_mutex_ cleanup_connection_mutex
struct MHD_Connection * connections_head
void * early_uri_logger_cb_cls
enum MHD_EventLoopSyscall event_loop_syscall
struct MHD_Connection * manual_timeout_tail
size_t connection_memory_increment_b
struct MHD_Connection * cleanup_tail
enum MHD_ProtocolStrictLevel protocol_strict_level
time_t connection_default_timeout
struct MHD_Connection * manual_timeout_head
struct MHD_Connection * suspended_connections_tail
struct MHD_Connection * cleanup_head
struct MHD_Connection * normal_timeout_head
size_t connection_memory_limit_b
struct MHD_Connection * normal_timeout_tail
enum MHD_ThreadingMode threading_mode
MHD_UnescapeCallback unescape_cb
struct MHD_Connection * suspended_connections_head
struct MHD_Connection * connections_tail
size_t write_buffer_append_offset
struct MHD_Response * response
uint64_t current_chunk_size
uint64_t current_chunk_offset
struct MHD_HTTP_Header * headers_received
size_t continue_message_write_offset
size_t write_buffer_send_offset
size_t read_buffer_offset
enum MHD_RequestEventLoopInfo event_loop_info
uint64_t response_write_position
struct MHD_Connection * connection
struct MHD_Daemon * daemon
enum MHD_REQUEST_STATE state
enum MHD_ConnKeepAlive keepalive
uint64_t remaining_upload_size
void * termination_cb_cls
struct MHD_HTTP_Header * first_header
enum MHD_HTTP_StatusCode status_code
MHD_ContentReaderCallback crc
MHD_RequestTerminationCallback termination_cb
enum MHD_ResponseFlags flags
enum MHD_Bool(* idle_ready)(void *cls, struct MHD_TLS_ConnectionState *cs)
enum MHD_Bool(* update_event_loop_info)(void *cls, struct MHD_TLS_ConnectionState *cs, enum MHD_RequestEventLoopInfo *eli)
enum MHD_Bool(* handshake)(void *cls, struct MHD_TLS_ConnectionState *cs)