@@ -124,6 +124,43 @@ describe("http.h2_stream", function()
124124 assert_loop (cq , TEST_TIMEOUT )
125125 assert .truthy (cq :empty ())
126126 end )
127+ it (" ignores delayed RST_STREAM on already closed stream" , function ()
128+ local s , c = new_pair ()
129+ local cq = cqueues .new ()
130+ cq :wrap (function ()
131+ local client_stream = c :new_stream ()
132+ local req_headers = new_headers ()
133+ req_headers :append (" :method" , " GET" )
134+ req_headers :append (" :scheme" , " http" )
135+ req_headers :append (" :path" , " /" )
136+ req_headers :append (" :authority" , " example.com" )
137+ assert (client_stream :write_headers (req_headers , true ))
138+ assert (client_stream :get_headers ())
139+ assert (" closed" , client_stream .state )
140+ -- both sides now have stream in closed state
141+ -- send server a RST_STREAM: it should get ignored
142+ assert (client_stream :rst_stream (" post-closed rst_stream" ))
143+ assert (c :close ())
144+ end )
145+ cq :wrap (function ()
146+ local stream = assert (s :get_next_incoming_stream ())
147+ assert (stream :get_headers ())
148+ local res_headers = new_headers ()
149+ res_headers :append (" :status" , " 200" )
150+ assert (stream :write_headers (res_headers , true ))
151+ -- both sides now have stream in closed state
152+ assert (" closed" , stream .state )
153+ -- process incoming frames until EOF (i.e. drain RST_STREAM)
154+ -- the RST_STREAM frame should be ignored.
155+ assert (s :loop ())
156+ assert (s :close ())
157+ end )
158+ cq :wrap (function ()
159+ assert (s :loop ())
160+ end )
161+ assert_loop (cq , TEST_TIMEOUT )
162+ assert .truthy (cq :empty ())
163+ end )
127164 end )
128165 describe (" push_promise" , function ()
129166 it (" permits a simple push promise from server => client" , function ()
0 commit comments