diff options
Diffstat (limited to 'src/microhttpd/mhd_send.c')
-rw-r--r-- | src/microhttpd/mhd_send.c | 347 |
1 files changed, 176 insertions, 171 deletions
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c index b3fb25da..e50be96e 100644 --- a/src/microhttpd/mhd_send.c +++ b/src/microhttpd/mhd_send.c | |||
@@ -55,68 +55,69 @@ pre_cork_setsockopt (struct MHD_Connection *connection, | |||
55 | 55 | ||
56 | /* If sk_cork_on is already what we pass in, return. */ | 56 | /* If sk_cork_on is already what we pass in, return. */ |
57 | if (connection->sk_cork_on == want_cork) | 57 | if (connection->sk_cork_on == want_cork) |
58 | { | 58 | { |
59 | /* nothing to do, success! */ | 59 | /* nothing to do, success! */ |
60 | return; | 60 | return; |
61 | } | 61 | } |
62 | if (! want_cork) | 62 | if (! want_cork) |
63 | return; /* nothing to do *pre* syscall! */ | 63 | return; /* nothing to do *pre* syscall! */ |
64 | ret = MHD_socket_cork_ (connection->socket_fd, | 64 | ret = MHD_socket_cork_ (connection->socket_fd, |
65 | true); | 65 | true); |
66 | if (0 == ret) | 66 | if (0 == ret) |
67 | { | 67 | { |
68 | connection->sk_cork_on = true; | 68 | connection->sk_cork_on = true; |
69 | return; | 69 | return; |
70 | } | 70 | } |
71 | switch (errno) | 71 | switch (errno) |
72 | { | 72 | { |
73 | case ENOTSOCK: | 73 | case ENOTSOCK: |
74 | /* FIXME: Could be we are talking to a pipe, maybe remember this | 74 | /* FIXME: Could be we are talking to a pipe, maybe remember this |
75 | and avoid all setsockopt() in the future? */ | 75 | and avoid all setsockopt() in the future? */ |
76 | break; | 76 | break; |
77 | case EBADF: | 77 | case EBADF: |
78 | /* FIXME: should we die hard here? */ | 78 | /* FIXME: should we die hard here? */ |
79 | break; | 79 | break; |
80 | case EINVAL: | 80 | case EINVAL: |
81 | /* FIXME: optlen invalid, should at least log this, maybe die */ | 81 | /* FIXME: optlen invalid, should at least log this, maybe die */ |
82 | #ifdef HAVE_MESSAGES | 82 | #ifdef HAVE_MESSAGES |
83 | MHD_DLOG (daemon, | 83 | MHD_DLOG (daemon, |
84 | _("optlen invalid: %s\n"), | 84 | _ ("optlen invalid: %s\n"), |
85 | MHD_socket_last_strerr_()); | 85 | MHD_socket_last_strerr_ ()); |
86 | #endif | 86 | #endif |
87 | break; | 87 | break; |
88 | case EFAULT: | 88 | case EFAULT: |
89 | /* wopsie, should at leats log this, FIXME: maybe die */ | 89 | /* wopsie, should at leats log this, FIXME: maybe die */ |
90 | #ifdef HAVE_MESSAGES | 90 | #ifdef HAVE_MESSAGES |
91 | MHD_DLOG (daemon, | 91 | MHD_DLOG (daemon, |
92 | _("The addresss pointed to by optval is not a valid part of the process address space: %s\n"), | 92 | _ ( |
93 | MHD_socket_last_strerr_()); | 93 | "The addresss pointed to by optval is not a valid part of the process address space: %s\n"), |
94 | MHD_socket_last_strerr_ ()); | ||
94 | #endif | 95 | #endif |
95 | break; | 96 | break; |
96 | case ENOPROTOOPT: | 97 | case ENOPROTOOPT: |
97 | /* optlen unknown, should at least log this */ | 98 | /* optlen unknown, should at least log this */ |
98 | #ifdef HAVE_MESSAGES | 99 | #ifdef HAVE_MESSAGES |
99 | MHD_DLOG (daemon, | 100 | MHD_DLOG (daemon, |
100 | _("The option is unknown: %s\n"), | 101 | _ ("The option is unknown: %s\n"), |
101 | MHD_socket_last_strerr_()); | 102 | MHD_socket_last_strerr_ ()); |
102 | #endif | 103 | #endif |
103 | break; | 104 | break; |
104 | default: | 105 | default: |
105 | /* any others? man page does not list more... */ | 106 | /* any others? man page does not list more... */ |
106 | break; | 107 | break; |
107 | } | 108 | } |
108 | #else | 109 | #else |
109 | /* CORK/NOPUSH/MSG_MORE do not exist on this platform, | 110 | /* CORK/NOPUSH/MSG_MORE do not exist on this platform, |
110 | so we must toggle Naggle's algorithm on/off instead | 111 | so we must toggle Naggle's algorithm on/off instead |
111 | (otherwise we keep it always off) */ | 112 | (otherwise we keep it always off) */ |
112 | if (connection->sk_cork_on == want_cork) | 113 | if (connection->sk_cork_on == want_cork) |
113 | { | 114 | { |
114 | /* nothing to do, success! */ | 115 | /* nothing to do, success! */ |
115 | return; | 116 | return; |
116 | } | 117 | } |
117 | if ( (want_cork) && | 118 | if ( (want_cork) && |
118 | (0 == MHD_socket_set_nodelay_ (connection->socket_fd, | 119 | (0 == MHD_socket_set_nodelay_ (connection->socket_fd, |
119 | false)) ) | 120 | false)) ) |
120 | connection->sk_cork_on = true; | 121 | connection->sk_cork_on = true; |
121 | #endif | 122 | #endif |
122 | } | 123 | } |
@@ -139,10 +140,10 @@ post_cork_setsockopt (struct MHD_Connection *connection, | |||
139 | 140 | ||
140 | /* If sk_cork_on is already what we pass in, return. */ | 141 | /* If sk_cork_on is already what we pass in, return. */ |
141 | if (connection->sk_cork_on == want_cork) | 142 | if (connection->sk_cork_on == want_cork) |
142 | { | 143 | { |
143 | /* nothing to do, success! */ | 144 | /* nothing to do, success! */ |
144 | return; | 145 | return; |
145 | } | 146 | } |
146 | if (want_cork) | 147 | if (want_cork) |
147 | return; /* nothing to do *post* syscall (in fact, we should never | 148 | return; /* nothing to do *post* syscall (in fact, we should never |
148 | get here, as sk_cork_on should have succeeded in the | 149 | get here, as sk_cork_on should have succeeded in the |
@@ -150,59 +151,60 @@ post_cork_setsockopt (struct MHD_Connection *connection, | |||
150 | ret = MHD_socket_cork_ (connection->socket_fd, | 151 | ret = MHD_socket_cork_ (connection->socket_fd, |
151 | false); | 152 | false); |
152 | if (0 == ret) | 153 | if (0 == ret) |
153 | { | 154 | { |
154 | connection->sk_cork_on = false; | 155 | connection->sk_cork_on = false; |
155 | return; | 156 | return; |
156 | } | 157 | } |
157 | switch (errno) | 158 | switch (errno) |
158 | { | 159 | { |
159 | case ENOTSOCK: | 160 | case ENOTSOCK: |
160 | /* FIXME: Could be we are talking to a pipe, maybe remember this | 161 | /* FIXME: Could be we are talking to a pipe, maybe remember this |
161 | and avoid all setsockopt() in the future? */ | 162 | and avoid all setsockopt() in the future? */ |
162 | break; | 163 | break; |
163 | case EBADF: | 164 | case EBADF: |
164 | /* FIXME: should we die hard here? */ | 165 | /* FIXME: should we die hard here? */ |
165 | break; | 166 | break; |
166 | case EINVAL: | 167 | case EINVAL: |
167 | /* FIXME: optlen invalid, should at least log this, maybe die */ | 168 | /* FIXME: optlen invalid, should at least log this, maybe die */ |
168 | #ifdef HAVE_MESSAGES | 169 | #ifdef HAVE_MESSAGES |
169 | MHD_DLOG (daemon, | 170 | MHD_DLOG (daemon, |
170 | _("optlen invalid: %s\n"), | 171 | _ ("optlen invalid: %s\n"), |
171 | MHD_socket_last_strerr_()); | 172 | MHD_socket_last_strerr_ ()); |
172 | #endif | 173 | #endif |
173 | break; | 174 | break; |
174 | case EFAULT: | 175 | case EFAULT: |
175 | /* wopsie, should at leats log this, FIXME: maybe die */ | 176 | /* wopsie, should at leats log this, FIXME: maybe die */ |
176 | #ifdef HAVE_MESSAGES | 177 | #ifdef HAVE_MESSAGES |
177 | MHD_DLOG (daemon, | 178 | MHD_DLOG (daemon, |
178 | _("The addresss pointed to by optval is not a valid part of the process address space: %s\n"), | 179 | _ ( |
179 | MHD_socket_last_strerr_()); | 180 | "The addresss pointed to by optval is not a valid part of the process address space: %s\n"), |
181 | MHD_socket_last_strerr_ ()); | ||
180 | #endif | 182 | #endif |
181 | break; | 183 | break; |
182 | case ENOPROTOOPT: | 184 | case ENOPROTOOPT: |
183 | /* optlen unknown, should at least log this */ | 185 | /* optlen unknown, should at least log this */ |
184 | #ifdef HAVE_MESSAGES | 186 | #ifdef HAVE_MESSAGES |
185 | MHD_DLOG (daemon, | 187 | MHD_DLOG (daemon, |
186 | _("The option is unknown: %s\n"), | 188 | _ ("The option is unknown: %s\n"), |
187 | MHD_socket_last_strerr_()); | 189 | MHD_socket_last_strerr_ ()); |
188 | #endif | 190 | #endif |
189 | break; | 191 | break; |
190 | default: | 192 | default: |
191 | /* any others? man page does not list more... */ | 193 | /* any others? man page does not list more... */ |
192 | break; | 194 | break; |
193 | } | 195 | } |
194 | #else | 196 | #else |
195 | /* CORK/NOPUSH/MSG_MORE do not exist on this platform, | 197 | /* CORK/NOPUSH/MSG_MORE do not exist on this platform, |
196 | so we must toggle Naggle's algorithm on/off instead | 198 | so we must toggle Naggle's algorithm on/off instead |
197 | (otherwise we keep it always off) */ | 199 | (otherwise we keep it always off) */ |
198 | if (connection->sk_cork_on == want_cork) | 200 | if (connection->sk_cork_on == want_cork) |
199 | { | 201 | { |
200 | /* nothing to do, success! */ | 202 | /* nothing to do, success! */ |
201 | return; | 203 | return; |
202 | } | 204 | } |
203 | if ( (! want_cork) && | 205 | if ( (! want_cork) && |
204 | (0 == MHD_socket_set_nodelay_ (connection->socket_fd, | 206 | (0 == MHD_socket_set_nodelay_ (connection->socket_fd, |
205 | true)) ) | 207 | true)) ) |
206 | connection->sk_cork_on = false; | 208 | connection->sk_cork_on = false; |
207 | #endif | 209 | #endif |
208 | } | 210 | } |
@@ -403,7 +405,7 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
403 | { | 405 | { |
404 | struct msghdr msg; | 406 | struct msghdr msg; |
405 | 407 | ||
406 | memset(&msg, 0, sizeof(struct msghdr)); | 408 | memset (&msg, 0, sizeof(struct msghdr)); |
407 | msg.msg_iov = vector; | 409 | msg.msg_iov = vector; |
408 | msg.msg_iovlen = 2; | 410 | msg.msg_iovlen = 2; |
409 | 411 | ||
@@ -473,9 +475,9 @@ MHD_send_sendfile_ (struct MHD_Connection *connection) | |||
473 | uint64_t left; | 475 | uint64_t left; |
474 | uint64_t offsetu64; | 476 | uint64_t offsetu64; |
475 | #ifndef HAVE_SENDFILE64 | 477 | #ifndef HAVE_SENDFILE64 |
476 | const uint64_t max_off_t = (uint64_t)OFF_T_MAX; | 478 | const uint64_t max_off_t = (uint64_t) OFF_T_MAX; |
477 | #else /* HAVE_SENDFILE64 */ | 479 | #else /* HAVE_SENDFILE64 */ |
478 | const uint64_t max_off_t = (uint64_t)OFF64_T_MAX; | 480 | const uint64_t max_off_t = (uint64_t) OFF64_T_MAX; |
479 | #endif /* HAVE_SENDFILE64 */ | 481 | #endif /* HAVE_SENDFILE64 */ |
480 | #ifdef MHD_LINUX_SOLARIS_SENDFILE | 482 | #ifdef MHD_LINUX_SOLARIS_SENDFILE |
481 | #ifndef HAVE_SENDFILE64 | 483 | #ifndef HAVE_SENDFILE64 |
@@ -491,23 +493,26 @@ MHD_send_sendfile_ (struct MHD_Connection *connection) | |||
491 | #ifdef HAVE_DARWIN_SENDFILE | 493 | #ifdef HAVE_DARWIN_SENDFILE |
492 | off_t len; | 494 | off_t len; |
493 | #endif /* HAVE_DARWIN_SENDFILE */ | 495 | #endif /* HAVE_DARWIN_SENDFILE */ |
494 | const bool used_thr_p_c = (0 != (connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION)); | 496 | const bool used_thr_p_c = (0 != (connection->daemon->options |
495 | const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : MHD_SENFILE_CHUNK_; | 497 | & MHD_USE_THREAD_PER_CONNECTION)); |
498 | const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : | ||
499 | MHD_SENFILE_CHUNK_; | ||
496 | size_t send_size = 0; | 500 | size_t send_size = 0; |
497 | mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender); | 501 | mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender); |
498 | 502 | ||
499 | pre_cork_setsockopt (connection, false); | 503 | pre_cork_setsockopt (connection, false); |
500 | 504 | ||
501 | offsetu64 = connection->response_write_position + connection->response->fd_off; | 505 | offsetu64 = connection->response_write_position |
506 | + connection->response->fd_off; | ||
502 | left = connection->response->total_size - connection->response_write_position; | 507 | left = connection->response->total_size - connection->response_write_position; |
503 | /* Do not allow system to stick sending on single fast connection: | 508 | /* Do not allow system to stick sending on single fast connection: |
504 | * use 128KiB chunks (2MiB for thread-per-connection). */ | 509 | * use 128KiB chunks (2MiB for thread-per-connection). */ |
505 | send_size = (left > chunk_size) ? chunk_size : (size_t) left; | 510 | send_size = (left > chunk_size) ? chunk_size : (size_t) left; |
506 | if (max_off_t < offsetu64) | 511 | if (max_off_t < offsetu64) |
507 | { /* Retry to send with standard 'send()'. */ | 512 | { /* Retry to send with standard 'send()'. */ |
508 | connection->resp_sender = MHD_resp_sender_std; | 513 | connection->resp_sender = MHD_resp_sender_std; |
509 | return MHD_ERR_AGAIN_; | 514 | return MHD_ERR_AGAIN_; |
510 | } | 515 | } |
511 | #ifdef MHD_LINUX_SOLARIS_SENDFILE | 516 | #ifdef MHD_LINUX_SOLARIS_SENDFILE |
512 | #ifndef HAVE_SENDFILE64 | 517 | #ifndef HAVE_SENDFILE64 |
513 | offset = (off_t) offsetu64; | 518 | offset = (off_t) offsetu64; |
@@ -523,53 +528,53 @@ MHD_send_sendfile_ (struct MHD_Connection *connection) | |||
523 | send_size); | 528 | send_size); |
524 | #endif /* HAVE_SENDFILE64 */ | 529 | #endif /* HAVE_SENDFILE64 */ |
525 | if (0 > ret) | 530 | if (0 > ret) |
531 | { | ||
532 | const int err = MHD_socket_get_error_ (); | ||
533 | if (MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
526 | { | 534 | { |
527 | const int err = MHD_socket_get_error_(); | ||
528 | if (MHD_SCKT_ERR_IS_EAGAIN_(err)) | ||
529 | { | ||
530 | #ifdef EPOLL_SUPPORT | 535 | #ifdef EPOLL_SUPPORT |
531 | /* EAGAIN --- no longer write-ready */ | 536 | /* EAGAIN --- no longer write-ready */ |
532 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 537 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; |
533 | #endif /* EPOLL_SUPPORT */ | 538 | #endif /* EPOLL_SUPPORT */ |
534 | return MHD_ERR_AGAIN_; | 539 | return MHD_ERR_AGAIN_; |
535 | } | 540 | } |
536 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) | 541 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) |
537 | return MHD_ERR_AGAIN_; | 542 | return MHD_ERR_AGAIN_; |
538 | #ifdef HAVE_LINUX_SENDFILE | 543 | #ifdef HAVE_LINUX_SENDFILE |
539 | if (MHD_SCKT_ERR_IS_(err, | 544 | if (MHD_SCKT_ERR_IS_ (err, |
540 | MHD_SCKT_EBADF_)) | 545 | MHD_SCKT_EBADF_)) |
541 | return MHD_ERR_BADF_; | 546 | return MHD_ERR_BADF_; |
542 | /* sendfile() failed with EINVAL if mmap()-like operations are not | 547 | /* sendfile() failed with EINVAL if mmap()-like operations are not |
543 | supported for FD or other 'unusual' errors occurred, so we should try | 548 | supported for FD or other 'unusual' errors occurred, so we should try |
544 | to fall back to 'SEND'; see also this thread for info on | 549 | to fall back to 'SEND'; see also this thread for info on |
545 | odd libc/Linux behavior with sendfile: | 550 | odd libc/Linux behavior with sendfile: |
546 | http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */ | 551 | http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */ |
552 | connection->resp_sender = MHD_resp_sender_std; | ||
553 | return MHD_ERR_AGAIN_; | ||
554 | #else /* HAVE_SOLARIS_SENDFILE */ | ||
555 | if ( (EAFNOSUPPORT == err) || | ||
556 | (EINVAL == err) || | ||
557 | (EOPNOTSUPP == err) ) | ||
558 | { /* Retry with standard file reader. */ | ||
547 | connection->resp_sender = MHD_resp_sender_std; | 559 | connection->resp_sender = MHD_resp_sender_std; |
548 | return MHD_ERR_AGAIN_; | 560 | return MHD_ERR_AGAIN_; |
549 | #else /* HAVE_SOLARIS_SENDFILE */ | ||
550 | if ( (EAFNOSUPPORT == err) || | ||
551 | (EINVAL == err) || | ||
552 | (EOPNOTSUPP == err) ) | ||
553 | { /* Retry with standard file reader. */ | ||
554 | connection->resp_sender = MHD_resp_sender_std; | ||
555 | return MHD_ERR_AGAIN_; | ||
556 | } | ||
557 | if ( (ENOTCONN == err) || | ||
558 | (EPIPE == err) ) | ||
559 | { | ||
560 | return MHD_ERR_CONNRESET_; | ||
561 | } | ||
562 | return MHD_ERR_BADF_; /* Fail hard */ | ||
563 | #endif /* HAVE_SOLARIS_SENDFILE */ | ||
564 | } | 561 | } |
562 | if ( (ENOTCONN == err) || | ||
563 | (EPIPE == err) ) | ||
564 | { | ||
565 | return MHD_ERR_CONNRESET_; | ||
566 | } | ||
567 | return MHD_ERR_BADF_; /* Fail hard */ | ||
568 | #endif /* HAVE_SOLARIS_SENDFILE */ | ||
569 | } | ||
565 | #ifdef EPOLL_SUPPORT | 570 | #ifdef EPOLL_SUPPORT |
566 | else if (send_size > (size_t)ret) | 571 | else if (send_size > (size_t) ret) |
567 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 572 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; |
568 | #endif /* EPOLL_SUPPORT */ | 573 | #endif /* EPOLL_SUPPORT */ |
569 | #elif defined(HAVE_FREEBSD_SENDFILE) | 574 | #elif defined(HAVE_FREEBSD_SENDFILE) |
570 | #ifdef SF_FLAGS | 575 | #ifdef SF_FLAGS |
571 | flags = used_thr_p_c ? | 576 | flags = used_thr_p_c ? |
572 | freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_; | 577 | freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_; |
573 | #endif /* SF_FLAGS */ | 578 | #endif /* SF_FLAGS */ |
574 | if (0 != sendfile (file_fd, | 579 | if (0 != sendfile (file_fd, |
575 | connection->socket_fd, | 580 | connection->socket_fd, |
@@ -578,63 +583,63 @@ MHD_send_sendfile_ (struct MHD_Connection *connection) | |||
578 | NULL, | 583 | NULL, |
579 | &sent_bytes, | 584 | &sent_bytes, |
580 | flags)) | 585 | flags)) |
586 | { | ||
587 | const int err = MHD_socket_get_error_ (); | ||
588 | if (MHD_SCKT_ERR_IS_EAGAIN_ (err) || | ||
589 | MHD_SCKT_ERR_IS_EINTR_ (err) || | ||
590 | (EBUSY == err) ) | ||
581 | { | 591 | { |
582 | const int err = MHD_socket_get_error_(); | 592 | mhd_assert (SSIZE_MAX >= sent_bytes); |
583 | if (MHD_SCKT_ERR_IS_EAGAIN_(err) || | 593 | if (0 != sent_bytes) |
584 | MHD_SCKT_ERR_IS_EINTR_(err) || | 594 | return (ssize_t) sent_bytes; |
585 | EBUSY == err) | 595 | |
586 | { | ||
587 | mhd_assert (SSIZE_MAX >= sent_bytes); | ||
588 | if (0 != sent_bytes) | ||
589 | return (ssize_t)sent_bytes; | ||
590 | |||
591 | return MHD_ERR_AGAIN_; | ||
592 | } | ||
593 | /* Some unrecoverable error. Possibly file FD is not suitable | ||
594 | * for sendfile(). Retry with standard send(). */ | ||
595 | connection->resp_sender = MHD_resp_sender_std; | ||
596 | return MHD_ERR_AGAIN_; | 596 | return MHD_ERR_AGAIN_; |
597 | } | 597 | } |
598 | /* Some unrecoverable error. Possibly file FD is not suitable | ||
599 | * for sendfile(). Retry with standard send(). */ | ||
600 | connection->resp_sender = MHD_resp_sender_std; | ||
601 | return MHD_ERR_AGAIN_; | ||
602 | } | ||
598 | mhd_assert (0 < sent_bytes); | 603 | mhd_assert (0 < sent_bytes); |
599 | mhd_assert (SSIZE_MAX >= sent_bytes); | 604 | mhd_assert (SSIZE_MAX >= sent_bytes); |
600 | ret = (ssize_t)sent_bytes; | 605 | ret = (ssize_t) sent_bytes; |
601 | #elif defined(HAVE_DARWIN_SENDFILE) | 606 | #elif defined(HAVE_DARWIN_SENDFILE) |
602 | len = (off_t)send_size; /* chunk always fit */ | 607 | len = (off_t) send_size; /* chunk always fit */ |
603 | if (0 != sendfile (file_fd, | 608 | if (0 != sendfile (file_fd, |
604 | connection->socket_fd, | 609 | connection->socket_fd, |
605 | (off_t) offsetu64, | 610 | (off_t) offsetu64, |
606 | &len, | 611 | &len, |
607 | NULL, | 612 | NULL, |
608 | 0)) | 613 | 0)) |
614 | { | ||
615 | const int err = MHD_socket_get_error_ (); | ||
616 | if (MHD_SCKT_ERR_IS_EAGAIN_ (err) || | ||
617 | MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
609 | { | 618 | { |
610 | const int err = MHD_socket_get_error_(); | 619 | mhd_assert (0 <= len); |
611 | if (MHD_SCKT_ERR_IS_EAGAIN_(err) || | 620 | mhd_assert (SSIZE_MAX >= len); |
612 | MHD_SCKT_ERR_IS_EINTR_(err)) | 621 | mhd_assert (send_size >= (size_t) len); |
613 | { | 622 | if (0 != len) |
614 | mhd_assert (0 <= len); | 623 | return (ssize_t) len; |
615 | mhd_assert (SSIZE_MAX >= len); | 624 | |
616 | mhd_assert (send_size >= (size_t)len); | 625 | return MHD_ERR_AGAIN_; |
617 | if (0 != len) | 626 | } |
618 | return (ssize_t)len; | 627 | if ((ENOTCONN == err) || |
619 | 628 | (EPIPE == err) ) | |
620 | return MHD_ERR_AGAIN_; | 629 | return MHD_ERR_CONNRESET_; |
621 | } | 630 | if ((ENOTSUP == err) || |
622 | if (ENOTCONN == err || | 631 | (EOPNOTSUPP == err) ) |
623 | EPIPE == err) | 632 | { /* This file FD is not suitable for sendfile(). |
624 | return MHD_ERR_CONNRESET_; | ||
625 | if (ENOTSUP == err || | ||
626 | EOPNOTSUPP == err) | ||
627 | { /* This file FD is not suitable for sendfile(). | ||
628 | * Retry with standard send(). */ | 633 | * Retry with standard send(). */ |
629 | connection->resp_sender = MHD_resp_sender_std; | 634 | connection->resp_sender = MHD_resp_sender_std; |
630 | return MHD_ERR_AGAIN_; | 635 | return MHD_ERR_AGAIN_; |
631 | } | ||
632 | return MHD_ERR_BADF_; /* Return hard error. */ | ||
633 | } | 636 | } |
637 | return MHD_ERR_BADF_; /* Return hard error. */ | ||
638 | } | ||
634 | mhd_assert (0 <= len); | 639 | mhd_assert (0 <= len); |
635 | mhd_assert (SSIZE_MAX >= len); | 640 | mhd_assert (SSIZE_MAX >= len); |
636 | mhd_assert (send_size >= (size_t)len); | 641 | mhd_assert (send_size >= (size_t) len); |
637 | ret = (ssize_t)len; | 642 | ret = (ssize_t) len; |
638 | #endif /* HAVE_FREEBSD_SENDFILE */ | 643 | #endif /* HAVE_FREEBSD_SENDFILE */ |
639 | 644 | ||
640 | /* Make sure we send the data without delay ONLY if we | 645 | /* Make sure we send the data without delay ONLY if we |