Commit d4e6802
committed
ws-over-h2: permessage-deflate fixes: short return, ext tx-drain wedge, client extension offer -- with selftest
Three fixes for permessage-deflate on ws-over-h2 (RFC 8441)
encapsulated streams, plus a ctest-wired selftest:
1) The encapsulated tx path returned the h2 role's write result, which
reflects the POST-COMPRESSION frame size -- with pmd active that is
routinely smaller than what the caller passed in, so any
well-compressed message made callers checking (wr < len) conclude a
short write and kill a healthy connection. The lws_write() contract
is to report how much of the CALLER's payload was accepted, and the
h1 path already returns orig_len for exactly this reason; do the
same, still propagating write errors as < 0.
2) When pmd's compressed output exceeds its chunk buffer, the ws role
sets ws->tx_draining_ext and expects the next POLLOUT to send the
remaining fragments -- the h1 path services this in
rops_handle_POLLOUT_ws() priority 5, before letting the user write
anything new. An h2-encapsulated child never reaches that path: its
only POLLOUT servicing is the child loop in
rops_perform_user_POLLOUT_h2(), which went straight to the user
callback. Meanwhile lws_send_pipe_choked() reports choked while
tx_draining_ext is set, so a user write loop gated on it never
writes again either: the drain never advances and the stream wedges
permanently. Service the drain from the child loop, ahead of the
user callback. It slots in after the generic 'deal with partial at
nwsi' branch that 774c64a ("ws-over-h2: deal with choked nwsi")
routes carries-ws children through, preserving its ordering: a child
on a backed-up network socket still defers there first, the same
priority h1 connections get, and the extension drain only runs once
the nwsi partial has cleared.
3) lws_h2_client_handshake() only emitted sec-websocket-version and
sec-websocket-protocol, so an lws client could never negotiate
permessage-deflate (or any extension) over h2 even against a willing
server. RFC 8441 Sect 5 carries the ws handshake headers unchanged
over extended CONNECT, so build the same offer list as
lws_generate_client_ws_handshake() and emit it after the
pseudo-headers; the response side already instantiates accepted
extensions in the shared lws_client_ws_upgrade() path.
api-test-ws-h2-pmd (needs LWS_WITHOUT_EXTENSIONS=OFF): single-process
h2 ws server + client, both offering pmd; the server bulk-sends a 64KB
deterministic pattern in 4KB messages gated only on
lws_send_pipe_choked(), alternating trivially-compressible blocks
(deflated frame far smaller than the payload) with incompressible hash
noise (deflated output overflows pmd's default 1KB chunk buffer,
forcing tx_draining_ext). It fails if the connection is not genuinely
ws-over-h2, if the extended CONNECT did not offer pmd, if any
lws_write() reports fewer bytes accepted than requested, if the pattern
corrupts, or if the transfer stalls. Reverting any one of the three
fixes makes it fail in the corresponding distinct way.1 parent 9428500 commit d4e6802
5 files changed
Lines changed: 536 additions & 1 deletion
File tree
- lib/roles
- h2
- ws
- minimal-examples-lowlevel/api-tests/api-test-ws-h2-pmd
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2870 | 2870 | | |
2871 | 2871 | | |
2872 | 2872 | | |
| 2873 | + | |
| 2874 | + | |
| 2875 | + | |
| 2876 | + | |
| 2877 | + | |
| 2878 | + | |
| 2879 | + | |
| 2880 | + | |
| 2881 | + | |
| 2882 | + | |
| 2883 | + | |
| 2884 | + | |
| 2885 | + | |
| 2886 | + | |
| 2887 | + | |
| 2888 | + | |
| 2889 | + | |
| 2890 | + | |
| 2891 | + | |
| 2892 | + | |
| 2893 | + | |
| 2894 | + | |
| 2895 | + | |
| 2896 | + | |
| 2897 | + | |
| 2898 | + | |
| 2899 | + | |
| 2900 | + | |
| 2901 | + | |
| 2902 | + | |
| 2903 | + | |
| 2904 | + | |
| 2905 | + | |
| 2906 | + | |
2873 | 2907 | | |
2874 | 2908 | | |
2875 | 2909 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1139 | 1139 | | |
1140 | 1140 | | |
1141 | 1141 | | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
1142 | 1169 | | |
1143 | 1170 | | |
1144 | 1171 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2001 | 2001 | | |
2002 | 2002 | | |
2003 | 2003 | | |
2004 | | - | |
| 2004 | + | |
2005 | 2005 | | |
2006 | 2006 | | |
2007 | 2007 | | |
| 2008 | + | |
| 2009 | + | |
| 2010 | + | |
| 2011 | + | |
| 2012 | + | |
| 2013 | + | |
| 2014 | + | |
| 2015 | + | |
| 2016 | + | |
| 2017 | + | |
| 2018 | + | |
| 2019 | + | |
| 2020 | + | |
| 2021 | + | |
2008 | 2022 | | |
2009 | 2023 | | |
2010 | 2024 | | |
| |||
Lines changed: 37 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
0 commit comments