Skip to content

Commit

Permalink
Merge r1918003, r1918022, r1918035, r1918078, r1918098, r1918099, r19…
Browse files Browse the repository at this point in the history
…18257, r1918482, r1918483, r1918491, r1919141, r1919148 from trunk

 *) mod_http2: sync with module's github.
    - on newer HTTPD versions, return connection monitoring
      to the event MPM when block on client updates.
      2.4.x versions still treat connections in the event
      MPM as KeepAlive and purge them on load in the middle
      of response processing.
    - spelling fixes
    - support for yield calls in c2 "network" filter


 mpm_event,core: Handle async POLLIN/POLLOUT in CONN_STATE_PROCESS state.

* include/httpd.h:
  Rename CONN_STATE_CHECK_REQUEST_LINE_READABLE to CONN_STATE_KEEPALIVE
  and CONN_STATE_READ_REQUEST_LINE to CONN_STATE_PROCESS, keeping the
  old enums as aliases. Rework comments about each state.

* server/mpm/event/event.c:
  Use the new states names.
  Let the process_connection hooks return CONN_STATE_PROCESS for mpm_event
  to POLLIN or POLLOUT depending on c->cs->sense being CONN_SENSE_WANT_READ
  or CONN_SENSE_WANT_WRITE respectively.
  Remove (ab)use of CONN_STATE_WRITE_COMPLETION with CONN_SENSE_WANT_READ to
  mean poll() for read (and the need for the obscure c->clogging_input_filters
  to make it work as expected). This is what CONN_STATE_PROCESS is for now.
  Update the comment about the states that can be returned by process_connection
  hooks (and their usage).
  Use the same queue (process_q renamed from write_completion_q) for polling
  connections in both CONN_STATE_PROCESS and CONN_STATE_WRITE_COMPLETION
  states since they both use the same (server_rec's) Timeout. This implies
  that both states are accounted as "write-completion" in mod_status for now.

* server/mpm/motorz/motorz.c, server/mpm/simple/simple_io.c, modules/http/http_core.c:
  Use the new states names (only).

* include/scoreboard.h:
  Change comment about process_score->write_completion to note that the
  counter refers to CONN_STATE_PROCESS connections returned to the MPM
  too.

* modules/http2/h2_c1.c:
  Return the c1 connection with the CONN_STATE_PROCESS state rather than
  CONN_STATE_WRITE_COMPLETION when waiting for a window update (i.e. ask
  the MPM to poll for read directly). This avoids the transition to
  CONN_STATE_KEEPALIVE which could kill the connection under high load.


Github: closes #448


Follow up to r1918022: MMN minor bump and checks for the new conn_state_e aliases' usability.

mpm_event: Don't spam with "Stopping process due to MaxConnectionsPerChild"

When MaxConnectionsPerChild is reached there may be some connections to process
still and the listener should stop writing this at every loop. Logging once
is enough.

* server/mpm/event/event.c(check_infinite_requests): Raise conns_this_child
  unconditionally.
  

mpm_event, mod_status: Separate processing and write completion queues.

As a follow up to r1918022 which handled the new CONN_STATE_PROCESS(ing) and
existing CONN_STATE_WRITE_COMPLETION in the same async queue, let's now have
two separates ones which allows more relevant async accounting in mod_status.

Rename CONN_STATE_PROCESS to CONN_STATE_PROCESSING as it's how it will be
called in mod_status.

* include/ap_mmn.h:
  MMN minor bump for process_score->processing counter.

* include/httpd.h:
  Rename CONN_STATE_PROCESS to CONN_STATE_PROCESSING.

* include/scoreboard.h:
  Add process_score->processing field.

* include/httpd.h, modules/http/http_core.c, modules/http2/h2_c1.c,
    server/mpm/event/event.c, server/mpm/motorz/motorz.c,
    server/mpm/simple/simple_io.c:
  Rename CONN_STATE_PROCESS to CONN_STATE_PROCESSING.

* server/mpm/event/event.c:
  Restore write_completion_q to handle connections in CONN_STATE_WRITE_COMPLETION.
  Use processing_q (renamed from process_q) solely for CONN_STATE_PROCESSING.
  Update process_score->processing according to the length of processing_q.
  
* modules/generators/mod_status.c:
  Show the value of process_score->processing in the stats.


Follow up to r1918098 (and r1918022): Push missing changes.

mpm_event,mod_http2: Keep compatibility with CONN_STATE_PROCESSING + OK

Before r1918022, returning OK with CONN_STATE_PROCESSING to mpm_event was
handled like/by CONN_STATE_LINGER "to not break old or third-party modules
which might return OK w/o touching the state and expect lingering close,
like with worker or prefork MPMs".

So we need a new return code to be allowed to apply the new POLLIN/POLLOUT
behaviour for CONN_STATE_PROCESSING, thus revive AGAIN as introduced by
Graham some times ago for a nonblocking WIP (moved to a branch/PR since then).

MPM event will advertise its ability to handle CONN_STATE_PROCESSING + AGAIN
with AP_MPMQ_CAN_AGAIN, and mod_http2 can use that to know how to return to
the MPM as expected. When !AP_MPMQ_CAN_AGAIN modules/mod_http2 can still use
CONN_STATE_WRITE_COMPLETION + CONN_SENSE_WANT_READ + c->clogging_input_filters
which will work in mpm_even-2.4.x still.

* include/ap_mmn.h:
  Bump MMN minor for AP_MPMQ_CAN_AGAIN and AGAIN.

* include/ap_mpm.h:
  Define AP_MPMQ_CAN_AGAIN.

* include/httpd.h:
  Define AGAIN.

* modules/http2/h2.h:
  No need for H2_USE_STATE_PROCESSING anymore with AP_MPMQ_CAN_AGAIN.

* modules/http2/h2_c1.c:
  For !keepalive case return to the MPM using CONN_STATE_PROCESSING + AGAIN
  or CONN_STATE_WRITE_COMPLETION + c->clogging_input_filters depending on
  AP_MPMQ_CAN_AGAIN only.

* modules/http2/h2_session.c:
  Can return to the MPM for h2_send_flow_blocked() provided it's async only.

* server/mpm/event/event.c:
  Rework process_socket()'s CONN_STATE_PROCESSING to handle AGAIN and preserve
  compatibility. Have a lingering_close label to goto there faster when
  process_lingering_close() is to be called. Improve relevant comments.


mpm_event,mod_http2,mod_status: Follow up to r1918257: CONN_STATE_ASYNC_WAITIO.

Per discussion on PR #449, have a separate state for returning the connection
to the MPM to wait for an IO (namely CONN_STATE_ASYNC_WAITIO), rather than
(ab)using CONN_STATE_PROCESSING.

This removes the need for AGAIN added in r1918257 (for now), and AP_MPMQ_CAN_AGAIN
is renamed to AP_MPMQ_CAN_WAITIO.

This is also the state that mod_status accounts for, so rename ->processing
to ->wait_io in process_score (shows as "wait-io" in mod_status and mod_lua).


mpm_event: Follow up to r1918482: CONN_STATE_ASYNC_WAITIO > CONN_STATE_LINGER.


mpm_event: Follow up to r1918482: CONN_STATE_LINGER* are not the last anymore.

Since CONN_STATE_ASYNC_WAITIO, we cannot check for < or >= CONN_STATE_LINGER
anymore to determine if in an lingering close state, so let's add a new
CONN_STATE_IS_LINGERING_CLOSE() macro for this and use it in mpm_event.

The test for state == CONN_STATE_LINGER in process_lingering_close() is a
bit weak too in order to call ap_start_lingering_close() the first time only,
so have a conn_state->linger_started flag instead.


mod_status: Follow up to r1918482: Bump colspan for the new wait-io colomn


mod_status: "Threads" span three colomns (busy, graceful, idle), not two.


Submitted by: icing, ylavic, ylavic, ylavic, ylavic, ylavic, ylavic, ylavic, ylavic, ylavic, ylavic, ylavic
Reviewed by: ylavic, icing, gbechis
Github: closes #449


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1919548 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
ylavic committed Jul 27, 2024
1 parent 0f69443 commit 8ace8c7
Show file tree
Hide file tree
Showing 14 changed files with 399 additions and 197 deletions.
6 changes: 5 additions & 1 deletion include/ap_mmn.h
Original file line number Diff line number Diff line change
Expand Up @@ -603,14 +603,18 @@
* and AP_REQUEST_TRUSTED_CT BNOTE.
* 20120211.133 (2.4.60-dev) Add ap_proxy_fixup_uds_filename()
* 20120211.134 (2.4.60-dev) AP_SLASHES and AP_IS_SLASH
* 20120211.135 (2.4.59-dev) Add CONN_STATE_ASYNC_WAITIO, CONN_STATE_KEEPALIVE
* and CONN_STATE_PROCESSING
* 20120211.136 (2.4.59-dev) Add wait_io field to struct process_score
* 20120211.137 (2.4.59-dev) Add AP_MPMQ_CAN_WAITIO
*/

#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */

#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
#define MODULE_MAGIC_NUMBER_MINOR 134 /* 0...n */
#define MODULE_MAGIC_NUMBER_MINOR 137 /* 0...n */

/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Expand Down
3 changes: 3 additions & 0 deletions include/ap_mpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ AP_DECLARE(apr_status_t) ap_os_create_privileged_process(
#define AP_MPMQ_GENERATION 15
/** MPM can drive serf internally */
#define AP_MPMQ_HAS_SERF 16
/* 17-18 are trunk only */
/** MPM supports CONN_STATE_ASYNC_WAITIO */
#define AP_MPMQ_CAN_WAITIO 19
/** @} */

/**
Expand Down
43 changes: 26 additions & 17 deletions include/httpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,13 +453,13 @@ AP_DECLARE(const char *) ap_get_server_built(void);

/* non-HTTP status codes returned by hooks */

#define OK 0 /**< Module has handled this stage. */
#define DECLINED -1 /**< Module declines to handle */
#define DONE -2 /**< Module has served the response completely
* - it's safe to die() with no more output
*/
#define SUSPENDED -3 /**< Module will handle the remainder of the request.
* The core will never invoke the request again, */
#define OK 0 /**< Module has handled this stage. */
#define DECLINED -1 /**< Module declines to handle */
#define DONE -2 /**< Module has served the response completely
* - it's safe to die() with no more output
*/
#define SUSPENDED -3 /**< Module will handle the remainder of the request.
* The core will never invoke the request again */

/** Returned by the bottom-most filter if no data was written.
* @see ap_pass_brigade(). */
Expand Down Expand Up @@ -1256,16 +1256,25 @@ struct conn_rec {
* only be set by the MPM. Use CONN_STATE_LINGER outside of the MPM.
*/
typedef enum {
CONN_STATE_CHECK_REQUEST_LINE_READABLE,
CONN_STATE_READ_REQUEST_LINE,
CONN_STATE_HANDLER,
CONN_STATE_WRITE_COMPLETION,
CONN_STATE_SUSPENDED,
CONN_STATE_LINGER, /* connection may be closed with lingering */
CONN_STATE_LINGER_NORMAL, /* MPM has started lingering close with normal timeout */
CONN_STATE_LINGER_SHORT, /* MPM has started lingering close with short timeout */

CONN_STATE_NUM /* Number of states (keep/kept last) */
CONN_STATE_KEEPALIVE, /* Kept alive in the MPM (using KeepAliveTimeout) */
CONN_STATE_PROCESSING, /* Processed by process_connection hooks */
CONN_STATE_HANDLER, /* Processed by the modules handlers */
CONN_STATE_WRITE_COMPLETION, /* Flushed by the MPM before entering CONN_STATE_KEEPALIVE */
CONN_STATE_SUSPENDED, /* Suspended in the MPM until ap_run_resume_suspended() */
CONN_STATE_LINGER, /* MPM flushes then closes the connection with lingering */
CONN_STATE_LINGER_NORMAL, /* MPM has started lingering close with normal timeout */
CONN_STATE_LINGER_SHORT, /* MPM has started lingering close with short timeout */

CONN_STATE_ASYNC_WAITIO, /* Returning this state to the MPM will make it wait for
* the connection to be readable or writable according to
* c->cs->sense (resp. CONN_SENSE_WANT_READ or _WRITE),
* using the configured Timeout */

CONN_STATE_NUM, /* Number of states (keep here before aliases) */

/* Aliases (legacy) */
CONN_STATE_CHECK_REQUEST_LINE_READABLE = CONN_STATE_KEEPALIVE,
CONN_STATE_READ_REQUEST_LINE = CONN_STATE_PROCESSING,
} conn_state_e;

typedef enum {
Expand Down
3 changes: 2 additions & 1 deletion include/scoreboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,14 @@ struct process_score {
* connections (for async MPMs)
*/
apr_uint32_t connections; /* total connections (for async MPMs) */
apr_uint32_t write_completion; /* async connections doing write completion */
apr_uint32_t write_completion; /* async connections in write completion */
apr_uint32_t lingering_close; /* async connections in lingering close */
apr_uint32_t keep_alive; /* async connections in keep alive */
apr_uint32_t suspended; /* connections suspended by some module */
int bucket; /* Listener bucket used by this child; this field is DEPRECATED
* and no longer updated by the MPMs (i.e. always zero).
*/
apr_uint32_t wait_io; /* async connections waiting an IO in the MPM */
};

/* Scoreboard is now in 'local' memory, since it isn't updated once created,
Expand Down
22 changes: 14 additions & 8 deletions modules/generators/mod_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,23 +564,25 @@ static int status_handler(request_rec *r)
ap_rputs("</dl>", r);

if (is_async) {
int write_completion = 0, lingering_close = 0, keep_alive = 0,
int wait_io = 0, write_completion = 0, lingering_close = 0, keep_alive = 0,
connections = 0, stopping = 0, procs = 0;
if (!short_report)
ap_rputs("\n\n<table rules=\"all\" cellpadding=\"1%\">\n"
"<tr><th rowspan=\"2\">Slot</th>"
"<th rowspan=\"2\">PID</th>"
"<th rowspan=\"2\">Stopping</th>"
"<th colspan=\"2\">Connections</th>\n"
"<th colspan=\"2\">Threads</th>"
"<th colspan=\"3\">Async connections</th></tr>\n"
"<th colspan=\"3\">Threads</th>"
"<th colspan=\"4\">Async connections</th></tr>\n"
"<tr><th>total</th><th>accepting</th>"
"<th>busy</th><th>graceful</th><th>idle</th>"
"<th>writing</th><th>keep-alive</th><th>closing</th></tr>\n", r);
"<th>wait-io</th><th>writing</th><th>keep-alive</th>"
"<th>closing</th></tr>\n", r);
for (i = 0; i < server_limit; ++i) {
ps_record = ap_get_scoreboard_process(i);
if (ps_record->pid) {
connections += ps_record->connections;
wait_io += ps_record->wait_io;
write_completion += ps_record->write_completion;
keep_alive += ps_record->keep_alive;
lingering_close += ps_record->lingering_close;
Expand All @@ -600,7 +602,7 @@ static int status_handler(request_rec *r)
"<td>%s%s</td>"
"<td>%u</td><td>%s</td>"
"<td>%u</td><td>%u</td><td>%u</td>"
"<td>%u</td><td>%u</td><td>%u</td>"
"<td>%u</td><td>%u</td><td>%u</td><td>%u</td>"
"</tr>\n",
i, ps_record->pid,
dying, old,
Expand All @@ -609,6 +611,7 @@ static int status_handler(request_rec *r)
thread_busy_buffer[i],
thread_graceful_buffer[i],
thread_idle_buffer[i],
ps_record->wait_io,
ps_record->write_completion,
ps_record->keep_alive,
ps_record->lingering_close);
Expand All @@ -620,23 +623,26 @@ static int status_handler(request_rec *r)
"<td>%d</td><td>%d</td>"
"<td>%d</td><td>&nbsp;</td>"
"<td>%d</td><td>%d</td><td>%d</td>"
"<td>%d</td><td>%d</td><td>%d</td>"
"<td>%d</td><td>%d</td><td>%d</td><td>%d</td>"
"</tr>\n</table>\n",
procs, stopping,
connections,
busy, graceful, idle,
write_completion, keep_alive, lingering_close);
wait_io, write_completion, keep_alive,
lingering_close);
}
else {
ap_rprintf(r, "Processes: %d\n"
"Stopping: %d\n"
"ConnsTotal: %d\n"
"ConnsAsyncWaitIO: %d\n"
"ConnsAsyncWriting: %d\n"
"ConnsAsyncKeepAlive: %d\n"
"ConnsAsyncClosing: %d\n",
procs, stopping,
connections,
write_completion, keep_alive, lingering_close);
wait_io, write_completion, keep_alive,
lingering_close);
}
}

Expand Down
4 changes: 2 additions & 2 deletions modules/http/http_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ static int ap_process_http_async_connection(conn_rec *c)
conn_state_t *cs = c->cs;

AP_DEBUG_ASSERT(cs != NULL);
AP_DEBUG_ASSERT(cs->state == CONN_STATE_READ_REQUEST_LINE);
AP_DEBUG_ASSERT(cs->state == CONN_STATE_PROCESSING);

if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
if (cs->state == CONN_STATE_PROCESSING) {
ap_update_child_status_from_conn(c->sbh, SERVER_BUSY_READ, c);
if (ap_extended_status) {
ap_set_conn_count(c->sbh, r, c->keepalives);
Expand Down
65 changes: 46 additions & 19 deletions modules/http2/h2_c1.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,25 @@

static struct h2_workers *workers;

static int async_mpm;
static int async_mpm, mpm_can_waitio;

APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_in) *h2_c_logio_add_bytes_in;
APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *h2_c_logio_add_bytes_out;

apr_status_t h2_c1_child_init(apr_pool_t *pool, server_rec *s)
{
apr_status_t status = APR_SUCCESS;
int minw, maxw;
apr_time_t idle_limit;

status = ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm);
if (status != APR_SUCCESS) {
if (ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm)) {
/* some MPMs do not implemnent this */
async_mpm = 0;
status = APR_SUCCESS;
}
#ifdef AP_MPMQ_CAN_WAITIO
if (!async_mpm || ap_mpm_query(AP_MPMQ_CAN_WAITIO, &mpm_can_waitio)) {
mpm_can_waitio = 0;
}
#endif

h2_config_init(pool);

Expand Down Expand Up @@ -113,23 +115,22 @@ apr_status_t h2_c1_setup(conn_rec *c, request_rec *r, server_rec *s)
return rv;
}

apr_status_t h2_c1_run(conn_rec *c)
int h2_c1_run(conn_rec *c)
{
apr_status_t status;
int mpm_state = 0;
int mpm_state = 0, keepalive = 0;
h2_conn_ctx_t *conn_ctx = h2_conn_ctx_get(c);

ap_assert(conn_ctx);
ap_assert(conn_ctx->session);
c->clogging_input_filters = 0;
do {
if (c->cs) {
c->cs->sense = CONN_SENSE_DEFAULT;
c->cs->state = CONN_STATE_HANDLER;
}

status = h2_session_process(conn_ctx->session, async_mpm);

if (APR_STATUS_IS_EOF(status)) {
status = h2_session_process(conn_ctx->session, async_mpm, &keepalive);
if (status != APR_SUCCESS) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c,
H2_SSSN_LOG(APLOGNO(03045), conn_ctx->session,
"process, closing conn"));
Expand All @@ -152,24 +153,51 @@ apr_status_t h2_c1_run(conn_rec *c)
case H2_SESSION_ST_IDLE:
case H2_SESSION_ST_BUSY:
case H2_SESSION_ST_WAIT:
c->cs->state = CONN_STATE_WRITE_COMPLETION;
if (c->cs && !conn_ctx->session->remote.emitted_count) {
/* let the MPM know that we are not done and want
* the Timeout behaviour instead of a KeepAliveTimeout
if (keepalive) {
/* Flush then keep-alive */
c->cs->sense = CONN_SENSE_DEFAULT;
c->cs->state = CONN_STATE_WRITE_COMPLETION;
}
else {
/* Let the MPM know that we are not done and want to wait
* for read using Timeout instead of KeepAliveTimeout.
* See PR 63534.
*/
c->cs->sense = CONN_SENSE_WANT_READ;
#ifdef AP_MPMQ_CAN_WAITIO
if (mpm_can_waitio) {
/* This tells the MPM to wait for the connection to be
* readable (CONN_SENSE_WANT_READ) within the configured
* Timeout and then come back to the process_connection()
* hooks again when ready.
*/
c->cs->state = CONN_STATE_ASYNC_WAITIO;
}
else
#endif
{
/* This is a compat workaround to do the same using the
* CONN_STATE_WRITE_COMPLETION state but with both
* CONN_SENSE_WANT_READ to wait for readability rather
* than writing and c->clogging_input_filters to force
* reentering the process_connection() hooks from any
* state when ready. This somehow will use Timeout too.
*/
c->cs->state = CONN_STATE_WRITE_COMPLETION;
c->clogging_input_filters = 1;
}
}
break;

case H2_SESSION_ST_CLEANUP:
case H2_SESSION_ST_DONE:
default:
c->cs->state = CONN_STATE_LINGER;
break;
break;
}
}

return APR_SUCCESS;
return OK;
}

apr_status_t h2_c1_pre_close(struct h2_conn_ctx_t *ctx, conn_rec *c)
Expand Down Expand Up @@ -275,8 +303,7 @@ static int h2_c1_hook_process_connection(conn_rec* c)
return !OK;
}
}
h2_c1_run(c);
return OK;
return h2_c1_run(c);

declined:
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, declined");
Expand Down
24 changes: 24 additions & 0 deletions modules/http2/h2_mplx.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ apr_status_t h2_mplx_c1_streams_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx)
typedef struct {
int stream_count;
int stream_want_send;
int stream_send_win_exhausted;
} stream_iter_aws_t;

static int m_stream_want_send_data(void *ctx, void *stream)
Expand All @@ -419,6 +420,29 @@ int h2_mplx_c1_all_streams_want_send_data(h2_mplx *m)
return x.stream_count && (x.stream_count == x.stream_want_send);
}

static int m_stream_send_win_exh(void *ctx, void *s)
{
h2_stream *stream = s;
int win;
stream_iter_aws_t *x = ctx;
++x->stream_count;
win = nghttp2_session_get_stream_remote_window_size(stream->session->ngh2, stream->id);
if (win == 0)
++x->stream_send_win_exhausted;
return 1;
}

int h2_mplx_c1_all_streams_send_win_exhausted(h2_mplx *m)
{
stream_iter_aws_t x;
x.stream_count = 0;
x.stream_send_win_exhausted = 0;
H2_MPLX_ENTER(m);
h2_ihash_iter(m->streams, m_stream_send_win_exh, &x);
H2_MPLX_LEAVE(m);
return x.stream_count && (x.stream_count == x.stream_send_win_exhausted);
}

static int m_report_stream_iter(void *ctx, void *val) {
h2_mplx *m = ctx;
h2_stream *stream = val;
Expand Down
5 changes: 5 additions & 0 deletions modules/http2/h2_mplx.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ apr_status_t h2_mplx_c1_streams_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx)
*/
int h2_mplx_c1_all_streams_want_send_data(h2_mplx *m);

/**
* Return != 0 iff all open streams have send window exhausted
*/
int h2_mplx_c1_all_streams_send_win_exhausted(h2_mplx *m);

/**
* A stream has been RST_STREAM by the client. Abort
* any processing going on and remove from processing
Expand Down
Loading

0 comments on commit 8ace8c7

Please sign in to comment.