diff options
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r-- | src/microhttpd/connection.c | 73 |
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, |