From a490172d6938943ce5af81e147a64b3f14870144 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Sat, 31 Oct 2020 22:53:31 +0300 Subject: [PATCH] Introduce new BUFFEREVENT_SSL_BATCH_WRITE flag to avoid Nagle effect in SSL --- bufferevent_ssl.c | 9 +++++++-- include/event2/bufferevent_ssl.h | 12 ++++++++++++ test/regress_ssl.c | 9 +++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/bufferevent_ssl.c b/bufferevent_ssl.c index dd013c98..b34af9af 100644 --- a/bufferevent_ssl.c +++ b/bufferevent_ssl.c @@ -328,6 +328,11 @@ do_write(struct bufferevent_ssl *bev_ssl, int atmost) else atmost = bufferevent_get_write_max_(&bev_ssl->bev); + if (bev_ssl->flags & BUFFEREVENT_SSL_BATCH_WRITE) { + /* Try to send as many as we can to avoid Nagle effect */ + evbuffer_pullup(output, -1); + } + n = evbuffer_peek(output, atmost, NULL, space, 8); if (n < 0) return OP_ERR | result; @@ -1084,7 +1089,7 @@ ev_uint64_t bufferevent_ssl_set_flags(struct bufferevent *bev, ev_uint64_t flags ev_uint64_t old_flags = EV_UINT64_MAX; struct bufferevent_ssl *bev_ssl; - flags &= (BUFFEREVENT_SSL_DIRTY_SHUTDOWN); + flags &= (BUFFEREVENT_SSL_DIRTY_SHUTDOWN|BUFFEREVENT_SSL_BATCH_WRITE); if (!flags) return old_flags; @@ -1103,7 +1108,7 @@ ev_uint64_t bufferevent_ssl_clear_flags(struct bufferevent *bev, ev_uint64_t fla ev_uint64_t old_flags = EV_UINT64_MAX; struct bufferevent_ssl *bev_ssl; - flags &= (BUFFEREVENT_SSL_DIRTY_SHUTDOWN); + flags &= (BUFFEREVENT_SSL_DIRTY_SHUTDOWN|BUFFEREVENT_SSL_BATCH_WRITE); if (!flags) return old_flags; diff --git a/include/event2/bufferevent_ssl.h b/include/event2/bufferevent_ssl.h index 5abcb790..355b632d 100644 --- a/include/event2/bufferevent_ssl.h +++ b/include/event2/bufferevent_ssl.h @@ -65,6 +65,18 @@ enum bufferevent_ssl_state { not to use SSL 2.) */ #define BUFFEREVENT_SSL_DIRTY_SHUTDOWN 1 +/** Control writes in the SSL bufferevents. + + By default SSL bufferevent will peek bytes from the buffer as the arrived. + with respect to the segment boundaries in the buffer. + However, by ignoring these segment boundaries number of packets to send + can be decreased. + + This flags will ignore the segment boundaries. + + Useful in conjunction with http layer. +*/ +#define BUFFEREVENT_SSL_BATCH_WRITE 2 #if defined(EVENT__HAVE_OPENSSL) || defined(EVENT_IN_DOXYGEN_) /* This is what openssl's SSL objects are underneath. */ diff --git a/test/regress_ssl.c b/test/regress_ssl.c index b5c37b80..447a4c34 100644 --- a/test/regress_ssl.c +++ b/test/regress_ssl.c @@ -128,6 +128,8 @@ enum regress_openssl_type REGRESS_OPENSSL_CLIENT_WRITE = 2048, REGRESS_DEFERRED_CALLBACKS = 4096, + + REGRESS_OPENSSL_BATCH_WRITE = 8192, }; static void @@ -299,6 +301,11 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out, bufferevent_ssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown); bufferevent_ssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown); + + if (REGRESS_OPENSSL_BATCH_WRITE) { + bufferevent_ssl_set_flags(*bev1_out, BUFFEREVENT_SSL_BATCH_WRITE); + bufferevent_ssl_set_flags(*bev2_out, BUFFEREVENT_SSL_BATCH_WRITE); + } } static void @@ -730,6 +737,8 @@ struct testcase_t TESTCASES_NAME[] = { #define T(a) ((void *)(a)) { "bufferevent_socketpair", regress_bufferevent_openssl, TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) }, + { "bufferevent_socketpair_batch_write", regress_bufferevent_openssl, + TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_BATCH_WRITE) }, { "bufferevent_socketpair_write_after_connect", regress_bufferevent_openssl, TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR|REGRESS_OPENSSL_CLIENT_WRITE) }, -- 2.40.0