Commit ec447924 authored by Matt Caswell's avatar Matt Caswell
Browse files

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: default avatarViktor Dukhovni <viktor@openssl.org>
parent 35ade23b
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -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) {
+31 −13
Original line number Diff line number Diff line
@@ -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);
}