diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2017-06-05 00:31:03 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2017-06-05 00:32:27 +0300 |
commit | ddac6d53713141068625b074da18dc306e0bd6fa (patch) | |
tree | 14ccf417ad7b3ddf5f07159c2ad882ad4afc2330 /src/microhttpd/connection.c | |
parent | 3777686c912cc6102694e55862302aec9a16812b (diff) | |
download | libmicrohttpd-ddac6d53713141068625b074da18dc306e0bd6fa.tar.gz libmicrohttpd-ddac6d53713141068625b074da18dc306e0bd6fa.zip |
Do not use errno to return errors from send_param_adapter()/send_tls_adapter()
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r-- | src/microhttpd/connection.c | 147 |
1 files changed, 68 insertions, 79 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 45cc6566..27a4efb3 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -169,7 +169,8 @@ recv_param_adapter (struct MHD_Connection *connection, | |||
169 | * @param connection the MHD connection structure | 169 | * @param connection the MHD connection structure |
170 | * @param other data to write | 170 | * @param other data to write |
171 | * @param i number of bytes to write | 171 | * @param i number of bytes to write |
172 | * @return actual number of bytes written | 172 | * @return positive value for number of bytes actually sent or |
173 | * negative value for error number MHD_ERR_xxx_ | ||
173 | */ | 174 | */ |
174 | static ssize_t | 175 | static ssize_t |
175 | send_param_adapter (struct MHD_Connection *connection, | 176 | send_param_adapter (struct MHD_Connection *connection, |
@@ -177,13 +178,11 @@ send_param_adapter (struct MHD_Connection *connection, | |||
177 | size_t i) | 178 | size_t i) |
178 | { | 179 | { |
179 | ssize_t ret; | 180 | ssize_t ret; |
180 | int err; | ||
181 | 181 | ||
182 | if ( (MHD_INVALID_SOCKET == connection->socket_fd) || | 182 | if ( (MHD_INVALID_SOCKET == connection->socket_fd) || |
183 | (MHD_CONNECTION_CLOSED == connection->state) ) | 183 | (MHD_CONNECTION_CLOSED == connection->state) ) |
184 | { | 184 | { |
185 | MHD_socket_set_error_ (MHD_SCKT_ENOTCONN_); | 185 | return MHD_ERR_NOTCONN_; |
186 | return -1; | ||
187 | } | 186 | } |
188 | if (i > MHD_SCKT_SEND_MAX_SIZE_) | 187 | if (i > MHD_SCKT_SEND_MAX_SIZE_) |
189 | i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */ | 188 | i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */ |
@@ -191,23 +190,27 @@ send_param_adapter (struct MHD_Connection *connection, | |||
191 | ret = MHD_send_ (connection->socket_fd, | 190 | ret = MHD_send_ (connection->socket_fd, |
192 | other, | 191 | other, |
193 | i); | 192 | i); |
194 | err = MHD_socket_get_error_(); | ||
195 | #ifdef EPOLL_SUPPORT | ||
196 | if (0 > ret) | 193 | if (0 > ret) |
197 | { | 194 | { |
198 | /* EAGAIN --- no longer write-ready */ | 195 | const int err = MHD_socket_get_error_(); |
196 | |||
199 | if (MHD_SCKT_ERR_IS_EAGAIN_(err)) | 197 | if (MHD_SCKT_ERR_IS_EAGAIN_(err)) |
200 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 198 | { |
199 | #ifdef EPOLL_SUPPORT | ||
200 | /* EAGAIN --- no longer write-ready */ | ||
201 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
202 | #endif /* EPOLL_SUPPORT */ | ||
203 | return MHD_ERR_AGAIN_; | ||
204 | } | ||
205 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
206 | return MHD_ERR_AGAIN_; | ||
207 | /* Treat any other error as hard error. */ | ||
208 | return MHD_ERR_CONNRESET_; | ||
201 | } | 209 | } |
210 | #ifdef EPOLL_SUPPORT | ||
202 | else if (i > (size_t)ret) | 211 | else if (i > (size_t)ret) |
203 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 212 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; |
204 | #endif | 213 | #endif /* EPOLL_SUPPORT */ |
205 | /* Handle broken kernel / libc, returning -1 but not setting errno; | ||
206 | kill connection as that should be safe; reported on mailinglist here: | ||
207 | http://lists.gnu.org/archive/html/libmicrohttpd/2014-10/msg00023.html */ | ||
208 | if ( (0 > ret) && | ||
209 | (0 == err) ) | ||
210 | MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_); | ||
211 | return ret; | 214 | return ret; |
212 | } | 215 | } |
213 | 216 | ||
@@ -223,7 +226,6 @@ static ssize_t | |||
223 | sendfile_adapter (struct MHD_Connection *connection) | 226 | sendfile_adapter (struct MHD_Connection *connection) |
224 | { | 227 | { |
225 | int ret; | 228 | int ret; |
226 | int err; | ||
227 | const int file_fd = connection->response->fd; | 229 | const int file_fd = connection->response->fd; |
228 | uint64_t left; | 230 | uint64_t left; |
229 | uint64_t offsetu64; | 231 | uint64_t offsetu64; |
@@ -236,61 +238,60 @@ sendfile_adapter (struct MHD_Connection *connection) | |||
236 | 238 | ||
237 | offsetu64 = connection->response_write_position + connection->response->fd_off; | 239 | offsetu64 = connection->response_write_position + connection->response->fd_off; |
238 | left = connection->response->total_size - connection->response_write_position; | 240 | left = connection->response->total_size - connection->response_write_position; |
239 | ret = 0; | 241 | if (left > SSIZE_MAX) |
242 | left = SSIZE_MAX; | ||
240 | #ifndef HAVE_SENDFILE64 | 243 | #ifndef HAVE_SENDFILE64 |
241 | if ((uint64_t)OFF_T_MAX < offsetu64) | 244 | if ((uint64_t)OFF_T_MAX < offsetu64) |
242 | MHD_socket_set_error_to_ENOMEM (); | 245 | { /* Retry to send with standard 'send()'. */ |
243 | else | 246 | connection->resp_sender = MHD_resp_sender_std; |
244 | { | 247 | return MHD_ERR_AGAIN_; |
245 | offset = (off_t) offsetu64; | 248 | } |
246 | ret = sendfile (connection->socket_fd, | 249 | offset = (off_t) offsetu64; |
247 | file_fd, | 250 | ret = sendfile (connection->socket_fd, |
248 | &offset, | 251 | file_fd, |
249 | left); | 252 | &offset, |
250 | } | 253 | left); |
251 | #else /* HAVE_SENDFILE64 */ | 254 | #else /* HAVE_SENDFILE64 */ |
252 | if ((uint64_t)OFF64_T_MAX < offsetu64) | 255 | if ((uint64_t)OFF64_T_MAX < offsetu64) |
253 | MHD_socket_set_error_to_ENOMEM (); | 256 | { /* Retry to send with standard 'send()'. */ |
254 | else | 257 | connection->resp_sender = MHD_resp_sender_std; |
255 | { | 258 | return MHD_ERR_AGAIN_; |
256 | offset = (off64_t) offsetu64; | ||
257 | ret = sendfile64 (connection->socket_fd, | ||
258 | file_fd, | ||
259 | &offset, | ||
260 | left); | ||
261 | } | 259 | } |
260 | offset = (off64_t) offsetu64; | ||
261 | ret = sendfile64 (connection->socket_fd, | ||
262 | file_fd, | ||
263 | &offset, | ||
264 | left); | ||
262 | #endif /* HAVE_SENDFILE64 */ | 265 | #endif /* HAVE_SENDFILE64 */ |
263 | if (0 < ret) | 266 | if (0 > ret) |
264 | { | 267 | { |
265 | /* write successful */ | 268 | const int err = MHD_socket_get_error_(); |
269 | if (MHD_SCKT_ERR_IS_EAGAIN_(err)) | ||
270 | { | ||
266 | #ifdef EPOLL_SUPPORT | 271 | #ifdef EPOLL_SUPPORT |
267 | if (left > (uint64_t)ret) | 272 | /* EAGAIN --- no longer write-ready */ |
268 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 273 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; |
269 | #endif /* EPOLL_SUPPORT */ | 274 | #endif /* EPOLL_SUPPORT */ |
270 | return ret; | 275 | return MHD_ERR_AGAIN_; |
276 | } | ||
277 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
278 | return MHD_ERR_AGAIN_; | ||
279 | if (MHD_SCKT_ERR_IS_(err, | ||
280 | MHD_SCKT_EBADF_)) | ||
281 | return MHD_ERR_BADF_; | ||
282 | /* sendfile() failed with EINVAL if mmap()-like operations are not | ||
283 | supported for FD or other 'unusual' errors occurred, so we should try | ||
284 | to fall back to 'SEND'; see also this thread for info on | ||
285 | odd libc/Linux behavior with sendfile: | ||
286 | http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */ | ||
287 | connection->resp_sender = MHD_resp_sender_std; | ||
288 | return MHD_ERR_AGAIN_; | ||
271 | } | 289 | } |
272 | err = MHD_socket_get_error_(); | ||
273 | #ifdef EPOLL_SUPPORT | 290 | #ifdef EPOLL_SUPPORT |
274 | if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_(err)) ) | 291 | else if (left > (uint64_t)ret) |
275 | { | 292 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; |
276 | /* EAGAIN --- no longer write-ready */ | 293 | #endif /* EPOLL_SUPPORT */ |
277 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 294 | return ret; |
278 | } | ||
279 | #endif | ||
280 | if (MHD_SCKT_ERR_IS_EINTR_ (err) || | ||
281 | MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
282 | return 0; | ||
283 | if (MHD_SCKT_ERR_IS_(err, | ||
284 | MHD_SCKT_EBADF_)) | ||
285 | return -1; | ||
286 | /* sendfile() failed with EINVAL if mmap()-like operations are not | ||
287 | supported for FD or other 'unusual' errors occurred, so we should try | ||
288 | to fall back to 'SEND'; see also this thread for info on | ||
289 | odd libc/Linux behavior with sendfile: | ||
290 | http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */ | ||
291 | connection->resp_sender = MHD_resp_sender_std; | ||
292 | MHD_socket_set_error_ (MHD_SCKT_EAGAIN_); | ||
293 | return 0; | ||
294 | } | 295 | } |
295 | #endif /* __linux__ */ | 296 | #endif /* __linux__ */ |
296 | 297 | ||
@@ -2786,16 +2787,12 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
2786 | connection->continue_message_write_offset); | 2787 | connection->continue_message_write_offset); |
2787 | if (ret < 0) | 2788 | if (ret < 0) |
2788 | { | 2789 | { |
2789 | const int err = MHD_socket_get_error_ (); | 2790 | if (MHD_ERR_AGAIN_ == ret) |
2790 | |||
2791 | if (MHD_SCKT_ERR_IS_EINTR_ (err) || | ||
2792 | MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
2793 | break; | 2791 | break; |
2794 | #ifdef HAVE_MESSAGES | 2792 | #ifdef HAVE_MESSAGES |
2795 | MHD_DLOG (connection->daemon, | 2793 | MHD_DLOG (connection->daemon, |
2796 | _("Failed to send data in request for %s: %s\n"), | 2794 | _("Failed to send data in request for %s.\n"), |
2797 | connection->url, | 2795 | connection->url); |
2798 | MHD_socket_strerr_ (err)); | ||
2799 | #endif | 2796 | #endif |
2800 | CONNECTION_CLOSE_ERROR (connection, | 2797 | CONNECTION_CLOSE_ERROR (connection, |
2801 | NULL); | 2798 | NULL); |
@@ -2824,9 +2821,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
2824 | connection->write_buffer_send_offset); | 2821 | connection->write_buffer_send_offset); |
2825 | if (ret < 0) | 2822 | if (ret < 0) |
2826 | { | 2823 | { |
2827 | const int err = MHD_socket_get_error_ (); | 2824 | if (MHD_ERR_AGAIN_ == ret) |
2828 | if (MHD_SCKT_ERR_IS_EINTR_ (err) || | ||
2829 | MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
2830 | break; | 2825 | break; |
2831 | CONNECTION_CLOSE_ERROR (connection, | 2826 | CONNECTION_CLOSE_ERROR (connection, |
2832 | _("Connection was closed while sending response headers.\n")); | 2827 | _("Connection was closed while sending response headers.\n")); |
@@ -2889,9 +2884,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
2889 | MHD_mutex_unlock_chk_ (&response->mutex); | 2884 | MHD_mutex_unlock_chk_ (&response->mutex); |
2890 | if (ret < 0) | 2885 | if (ret < 0) |
2891 | { | 2886 | { |
2892 | err = MHD_socket_get_error_ (); | 2887 | if (MHD_ERR_AGAIN_ == ret) |
2893 | if (MHD_SCKT_ERR_IS_EINTR_ (err) || | ||
2894 | MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
2895 | return MHD_YES; | 2888 | return MHD_YES; |
2896 | #ifdef HAVE_MESSAGES | 2889 | #ifdef HAVE_MESSAGES |
2897 | MHD_DLOG (connection->daemon, | 2890 | MHD_DLOG (connection->daemon, |
@@ -2921,9 +2914,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
2921 | connection->write_buffer_send_offset); | 2914 | connection->write_buffer_send_offset); |
2922 | if (ret < 0) | 2915 | if (ret < 0) |
2923 | { | 2916 | { |
2924 | const int err = MHD_socket_get_error_ (); | 2917 | if (MHD_ERR_AGAIN_ == ret) |
2925 | if (MHD_SCKT_ERR_IS_EINTR_ (err) || | ||
2926 | MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
2927 | break; | 2918 | break; |
2928 | CONNECTION_CLOSE_ERROR (connection, | 2919 | CONNECTION_CLOSE_ERROR (connection, |
2929 | _("Connection was closed while sending response body.\n")); | 2920 | _("Connection was closed while sending response body.\n")); |
@@ -2951,9 +2942,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
2951 | connection->write_buffer_send_offset); | 2942 | connection->write_buffer_send_offset); |
2952 | if (ret < 0) | 2943 | if (ret < 0) |
2953 | { | 2944 | { |
2954 | const int err = MHD_socket_get_error_ (); | 2945 | if (MHD_ERR_AGAIN_ == ret) |
2955 | if (MHD_SCKT_ERR_IS_EINTR_ (err) || | ||
2956 | MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
2957 | break; | 2946 | break; |
2958 | CONNECTION_CLOSE_ERROR (connection, | 2947 | CONNECTION_CLOSE_ERROR (connection, |
2959 | _("Connection was closed while sending response body.\n")); | 2948 | _("Connection was closed while sending response body.\n")); |