Skip to content

Commit a65d3cd

Browse files
authored
Merge pull request #14 from python-hyper/clean-linter
Clean up linter failures
2 parents 0872c53 + 60deba5 commit a65d3cd

File tree

3 files changed

+82
-62
lines changed

3 files changed

+82
-62
lines changed

.travis/run.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ install_wsproto() {
1515
case "$MODE" in
1616
flake8)
1717
pip install flake8
18-
flake8 --max-complexity 20 wsproto
18+
flake8 --max-complexity 12 wsproto
1919
;;
2020

2121
docs)

test/test_frame_protocol.py

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import struct
44
import wsproto.frame_protocol as fp
55

6+
67
def test_close_with_long_reason():
78
# Long close reasons get silently truncated
89
proto = fp.FrameProtocol(client=False, extensions=[])

wsproto/frame_protocol.py

+80-61
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,28 @@ def _consume_exactly(self, nbytes):
142142
yield
143143
return (yield from self._consume_at_most(nbytes))
144144

145+
def _parse_extended_payload_length(self, opcode, payload_len):
146+
if opcode.iscontrol() and payload_len > 125:
147+
raise ParseFailed("Control frame with payload len > 125")
148+
if payload_len == 126:
149+
data = yield from self._consume_exactly(2)
150+
(payload_len,) = struct.unpack("!H", data)
151+
if payload_len <= 125:
152+
raise ParseFailed(
153+
"Payload length used 2 bytes when 1 would have sufficed")
154+
elif payload_len == 127:
155+
data = yield from self._consume_exactly(8)
156+
(payload_len,) = struct.unpack("!Q", data)
157+
if payload_len < 2 ** 16:
158+
raise ParseFailed(
159+
"Payload length used 8 bytes when 2 would have sufficed")
160+
if payload_len >> 63:
161+
# I'm not sure why this is illegal, but that's what the RFC
162+
# says, so...
163+
raise ParseFailed("8-byte payload length with non-zero MSB")
164+
165+
return payload_len
166+
145167
def _parse_header(self):
146168
# returns a Header object
147169
(fin_rsv_opcode,) = yield from self._consume_exactly(1)
@@ -161,25 +183,9 @@ def _parse_header(self):
161183
(mask_len,) = yield from self._consume_exactly(1)
162184
has_mask = bool(mask_len & 0x80)
163185
payload_len = mask_len & 0x7f
164-
165-
if opcode.iscontrol() and payload_len > 125:
166-
raise ParseFailed("Control frame with payload len > 125")
167-
if payload_len == 126:
168-
data = yield from self._consume_exactly(2)
169-
(payload_len,) = struct.unpack("!H", data)
170-
if payload_len <= 125:
171-
raise ParseFailed(
172-
"Payload length used 2 bytes when 1 would have sufficed")
173-
elif payload_len == 127:
174-
data = yield from self._consume_exactly(8)
175-
(payload_len,) = struct.unpack("!Q", data)
176-
if payload_len < 2 ** 16:
177-
raise ParseFailed(
178-
"Payload length used 8 bytes when 2 would have sufficed")
179-
if payload_len >> 63:
180-
# I'm not sure why this is illegal, but that's what the RFC
181-
# says, so...
182-
raise ParseFailed("8-byte payload length with non-zero MSB")
186+
payload_len = yield from self._parse_extended_payload_length(
187+
opcode, payload_len
188+
)
183189

184190
for extension in self.extensions:
185191
result = extension.frame_inbound_header(
@@ -247,6 +253,46 @@ def _process_CLOSE_payload(self, data):
247253
CloseReason.INVALID_FRAME_PAYLOAD_DATA)
248254
return (code, reason)
249255

256+
def _parse_frame_payload(self,
257+
opcode,
258+
remaining,
259+
message_decoder,
260+
masker,
261+
fin_flag):
262+
frame_finished = False
263+
message_finished = False
264+
while not frame_finished:
265+
# For control frames, we collect all the data and return it as
266+
# a single lump. For message frames, we stream out chunks as
267+
# they arrive, to minimize buffering.
268+
if opcode.iscontrol():
269+
data = yield from self._consume_exactly(remaining)
270+
else:
271+
data = yield from self._consume_at_most(remaining)
272+
remaining -= len(data)
273+
frame_finished = (remaining == 0)
274+
message_finished = (frame_finished and fin_flag)
275+
276+
data = self._process_payload_chunk(masker, data)
277+
if frame_finished:
278+
data += self._process_payload_complete(fin_flag)
279+
280+
if opcode is Opcode.CLOSE:
281+
data = self._process_CLOSE_payload(data)
282+
283+
if not opcode.iscontrol():
284+
if message_decoder is not None:
285+
try:
286+
data = message_decoder.decode(data, message_finished)
287+
except UnicodeDecodeError as exc:
288+
raise ParseFailed(
289+
str(exc),
290+
CloseReason.INVALID_FRAME_PAYLOAD_DATA)
291+
292+
yield Frame(opcode, data, frame_finished, message_finished)
293+
294+
return message_finished
295+
250296
def parse_more_gen(self):
251297
# Consume as much as we can from self._buffer, yielding events, and
252298
# then yield None when we need more data. Or raise ParseFailed.
@@ -257,7 +303,8 @@ def parse_more_gen(self):
257303

258304
unfinished_message_opcode = None
259305
unfinished_message_decoder = None
260-
while True:
306+
effective_opcode = None
307+
while effective_opcode is not Opcode.CLOSE:
261308
header = yield from self._parse_header()
262309

263310
if unfinished_message_opcode is None:
@@ -286,47 +333,19 @@ def parse_more_gen(self):
286333
unfinished_message_decoder is None:
287334
unfinished_message_decoder = getincrementaldecoder("utf-8")()
288335

289-
remaining = header.payload_len
290-
frame_finished = False
291-
while not frame_finished:
292-
# For control frames, we collect all the data and return it as
293-
# a single lump. For message frames, we stream out chunks as
294-
# they arrive, to minimize buffering.
295-
if effective_opcode.iscontrol():
296-
data = yield from self._consume_exactly(remaining)
297-
else:
298-
data = yield from self._consume_at_most(remaining)
299-
remaining -= len(data)
300-
frame_finished = (remaining == 0)
301-
message_finished = (frame_finished and header.fin)
302-
303-
data = self._process_payload_chunk(masker, data)
304-
if frame_finished:
305-
data += self._process_payload_complete(header.fin)
306-
307-
if effective_opcode is Opcode.CLOSE:
308-
data = self._process_CLOSE_payload(data)
309-
310-
if not effective_opcode.iscontrol():
311-
if unfinished_message_decoder is not None:
312-
try:
313-
data = unfinished_message_decoder.decode(
314-
data, message_finished)
315-
except UnicodeDecodeError as exc:
316-
raise ParseFailed(
317-
str(exc),
318-
CloseReason.INVALID_FRAME_PAYLOAD_DATA)
319-
# This isn't a control, so if this message is finished
320-
# then the unfinished message is also finished.
321-
if message_finished:
322-
unfinished_message_opcode = None
323-
unfinished_message_decoder = None
324-
325-
yield Frame(
326-
effective_opcode, data, frame_finished, message_finished)
327-
328-
if effective_opcode is Opcode.CLOSE:
329-
break
336+
message_finished = yield from self._parse_frame_payload(
337+
opcode=effective_opcode,
338+
remaining=header.payload_len,
339+
message_decoder=unfinished_message_decoder,
340+
masker=masker,
341+
fin_flag=header.fin
342+
)
343+
344+
if message_finished and not effective_opcode.iscontrol():
345+
# This isn't a control, so if this message is finished
346+
# then the unfinished message is also finished.
347+
unfinished_message_opcode = None
348+
unfinished_message_decoder = None
330349

331350
def receive_bytes(self, data):
332351
self._buffer += data

0 commit comments

Comments
 (0)