aboutsummaryrefslogtreecommitdiffstats
path: root/netlib/http/http2/connections.py
diff options
context:
space:
mode:
authorThomas Kriechbaumer <thomas@kriechbaumer.name>2016-01-31 12:15:44 +0100
committerThomas Kriechbaumer <thomas@kriechbaumer.name>2016-01-31 20:03:25 +0100
commit280b491ab2b743f75483e2916e5344b22d4136e1 (patch)
tree8fd4aaa0934ec9abe21d2a652857fbd77fd131a7 /netlib/http/http2/connections.py
parentd253ebc142d80708a1bdc065d3db05d1394e3819 (diff)
downloadmitmproxy-280b491ab2b743f75483e2916e5344b22d4136e1.tar.gz
mitmproxy-280b491ab2b743f75483e2916e5344b22d4136e1.tar.bz2
mitmproxy-280b491ab2b743f75483e2916e5344b22d4136e1.zip
migrate to hyperframe
Diffstat (limited to 'netlib/http/http2/connections.py')
-rw-r--r--netlib/http/http2/connections.py81
1 files changed, 43 insertions, 38 deletions
diff --git a/netlib/http/http2/connections.py b/netlib/http/http2/connections.py
index c493abe6..c963f7c4 100644
--- a/netlib/http/http2/connections.py
+++ b/netlib/http/http2/connections.py
@@ -5,7 +5,8 @@ import time
from hpack.hpack import Encoder, Decoder
from ... import utils
from .. import Headers, Response, Request
-from . import frame
+
+from hyperframe import frame
class TCPHandler(object):
@@ -36,6 +37,15 @@ class HTTP2Protocol(object):
CLIENT_CONNECTION_PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+ HTTP2_DEFAULT_SETTINGS = {
+ frame.SettingsFrame.HEADER_TABLE_SIZE: 4096,
+ frame.SettingsFrame.ENABLE_PUSH: 1,
+ frame.SettingsFrame.MAX_CONCURRENT_STREAMS: None,
+ frame.SettingsFrame.INITIAL_WINDOW_SIZE: 2 ** 16 - 1,
+ frame.SettingsFrame.MAX_FRAME_SIZE: 2 ** 14,
+ frame.SettingsFrame.MAX_HEADER_LIST_SIZE: None,
+ }
+
def __init__(
self,
tcp_handler=None,
@@ -54,7 +64,7 @@ class HTTP2Protocol(object):
self.decoder = decoder or Decoder()
self.unhandled_frame_cb = unhandled_frame_cb
- self.http2_settings = frame.HTTP2_DEFAULT_SETTINGS.copy()
+ self.http2_settings = self.HTTP2_DEFAULT_SETTINGS.copy()
self.current_stream_id = None
self.connection_preface_performed = False
@@ -240,9 +250,9 @@ class HTTP2Protocol(object):
magic = self.tcp_handler.rfile.safe_read(magic_length)
assert magic == self.CLIENT_CONNECTION_PREFACE
- frm = frame.SettingsFrame(state=self, settings={
- frame.SettingsFrame.SETTINGS.SETTINGS_ENABLE_PUSH: 0,
- frame.SettingsFrame.SETTINGS.SETTINGS_MAX_CONCURRENT_STREAMS: 1,
+ frm = frame.SettingsFrame(settings={
+ frame.SettingsFrame.ENABLE_PUSH: 0,
+ frame.SettingsFrame.MAX_CONCURRENT_STREAMS: 1,
})
self.send_frame(frm, hide=True)
self._receive_settings(hide=True)
@@ -253,12 +263,12 @@ class HTTP2Protocol(object):
self.tcp_handler.wfile.write(self.CLIENT_CONNECTION_PREFACE)
- self.send_frame(frame.SettingsFrame(state=self), hide=True)
+ self.send_frame(frame.SettingsFrame(), hide=True)
self._receive_settings(hide=True) # server announces own settings
self._receive_settings(hide=True) # server acks my settings
def send_frame(self, frm, hide=False):
- raw_bytes = frm.to_bytes()
+ raw_bytes = frm.serialize()
self.tcp_handler.wfile.write(raw_bytes)
self.tcp_handler.wfile.flush()
if not hide and self.dump_frames: # pragma no cover
@@ -266,19 +276,19 @@ class HTTP2Protocol(object):
def read_frame(self, hide=False):
while True:
- frm = frame.Frame.from_file(self.tcp_handler.rfile, self)
+ frm = utils.http2_read_frame(self.tcp_handler.rfile)
if not hide and self.dump_frames: # pragma no cover
print(frm.human_readable("<<"))
if isinstance(frm, frame.PingFrame):
- raw_bytes = frame.PingFrame(flags=frame.Frame.FLAG_ACK, payload=frm.payload).to_bytes()
+ raw_bytes = frame.PingFrame(flags=['ACK'], payload=frm.payload).serialize()
self.tcp_handler.wfile.write(raw_bytes)
self.tcp_handler.wfile.flush()
continue
- if isinstance(frm, frame.SettingsFrame) and not frm.flags & frame.Frame.FLAG_ACK:
+ if isinstance(frm, frame.SettingsFrame) and 'ACK' not in frm.flags:
self._apply_settings(frm.settings, hide)
- if isinstance(frm, frame.DataFrame) and frm.length > 0:
- self._update_flow_control_window(frm.stream_id, frm.length)
+ if isinstance(frm, frame.DataFrame) and frm.flow_controlled_length > 0:
+ self._update_flow_control_window(frm.stream_id, frm.flow_controlled_length)
return frm
def check_alpn(self):
@@ -321,15 +331,13 @@ class HTTP2Protocol(object):
old_value = '-'
self.http2_settings[setting] = value
- frm = frame.SettingsFrame(
- state=self,
- flags=frame.Frame.FLAG_ACK)
+ frm = frame.SettingsFrame(flags=['ACK'])
self.send_frame(frm, hide)
def _update_flow_control_window(self, stream_id, increment):
- frm = frame.WindowUpdateFrame(stream_id=0, window_size_increment=increment)
+ frm = frame.WindowUpdateFrame(stream_id=0, window_increment=increment)
self.send_frame(frm)
- frm = frame.WindowUpdateFrame(stream_id=stream_id, window_size_increment=increment)
+ frm = frame.WindowUpdateFrame(stream_id=stream_id, window_increment=increment)
self.send_frame(frm)
def _create_headers(self, headers, stream_id, end_stream=True):
@@ -342,43 +350,40 @@ class HTTP2Protocol(object):
header_block_fragment = self.encoder.encode(headers.fields)
- chunk_size = self.http2_settings[frame.SettingsFrame.SETTINGS.SETTINGS_MAX_FRAME_SIZE]
+ chunk_size = self.http2_settings[frame.SettingsFrame.MAX_FRAME_SIZE]
chunks = range(0, len(header_block_fragment), chunk_size)
frms = [frm_cls(
- state=self,
- flags=frame.Frame.FLAG_NO_FLAGS,
+ flags=[],
stream_id=stream_id,
- header_block_fragment=header_block_fragment[i:i+chunk_size]) for frm_cls, i in frame_cls(chunks)]
+ data=header_block_fragment[i:i+chunk_size]) for frm_cls, i in frame_cls(chunks)]
- last_flags = frame.Frame.FLAG_END_HEADERS
+ frms[-1].flags.add('END_HEADERS')
if end_stream:
- last_flags |= frame.Frame.FLAG_END_STREAM
- frms[-1].flags = last_flags
+ frms[0].flags.add('END_STREAM')
if self.dump_frames: # pragma no cover
for frm in frms:
print(frm.human_readable(">>"))
- return [frm.to_bytes() for frm in frms]
+ return [frm.serialize() for frm in frms]
def _create_body(self, body, stream_id):
if body is None or len(body) == 0:
return b''
- chunk_size = self.http2_settings[frame.SettingsFrame.SETTINGS.SETTINGS_MAX_FRAME_SIZE]
+ chunk_size = self.http2_settings[frame.SettingsFrame.MAX_FRAME_SIZE]
chunks = range(0, len(body), chunk_size)
frms = [frame.DataFrame(
- state=self,
- flags=frame.Frame.FLAG_NO_FLAGS,
+ flags=[],
stream_id=stream_id,
- payload=body[i:i+chunk_size]) for i in chunks]
- frms[-1].flags = frame.Frame.FLAG_END_STREAM
+ data=body[i:i+chunk_size]) for i in chunks]
+ frms[-1].flags.add('END_STREAM')
if self.dump_frames: # pragma no cover
for frm in frms:
print(frm.human_readable(">>"))
- return [frm.to_bytes() for frm in frms]
+ return [frm.serialize() for frm in frms]
def _receive_transmission(self, stream_id=None, include_body=True):
if not include_body:
@@ -386,7 +391,7 @@ class HTTP2Protocol(object):
body_expected = True
- header_block_fragment = b''
+ header_blocks = b''
body = b''
while True:
@@ -396,10 +401,10 @@ class HTTP2Protocol(object):
(stream_id is None or frm.stream_id == stream_id)
):
stream_id = frm.stream_id
- header_block_fragment += frm.header_block_fragment
- if frm.flags & frame.Frame.FLAG_END_STREAM:
+ header_blocks += frm.data
+ if 'END_STREAM' in frm.flags:
body_expected = False
- if frm.flags & frame.Frame.FLAG_END_HEADERS:
+ if 'END_HEADERS' in frm.flags:
break
else:
self._handle_unexpected_frame(frm)
@@ -407,14 +412,14 @@ class HTTP2Protocol(object):
while body_expected:
frm = self.read_frame()
if isinstance(frm, frame.DataFrame) and frm.stream_id == stream_id:
- body += frm.payload
- if frm.flags & frame.Frame.FLAG_END_STREAM:
+ body += frm.data
+ if 'END_STREAM' in frm.flags:
break
else:
self._handle_unexpected_frame(frm)
headers = Headers(
- [[str(k), str(v)] for k, v in self.decoder.decode(header_block_fragment)]
+ [[str(k), str(v)] for k, v in self.decoder.decode(header_blocks)]
)
return stream_id, headers, body