38 #ifdef MHD_LINUX_SOLARIS_SENDFILE
39 #include <sys/sendfile.h>
41 #if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
42 #include <sys/types.h>
43 #include <sys/socket.h>
46 #ifdef HAVE_SYS_PARAM_H
48 #include <sys/param.h>
58 #if (! defined (HAVE_SENDMSG) || ! defined(MSG_NOSIGNAL)) && \
59 defined (MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
60 defined (MHD_SEND_SPIPE_SUPPRESS_NEEDED)
61 #define _MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED 1
69 #define MHD_SENFILE_CHUNK_ (0x20000)
74 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
76 #ifdef HAVE_FREEBSD_SENDFILE
81 static int freebsd_sendfile_flags_;
86 static int freebsd_sendfile_flags_thd_p_c_;
93 freebsd_sendfile_init_ (
void)
95 long sys_page_size = sysconf (_SC_PAGESIZE);
96 if (0 >= sys_page_size)
98 freebsd_sendfile_flags_ = SF_NODISKIO;
99 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
103 freebsd_sendfile_flags_ =
105 / sys_page_size), SF_NODISKIO);
106 freebsd_sendfile_flags_thd_p_c_ =
108 / sys_page_size), SF_NODISKIO);
117 #if defined(HAVE_SYSCONF) && defined(_SC_IOV_MAX)
121 static unsigned long mhd_iov_max_ = 0;
126 long res = sysconf (_SC_IOV_MAX);
131 mhd_iov_max_ = IOV_MAX;
139 #define _MHD_IOV_MAX mhd_iov_max_
140 #elif defined(IOV_MAX)
145 #define _MHD_IOV_MAX IOV_MAX
155 #ifdef HAVE_FREEBSD_SENDFILE
160 freebsd_sendfile_init_ ();
163 #if defined(HAVE_SYSCONF) && defined(_SC_IOV_MAX)
181 if (0 == setsockopt (connection->
socket_fd,
184 (
const void *) (nodelay_state ? &on_val : &off_val),
201 MHD_DLOG (connection->
daemon,
202 _ (
"Setting %s option to %s state failed "
203 "for TCP/IP socket %d: %s\n"),
205 nodelay_state ?
_ (
"ON") :
_ (
"OFF"),
214 MHD_DLOG (connection->
daemon,
215 _ (
"Setting %s option to %s state failed: %s\n"),
217 nodelay_state ?
_ (
"ON") :
_ (
"OFF"),
223 (void) connection; (void) nodelay_state;
243 #if defined(MHD_TCP_CORK_NOPUSH)
250 if (0 == setsockopt (connection->
socket_fd,
253 (
const void *) (cork_state ? &on_val : &off_val),
270 MHD_DLOG (connection->
daemon,
271 _ (
"Setting %s option to %s state failed "
272 "for TCP/IP socket %d: %s\n"),
278 cork_state ?
_ (
"ON") :
_ (
"OFF"),
287 MHD_DLOG (connection->
daemon,
288 _ (
"Setting %s option to %s state failed: %s\n"),
294 cork_state ?
_ (
"ON") :
_ (
"OFF"),
300 (void) connection; (void) cork_state;
323 const bool buffer_data = (! push_data);
335 #ifdef MHD_USE_MSG_MORE
343 #ifdef MHD_TCP_CORK_NOPUSH
370 #ifdef MHD_TCP_CORK_NOPUSH
371 #ifdef _MHD_CORK_RESET_PUSH_DATA
372 #ifdef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
386 #ifdef _MHD_NODELAY_SET_PUSH_DATA_ALWAYS
395 #ifdef _MHD_NODELAY_SET_PUSH_DATA
422 #ifdef _MHD_NODELAY_SET_PUSH_DATA
450 #ifdef _MHD_NODELAY_SET_PUSH_DATA
491 #ifdef _MHD_NODELAY_SET_PUSH_DATA
532 #ifndef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
557 MHD_DLOG (connection->
daemon,
558 _ (
"Zero-send failed: %s\n"),
579 bool plain_send_next,
584 const bool buffer_data = (! push_data);
591 #ifndef MHD_USE_MSG_MORE
592 (void) plain_send_next;
596 #ifdef MHD_TCP_CORK_NOPUSH
597 #ifdef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
598 #ifdef _MHD_NODELAY_SET_PUSH_DATA_ALWAYS
599 #ifdef MHD_USE_MSG_MORE
691 #ifdef _MHD_CORK_RESET_PUSH_DATA
698 #ifdef _MHD_CORK_RESET_PUSH_DATA
739 MHD_DLOG (connection->
daemon,
740 _ (
"Failed to push the data from buffers to the network. "
741 "Client may experience some delay "
742 "(usually in range 200ms - 5 sec).\n"));
759 const bool tls_conn =
false;
778 ret = gnutls_record_send (connection->tls_session,
781 if (GNUTLS_E_AGAIN == ret)
788 if (GNUTLS_E_INTERRUPTED == ret)
790 if ( (GNUTLS_E_ENCRYPTION_FAILED == ret) ||
791 (GNUTLS_E_INVALID_SESSION == ret) ||
792 (GNUTLS_E_COMPRESSION_FAILED == ret) ||
793 (GNUTLS_E_EXPIRED == ret) ||
794 (GNUTLS_E_HASH_FAILED == ret) )
796 if ( (GNUTLS_E_PUSH_ERROR == ret) ||
797 (GNUTLS_E_INTERNAL_ERROR == ret) ||
798 (GNUTLS_E_CRYPTODEV_IOCTL_ERROR == ret) ||
799 (GNUTLS_E_CRYPTODEV_DEVICE_ERROR == ret) )
801 if (GNUTLS_E_PREMATURE_TERMINATION == ret)
803 if (GNUTLS_E_MEMORY_ERROR == ret)
828 #ifdef MHD_USE_MSG_MORE
832 push_data ? 0 : MSG_MORE);
872 else if (buffer_size > (
size_t) ret)
884 (buffer_size == (
size_t) ret) )
898 bool complete_response)
905 #define _MHD_SEND_VEC_MAX MHD_SCKT_SEND_MAX_SIZE_
907 #define _MHD_SEND_VEC_MAX UINT32_MAX
910 #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
911 struct iovec vector[2];
926 #if (! defined(HAVE_SENDMSG) || ! defined(MSG_NOSIGNAL) ) && \
927 defined(MHD_SEND_SPIPE_SEND_SUPPRESS_POSSIBLE) && \
928 defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
944 push_body = complete_response;
946 if (! never_push_hdr)
948 if (! complete_response)
954 if (1400 > (header_size + body_size))
967 if (complete_response && (0 == body_size))
977 || ((
size_t)
UINT_MAX < header_size)
989 if ( (header_size == (
size_t) ret) &&
1000 if ( (((
size_t)
SSIZE_MAX) - ((
size_t) ret)) < body_size)
1002 body_size = (((size_t)
SSIZE_MAX) - ((size_t) ret));
1003 complete_response =
false;
1004 push_body = complete_response;
1020 #ifdef MHD_VECT_SEND
1022 if ( ((
size_t)
SSIZE_MAX <= body_size) ||
1023 ((
size_t)
SSIZE_MAX < (header_size + body_size)) )
1027 complete_response =
false;
1028 push_body = complete_response;
1030 #if (SSIZE_MAX != _MHD_SEND_VEC_MAX) || (_MHD_SEND_VEC_MAX + 0 == 0)
1036 complete_response =
false;
1037 push_body = complete_response;
1047 push_hdr || push_body);
1048 #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
1049 vector[0].iov_base = (
void *) header;
1050 vector[0].iov_len = header_size;
1051 vector[1].iov_base = (
void *) body;
1052 vector[1].iov_len = body_size;
1054 #if defined(HAVE_SENDMSG)
1055 memset (&msg, 0,
sizeof(msg));
1056 msg.msg_iov = vector;
1060 #elif defined (HAVE_WRITEV)
1061 ret = writev (s, vector, 2);
1069 complete_response =
false;
1070 push_body = complete_response;
1072 vector[0].buf = (
char *) header;
1073 vector[0].len = (
unsigned long) header_size;
1074 vector[1].buf = (
char *) body;
1075 vector[1].len = (
unsigned long) body_size;
1077 ret = WSASend (s, vector, 2, &vec_sent, 0,
NULL,
NULL);
1079 ret = (ssize_t) vec_sent;
1116 else if ((header_size + body_size) > (
size_t) ret)
1123 ((header_size + body_size) == (
size_t) ret) )
1139 else if ( (push_hdr) &&
1140 (header_size <= (
size_t) ret))
1146 #
if defined(_MHD_HAVE_SENDFILE)
1147 MHD_resp_sender_std == connection->resp_sender,
1162 #if defined(_MHD_HAVE_SENDFILE)
1167 const int file_fd = connection->
response->
fd;
1170 #ifndef HAVE_SENDFILE64
1171 const uint64_t max_off_t = (uint64_t)
OFF_T_MAX;
1173 const uint64_t max_off_t = (uint64_t) OFF64_T_MAX;
1175 #ifdef MHD_LINUX_SOLARIS_SENDFILE
1176 #ifndef HAVE_SENDFILE64
1182 #ifdef HAVE_FREEBSD_SENDFILE
1186 #ifdef HAVE_DARWIN_SENDFILE
1189 const bool used_thr_p_c = (0 != (connection->
daemon->
options
1193 size_t send_size = 0;
1195 mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
1200 if (max_off_t < offsetu64)
1202 connection->resp_sender = MHD_resp_sender_std;
1213 if (chunk_size < left)
1215 send_size = chunk_size;
1220 send_size = (size_t) left;
1225 #ifdef MHD_LINUX_SOLARIS_SENDFILE
1226 #ifndef HAVE_SENDFILE64
1227 offset = (off_t) offsetu64;
1233 offset = (off64_t) offsetu64;
1234 ret = sendfile64 (connection->
socket_fd,
1244 #ifdef EPOLL_SUPPORT
1252 #ifdef HAVE_LINUX_SENDFILE
1261 connection->resp_sender = MHD_resp_sender_std;
1264 if ( (EAFNOSUPPORT == err) ||
1266 (EOPNOTSUPP == err) )
1268 connection->resp_sender = MHD_resp_sender_std;
1271 if ( (ENOTCONN == err) ||
1279 #ifdef EPOLL_SUPPORT
1280 else if (send_size > (
size_t) ret)
1283 #elif defined(HAVE_FREEBSD_SENDFILE)
1285 flags = used_thr_p_c ?
1286 freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
1288 if (0 != sendfile (file_fd,
1302 if (0 != sent_bytes)
1303 return (ssize_t) sent_bytes;
1309 connection->resp_sender = MHD_resp_sender_std;
1314 ret = (ssize_t) sent_bytes;
1315 #elif defined(HAVE_DARWIN_SENDFILE)
1316 len = (off_t) send_size;
1317 if (0 != sendfile (file_fd,
1332 return (ssize_t) len;
1336 if ((ENOTCONN == err) ||
1339 if ((ENOTSUP == err) ||
1340 (EOPNOTSUPP == err) )
1343 connection->resp_sender = MHD_resp_sender_std;
1351 ret = (ssize_t) len;
1359 (send_size == (size_t) ret) )
1368 #if defined(MHD_VECT_SEND)
1391 size_t items_to_send;
1394 #elif defined(MHD_WINSOCK_SOCKETS)
1407 items_to_send = r_iov->
cnt - r_iov->
sent;
1409 if (_MHD_IOV_MAX < items_to_send)
1412 if (0 == _MHD_IOV_MAX)
1414 items_to_send = _MHD_IOV_MAX;
1419 memset (&msg, 0,
sizeof(
struct msghdr));
1420 msg.msg_iov = r_iov->
iov + r_iov->
sent;
1421 msg.msg_iovlen = items_to_send;
1424 #ifdef MHD_USE_MSG_MORE
1425 res = sendmsg (connection->
socket_fd, &msg,
1430 #elif defined(HAVE_WRITEV)
1434 #elif defined(MHD_WINSOCK_SOCKETS)
1442 cnt_w = (DWORD) items_to_send;
1444 cnt_w = (DWORD) items_to_send;
1447 if (0 == WSASend (connection->
socket_fd,
1448 (LPWSABUF) (r_iov->
iov + r_iov->
sent),
1451 res = (ssize_t) bytes_sent;
1455 #error No vector-send function available
1464 #ifdef EPOLL_SUPPORT
1494 while ((0 != res) && (r_iov->
iov[r_iov->
sent].
iov_len <= (
size_t) res))
1501 if (r_iov->
cnt == r_iov->
sent)
1505 #ifdef EPOLL_SUPPORT
1524 #if ! defined(MHD_VECT_SEND) || defined(HTTPS_SUPPORT) || \
1525 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)
1555 if ((
size_t)
SSIZE_MAX - total_sent < r_iov->iov[r_iov->
sent].iov_len)
1561 push_data && (r_iov->
cnt == r_iov->
sent + 1));
1565 if (0 == total_sent)
1574 total_sent += (size_t) res;
1588 }
while ((r_iov->
cnt > r_iov->
sent) && (non_blk));
1590 return (ssize_t) total_sent;
1603 #ifdef MHD_VECT_SEND
1604 #if defined(HTTPS_SUPPORT) || \
1605 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)
1606 bool use_iov_send =
true;
1613 #ifdef MHD_VECT_SEND
1614 #if defined(HTTPS_SUPPORT) || \
1615 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)
1616 #ifdef HTTPS_SUPPORT
1617 use_iov_send = use_iov_send &&
1620 #ifdef _MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED
1626 return send_iov_nontls (connection, r_iov, push_data);
1629 #if ! defined(MHD_VECT_SEND) || defined(HTTPS_SUPPORT) || \
1630 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)