Skip to content

Commit 55860eb

Browse files
authored
Merge pull request #479 from python-hyper/backport-2.4.X
Backport #476 to 2.4.X
2 parents 00946e2 + d69aeaf commit 55860eb

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

HISTORY.rst

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Release History
44
2.4.4dev0
55
---------
66

7+
Bugfixes
8+
~~~~~~~~
9+
10+
- Allowed hyperframe v5 support while continuing to ignore unexpected frames.
11+
12+
713
2.4.3 (2017-01-27)
814
------------------
915

h2/connection.py

+23-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from .exceptions import (
2828
ProtocolError, NoSuchStreamError, FlowControlError, FrameTooLargeError,
2929
TooManyStreamsError, StreamClosedError, StreamIDTooLowError,
30-
NoAvailableStreamIDError, UnsupportedFrameError, RFC1122Error
30+
NoAvailableStreamIDError, RFC1122Error
3131
)
3232
from .frame_buffer import FrameBuffer
3333
from .settings import (
@@ -38,6 +38,15 @@
3838
from .utilities import validate_headers, guard_increment_window
3939

4040

41+
try:
42+
from hyperframe.frame import ExtensionFrame
43+
except ImportError: # Platform-specific: Hyperframe < 5.0.0
44+
# If the frame doesn't exist, that's just fine: we'll define it ourselves
45+
# and the method will just never be called.
46+
class ExtensionFrame(object):
47+
pass
48+
49+
4150
class ConnectionState(Enum):
4251
IDLE = 0
4352
CLIENT_OPEN = 1
@@ -358,6 +367,7 @@ def __init__(self, client_side=True, header_encoding='utf-8'):
358367
GoAwayFrame: self._receive_goaway_frame,
359368
ContinuationFrame: self._receive_naked_continuation,
360369
AltSvcFrame: self._receive_alt_svc_frame,
370+
ExtensionFrame: self._receive_unknown_frame
361371
}
362372

363373
def _prepare_for_sending(self, frames):
@@ -1352,10 +1362,6 @@ def _receive_frame(self, frame):
13521362
if frame.stream_id not in self._reset_streams:
13531363
raise
13541364
events = []
1355-
except KeyError as e: # pragma: no cover
1356-
# We don't have a function for handling this frame. Let's call this
1357-
# a PROTOCOL_ERROR and exit.
1358-
raise UnsupportedFrameError("Unexpected frame: %s" % frame)
13591365
else:
13601366
self._prepare_for_sending(frames)
13611367

@@ -1713,6 +1719,18 @@ def _receive_alt_svc_frame(self, frame):
17131719

17141720
return frames, events
17151721

1722+
def _receive_unknown_frame(self, frame):
1723+
"""
1724+
We have received a frame that we do not understand. This is almost
1725+
certainly an extension frame, though it's impossible to be entirely
1726+
sure.
1727+
1728+
RFC 7540 § 5.5 says that we MUST ignore unknown frame types: so we
1729+
do.
1730+
"""
1731+
# We don't do anything here.
1732+
return [], []
1733+
17161734
def _local_settings_acked(self):
17171735
"""
17181736
Handle the local settings being ACKed, update internal state.

h2/frame_buffer.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,13 @@ def _parse_frame_header(self, data):
6565
"""
6666
try:
6767
frame, length = Frame.parse_frame_header(data[:9])
68-
except UnknownFrameError as e:
68+
except UnknownFrameError as e: # Platform-specific: Hyperframe < 5.0
6969
# Here we do something a bit odd. We want to consume the frame data
7070
# as consistently as possible, but we also don't ever want to yield
7171
# None. Instead, we make sure that, if there is no frame, we
7272
# recurse into ourselves.
73+
# This can only happen now on older versions of hyperframe.
74+
# TODO: Remove in 3.0
7375
length = e.length
7476
frame = None
7577
except ValueError as e:

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
'Programming Language :: Python :: Implementation :: PyPy',
6262
],
6363
install_requires=[
64-
'hyperframe>=3.1, <5, !=4.0.0',
64+
'hyperframe>=3.1, <6, !=4.0.0',
6565
'hpack>=2.2, <3',
6666
],
6767
extras_require={

0 commit comments

Comments
 (0)