コード例 #1
0
def test_close_with_long_reason():
    # Long close reasons get silently truncated
    proto = fp.FrameProtocol(client=False, extensions=[])
    data = proto.close(code=fp.CloseReason.NORMAL_CLOSURE, reason="x" * 200)
    assert data == unhexlify("887d03e8") + b"x" * 123

    # While preserving valid utf-8
    proto = fp.FrameProtocol(client=False, extensions=[])
    # pound sign is 2 bytes in utf-8, so naive truncation to 123 bytes will
    # cut it in half. Instead we truncate to 122 bytes.
    data = proto.close(code=fp.CloseReason.NORMAL_CLOSURE, reason="£" * 100)
    assert data == unhexlify("887c03e8") + "£".encode("utf-8") * 61
コード例 #2
0
 def test_single_short_text_data(self) -> None:
     proto = fp.FrameProtocol(client=False, extensions=[])
     payload = "😃😄🙃😉"
     data = proto.send_data(payload, fin=True)
     payload = payload.encode("utf8")  # type: ignore
     assert data == b"\x81" + bytearray([len(payload)
                                         ]) + payload  # type: ignore
コード例 #3
0
    def test_data_we_have_no_idea_what_to_do_with(self) -> None:
        proto = fp.FrameProtocol(client=False, extensions=[])
        payload: Dict[str, str] = dict()

        with pytest.raises(ValueError):
            # Intentionally passing illegal type.
            proto.send_data(payload)  # type: ignore
コード例 #4
0
 def test_overly_reasoned_close(self):
     proto = fp.FrameProtocol(client=False, extensions=[])
     reason = u"¯\_(ツ)_/¯" * 10
     data = proto.close(code=fp.CloseReason.NORMAL_CLOSURE, reason=reason)
     assert bytes(data[0:1]) == b"\x88"
     assert len(data) <= 127
     assert data[4:].decode("utf8")
コード例 #5
0
 def test_outbound_handling_single_frame(self):
     ext = self.FakeExtension()
     proto = fp.FrameProtocol(client=False, extensions=[ext])
     payload = u"😃😄🙃😉"
     data = proto.send_data(payload, fin=True)
     payload = (payload + u"®").encode("utf8")
     assert data == b"\x91" + bytearray([len(payload)]) + payload
コード例 #6
0
    def test_client_inbound_compressed_multiple_data_frames(self, client):
        payload = b'x' * 23
        compressed_payload = b'\xaa\xa8\xc0\n\x00\x00'
        split = 3
        data = b''

        ext = wpext.PerMessageDeflate()
        ext._enabled = True
        proto = fp.FrameProtocol(client=client, extensions=[ext])

        result = ext.frame_inbound_header(proto, fp.Opcode.BINARY,
                                          fp.RsvBits(True, False, False),
                                          split)
        assert result.rsv1
        result = ext.frame_inbound_payload_data(proto,
                                                compressed_payload[:split])
        assert not isinstance(result, fp.CloseReason)
        data += result
        assert ext.frame_inbound_complete(proto, False) is None

        result = ext.frame_inbound_header(proto, fp.Opcode.CONTINUATION,
                                          fp.RsvBits(False, False, False),
                                          len(compressed_payload) - split)
        assert result.rsv1
        result = ext.frame_inbound_payload_data(proto,
                                                compressed_payload[split:])
        assert not isinstance(result, fp.CloseReason)
        data += result

        result = ext.frame_inbound_complete(proto, True)
        assert not isinstance(result, fp.CloseReason)
        data += result

        assert data == payload
コード例 #7
0
    def test_client_decompress_after_uncompressible_frame(
            self, client: bool) -> None:
        ext = wpext.PerMessageDeflate()
        ext._enabled = True
        proto = fp.FrameProtocol(client=client, extensions=[ext])

        # A PING frame
        result = ext.frame_inbound_header(proto, fp.Opcode.PING,
                                          fp.RsvBits(False, False, False), 0)
        result2 = ext.frame_inbound_payload_data(proto, b"")
        assert not isinstance(result2, fp.CloseReason)
        assert ext.frame_inbound_complete(proto, True) is None

        # A compressed TEXT frame
        payload = b"x" * 23
        compressed_payload = b"\xaa\xa8\xc0\n\x00\x00"

        result3 = ext.frame_inbound_header(
            proto,
            fp.Opcode.TEXT,
            fp.RsvBits(True, False, False),
            len(compressed_payload),
        )
        assert isinstance(result3, fp.RsvBits)
        assert result3.rsv1
        result4 = ext.frame_inbound_payload_data(proto, compressed_payload)
        assert result4 == payload

        result5 = ext.frame_inbound_complete(proto, True)
        assert not isinstance(result5, fp.CloseReason)
コード例 #8
0
    def test_inbound_bad_zlib_decoder_end_state(
            self, monkeypatch: MonkeyPatch) -> None:
        compressed_payload = b"x" * 23

        ext = wpext.PerMessageDeflate()
        ext._enabled = True
        proto = fp.FrameProtocol(client=True, extensions=[ext])

        result = ext.frame_inbound_header(
            proto,
            fp.Opcode.BINARY,
            fp.RsvBits(True, False, False),
            len(compressed_payload),
        )
        assert isinstance(result, fp.RsvBits)
        assert result.rsv1

        class FailDecompressor:
            def decompress(self, data: bytes) -> bytes:
                return b""

            def flush(self) -> None:
                raise zlib.error()

        monkeypatch.setattr(ext, "_decompressor", FailDecompressor())

        result2 = ext.frame_inbound_complete(proto, True)
        assert result2 is fp.CloseReason.INVALID_FRAME_PAYLOAD_DATA
コード例 #9
0
    def test_decompressor_reset(self, client: bool,
                                no_context_takeover: bool) -> None:
        if client:
            args = {"server_no_context_takeover": no_context_takeover}
        else:
            args = {"client_no_context_takeover": no_context_takeover}
        ext = wpext.PerMessageDeflate(**args)
        ext._enabled = True
        proto = fp.FrameProtocol(client=client, extensions=[ext])

        result = ext.frame_inbound_header(proto, fp.Opcode.BINARY,
                                          fp.RsvBits(True, False, False), 0)
        assert isinstance(result, fp.RsvBits)
        assert result.rsv1

        assert ext._decompressor is not None

        result2 = ext.frame_inbound_complete(proto, True)
        assert not isinstance(result2, fp.CloseReason)

        if no_context_takeover:
            assert ext._decompressor is None
        else:
            assert ext._decompressor is not None

        result3 = ext.frame_inbound_header(proto, fp.Opcode.BINARY,
                                           fp.RsvBits(True, False, False), 0)
        assert isinstance(result3, fp.RsvBits)
        assert result3.rsv1

        assert ext._decompressor is not None
コード例 #10
0
    def _close_test(self,
                    code: Optional[int],
                    reason: str = None,
                    reason_bytes: bytes = None) -> None:
        payload = b""
        if code:
            payload += struct.pack("!H", code)
        if reason:
            payload += reason.encode("utf8")
        elif reason_bytes:
            payload += reason_bytes

        frame_bytes = b"\x88" + bytearray([len(payload)]) + payload

        protocol = fp.FrameProtocol(client=True, extensions=[])
        protocol.receive_bytes(frame_bytes)
        frames = list(protocol.received_frames())
        assert len(frames) == 1
        frame = frames[0]
        assert frame.opcode == fp.Opcode.CLOSE
        assert frame.payload[0] == code or fp.CloseReason.NO_STATUS_RCVD
        if reason:
            assert frame.payload[1] == reason
        else:
            assert not frame.payload[1]
コード例 #11
0
    def test_compressor_reset(self, client: bool,
                              no_context_takeover: bool) -> None:
        if client:
            args = {"client_no_context_takeover": no_context_takeover}
        else:
            args = {"server_no_context_takeover": no_context_takeover}
        ext = wpext.PerMessageDeflate(**args)
        ext._enabled = True
        proto = fp.FrameProtocol(client=client, extensions=[ext])
        rsv = fp.RsvBits(False, False, False)

        rsv, data = ext.frame_outbound(proto, fp.Opcode.BINARY, rsv, b"",
                                       False)
        assert rsv.rsv1 is True
        assert ext._compressor is not None

        rsv = fp.RsvBits(False, False, False)
        rsv, data = ext.frame_outbound(proto, fp.Opcode.CONTINUATION, rsv, b"",
                                       True)
        assert rsv.rsv1 is False
        if no_context_takeover:
            assert ext._compressor is None
        else:
            assert ext._compressor is not None

        rsv = fp.RsvBits(False, False, False)
        rsv, data = ext.frame_outbound(proto, fp.Opcode.BINARY, rsv, b"",
                                       False)
        assert rsv.rsv1 is True
        assert ext._compressor is not None
コード例 #12
0
 def test_reasoned_close(self):
     proto = fp.FrameProtocol(client=False, extensions=[])
     reason = u"¯\_(ツ)_/¯"
     expected_payload = struct.pack(
         "!H", fp.CloseReason.NORMAL_CLOSURE) + reason.encode("utf8")
     data = proto.close(code=fp.CloseReason.NORMAL_CLOSURE, reason=reason)
     assert data == b"\x88" + bytearray([len(expected_payload)
                                         ]) + expected_payload
コード例 #13
0
    def test_close_one_byte_code(self):
        frame_bytes = b"\x88\x01\x0e"
        protocol = fp.FrameProtocol(client=True, extensions=[])

        with pytest.raises(fp.ParseFailed) as exc:
            protocol.receive_bytes(frame_bytes)
            list(protocol.received_frames())
        assert exc.value.code == fp.CloseReason.PROTOCOL_ERROR
コード例 #14
0
 def test_reasoned_close(self):
     proto = fp.FrameProtocol(client=False, extensions=[])
     reason = u'¯\_(ツ)_/¯'
     expected_payload = struct.pack('!H', fp.CloseReason.NORMAL_CLOSURE) + \
         reason.encode('utf8')
     data = proto.close(code=fp.CloseReason.NORMAL_CLOSURE, reason=reason)
     assert data == b'\x88' + bytearray([len(expected_payload)]) + \
         expected_payload
コード例 #15
0
    def test_mismatched_data_messages2(self):
        proto = fp.FrameProtocol(client=False, extensions=[])
        payload = b"it's all just ascii, right?"
        data = proto.send_data(payload, fin=False)
        assert data == b"\x02" + bytearray([len(payload)]) + payload

        payload = u"✔️☑️✅✔︎☑"
        with pytest.raises(TypeError):
            proto.send_data(payload)
コード例 #16
0
    def test_multiple_short_binary_data(self):
        proto = fp.FrameProtocol(client=False, extensions=[])
        payload = b"it's all just ascii, right?"
        data = proto.send_data(payload, fin=False)
        assert data == b"\x02" + bytearray([len(payload)]) + payload

        payload = b"sure no worries"
        data = proto.send_data(payload, fin=True)
        assert data == b"\x80" + bytearray([len(payload)]) + payload
コード例 #17
0
 def test_client_side_masking_short_frame(self) -> None:
     proto = fp.FrameProtocol(client=True, extensions=[])
     payload = b"x" * 125
     data = proto.send_data(payload, fin=True)
     assert data[0] == 0x82
     assert struct.unpack("!B", data[1:2])[0] == len(payload) | 0x80
     masking_key = data[2:6]
     maskbytes = itertools.cycle(masking_key)
     assert data[6:] == bytearray(b ^ next(maskbytes) for b in bytearray(payload))
コード例 #18
0
    def test_mismatched_data_messages1(self):
        proto = fp.FrameProtocol(client=False, extensions=[])
        payload = u"😃😄🙃😉"
        data = proto.send_data(payload, fin=False)
        payload = payload.encode("utf8")
        assert data == b"\x01" + bytearray([len(payload)]) + payload

        payload = b"seriously, all ascii"
        with pytest.raises(TypeError):
            proto.send_data(payload)
コード例 #19
0
 def test_client_side_masking_eight_byte_frame(self) -> None:
     proto = fp.FrameProtocol(client=True, extensions=[])
     payload = b"x" * 65536
     data = proto.send_data(payload, fin=True)
     assert data[0] == 0x82
     assert data[1] == 0xFF
     assert struct.unpack("!Q", data[2:10])[0] == len(payload)
     masking_key = data[10:14]
     maskbytes = itertools.cycle(masking_key)
     assert data[14:] == bytearray(b ^ next(maskbytes) for b in bytearray(payload))
コード例 #20
0
    def test_multiple_short_text_data(self):
        proto = fp.FrameProtocol(client=False, extensions=[])
        payload = u"😃😄🙃😉"
        data = proto.send_data(payload, fin=False)
        payload = payload.encode("utf8")
        assert data == b"\x01" + bytearray([len(payload)]) + payload

        payload = u"🙈🙉🙊"
        data = proto.send_data(payload, fin=True)
        payload = payload.encode("utf8")
        assert data == b"\x80" + bytearray([len(payload)]) + payload
コード例 #21
0
    def test_multiple_short_text_data(self):
        proto = fp.FrameProtocol(client=False, extensions=[])
        payload = u'😃😄🙃😉'
        data = proto.send_data(payload, fin=False)
        payload = payload.encode('utf8')
        assert data == b'\x01' + bytearray([len(payload)]) + payload

        payload = u'🙈🙉🙊'
        data = proto.send_data(payload, fin=True)
        payload = payload.encode('utf8')
        assert data == b'\x80' + bytearray([len(payload)]) + payload
コード例 #22
0
 def test_client_side_masking_two_byte_frame(self):
     proto = fp.FrameProtocol(client=True, extensions=[])
     payload = b"x" * 126
     data = proto.send_data(payload, fin=True)
     assert data[0] == 0x82
     assert data[1] == 0xFE
     assert struct.unpack("!H", data[2:4])[0] == len(payload)
     masking_key = data[4:8]
     maskbytes = itertools.cycle(masking_key)
     assert data[8:] == bytearray(b ^ next(maskbytes)
                                  for b in bytearray(payload))
コード例 #23
0
    def test_inbound_compressed_continuation_frame(self) -> None:
        payload = b"x" * 23

        ext = wpext.PerMessageDeflate()
        ext._enabled = True
        proto = fp.FrameProtocol(client=True, extensions=[ext])

        result = ext.frame_inbound_header(proto, fp.Opcode.CONTINUATION,
                                          fp.RsvBits(True, False, False),
                                          len(payload))
        assert result == fp.CloseReason.PROTOCOL_ERROR
コード例 #24
0
    def test_outbound_uncompressible_opcode(self) -> None:
        ext = wpext.PerMessageDeflate()
        ext._enabled = True
        proto = fp.FrameProtocol(client=True, extensions=[ext])

        rsv = fp.RsvBits(False, False, False)
        payload = b"x" * 23

        rsv, data = ext.frame_outbound(proto, fp.Opcode.PING, rsv, payload, True)

        assert rsv.rsv1 is False
        assert data == payload
コード例 #25
0
    def test_outbound_handling_multiple_frames(self):
        ext = self.FakeExtension()
        proto = fp.FrameProtocol(client=False, extensions=[ext])
        payload = u'😃😄🙃😉'
        data = proto.send_data(payload, fin=False)
        payload = payload.encode('utf8')
        assert data == b'\x11' + bytearray([len(payload)]) + payload

        payload = u'¯\_(ツ)_/¯'
        data = proto.send_data(payload, fin=True)
        payload = (payload + u'®').encode('utf8')
        assert data == b'\x80' + bytearray([len(payload)]) + payload
コード例 #26
0
    def test_random_control_frame(self):
        payload = b"give me one ping vasily"
        frame_bytes = b"\x89" + bytearray([len(payload)]) + payload

        protocol = fp.FrameProtocol(client=True, extensions=[])
        protocol.receive_bytes(frame_bytes)
        frames = list(protocol.received_frames())
        assert len(frames) == 1
        frame = frames[0]
        assert frame.opcode == fp.Opcode.PING
        assert len(frame.payload) == len(payload)
        assert frame.payload == payload
コード例 #27
0
    def test_outbound_handling_multiple_frames(self) -> None:
        ext = self.FakeExtension()
        proto = fp.FrameProtocol(client=False, extensions=[ext])
        payload = "😃😄🙃😉"
        data = proto.send_data(payload, fin=False)
        payload_bytes = payload.encode("utf8")
        assert data == b"\x11" + bytearray([len(payload_bytes)]) + payload_bytes

        payload = r"¯\_(ツ)_/¯"
        data = proto.send_data(payload, fin=True)
        payload_bytes = (payload + "®").encode("utf8")
        assert data == b"\x80" + bytearray([len(payload_bytes)]) + payload_bytes
コード例 #28
0
    def test_inbound_bad_zlib_payload(self):
        compressed_payload = b'x' * 23

        ext = wpext.PerMessageDeflate()
        ext._enabled = True
        proto = fp.FrameProtocol(client=True, extensions=[ext])

        result = ext.frame_inbound_header(proto, fp.Opcode.BINARY,
                                          fp.RsvBits(True, False, False),
                                          len(compressed_payload))
        assert result.rsv1
        result = ext.frame_inbound_payload_data(proto, compressed_payload)
        assert result is fp.CloseReason.INVALID_FRAME_PAYLOAD_DATA
コード例 #29
0
    def test_outbound_compress_single_frame(self, client: bool) -> None:
        ext = wpext.PerMessageDeflate()
        ext._enabled = True
        proto = fp.FrameProtocol(client=client, extensions=[ext])

        rsv = fp.RsvBits(False, False, False)
        payload = b"x" * 23
        compressed_payload = b"\xaa\xa8\xc0\n\x00\x00"

        rsv, data = ext.frame_outbound(proto, fp.Opcode.BINARY, rsv, payload, True)

        assert rsv.rsv1 is True
        assert data == compressed_payload
コード例 #30
0
    def test_long_text_message(self):
        payload = "x" * 65535
        encoded_payload = payload.encode("utf-8")
        payload_len = struct.pack("!H", len(encoded_payload))
        frame_bytes = b"\x81\x7e" + payload_len + encoded_payload

        protocol = fp.FrameProtocol(client=True, extensions=[])
        protocol.receive_bytes(frame_bytes)
        frames = list(protocol.received_frames())
        assert len(frames) == 1
        frame = frames[0]
        assert frame.opcode == fp.Opcode.TEXT
        assert len(frame.payload) == len(payload)
        assert frame.payload == payload