Skip to content
This repository was archived by the owner on Jan 13, 2021. It is now read-only.

Commit 1cbc63c

Browse files
authored
Merge pull request #261 from Lukasa/issue/260
Don't send WINDOW_UPDATE frames on closed streams.
2 parents a952ff0 + 0fcfecb commit 1cbc63c

File tree

4 files changed

+67
-2
lines changed

4 files changed

+67
-2
lines changed

HISTORY.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Release History
22
===============
33

4+
dev
5+
---
6+
7+
*Bugfixes*
8+
9+
- Don't send WINDOWUPDATE frames on closed streams.
10+
411
0.6.2 (2016-06-13)
512
------------------
613

hyper/http20/stream.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ def receive_data(self, event):
186186
# Append the data to the buffer.
187187
self.data.append(event.data)
188188

189-
if increment and not self.remote_closed:
189+
stream_about_to_close = (event.stream_ended is not None)
190+
191+
if increment and not self.remote_closed and not stream_about_to_close:
190192
with self._conn as conn:
191193
conn.increment_flow_control_window(
192194
increment, stream_id=self.stream_id

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def run_tests(self):
7878
'Programming Language :: Python :: 3.5',
7979
'Programming Language :: Python :: Implementation :: CPython',
8080
],
81-
install_requires=['h2>=2.3,<3.0', 'hyperframe>=3.2,<4.0'],
81+
install_requires=['h2>=2.4,<3.0', 'hyperframe>=3.2,<4.0'],
8282
tests_require=['pytest', 'requests', 'mock'],
8383
cmdclass={'test': PyTest},
8484
entry_points={

test/test_hyper.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# -*- coding: utf-8 -*-
2+
import h2.settings
3+
24
from h2.frame_buffer import FrameBuffer
35
from hyperframe.frame import (
46
Frame, DataFrame, RstStreamFrame, SettingsFrame, PushPromiseFrame,
@@ -583,6 +585,60 @@ def test_closing_incomplete_stream(self, frame_buffer):
583585
assert isinstance(f, RstStreamFrame)
584586
assert 1 not in c.streams
585587

588+
def test_incrementing_window_after_close(self):
589+
"""
590+
Hyper does not attempt to increment the flow control window once the
591+
stream is closed.
592+
"""
593+
# For this test, we want to send a response that has three frames at
594+
# the default max frame size (16,384 bytes). That will, on the third
595+
# frame, trigger the processing to increment the flow control window,
596+
# which should then not happen.
597+
f = SettingsFrame(0, settings={h2.settings.INITIAL_WINDOW_SIZE: 100})
598+
599+
c = HTTP20Connection('www.google.com')
600+
c._sock = DummySocket()
601+
c._sock.buffer = BytesIO(f.serialize())
602+
603+
# Open stream 1.
604+
c.request('GET', '/')
605+
606+
# Check what data we've sent right now.
607+
originally_sent_data = c._sock.queue[:]
608+
609+
# Swap out the buffer to get a GoAway frame.
610+
length = 16384
611+
total_length = (3 * 16384) + len(b'some more data')
612+
e = Encoder()
613+
h1 = HeadersFrame(1)
614+
h1.data = e.encode(
615+
[(':status', 200), ('content-length', '%d' % total_length)]
616+
)
617+
h1.flags |= set(['END_HEADERS'])
618+
619+
d1 = DataFrame(1)
620+
d1.data = b'\x00' * length
621+
d2 = d1
622+
d3 = d1
623+
d4 = DataFrame(1)
624+
d4.data = b'some more data'
625+
d4.flags |= set(['END_STREAM'])
626+
627+
buffer = BytesIO(
628+
b''.join(f.serialize() for f in [h1, d1, d2, d3, d4])
629+
)
630+
c._sock.buffer = buffer
631+
632+
# Read the response
633+
resp = c.get_response(stream_id=1)
634+
assert resp.status == 200
635+
assert resp.read() == b''.join(
636+
[b'\x00' * (3 * length), b'some more data']
637+
)
638+
639+
# We should have sent only one extra frame
640+
assert len(originally_sent_data) + 1 == len(c._sock.queue)
641+
586642

587643
class TestServerPush(object):
588644
def setup_method(self, method):

0 commit comments

Comments
 (0)