Lines 1-174
Link Here
|
1 |
--- mitmproxy/proxy/protocol/websocket.py.orig 2019-02-14 21:03:58 UTC |
|
|
2 |
+++ mitmproxy/proxy/protocol/websocket.py |
3 |
@@ -4,8 +4,9 @@ from OpenSSL import SSL |
4 |
|
5 |
|
6 |
import wsproto |
7 |
-from wsproto import events |
8 |
-from wsproto.connection import ConnectionType, WSConnection |
9 |
+from wsproto import events, WSConnection |
10 |
+from wsproto.connection import ConnectionType |
11 |
+from wsproto.events import AcceptConnection, CloseConnection, Message, Ping, Request |
12 |
from wsproto.extensions import PerMessageDeflate |
13 |
|
14 |
from mitmproxy import exceptions |
15 |
@@ -52,51 +53,52 @@ class WebSocketLayer(base.Layer): |
16 |
|
17 |
self.connections: dict[object, WSConnection] = {} |
18 |
|
19 |
- extensions = [] |
20 |
+ client_extensions = [] |
21 |
+ server_extensions = [] |
22 |
if 'Sec-WebSocket-Extensions' in handshake_flow.response.headers: |
23 |
if PerMessageDeflate.name in handshake_flow.response.headers['Sec-WebSocket-Extensions']: |
24 |
- extensions = [PerMessageDeflate()] |
25 |
- self.connections[self.client_conn] = WSConnection(ConnectionType.SERVER, |
26 |
- extensions=extensions) |
27 |
- self.connections[self.server_conn] = WSConnection(ConnectionType.CLIENT, |
28 |
- host=handshake_flow.request.host, |
29 |
- resource=handshake_flow.request.path, |
30 |
- extensions=extensions) |
31 |
- if extensions: |
32 |
- for conn in self.connections.values(): |
33 |
- conn.extensions[0].finalize(conn, handshake_flow.response.headers['Sec-WebSocket-Extensions']) |
34 |
+ client_extensions = [PerMessageDeflate()] |
35 |
+ server_extensions = [PerMessageDeflate()] |
36 |
+ self.connections[self.client_conn] = WSConnection(ConnectionType.SERVER) |
37 |
+ self.connections[self.server_conn] = WSConnection(ConnectionType.CLIENT) |
38 |
|
39 |
- data = self.connections[self.server_conn].bytes_to_send() |
40 |
- self.connections[self.client_conn].receive_bytes(data) |
41 |
+ if client_extensions: |
42 |
+ client_extensions[0].finalize(handshake_flow.response.headers['Sec-WebSocket-Extensions']) |
43 |
+ if server_extensions: |
44 |
+ server_extensions[0].finalize(handshake_flow.response.headers['Sec-WebSocket-Extensions']) |
45 |
|
46 |
+ request = Request(extensions=client_extensions, host=handshake_flow.request.host, target=handshake_flow.request.path) |
47 |
+ data = self.connections[self.server_conn].send(request) |
48 |
+ self.connections[self.client_conn].receive_data(data) |
49 |
+ |
50 |
event = next(self.connections[self.client_conn].events()) |
51 |
- assert isinstance(event, events.ConnectionRequested) |
52 |
+ assert isinstance(event, events.Request) |
53 |
|
54 |
- self.connections[self.client_conn].accept(event) |
55 |
- self.connections[self.server_conn].receive_bytes(self.connections[self.client_conn].bytes_to_send()) |
56 |
- assert isinstance(next(self.connections[self.server_conn].events()), events.ConnectionEstablished) |
57 |
+ data = self.connections[self.client_conn].send(AcceptConnection(extensions=server_extensions)) |
58 |
+ self.connections[self.server_conn].receive_data(data) |
59 |
+ assert isinstance(next(self.connections[self.server_conn].events()), events.AcceptConnection) |
60 |
|
61 |
def _handle_event(self, event, source_conn, other_conn, is_server): |
62 |
- if isinstance(event, events.DataReceived): |
63 |
- return self._handle_data_received(event, source_conn, other_conn, is_server) |
64 |
- elif isinstance(event, events.PingReceived): |
65 |
- return self._handle_ping_received(event, source_conn, other_conn, is_server) |
66 |
- elif isinstance(event, events.PongReceived): |
67 |
- return self._handle_pong_received(event, source_conn, other_conn, is_server) |
68 |
- elif isinstance(event, events.ConnectionClosed): |
69 |
- return self._handle_connection_closed(event, source_conn, other_conn, is_server) |
70 |
+ if isinstance(event, events.Message): |
71 |
+ return self._handle_message(event, source_conn, other_conn, is_server) |
72 |
+ elif isinstance(event, events.Ping): |
73 |
+ return self._handle_ping(event, source_conn, other_conn, is_server) |
74 |
+ elif isinstance(event, events.Pong): |
75 |
+ return self._handle_pong(event, source_conn, other_conn, is_server) |
76 |
+ elif isinstance(event, events.CloseConnection): |
77 |
+ return self._handle_close_connection(event, source_conn, other_conn, is_server) |
78 |
|
79 |
# fail-safe for unhandled events |
80 |
return True # pragma: no cover |
81 |
|
82 |
- def _handle_data_received(self, event, source_conn, other_conn, is_server): |
83 |
+ def _handle_message(self, event, source_conn, other_conn, is_server): |
84 |
fb = self.server_frame_buffer if is_server else self.client_frame_buffer |
85 |
fb.append(event.data) |
86 |
|
87 |
if event.message_finished: |
88 |
original_chunk_sizes = [len(f) for f in fb] |
89 |
|
90 |
- if isinstance(event, events.TextReceived): |
91 |
+ if isinstance(event, events.TextMessage): |
92 |
message_type = wsproto.frame_protocol.Opcode.TEXT |
93 |
payload = ''.join(fb) |
94 |
else: |
95 |
@@ -127,19 +129,20 @@ class WebSocketLayer(base.Layer): |
96 |
yield (payload[i:i + chunk_size], True if i + chunk_size >= len(payload) else False) |
97 |
|
98 |
for chunk, final in get_chunk(websocket_message.content): |
99 |
- self.connections[other_conn].send_data(chunk, final) |
100 |
- other_conn.send(self.connections[other_conn].bytes_to_send()) |
101 |
+ data = self.connections[other_conn].send(Message(data=chunk, message_finished=final)) |
102 |
+ other_conn.send(data) |
103 |
|
104 |
if self.flow.stream: |
105 |
- self.connections[other_conn].send_data(event.data, event.message_finished) |
106 |
- other_conn.send(self.connections[other_conn].bytes_to_send()) |
107 |
+ data = self.connections[other_conn].send(Message(data=event.data, message_finished=event.message_finished)) |
108 |
+ other_conn.send(data) |
109 |
return True |
110 |
|
111 |
- def _handle_ping_received(self, event, source_conn, other_conn, is_server): |
112 |
- # PING is automatically answered with a PONG by wsproto |
113 |
- self.connections[other_conn].ping() |
114 |
- other_conn.send(self.connections[other_conn].bytes_to_send()) |
115 |
- source_conn.send(self.connections[source_conn].bytes_to_send()) |
116 |
+ def _handle_ping(self, event, source_conn, other_conn, is_server): |
117 |
+ # Use event.response to create the approprate Pong response |
118 |
+ data = self.connections[other_conn].send(Ping()) |
119 |
+ other_conn.send(data) |
120 |
+ data = self.connections[source_conn].send(event.response()) |
121 |
+ source_conn.send(data) |
122 |
self.log( |
123 |
"Ping Received from {}".format("server" if is_server else "client"), |
124 |
"info", |
125 |
@@ -147,7 +150,7 @@ class WebSocketLayer(base.Layer): |
126 |
) |
127 |
return True |
128 |
|
129 |
- def _handle_pong_received(self, event, source_conn, other_conn, is_server): |
130 |
+ def _handle_pong(self, event, source_conn, other_conn, is_server): |
131 |
self.log( |
132 |
"Pong Received from {}".format("server" if is_server else "client"), |
133 |
"info", |
134 |
@@ -155,14 +158,15 @@ class WebSocketLayer(base.Layer): |
135 |
) |
136 |
return True |
137 |
|
138 |
- def _handle_connection_closed(self, event, source_conn, other_conn, is_server): |
139 |
+ def _handle_close_connection(self, event, source_conn, other_conn, is_server): |
140 |
self.flow.close_sender = "server" if is_server else "client" |
141 |
self.flow.close_code = event.code |
142 |
self.flow.close_reason = event.reason |
143 |
|
144 |
- self.connections[other_conn].close(event.code, event.reason) |
145 |
- other_conn.send(self.connections[other_conn].bytes_to_send()) |
146 |
- source_conn.send(self.connections[source_conn].bytes_to_send()) |
147 |
+ data = self.connections[other_conn].send(CloseConnection(code=event.code, reason=event.reason)) |
148 |
+ other_conn.send(data) |
149 |
+ data = self.connections[source_conn].send(event.response()) |
150 |
+ source_conn.send(data) |
151 |
|
152 |
return False |
153 |
|
154 |
@@ -170,8 +174,7 @@ class WebSocketLayer(base.Layer): |
155 |
while True: |
156 |
try: |
157 |
payload = message_queue.get_nowait() |
158 |
- self.connections[endpoint].send_data(payload, final=True) |
159 |
- data = self.connections[endpoint].bytes_to_send() |
160 |
+ data = self.connections[endpoint].send(Message(data=payload, message_finished=True)) |
161 |
endpoint.send(data) |
162 |
except queue.Empty: |
163 |
break |
164 |
@@ -197,8 +200,8 @@ class WebSocketLayer(base.Layer): |
165 |
is_server = (source_conn == self.server_conn) |
166 |
|
167 |
frame = websockets.Frame.from_file(source_conn.rfile) |
168 |
- self.connections[source_conn].receive_bytes(bytes(frame)) |
169 |
- source_conn.send(self.connections[source_conn].bytes_to_send()) |
170 |
+ data = self.connections[source_conn].receive_data(bytes(frame)) |
171 |
+ source_conn.send(data) |
172 |
|
173 |
if close_received: |
174 |
return |