diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 60ad71054..f0e8fedff 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -331,7 +331,7 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len) if (n < 0) goto bail; if (n) - lws_dll_add_head(&wsi->dll_buflist, &pt->dll_head_buflist); + lws_dll2_add_head(&wsi->dll_buflist, &pt->dll_buflist_owner); /* * we can't process the initial read data until we can attach an ah. diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 25de2d015..7ddc58b88 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -446,7 +446,7 @@ just_kill_connection: lwsi_set_state(wsi, LRS_DEAD_SOCKET); lws_buflist_destroy_all_segments(&wsi->buflist); - lws_dll_remove_track_tail(&wsi->dll_buflist, &pt->dll_head_buflist); + lws_dll2_remove(&wsi->dll_buflist); if (wsi->role_ops->close_role) wsi->role_ops->close_role(pt, wsi); diff --git a/lib/core-net/private.h b/lib/core-net/private.h index fab2f0685..3144e98a1 100644 --- a/lib/core-net/private.h +++ b/lib/core-net/private.h @@ -265,7 +265,7 @@ struct lws_context_per_thread { struct lws_dll dll_timeout_head; struct lws_dll dll_hrtimer_head; - struct lws_dll dll_head_buflist; /* guys with pending rxflow */ + struct lws_dll2_owner dll_buflist_owner; /* guys with pending rxflow */ #if defined(LWS_WITH_TLS) struct lws_pt_tls tls; @@ -491,7 +491,7 @@ struct lws { struct lws_dll dll_timeout; struct lws_dll dll_hrtimer; - struct lws_dll dll_buflist; /* guys with pending rxflow */ + struct lws_dll2 dll_buflist; /* guys with pending rxflow */ #if defined(LWS_WITH_THREADPOOL) struct lws_threadpool_task *tp_task; diff --git a/lib/core-net/service.c b/lib/core-net/service.c index ab0812806..7808ff2af 100644 --- a/lib/core-net/service.c +++ b/lib/core-net/service.c @@ -331,7 +331,7 @@ lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len) return LWSRXFC_ERROR; if (m) { lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi); - lws_dll_add_head(&wsi->dll_buflist, &pt->dll_head_buflist); + lws_dll2_add_head(&wsi->dll_buflist, &pt->dll_buflist_owner); } return ret; @@ -372,10 +372,11 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi) * it, we should not wait in poll */ - lws_start_foreach_dll(struct lws_dll *, d, pt->dll_head_buflist.next) { + lws_start_foreach_dll(struct lws_dll2 *, d, pt->dll_buflist_owner.head) { struct lws *wsi = lws_container_of(d, struct lws, dll_buflist); - if (lwsi_state(wsi) != LRS_DEFERRING_ACTION) + if (!lws_is_flowcontrolled(wsi) && + lwsi_state(wsi) != LRS_DEFERRING_ACTION) return 0; /* @@ -422,7 +423,7 @@ lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi, return -1; if (n) { lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi); - lws_dll_add_head(&wsi->dll_buflist, &pt->dll_head_buflist); + lws_dll2_add_head(&wsi->dll_buflist, &pt->dll_buflist_owner); } /* get the first buflist guy in line */ @@ -455,8 +456,7 @@ lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used, return 0; lwsl_info("%s: removed %p from dll_buflist\n", __func__, wsi); - lws_dll_remove_track_tail(&wsi->dll_buflist, - &pt->dll_head_buflist); + lws_dll2_remove(&wsi->dll_buflist); return 0; } @@ -472,8 +472,8 @@ lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used, if (m) { lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi); - lws_dll_add_head(&wsi->dll_buflist, - &pt->dll_head_buflist); + lws_dll2_add_head(&wsi->dll_buflist, + &pt->dll_buflist_owner); } } @@ -485,7 +485,7 @@ lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt) { struct lws_pollfd pfd; - if (!pt->dll_head_buflist.next) + if (!pt->dll_buflist_owner.head) return; /* @@ -495,15 +495,16 @@ lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt) lws_pt_lock(pt, __func__); - lws_start_foreach_dll_safe(struct lws_dll *, d, d1, - pt->dll_head_buflist.next) { + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + pt->dll_buflist_owner.head) { struct lws *wsi = lws_container_of(d, struct lws, dll_buflist); pfd.events = LWS_POLLIN; pfd.revents = LWS_POLLIN; pfd.fd = -1; - lwsl_debug("%s: rxflow processing: %p 0x%x\n", __func__, wsi, + lwsl_debug("%s: rxflow processing: %p fc=%d, 0x%x\n", __func__, + wsi, lws_is_flowcontrolled(wsi), wsi->wsistate); if (!lws_is_flowcontrolled(wsi) && @@ -537,10 +538,11 @@ lws_service_flag_pending(struct lws_context *context, int tsi) * it, we should not wait in poll */ - lws_start_foreach_dll(struct lws_dll *, d, pt->dll_head_buflist.next) { + lws_start_foreach_dll(struct lws_dll2 *, d, pt->dll_buflist_owner.head) { struct lws *wsi = lws_container_of(d, struct lws, dll_buflist); - if (lwsi_state(wsi) != LRS_DEFERRING_ACTION) { + if (!lws_is_flowcontrolled(wsi) && + lwsi_state(wsi) != LRS_DEFERRING_ACTION) { forced = 1; break; } diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 9bf320ca4..984560983 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -1884,7 +1884,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen, if (m) { struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi); - lws_dll_add_head(&h2n->swsi->dll_buflist, &pt->dll_head_buflist); + lws_dll2_add_head(&h2n->swsi->dll_buflist, &pt->dll_buflist_owner); } in += n - 1; h2n->inside += n; diff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c index c72f0b479..804176a1a 100644 --- a/lib/roles/h2/ops-h2.c +++ b/lib/roles/h2/ops-h2.c @@ -276,8 +276,7 @@ drain: if (!m) { lwsl_notice("%s: removed %p from dll_buflist\n", __func__, wsi); - lws_dll_remove_track_tail(&wsi->dll_buflist, - &pt->dll_head_buflist); + lws_dll2_remove(&wsi->dll_buflist); } } else if (n != ebuf.len) { @@ -289,8 +288,8 @@ drain: if (m) { lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi); - lws_dll_add_head(&wsi->dll_buflist, - &pt->dll_head_buflist); + lws_dll2_add_head(&wsi->dll_buflist, + &pt->dll_buflist_owner); } } } diff --git a/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c b/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c index 4a0d6d769..191a129e8 100644 --- a/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c +++ b/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c @@ -33,6 +33,7 @@ struct msg { struct per_session_data__minimal_client_echo { struct lws_ring *ring; uint32_t tail; + char flow_controlled; uint8_t completed:1; }; @@ -191,8 +192,11 @@ callback_minimal_client_echo(struct lws *wsi, enum lws_callback_reasons reason, /* come back as soon as we can write more */ lws_callback_on_writable(wsi); - if ((int)lws_ring_get_count_free_elements(pss->ring) > RING_DEPTH - 5) + if (pss->flow_controlled && + (int)lws_ring_get_count_free_elements(pss->ring) > RING_DEPTH - 5) { lws_rx_flow_control(wsi, 1); + pss->flow_controlled = 0; + } break; @@ -231,8 +235,10 @@ callback_minimal_client_echo(struct lws *wsi, enum lws_callback_reasons reason, } lws_callback_on_writable(wsi); - if (n < 3) + if (!pss->flow_controlled && n < 3) { + pss->flow_controlled = 1; lws_rx_flow_control(wsi, 0); + } break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: