From 0badb3ec91d27ff529b8ea446848431e89fe8ad7 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Thu, 18 Aug 2016 17:23:47 +0200 Subject: cleanup --- mitmproxy/protocol/http2.py | 35 ++++++++++++++++++----------------- test/mitmproxy/protocol/test_http2.py | 1 + 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index 0e42d619..ee105781 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -96,15 +96,17 @@ class Http2Layer(base.Layer): self.server_to_client_stream_ids = dict([(0, 0)]) self.client_conn.h2 = SafeH2Connection(self.client_conn, client_side=False, header_encoding=False) - # make sure that we only pass actual SSL.Connection objects in here, - # because otherwise ssl_read_select fails! - self.active_conns = [self.client_conn.connection] - def _initiate_server_conn(self): - self.server_conn.h2 = SafeH2Connection(self.server_conn, client_side=True, header_encoding=False) - self.server_conn.h2.initiate_connection() - self.server_conn.send(self.server_conn.h2.data_to_send()) - self.active_conns.append(self.server_conn.connection) + if self.server_conn: + self.server_conn.h2 = SafeH2Connection(self.server_conn, client_side=True, header_encoding=False) + self.server_conn.h2.initiate_connection() + self.server_conn.send(self.server_conn.h2.data_to_send()) + + def _complete_handshake(self): + preamble = self.client_conn.rfile.read(24) + self.client_conn.h2.initiate_connection() + self.client_conn.h2.receive_data(preamble) + self.client_conn.send(self.client_conn.h2.data_to_send()) def next_layer(self): # pragma: no cover # WebSockets over HTTP/2? @@ -301,20 +303,19 @@ class Http2Layer(base.Layer): stream.data_finished.set() def __call__(self): - if self.server_conn: - self._initiate_server_conn() + self._initiate_server_conn() + self._complete_handshake() - preamble = self.client_conn.rfile.read(24) - self.client_conn.h2.initiate_connection() - self.client_conn.h2.receive_data(preamble) - self.client_conn.send(self.client_conn.h2.data_to_send()) + client = self.client_conn.connection + server = self.server_conn.connection + conns = [client, server] try: while True: - r = tcp.ssl_read_select(self.active_conns, 1) + r = tcp.ssl_read_select(conns, 1) for conn in r: - source_conn = self.client_conn if conn == self.client_conn.connection else self.server_conn - other_conn = self.server_conn if conn == self.client_conn.connection else self.client_conn + source_conn = self.client_conn if conn == client else self.server_conn + other_conn = self.server_conn if conn == client else self.client_conn is_server = (conn == self.server_conn.connection) with source_conn.h2.lock: diff --git a/test/mitmproxy/protocol/test_http2.py b/test/mitmproxy/protocol/test_http2.py index 1eabebf1..4dce698d 100644 --- a/test/mitmproxy/protocol/test_http2.py +++ b/test/mitmproxy/protocol/test_http2.py @@ -130,6 +130,7 @@ class _Http2TestBase(object): b"\r\n" % (self.server.server.address.port, self.server.server.address.port) ) client.wfile.flush() + # TODO: rewrite as http.Request object with http.assemble_request # read CONNECT response while client.rfile.readline() != b"\r\n": -- cgit v1.2.3 From 9b5acc19e2171cb70f7c87c62a283b9398156883 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 23 Aug 2016 19:12:03 +0200 Subject: http2: improve zombie exception handling --- mitmproxy/exceptions.py | 3 +++ mitmproxy/protocol/http2.py | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mitmproxy/exceptions.py b/mitmproxy/exceptions.py index 94876514..9ecfa8e5 100644 --- a/mitmproxy/exceptions.py +++ b/mitmproxy/exceptions.py @@ -61,6 +61,9 @@ class HttpProtocolException(ProtocolException): class Http2ProtocolException(ProtocolException): pass +class Http2ZombieException(ProtocolException): + pass + class ServerException(ProxyException): pass diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index ee105781..7ae7f09d 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -422,10 +422,11 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread) self.request_queued_data_length = v def raise_zombie(self, pre_command=None): - if self.zombie is not None: + connection_closed = self.h2_connection.state_machine.state == h2.connection.ConnectionState.CLOSED + if self.zombie is not None or connection_closed: if pre_command is not None: pre_command() - raise exceptions.Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ZombieException("Connection already dead") @detect_zombie_stream def read_request(self): @@ -582,6 +583,8 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread) try: layer() + except exceptions.Http2ZombieException as e: # pragma: no cover + pass except exceptions.ProtocolException as e: # pragma: no cover self.log(repr(e), "info") self.log(traceback.format_exc(), "debug") -- cgit v1.2.3 From 043180a8faa2b6f9f75c3fe12b110ee18e623fbf Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 23 Aug 2016 19:14:06 +0200 Subject: http2: improve closed connection handling --- mitmproxy/protocol/http2.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index 7ae7f09d..25ccfcf3 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -128,7 +128,7 @@ class Http2Layer(base.Layer): eid = event.stream_id if isinstance(event, events.RequestReceived): - return self._handle_request_received(eid, event) + return self._handle_request_received(eid, event, source_conn.h2) elif isinstance(event, events.ResponseReceived): return self._handle_response_received(eid, event) elif isinstance(event, events.DataReceived): @@ -140,7 +140,7 @@ class Http2Layer(base.Layer): elif isinstance(event, events.RemoteSettingsChanged): return self._handle_remote_settings_changed(event, other_conn) elif isinstance(event, events.ConnectionTerminated): - return self._handle_connection_terminated(event) + return self._handle_connection_terminated(event, is_server) elif isinstance(event, events.PushedStreamReceived): return self._handle_pushed_stream_received(event) elif isinstance(event, events.PriorityUpdated): @@ -151,9 +151,9 @@ class Http2Layer(base.Layer): # fail-safe for unhandled events return True - def _handle_request_received(self, eid, event): + def _handle_request_received(self, eid, event, h2_connection): headers = netlib.http.Headers([[k, v] for k, v in event.headers]) - self.streams[eid] = Http2SingleStreamLayer(self, eid, headers) + self.streams[eid] = Http2SingleStreamLayer(self, h2_connection, eid, headers) self.streams[eid].timestamp_start = time.time() self.streams[eid].no_body = (event.stream_ended is not None) if event.priority_updated is not None: @@ -211,7 +211,7 @@ class Http2Layer(base.Layer): other_conn.h2.safe_update_settings(new_settings) return True - def _handle_connection_terminated(self, event): + def _handle_connection_terminated(self, event, is_server): if event.error_code != h2.errors.NO_ERROR: # Something terrible has happened - kill everything! self.client_conn.h2.close_connection( @@ -221,6 +221,11 @@ class Http2Layer(base.Layer): ) self.client_conn.send(self.client_conn.h2.data_to_send()) self._kill_all_streams() + self.log("HTTP/2 connection terminated by {}: error code: {}, last stream id: {}, additional data: {}".format( + "server" if is_server else "client", + event.error_code, + event.last_stream_id, + event.additional_data), "info") else: """ Do not immediately terminate the other connection. @@ -326,6 +331,10 @@ class Http2Layer(base.Layer): self._kill_all_streams() return + if source_conn.h2.state_machine.state == h2.connection.ConnectionState.CLOSED: + self.log("HTTP/2 connection entered closed state already", "debug") + return + incoming_events = source_conn.h2.receive_data(raw_frame) source_conn.send(source_conn.h2.data_to_send()) @@ -355,10 +364,11 @@ def detect_zombie_stream(func): class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread): - def __init__(self, ctx, stream_id, request_headers): + def __init__(self, ctx, h2_connection, stream_id, request_headers): super(Http2SingleStreamLayer, self).__init__( ctx, name="Http2SingleStreamLayer-{}".format(stream_id) ) + self.h2_connection = h2_connection self.zombie = None self.client_stream_id = stream_id self.server_stream_id = None -- cgit v1.2.3 From 5dda9505b6f07422eb9a24590f30e9230a5453ef Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 23 Aug 2016 19:29:24 +0200 Subject: http2: improve framereader --- mitmproxy/protocol/http2.py | 2 +- netlib/http/http2/__init__.py | 6 ++++-- netlib/http/http2/framereader.py | 9 ++++++--- pathod/protocols/http2.py | 2 +- test/mitmproxy/protocol/test_http2.py | 28 ++++++++++++++-------------- test/pathod/test_protocols_http2.py | 6 +++--- 6 files changed, 29 insertions(+), 24 deletions(-) diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index 25ccfcf3..6b8c8903 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -325,7 +325,7 @@ class Http2Layer(base.Layer): with source_conn.h2.lock: try: - raw_frame = b''.join(http2.framereader.http2_read_raw_frame(source_conn.rfile)) + raw_frame = b''.join(http2.read_raw_frame(source_conn.rfile)) except: # read frame failed: connection closed self._kill_all_streams() diff --git a/netlib/http/http2/__init__.py b/netlib/http/http2/__init__.py index 60064190..7f84a1ab 100644 --- a/netlib/http/http2/__init__.py +++ b/netlib/http/http2/__init__.py @@ -1,8 +1,10 @@ from __future__ import absolute_import, print_function, division -from netlib.http.http2 import framereader + +from netlib.http.http2.framereader import read_raw_frame, parse_frame from netlib.http.http2.utils import parse_headers __all__ = [ - "framereader", + "read_raw_frame", + "parse_frame", "parse_headers", ] diff --git a/netlib/http/http2/framereader.py b/netlib/http/http2/framereader.py index eb9b069a..8b7cfffb 100644 --- a/netlib/http/http2/framereader.py +++ b/netlib/http/http2/framereader.py @@ -4,7 +4,7 @@ import hyperframe from ...exceptions import HttpException -def http2_read_raw_frame(rfile): +def read_raw_frame(rfile): header = rfile.safe_read(9) length = int(codecs.encode(header[:3], 'hex_codec'), 16) @@ -15,8 +15,11 @@ def http2_read_raw_frame(rfile): return [header, body] -def http2_read_frame(rfile): - header, body = http2_read_raw_frame(rfile) +def parse_frame(header, body=None): + if body is None: + body = header[9:] + header = header[:9] + frame, length = hyperframe.frame.Frame.parse_frame_header(header) frame.parse_body(memoryview(body)) return frame diff --git a/pathod/protocols/http2.py b/pathod/protocols/http2.py index 5ad120de..a2aa91b4 100644 --- a/pathod/protocols/http2.py +++ b/pathod/protocols/http2.py @@ -254,7 +254,7 @@ class HTTP2StateProtocol(object): def read_frame(self, hide=False): while True: - frm = http2.framereader.http2_read_frame(self.tcp_handler.rfile) + frm = http2.parse_frame(*http2.read_raw_frame(self.tcp_handler.rfile)) if not hide and self.dump_frames: # pragma no cover print(frm.human_readable("<<")) diff --git a/test/mitmproxy/protocol/test_http2.py b/test/mitmproxy/protocol/test_http2.py index 4dce698d..c2f96559 100644 --- a/test/mitmproxy/protocol/test_http2.py +++ b/test/mitmproxy/protocol/test_http2.py @@ -15,7 +15,7 @@ from mitmproxy.proxy.config import ProxyConfig import netlib from ...netlib import tservers as netlib_tservers from netlib.exceptions import HttpException -from netlib.http.http2 import framereader +from netlib.http import http2 from .. import tservers @@ -55,7 +55,7 @@ class _Http2ServerBase(netlib_tservers.ServerTestBase): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(self.rfile)) + raw = b''.join(http2.read_raw_frame(self.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -243,7 +243,7 @@ class TestSimple(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -320,7 +320,7 @@ class TestRequestWithPriority(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -359,7 +359,7 @@ class TestRequestWithPriority(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -431,7 +431,7 @@ class TestPriority(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -508,7 +508,7 @@ class TestPriorityWithExistingStream(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -559,7 +559,7 @@ class TestStreamResetFromServer(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -609,7 +609,7 @@ class TestBodySizeLimit(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -694,7 +694,7 @@ class TestPushPromise(_Http2Test): responses = 0 while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -747,7 +747,7 @@ class TestPushPromise(_Http2Test): responses = 0 while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -807,7 +807,7 @@ class TestConnectionLost(_Http2Test): done = False while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) h2_conn.receive_data(raw) except HttpException: print(traceback.format_exc()) @@ -864,7 +864,7 @@ class TestMaxConcurrentStreams(_Http2Test): ended_streams = 0 while ended_streams != len(new_streams): try: - header, body = framereader.http2_read_raw_frame(client.rfile) + header, body = http2.read_raw_frame(client.rfile) events = h2_conn.receive_data(b''.join([header, body])) except: break @@ -910,7 +910,7 @@ class TestConnectionTerminated(_Http2Test): connection_terminated_event = None while not done: try: - raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + raw = b''.join(http2.read_raw_frame(client.rfile)) events = h2_conn.receive_data(raw) for event in events: if isinstance(event, h2.events.ConnectionTerminated): diff --git a/test/pathod/test_protocols_http2.py b/test/pathod/test_protocols_http2.py index 8d7efc82..7f65c0eb 100644 --- a/test/pathod/test_protocols_http2.py +++ b/test/pathod/test_protocols_http2.py @@ -5,7 +5,7 @@ import hyperframe from netlib import tcp, http from netlib.tutils import raises from netlib.exceptions import TcpDisconnect -from netlib.http.http2 import framereader +from netlib.http import http2 from ..netlib import tservers as netlib_tservers @@ -112,11 +112,11 @@ class TestPerformServerConnectionPreface(netlib_tservers.ServerTestBase): self.wfile.flush() # check empty settings frame - raw = framereader.http2_read_raw_frame(self.rfile) + raw = http2.read_raw_frame(self.rfile) assert raw == codecs.decode('00000c040000000000000200000000000300000001', 'hex_codec') # check settings acknowledgement - raw = framereader.http2_read_raw_frame(self.rfile) + raw = http2.read_raw_frame(self.rfile) assert raw == codecs.decode('000000040100000000', 'hex_codec') # send settings acknowledgement -- cgit v1.2.3 From ea2a51d3be73ac132dc8a60f7794d3922d8190ff Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 23 Aug 2016 20:15:42 +0200 Subject: http2: fixes --- mitmproxy/exceptions.py | 1 + mitmproxy/protocol/http2.py | 19 ++++++++++--------- test/mitmproxy/protocol/test_http2.py | 5 +++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/mitmproxy/exceptions.py b/mitmproxy/exceptions.py index 9ecfa8e5..4d1d90c3 100644 --- a/mitmproxy/exceptions.py +++ b/mitmproxy/exceptions.py @@ -61,6 +61,7 @@ class HttpProtocolException(ProtocolException): class Http2ProtocolException(ProtocolException): pass + class Http2ZombieException(ProtocolException): pass diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index 6b8c8903..a491f8e4 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -142,7 +142,7 @@ class Http2Layer(base.Layer): elif isinstance(event, events.ConnectionTerminated): return self._handle_connection_terminated(event, is_server) elif isinstance(event, events.PushedStreamReceived): - return self._handle_pushed_stream_received(event) + return self._handle_pushed_stream_received(event, source_conn.h2) elif isinstance(event, events.PriorityUpdated): return self._handle_priority_updated(eid, event) elif isinstance(event, events.TrailersReceived): @@ -212,6 +212,12 @@ class Http2Layer(base.Layer): return True def _handle_connection_terminated(self, event, is_server): + self.log("HTTP/2 connection terminated by {}: error code: {}, last stream id: {}, additional data: {}".format( + "server" if is_server else "client", + event.error_code, + event.last_stream_id, + event.additional_data), "info") + if event.error_code != h2.errors.NO_ERROR: # Something terrible has happened - kill everything! self.client_conn.h2.close_connection( @@ -221,11 +227,6 @@ class Http2Layer(base.Layer): ) self.client_conn.send(self.client_conn.h2.data_to_send()) self._kill_all_streams() - self.log("HTTP/2 connection terminated by {}: error code: {}, last stream id: {}, additional data: {}".format( - "server" if is_server else "client", - event.error_code, - event.last_stream_id, - event.additional_data), "info") else: """ Do not immediately terminate the other connection. @@ -233,7 +234,7 @@ class Http2Layer(base.Layer): """ return False - def _handle_pushed_stream_received(self, event): + def _handle_pushed_stream_received(self, event, h2_connection): # pushed stream ids should be unique and not dependent on race conditions # only the parent stream id must be looked up first parent_eid = self.server_to_client_stream_ids[event.parent_stream_id] @@ -242,7 +243,7 @@ class Http2Layer(base.Layer): self.client_conn.send(self.client_conn.h2.data_to_send()) headers = netlib.http.Headers([[k, v] for k, v in event.headers]) - self.streams[event.pushed_stream_id] = Http2SingleStreamLayer(self, event.pushed_stream_id, headers) + self.streams[event.pushed_stream_id] = Http2SingleStreamLayer(self, h2_connection, event.pushed_stream_id, headers) self.streams[event.pushed_stream_id].timestamp_start = time.time() self.streams[event.pushed_stream_id].pushed = True self.streams[event.pushed_stream_id].parent_stream_id = parent_eid @@ -260,7 +261,7 @@ class Http2Layer(base.Layer): with self.server_conn.h2.lock: mapped_stream_id = event.stream_id if mapped_stream_id in self.streams and self.streams[mapped_stream_id].server_stream_id: - # if the stream is already up and running and was sent to the server + # if the stream is already up and running and was sent to the server, # use the mapped server stream id to update priority information mapped_stream_id = self.streams[mapped_stream_id].server_stream_id diff --git a/test/mitmproxy/protocol/test_http2.py b/test/mitmproxy/protocol/test_http2.py index c2f96559..d5860518 100644 --- a/test/mitmproxy/protocol/test_http2.py +++ b/test/mitmproxy/protocol/test_http2.py @@ -33,6 +33,11 @@ requires_alpn = pytest.mark.skipif( reason='requires OpenSSL with ALPN support') +# inspect the log: +# for msg in self.proxy.tmaster.tlog: +# print(msg) + + class _Http2ServerBase(netlib_tservers.ServerTestBase): ssl = dict(alpn_select=b'h2') -- cgit v1.2.3 From 69b770469e13079f01ea61fba0a71a0ca9d3fc37 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sat, 3 Sep 2016 12:31:35 +0200 Subject: http2: assemble connect-request from object --- test/mitmproxy/protocol/test_http2.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/mitmproxy/protocol/test_http2.py b/test/mitmproxy/protocol/test_http2.py index d5860518..c4bd2049 100644 --- a/test/mitmproxy/protocol/test_http2.py +++ b/test/mitmproxy/protocol/test_http2.py @@ -15,7 +15,7 @@ from mitmproxy.proxy.config import ProxyConfig import netlib from ...netlib import tservers as netlib_tservers from netlib.exceptions import HttpException -from netlib.http import http2 +from netlib.http import http1, http2 from .. import tservers @@ -129,13 +129,18 @@ class _Http2TestBase(object): client.connect() # send CONNECT request - client.wfile.write( - b"CONNECT localhost:%d HTTP/1.1\r\n" - b"Host: localhost:%d\r\n" - b"\r\n" % (self.server.server.address.port, self.server.server.address.port) - ) + client.wfile.write(http1.assemble_request(netlib.http.Request( + 'authority', + b'CONNECT', + b'', + b'localhost', + self.server.server.address.port, + b'/', + b'HTTP/1.1', + [(b'host', b'localhost:%d' % self.server.server.address.port)], + b'', + ))) client.wfile.flush() - # TODO: rewrite as http.Request object with http.assemble_request # read CONNECT response while client.rfile.readline() != b"\r\n": -- cgit v1.2.3 From e273a29a8ce3b7928d68c412ea1698393756ab33 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sat, 3 Sep 2016 13:25:22 +0200 Subject: http2: improve kill and cleanup threads --- mitmproxy/protocol/http2.py | 23 ++++++++++++++--------- netlib/debug.py | 4 ++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index a491f8e4..881dbf83 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -175,7 +175,7 @@ class Http2Layer(base.Layer): def _handle_data_received(self, eid, event, source_conn): bsl = self.config.options.body_size_limit if bsl and self.streams[eid].queued_data_length > bsl: - self.streams[eid].zombie = time.time() + self.streams[eid].kill() source_conn.h2.safe_reset_stream( event.stream_id, h2.errors.REFUSED_STREAM @@ -196,7 +196,7 @@ class Http2Layer(base.Layer): return True def _handle_stream_reset(self, eid, event, is_server, other_conn): - self.streams[eid].zombie = time.time() + self.streams[eid].kill() if eid in self.streams and event.error_code == h2.errors.CANCEL: if is_server: other_stream_id = self.streams[eid].client_stream_id @@ -302,11 +302,7 @@ class Http2Layer(base.Layer): def _kill_all_streams(self): for stream in self.streams.values(): - if not stream.zombie: - stream.zombie = time.time() - stream.request_data_finished.set() - stream.response_arrived.set() - stream.data_finished.set() + stream.kill() def __call__(self): self._initiate_server_conn() @@ -377,6 +373,9 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread) self.response_headers = None self.pushed = False + self.timestamp_start = None + self.timestamp_end = None + self.request_data_queue = queue.Queue() self.request_queued_data_length = 0 self.request_data_finished = threading.Event() @@ -393,6 +392,13 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread) self.priority_weight = None self.handled_priority_event = None + def kill(self): + if not self.zombie: + self.zombie = time.time() + self.request_data_finished.set() + self.response_arrived.set() + self.response_data_finished.set() + def connect(self): # pragma: no cover raise exceptions.Http2ProtocolException("HTTP2 layer should already have a connection.") @@ -604,5 +610,4 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread) except exceptions.Kill: self.log("Connection killed", "info") - if not self.zombie: - self.zombie = time.time() + self.kill() diff --git a/netlib/debug.py b/netlib/debug.py index 29c7f655..f9c700de 100644 --- a/netlib/debug.py +++ b/netlib/debug.py @@ -37,7 +37,7 @@ def sysinfo(): return "\n".join(data) -def dump_info(sig, frm, file=sys.stdout): # pragma: no cover +def dump_info(signal=None, frame=None, file=sys.stdout): # pragma: no cover print("****************************************************", file=file) print("Summary", file=file) print("=======", file=file) @@ -81,7 +81,7 @@ def dump_info(sig, frm, file=sys.stdout): # pragma: no cover print("****************************************************", file=file) -def dump_stacks(signal, frame, file=sys.stdout): +def dump_stacks(signal=None, frame=None, file=sys.stdout): id2name = dict([(th.ident, th.name) for th in threading.enumerate()]) code = [] for threadId, stack in sys._current_frames().items(): -- cgit v1.2.3 From d895d6caf0dde49c71df2193621238532a66c29c Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sat, 3 Sep 2016 13:48:28 +0200 Subject: improve CI --- .appveyor.yml | 2 +- setup.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 13782ee8..1acc5abb 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -25,7 +25,7 @@ install: - "pip install -U tox" test_script: - - ps: "tox -- --cov netlib --cov mitmproxy --cov pathod | Select-String -NotMatch Cryptography_locking_cb" + - ps: "tox -- --cov netlib --cov mitmproxy --cov pathod" deploy_script: ps: | diff --git a/setup.py b/setup.py index b86a48c0..f54d9037 100644 --- a/setup.py +++ b/setup.py @@ -107,6 +107,7 @@ setup( "pytest-cov>=2.2.1, <3", "pytest-timeout>=1.0.0, <2", "pytest-xdist>=1.14, <2", + "pytest-faulthandler>=1.3.0, <2", "sphinx>=1.3.5, <1.5", "sphinx-autobuild>=0.5.2, <0.7", "sphinxcontrib-documentedlist>=0.4.0, <0.5", -- cgit v1.2.3 From 3da9e37d9eb346f8e9cf4ab1b3be15abc1051f57 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sat, 3 Sep 2016 16:56:21 +0200 Subject: http2: improve connection lost --- mitmproxy/protocol/http2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index 881dbf83..1595fb61 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -440,7 +440,7 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread) def raise_zombie(self, pre_command=None): connection_closed = self.h2_connection.state_machine.state == h2.connection.ConnectionState.CLOSED - if self.zombie is not None or connection_closed: + if self.zombie is not None or not hasattr(self.server_conn, 'h2') or connection_closed: if pre_command is not None: pre_command() raise exceptions.Http2ZombieException("Connection already dead") @@ -527,6 +527,7 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread) except Exception as e: # pragma: no cover raise e finally: + self.raise_zombie() self.server_conn.h2.lock.release() if not self.no_body: -- cgit v1.2.3