aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r--src/microhttpd/connection.c73
1 files changed, 56 insertions, 17 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index fbe9f9d3..30ad1829 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -39,6 +39,11 @@
39#ifdef HAVE_LINUX_SENDFILE 39#ifdef HAVE_LINUX_SENDFILE
40#include <sys/sendfile.h> 40#include <sys/sendfile.h>
41#endif /* HAVE_LINUX_SENDFILE */ 41#endif /* HAVE_LINUX_SENDFILE */
42#ifdef HAVE_FREEBSD_SENDFILE
43#include <sys/types.h>
44#include <sys/socket.h>
45#include <sys/uio.h>
46#endif /* HAVE_FREEBSD_SENDFILE */
42#ifdef HTTPS_SUPPORT 47#ifdef HTTPS_SUPPORT
43#include "connection_https.h" 48#include "connection_https.h"
44#endif /* HTTPS_SUPPORT */ 49#endif /* HTTPS_SUPPORT */
@@ -219,7 +224,7 @@ send_param_adapter (struct MHD_Connection *connection,
219} 224}
220 225
221 226
222#ifdef HAVE_LINUX_SENDFILE 227#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE)
223/** 228/**
224 * Function for sending responses backed by file FD. 229 * Function for sending responses backed by file FD.
225 * 230 *
@@ -234,13 +239,23 @@ sendfile_adapter (struct MHD_Connection *connection)
234 uint64_t left; 239 uint64_t left;
235 uint64_t offsetu64; 240 uint64_t offsetu64;
236#ifndef HAVE_SENDFILE64 241#ifndef HAVE_SENDFILE64
242 const uint64_t max_off_t = (uint64_t)OFF_T_MAX;
243#else /* HAVE_SENDFILE64 */
244 const uint64_t max_off_t = (uint64_t)OFF64_T_MAX;
245#endif /* HAVE_SENDFILE64 */
246#ifdef HAVE_LINUX_SENDFILE
247#ifndef HAVE_SENDFILE64
237 off_t offset; 248 off_t offset;
238#else /* HAVE_SENDFILE64 */ 249#else /* HAVE_SENDFILE64 */
239 off64_t offset; 250 off64_t offset;
240#endif /* HAVE_SENDFILE64 */ 251#endif /* HAVE_SENDFILE64 */
252#endif /* HAVE_LINUX_SENDFILE */
253#ifdef HAVE_FREEBSD_SENDFILE
254 off_t sent_bytes;
255#endif
241 const bool used_thr_p_c = (0 != (connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION)); 256 const bool used_thr_p_c = (0 != (connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION));
242 const size_t chunk_size = used_thr_p_c ? 0x200000 : 0x20000; 257 const size_t chunk_size = used_thr_p_c ? 0x200000 : 0x20000;
243 size_t send_size; 258 size_t send_size = 0;
244 mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender); 259 mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
245 260
246 offsetu64 = connection->response_write_position + connection->response->fd_off; 261 offsetu64 = connection->response_write_position + connection->response->fd_off;
@@ -248,23 +263,19 @@ sendfile_adapter (struct MHD_Connection *connection)
248 /* Do not allow system to stick sending on single fast connection: 263 /* Do not allow system to stick sending on single fast connection:
249 * use 128KiB chunks (2MiB for thread-per-connection). */ 264 * use 128KiB chunks (2MiB for thread-per-connection). */
250 send_size = (left > chunk_size) ? chunk_size : (size_t) left; 265 send_size = (left > chunk_size) ? chunk_size : (size_t) left;
251#ifndef HAVE_SENDFILE64 266 if (max_off_t < offsetu64)
252 if ((uint64_t)OFF_T_MAX < offsetu64)
253 { /* Retry to send with standard 'send()'. */ 267 { /* Retry to send with standard 'send()'. */
254 connection->resp_sender = MHD_resp_sender_std; 268 connection->resp_sender = MHD_resp_sender_std;
255 return MHD_ERR_AGAIN_; 269 return MHD_ERR_AGAIN_;
256 } 270 }
271#ifdef HAVE_LINUX_SENDFILE
272#ifndef HAVE_SENDFILE64
257 offset = (off_t) offsetu64; 273 offset = (off_t) offsetu64;
258 ret = sendfile (connection->socket_fd, 274 ret = sendfile (connection->socket_fd,
259 file_fd, 275 file_fd,
260 &offset, 276 &offset,
261 send_size); 277 send_size);
262#else /* HAVE_SENDFILE64 */ 278#else /* HAVE_SENDFILE64 */
263 if ((uint64_t)OFF64_T_MAX < offsetu64)
264 { /* Retry to send with standard 'send()'. */
265 connection->resp_sender = MHD_resp_sender_std;
266 return MHD_ERR_AGAIN_;
267 }
268 offset = (off64_t) offsetu64; 279 offset = (off64_t) offsetu64;
269 ret = sendfile64 (connection->socket_fd, 280 ret = sendfile64 (connection->socket_fd,
270 file_fd, 281 file_fd,
@@ -299,9 +310,37 @@ sendfile_adapter (struct MHD_Connection *connection)
299 else if (send_size > (size_t)ret) 310 else if (send_size > (size_t)ret)
300 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; 311 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
301#endif /* EPOLL_SUPPORT */ 312#endif /* EPOLL_SUPPORT */
313#elif defined(HAVE_FREEBSD_SENDFILE)
314 if (0 != sendfile (file_fd,
315 connection->socket_fd,
316 (off_t) offsetu64,
317 send_size,
318 NULL,
319 &sent_bytes,
320 0))
321 {
322 const int err = MHD_socket_get_error_();
323 if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
324 MHD_SCKT_ERR_IS_EINTR_(err) ||
325 EBUSY == err)
326 {
327 mhd_assert (SSIZE_MAX >= sent_bytes);
328 if (0 != sent_bytes)
329 return (ssize_t)sent_bytes;
330
331 return MHD_ERR_AGAIN_;
332 }
333 /* Some unrecoverable error. Possibly file FD is not suitable
334 * for sendfile(). Retry with standard send(). */
335 connection->resp_sender = MHD_resp_sender_std;
336 return MHD_ERR_AGAIN_;
337 }
338 mhd_assert (0 < sent_bytes);
339 ret = (ssize_t)sent_bytes;
340#endif /* HAVE_FREEBSD_SENDFILE */
302 return ret; 341 return ret;
303} 342}
304#endif /* HAVE_LINUX_SENDFILE */ 343#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE */
305 344
306 345
307/** 346/**
@@ -933,13 +972,13 @@ try_ready_normal_body (struct MHD_Connection *connection)
933 (response->data_size + response->data_start > 972 (response->data_size + response->data_start >
934 connection->response_write_position) ) 973 connection->response_write_position) )
935 return MHD_YES; /* response already ready */ 974 return MHD_YES; /* response already ready */
936#if defined(HAVE_LINUX_SENDFILE) 975#if defined(HAVE_LINUX_SENDFILE) || defined (HAVE_FREEBSD_SENDFILE)
937 if (MHD_resp_sender_sendfile == connection->resp_sender) 976 if (MHD_resp_sender_sendfile == connection->resp_sender)
938 { 977 {
939 /* will use sendfile, no need to bother response crc */ 978 /* will use sendfile, no need to bother response crc */
940 return MHD_YES; 979 return MHD_YES;
941 } 980 }
942#endif 981#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE */
943 982
944 ret = response->crc (response->crc_cls, 983 ret = response->crc (response->crc_cls,
945 connection->response_write_position, 984 connection->response_write_position,
@@ -2875,15 +2914,15 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
2875 /* mutex was already unlocked by try_ready_normal_body */ 2914 /* mutex was already unlocked by try_ready_normal_body */
2876 return; 2915 return;
2877 } 2916 }
2878#if defined(HAVE_LINUX_SENDFILE) 2917#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE)
2879 if (MHD_resp_sender_sendfile == connection->resp_sender) 2918 if (MHD_resp_sender_sendfile == connection->resp_sender)
2880 { 2919 {
2881 ret = sendfile_adapter (connection); 2920 ret = sendfile_adapter (connection);
2882 } 2921 }
2883 else 2922 else
2884#else /* ! HAVE_LINUX_SENDFILE */ 2923#else /* ! (HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE) */
2885 if (1) 2924 if (1)
2886#endif /* ! HAVE_LINUX_SENDFILE */ 2925#endif /* ! (HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE) */
2887 { 2926 {
2888 data_write_offset = connection->response_write_position 2927 data_write_offset = connection->response_write_position
2889 - response->data_start; 2928 - response->data_start;
@@ -3819,13 +3858,13 @@ MHD_queue_response (struct MHD_Connection *connection,
3819 MHD_increment_response_rc (response); 3858 MHD_increment_response_rc (response);
3820 connection->response = response; 3859 connection->response = response;
3821 connection->responseCode = status_code; 3860 connection->responseCode = status_code;
3822#if defined(HAVE_LINUX_SENDFILE) 3861#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE)
3823 if ( (response->fd == -1) || 3862 if ( (response->fd == -1) ||
3824 (0 != (connection->daemon->options & MHD_USE_TLS)) ) 3863 (0 != (connection->daemon->options & MHD_USE_TLS)) )
3825 connection->resp_sender = MHD_resp_sender_std; 3864 connection->resp_sender = MHD_resp_sender_std;
3826 else 3865 else
3827 connection->resp_sender = MHD_resp_sender_sendfile; 3866 connection->resp_sender = MHD_resp_sender_sendfile;
3828#endif /* HAVE_LINUX_SENDFILE */ 3867#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE */
3829 3868
3830 if ( ( (NULL != connection->method) && 3869 if ( ( (NULL != connection->method) &&
3831 (MHD_str_equal_caseless_ (connection->method, 3870 (MHD_str_equal_caseless_ (connection->method,