38#ifdef MHD_LINUX_SOLARIS_SENDFILE
39#include <sys/sendfile.h>
41#if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
43#include <sys/socket.h>
46#ifdef HAVE_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
81static int freebsd_sendfile_flags_;
86static int freebsd_sendfile_flags_thd_p_c_;
93freebsd_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)
121static unsigned long mhd_iov_max_ = 0;
126 long res = sysconf (_SC_IOV_MAX);
128 mhd_iov_max_ = (
unsigned long) res;
132 mhd_iov_max_ = IOV_MAX;
143#define _MHD_IOV_MAX mhd_iov_max_
144#elif defined(IOV_MAX)
149#define _MHD_IOV_MAX IOV_MAX
159#ifdef HAVE_FREEBSD_SENDFILE
164 freebsd_sendfile_init_ ();
167#if defined(HAVE_SYSCONF) && defined(_SC_IOV_MAX)
185 if (0 == setsockopt (connection->
socket_fd,
188 (
const void *) (nodelay_state ? &on_val : &off_val),
205 MHD_DLOG (connection->
daemon,
206 _ (
"Setting %s option to %s state failed "
207 "for TCP/IP socket %d: %s\n"),
209 nodelay_state ?
_ (
"ON") :
_ (
"OFF"),
218 MHD_DLOG (connection->
daemon,
219 _ (
"Setting %s option to %s state failed: %s\n"),
221 nodelay_state ?
_ (
"ON") :
_ (
"OFF"),
227 (void) connection; (void) nodelay_state;
247#if defined(MHD_TCP_CORK_NOPUSH)
254 if (0 == setsockopt (connection->
socket_fd,
257 (
const void *) (cork_state ? &on_val : &off_val),
274 MHD_DLOG (connection->
daemon,
275 _ (
"Setting %s option to %s state failed "
276 "for TCP/IP socket %d: %s\n"),
282 cork_state ?
_ (
"ON") :
_ (
"OFF"),
291 MHD_DLOG (connection->
daemon,
292 _ (
"Setting %s option to %s state failed: %s\n"),
298 cork_state ?
_ (
"ON") :
_ (
"OFF"),
304 (void) connection; (void) cork_state;
327 const bool buffer_data = (! push_data);
339#ifdef MHD_USE_MSG_MORE
347#ifdef MHD_TCP_CORK_NOPUSH
374#ifdef MHD_TCP_CORK_NOPUSH
375#ifdef _MHD_CORK_RESET_PUSH_DATA
376#ifdef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
390#ifdef _MHD_NODELAY_SET_PUSH_DATA_ALWAYS
399#ifdef _MHD_NODELAY_SET_PUSH_DATA
426#ifdef _MHD_NODELAY_SET_PUSH_DATA
454#ifdef _MHD_NODELAY_SET_PUSH_DATA
495#ifdef _MHD_NODELAY_SET_PUSH_DATA
536#ifndef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
561 MHD_DLOG (connection->
daemon,
562 _ (
"Zero-send failed: %s\n"),
583 bool plain_send_next,
588 const bool buffer_data = (! push_data);
595#ifndef MHD_USE_MSG_MORE
596 (void) plain_send_next;
600#ifdef MHD_TCP_CORK_NOPUSH
601#ifdef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
602#ifdef _MHD_NODELAY_SET_PUSH_DATA_ALWAYS
603#ifdef MHD_USE_MSG_MORE
695#ifdef _MHD_CORK_RESET_PUSH_DATA
702#ifdef _MHD_CORK_RESET_PUSH_DATA
743 MHD_DLOG (connection->
daemon,
744 _ (
"Failed to push the data from buffers to the network. "
745 "Client may experience some delay "
746 "(usually in range 200ms - 5 sec).\n"));
763 const bool tls_conn =
false;
782 ret = gnutls_record_send (connection->tls_session,
785 if (GNUTLS_E_AGAIN == ret)
788 connection->epoll_state &=
793 if (GNUTLS_E_INTERRUPTED == ret)
795 if ( (GNUTLS_E_ENCRYPTION_FAILED == ret) ||
796 (GNUTLS_E_INVALID_SESSION == ret) ||
797 (GNUTLS_E_COMPRESSION_FAILED == ret) ||
798 (GNUTLS_E_EXPIRED == ret) ||
799 (GNUTLS_E_HASH_FAILED == ret) )
801 if ( (GNUTLS_E_PUSH_ERROR == ret) ||
802 (GNUTLS_E_INTERNAL_ERROR == ret) ||
803 (GNUTLS_E_CRYPTODEV_IOCTL_ERROR == ret) ||
804 (GNUTLS_E_CRYPTODEV_DEVICE_ERROR == ret) )
806#if defined(GNUTLS_E_PREMATURE_TERMINATION)
807 if (GNUTLS_E_PREMATURE_TERMINATION == ret)
809#elif defined(GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
810 if (GNUTLS_E_UNEXPECTED_PACKET_LENGTH == ret)
813 if (GNUTLS_E_MEMORY_ERROR == ret)
839#ifdef MHD_USE_MSG_MORE
843 push_data ? 0 : MSG_MORE);
859 connection->epoll_state &=
884 else if (buffer_size > (
size_t) ret)
885 connection->epoll_state &=
897 (buffer_size == (
size_t) ret) )
911 bool complete_response)
918#define _MHD_SEND_VEC_MAX MHD_SCKT_SEND_MAX_SIZE_
920#define _MHD_SEND_VEC_MAX UINT32_MAX
923#if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
924 struct iovec vector[2];
939#if (! defined(HAVE_SENDMSG) || ! defined(MSG_NOSIGNAL) ) && \
940 defined(MHD_SEND_SPIPE_SEND_SUPPRESS_POSSIBLE) && \
941 defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
957 push_body = complete_response;
959 if (! never_push_hdr)
961 if (! complete_response)
967 if (1400 > (header_size + body_size))
980 if (complete_response && (0 == body_size))
990 || ((
size_t)
UINT_MAX < header_size)
1002 if ( (header_size == (
size_t) ret) &&
1013 if ( (((
size_t)
SSIZE_MAX) - ((
size_t) ret)) < body_size)
1015 body_size = (((size_t)
SSIZE_MAX) - ((size_t) ret));
1016 complete_response =
false;
1017 push_body = complete_response;
1035 if ( ((
size_t)
SSIZE_MAX <= body_size) ||
1036 ((
size_t)
SSIZE_MAX < (header_size + body_size)) )
1040 complete_response =
false;
1041 push_body = complete_response;
1043#if (SSIZE_MAX != _MHD_SEND_VEC_MAX) || (_MHD_SEND_VEC_MAX + 0 == 0)
1049 complete_response =
false;
1050 push_body = complete_response;
1060 push_hdr || push_body);
1061#if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
1063 vector[0].iov_len = header_size;
1065 vector[1].iov_len = body_size;
1067#if defined(HAVE_SENDMSG)
1068 memset (&msg, 0,
sizeof(msg));
1069 msg.msg_iov = vector;
1073#elif defined(HAVE_WRITEV)
1074 ret = writev (s, vector, 2);
1082 complete_response =
false;
1083 push_body = complete_response;
1086 vector[0].len = (
unsigned long) header_size;
1088 vector[1].len = (
unsigned long) body_size;
1090 ret = WSASend (s, vector, 2, &vec_sent, 0,
NULL,
NULL);
1092 ret = (ssize_t) vec_sent;
1105 connection->epoll_state &=
1130 else if ((header_size + body_size) > (
size_t) ret)
1131 connection->epoll_state &=
1138 ((header_size + body_size) == (
size_t) ret) )
1154 else if ( (push_hdr) &&
1155 (header_size <= (
size_t) ret))
1161#
if defined(_MHD_HAVE_SENDFILE)
1162 MHD_resp_sender_std == connection->
rp.resp_sender,
1177#if defined(_MHD_HAVE_SENDFILE)
1185#ifndef HAVE_SENDFILE64
1186 const uint64_t max_off_t = (uint64_t)
OFF_T_MAX;
1188 const uint64_t max_off_t = (uint64_t) OFF64_T_MAX;
1190#ifdef MHD_LINUX_SOLARIS_SENDFILE
1191#ifndef HAVE_SENDFILE64
1197#ifdef HAVE_FREEBSD_SENDFILE
1201#ifdef HAVE_DARWIN_SENDFILE
1204 const bool used_thr_p_c =
1208 size_t send_size = 0;
1210 mhd_assert (MHD_resp_sender_sendfile == connection->
rp.resp_sender);
1215 if (max_off_t < offsetu64)
1217 connection->
rp.resp_sender = MHD_resp_sender_std;
1229 if (chunk_size < left)
1231 send_size = chunk_size;
1236 send_size = (size_t) left;
1241#ifdef MHD_LINUX_SOLARIS_SENDFILE
1242#ifndef HAVE_SENDFILE64
1243 offset = (off_t) offsetu64;
1249 offset = (off64_t) offsetu64;
1250 ret = sendfile64 (connection->
socket_fd,
1262 connection->epoll_state &=
1269#ifdef HAVE_LINUX_SENDFILE
1278 connection->
rp.resp_sender = MHD_resp_sender_std;
1281 if ( (EAFNOSUPPORT == err) ||
1283 (EOPNOTSUPP == err) )
1285 connection->
rp.resp_sender = MHD_resp_sender_std;
1288 if ( (ENOTCONN == err) ||
1297 else if (send_size > (
size_t) ret)
1298 connection->epoll_state &=
1301#elif defined(HAVE_FREEBSD_SENDFILE)
1303 flags = used_thr_p_c ?
1304 freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
1306 if (0 != sendfile (file_fd,
1320 if (0 != sent_bytes)
1321 return (ssize_t) sent_bytes;
1327 connection->
rp.resp_sender = MHD_resp_sender_std;
1332 ret = (ssize_t) sent_bytes;
1333#elif defined(HAVE_DARWIN_SENDFILE)
1334 len = (off_t) send_size;
1335 if (0 != sendfile (file_fd,
1350 return (ssize_t) len;
1354 if ((ENOTCONN == err) ||
1357 if ((ENOTSUP == err) ||
1358 (EOPNOTSUPP == err) )
1361 connection->
rp.resp_sender = MHD_resp_sender_std;
1369 ret = (ssize_t) len;
1377 (send_size == (
size_t) ret) )
1386#if defined(MHD_VECT_SEND)
1408 size_t items_to_send;
1411#elif defined(MHD_WINSOCK_SOCKETS)
1424 items_to_send = r_iov->
cnt - r_iov->
sent;
1426 if (_MHD_IOV_MAX < items_to_send)
1429 if (0 == _MHD_IOV_MAX)
1431 items_to_send = _MHD_IOV_MAX;
1436 memset (&msg, 0,
sizeof(
struct msghdr));
1437 msg.msg_iov = r_iov->
iov + r_iov->
sent;
1438 msg.msg_iovlen = items_to_send;
1441#ifdef MHD_USE_MSG_MORE
1442 res = sendmsg (connection->
socket_fd, &msg,
1447#elif defined(HAVE_WRITEV)
1451#elif defined(MHD_WINSOCK_SOCKETS)
1459 cnt_w = (DWORD) items_to_send;
1461 cnt_w = (DWORD) items_to_send;
1464 if (0 == WSASend (connection->
socket_fd,
1465 (LPWSABUF) (r_iov->
iov + r_iov->
sent),
1468 res = (ssize_t) bytes_sent;
1472#error No vector-send function available
1483 connection->epoll_state &=
1511 size_t track_sent = (size_t) res;
1514 while ((0 != track_sent) && (r_iov->
iov[r_iov->
sent].
iov_len <= track_sent))
1521 if (r_iov->
cnt == r_iov->
sent)
1526 connection->epoll_state &=
1529 if (0 != track_sent)
1546#if ! defined(MHD_VECT_SEND) || defined(HTTPS_SUPPORT) || \
1547 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)
1577 if ((
size_t)
SSIZE_MAX - total_sent < r_iov->iov[r_iov->
sent].iov_len)
1578 return (ssize_t) total_sent;
1583 push_data && (r_iov->
cnt == r_iov->
sent + 1));
1587 if (0 == total_sent)
1591 return (ssize_t) total_sent;
1596 total_sent += (size_t) res;
1600 const size_t sent = (size_t) res;
1607 return (ssize_t) total_sent;
1611 }
while ((r_iov->
cnt > r_iov->
sent) && (non_blk));
1613 return (ssize_t) total_sent;
1627#if defined(HTTPS_SUPPORT) || \
1628 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)
1629 bool use_iov_send =
true;
1637#if defined(HTTPS_SUPPORT) || \
1638 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)
1640 use_iov_send = use_iov_send &&
1643#ifdef _MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED
1649 return send_iov_nontls (connection, r_iov, push_data);
1652#if ! defined(MHD_VECT_SEND) || defined(HTTPS_SUPPORT) || \
1653 defined(_MHD_VECT_SEND_NEEDS_SPIPE_SUPPRESSED)
#define MHD_SENFILE_CHUNK_THR_P_C_
#define MHD_SENFILE_CHUNK_
#define MHD_ERR_CONNRESET_
#define MHD_ERR_OPNOTSUPP_
@ MHD_EPOLL_STATE_WRITE_READY
#define _MHD_DROP_CONST(ptr)
#define MHD_D_IS_USING_THREAD_PER_CONN_(d)
#define mhd_assert(ignore)
limits values definitions
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)
static bool zero_send_(struct MHD_Connection *connection)
bool MHD_connection_set_cork_state_(struct MHD_Connection *connection, bool cork_state)
#define _MHD_SEND_VEC_MAX
void MHD_send_init_static_vars_(void)
static void pre_send_setopt(struct MHD_Connection *connection, bool plain_send, bool push_data)
static void post_send_setopt(struct MHD_Connection *connection, bool plain_send_next, bool push_data)
static ssize_t send_iov_emu(struct MHD_Connection *connection, struct MHD_iovec_track_ *const r_iov, bool push_data)
bool MHD_connection_set_nodelay_state_(struct MHD_Connection *connection, bool nodelay_state)
Declarations of send() wrappers.
#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_strerr_(err)
#define MHD_socket_last_strerr_()
#define MHD_SCKT_EOPNOTSUPP_
#define MHD_SCKT_ENOPROTOOPT_
#define MHD_socket_get_error_()
#define MHD_SCKT_ERR_IS_REMOTE_DISCNN_(err)
#define MHD_send4_(s, b, l, f)
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MHD_SCKT_ENOTCONN_
#define MHD_SCKT_ENOTSOCK_
#define MHD_send_(s, b, l)
#define MSG_NOSIGNAL_OR_ZERO
#define MHD_INVALID_SOCKET
enum MHD_tristate sk_nodelay
enum MHD_tristate is_nonip
enum MHD_CONNECTION_STATE state
struct MHD_Daemon * daemon
enum MHD_tristate sk_corked
uint64_t rsp_write_position
struct MHD_iovec_track_ resp_iov
struct MHD_Response * response