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>
57 #define MHD_SENFILE_CHUNK_ (0x20000)
62 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
64 #ifdef HAVE_FREEBSD_SENDFILE
69 static int freebsd_sendfile_flags_;
74 static int freebsd_sendfile_flags_thd_p_c_;
80 MHD_send_init_static_vars_ (
void)
86 long sys_page_size = sysconf (_SC_PAGESIZE);
87 if (0 >= sys_page_size)
89 freebsd_sendfile_flags_ = SF_NODISKIO;
90 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
94 freebsd_sendfile_flags_ =
96 / sys_page_size), SF_NODISKIO);
97 freebsd_sendfile_flags_thd_p_c_ =
99 / sys_page_size), SF_NODISKIO);
124 if (0 == setsockopt (connection->
socket_fd,
127 (
const void *) (nodelay_state ? &on_val : &off_val),
150 MHD_DLOG (connection->
daemon,
151 _ (
"Setting %s option to %s state failed: %s\n"),
153 nodelay_state ?
_ (
"ON") :
_ (
"OFF"),
162 #if defined(MHD_TCP_CORK_NOPUSH)
179 if (0 == setsockopt (connection->
socket_fd,
182 (
const void *) (cork_state ? &on_val : &off_val),
205 MHD_DLOG (connection->
daemon,
206 _ (
"Setting %s option to %s state failed: %s\n"),
212 cork_state ?
_ (
"ON") :
_ (
"OFF"),
240 const bool buffer_data = (! push_data);
250 #ifdef MHD_USE_MSG_MORE
258 #ifdef MHD_TCP_CORK_NOPUSH
262 if (connection_set_cork_state_ (connection,
true))
285 #ifdef MHD_TCP_CORK_NOPUSH
286 #ifdef _MHD_CORK_RESET_PUSH_DATA
287 #ifdef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
301 #ifdef _MHD_NODELAY_SET_PUSH_DATA_ALWAYS
310 #ifdef _MHD_NODELAY_SET_PUSH_DATA
337 #ifdef _MHD_NODELAY_SET_PUSH_DATA
342 if (connection_set_cork_state_ (connection,
true))
365 #ifdef _MHD_NODELAY_SET_PUSH_DATA
386 connection_set_cork_state_ (connection,
true);
396 if (connection_set_cork_state_ (connection,
true))
406 #ifdef _MHD_NODELAY_SET_PUSH_DATA
429 connection_set_cork_state_ (connection,
false);
447 #ifndef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
472 MHD_DLOG (connection->
daemon,
473 _ (
"Zero-send failed: %s\n"),
494 bool plain_send_next,
499 const bool buffer_data = (! push_data);
504 #ifndef MHD_USE_MSG_MORE
505 (void) plain_send_next;
509 #ifdef MHD_TCP_CORK_NOPUSH
510 #ifdef _MHD_CORK_RESET_PUSH_DATA_ALWAYS
511 #ifdef _MHD_NODELAY_SET_PUSH_DATA_ALWAYS
512 #ifdef MHD_USE_MSG_MORE
540 if (connection_set_cork_state_ (connection,
false))
549 if (connection_set_cork_state_ (connection,
false))
567 if (connection_set_cork_state_ (connection,
false))
575 if (connection_set_cork_state_ (connection,
false))
604 #ifdef _MHD_CORK_RESET_PUSH_DATA
609 if (connection_set_cork_state_ (connection,
false))
611 #ifdef _MHD_CORK_RESET_PUSH_DATA
652 MHD_DLOG (connection->
daemon,
653 _ (
"Failed to push the data from buffers to the network. "
654 "Client may experience some delay "
655 "(usually in range 200ms - 5 sec).\n"));
672 const bool tls_conn =
false;
691 ret = gnutls_record_send (connection->tls_session,
694 if (GNUTLS_E_AGAIN == ret)
701 if (GNUTLS_E_INTERRUPTED == ret)
703 if ( (GNUTLS_E_ENCRYPTION_FAILED == ret) ||
704 (GNUTLS_E_INVALID_SESSION == ret) )
706 if (GNUTLS_E_MEMORY_ERROR == ret)
731 #ifdef MHD_USE_MSG_MORE
735 push_data ? 0 : MSG_MORE);
765 else if (buffer_size > (
size_t) ret)
777 (buffer_size == (
size_t) ret) )
784 #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV) || defined(_WIN32)
785 #define _MHD_USE_SEND_VEC 1
795 bool complete_response)
802 #define _MHD_SEND_VEC_MAX MHD_SCKT_SEND_MAX_SIZE_
804 #define _MHD_SEND_VEC_MAX UINT32_MAX
806 #ifdef _MHD_USE_SEND_VEC
807 #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
808 struct iovec vector[2];
823 #if ! defined(MHD_WINSOCK_SOCKETS) && \
824 (! defined(HAVE_SENDMSG) || ! defined(MSG_NOSIGNAL)) && \
825 defined(HAVE_SEND_SIGPIPE_SUPPRESS)
840 push_body = complete_response;
842 if (! never_push_hdr)
844 if (! complete_response)
850 if (1400 > (header_size + body_size))
863 if (complete_response && (0 == body_size))
867 #ifdef _MHD_USE_SEND_VEC
873 || ((
size_t)
UINT_MAX < header_size)
885 if ( (header_size == (
size_t) ret) &&
896 if ( (((
size_t)
SSIZE_MAX) - ((
size_t) ret)) < body_size)
898 body_size = (((size_t)
SSIZE_MAX) - ((size_t) ret));
899 complete_response =
false;
900 push_body = complete_response;
916 #ifdef _MHD_USE_SEND_VEC
918 if ( ((
size_t)
SSIZE_MAX <= body_size) ||
919 ((
size_t)
SSIZE_MAX < (header_size + body_size)) )
923 complete_response =
false;
924 push_body = complete_response;
926 #if (SSIZE_MAX != _MHD_SEND_VEC_MAX) || (_MHD_SEND_VEC_MAX + 0 == 0)
932 complete_response =
false;
933 push_body = complete_response;
943 push_hdr || push_body);
944 #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
945 vector[0].iov_base = (
void *) header;
946 vector[0].iov_len = header_size;
947 vector[1].iov_base = (
void *) body;
948 vector[1].iov_len = body_size;
950 #if defined(HAVE_SENDMSG)
951 memset (&msg, 0,
sizeof(msg));
952 msg.msg_iov = vector;
956 #elif defined (HAVE_WRITEV)
957 ret = writev (s, vector, 2);
965 complete_response =
false;
966 push_body = complete_response;
968 vector[0].buf = (
char *) header;
969 vector[0].len = (
unsigned long) header_size;
970 vector[1].buf = (
char *) body;
971 vector[1].len = (
unsigned long) body_size;
973 ret = WSASend (s, vector, 2, &vec_sent, 0,
NULL,
NULL);
975 ret = (ssize_t) vec_sent;
1002 else if ((header_size + body_size) > (
size_t) ret)
1009 ((header_size + body_size) == (
size_t) ret) )
1025 else if ( (push_hdr) &&
1026 (header_size <= (
size_t) ret))
1032 #
if defined(_MHD_HAVE_SENDFILE)
1033 MHD_resp_sender_std == connection->resp_sender,
1048 #if defined(_MHD_HAVE_SENDFILE)
1053 const int file_fd = connection->
response->
fd;
1056 #ifndef HAVE_SENDFILE64
1057 const uint64_t max_off_t = (uint64_t)
OFF_T_MAX;
1059 const uint64_t max_off_t = (uint64_t) OFF64_T_MAX;
1061 #ifdef MHD_LINUX_SOLARIS_SENDFILE
1062 #ifndef HAVE_SENDFILE64
1068 #ifdef HAVE_FREEBSD_SENDFILE
1072 #ifdef HAVE_DARWIN_SENDFILE
1075 const bool used_thr_p_c = (0 != (connection->
daemon->
options
1079 size_t send_size = 0;
1081 mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
1086 if (max_off_t < offsetu64)
1088 connection->resp_sender = MHD_resp_sender_std;
1099 if (chunk_size < left)
1101 send_size = chunk_size;
1106 send_size = (size_t) left;
1111 #ifdef MHD_LINUX_SOLARIS_SENDFILE
1112 #ifndef HAVE_SENDFILE64
1113 offset = (off_t) offsetu64;
1119 offset = (off64_t) offsetu64;
1120 ret = sendfile64 (connection->
socket_fd,
1130 #ifdef EPOLL_SUPPORT
1138 #ifdef HAVE_LINUX_SENDFILE
1147 connection->resp_sender = MHD_resp_sender_std;
1150 if ( (EAFNOSUPPORT == err) ||
1152 (EOPNOTSUPP == err) )
1154 connection->resp_sender = MHD_resp_sender_std;
1157 if ( (ENOTCONN == err) ||
1165 #ifdef EPOLL_SUPPORT
1166 else if (send_size > (
size_t) ret)
1169 #elif defined(HAVE_FREEBSD_SENDFILE)
1171 flags = used_thr_p_c ?
1172 freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
1174 if (0 != sendfile (file_fd,
1188 if (0 != sent_bytes)
1189 return (ssize_t) sent_bytes;
1195 connection->resp_sender = MHD_resp_sender_std;
1200 ret = (ssize_t) sent_bytes;
1201 #elif defined(HAVE_DARWIN_SENDFILE)
1202 len = (off_t) send_size;
1203 if (0 != sendfile (file_fd,
1218 return (ssize_t) len;
1222 if ((ENOTCONN == err) ||
1225 if ((ENOTSUP == err) ||
1226 (EOPNOTSUPP == err) )
1229 connection->resp_sender = MHD_resp_sender_std;
1237 ret = (ssize_t) len;
1245 (send_size == (size_t) ret) )
#define MHD_ERR_CONNRESET_
@ MHD_EPOLL_STATE_WRITE_READY
#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_socket_get_error_()
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MHD_send_(s, b, l)
#define MHD_SCKT_ECONNRESET_
#define MHD_SENFILE_CHUNK_THR_P_C_
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_data_(struct MHD_Connection *connection, const char *buffer, size_t buffer_size, bool push_data)
static bool zero_send_(struct MHD_Connection *connection)
#define _MHD_SEND_VEC_MAX
static bool connection_set_nodelay_state_(struct MHD_Connection *connection, bool nodelay_state)
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)
#define MHD_SENFILE_CHUNK_
Declarations of send() wrappers.
limits values definitions
#define MHD_send4_(s, b, l, f)
#define MSG_NOSIGNAL_OR_ZERO
#define MHD_INVALID_SOCKET
@ MHD_USE_THREAD_PER_CONNECTION
enum MHD_tristate sk_nodelay
struct MHD_Response * response
uint64_t response_write_position
enum MHD_CONNECTION_STATE state
struct MHD_Daemon * daemon
enum MHD_tristate sk_corked