From 62dc817cafb3f9555d835ce20927538aa73c993a Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Wed, 29 Sep 2021 09:22:28 -0400 Subject: [PATCH] [core] h2_send_cqdata() returns how much data sent --- src/connections.c | 30 ++++++++++++------------------ src/h2.c | 30 +++++++++++++++++++----------- src/h2.h | 2 +- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/connections.c b/src/connections.c index 43f8c343..87f22772 100644 --- a/src/connections.c +++ b/src/connections.c @@ -1241,7 +1241,6 @@ connection_state_machine_h2 (request_st * const h2r, connection * const con) off_t max_bytes = con->is_writable > 0 ? connection_write_throttle(con, MAX_WRITE_LIMIT) : 0; - const off_t fsize = (off_t)h2c->s_max_frame_size; const off_t cqlen = chunkqueue_length(con->write_queue); if (cqlen > 8192 && max_bytes > 65536) max_bytes = 65536; max_bytes -= cqlen; @@ -1268,30 +1267,25 @@ connection_state_machine_h2 (request_st * const h2r, connection * const con) connection_state_machine_loop(r, con); if (r->resp_header_len && !chunkqueue_is_empty(&r->write_queue) + && max_bytes && (r->resp_body_finished || (r->conf.stream_response_body & (FDEVENT_STREAM_RESPONSE |FDEVENT_STREAM_RESPONSE_BUFMIN)))) { - chunkqueue * const cq = &r->write_queue; - off_t avail = chunkqueue_length(cq); - if (avail > max_bytes) avail = max_bytes; - if (avail > fsize) avail = fsize; - if (avail > r->h2_swin) avail = r->h2_swin; - if (avail > h2r->h2_swin) avail = h2r->h2_swin; + uint32_t dlen = (uint32_t)max_bytes; + dlen = h2_send_cqdata(r, con, &r->write_queue, dlen); + max_bytes -= (off_t)dlen; - if (avail > 0) { - max_bytes -= avail; - h2_send_cqdata(r, con, cq, (uint32_t)avail); - } - - if (r->resp_body_finished && chunkqueue_is_empty(cq)) { - connection_set_state(r, CON_STATE_RESPONSE_END); - if (r->conf.log_state_handling) - connection_state_machine_loop(r, con); + if (chunkqueue_is_empty(&r->write_queue)) { + if (r->resp_body_finished) { + connection_set_state(r, CON_STATE_RESPONSE_END); + if (__builtin_expect( (r->conf.log_state_handling), 0)) + connection_state_machine_loop(r, con); + } } - else if (avail) /*(do not spin if swin empty window)*/ - resched |= (!chunkqueue_is_empty(cq)); + else if (dlen) /*(do not spin if swin empty window)*/ + resched |= 1; /*(!chunkqueue_is_empty(&r->write_queue))*/ } #if 0 diff --git a/src/h2.c b/src/h2.c index 3a978d3e..12e53086 100644 --- a/src/h2.c +++ b/src/h2.c @@ -2315,7 +2315,7 @@ h2_send_cqheaders (request_st * const r, connection * const con) #if 0 -void +uint32_t h2_send_data (request_st * const r, connection * const con, const char *data, uint32_t dlen) { /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */ @@ -2340,11 +2340,11 @@ h2_send_data (request_st * const r, connection * const con, const char *data, ui /* adjust stream and connection windows */ /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */ request_st * const h2r = &con->request; - if (r->h2_swin < 0) return; - if (h2r->h2_swin < 0) return; + if (r->h2_swin < 0) return 0; + if (h2r->h2_swin < 0) return 0; if ((int32_t)dlen > r->h2_swin) dlen = (uint32_t)r->h2_swin; if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin; - if (0 == dlen) return; + if (0 == dlen) return 0; r->h2_swin -= (int32_t)dlen; h2r->h2_swin -= (int32_t)dlen; @@ -2362,6 +2362,7 @@ h2_send_data (request_st * const r, connection * const con, const char *data, ui char * restrict ptr = b->ptr; h2con * const h2c = con->h2; const uint32_t fsize = h2c->s_max_frame_size; + uint32_t sent = 0; do { const uint32_t len = dlen < fsize ? dlen : fsize; dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/ @@ -2377,16 +2378,18 @@ h2_send_data (request_st * const r, connection * const con, const char *data, ui ptr += len + sizeof(dataframe)-3; #endif data += len; + sent += len; dlen -= len; } while (dlen); buffer_truncate(b, (uint32_t)(ptr - b->ptr)); chunkqueue_append_buffer_commit(con->write_queue); + return sent; } #endif -void +uint32_t h2_send_cqdata (request_st * const r, connection * const con, chunkqueue * const cq, uint32_t dlen) { /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */ @@ -2411,13 +2414,13 @@ h2_send_cqdata (request_st * const r, connection * const con, chunkqueue * const /* adjust stream and connection windows */ /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */ request_st * const h2r = &con->request; - if (r->h2_swin < 0) return; - if (h2r->h2_swin < 0) return; + if (r->h2_swin < 0) return 0; + if (h2r->h2_swin < 0) return 0; if ((int32_t)dlen > r->h2_swin) dlen = (uint32_t)r->h2_swin; if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin; - if (0 == dlen) return; - r->h2_swin -= (int32_t)dlen; - h2r->h2_swin -= (int32_t)dlen; + const uint32_t cqlen = (uint32_t)chunkqueue_length(cq); + if (dlen > cqlen) dlen = cqlen; + if (0 == dlen) return 0; /* XXX: future: should have an interface which processes chunkqueue * and takes string refs to mmap FILE_CHUNK to avoid extra copying @@ -2425,16 +2428,21 @@ h2_send_cqdata (request_st * const r, connection * const con, chunkqueue * const h2con * const h2c = con->h2; const uint32_t fsize = h2c->s_max_frame_size; + uint32_t sent = 0; do { const uint32_t len = dlen < fsize ? dlen : fsize; + dlen -= len; + sent += len; dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/ dataframe.c[4] = (len >> 8) & 0xFF; dataframe.c[5] = (len ) & 0xFF; chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/ (const char *)dataframe.c+3, sizeof(dataframe)-3); chunkqueue_steal(con->write_queue, cq, (off_t)len); - dlen -= len; } while (dlen); + r->h2_swin -= (int32_t)sent; + h2r->h2_swin -= (int32_t)sent; + return sent; } diff --git a/src/h2.h b/src/h2.h index 7c3d6266..d53eb57b 100644 --- a/src/h2.h +++ b/src/h2.h @@ -101,7 +101,7 @@ void h2_send_100_continue (request_st *r, connection *con); void h2_send_headers (request_st *r, connection *con); -void h2_send_cqdata (request_st *r, connection *con, struct chunkqueue *cq, uint32_t dlen); +uint32_t h2_send_cqdata (request_st *r, connection *con, struct chunkqueue *cq, uint32_t dlen); void h2_send_end_stream (request_st *r, connection *con);