35 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
36 #include "mhd_locks.h"
41 #ifdef MHD_LINUX_SOLARIS_SENDFILE
42 #include <sys/sendfile.h>
44 #if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
45 #include <sys/types.h>
46 #include <sys/socket.h>
57 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
67 #define REQUEST_TOO_BIG "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
69 #define REQUEST_TOO_BIG ""
80 #define REQUEST_LACKS_HOST "<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>"
82 #define REQUEST_LACKS_HOST ""
93 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
95 #define REQUEST_MALFORMED ""
105 #define INTERNAL_ERROR "<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>"
107 #define INTERNAL_ERROR ""
114 #define DEBUG_CLOSE MHD_NO
119 #define DEBUG_SEND_DATA MHD_NO
125 #define MHD_SENFILE_CHUNK_ (0x20000)
130 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
132 #ifdef HAVE_FREEBSD_SENDFILE
137 static int freebsd_sendfile_flags_;
142 static int freebsd_sendfile_flags_thd_p_c_;
148 MHD_conn_init_static_ (
void)
154 long sys_page_size = sysconf (_SC_PAGESIZE);
155 if (0 > sys_page_size)
157 freebsd_sendfile_flags_ = SF_NODISKIO;
158 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
162 freebsd_sendfile_flags_ =
164 freebsd_sendfile_flags_thd_p_c_ =
216 else if (i > (
size_t)ret)
270 else if (i > (
size_t)ret)
277 #if defined(_MHD_HAVE_SENDFILE)
291 #ifndef HAVE_SENDFILE64
292 const uint64_t max_off_t = (uint64_t)
OFF_T_MAX;
294 const uint64_t max_off_t = (uint64_t)OFF64_T_MAX;
296 #ifdef MHD_LINUX_SOLARIS_SENDFILE
297 #ifndef HAVE_SENDFILE64
303 #ifdef HAVE_FREEBSD_SENDFILE
307 #ifdef HAVE_DARWIN_SENDFILE
312 size_t send_size = 0;
313 mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
319 send_size = (left > chunk_size) ? chunk_size : (
size_t) left;
320 if (max_off_t < offsetu64)
322 connection->resp_sender = MHD_resp_sender_std;
325 #ifdef MHD_LINUX_SOLARIS_SENDFILE
326 #ifndef HAVE_SENDFILE64
327 offset = (off_t) offsetu64;
333 offset = (off64_t) offsetu64;
352 #ifdef HAVE_LINUX_SENDFILE
361 connection->resp_sender = MHD_resp_sender_std;
364 if ( (EAFNOSUPPORT == err) ||
366 (EOPNOTSUPP == err) )
368 connection->resp_sender = MHD_resp_sender_std;
371 if ( (ENOTCONN == err) ||
380 else if (send_size > (
size_t)ret)
383 #elif defined(HAVE_FREEBSD_SENDFILE)
385 flags = used_thr_p_c ?
386 freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
388 if (0 != sendfile (file_fd,
403 return (ssize_t)sent_bytes;
409 connection->resp_sender = MHD_resp_sender_std;
414 ret = (ssize_t)sent_bytes;
415 #elif defined(HAVE_DARWIN_SENDFILE)
416 len = (off_t)send_size;
417 if (0 != sendfile (file_fd,
436 if (ENOTCONN == err ||
439 if (ENOTSUP == err ||
443 connection->resp_sender = MHD_resp_sender_std;
481 #if defined(TCP_CORK) || defined(TCP_PUSH)
500 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
502 #if defined(TCP_NODELAY)
508 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
510 res = (0 == setsockopt (connection->
socket_fd,
513 (
const void *) &on_val,
516 #if defined(TCP_NODELAY)
519 res &= (0 == setsockopt (connection->
socket_fd,
522 (
const void *) &off_val,
527 #if defined(TCP_NODELAY)
531 (void) setsockopt (connection->
socket_fd,
534 (
const void *) &off_val,
538 res = (0 == setsockopt (connection->
socket_fd,
541 (
const void *) &on_val,
559 #if defined(TCP_NODELAY)
562 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
568 #if defined(TCP_CORK)
570 res &= (0 == setsockopt (connection->
socket_fd,
573 (
const void *) &off_val,
577 #if defined(TCP_NODELAY)
579 res &= (0 == setsockopt (connection->
socket_fd,
582 (
const void *) &on_val,
586 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
588 res &= (0 == setsockopt (connection->
socket_fd,
591 (
const void *) &off_val,
613 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
617 if (NULL == connection)
620 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
642 #if defined(TCP_NODELAY)
645 #if defined(TCP_CORK)
647 socklen_t param_size =
sizeof (cork_val);
650 #if defined(TCP_CORK)
654 if ( (0 != getsockopt (connection->
socket_fd,
660 res &= (0 == setsockopt (connection->
socket_fd,
663 (
const void *) &off_val,
666 #elif defined(TCP_NOPUSH)
670 res &= (0 == setsockopt (connection->
socket_fd,
673 (
const void *) &off_val,
678 res &= (0 == setsockopt (connection->
socket_fd,
681 (
const void *) &off_val,
711 if (NULL == connection)
715 if (0 != (pos->
kind & kind))
718 if ( (NULL != iterator) &&
719 (
MHD_YES != iterator (iterator_cls,
767 pos->
header = (
char *) key;
768 pos->
value = (
char *) value;
803 if (NULL == connection)
806 if ((0 != (pos->
kind & kind)) &&
808 ( (NULL != pos->
header) &&
838 if (NULL == connection || NULL == header || 0 == header[0] || NULL == token || 0 == token[0])
843 ( (header == pos->
header) ||
864 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
865 MHD_lookup_header_token_ci((c),(h),(tkn),MHD_STATICSTR_LEN_(tkn))
880 return ( (NULL == connection->
response) &&
881 (NULL != connection->
version) &&
961 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
976 struct MHD_UpgradeResponseHandle *urh = connection->urh;
987 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
992 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
994 if (urh->in_eready_list)
997 daemon->eready_urh_tail,
999 urh->in_eready_list =
false;
1006 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1011 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
1016 shutdown (urh->mhd.socket, SHUT_RDWR);
1038 #ifdef HAVE_MESSAGES
1040 MHD_DLOG (connection->
daemon,
1054 #ifdef HAVE_MESSAGES
1055 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
1057 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
1080 if (NULL == response->
crc)
1090 #if defined(_MHD_HAVE_SENDFILE)
1091 if (MHD_resp_sender_sendfile == connection->resp_sender)
1109 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1112 if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
1117 _(
"Closing connection (application reported error generating data)\n"));
1125 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1154 if (NULL == response->
crc)
1159 2 * (0xFFFFFF +
sizeof(cbuf) + 2));
1165 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1170 _(
"Closing connection (out of memory)\n"));
1177 while (NULL == buf);
1191 const size_t data_write_offset
1194 ret = response->
data_size - data_write_offset;
1198 &response->
data[data_write_offset],
1213 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1217 _(
"Closing connection (application error generating response)\n"));
1235 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1242 cblen = MHD_snprintf_(cbuf,
1245 (
unsigned int) ret);
1248 memcpy (&connection->
write_buffer[sizeof (cbuf) - cblen],
1251 memcpy (&connection->
write_buffer[sizeof (cbuf) + ret],
1282 if (NULL == connection->
version)
1284 if ( (NULL != connection->
response) &&
1290 ( (NULL == connection->
response) ||
1330 static const char *
const days[] = {
1331 "Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
1333 static const char *
const mons[] = {
1334 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
1335 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
1339 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
1345 #if defined(HAVE_C11_GMTIME_S)
1346 if (NULL == gmtime_s (&t,
1349 #elif defined(HAVE_W32_GMTIME_S)
1350 if (0 != gmtime_s (&now,
1353 #elif defined(HAVE_GMTIME_R)
1354 if (NULL == gmtime_r(&t,
1363 MHD_snprintf_ (date,
1365 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1366 days[now.tm_wday % 7],
1367 (
unsigned int) now.tm_mday,
1368 mons[now.tm_mon % 12],
1369 (
unsigned int) (1900 + now.tm_year),
1370 (
unsigned int) now.tm_hour,
1371 (
unsigned int) now.tm_min,
1372 (
unsigned int) now.tm_sec);
1428 char content_length_buf[128];
1429 size_t content_length_len;
1432 const char *reason_phrase;
1434 bool client_requested_close;
1435 bool response_has_close;
1436 bool response_has_keepalive;
1437 const char *have_encoding;
1439 int must_add_chunked_encoding;
1440 int must_add_keep_alive;
1441 int must_add_content_length;
1442 int may_add_content_length;
1445 if (0 == connection->
version[0])
1460 MHD_snprintf_ (code,
1472 off = strlen (code);
1483 datelen = strlen (date);
1498 must_add_chunked_encoding =
MHD_NO;
1499 must_add_keep_alive =
MHD_NO;
1500 must_add_content_length =
MHD_NO;
1501 response_has_close =
false;
1502 switch (connection->
state)
1517 #ifdef UPGRADE_SUPPORT
1518 else if (NULL != response->upgrade_handler)
1527 if (NULL == have_encoding)
1528 may_add_content_length =
MHD_YES;
1530 may_add_content_length =
MHD_NO;
1532 #ifdef UPGRADE_SUPPORT
1533 (NULL == response->upgrade_handler) &&
1535 (! response_has_close) &&
1536 (! client_requested_close) )
1547 if (NULL == have_encoding)
1549 must_add_chunked_encoding =
MHD_YES;
1570 if (! response_has_close)
1576 if ( ( (client_requested_close) ||
1579 (! response_has_close) &&
1580 #ifdef UPGRADE_SUPPORT
1581 (NULL == response->upgrade_handler) &&
1588 if ( (! may_add_content_length) &&
1590 (! response_has_close) )
1603 (may_add_content_length) &&
1604 ( (NULL == connection->
method) ||
1624 = MHD_snprintf_ (content_length_buf,
1625 sizeof (content_length_buf),
1628 must_add_content_length =
MHD_YES;
1632 if ( (! response_has_keepalive) &&
1633 (! response_has_close) &&
1634 (
MHD_NO == must_add_close) &&
1636 #ifdef UPGRADE_SUPPORT
1637 (NULL == response->upgrade_handler) &&
1640 must_add_keep_alive =
MHD_YES;
1643 response_has_keepalive =
false;
1652 if ( (must_add_close) || (response_has_close) )
1654 else if ( (must_add_keep_alive) || (response_has_keepalive) )
1660 if (must_add_keep_alive)
1662 if (must_add_chunked_encoding)
1664 if (must_add_content_length)
1665 size += content_length_len;
1666 mhd_assert (! (must_add_close && must_add_keep_alive) );
1667 mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1672 if ( (pos->
kind == kind) &&
1673 (! ( (
MHD_YES == must_add_close) &&
1674 (response_has_keepalive) &&
1678 "Keep-Alive")) ) ) )
1679 size += strlen (pos->
header) + strlen (pos->
value) + 4;
1687 #ifdef HAVE_MESSAGES
1688 MHD_DLOG (connection->
daemon,
1689 "Not enough memory for write!\n");
1703 "Connection: close\r\n",
1707 if (must_add_keep_alive)
1711 "Connection: Keep-Alive\r\n",
1715 if (must_add_chunked_encoding)
1719 "Transfer-Encoding: chunked\r\n",
1723 if (must_add_content_length)
1728 content_length_len);
1729 off += content_length_len;
1734 if ( (pos->
kind == kind) &&
1735 (! ( (
MHD_YES == must_add_close) &&
1736 (response_has_keepalive) &&
1740 "Keep-Alive")) ) ) )
1741 off += MHD_snprintf_ (&data[off],
1783 unsigned int status_code,
1784 const char *message)
1789 if (NULL == connection->
version)
1797 #ifdef HAVE_MESSAGES
1798 MHD_DLOG (connection->
daemon,
1799 _(
"Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1811 if (NULL == response)
1825 _(
"Closing connection (failed to queue response)\n"));
1835 _(
"Closing connection (failed to create response header)\n"));
1858 #ifdef HTTPS_SUPPORT
1861 switch (connection->tls_state)
1867 if (0 == gnutls_record_get_direction (connection->tls_session))
1880 MHD_DLOG (connection->
daemon,
1881 _(
"In function %s handling connection at state: %s\n"),
1883 MHD_state_to_string (connection->
state));
1885 switch (connection->
state)
1896 (connection->
url != NULL)
1994 #ifdef UPGRADE_SUPPORT
1995 case MHD_CONNECTION_UPGRADE:
2031 while ( (pos < connection->read_buffer_offset - 1) &&
2032 (
'\r' != rbuf[pos]) &&
2033 (
'\n' != rbuf[pos]) )
2036 (
'\n' != rbuf[pos]) )
2044 (NULL != connection->
url)
2057 if ( (
'\r' == rbuf[pos]) &&
2058 (
'\n' == rbuf[pos + 1]) )
2091 #ifdef HAVE_MESSAGES
2092 MHD_DLOG (connection->
daemon,
2093 _(
"Not enough memory in pool to allocate header record!\n"));
2133 #ifdef HAVE_MESSAGES
2134 MHD_DLOG (connection->
daemon,
2135 _(
"Not enough memory in pool to parse cookies!\n"));
2152 while ( ((*sce) !=
'\0') &&
2159 while ( (*ekill ==
' ') &&
2181 while ( (
'\0' != semicolon[0]) &&
2183 ( (
';' != semicolon[0]) &&
2184 (
',' != semicolon[0]) ) ) )
2186 if (
'"' == semicolon[0])
2187 quotes = (quotes + 1) & 1;
2190 if (
'\0' == semicolon[0])
2192 if (NULL != semicolon)
2194 semicolon[0] =
'\0';
2198 if ( (
'"' == equals[0]) &&
2199 (
'"' == equals[strlen (equals) - 1]) )
2201 equals[strlen (equals) - 1] =
'\0';
2234 unsigned int unused_num_headers;
2237 if (NULL == (uri = memchr (line,
2242 connection->
method = line;
2246 while ( (
' ' == uri[0]) &&
2247 ( (
size_t)(uri - line) < line_len) )
2249 if ((
size_t)(uri - line) == line_len)
2262 http_version = line + line_len - 1;
2264 while ( (
' ' == http_version[0]) &&
2265 (http_version > uri) )
2268 while ( (
' ' != http_version[0]) &&
2269 (http_version > uri) )
2271 if (http_version > uri)
2274 http_version[0] =
'\0';
2275 connection->
version = http_version + 1;
2276 uri_len = http_version - uri;
2281 uri_len = line_len - (uri - line);
2285 (NULL != memchr (uri,
2297 uri_len = strlen (uri);
2320 &unused_num_headers);
2322 connection->
url = curi;
2356 _(
"Application reported internal error, closing connection.\n"));
2384 size_t to_be_processed;
2385 size_t left_unprocessed;
2386 size_t processed_size;
2399 if ( (
'\r' == buffer_head[i]) ||
2400 (
'\n' == buffer_head[i]) )
2402 if ( (
'\r' == buffer_head[i]) ||
2403 (
'\n' == buffer_head[i]) )
2409 _(
"Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2420 uint64_t cur_chunk_left;
2426 if (cur_chunk_left > available)
2427 to_be_processed = available;
2430 to_be_processed = (size_t)cur_chunk_left;
2431 if (available > to_be_processed)
2443 while (i < available)
2445 if ( (
'\r' == buffer_head[i]) ||
2446 (
'\n' == buffer_head[i]) ||
2447 (
';' == buffer_head[i]) )
2455 if (
';' == buffer_head[i])
2457 while (i < available)
2459 if ( (
'\r' == buffer_head[i]) ||
2460 (
'\n' == buffer_head[i]) )
2468 if ( (i + 1 >= available) &&
2471 (
'0' == buffer_head[0]) ) )
2474 malformed = (end_size >= 16);
2480 malformed = (end_size != num_dig);
2486 _(
"Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2490 if ( (i < available) &&
2491 ( (
'\r' == buffer_head[i]) ||
2492 (
'\n' == buffer_head[i]) ) )
2524 to_be_processed = available;
2527 left_unprocessed = to_be_processed;
2541 _(
"Application reported internal error, closing connection.\n"));
2544 if (left_unprocessed > to_be_processed)
2548 #ifdef HAVE_MESSAGES
2549 ,
_(
"libmicrohttpd API violation")
2554 if (0 != left_unprocessed)
2557 #ifdef HAVE_MESSAGES
2564 _(
"WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2567 processed_size = to_be_processed - left_unprocessed;
2571 buffer_head += processed_size;
2572 available -= processed_size;
2576 while (
MHD_YES == instant_retry);
2602 connection->
state = next_state;
2629 colon = strchr (line,
':');
2634 _(
"Received malformed line (no colon). Closing connection.\n"));
2644 white = strchr (line,
' ');
2645 if ( (NULL != white) &&
2648 white = strchr (line,
'\t');
2649 if ( (NULL != white) &&
2656 while ( (
'\0' != colon[0]) &&
2657 ( (
' ' == colon[0]) ||
2658 (
'\t' == colon[0]) ) )
2665 connection->
last = line;
2666 connection->
colon = colon;
2691 last = connection->
last;
2692 if ( (
' ' == line[0]) ||
2697 last_len = strlen (last);
2700 while ( (
' ' == tmp[0]) ||
2703 tmp_len = strlen (tmp);
2716 last_len + tmp_len + 1);
2724 memcpy (&last[last_len], tmp, tmp_len + 1);
2725 connection->
last = last;
2729 (NULL != connection->
colon) );
2773 (NULL != connection->
version) &&
2786 #ifdef HAVE_MESSAGES
2787 MHD_DLOG (connection->
daemon,
2788 _(
"Received HTTP 1.1 request without `Host' header.\n"));
2795 if (NULL == response)
2799 _(
"Closing connection (failed to create response)\n"));
2810 _(
"Closing connection (failed to queue response)\n"));
2835 if ( (clen == end) ||
2839 #ifdef HAVE_MESSAGES
2840 MHD_DLOG (connection->
daemon,
2841 "Failed to parse `Content-Length' header. Closing connection.\n");
2876 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2886 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2906 #ifdef HTTPS_SUPPORT
2925 bytes_read = connection->
recv_cls (connection,
2939 _(
"Socket disconnected while reading request.\n"));
2945 _(
"Connection socket is closed due to error when reading request.\n"));
2949 if (0 == bytes_read)
2959 MHD_DLOG (connection->
daemon,
2960 _(
"In function %s handling connection at state: %s\n"),
2962 MHD_state_to_string (connection->
state));
2964 switch (connection->
state)
2984 #ifdef UPGRADE_SUPPORT
2985 case MHD_CONNECTION_UPGRADE:
3015 #ifdef HTTPS_SUPPORT
3027 MHD_DLOG (connection->
daemon,
3028 _(
"In function %s handling connection at state: %s\n"),
3030 MHD_state_to_string (connection->
state));
3032 switch (connection->
state)
3043 ret = connection->
send_cls (connection,
3052 #ifdef HAVE_MESSAGES
3053 MHD_DLOG (connection->
daemon,
3054 _(
"Failed to send data in request for %s.\n"),
3063 _(
"Sent 100 continue response: `%.*s'\n"),
3077 ret = connection->
send_cls (connection,
3087 _(
"Connection was closed while sending response headers.\n"));
3104 uint64_t data_write_offset;
3106 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3107 if (NULL != response->
crc)
3115 #if defined(_MHD_HAVE_SENDFILE)
3116 if (MHD_resp_sender_sendfile == connection->resp_sender)
3118 ret = sendfile_adapter (connection);
3127 if (data_write_offset > (uint64_t)
SIZE_MAX)
3129 ret = connection->
send_cls (connection,
3131 [(
size_t)data_write_offset],
3133 (
size_t)data_write_offset);
3137 _(
"Sent %d-byte DATA response: `%.*s'\n"),
3144 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3145 if (NULL != response->
crc)
3152 #ifdef HAVE_MESSAGES
3153 MHD_DLOG (connection->
daemon,
3154 _(
"Failed to send data in request for `%s'.\n"),
3172 ret = connection->
send_cls (connection,
3182 _(
"Connection was closed while sending response body.\n"));
3195 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
3200 ret = connection->
send_cls (connection,
3210 _(
"Connection was closed while sending response body.\n"));
3225 #ifdef UPGRADE_SUPPORT
3226 case MHD_CONNECTION_UPGRADE:
3233 _(
"Internal error\n"));
3261 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3293 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3301 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3302 (! MHD_itc_activate_ (daemon->
itc,
"c")) )
3304 #ifdef HAVE_MESSAGES
3306 _(
"Failed to signal end of connection via inter-thread communication channel"));
3334 #ifdef HTTPS_SUPPORT
3337 if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3344 _(
"In function %s handling connection at state: %s\n"),
3346 MHD_state_to_string (connection->
state));
3348 switch (connection->
state)
3357 if ( (NULL == line) ||
3458 if ( (NULL != connection->
response) &&
3579 _(
"Closing connection (failed to create response header)\n"));
3597 #ifdef UPGRADE_SUPPORT
3598 if (NULL != connection->
response->upgrade_handler)
3601 connection->
state = MHD_CONNECTION_UPGRADE;
3636 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3642 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3651 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3668 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3676 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3685 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3702 _(
"Closing connection (failed to create response header)\n"));
3794 #ifdef UPGRADE_SUPPORT
3795 case MHD_CONNECTION_UPGRADE:
3809 if ( (0 != timeout) &&
3820 #ifdef EPOLL_SUPPORT
3824 ret = MHD_connection_epoll_update_ (connection);
3832 #ifdef EPOLL_SUPPORT
3855 struct epoll_event event;
3857 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3858 event.data.ptr = connection;
3859 if (0 != epoll_ctl (daemon->epoll_fd,
3864 #ifdef HAVE_MESSAGES
3867 _(
"Call to epoll_ctl failed: %s\n"),
3911 #ifdef HTTPS_SUPPORT
3913 if (NULL == connection->tls_session)
3915 connection->cipher = gnutls_cipher_get (connection->tls_session);
3918 if (NULL == connection->tls_session)
3920 connection->protocol = gnutls_protocol_get_version (connection->tls_session);
3923 if (NULL == connection->tls_session)
3969 daemon = connection->
daemon;
3975 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3990 va_start (ap, option);
4006 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4029 unsigned int status_code,
4034 if ( (NULL == connection) ||
4035 (NULL == response) ||
4040 daemon = connection->
daemon;
4046 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4049 (!MHD_thread_ID_match_current_(connection->
pid.ID)) )
4051 #ifdef HAVE_MESSAGES
4053 _(
"Attempted to queue response on wrong thread!\n"));
4058 #ifdef UPGRADE_SUPPORT
4059 if ( (NULL != response->upgrade_handler) &&
4062 #ifdef HAVE_MESSAGES
4064 _(
"Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
4069 (NULL != response->upgrade_handler) )
4071 #ifdef HAVE_MESSAGES
4073 _(
"Application used invalid status code for 'upgrade' response!\n"));
4081 #if defined(_MHD_HAVE_SENDFILE)
4082 if ( (response->
fd == -1) ||
4084 connection->resp_sender = MHD_resp_sender_std;
4086 connection->resp_sender = MHD_resp_sender_sendfile;
4089 if ( ( (NULL != connection->
method) &&
4102 (NULL != connection->
method) &&
static int process_header_line(struct MHD_Connection *connection, char *line)
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
#define MHD_send_(s, b, l)
static int parse_cookie_header(struct MHD_Connection *connection)
void * unescape_callback_cls
void MHD_connection_handle_write(struct MHD_Connection *connection)
Header for platform missing functions.
static int try_ready_normal_body(struct MHD_Connection *connection)
uint64_t current_chunk_offset
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
DLL_remove(daemon->suspended_connections_head, daemon->suspended_connections_tail, pos)
#define MHD_HTTP_METHOD_CONNECT
void MHD_update_last_activity_(struct MHD_Connection *connection)
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
struct sockaddr_storage addr
struct MHD_Connection * cleanup_head
enum MHD_CONNECTION_STATE state
static int try_ready_chunked_body(struct MHD_Connection *connection)
#define MHD_lookup_header_s_token_ci(c, h, tkn)
uint64_t response_write_position
enum MHD_ConnKeepAlive keepalive
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
#define HTTP_100_CONTINUE
MHD_mutex_lock_chk_ & daemon
enum MHD_ConnectionEventLoopInfo event_loop_info
#define MHD_mutex_unlock_chk_(pmutex)
time_t connection_timeout
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Methods for managing connections.
MHD_PanicCallback mhd_panic
#define MHD_socket_get_error_()
internal monotonic clock functions implementations
struct MHD_Response * response
#define REQUEST_LACKS_HOST
#define MHD_SENFILE_CHUNK_
#define MHD_HTTP_NOT_MODIFIED
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
struct MHD_Connection * manual_timeout_head
MHD_RequestTerminationCode
MHD_thread_handle_ID_ pid
int MHD_str_equal_caseless_(const char *str1, const char *str2)
time_t MHD_monotonic_sec_counter(void)
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
MHD_AccessHandlerCallback default_handler
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
static void call_connection_handler(struct MHD_Connection *connection)
uint64_t remaining_upload_size
unsigned int responseCode
#define MHD_ERR_CONNRESET_
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
#define MHD_UNSIGNED_LONG_LONG
void * uri_log_callback_cls
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
struct MHD_Daemon * daemon
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
#define MHD_check_response_header_s_token_ci(r, k, tkn)
#define MHD_SENFILE_CHUNK_THR_P_C_
static bool MHD_lookup_header_token_ci(const struct MHD_Connection *connection, const char *header, const char *token, size_t token_len)
Header for platform-independent inter-thread communication.
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
static int keepalive_possible(struct MHD_Connection *connection)
#define DLL_insert(head, tail, element)
void MHD_increment_response_rc(struct MHD_Response *response)
#define MHD_HTTP_URI_TOO_LONG
struct MHD_HTTP_Header * first_header
#define MHD_socket_last_strerr_()
size_t write_buffer_send_offset
struct MHD_Connection * connections_tail
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
_MHD_EXTERN union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
size_t continue_message_write_offset
#define REQUEST_MALFORMED
#define MHD_INVALID_SOCKET
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
internal shared structures
#define MHD_SCKT_SEND_MAX_SIZE_
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
struct MHD_Connection * connections_head
#define MHD_HTTP_NO_CONTENT
LogCallback uri_log_callback
static int socket_start_no_buffering(struct MHD_Connection *connection)
void MHD_connection_handle_read(struct MHD_Connection *connection)
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
time_t connection_timeout
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
#define MHD_SCKT_ERR_IS_(err, code)
Methods for managing connections.
#define MHD_CONTENT_READER_END_OF_STREAM
#define EDLL_remove(head, tail, element)
struct MHD_Connection * manual_timeout_tail
static void get_date_string(char *date, size_t date_len)
Header for string manipulating helpers.
static int need_100_continue(struct MHD_Connection *connection)
#define MHD_STATICSTR_LEN_(macro)
#define MHD_HTTP_VERSION_1_1
struct MHD_Connection * normal_timeout_head
void MHD_pool_destroy(struct MemoryPool *pool)
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
UnescapeCallback unescape_callback
static int try_grow_read_buffer(struct MHD_Connection *connection)
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
#define XDLL_remove(head, tail, element)
unsigned int connection_timeout_dummy
#define MHD_HTTP_BAD_REQUEST
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
struct MHD_Connection * suspended_connections_tail
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
struct MHD_Connection * cleanup_tail
int MHD_connection_handle_idle(struct MHD_Connection *connection)
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
enum MHD_ResponseFlags flags
#define MHD_recv_(s, b, l)
#define MHD_connection_finish_forward_(conn)
#define MHD_HTTP_METHOD_HEAD
static void parse_connection_headers(struct MHD_Connection *connection)
size_t write_buffer_append_offset
struct MHD_Connection * normal_timeout_tail
MHD_RequestCompletedCallback notify_completed
#define MHD_mutex_lock_chk_(pmutex)
static int socket_start_extra_buffering(struct MHD_Connection *connection)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
#define MHD_HTTP_METHOD_PUT
void * notify_completed_cls
static void process_request_body(struct MHD_Connection *connection)
#define MHD_HTTP_VERSION_1_0
TransmitCallback send_cls
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
#define MHD_HTTP_INTERNAL_SERVER_ERROR
#define MHD_CONTENT_READER_END_WITH_ERROR
MHD_ContentReaderCallback crc
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
#define XDLL_insert(head, tail, element)
static int socket_start_normal_buffering(struct MHD_Connection *connection)
#define MHD_UNSIGNED_LONG_LONG_PRINTF
#define MHD_HTTP_PROCESSING
#define MHD_SCKT_ECONNRESET_
static int socket_flush_possible(struct MHD_Connection *connection)
struct MHD_Connection * suspended_connections_head
static int socket_start_no_buffering_flush(struct MHD_Connection *connection)
size_t read_buffer_offset
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
void * default_handler_cls
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
#define MHD_SCKT_ERR_IS_EINTR_(err)
MHD_mutex_ cleanup_connection_mutex
#define CONNECTION_CLOSE_ERROR(c, emsg)
uint64_t current_chunk_size
struct MHD_HTTP_Header * headers_received
#define MHD_HTTP_SWITCHING_PROTOCOLS
limits values definitions
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
_MHD_EXTERN int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
struct MHD_HTTP_Header * headers_received_tail
static int build_header_response(struct MHD_Connection *connection)
#define MHD_HTTP_METHOD_POST