[PATCH] OpenSSL-1.1.0锛歋upport Asynchronous Operations of SSL with openSSL-1.1.0

Junli Liu jlliudh at isoftstone.com
Tue Sep 7 08:48:08 UTC 2021


# HG changeset patch
# User Junli Liu<jlliudh at isoftstone.com>
# Date 1631003347 -28800
#      Tue Sep 07 16:29:07 2021 +0800
# Node ID 301a837387ed63bb2e455942ef2ef79bc9aaa972
# Parent  2245324a507abc54cf0274fd1b1e81bfac7c1c73
OpenSSL-1.1.0:Support Asynchronous Operations of SSL with openSSL-1.1.0

Security is critical to the foundation of networking and Transport Layer Security (TLS) is the backbone protocol for Internet security today. But normally, the introduction of TLS usually leads to network performance degradation, because encryption and decryption need to consume more compute resources.OpenSSL-1.1.0 has involved features of asynchronous operations to improve the performance of network and often combined with hardware feature.

This changeset make Nginx can work well with  OpenSSL asynchronous operations when process http request.

diff -r 2245324a507a -r 301a837387ed auto/lib/openssl/conf
--- a/auto/lib/openssl/conf	Thu Sep 02 12:25:37 2021 +0300
+++ b/auto/lib/openssl/conf	Tue Sep 07 16:29:07 2021 +0800
@@ -139,4 +139,33 @@
         exit 1
     fi
 
+    OPENSSL_ASYNC=
+    if [ "$NGX_SSL_ASYNC" != NO ]; then
+
+        OPENSSL_ASYNC=NO
+
+        ngx_feature="OpenSSL library"
+        ngx_feature_name=
+        ngx_feature_run=no
+        ngx_feature_incs="#include <openssl/ssl.h>"
+        ngx_feature_path=
+        ngx_feature_libs="-lssl -lcrypto"
+        ngx_feature_test="#ifndef SSL_MODE_ASYNC
+        error: not define async
+        #endif
+        "
+        . auto/feature
+        if [ $ngx_found = yes ]; then
+            have=NGX_SSL_ASYNC . auto/have
+            OPENSSL_ASYNC=YES
+        fi
+    fi
+
+    if [ -n "$OPENSSL_ASYNC"  -a  "$OPENSSL_ASYNC" != YES  ]; then
+cat << END
+$1: error: For using asynchronous mode, The OpenSSL must be version 1.1.0 or greater.
+
+END
+        exit 1
+    fi
 fi
diff -r 2245324a507a -r 301a837387ed src/core/nginx.c
--- a/src/core/nginx.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/core/nginx.c	Tue Sep 07 16:29:07 2021 +0800
@@ -182,6 +182,12 @@
 static ngx_uint_t   ngx_show_help;
 static ngx_uint_t   ngx_show_version;
 static ngx_uint_t   ngx_show_configure;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+/* indicate that nginx start without ngx_ssl_init()
+ * which will involve OpenSSL configuration file to
+ * start OpenSSL engine */
+static ngx_uint_t   ngx_no_ssl_init;
+#endif
 static u_char      *ngx_prefix;
 static u_char      *ngx_error_log;
 static u_char      *ngx_conf_file;
@@ -238,7 +244,13 @@
 
     /* STUB */
 #if (NGX_OPENSSL)
-    ngx_ssl_init(log);
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (!ngx_no_ssl_init) {
+#endif
+        ngx_ssl_init(log);
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    }
+#endif
 #endif
 
     /*
@@ -248,6 +260,9 @@
 
     ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
     init_cycle.log = log;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    init_cycle.no_ssl_init = ngx_no_ssl_init;
+#endif
     ngx_cycle = &init_cycle;
 
     init_cycle.pool = ngx_create_pool(1024, log);
@@ -782,11 +797,17 @@
 
             case 't':
                 ngx_test_config = 1;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+                ngx_no_ssl_init = 1;
+#endif
                 break;
 
             case 'T':
                 ngx_test_config = 1;
                 ngx_dump_config = 1;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+                ngx_no_ssl_init = 1;
+#endif
                 break;
 
             case 'q':
@@ -854,6 +875,9 @@
                 return NGX_ERROR;
 
             case 's':
+#if (NGX_SSL && NGX_SSL_ASYNC)
+                ngx_no_ssl_init = 1;
+#endif
                 if (*p) {
                     ngx_signal = (char *) p;
 
@@ -879,6 +903,9 @@
 
             default:
                 ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
+#if (NGX_SSL && NGX_SSL_ASYNC)
+                ngx_no_ssl_init = 1;
+#endif
                 return NGX_ERROR;
             }
         }
diff -r 2245324a507a -r 301a837387ed src/core/ngx_conf_file.h
--- a/src/core/ngx_conf_file.h	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/core/ngx_conf_file.h	Tue Sep 07 16:29:07 2021 +0800
@@ -129,6 +129,7 @@
 
     ngx_conf_handler_pt   handler;
     void                 *handler_conf;
+    ngx_flag_t            no_ssl_init;
 };
 
 
diff -r 2245324a507a -r 301a837387ed src/core/ngx_connection.c
--- a/src/core/ngx_connection.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/core/ngx_connection.c	Tue Sep 07 16:29:07 2021 +0800
@@ -8,6 +8,7 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 #include <ngx_event.h>
+#include <nginx.h>
 
 
 ngx_os_io_t  ngx_io;
@@ -1048,7 +1049,14 @@
                      * for closed shared listening sockets unless
                      * the events was explicitly deleted
                      */
-
+#if (NGX_SSL && NGX_SSL_ASYNC)
+                    if (c->async_enable && ngx_del_async_conn) {
+                        if (c->num_async_fds) {
+                            ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                            c->num_async_fds--;
+                        }
+                    }
+#endif
                     ngx_del_event(c->read, NGX_READ_EVENT, 0);
 
                 } else {
@@ -1098,6 +1106,9 @@
 {
     ngx_uint_t         instance;
     ngx_event_t       *rev, *wev;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_event_t       *aev;
+#endif
     ngx_connection_t  *c;
 
     /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
@@ -1131,11 +1142,18 @@
 
     rev = c->read;
     wev = c->write;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    aev = c->async;
+#endif
 
     ngx_memzero(c, sizeof(ngx_connection_t));
 
     c->read = rev;
     c->write = wev;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    c->async = aev;
+#endif
+
     c->fd = s;
     c->log = log;
 
@@ -1143,17 +1161,32 @@
 
     ngx_memzero(rev, sizeof(ngx_event_t));
     ngx_memzero(wev, sizeof(ngx_event_t));
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_memzero(aev, sizeof(ngx_event_t));
+#endif
 
     rev->instance = !instance;
     wev->instance = !instance;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    aev->instance = !instance;
+#endif
 
     rev->index = NGX_INVALID_INDEX;
     wev->index = NGX_INVALID_INDEX;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    aev->index = NGX_INVALID_INDEX;
+#endif
 
     rev->data = c;
     wev->data = c;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    aev->data = c;
+#endif
 
     wev->write = 1;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    aev->async = 1;
+#endif
 
     return c;
 }
@@ -1192,11 +1225,32 @@
         ngx_del_timer(c->write);
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (c->async->timer_set) {
+        ngx_del_timer(c->async);
+    }
+
+    if (c->async_enable && ngx_del_async_conn) {
+        if (c->num_async_fds) {
+            ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+            c->num_async_fds--;
+        }
+    }
+#endif
+
     if (!c->shared) {
         if (ngx_del_conn) {
             ngx_del_conn(c, NGX_CLOSE_EVENT);
 
         } else {
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_del_async_conn) {
+            if (c->num_async_fds) {
+                ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                c->num_async_fds--;
+            }
+        }
+#endif
             if (c->read->active || c->read->disabled) {
                 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
             }
@@ -1215,8 +1269,17 @@
         ngx_delete_posted_event(c->write);
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (c->async->posted) {
+        ngx_delete_posted_event(c->async);
+    }
+#endif
+
     c->read->closed = 1;
     c->write->closed = 1;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    c->async->closed = 1;
+#endif
 
     ngx_reusable_connection(c, 0);
 
@@ -1226,6 +1289,9 @@
 
     fd = c->fd;
     c->fd = (ngx_socket_t) -1;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    c->async_fd = (ngx_socket_t) -1;
+#endif
 
     if (c->shared) {
         return;
diff -r 2245324a507a -r 301a837387ed src/core/ngx_connection.h
--- a/src/core/ngx_connection.h	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/core/ngx_connection.h	Tue Sep 07 16:29:07 2021 +0800
@@ -123,9 +123,14 @@
     void               *data;
     ngx_event_t        *read;
     ngx_event_t        *write;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_event_t        *async;
+#endif
 
     ngx_socket_t        fd;
-
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_socket_t        async_fd;
+#endif
     ngx_recv_pt         recv;
     ngx_send_pt         send;
     ngx_recv_chain_pt   recv_chain;
@@ -149,6 +154,9 @@
 
 #if (NGX_SSL || NGX_COMPAT)
     ngx_ssl_connection_t  *ssl;
+#if (NGX_SSL_ASYNC)
+    ngx_flag_t          async_enable;
+#endif
 #endif
 
     ngx_udp_connection_t  *udp;
@@ -184,6 +192,9 @@
     unsigned            tcp_nopush:2;    /* ngx_connection_tcp_nopush_e */
 
     unsigned            need_last_buf:1;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    unsigned            num_async_fds:8;
+#endif
 
 #if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
     unsigned            busy_count:2;
diff -r 2245324a507a -r 301a837387ed src/core/ngx_cycle.c
--- a/src/core/ngx_cycle.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/core/ngx_cycle.c	Tue Sep 07 16:29:07 2021 +0800
@@ -81,6 +81,9 @@
     cycle->pool = pool;
     cycle->log = log;
     cycle->old_cycle = old_cycle;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    cycle->no_ssl_init = old_cycle->no_ssl_init;
+#endif
 
     cycle->conf_prefix.len = old_cycle->conf_prefix.len;
     cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);
@@ -270,6 +273,9 @@
     conf.log = log;
     conf.module_type = NGX_CORE_MODULE;
     conf.cmd_type = NGX_MAIN_CONF;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    conf.no_ssl_init = cycle->no_ssl_init;
+#endif
 
 #if 0
     log->log_level = NGX_LOG_DEBUG_ALL;
diff -r 2245324a507a -r 301a837387ed src/core/ngx_cycle.h
--- a/src/core/ngx_cycle.h	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/core/ngx_cycle.h	Tue Sep 07 16:29:07 2021 +0800
@@ -73,6 +73,9 @@
     ngx_connection_t         *connections;
     ngx_event_t              *read_events;
     ngx_event_t              *write_events;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_event_t              *async_events;
+#endif
 
     ngx_cycle_t              *old_cycle;
 
@@ -83,6 +86,9 @@
     ngx_str_t                 error_log;
     ngx_str_t                 lock_file;
     ngx_str_t                 hostname;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_flag_t                no_ssl_init;
+#endif
 };
 
 
diff -r 2245324a507a -r 301a837387ed src/event/modules/ngx_devpoll_module.c
--- a/src/event/modules/ngx_devpoll_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/modules/ngx_devpoll_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -94,6 +94,10 @@
         ngx_devpoll_process_events,        /* process the events */
         ngx_devpoll_init,                  /* init the events */
         ngx_devpoll_done,                  /* done the events */
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        NULL,                              /* add an async conn */
+        NULL,                              /* del an async conn */
+#endif
     }
 
 };
diff -r 2245324a507a -r 301a837387ed src/event/modules/ngx_epoll_module.c
--- a/src/event/modules/ngx_epoll_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/modules/ngx_epoll_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -122,6 +122,11 @@
 #endif
 static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
     ngx_uint_t flags);
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static ngx_int_t ngx_epoll_add_async_connection(ngx_connection_t *c);
+static ngx_int_t ngx_epoll_del_async_connection(ngx_connection_t *c,
+    ngx_uint_t flags);
+#endif
 
 #if (NGX_HAVE_FILE_AIO)
 static void ngx_epoll_eventfd_handler(ngx_event_t *ev);
@@ -196,6 +201,10 @@
         ngx_epoll_process_events,        /* process the events */
         ngx_epoll_init,                  /* init the events */
         ngx_epoll_done,                  /* done the events */
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        ngx_epoll_add_async_connection,  /* add an async conn */
+        ngx_epoll_del_async_connection   /* del an async conn */
+#endif
     }
 };
 
@@ -758,6 +767,53 @@
     return NGX_OK;
 }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static ngx_int_t
+ngx_epoll_add_async_connection(ngx_connection_t *c)
+{
+    struct epoll_event  ee;
+
+    ee.events = EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP;
+    ee.data.ptr = (void *) ((uintptr_t) c | (c->async->async << 1) | c->async->instance);
+
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "epoll add async connection: fd:%d ev:%08XD", c->async_fd, ee.events);
+    if (epoll_ctl(ep, EPOLL_CTL_ADD, c->async_fd, &ee) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
+                      "async add conn epoll_ctl(EPOLL_CTL_ADD, %d) failed", c->async_fd);
+        return NGX_ERROR;
+    }
+
+    c->async->active = 1;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_epoll_del_async_connection(ngx_connection_t *c, ngx_uint_t flags)
+{
+    int                 op;
+    struct epoll_event  ee;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "epoll del async connection: fd:%d", c->async_fd);
+
+    op = EPOLL_CTL_DEL;
+    ee.events = 0;
+    ee.data.ptr = NULL;
+    if (epoll_ctl(ep, op, c->async_fd, &ee) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
+                      "async del conn epoll_ctl(%d, %d) failed", op, c->async_fd);
+        c->async_fd = -1;
+        return NGX_ERROR;
+    }
+    c->async_fd = -1;
+    c->async->active = 0;
+
+    return NGX_OK;
+}
+#endif
 
 #if (NGX_HAVE_EVENTFD)
 
@@ -791,6 +847,10 @@
     ngx_event_t       *rev, *wev;
     ngx_queue_t       *queue;
     ngx_connection_t  *c;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_int_t          async;
+    ngx_event_t       *aev;
+#endif
 
     /* NGX_TIMER_INFINITE == INFTIM */
 
@@ -837,7 +897,14 @@
         c = event_list[i].data.ptr;
 
         instance = (uintptr_t) c & 1;
+#if (NGX_SSL)
+#if (NGX_SSL_ASYNC)
+        async = ((uintptr_t) c & 2) >> 1;
+#endif
+        c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~3);
+#else
         c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
+#endif
 
         rev = c->read;
 
@@ -880,7 +947,11 @@
         }
 #endif
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if ((revents & EPOLLIN) && rev->active && !async) {
+#else
         if ((revents & EPOLLIN) && rev->active) {
+#endif
 
 #if (NGX_HAVE_EPOLLRDHUP)
             if (revents & EPOLLRDHUP) {
@@ -904,7 +975,11 @@
 
         wev = c->write;
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if ((revents & EPOLLOUT) && wev->active && !async) {
+#else
         if ((revents & EPOLLOUT) && wev->active) {
+#endif
 
             if (c->fd == -1 || wev->instance != instance) {
 
@@ -930,6 +1005,33 @@
                 wev->handler(wev);
             }
         }
+
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        aev = c->async;
+
+        if ((revents & EPOLLIN) && aev->active && async) {
+
+            if (c->async_fd == -1 || aev->instance!= instance) {
+                /*
+                 * the stale event from a file descriptor
+                 * that was just closed in this iteration
+                 */
+
+                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+                               "epoll: stale event %p", c);
+                continue;
+            }
+
+            aev->ready = 1;
+
+            if (flags & NGX_POST_EVENTS) {
+                ngx_post_event(aev, &ngx_posted_events);
+
+            } else {
+                aev->handler(aev);
+            }
+        }
+#endif
     }
 
     return NGX_OK;
diff -r 2245324a507a -r 301a837387ed src/event/modules/ngx_eventport_module.c
--- a/src/event/modules/ngx_eventport_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/modules/ngx_eventport_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -187,6 +187,10 @@
         ngx_eventport_process_events,      /* process the events */
         ngx_eventport_init,                /* init the events */
         ngx_eventport_done,                /* done the events */
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        NULL,                              /* add an async conn */
+        NULL,                              /* del an async conn */
+#endif
     }
 
 };
diff -r 2245324a507a -r 301a837387ed src/event/modules/ngx_kqueue_module.c
--- a/src/event/modules/ngx_kqueue_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/modules/ngx_kqueue_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -92,7 +92,11 @@
 #endif
         ngx_kqueue_process_events,         /* process the events */
         ngx_kqueue_init,                   /* init the events */
-        ngx_kqueue_done                    /* done the events */
+        ngx_kqueue_done,                   /* done the events */
+#if (NGX_SSL && NGX_SSL_ASYNC)        
+        NULL,                              /* add an async conn */
+        NULL,                              /* del an async conn */
+#endif
     }
 
 };
diff -r 2245324a507a -r 301a837387ed src/event/modules/ngx_poll_module.c
--- a/src/event/modules/ngx_poll_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/modules/ngx_poll_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -42,7 +42,11 @@
         NULL,                              /* trigger a notify */
         ngx_poll_process_events,           /* process the events */
         ngx_poll_init,                     /* init the events */
-        ngx_poll_done                      /* done the events */
+        ngx_poll_done,                     /* done the events */
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        NULL,                              /* add an async conn */
+        NULL,                              /* del an async conn */
+#endif
     }
 
 };
diff -r 2245324a507a -r 301a837387ed src/event/modules/ngx_select_module.c
--- a/src/event/modules/ngx_select_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/modules/ngx_select_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -50,7 +50,11 @@
         NULL,                              /* trigger a notify */
         ngx_select_process_events,         /* process the events */
         ngx_select_init,                   /* init the events */
-        ngx_select_done                    /* done the events */
+        ngx_select_done,                   /* done the events */
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        NULL,                              /* add an async conn */
+        NULL,                              /* del an async conn */
+#endif
     }
 
 };
diff -r 2245324a507a -r 301a837387ed src/event/modules/ngx_win32_select_module.c
--- a/src/event/modules/ngx_win32_select_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/modules/ngx_win32_select_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -52,7 +52,11 @@
         NULL,                              /* trigger a notify */
         ngx_select_process_events,         /* process the events */
         ngx_select_init,                   /* init the events */
-        ngx_select_done                    /* done the events */
+        ngx_select_done,                   /* done the events */
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        NULL,                              /* add an async conn */
+        NULL,                              /* del an async conn */
+#endif
     }
 
 };
diff -r 2245324a507a -r 301a837387ed src/event/ngx_event.c
--- a/src/event/ngx_event.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/ngx_event.c	Tue Sep 07 16:29:07 2021 +0800
@@ -169,8 +169,11 @@
     &event_core_name,
     ngx_event_core_create_conf,            /* create configuration */
     ngx_event_core_init_conf,              /* init configuration */
-
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+#else
     { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+#endif
 };
 
 
@@ -237,11 +240,6 @@
         }
     }
 
-    if (!ngx_queue_empty(&ngx_posted_next_events)) {
-        ngx_event_move_posted_next(cycle);
-        timer = 0;
-    }
-
     delta = ngx_current_msec;
 
     (void) ngx_process_events(cycle, timer, flags);
@@ -758,6 +756,20 @@
         wev[i].closed = 1;
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    cycle->async_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
+                                    cycle->log);
+    if (cycle->async_events == NULL) {
+        return NGX_ERROR;
+    }
+
+    aev = cycle->async_events;
+    for (i = 0; i < cycle->connection_n; i++) {
+        aev[i].closed = 1;
+        aev[i].instance = 1;
+    }
+#endif
+
     i = cycle->connection_n;
     next = NULL;
 
@@ -768,6 +780,10 @@
         c[i].read = &cycle->read_events[i];
         c[i].write = &cycle->write_events[i];
         c[i].fd = (ngx_socket_t) -1;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        c[i].async = &cycle->async_events[i];
+        c[i].async_fd = (ngx_socket_t) -1;
+#endif
 
         next = &c[i];
     } while (i);
diff -r 2245324a507a -r 301a837387ed src/event/ngx_event.h
--- a/src/event/ngx_event.h	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/ngx_event.h	Tue Sep 07 16:29:07 2021 +0800
@@ -32,6 +32,10 @@
 
     unsigned         write:1;
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    unsigned         async:1;
+#endif
+
     unsigned         accept:1;
 
     /* used to detect the stale events in kqueue and epoll */
@@ -101,6 +105,9 @@
     int              available;
 
     ngx_event_handler_pt  handler;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_event_handler_pt  saved_handler;
+#endif
 
 
 #if (NGX_HAVE_IOCP)
@@ -184,6 +191,11 @@
 
     ngx_int_t  (*init)(ngx_cycle_t *cycle, ngx_msec_t timer);
     void       (*done)(ngx_cycle_t *cycle);
+
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_int_t  (*add_async_conn)(ngx_connection_t *c);
+    ngx_int_t  (*del_async_conn)(ngx_connection_t *c, ngx_uint_t flags);
+#endif
 } ngx_event_actions_t;
 
 
@@ -409,6 +421,11 @@
 #define ngx_add_conn         ngx_event_actions.add_conn
 #define ngx_del_conn         ngx_event_actions.del_conn
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+#define ngx_add_async_conn   ngx_event_actions.add_async_conn
+#define ngx_del_async_conn   ngx_event_actions.del_async_conn
+#endif
+
 #define ngx_notify           ngx_event_actions.notify
 
 #define ngx_add_timer        ngx_event_add_timer
diff -r 2245324a507a -r 301a837387ed src/event/ngx_event_accept.c
--- a/src/event/ngx_event_accept.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/ngx_event_accept.c	Tue Sep 07 16:29:07 2021 +0800
@@ -244,6 +244,9 @@
 
         rev->log = log;
         wev->log = log;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        c->async->log = log;
+#endif
 
         /*
          * TODO: MT: - ngx_atomic_fetch_add()
@@ -409,6 +412,15 @@
 
 #endif
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_del_async_conn) {
+            if (c->num_async_fds) {
+                ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                c->num_async_fds--;
+            }
+        }
+#endif
+
         if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
             == NGX_ERROR)
         {
diff -r 2245324a507a -r 301a837387ed src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/ngx_event_openssl.c	Tue Sep 07 16:29:07 2021 +0800
@@ -89,6 +89,12 @@
 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static void ngx_openssl_exit(ngx_cycle_t *cycle);
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static void ngx_ssl_handshake_async_handler(ngx_event_t * aev);
+static void ngx_ssl_read_async_handler(ngx_event_t * aev);
+static void ngx_ssl_write_async_handler(ngx_event_t * aev);
+static void ngx_ssl_shutdown_async_handler(ngx_event_t *aev);
+#endif
 
 static ngx_command_t  ngx_openssl_commands[] = {
 
@@ -137,6 +143,16 @@
 int  ngx_ssl_stapling_index;
 
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static void
+ngx_ssl_empty_handler(ngx_event_t *aev)
+{
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, aev->log, 0, "ssl empty handler");
+
+    return;
+}
+#endif
+
 ngx_int_t
 ngx_ssl_init(ngx_log_t *log)
 {
@@ -385,6 +401,12 @@
     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_NO_AUTO_CHAIN);
 #endif
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (ssl->async_enable) {
+        SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ASYNC);
+    }
+#endif
+
     SSL_CTX_set_read_ahead(ssl->ctx, 1);
 
     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
@@ -1662,7 +1684,9 @@
     }
 
     c->ssl = sc;
-
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    c->async_enable = ssl->async_enable;
+#endif
     return NGX_OK;
 }
 
@@ -1706,6 +1730,205 @@
 }
 
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+ngx_int_t
+ngx_ssl_async_process_fds(ngx_connection_t *c)
+{
+    OSSL_ASYNC_FD *add_fds = NULL;
+    OSSL_ASYNC_FD *del_fds = NULL;
+    size_t        num_add_fds = 0;
+    size_t        num_del_fds = 0;
+    unsigned      loop = 0;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "ngx_ssl_async_process_fds called");
+
+    if (!ngx_del_async_conn || !ngx_add_async_conn) {
+        ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
+                      "Async notifications not supported");
+        return NGX_ERROR;
+    }
+
+    SSL_get_changed_async_fds(c->ssl->connection, NULL, &num_add_fds,
+                              NULL, &num_del_fds);
+
+    if (num_add_fds) {
+        add_fds = ngx_alloc(num_add_fds * sizeof(OSSL_ASYNC_FD), c->log);
+        if (add_fds == NULL) {
+            ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
+                          "Memory Allocation Error");
+            return NGX_ERROR;
+        }
+    }
+
+    if (num_del_fds) {
+        del_fds = ngx_alloc(num_del_fds * sizeof(OSSL_ASYNC_FD), c->log);
+        if (del_fds == NULL) {
+            ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
+                          "Memory Allocation Error");
+            if (add_fds)
+                ngx_free(add_fds);
+            return NGX_ERROR;
+        }
+    }
+
+    SSL_get_changed_async_fds(c->ssl->connection, add_fds, &num_add_fds,
+                              del_fds, &num_del_fds);
+
+    if (num_del_fds) {
+        for (loop = 0; loop < num_del_fds; loop++) {
+            c->async_fd = del_fds[loop];
+            if (c->num_async_fds) {
+                ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "%s: deleting fd = %d", __func__, c->async_fd);
+                ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                c->num_async_fds--;
+            }
+        }
+    }
+    if (num_add_fds) {
+        for (loop = 0; loop < num_add_fds; loop++) {
+            if (c->num_async_fds == 0) {
+                c->num_async_fds++;
+                c->async_fd = add_fds[loop];
+                ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "%s: adding fd = %d", __func__, c->async_fd);
+                ngx_add_async_conn(c);
+            }
+        }
+    }
+
+    if (add_fds)
+        ngx_free(add_fds);
+    if (del_fds)
+        ngx_free(del_fds);
+
+    return NGX_OK;
+}
+#endif
+
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+static ngx_int_t
+ngx_ssl_read_early_data(ngx_connection_t *c,
+                        u_char *buf,
+                        size_t size,
+                        size_t *readbytes)
+{
+    int errret;
+
+    if (!SSL_is_server(c->ssl->connection)) {
+        return 0;
+    }
+
+    if (c->ssl->read_early_state == SSL_READ_EARLY_DATA_FINISH) {
+        return 0;
+    }
+
+    errret = SSL_read_early_data(c->ssl->connection, buf,
+                                 size, readbytes);
+    c->ssl->read_early_state = errret;
+
+    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+        "SSL_read_early_data: %d readbytes: %d "
+        "early_data_status: %d",
+        errret, *readbytes,
+        SSL_get_early_data_status(c->ssl->connection));
+
+    return errret;
+}
+
+static ngx_int_t
+ngx_ssl_handshake_early_data(ngx_connection_t *c)
+{
+    int        sslerr, errret;
+    size_t     size, readbytes = 0;
+    ngx_buf_t *b;
+
+    if (!c->ssl->enable_early_data) {
+        SSL_set_max_early_data(c->ssl->connection, 0);
+        return 0;
+    }
+
+    if (SSL_get_options(c->ssl->connection) & SSL_OP_NO_TLSv1_3) {
+        return 0;
+    }
+
+    if (!SSL_is_server(c->ssl->connection)) {
+        return 0;
+    }
+
+    if (c->ssl->read_early_state == SSL_READ_EARLY_DATA_FINISH) {
+        return 0;
+    }
+
+    b = c->ssl->early_buf;
+#if (TLS1_3_VERSION_DRAFT == 0x7f12)
+    size = SSL_get_max_early_data(c->ssl->session_ctx);
+#else
+    size = SSL_get_max_early_data(c->ssl->connection);
+#endif
+    if (size == 0) {
+        return 0;
+    }
+
+    if (b == NULL) {
+        b = ngx_create_temp_buf(c->pool, size);
+        if (b == NULL) {
+            return 0;
+        }
+
+        c->ssl->early_buf = b;
+
+    } else if (b->start == NULL) {
+
+        b->start = ngx_palloc(c->pool, size);
+        if (b->start == NULL) {
+            return 0;
+        }
+
+        b->pos = b->start;
+        b->last = b->start;
+        b->end = b->last + size;
+    }
+
+
+
+    errret = ngx_ssl_read_early_data(c, b->last,
+                                     b->end - b->last, &readbytes);
+    if (readbytes > 0) {
+        b->last += readbytes;
+    }
+
+    if (errret != SSL_READ_EARLY_DATA_ERROR) {
+        if (SSL_get_early_data_status(c->ssl->connection) ==
+            SSL_EARLY_DATA_ACCEPTED) {
+            switch (errret) {
+            case SSL_READ_EARLY_DATA_FINISH:
+                return 1;
+            case SSL_READ_EARLY_DATA_SUCCESS:
+                return 1; 
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    sslerr = SSL_get_error(c->ssl->connection, 0); 
+    switch (sslerr) {
+    case SSL_ERROR_WANT_WRITE:
+    case SSL_ERROR_WANT_ASYNC:
+    case SSL_ERROR_WANT_READ:
+            break; 
+    default:
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+            "SSL_get_error: %d while reading early data\n", sslerr);
+            return -2;
+    }
+
+    return -1;
+}
+#endif
+
+
+
 ngx_int_t
 ngx_ssl_handshake(ngx_connection_t *c)
 {
@@ -1730,7 +1953,11 @@
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
 
     if (n == 1) {
-
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
             return NGX_ERROR;
         }
@@ -1785,7 +2012,17 @@
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
 
-    if (sslerr == SSL_ERROR_WANT_READ) {
+    if (sslerr == SSL_ERROR_WANT_READ
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+        || (sslerr == SSL_ERROR_NONE &&
+            c->ssl->read_early_state == SSL_READ_EARLY_DATA_SUCCESS)
+#endif
+        ) {
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
         c->read->ready = 0;
         c->read->handler = ngx_ssl_handshake_handler;
         c->write->handler = ngx_ssl_handshake_handler;
@@ -1802,6 +2039,12 @@
     }
 
     if (sslerr == SSL_ERROR_WANT_WRITE) {
+    	
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif    	
         c->write->ready = 0;
         c->read->handler = ngx_ssl_handshake_handler;
         c->write->handler = ngx_ssl_handshake_handler;
@@ -1817,6 +2060,24 @@
         return NGX_AGAIN;
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (c->async_enable && sslerr == SSL_ERROR_WANT_ASYNC)
+    {
+        c->async->handler = ngx_ssl_handshake_async_handler;
+        c->read->saved_handler = c->read->handler;
+        c->read->handler = ngx_ssl_empty_handler;
+
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "SSL ASYNC WANT recieved: \"%s\"", __func__);
+
+        if (ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+
+        return NGX_AGAIN;
+    }
+#endif
+
     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
 
     c->ssl->no_wait_shutdown = 1;
@@ -1844,6 +2105,29 @@
     return NGX_ERROR;
 }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static void
+ngx_ssl_handshake_async_handler(ngx_event_t *aev)
+{
+    ngx_connection_t  *c;
+
+    c = aev->data;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "SSL handshake async handler");
+
+    aev->ready = 0;
+    aev->handler = ngx_ssl_empty_handler;
+    c->read->handler = c->read->saved_handler;
+
+    if (ngx_ssl_handshake(c) == NGX_AGAIN) {
+        return;
+    }
+
+    c->ssl->handler(c);
+}
+#endif
+
 
 #ifdef SSL_READ_EARLY_DATA_SUCCESS
 
@@ -2052,6 +2336,13 @@
         return;
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    /*
+     * empty the handler of async event to avoid
+     * going back to previous ssl handshake state
+     */
+    c->async->handler = ngx_ssl_empty_handler;
+#endif
     c->ssl->handler(c);
 }
 
@@ -2151,7 +2442,32 @@
      */
 
     for ( ;; ) {
-
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+        if (c->ssl->enable_early_data &&
+            c->ssl->early_buf &&
+            c->ssl->early_buf->start &&
+            (c->ssl->early_buf->last > c->ssl->early_buf->pos)) {
+            n = c->ssl->early_buf->last - c->ssl->early_buf->pos;
+            if (n > (int)size)
+                n = size;
+            ngx_memcpy(buf, c->ssl->early_buf->start, n);
+            c->ssl->early_buf->pos += n;
+            return n;
+        }
+
+        if (c->ssl->enable_early_data &&
+            !SSL_is_init_finished(c->ssl->connection) &&
+            (c->ssl->read_early_state != SSL_READ_EARLY_DATA_FINISH) &&
+            (SSL_get_early_data_status(c->ssl->connection) ==
+              SSL_EARLY_DATA_ACCEPTED)) {
+            size_t readbytes = 0;
+            n = ngx_ssl_read_early_data(c, buf, size, &readbytes);
+            if (readbytes > 0)
+                n = readbytes;
+            else if (n == SSL_READ_EARLY_DATA_FINISH)
+                n = SSL_read(c->ssl->connection, buf, size);
+        } else
+#endif
         n = SSL_read(c->ssl->connection, buf, size);
 
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
@@ -2373,7 +2689,11 @@
 
 #ifndef SSL_OP_NO_RENEGOTIATION
 
-    if (c->ssl->renegotiation) {
+    if (c->ssl->renegotiation
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+        && (SSL_version(c->ssl->connection) != TLS1_3_VERSION)
+#endif
+        ) {
         /*
          * disable renegotiation (CVE-2009-3555):
          * OpenSSL (at least up to 0.9.8l) does not handle disabled
@@ -2398,7 +2718,11 @@
 #endif
 
     if (n > 0) {
-
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
         if (c->ssl->saved_write_handler) {
 
             c->write->handler = c->ssl->saved_write_handler;
@@ -2421,7 +2745,12 @@
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
 
-    if (sslerr == SSL_ERROR_WANT_READ) {
+    if (sslerr == SSL_ERROR_WANT_READ) {    	
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
 
         if (c->ssl->saved_write_handler) {
 
@@ -2444,6 +2773,11 @@
 
         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "SSL_read: want write");
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
 
         c->write->ready = 0;
 
@@ -2463,6 +2797,22 @@
         return NGX_AGAIN;
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (c->async_enable && sslerr == SSL_ERROR_WANT_ASYNC) {
+        c->async->handler = ngx_ssl_read_async_handler;
+        c->read->saved_handler = c->read->handler;
+        c->read->handler = ngx_ssl_empty_handler;
+
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "SSL ASYNC WANT recieved: \"%s\"", __func__);
+
+        if (ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+
+        return NGX_AGAIN;
+    }
+#endif
     c->ssl->no_wait_shutdown = 1;
     c->ssl->no_send_shutdown = 1;
 
@@ -2477,6 +2827,24 @@
     return NGX_ERROR;
 }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static void
+ngx_ssl_read_async_handler(ngx_event_t *aev)
+{
+    ngx_connection_t  *c;
+
+    c = aev->data;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "SSL read async handler");
+
+    aev->ready = 0;
+    aev->handler = ngx_ssl_empty_handler;
+    c->read->handler = c->read->saved_handler;
+
+    c->read->handler(c->read);
+}
+#endif
 
 static void
 ngx_ssl_write_handler(ngx_event_t *wev)
@@ -2670,12 +3038,30 @@
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %uz", size);
 
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+    if (c->ssl->enable_early_data &&
+        !SSL_is_init_finished(c->ssl->connection) &&
+        (SSL_get_early_data_status(c->ssl->connection) ==
+         SSL_EARLY_DATA_ACCEPTED)) {
+        size_t wrttenbytes = 0;
+        n = SSL_write_early_data(c->ssl->connection, data, size, &wrttenbytes);
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "SSL_write_early_data: %d written: %d", n, wrttenbytes);
+        if (wrttenbytes > 0)
+            n = wrttenbytes;
+    } else
+#endif
     n = SSL_write(c->ssl->connection, data, size);
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
 
     if (n > 0) {
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
         if (c->ssl->saved_read_handler) {
 
             c->read->handler = c->ssl->saved_read_handler;
@@ -2713,6 +3099,11 @@
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
 
     if (sslerr == SSL_ERROR_WANT_WRITE) {
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
 
         if (c->ssl->saved_read_handler) {
 
@@ -2735,7 +3126,11 @@
 
         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "SSL_write: want read");
-
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+#endif
         c->read->ready = 0;
 
         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
@@ -2755,6 +3150,22 @@
         return NGX_AGAIN;
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (c->async_enable && sslerr == SSL_ERROR_WANT_ASYNC) {
+        c->async->handler = ngx_ssl_write_async_handler;
+        c->read->saved_handler = c->read->handler;
+        c->read->handler = ngx_ssl_empty_handler;
+
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "SSL ASYNC WANT recieved: \"%s\"", __func__);
+
+        if (ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+
+        return NGX_AGAIN;
+    }
+#endif
     c->ssl->no_wait_shutdown = 1;
     c->ssl->no_send_shutdown = 1;
     c->write->error = 1;
@@ -2764,6 +3175,24 @@
     return NGX_ERROR;
 }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static void
+ngx_ssl_write_async_handler(ngx_event_t *aev)
+{
+    ngx_connection_t  *c;
+
+    c = aev->data;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "SSL write async handler");
+
+    aev->ready = 0;
+    aev->handler = ngx_ssl_empty_handler;
+    c->read->handler = c->read->saved_handler;
+
+    c->write->handler(c->write);
+}
+#endif
 
 #ifdef SSL_READ_EARLY_DATA_SUCCESS
 
@@ -2903,6 +3332,13 @@
             c->ssl->buf->start = NULL;
         }
     }
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+    if (c->ssl->early_buf && c->ssl->early_buf->start) {
+        if (ngx_pfree(c->pool, c->ssl->early_buf->start) == NGX_OK) {
+            c->ssl->early_buf->start = NULL;
+        }
+    }
+#endif
 }
 
 
@@ -2913,6 +3349,11 @@
     ngx_int_t   rc;
     ngx_err_t   err;
     ngx_uint_t  tries;
+    
+    if (!c->ssl) {
+        return NGX_OK;
+    }
+
 
     rc = NGX_OK;
 
@@ -2924,6 +3365,31 @@
          * an SSL handshake, while previous versions always return 0.
          * Avoid calling SSL_shutdown() if handshake wasn't completed.
          */
+#if (NGX_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable) {
+            /* Check if there is inflight request */
+            if (SSL_want_async(c->ssl->connection) && !c->timedout) {
+                c->async->handler = ngx_ssl_shutdown_async_handler;
+                ngx_ssl_async_process_fds(c);
+                ngx_add_timer(c->async, 300);
+                return NGX_AGAIN;
+            }
+
+            /* Ignore errors from ngx_ssl_async_process_fds as
+               we want to carry on and close the SSL connection
+               anyway. */
+            ngx_ssl_async_process_fds(c);
+            if (ngx_del_async_conn) {
+                if (c->num_async_fds) {
+                    ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                    c->num_async_fds--;
+                }
+            }
+            ngx_del_conn(c, NGX_DISABLE_EVENT);
+        }
+#endif
+        SSL_free(c->ssl->connection);
+        c->ssl = NULL;
 
         goto done;
     }
@@ -2976,12 +3442,19 @@
 
         /* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
 
+
         sslerr = SSL_get_error(c->ssl->connection, n);
 
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "SSL_get_error: %d", sslerr);
 
         if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
+            
+#if (NGX_SSL && NGX_SSL_ASYNC)
+            if (c->async_enable && ngx_ssl_async_process_fds(c) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+#endif
             c->read->handler = ngx_ssl_shutdown_handler;
             c->write->handler = ngx_ssl_shutdown_handler;
 
@@ -3021,6 +3494,13 @@
     rc = NGX_ERROR;
 
 done:
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    if (c->async_enable && n == -1) {
+        sslerr = SSL_get_error(c->ssl->connection, n);
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "SSL_get_error async: %d", sslerr);
+    }
+#endif
 
     if (c->ssl->shutdown_without_free) {
         c->ssl->shutdown_without_free = 0;
@@ -3035,6 +3515,34 @@
     return rc;
 }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+static void
+ngx_ssl_shutdown_async_handler(ngx_event_t *aev)
+{
+    ngx_connection_t           *c;
+    ngx_connection_handler_pt   handler;
+
+    c = aev->data;
+    handler = c->ssl->handler;
+
+    if (aev->timedout) {
+        c->timedout = 1;
+    }
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, aev->log, 0,
+                   "SSL shutdown async handler");
+
+    aev->ready = 0;
+    aev->handler = ngx_ssl_empty_handler;
+    c->read->handler = c->read->saved_handler;
+
+    if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
+        return;
+    }
+
+    handler(c);
+}
+#endif
 
 static void
 ngx_ssl_shutdown_handler(ngx_event_t *ev)
@@ -3055,6 +3563,13 @@
         return;
     }
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    /*
+     * empty the handler of async event to avoid
+     * going back to previous ssl shutdown state
+     */
+    c->async->handler = ngx_ssl_empty_handler;
+#endif
     handler(c);
 }
 
diff -r 2245324a507a -r 301a837387ed src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/event/ngx_event_openssl.h	Tue Sep 07 16:29:07 2021 +0800
@@ -82,6 +82,9 @@
     SSL_CTX                    *ctx;
     ngx_log_t                  *log;
     size_t                      buffer_size;
+#if (NGX_SSL && NGX_SSL_ASYNC)
+    ngx_flag_t                  async_enable;
+#endif
 };
 
 
@@ -92,6 +95,9 @@
     ngx_int_t                   last;
     ngx_buf_t                  *buf;
     size_t                      buffer_size;
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+    ngx_buf_t                  *early_buf;
+#endif
 
     ngx_connection_handler_pt   handler;
 
@@ -118,6 +124,10 @@
     unsigned                    in_ocsp:1;
     unsigned                    early_preread:1;
     unsigned                    write_blocked:1;
+    unsigned                    enable_early_data:1;
+#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+    int                         read_early_state;
+#endif
 };
 
 
@@ -248,6 +258,9 @@
 
 ngx_int_t ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name);
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+#define ngx_ssl_waiting_for_async(c) SSL_waiting_for_async(c->ssl->connection)
+#endif
 
 ngx_int_t ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool,
     ngx_str_t *s);
@@ -305,6 +318,9 @@
     char *fmt, ...);
 void ngx_ssl_cleanup_ctx(void *data);
 
+#if (NGX_SSL && NGX_SSL_ASYNC)
+ngx_int_t ngx_ssl_async_process_fds(ngx_connection_t *c) ;
+#endif
 
 extern int  ngx_ssl_connection_index;
 extern int  ngx_ssl_server_conf_index;
diff -r 2245324a507a -r 301a837387ed src/http/modules/ngx_http_ssl_module.c
--- a/src/http/modules/ngx_http_ssl_module.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/http/modules/ngx_http_ssl_module.c	Tue Sep 07 16:29:07 2021 +0800
@@ -46,6 +46,10 @@
 
 static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+static char *ngx_http_ssl_enable_async(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+#endif
 static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -105,6 +109,15 @@
       offsetof(ngx_http_ssl_srv_conf_t, enable),
       &ngx_http_ssl_deprecated },
 
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+    { ngx_string("ssl_async"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
+      ngx_http_ssl_enable_async,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_ssl_srv_conf_t, async_enable),
+      NULL },
+#endif
+
     { ngx_string("ssl_certificate"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
@@ -619,6 +632,9 @@
      */
 
     sscf->enable = NGX_CONF_UNSET;
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+    sscf->async_enable = NGX_CONF_UNSET;
+#endif
     sscf->prefer_server_ciphers = NGX_CONF_UNSET;
     sscf->early_data = NGX_CONF_UNSET;
     sscf->reject_handshake = NGX_CONF_UNSET;
@@ -637,6 +653,7 @@
     sscf->ocsp_cache_zone = NGX_CONF_UNSET_PTR;
     sscf->stapling = NGX_CONF_UNSET;
     sscf->stapling_verify = NGX_CONF_UNSET;
+    sscf->early_data = NGX_CONF_UNSET;
 
     return sscf;
 }
@@ -661,6 +678,18 @@
         }
     }
 
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+    if (conf->async_enable == NGX_CONF_UNSET) {
+        if (prev->async_enable == NGX_CONF_UNSET) {
+            conf->async_enable = 0;
+
+        } else {
+            conf->async_enable = prev->async_enable;
+            conf->file = prev->file;
+            conf->line = prev->line;
+        }
+    }
+#endif
     ngx_conf_merge_value(conf->session_timeout,
                          prev->session_timeout, 300);
 
@@ -712,6 +741,8 @@
     ngx_conf_merge_str_value(conf->stapling_responder,
                          prev->stapling_responder, "");
 
+    ngx_conf_merge_value(conf->early_data, prev->early_data, 1);
+
     conf->ssl.log = cf->log;
 
     if (conf->enable) {
@@ -735,6 +766,9 @@
                               conf->file, conf->line);
                 return NGX_CONF_ERROR;
             }
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+        conf->ssl.async_enable = conf->async_enable;
+#endif
 
         } else if (!conf->reject_handshake) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
@@ -1054,6 +1088,40 @@
     return NGX_CONF_OK;
 }
 
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+static char *
+ngx_http_ssl_enable_async(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_ssl_srv_conf_t *sscf = conf;
+    char                    *rv;
+    ngx_flag_t              *pssl, *pssl_async;
+
+    rv = ngx_conf_set_flag_slot(cf, cmd, conf);
+
+    if (rv != NGX_CONF_OK) {
+        return rv;
+    }
+
+    /* If ssl_async on is configured, then ssl on is configured by default
+     * This will align 'ssl_async on;' and 'listen port ssl' diretives
+     * */
+    pssl = (ngx_flag_t *) ((char *)conf + offsetof(ngx_http_ssl_srv_conf_t, enable));
+    pssl_async = (ngx_flag_t *) ((char *)conf + cmd->offset);
+
+    if(*pssl_async) {
+        ngx_log_error(NGX_LOG_NOTICE, cf->log, 0, "Nginx enables async mode.");
+    }
+
+    if(*pssl_async && *pssl != 1) {
+        *pssl = *pssl_async;
+    }
+
+    sscf->file = cf->conf_file->file.name.data;
+    sscf->line = cf->conf_file->line;
+
+    return NGX_CONF_OK;
+}
+#endif
 
 static char *
 ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
diff -r 2245324a507a -r 301a837387ed src/http/modules/ngx_http_ssl_module.h
--- a/src/http/modules/ngx_http_ssl_module.h	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/http/modules/ngx_http_ssl_module.h	Tue Sep 07 16:29:07 2021 +0800
@@ -17,6 +17,10 @@
 typedef struct {
     ngx_flag_t                      enable;
 
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+    ngx_flag_t                      async_enable;
+#endif
+
     ngx_ssl_t                       ssl;
 
     ngx_flag_t                      prefer_server_ciphers;
@@ -65,6 +69,8 @@
     ngx_str_t                       stapling_file;
     ngx_str_t                       stapling_responder;
 
+    ngx_flag_t                      early_data;
+
     u_char                         *file;
     ngx_uint_t                      line;
 } ngx_http_ssl_srv_conf_t;
diff -r 2245324a507a -r 301a837387ed src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/http/ngx_http_request.c	Tue Sep 07 16:29:07 2021 +0800
@@ -447,9 +447,21 @@
          * We are trying to not hold c->buffer's memory for an idle connection.
          */
 
-        if (ngx_pfree(c->pool, b->start) == NGX_OK) {
-            b->start = NULL;
+        /* For the Async implementation we need the same buffer to be used
+         * again on any async calls that have not completed.
+         * As such we need to turn off this optimisation if an async request
+         * is still in progress.
+         */
+
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+        if ((c->async_enable && !ngx_ssl_waiting_for_async(c)) || !c->async_enable) {
+#endif
+            if (ngx_pfree(c->pool, b->start) == NGX_OK) {
+                b->start = NULL;
+            }
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
         }
+#endif
 
         return;
     }
@@ -755,6 +767,8 @@
             }
 
             ngx_reusable_connection(c, 0);
+            
+            c->ssl->enable_early_data = sscf->early_data;
 
             rc = ngx_ssl_handshake(c);
 
@@ -1551,12 +1565,21 @@
         return n;
     }
 
-    if (rev->ready) {
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+    if(c->async_enable)
         n = c->recv(c, r->header_in->last,
                     r->header_in->end - r->header_in->last);
-    } else {
-        n = NGX_AGAIN;
+    else {
+#endif
+        if (rev->ready) {
+            n = c->recv(c, r->header_in->last,
+                        r->header_in->end - r->header_in->last);
+        } else {
+            n = NGX_AGAIN;
+        }
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
     }
+#endif
 
     if (n == NGX_AGAIN) {
         if (!rev->timer_set) {
@@ -2048,7 +2071,7 @@
 
     c = r->connection;
 
-#if (NGX_HTTP_SSL)
+#if 0 && (NGX_HTTP_SSL)
 
     if (r->http_connection->ssl) {
         long                      rc;
@@ -3178,52 +3201,63 @@
      * c->pool and are freed too.
      */
 
-    b = c->buffer;
-
-    if (ngx_pfree(c->pool, b->start) == NGX_OK) {
-
-        /*
-         * the special note for ngx_http_keepalive_handler() that
-         * c->buffer's memory was freed
-         */
-
-        b->pos = NULL;
-
-    } else {
-        b->pos = b->start;
-        b->last = b->start;
+    /* For the Async implementation we need the same buffer to be used
+     * again on any async calls that have not completed.
+     * As such we need to turn off this optimisation if an async request
+     * is still in progress.
+     */
+
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+    if ((c->async_enable && !ngx_ssl_waiting_for_async(c)) || !c->async_enable)
+    {
+#endif
+        b = c->buffer;
+
+        if (ngx_pfree(c->pool, b->start) == NGX_OK) {
+
+            /*
+             * the special note for ngx_http_keepalive_handler() that
+             * c->buffer's memory was freed
+             */
+
+            b->pos = NULL;
+
+        } else {
+            b->pos = b->start;
+            b->last = b->start;
+        }
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p",
+                       hc->free);
+
+        if (hc->free) {
+            for (cl = hc->free; cl; /* void */) {
+                ln = cl;
+                cl = cl->next;
+                ngx_pfree(c->pool, ln->buf->start);
+                ngx_free_chain(c->pool, ln);
+            }
+
+            hc->free = NULL;
+        }
+
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i",
+                       hc->busy, hc->nbusy);
+
+        if (hc->busy) {
+            for (cl = hc->busy; cl; /* void */) {
+                ln = cl;
+                cl = cl->next;
+                ngx_pfree(c->pool, ln->buf->start);
+                ngx_free_chain(c->pool, ln);
+            }
+
+            hc->busy = NULL;
+            hc->nbusy = 0;
+        }
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
     }
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p",
-                   hc->free);
-
-    if (hc->free) {
-        for (cl = hc->free; cl; /* void */) {
-            ln = cl;
-            cl = cl->next;
-            ngx_pfree(c->pool, ln->buf->start);
-            ngx_free_chain(c->pool, ln);
-        }
-
-        hc->free = NULL;
-    }
-
-    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i",
-                   hc->busy, hc->nbusy);
-
-    if (hc->busy) {
-        for (cl = hc->busy; cl; /* void */) {
-            ln = cl;
-            cl = cl->next;
-            ngx_pfree(c->pool, ln->buf->start);
-            ngx_free_chain(c->pool, ln);
-        }
-
-        hc->busy = NULL;
-        hc->nbusy = 0;
-    }
-
-#if (NGX_HTTP_SSL)
     if (c->ssl) {
         ngx_ssl_free_buffer(c);
     }
@@ -3232,6 +3266,14 @@
     rev->handler = ngx_http_keepalive_handler;
 
     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_del_async_conn) {
+            if (c->num_async_fds) {
+                ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                c->num_async_fds--;
+            }
+        }
+#endif
         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
             ngx_http_close_connection(c);
             return;
@@ -3356,14 +3398,26 @@
          * c->buffer's memory for a keepalive connection.
          */
 
-        if (ngx_pfree(c->pool, b->start) == NGX_OK) {
-
-            /*
-             * the special note that c->buffer's memory was freed
-             */
-
-            b->pos = NULL;
+        /* For the Asynch implementation we need the same buffer to be used
+         * on subsequent read requests. As such we need to turn off this optimisation that
+         * frees the buffer between invocations as may end up with a buffer that is at a
+         * different address */
+
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+        if ((c->async_enable && !ngx_ssl_waiting_for_async(c)) || !c->async_enable)
+        {
+#endif
+            if (ngx_pfree(c->pool, b->start) == NGX_OK) {
+
+                /*
+                 * the special note that c->buffer's memory was freed
+                 */
+
+                b->pos = NULL;
+            }
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
         }
+#endif
 
         return;
     }
@@ -3453,6 +3507,14 @@
     wev->handler = ngx_http_empty_handler;
 
     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_del_async_conn) {
+            if (c->num_async_fds) {
+                ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                c->num_async_fds--;
+            }
+        }
+#endif
         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
             ngx_http_close_request(r, 0);
             return;
diff -r 2245324a507a -r 301a837387ed src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/http/ngx_http_upstream.c	Tue Sep 07 16:29:07 2021 +0800
@@ -1336,7 +1336,14 @@
         if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
 
             event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
-
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+            if (c->async_enable && ngx_del_async_conn) {
+                if (c->num_async_fds) {
+                    ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                    c->num_async_fds--;
+                }
+            }
+#endif
             if (ngx_del_event(ev, event, 0) != NGX_OK) {
                 ngx_http_upstream_finalize_request(r, u,
                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -1463,7 +1470,14 @@
     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
 
         event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
-
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+        if (c->async_enable && ngx_del_async_conn) {
+            if (c->num_async_fds) {
+                ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                c->num_async_fds--;
+            }
+        }
+#endif
         if (ngx_del_event(ev, event, 0) != NGX_OK) {
             ngx_http_upstream_finalize_request(r, u,
                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -1907,7 +1921,12 @@
                    "upstream SSL server name: \"%s\"", name.data);
 
     if (SSL_set_tlsext_host_name(c->ssl->connection,
-                                 (char *) name.data)
+#ifdef OPENSSL_IS_BORINGSSL
+                                 (const char *)
+#else
+                                 (char *)
+#endif
+                                 name.data)
         == 0)
     {
         ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0,
diff -r 2245324a507a -r 301a837387ed src/os/unix/ngx_process_cycle.c
--- a/src/os/unix/ngx_process_cycle.c	Thu Sep 02 12:25:37 2021 +0300
+++ b/src/os/unix/ngx_process_cycle.c	Tue Sep 07 16:29:07 2021 +0800
@@ -595,6 +595,14 @@
                 && !ngx_terminate
                 && !ngx_quit)
             {
+
+#if (NGX_SSL)
+                /* Delay added to give KAE Driver time to cleanup
+                * if worker exit with non-zero code. */
+                if(ngx_processes[i].status != 0) {
+                    usleep(2000000);
+                }
+#endif
                 if (ngx_spawn_process(cycle, ngx_processes[i].proc,
                                       ngx_processes[i].data,
                                       ngx_processes[i].name, i)
@@ -1031,6 +1039,14 @@
         if (n == NGX_ERROR) {
 
             if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
+#if (NGX_HTTP_SSL && NGX_SSL_ASYNC)
+            if (c->async_enable && ngx_del_async_conn) {
+                if (c->num_async_fds) {
+                    ngx_del_async_conn(c, NGX_DISABLE_EVENT);
+                    c->num_async_fds--;
+                }
+            }
+#endif
                 ngx_del_conn(c, 0);
             }
 


More information about the nginx-devel mailing list