Initial Async notify code changes
authorMatt Caswell <matt@openssl.org>
Fri, 24 Jul 2015 07:15:31 +0000 (08:15 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 20 Nov 2015 23:33:46 +0000 (23:33 +0000)
Initial API implemented for notifying applications that an ASYNC_JOB
has completed. Currently only s_server is using this. The Dummy Async
engine "cheats" in that it notifies that it has completed *before* it
pauses the job. A normal async engine would not do that.

Only the posix version of this has been implemented so far, so it will
probably fail to compile on Windows at the moment.

Reviewed-by: Rich Salz <rsalz@openssl.org>
apps/s_server.c
crypto/async/arch/async_posix.c
crypto/async/arch/async_posix.h
crypto/async/async.c
crypto/async/async_locl.h
engines/e_dasync.c
include/openssl/async.h
include/openssl/ssl.h
ssl/ssl_lib.c

index 6fb8f675a3733d237a779f5fdf6d04fa0f09be22..75a3ba0a360038b38e27d33a874648bc13b89d80 100644 (file)
@@ -194,6 +194,7 @@ typedef unsigned int u_int;
 static RSA *tmp_rsa_cb(SSL *s, int is_export, int keylength);
 #endif
 static int not_resumable_sess_cb(SSL *s, int is_forward_secure);
 static RSA *tmp_rsa_cb(SSL *s, int is_export, int keylength);
 #endif
 static int not_resumable_sess_cb(SSL *s, int is_forward_secure);
+static void wait_for_async(SSL *s);
 static int sv_body(char *hostname, int s, int stype, unsigned char *context);
 static int www_body(char *hostname, int s, int stype, unsigned char *context);
 static int rev_body(char *hostname, int s, int stype, unsigned char *context);
 static int sv_body(char *hostname, int s, int stype, unsigned char *context);
 static int www_body(char *hostname, int s, int stype, unsigned char *context);
 static int rev_body(char *hostname, int s, int stype, unsigned char *context);
@@ -1735,7 +1736,7 @@ int s_server_main(int argc, char *argv[])
             SSL_CTX_sess_set_cache_size(ctx2, 128);
 
         if (async)
             SSL_CTX_sess_set_cache_size(ctx2, 128);
 
         if (async)
-                       SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
+            SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
 
         if ((!SSL_CTX_load_verify_locations(ctx2, CAfile, CApath)) ||
             (!SSL_CTX_set_default_verify_paths(ctx2))) {
 
         if ((!SSL_CTX_load_verify_locations(ctx2, CAfile, CApath)) ||
             (!SSL_CTX_set_default_verify_paths(ctx2))) {
@@ -2007,6 +2008,21 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
                SSL_CTX_sess_get_cache_size(ssl_ctx));
 }
 
                SSL_CTX_sess_get_cache_size(ssl_ctx));
 }
 
+static void wait_for_async(SSL *s)
+{
+    int width, fd;
+    fd_set asyncfds;
+
+    fd = SSL_get_async_wait_fd(s);
+    if (!fd)
+        return;
+
+    width = fd + 1;
+    FD_ZERO(&asyncfds);
+    openssl_fdset(fd, &asyncfds);
+    select(width, (void *)&asyncfds, NULL, NULL, NULL);
+}
+
 static int sv_body(char *hostname, int s, int stype, unsigned char *context)
 {
     char *buf = NULL;
 static int sv_body(char *hostname, int s, int stype, unsigned char *context)
 {
     char *buf = NULL;
@@ -2302,6 +2318,7 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
                     break;
                 case SSL_ERROR_WANT_ASYNC:
                     BIO_printf(bio_s_out, "Write BLOCK (Async)\n");
                     break;
                 case SSL_ERROR_WANT_ASYNC:
                     BIO_printf(bio_s_out, "Write BLOCK (Async)\n");
+                    wait_for_async(con);
                     break;
                 case SSL_ERROR_WANT_WRITE:
                 case SSL_ERROR_WANT_READ:
                     break;
                 case SSL_ERROR_WANT_WRITE:
                 case SSL_ERROR_WANT_READ:
@@ -2368,6 +2385,9 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
                         goto again;
                     break;
                 case SSL_ERROR_WANT_ASYNC:
                         goto again;
                     break;
                 case SSL_ERROR_WANT_ASYNC:
+                    BIO_printf(bio_s_out, "Read BLOCK (Async)\n");
+                    wait_for_async(con);
+                    break;
                 case SSL_ERROR_WANT_WRITE:
                 case SSL_ERROR_WANT_READ:
                     BIO_printf(bio_s_out, "Read BLOCK\n");
                 case SSL_ERROR_WANT_WRITE:
                 case SSL_ERROR_WANT_READ:
                     BIO_printf(bio_s_out, "Read BLOCK\n");
index bb799e54f8f32bb30b0b1c9473f772c739309ee7..8474ea4ba1b3abab767271d56058e3a21409446e 100644 (file)
@@ -57,6 +57,7 @@
 #ifdef ASYNC_SYSV
 # include <stddef.h>
 # include <ucontext.h>
 #ifdef ASYNC_SYSV
 # include <stddef.h>
 # include <ucontext.h>
+# include <unistd.h>
 # include <openssl/crypto.h>
 # include <openssl/async.h>
 
 # include <openssl/crypto.h>
 # include <openssl/async.h>
 
@@ -85,4 +86,29 @@ void ASYNC_FIBRE_free(ASYNC_FIBRE *fibre)
     if (fibre->fibre.uc_stack.ss_sp)
         OPENSSL_free(fibre->fibre.uc_stack.ss_sp);
 }
     if (fibre->fibre.uc_stack.ss_sp)
         OPENSSL_free(fibre->fibre.uc_stack.ss_sp);
 }
+
+int async_pipe(int *pipefds)
+{
+    if (pipe(pipefds) == 0)
+        return 1;
+
+    return 0;
+}
+
+int async_write1(int fd, const void *buf)
+{
+    if (write(fd, buf, 1) > 0)
+        return 1;
+
+    return 0;
+}
+
+int async_read1(int fd, void *buf)
+{
+    if (read(fd, buf, 1) > 0)
+        return 1;
+
+    return 0;
+}
+
 #endif
 #endif
index 43cea6d9b0b18ffed7492dde1d0e520066e39c53..7b8e905bec8f7ad1f76d7f5d57d159270c3041eb 100644 (file)
@@ -99,5 +99,10 @@ static inline int ASYNC_FIBRE_swapcontext(ASYNC_FIBRE *o, ASYNC_FIBRE *n, int r)
 int ASYNC_FIBRE_init(ASYNC_FIBRE *fibre);
 void ASYNC_FIBRE_free(ASYNC_FIBRE *fibre);
 
 int ASYNC_FIBRE_init(ASYNC_FIBRE *fibre);
 void ASYNC_FIBRE_free(ASYNC_FIBRE *fibre);
 
+int async_pipe(int *pipefds);
+int async_write1(int fd, const void *buf);
+int async_read1(int fd, void *buf);
+
+
 # endif
 #endif
 # endif
 #endif
index 6fed1979f93317a530240837b673ac61b7808768..bf026ee9aab79863b94cae207307947760b5b40b 100644 (file)
@@ -106,11 +106,21 @@ static int ASYNC_CTX_free(void)
 static ASYNC_JOB *ASYNC_JOB_new(void)
 {
     ASYNC_JOB *job = NULL;
 static ASYNC_JOB *ASYNC_JOB_new(void)
 {
     ASYNC_JOB *job = NULL;
+    int pipefds[2];
 
     if(!(job = OPENSSL_malloc(sizeof (ASYNC_JOB)))) {
         return NULL;
     }
 
 
     if(!(job = OPENSSL_malloc(sizeof (ASYNC_JOB)))) {
         return NULL;
     }
 
+    if(!async_pipe(pipefds)) {
+        OPENSSL_free(job);
+        return NULL;
+    }
+
+    job->wake_set = 0;
+    job->wait_fd = pipefds[0];
+    job->wake_fd = pipefds[1];
+
     job->status = ASYNC_JOB_RUNNING;
     job->funcargs = NULL;
 
     job->status = ASYNC_JOB_RUNNING;
     job->funcargs = NULL;
 
@@ -335,3 +345,36 @@ void ASYNC_free_pool(void)
     } while (job);
     sk_ASYNC_JOB_free(pool);
 }
     } while (job);
     sk_ASYNC_JOB_free(pool);
 }
+
+ASYNC_JOB *ASYNC_get_current_job(void)
+{
+    ASYNC_CTX *ctx;
+    if((ctx = ASYNC_get_ctx()) == NULL)
+        return NULL;
+
+    return ctx->currjob;
+}
+
+int ASYNC_get_wait_fd(ASYNC_JOB *job)
+{
+    return job->wait_fd;
+}
+
+void ASYNC_wake(ASYNC_JOB *job)
+{
+    char dummy = 0;
+
+    if (job->wake_set)
+        return;
+    async_write1(job->wake_fd, &dummy);
+    job->wake_set = 1;
+}
+
+void ASYNC_clear_wake(ASYNC_JOB *job)
+{
+    char dummy = 0;
+    if (!job->wake_set)
+        return;
+    async_read1(job->wait_fd, &dummy);
+    job->wake_set = 0;
+}
index 4a6cb3e2c59fe23df84b943af2e13c1e328a787e..56480c8b0e129eaa9ce6b102428767740c66a547 100644 (file)
@@ -70,6 +70,9 @@ struct async_job_st {
     void *funcargs;
     int ret;
     int status;
     void *funcargs;
     int ret;
     int status;
+    int wake_set;
+    int wait_fd;
+    int wake_fd;
 };
 
 void ASYNC_start_func(void);
 };
 
 void ASYNC_start_func(void);
index 6c41f7522d611a943eb83269e9939631a1380e64..9e0ed1b492c95b03fea79911dd8dd3b3f04ec150 100644 (file)
@@ -82,6 +82,7 @@ static int dasync_digests(ENGINE *e, const EVP_MD **digest,
 
 static int dasync_digest_nids[] = { NID_sha1, 0 };
 
 
 static int dasync_digest_nids[] = { NID_sha1, 0 };
 
+static void dummy_pause_job(void);
 
 /* SHA1 */
 static int digest_sha1_init(EVP_MD_CTX *ctx);
 
 /* SHA1 */
 static int digest_sha1_init(EVP_MD_CTX *ctx);
@@ -234,6 +235,25 @@ static int dasync_digests(ENGINE *e, const EVP_MD **digest,
     return ok;
 }
 
     return ok;
 }
 
+static void dummy_pause_job(void) {
+    ASYNC_JOB *job;
+
+    if ((job = ASYNC_get_current_job()) == NULL)
+        return;
+
+    /*
+     * In the Dummy async engine we are cheating. We signal that the job
+     * is complete by waking it before the call to ASYNC_pause_job(). A real
+     * async engine would only wake when the job was actually complete
+     */
+    ASYNC_wake(job);
+
+    /* Ignore errors - we carry on anyway */
+    ASYNC_pause_job();
+
+    ASYNC_clear_wake(job);
+}
+
 
 /*
  * SHA1 implementation. At the moment we just defer to the standard
 
 /*
  * SHA1 implementation. At the moment we just defer to the standard
@@ -243,8 +263,7 @@ static int dasync_digests(ENGINE *e, const EVP_MD **digest,
 #define data(ctx) ((SHA_CTX *)(ctx)->md_data)
 static int digest_sha1_init(EVP_MD_CTX *ctx)
 {
 #define data(ctx) ((SHA_CTX *)(ctx)->md_data)
 static int digest_sha1_init(EVP_MD_CTX *ctx)
 {
-    /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
 
     return SHA1_Init(data(ctx));
 }
 
     return SHA1_Init(data(ctx));
 }
@@ -252,16 +271,14 @@ static int digest_sha1_init(EVP_MD_CTX *ctx)
 static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data,
                              unsigned long count)
 {
 static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data,
                              unsigned long count)
 {
-    /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
 
     return SHA1_Update(data(ctx), data, (size_t)count);
 }
 
 static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
 {
 
     return SHA1_Update(data(ctx), data, (size_t)count);
 }
 
 static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
 {
-    /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
 
     return SHA1_Final(md, data(ctx));
 }
 
     return SHA1_Final(md, data(ctx));
 }
@@ -273,14 +290,14 @@ static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
 static int dasync_pub_enc(int flen, const unsigned char *from,
                     unsigned char *to, RSA *rsa, int padding) {
     /* Ignore errors - we carry on anyway */
 static int dasync_pub_enc(int flen, const unsigned char *from,
                     unsigned char *to, RSA *rsa, int padding) {
     /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
     return RSA_PKCS1_OpenSSL()->rsa_pub_enc(flen, from, to, rsa, padding);
 }
 
 static int dasync_pub_dec(int flen, const unsigned char *from,
                     unsigned char *to, RSA *rsa, int padding) {
     /* Ignore errors - we carry on anyway */
     return RSA_PKCS1_OpenSSL()->rsa_pub_enc(flen, from, to, rsa, padding);
 }
 
 static int dasync_pub_dec(int flen, const unsigned char *from,
                     unsigned char *to, RSA *rsa, int padding) {
     /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
     return RSA_PKCS1_OpenSSL()->rsa_pub_dec(flen, from, to, rsa, padding);
 }
 
     return RSA_PKCS1_OpenSSL()->rsa_pub_dec(flen, from, to, rsa, padding);
 }
 
@@ -288,7 +305,7 @@ static int dasync_rsa_priv_enc(int flen, const unsigned char *from,
                       unsigned char *to, RSA *rsa, int padding)
 {
     /* Ignore errors - we carry on anyway */
                       unsigned char *to, RSA *rsa, int padding)
 {
     /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
     return RSA_PKCS1_OpenSSL()->rsa_priv_enc(flen, from, to, rsa, padding);
 }
 
     return RSA_PKCS1_OpenSSL()->rsa_priv_enc(flen, from, to, rsa, padding);
 }
 
@@ -296,14 +313,14 @@ static int dasync_rsa_priv_dec(int flen, const unsigned char *from,
                       unsigned char *to, RSA *rsa, int padding)
 {
     /* Ignore errors - we carry on anyway */
                       unsigned char *to, RSA *rsa, int padding)
 {
     /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
     return RSA_PKCS1_OpenSSL()->rsa_priv_dec(flen, from, to, rsa, padding);
 }
 
 static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
 {
     /* Ignore errors - we carry on anyway */
     return RSA_PKCS1_OpenSSL()->rsa_priv_dec(flen, from, to, rsa, padding);
 }
 
 static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
 {
     /* Ignore errors - we carry on anyway */
-    ASYNC_pause_job();
+    dummy_pause_job();
     return RSA_PKCS1_OpenSSL()->rsa_mod_exp(r0, I, rsa, ctx);
 }
 
     return RSA_PKCS1_OpenSSL()->rsa_mod_exp(r0, I, rsa, ctx);
 }
 
index 1cd799202fdaa7bdad3fb15c1593473853f03531..45e2f6e206bd0acdf1ad06d37ee67e5ed32a62af 100644 (file)
@@ -75,6 +75,11 @@ int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *),
 int ASYNC_pause_job(void);
 int ASYNC_in_job(void);
 
 int ASYNC_pause_job(void);
 int ASYNC_in_job(void);
 
+int ASYNC_get_wait_fd(ASYNC_JOB *job);
+ASYNC_JOB *ASYNC_get_current_job(void);
+void ASYNC_wake(ASYNC_JOB *job);
+void ASYNC_clear_wake(ASYNC_JOB *job);
+
 # ifdef  __cplusplus
 }
 # endif
 # ifdef  __cplusplus
 }
 # endif
index eaac1800374f0d0a16ffe3c3e6a0ce8ac654b1c6..ed9bc5bc5717a96e907569ba35e8c75e45abff6e 100644 (file)
@@ -1572,6 +1572,7 @@ __owur char *SSL_get_srp_userinfo(SSL *s);
 void SSL_certs_clear(SSL *s);
 void SSL_free(SSL *ssl);
 __owur int SSL_waiting_for_async(SSL *s);
 void SSL_certs_clear(SSL *s);
 void SSL_free(SSL *ssl);
 __owur int SSL_waiting_for_async(SSL *s);
+__owur int SSL_get_async_wait_fd(SSL *s);
 __owur int SSL_accept(SSL *ssl);
 __owur int SSL_connect(SSL *ssl);
 __owur int SSL_read(SSL *ssl, void *buf, int num);
 __owur int SSL_accept(SSL *ssl);
 __owur int SSL_connect(SSL *ssl);
 __owur int SSL_read(SSL *ssl, void *buf, int num);
index 31adbe473e37afb7103273a1aeb5885956ac5297..270a908a3ec4e63e8758922d6d8e3d8fe3677bb3 100644 (file)
@@ -931,6 +931,14 @@ int SSL_waiting_for_async(SSL *s)
     return 0;
 }
 
     return 0;
 }
 
+int SSL_get_async_wait_fd(SSL *s)
+{
+    if (!s->job)
+        return 0;
+
+    return ASYNC_get_wait_fd(s->job);
+}
+
 static int ssl_accept_intern(void *vargs)
 {
     struct ssl_async_args *args;
 static int ssl_accept_intern(void *vargs)
 {
     struct ssl_async_args *args;