aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2016-01-25 15:00:10 +0000
committerMatt Caswell <matt@openssl.org>2016-01-29 11:36:44 +0000
commitec4479249d9c0b0a9e2ba6a8c59a0ed62530e954 (patch)
tree3de699b498f28799d1ef631d70e647125bfcf859
parent35ade23b02a02b5514941586030016b67ac0934e (diff)
downloadopenssl-ec4479249d9c0b0a9e2ba6a8c59a0ed62530e954.tar.gz
Implement Async SSL_shutdown
This extends the existing async functionality to SSL_shutdown(), i.e. SSL_shutdown() can now casuse an SSL_ERROR_WANT_ASYNC error to be returned from SSL_get_error() if async mode has been enabled. Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
-rw-r--r--apps/s_client.c25
-rw-r--r--ssl/ssl_lib.c44
2 files changed, 54 insertions, 15 deletions
diff --git a/apps/s_client.c b/apps/s_client.c
index 717d7c146b..fe402ae3a8 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -218,6 +218,27 @@ static int restore_errno(void)
return ret;
}
+static void do_ssl_shutdown(SSL *ssl)
+{
+ int ret;
+
+ do {
+ /* We only do unidirectional shutdown */
+ ret = SSL_shutdown(ssl);
+ if (ret < 0) {
+ switch (SSL_get_error(ssl, ret)) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_ASYNC:
+ /* We just do busy waiting. Nothing clever */
+ continue;
+ }
+ ret = 0;
+ }
+ } while (ret < 0);
+}
+
+
#ifndef OPENSSL_NO_PSK
/* Default PSK identity and key */
static char *psk_identity = "Client_identity";
@@ -2002,7 +2023,7 @@ int s_client_main(int argc, char **argv)
reconnect--;
BIO_printf(bio_c_out,
"drop connection and then reconnect\n");
- SSL_shutdown(con);
+ do_ssl_shutdown(con);
SSL_set_connect_state(con);
SHUTDOWN(SSL_get_fd(con));
goto re_start;
@@ -2320,7 +2341,7 @@ int s_client_main(int argc, char **argv)
shut:
if (in_init)
print_stuff(bio_c_out, con, full_log);
- SSL_shutdown(con);
+ do_ssl_shutdown(con);
SHUTDOWN(SSL_get_fd(con));
end:
if (con != NULL) {
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index d29da6dfbf..a43ec52736 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -190,10 +190,11 @@ struct ssl_async_args {
SSL *s;
void *buf;
int num;
- int type;
+ enum { READFUNC, WRITEFUNC, OTHERFUNC} type;
union {
- int (*func1)(SSL *, void *, int);
- int (*func2)(SSL *, const void *, int);
+ int (*func_read)(SSL *, void *, int);
+ int (*func_write)(SSL *, const void *, int);
+ int (*func_other)(SSL *);
} f;
};
@@ -1469,10 +1470,15 @@ static int ssl_io_intern(void *vargs)
s = args->s;
buf = args->buf;
num = args->num;
- if (args->type == 1)
- return args->f.func1(s, buf, num);
- else
- return args->f.func2(s, buf, num);
+ switch (args->type) {
+ case READFUNC:
+ return args->f.func_read(s, buf, num);
+ case WRITEFUNC:
+ return args->f.func_write(s, buf, num);
+ case OTHERFUNC:
+ return args->f.func_other(s);
+ }
+ return -1;
}
int SSL_read(SSL *s, void *buf, int num)
@@ -1493,8 +1499,8 @@ int SSL_read(SSL *s, void *buf, int num)
args.s = s;
args.buf = buf;
args.num = num;
- args.type = 1;
- args.f.func1 = s->method->ssl_read;
+ args.type = READFUNC;
+ args.f.func_read = s->method->ssl_read;
return ssl_start_async_job(s, &args, ssl_io_intern);
} else {
@@ -1518,8 +1524,8 @@ int SSL_peek(SSL *s, void *buf, int num)
args.s = s;
args.buf = buf;
args.num = num;
- args.type = 1;
- args.f.func1 = s->method->ssl_peek;
+ args.type = READFUNC;
+ args.f.func_read = s->method->ssl_peek;
return ssl_start_async_job(s, &args, ssl_io_intern);
} else {
@@ -1546,8 +1552,8 @@ int SSL_write(SSL *s, const void *buf, int num)
args.s = s;
args.buf = (void *)buf;
args.num = num;
- args.type = 2;
- args.f.func2 = s->method->ssl_write;
+ args.type = WRITEFUNC;
+ args.f.func_write = s->method->ssl_write;
return ssl_start_async_job(s, &args, ssl_io_intern);
} else {
@@ -1569,6 +1575,18 @@ int SSL_shutdown(SSL *s)
return -1;
}
+ if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.type = OTHERFUNC;
+ args.f.func_other = s->method->ssl_shutdown;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_shutdown(s);
+ }
+
return s->method->ssl_shutdown(s);
}