summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzat Khuzhin <azat@libevent.org>2023-05-14 16:53:13 +0200
committerAzat Khuzhin <azat@libevent.org>2023-05-14 16:53:13 +0200
commit7652cf4068f77905a56b9165455ec7e90917ec31 (patch)
treed8069f294310ef5c1dee9b318edafae57ae53d47
parent6375dcb46db4bb05c9c19c980f3ed6d0ff9b1065 (diff)
downloadlibevent-7652cf4068f77905a56b9165455ec7e90917ec31.tar.gz
ssl: do not triger EOF if some data had been successfully read
Previously in case when evbuffer_reserve_space() returns > 1, but it was able to read only 1 IO vector, it will try to read the next one, got 0 (EOF for mbedTLS or SSL_ERROR_ZERO_RETURN for OpenSSL) and will trigger EOF, while instead, it should trigger EV_READ w/o EOF and only after EOF.
-rw-r--r--bufferevent_mbedtls.c6
-rw-r--r--bufferevent_openssl.c8
-rw-r--r--bufferevent_ssl.c5
-rw-r--r--ssl-compat.h1
4 files changed, 19 insertions, 1 deletions
diff --git a/bufferevent_mbedtls.c b/bufferevent_mbedtls.c
index b0e960fa..765d00be 100644
--- a/bufferevent_mbedtls.c
+++ b/bufferevent_mbedtls.c
@@ -136,6 +136,11 @@ mbedtls_is_want_write(int err)
{
return err == MBEDTLS_ERR_SSL_WANT_WRITE;
}
+static int mbedtls_err_is_ok(int err)
+{
+ /* What mbedtls_ssl_read() returns when the we can proceed existing data */
+ return err == 0;
+}
static evutil_socket_t
be_mbedtls_get_fd(void *ssl)
@@ -324,6 +329,7 @@ static struct le_ssl_ops le_mbedtls_ops = {
mbedtls_handshake_is_ok,
mbedtls_is_want_read,
mbedtls_is_want_write,
+ mbedtls_err_is_ok,
be_mbedtls_get_fd,
be_mbedtls_bio_set_fd,
(void (*)(struct bufferevent_ssl *))mbedtls_set_ssl_noops,
diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c
index f5d0808c..4ef3925a 100644
--- a/bufferevent_openssl.c
+++ b/bufferevent_openssl.c
@@ -346,6 +346,13 @@ SSL_handshake_is_ok(int err)
}
static int
+SSL_err_is_ok(int err)
+{
+ /* What SSL_read() returns when the we can proceed existing data */
+ return err == SSL_ERROR_ZERO_RETURN;
+}
+
+static int
SSL_is_want_read(int err)
{
return err == SSL_ERROR_WANT_READ;
@@ -417,6 +424,7 @@ static struct le_ssl_ops le_openssl_ops = {
SSL_handshake_is_ok,
SSL_is_want_read,
SSL_is_want_write,
+ SSL_err_is_ok,
(int (*)(void *))be_openssl_get_fd,
be_openssl_bio_set_fd,
init_bio_counts,
diff --git a/bufferevent_ssl.c b/bufferevent_ssl.c
index 847c8b67..17046b82 100644
--- a/bufferevent_ssl.c
+++ b/bufferevent_ssl.c
@@ -284,7 +284,10 @@ do_read(struct bufferevent_ssl *bev_ssl, int n_to_read) {
} else {
int err = bev_ssl->ssl_ops->get_error(bev_ssl->ssl, r);
bev_ssl->ssl_ops->print_err(err);
- if (bev_ssl->ssl_ops->err_is_want_read(err)) {
+ if (bev_ssl->ssl_ops->err_is_ok(err) && result & OP_MADE_PROGRESS) {
+ /* Process existing data */
+ break;
+ } else if (bev_ssl->ssl_ops->err_is_want_read(err)) {
/* Can't read until underlying has more data. */
if (bev_ssl->read_blocked_on_write)
if (clear_rbow(bev_ssl) < 0)
diff --git a/ssl-compat.h b/ssl-compat.h
index a556f4c0..146fdaf3 100644
--- a/ssl-compat.h
+++ b/ssl-compat.h
@@ -23,6 +23,7 @@ struct le_ssl_ops {
int (*handshake_is_ok)(int err);
int (*err_is_want_read)(int err);
int (*err_is_want_write)(int err);
+ int (*err_is_ok)(int err);
evutil_socket_t (*get_fd)(void *ssl);
int (*bio_set_fd)(struct bufferevent_ssl *ssl, evutil_socket_t fd);
void (*init_bio_counts)(struct bufferevent_ssl *bev);