(out, buf)
| 78 | |
| 79 | |
| 80 | def WebSocketParser(out, buf): |
| 81 | while True: |
| 82 | fin, opcode, payload = yield from parse_frame(buf) |
| 83 | |
| 84 | if opcode == OPCODE_CLOSE: |
| 85 | if len(payload) >= 2: |
| 86 | close_code = UNPACK_CLOSE_CODE(payload[:2])[0] |
| 87 | if close_code not in ALLOWED_CLOSE_CODES and close_code < 3000: |
| 88 | raise WebSocketError( |
| 89 | CLOSE_PROTOCOL_ERROR, |
| 90 | 'Invalid close code: {}'.format(close_code)) |
| 91 | try: |
| 92 | close_message = payload[2:].decode('utf-8') |
| 93 | except UnicodeDecodeError as exc: |
| 94 | raise WebSocketError( |
| 95 | CLOSE_INVALID_TEXT, |
| 96 | 'Invalid UTF-8 text message') from exc |
| 97 | msg = Message(OPCODE_CLOSE, close_code, close_message) |
| 98 | elif payload: |
| 99 | raise WebSocketError( |
| 100 | CLOSE_PROTOCOL_ERROR, |
| 101 | 'Invalid close frame: {} {} {!r}'.format( |
| 102 | fin, opcode, payload)) |
| 103 | else: |
| 104 | msg = Message(OPCODE_CLOSE, 0, '') |
| 105 | |
| 106 | out.feed_data(msg, 0) |
| 107 | |
| 108 | elif opcode == OPCODE_PING: |
| 109 | out.feed_data(Message(OPCODE_PING, payload, ''), len(payload)) |
| 110 | |
| 111 | elif opcode == OPCODE_PONG: |
| 112 | out.feed_data(Message(OPCODE_PONG, payload, ''), len(payload)) |
| 113 | |
| 114 | elif opcode not in (OPCODE_TEXT, OPCODE_BINARY): |
| 115 | raise WebSocketError( |
| 116 | CLOSE_PROTOCOL_ERROR, "Unexpected opcode={!r}".format(opcode)) |
| 117 | else: |
| 118 | # load text/binary |
| 119 | data = [payload] |
| 120 | |
| 121 | while not fin: |
| 122 | fin, _opcode, payload = yield from parse_frame(buf, True) |
| 123 | |
| 124 | # We can receive ping/close in the middle of |
| 125 | # text message, Case 5.* |
| 126 | if _opcode == OPCODE_PING: |
| 127 | out.feed_data( |
| 128 | Message(OPCODE_PING, payload, ''), len(payload)) |
| 129 | fin, _opcode, payload = yield from parse_frame(buf, True) |
| 130 | elif _opcode == OPCODE_CLOSE: |
| 131 | if len(payload) >= 2: |
| 132 | close_code = UNPACK_CLOSE_CODE(payload[:2])[0] |
| 133 | if (close_code not in ALLOWED_CLOSE_CODES and |
| 134 | close_code < 3000): |
| 135 | raise WebSocketError( |
| 136 | CLOSE_PROTOCOL_ERROR, |
| 137 | 'Invalid close code: {}'.format(close_code)) |
nothing calls this directly
no test coverage detected