Mercurial > hg > nginx
comparison src/event/ngx_event_openssl.c @ 7584:9d2ad2fb4423
SSL: available bytes handling (ticket #1431).
Added code to track number of bytes available in the socket.
This makes it possible to avoid looping for a long time while
working with fast enough peer when data are added to the socket buffer
faster than we are able to read and process data.
When kernel does not provide number of bytes available, it is
retrieved using ioctl(FIONREAD) as long as a buffer is filled by
SSL_read().
It is assumed that number of bytes returned by SSL_read() is close
to the number of bytes read from the socket, as we do not use
SSL compression. But even if it is not true for some reason, this
is not important, as we post an additional reading event anyway.
Note that data can be buffered at SSL layer, and it is not possible
to simply stop reading at some point and wait till the event will
be reported by the kernel again. This can be only done when there
are no data in SSL buffers, and there is no good way to find out if
it's the case.
Instead of trying to figure out if SSL buffers are empty, this patch
introduces events posted for the next event loop iteration - such
events will be processed only on the next event loop iteration,
after going into the kernel and retrieving additional events. This
seems to be simple and reliable approach.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 17 Oct 2019 16:02:24 +0300 |
parents | 70749256af79 |
children | 1ce3f01a4355 |
comparison
equal
deleted
inserted
replaced
7583:efd71d49bde0 | 7584:9d2ad2fb4423 |
---|---|
41 static ssize_t ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, | 41 static ssize_t ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, |
42 size_t size); | 42 size_t size); |
43 #endif | 43 #endif |
44 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); | 44 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); |
45 static void ngx_ssl_write_handler(ngx_event_t *wev); | 45 static void ngx_ssl_write_handler(ngx_event_t *wev); |
46 static void ngx_ssl_next_read_handler(ngx_event_t *rev); | |
46 #ifdef SSL_READ_EARLY_DATA_SUCCESS | 47 #ifdef SSL_READ_EARLY_DATA_SUCCESS |
47 static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data, | 48 static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data, |
48 size_t size); | 49 size_t size); |
49 #endif | 50 #endif |
50 static void ngx_ssl_read_handler(ngx_event_t *rev); | 51 static void ngx_ssl_read_handler(ngx_event_t *rev); |
2001 | 2002 |
2002 size -= n; | 2003 size -= n; |
2003 | 2004 |
2004 if (size == 0) { | 2005 if (size == 0) { |
2005 c->read->ready = 1; | 2006 c->read->ready = 1; |
2007 | |
2008 if (c->read->available >= 0) { | |
2009 c->read->available -= bytes; | |
2010 | |
2011 /* | |
2012 * there can be data buffered at SSL layer, | |
2013 * so we post an event to continue reading on the next | |
2014 * iteration of the event loop | |
2015 */ | |
2016 | |
2017 if (c->read->available < 0) { | |
2018 c->read->available = 0; | |
2019 c->read->ready = 0; | |
2020 | |
2021 if (c->ssl->next_read_handler == NULL) { | |
2022 c->ssl->next_read_handler = c->read->handler; | |
2023 c->read->handler = ngx_ssl_next_read_handler; | |
2024 } | |
2025 | |
2026 ngx_post_event(c->read, &ngx_posted_next_events); | |
2027 } | |
2028 | |
2029 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2030 "SSL_read: avail:%d", c->read->available); | |
2031 | |
2032 } else { | |
2033 | |
2034 #if (NGX_HAVE_FIONREAD) | |
2035 | |
2036 if (ngx_socket_nread(c->fd, &c->read->available) == -1) { | |
2037 c->read->error = 1; | |
2038 ngx_connection_error(c, ngx_socket_errno, | |
2039 ngx_socket_nread_n " failed"); | |
2040 return NGX_ERROR; | |
2041 } | |
2042 | |
2043 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2044 "SSL_read: avail:%d", c->read->available); | |
2045 | |
2046 #endif | |
2047 } | |
2048 | |
2006 return bytes; | 2049 return bytes; |
2007 } | 2050 } |
2008 | 2051 |
2009 buf += n; | 2052 buf += n; |
2010 | 2053 |
2280 c = wev->data; | 2323 c = wev->data; |
2281 | 2324 |
2282 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL write handler"); | 2325 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL write handler"); |
2283 | 2326 |
2284 c->read->handler(c->read); | 2327 c->read->handler(c->read); |
2328 } | |
2329 | |
2330 | |
2331 static void | |
2332 ngx_ssl_next_read_handler(ngx_event_t *rev) | |
2333 { | |
2334 ngx_connection_t *c; | |
2335 | |
2336 c = rev->data; | |
2337 | |
2338 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL next read handler"); | |
2339 | |
2340 rev->handler = c->ssl->next_read_handler; | |
2341 c->ssl->next_read_handler = NULL; | |
2342 | |
2343 if (!rev->ready) { | |
2344 rev->ready = 1; | |
2345 rev->available = -1; | |
2346 } | |
2347 | |
2348 if (rev->posted) { | |
2349 ngx_delete_posted_event(rev); | |
2350 } | |
2351 | |
2352 rev->handler(rev); | |
2285 } | 2353 } |
2286 | 2354 |
2287 | 2355 |
2288 /* | 2356 /* |
2289 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer | 2357 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer |