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

Commit 92b60c5

Browse files
committed
Fix confusion between MAX_FRAME_SIZE and endpoint settings
When hyper is sending a frame, it should validate its length against the constant MAX_FRAME_SIZE and not the endpoint's settings. Add error code parameter to the connection's close method. Check if socket is still alive before sending an ACK to the endpoint. Fix minor spelling errors.
1 parent 25f10db commit 92b60c5

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

hyper/http20/connection.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,17 @@ def _send_preamble(self):
248248
# The server will also send an initial settings frame, so get it.
249249
self._recv_cb()
250250

251-
def close(self):
251+
def close(self, error_code=None):
252252
"""
253253
Close the connection to the server.
254254
255+
:param error_code: (optional) The error code to reset all streams with.
255256
:returns: Nothing.
256257
"""
257258
# Close all streams
258259
for stream in list(self.streams.values()):
259260
log.debug("Close stream %d" % stream.stream_id)
260-
stream.close()
261+
stream.close(error_code)
261262

262263
# Send GoAway frame to the server
263264
try:
@@ -389,10 +390,14 @@ def receive_frame(self, frame):
389390
if 'ACK' not in frame.flags:
390391
self._update_settings(frame)
391392

392-
# Need to return an ack.
393-
f = SettingsFrame(0)
394-
f.flags.add('ACK')
395-
self._send_cb(f)
393+
# When the setting containing the max frame size value is out
394+
# of range, the spec dictates to tear down the connection.
395+
# Therefore we make sure the socket is still alive before
396+
# returning the ack.
397+
if self._sock is not None:
398+
f = SettingsFrame(0)
399+
f.flags.add('ACK')
400+
self._send_cb(f)
396401
elif frame.type == GoAwayFrame.type:
397402
# If we get GoAway with error code zero, we are doing a graceful
398403
# shutdown and all is well. Otherwise, throw an exception.
@@ -454,6 +459,12 @@ def _update_settings(self, frame):
454459
new_size = frame.settings[SettingsFrame.SETTINGS_MAX_FRAME_SIZE]
455460
if new_size > FRAME_MAX_LEN and new_size < FRAME_MAX_ALLOWED_LEN:
456461
self._settings[SettingsFrame.SETTINGS_MAX_FRAME_SIZE] = new_size
462+
else:
463+
log.warning(
464+
"Frame size %d is outside of allowed range",
465+
new_size)
466+
# Tear the connection down with error code PROTOCOL_ERROR
467+
self.close(1)
457468

458469
def _new_stream(self, stream_id=None, local_closed=False):
459470
"""
@@ -536,15 +547,14 @@ def _consume_single_frame(self):
536547
# Parse the header. We can use the returned memoryview directly here.
537548
frame, length = Frame.parse_frame_header(header)
538549

539-
frame_size = self._settings[SettingsFrame.SETTINGS_MAX_FRAME_SIZE]
540-
if (length > frame_size):
541-
self._send_rst_frame(frame.stream_id, 6) # 6 = FRAME_SIZE_ERROR
550+
if (length > FRAME_MAX_LEN):
542551
log.warning(
543552
"Frame size exceeded on stream %d (received: %d, max: %d)",
544553
frame.stream_id,
545554
length,
546-
frame_size
555+
FRAME_MAX_LEN
547556
)
557+
self._send_rst_frame(frame.stream_id, 6) # 6 = FRAME_SIZE_ERROR
548558

549559
# Read the remaining data from the socket.
550560
data = self._recv_payload(length)
@@ -646,12 +656,11 @@ def _recv_cb(self):
646656

647657
def _send_rst_frame(self, stream_id, error_code):
648658
"""
649-
Send reset stream frame with error code and remove stream from map.
659+
Send reset stream frame with error code and remove stream from map.
650660
"""
651-
if error_code is not None:
652-
f = RstStreamFrame(stream_id)
653-
f.error_code = error_code
654-
self._send_cb(f)
661+
f = RstStreamFrame(stream_id)
662+
f.error_code = error_code
663+
self._send_cb(f)
655664

656665
try:
657666
del self.streams[stream_id]

hyper/packages/hyperframe/frame.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import collections
1111
import struct
1212

13-
# The maximum initial lengh of a frame. Some frames have shorter maximum lengths.
13+
# The maximum initial length of a frame. Some frames have shorter maximum lengths.
1414
FRAME_MAX_LEN = (2 ** 14) - 1
1515

16-
# The maximum allowed lengh of a frame.
16+
# The maximum allowed length of a frame.
1717
FRAME_MAX_ALLOWED_LEN = (2 ** 24) - 1
1818

1919
class Frame(object):

0 commit comments

Comments
 (0)