Esempio n. 1
0
def test_inject_message(ws_testdata):
    tctx, playbook, flow = ws_testdata
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply() >>
            WebSocketMessageInjected(
                flow, WebSocketMessage(Opcode.TEXT, False, b"hello")) <<
            websocket.WebsocketMessageHook(flow))
    assert flow.websocket.messages[-1].content == b"hello"
    assert flow.websocket.messages[-1].from_client is False
    assert (playbook >> reply() << SendData(tctx.client, b"\x81\x05hello"))
Esempio n. 2
0
    def _handle_data_frame(self, frame, source_conn, other_conn, is_server):
        fb = self.server_frame_buffer if is_server else self.client_frame_buffer
        fb.append(frame)

        if frame.header.fin:
            payload = b''.join(f.payload for f in fb)
            original_chunk_sizes = [len(f.payload) for f in fb]
            message_type = fb[0].header.opcode
            compressed_message = fb[0].header.rsv1
            fb.clear()

            websocket_message = WebSocketMessage(message_type, not is_server,
                                                 payload)
            length = len(websocket_message.content)
            self.flow.messages.append(websocket_message)
            self.channel.ask("websocket_message", self.flow)

            def get_chunk(payload):
                if len(payload) == length:
                    # message has the same length, we can reuse the same sizes
                    pos = 0
                    for s in original_chunk_sizes:
                        yield payload[pos:pos + s]
                        pos += s
                else:
                    # just re-chunk everything into 10kB frames
                    chunk_size = 10240
                    chunks = range(0, len(payload), chunk_size)
                    for i in chunks:
                        yield payload[i:i + chunk_size]

            frms = [
                websockets.Frame(
                    payload=chunk,
                    opcode=frame.header.opcode,
                    mask=(False if is_server else 1),
                    masking_key=(b'' if is_server else os.urandom(4)))
                for chunk in get_chunk(websocket_message.content)
            ]

            if len(frms) > 0:
                frms[-1].header.fin = True
            else:
                frms.append(
                    websockets.Frame(
                        fin=True,
                        opcode=websockets.OPCODE.CONTINUE,
                        mask=(False if is_server else 1),
                        masking_key=(b'' if is_server else os.urandom(4))))

            frms[0].header.opcode = message_type
            frms[0].header.rsv1 = compressed_message

            for frm in frms:
                other_conn.send(bytes(frm))

        return True
Esempio n. 3
0
    def _handle_data_received(self, event, source_conn, other_conn, is_server):
        fb = self.server_frame_buffer if is_server else self.client_frame_buffer
        fb.append(event.data)

        if event.message_finished:
            original_chunk_sizes = [len(f) for f in fb]

            if isinstance(event, events.TextReceived):
                message_type = wsproto.frame_protocol.Opcode.TEXT
                payload = ''.join(fb)
            else:
                message_type = wsproto.frame_protocol.Opcode.BINARY
                payload = b''.join(fb)

            fb.clear()

            websocket_message = WebSocketMessage(message_type, not is_server,
                                                 payload)
            length = len(websocket_message.content)
            self.flow.messages.append(websocket_message)
            self.channel.ask("websocket_message", self.flow)

            if not self.flow.stream:

                def get_chunk(payload):
                    if len(payload) == length:
                        # message has the same length, we can reuse the same sizes
                        pos = 0
                        for s in original_chunk_sizes:
                            yield (payload[pos:pos + s],
                                   True if pos + s == length else False)
                            pos += s
                    else:
                        # just re-chunk everything into 4kB frames
                        # header len = 4 bytes without masking key and 8 bytes with masking key
                        chunk_size = 4092 if is_server else 4088
                        chunks = range(0, len(payload), chunk_size)
                        for i in chunks:
                            yield (payload[i:i + chunk_size], True if
                                   i + chunk_size >= len(payload) else False)

                for chunk, final in get_chunk(websocket_message.content):
                    self.connections[other_conn].send_data(chunk, final)
                    other_conn.send(
                        self.connections[other_conn].bytes_to_send())

            else:
                self.connections[other_conn].send_data(event.data,
                                                       event.message_finished)
                other_conn.send(self.connections[other_conn].bytes_to_send())

        elif self.flow.stream:
            self.connections[other_conn].send_data(event.data,
                                                   event.message_finished)
            other_conn.send(self.connections[other_conn].bytes_to_send())

        return True