Skip to content

Commit 79d15d5

Browse files
committed
Reduce complexity of parse_more_gen
1 parent 856c74b commit 79d15d5

File tree

1 file changed

+55
-42
lines changed

1 file changed

+55
-42
lines changed

wsproto/frame_protocol.py

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,46 @@ def _process_CLOSE_payload(self, data):
247247
CloseReason.INVALID_FRAME_PAYLOAD_DATA)
248248
return (code, reason)
249249

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

258298
unfinished_message_opcode = None
259299
unfinished_message_decoder = None
260-
while True:
300+
effective_opcode = None
301+
while effective_opcode is not Opcode.CLOSE:
261302
header = yield from self._parse_header()
262303

263304
if unfinished_message_opcode is None:
@@ -286,47 +327,19 @@ def parse_more_gen(self):
286327
unfinished_message_decoder is None:
287328
unfinished_message_decoder = getincrementaldecoder("utf-8")()
288329

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
330+
message_finished = yield from self._parse_frame_payload(
331+
opcode=effective_opcode,
332+
remaining=header.payload_len,
333+
message_decoder=unfinished_message_decoder,
334+
masker=masker,
335+
fin_flag=header.fin
336+
)
337+
338+
if message_finished and not effective_opcode.iscontrol():
339+
# This isn't a control, so if this message is finished
340+
# then the unfinished message is also finished.
341+
unfinished_message_opcode = None
342+
unfinished_message_decoder = None
330343

331344
def receive_bytes(self, data):
332345
self._buffer += data

0 commit comments

Comments
 (0)