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