diff options
Diffstat (limited to 'src/microhttpd/mhd_send.c')
-rw-r--r-- | src/microhttpd/mhd_send.c | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c index 315ee563..d713f1a8 100644 --- a/src/microhttpd/mhd_send.c +++ b/src/microhttpd/mhd_send.c | |||
@@ -85,7 +85,7 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
85 | /* The socket. */ | 85 | /* The socket. */ |
86 | MHD_socket s = connection->socket_fd; | 86 | MHD_socket s = connection->socket_fd; |
87 | int eno; | 87 | int eno; |
88 | int ret; | 88 | ssize_t ret; |
89 | int optval; | 89 | int optval; |
90 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | 90 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
91 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | 91 | const MHD_SCKT_OPT_BOOL_ on_val = 1; |
@@ -205,11 +205,36 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
205 | #ifdef HTTPS_SUPPORT | 205 | #ifdef HTTPS_SUPPORT |
206 | if (using_tls) | 206 | if (using_tls) |
207 | { | 207 | { |
208 | send_tls_adapter(connection, buffer, buffer_size); | 208 | if (i > SSIZE_MAX) |
209 | i = SSIZE_MAX; | ||
210 | ret = gnutls_record_send (connection->tls_session, | ||
211 | buffer, | ||
212 | buffer_size); | ||
213 | if ( (GNUTLS_E_AGAIN == ret) || | ||
214 | (GNUTLS_E_INTERRUPTED == ret) ) | ||
215 | { | ||
216 | #ifdef EPOLL_SUPPORT | ||
217 | if (GNUTLS_E_AGAIN == ret) | ||
218 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
219 | #endif | ||
220 | return MHD_ERR_AGAIN_; | ||
221 | } | ||
222 | if (ret < 0) | ||
223 | { | ||
224 | /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication | ||
225 | disrupted); interpret as a hard error */ | ||
226 | return MHD_ERR_NOTCONN_; | ||
227 | } | ||
228 | #ifdef EPOLL_SUPPORT | ||
229 | /* Unlike non-TLS connections, do not reset "write-ready" if | ||
230 | * sent amount smaller than provided amount, as TLS | ||
231 | * connections may break data into smaller parts for sending. */ | ||
232 | #endif /* EPOLL_SUPPORT */ | ||
209 | } | 233 | } |
210 | else | 234 | else |
211 | #endif | 235 | #endif |
212 | { | 236 | { |
237 | /* plaintext transmission */ | ||
213 | #if MSG_MORE | 238 | #if MSG_MORE |
214 | ret = send (connection->socket_fd, | 239 | ret = send (connection->socket_fd, |
215 | buffer, | 240 | buffer, |
@@ -218,6 +243,28 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
218 | #else | 243 | #else |
219 | ret = send (connection->socket_fd, buffer, buffer_size, 0); | 244 | ret = send (connection->socket_fd, buffer, buffer_size, 0); |
220 | #endif | 245 | #endif |
246 | |||
247 | if (0 > ret) | ||
248 | { | ||
249 | if (MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
250 | { | ||
251 | #if EPOLL_SUPPORT | ||
252 | /* EAGAIN, no longer write-ready */ | ||
253 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
254 | #endif /* EPOLL_SUPPORT */ | ||
255 | return MHD_ERR_AGAIN_; | ||
256 | } | ||
257 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
258 | return MHD_ERR_AGAIN_; | ||
259 | if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_)) | ||
260 | return MHD_ERR_CONNRESET_; | ||
261 | /* Treat any other error as hard error. */ | ||
262 | return MHD_ERR_NOTCONN_; | ||
263 | } | ||
264 | #if EPOLL_SUPPORT | ||
265 | else if (buffer_size > (size_t) ret) | ||
266 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
267 | #endif /* EPOLL_SUPPORT */ | ||
221 | } | 268 | } |
222 | #if TCP_CORK | 269 | #if TCP_CORK |
223 | if (use_corknopush) | 270 | if (use_corknopush) |
@@ -273,31 +320,6 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
273 | gnutls_record_uncork(connection->tls_session); | 320 | gnutls_record_uncork(connection->tls_session); |
274 | */ | 321 | */ |
275 | 322 | ||
276 | // shouldn't we return 0 or -1? Why re-use the _ERR_ functions? | ||
277 | // error handling from send_param_adapter(): | ||
278 | if (0 > ret) | ||
279 | { | ||
280 | if (MHD_SCKT_ERR_IS_EAGAIN_ (err)) | ||
281 | { | ||
282 | #if EPOLL_SUPPORT | ||
283 | /* EAGAIN, no longer write-ready */ | ||
284 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
285 | #endif /* EPOLL_SUPPORT */ | ||
286 | return MHD_ERR_AGAIN_; | ||
287 | } | ||
288 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
289 | return MHD_ERR_AGAIN_; | ||
290 | if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_)) | ||
291 | return MHD_ERR_CONNRESET_; | ||
292 | /* Treat any other error as hard error. */ | ||
293 | return MHD_ERR_NOTCONN_; | ||
294 | } | ||
295 | #if EPOLL_SUPPORT | ||
296 | else if (buffer_size > (size_t) ret) | ||
297 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
298 | #endif /* EPOLL_SUPPORT */ | ||
299 | // return ret; // should be return at the end of the function? | ||
300 | // previous error save: | ||
301 | errno = eno; | 323 | errno = eno; |
302 | return ret; | 324 | return ret; |
303 | } | 325 | } |