提交 ec447924 编写于 作者: M Matt Caswell

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: NViktor Dukhovni <viktor@openssl.org>
上级 35ade23b
...@@ -218,6 +218,27 @@ static int restore_errno(void) ...@@ -218,6 +218,27 @@ static int restore_errno(void)
return ret; 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 #ifndef OPENSSL_NO_PSK
/* Default PSK identity and key */ /* Default PSK identity and key */
static char *psk_identity = "Client_identity"; static char *psk_identity = "Client_identity";
...@@ -2002,7 +2023,7 @@ int s_client_main(int argc, char **argv) ...@@ -2002,7 +2023,7 @@ int s_client_main(int argc, char **argv)
reconnect--; reconnect--;
BIO_printf(bio_c_out, BIO_printf(bio_c_out,
"drop connection and then reconnect\n"); "drop connection and then reconnect\n");
SSL_shutdown(con); do_ssl_shutdown(con);
SSL_set_connect_state(con); SSL_set_connect_state(con);
SHUTDOWN(SSL_get_fd(con)); SHUTDOWN(SSL_get_fd(con));
goto re_start; goto re_start;
...@@ -2320,7 +2341,7 @@ int s_client_main(int argc, char **argv) ...@@ -2320,7 +2341,7 @@ int s_client_main(int argc, char **argv)
shut: shut:
if (in_init) if (in_init)
print_stuff(bio_c_out, con, full_log); print_stuff(bio_c_out, con, full_log);
SSL_shutdown(con); do_ssl_shutdown(con);
SHUTDOWN(SSL_get_fd(con)); SHUTDOWN(SSL_get_fd(con));
end: end:
if (con != NULL) { if (con != NULL) {
......
...@@ -190,10 +190,11 @@ struct ssl_async_args { ...@@ -190,10 +190,11 @@ struct ssl_async_args {
SSL *s; SSL *s;
void *buf; void *buf;
int num; int num;
int type; enum { READFUNC, WRITEFUNC, OTHERFUNC} type;
union { union {
int (*func1)(SSL *, void *, int); int (*func_read)(SSL *, void *, int);
int (*func2)(SSL *, const void *, int); int (*func_write)(SSL *, const void *, int);
int (*func_other)(SSL *);
} f; } f;
}; };
...@@ -1469,10 +1470,15 @@ static int ssl_io_intern(void *vargs) ...@@ -1469,10 +1470,15 @@ static int ssl_io_intern(void *vargs)
s = args->s; s = args->s;
buf = args->buf; buf = args->buf;
num = args->num; num = args->num;
if (args->type == 1) switch (args->type) {
return args->f.func1(s, buf, num); case READFUNC:
else return args->f.func_read(s, buf, num);
return args->f.func2(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) int SSL_read(SSL *s, void *buf, int num)
...@@ -1493,8 +1499,8 @@ 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.s = s;
args.buf = buf; args.buf = buf;
args.num = num; args.num = num;
args.type = 1; args.type = READFUNC;
args.f.func1 = s->method->ssl_read; args.f.func_read = s->method->ssl_read;
return ssl_start_async_job(s, &args, ssl_io_intern); return ssl_start_async_job(s, &args, ssl_io_intern);
} else { } else {
...@@ -1518,8 +1524,8 @@ int SSL_peek(SSL *s, void *buf, int num) ...@@ -1518,8 +1524,8 @@ int SSL_peek(SSL *s, void *buf, int num)
args.s = s; args.s = s;
args.buf = buf; args.buf = buf;
args.num = num; args.num = num;
args.type = 1; args.type = READFUNC;
args.f.func1 = s->method->ssl_peek; args.f.func_read = s->method->ssl_peek;
return ssl_start_async_job(s, &args, ssl_io_intern); return ssl_start_async_job(s, &args, ssl_io_intern);
} else { } else {
...@@ -1546,8 +1552,8 @@ int SSL_write(SSL *s, const void *buf, int num) ...@@ -1546,8 +1552,8 @@ int SSL_write(SSL *s, const void *buf, int num)
args.s = s; args.s = s;
args.buf = (void *)buf; args.buf = (void *)buf;
args.num = num; args.num = num;
args.type = 2; args.type = WRITEFUNC;
args.f.func2 = s->method->ssl_write; args.f.func_write = s->method->ssl_write;
return ssl_start_async_job(s, &args, ssl_io_intern); return ssl_start_async_job(s, &args, ssl_io_intern);
} else { } else {
...@@ -1569,6 +1575,18 @@ int SSL_shutdown(SSL *s) ...@@ -1569,6 +1575,18 @@ int SSL_shutdown(SSL *s)
return -1; 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); return s->method->ssl_shutdown(s);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册