예제 #1
0
def test_drop_message(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply() >>
            DataReceived(tctx.server, b"\x81\x03foo") <<
            websocket.WebsocketMessageHook(flow))
    flow().messages[-1].content = ""
    assert (playbook >> reply() << None)
예제 #2
0
def test_close_disconnect(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply() >>
            ConnectionClosed(tctx.server) << CloseConnection(tctx.server) <<
            SendData(tctx.client, b"\x88\x02\x03\xe8") << CloseConnection(
                tctx.client) << websocket.WebsocketErrorHook(flow) >> reply()
            >> ConnectionClosed(tctx.client))
    assert "ABNORMAL_CLOSURE" in flow().error.msg
예제 #3
0
def test_modify_message(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply() >>
            DataReceived(tctx.server, b"\x81\x03foo") <<
            websocket.WebsocketMessageHook(flow))
    flow().messages[-1].content = flow().messages[-1].content.replace(
        "foo", "foobar")
    assert (playbook >> reply() << SendData(tctx.client, b"\x81\x06foobar"))
예제 #4
0
def test_unknown_ext(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    # noinspection PyUnresolvedReferences
    http_flow: HTTPFlow = playbook.layer.flow.handshake_flow
    http_flow.response.headers[
        "Sec-WebSocket-Extensions"] = "funky-bits; param=42"
    assert (
        playbook << Log("Ignoring unknown WebSocket extension 'funky-bits'.")
        << websocket.WebsocketStartHook(flow) >> reply())
예제 #5
0
def test_close_error(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply() >>
            DataReceived(tctx.server, b"\x88\x02\x0f\xa0") << SendData(
                tctx.server, masked(b"\x88\x02\x0f\xa0")) << CloseConnection(
                    tctx.server) << SendData(tctx.client, b"\x88\x02\x0f\xa0")
            << CloseConnection(
                tctx.client) << websocket.WebsocketErrorHook(flow) >> reply())
    assert "UNKNOWN_ERROR=4000" in flow().error.msg
예제 #6
0
def test_fragmented(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply() >>
            DataReceived(tctx.server, b"\x01\x03foo") >> DataReceived(
                tctx.server, b"\x80\x03bar") <<
            websocket.WebsocketMessageHook(flow) >> reply() << SendData(
                tctx.client, b"\x01\x03foo") << SendData(
                    tctx.client, b"\x80\x03bar"))
    assert flow().messages[-1].content == "foobar"
예제 #7
0
def test_deflate(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    # noinspection PyUnresolvedReferences
    http_flow: HTTPFlow = playbook.layer.flow.handshake_flow
    http_flow.response.headers[
        "Sec-WebSocket-Extensions"] = "permessage-deflate; server_max_window_bits=10"
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply()
            # https://tools.ietf.org/html/rfc7692#section-7.2.3.1
            >> DataReceived(tctx.server,
                            bytes.fromhex("c1 07 f2 48 cd c9 c9 07 00")) <<
            websocket.WebsocketMessageHook(flow) >> reply() << SendData(
                tctx.client, bytes.fromhex("c1 07 f2 48 cd c9 c9 07 00")))
    assert flow().messages[0].content == "Hello"
예제 #8
0
def test_protocol_error(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    assert (
        playbook << websocket.WebsocketStartHook(flow) >> reply() >>
        DataReceived(tctx.server, b"\x01\x03foo") >>
        DataReceived(tctx.server, b"\x02\x03bar") << SendData(
            tctx.server,
            masked(
                b"\x88/\x03\xeaexpected CONTINUATION, got <Opcode.BINARY: 2>"))
        << CloseConnection(tctx.server) << SendData(
            tctx.client,
            b"\x88/\x03\xeaexpected CONTINUATION, got <Opcode.BINARY: 2>") <<
        CloseConnection(
            tctx.client) << websocket.WebsocketErrorHook(flow) >> reply())
    assert not flow().messages
예제 #9
0
def test_close_normal(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    masked_close = Placeholder(bytes)
    close = Placeholder(bytes)
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply() >>
            DataReceived(tctx.client, masked_bytes(b"\x88\x00")) << SendData(
                tctx.server, masked_close) << CloseConnection(tctx.server) <<
            SendData(tctx.client, close) << CloseConnection(
                tctx.client) << websocket.WebsocketEndHook(flow) >> reply())
    # wsproto currently handles this inconsistently, see
    # https://github.com/python-hyper/wsproto/pull/153/files
    assert masked_close() == masked(
        b"\x88\x02\x03\xe8") or masked_close() == masked(b"\x88\x00")
    assert close() == b"\x88\x02\x03\xe8" or close() == b"\x88\x00"

    assert flow().close_code == 1005
예제 #10
0
def test_ping(ws_testdata):
    tctx, playbook = ws_testdata
    flow = Placeholder(WebSocketFlow)
    assert (playbook << websocket.WebsocketStartHook(flow) >> reply(
    ) >> DataReceived(
        tctx.client, masked_bytes(b"\x89\x11ping-with-payload")
    ) << Log(
        "Received WebSocket ping from client (payload: b'ping-with-payload')"
    ) << SendData(
        tctx.server,
        masked(b"\x89\x11ping-with-payload")
    ) >> DataReceived(
        tctx.server,
        b"\x8a\x11pong-with-payload"
    ) << Log(
        "Received WebSocket pong from server (payload: b'pong-with-payload')")
            << SendData(tctx.client, b"\x8a\x11pong-with-payload"))
    assert not flow().messages
예제 #11
0
def test_upgrade(tctx):
    """Test a HTTP -> WebSocket upgrade"""
    tctx.server.address = ("example.com", 80)
    tctx.server.state = ConnectionState.OPEN
    http_flow = Placeholder(HTTPFlow)
    flow = Placeholder(WebSocketFlow)
    assert (
        Playbook(http.HttpLayer(tctx, HTTPMode.transparent)) >> DataReceived(
            tctx.client, b"GET / HTTP/1.1\r\n"
            b"Connection: upgrade\r\n"
            b"Upgrade: websocket\r\n"
            b"Sec-WebSocket-Version: 13\r\n"
            b"\r\n") << http.HttpRequestHeadersHook(http_flow) >> reply() <<
        http.HttpRequestHook(http_flow) >> reply() << SendData(
            tctx.server, b"GET / HTTP/1.1\r\n"
            b"Connection: upgrade\r\n"
            b"Upgrade: websocket\r\n"
            b"Sec-WebSocket-Version: 13\r\n"
            b"\r\n") >> DataReceived(
                tctx.server, b"HTTP/1.1 101 Switching Protocols\r\n"
                b"Upgrade: websocket\r\n"
                b"Connection: Upgrade\r\n"
                b"\r\n") << http.HttpResponseHeadersHook(http_flow) >> reply()
        << http.HttpResponseHook(http_flow) >> reply() << SendData(
            tctx.client, b"HTTP/1.1 101 Switching Protocols\r\n"
            b"Upgrade: websocket\r\n"
            b"Connection: Upgrade\r\n"
            b"\r\n") << websocket.WebsocketStartHook(flow) >> reply() >>
        DataReceived(tctx.client, masked_bytes(b"\x81\x0bhello world")) <<
        websocket.WebsocketMessageHook(flow) >> reply() << SendData(
            tctx.server, masked(b"\x81\x0bhello world")) >> DataReceived(
                tctx.server, b"\x82\nhello back") <<
        websocket.WebsocketMessageHook(flow) >> reply() << SendData(
            tctx.client, b"\x82\nhello back"))
    assert flow().handshake_flow == http_flow()
    assert len(flow().messages) == 2
    assert flow().messages[0].content == "hello world"
    assert flow().messages[0].from_client
    assert flow().messages[1].content == b"hello back"
    assert flow().messages[1].from_client is False