[TLS] write_cq_ssl defer remove_finished_chunks

not expecting 0-length chunks, but handle within loops as cold path

mark some cold paths in read_cq_ssl and write_cq_ssl callback funcs
This commit is contained in:
Glenn Strauss 2021-05-24 01:33:06 -04:00
parent 8b96169b68
commit 4a246a8754
6 changed files with 69 additions and 47 deletions

View File

@ -1198,6 +1198,8 @@ chunkqueue_peek_data (chunkqueue * const cq,
off_t len = c->file.length - c->offset;
if (len > (off_t)space)
len = (off_t)space;
if (0 == len)
break;
if (-1 == lseek(c->file.fd, offset, SEEK_SET)) {
log_perror(errh, __FILE__, __LINE__, "lseek(\"%s\")",

View File

@ -2413,10 +2413,10 @@ mod_gnutls_close_notify(handler_ctx *hctx);
static int
connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
gnutls_session_t ssl = hctx->ssl;
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
gnutls_session_t const ssl = hctx->ssl;
if (!hctx->handshake) return 0;
if (hctx->pending_write) {
@ -2428,9 +2428,8 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
chunkqueue_mark_written(cq, wr);
}
if (0 != hctx->close_notify) return mod_gnutls_close_notify(hctx);
chunkqueue_remove_finished_chunks(cq);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_gnutls_close_notify(hctx);
const size_t lim = gnutls_record_get_max_size(ssl);
@ -2453,6 +2452,10 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
int wr;
if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
if (__builtin_expect( (0 == data_len), 0)) {
chunkqueue_remove_finished_chunks(cq);
continue;
}
/* gnutls_record_send() copies the data, up to max record size, but if
* (temporarily) unable to write the entire record, it is documented
@ -2514,13 +2517,14 @@ mod_gnutls_ssl_handshake (handler_ctx *hctx)
static int
connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
UNUSED(max_bytes);
if (0 != hctx->close_notify) return mod_gnutls_close_notify(hctx);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_gnutls_close_notify(hctx);
if (!hctx->handshake) {
int rc = mod_gnutls_ssl_handshake(hctx);

View File

@ -1952,9 +1952,9 @@ mod_mbedtls_close_notify(handler_ctx *hctx);
static int
connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
mbedtls_ssl_context * const ssl = &hctx->ssl;
if (hctx->pending_write) {
@ -1971,9 +1971,8 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
chunkqueue_mark_written(cq, wr);
}
if (0 != hctx->close_notify) return mod_mbedtls_close_notify(hctx);
chunkqueue_remove_finished_chunks(cq);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_mbedtls_close_notify(hctx);
const int lim = mbedtls_ssl_get_max_out_record_payload(ssl);
if (lim < 0) return mod_mbedtls_ssl_write_err(con, hctx, lim, 0);
@ -1987,6 +1986,10 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
int wr;
if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
if (__builtin_expect( (0 == data_len), 0)) {
chunkqueue_remove_finished_chunks(cq);
continue;
}
/* mbedtls_ssl_write() copies the data, up to max record size, but if
* (temporarily) unable to write the entire record, it is documented
@ -2152,16 +2155,17 @@ mod_mbedtls_ssl_handshake (handler_ctx *hctx)
static int
connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
int len;
char *mem = NULL;
size_t mem_len = 0;
UNUSED(max_bytes);
if (0 != hctx->close_notify) return mod_mbedtls_close_notify(hctx);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_mbedtls_close_notify(hctx);
if (!hctx->handshake_done) {
int rc = mod_mbedtls_ssl_handshake(hctx);

View File

@ -2200,15 +2200,14 @@ mod_nss_close_notify(handler_ctx *hctx);
static int
connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
PRFileDesc *ssl = hctx->ssl;
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
PRFileDesc * const ssl = hctx->ssl;
log_error_st * const errh = hctx->errh;
if (0 != hctx->close_notify) return mod_nss_close_notify(hctx);
chunkqueue_remove_finished_chunks(cq);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_nss_close_notify(hctx);
/* future: for efficiency/performance might consider using NSS
* PR_Writev() PR_TransmitFile() PR_SendFile()
@ -2222,6 +2221,10 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
int wr;
if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
if (__builtin_expect( (0 == data_len), 0)) {
chunkqueue_remove_finished_chunks(cq);
continue;
}
/*(if partial write occurred, expect that subsequent writes will have
* at least that much data available from chunkqueue_peek_data(), which
@ -2263,15 +2266,16 @@ mod_nss_SSLHandshakeCallback (PRFileDesc *fd, void *arg)
static int
connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
UNUSED(max_bytes);
if (0 != hctx->close_notify) return mod_nss_close_notify(hctx);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_nss_close_notify(hctx);
PRFileDesc *ssl = hctx->ssl;
PRFileDesc * const ssl = hctx->ssl;
ssize_t len;
char *mem = NULL;
size_t mem_len = 0;

View File

@ -2978,15 +2978,14 @@ mod_openssl_close_notify(handler_ctx *hctx);
static int
connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
SSL *ssl = hctx->ssl;
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
SSL * const ssl = hctx->ssl;
log_error_st * const errh = hctx->errh;
if (0 != hctx->close_notify) return mod_openssl_close_notify(hctx);
chunkqueue_remove_finished_chunks(cq);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_openssl_close_notify(hctx);
while (max_bytes > 0 && !chunkqueue_is_empty(cq)) {
char *data = local_send_buffer;
@ -2996,6 +2995,10 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
int wr;
if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
if (__builtin_expect( (0 == data_len), 0)) {
chunkqueue_remove_finished_chunks(cq);
continue;
}
/**
* SSL_write man-page
@ -3009,7 +3012,7 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
ERR_clear_error();
wr = SSL_write(ssl, data, data_len);
if (hctx->renegotiations > 1
if (__builtin_expect( (hctx->renegotiations > 1), 0)
&& hctx->conf.ssl_disable_client_renegotiation) {
log_error(errh, __FILE__, __LINE__,
"SSL: renegotiation initiated by client, killing connection");
@ -3079,16 +3082,17 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
static int
connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
int len;
char *mem = NULL;
size_t mem_len = 0;
UNUSED(max_bytes);
if (0 != hctx->close_notify) return mod_openssl_close_notify(hctx);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_openssl_close_notify(hctx);
ERR_clear_error();
do {

View File

@ -2738,15 +2738,14 @@ mod_openssl_close_notify(handler_ctx *hctx);
static int
connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
SSL *ssl = hctx->ssl;
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
SSL * const ssl = hctx->ssl;
log_error_st * const errh = hctx->errh;
if (0 != hctx->close_notify) return mod_openssl_close_notify(hctx);
chunkqueue_remove_finished_chunks(cq);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_openssl_close_notify(hctx);
while (max_bytes > 0 && !chunkqueue_is_empty(cq)) {
char *data = local_send_buffer;
@ -2756,6 +2755,10 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
int wr;
if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
if (__builtin_expect( (0 == data_len), 0)) {
chunkqueue_remove_finished_chunks(cq);
continue;
}
/**
* SSL_write man-page
@ -2769,7 +2772,7 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
ERR_clear_error();
wr = SSL_write(ssl, data, data_len);
if (hctx->renegotiations > 1
if (__builtin_expect( (hctx->renegotiations > 1), 0)
&& hctx->conf.ssl_disable_client_renegotiation) {
log_error(errh, __FILE__, __LINE__,
"SSL: renegotiation initiated by client, killing connection");
@ -2839,16 +2842,17 @@ connection_write_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
static int
connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
{
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
int len;
char *mem = NULL;
size_t mem_len = 0;
UNUSED(max_bytes);
if (0 != hctx->close_notify) return mod_openssl_close_notify(hctx);
if (__builtin_expect( (0 != hctx->close_notify), 0))
return mod_openssl_close_notify(hctx);
ERR_clear_error();
do {