Esempio n. 1
0
def test_connection_send_state() -> None:
    client = WSConnection(CLIENT)
    assert client.state is ConnectionState.CONNECTING

    server = h11.Connection(h11.SERVER)
    server.receive_data(client.send(Request(
        host="localhost",
        target="/",
    )))
    headers = normed_header_dict(server.next_event().headers)
    response = h11.InformationalResponse(
        status_code=101,
        headers=[
            (b"connection", b"Upgrade"),
            (b"upgrade", b"WebSocket"),
            (
                b"Sec-WebSocket-Accept",
                generate_accept_token(headers[b"sec-websocket-key"]),
            ),
        ],
    )
    client.receive_data(server.send(response))
    assert len(list(client.events())) == 1
    assert client.state is ConnectionState.OPEN  # type: ignore # https://github.com/python/mypy/issues/9005

    with pytest.raises(LocalProtocolError) as excinfo:
        client.send(Request(host="localhost", target="/"))

    client.receive_data(b"foobar")
    assert len(list(client.events())) == 1
Esempio n. 2
0
def test_connection_request_simple_extension_no_offer() -> None:
    extension = FakeExtension(offer_response=False)
    request = _make_connection_request(
        Request(host="localhost", target="/", extensions=[extension]))

    headers = normed_header_dict(request.headers)
    assert b"sec-websocket-extensions" not in headers
Esempio n. 3
0
def test_connection_request_subprotocols():
    request = _make_connection_request(
        Request(host="localhost", target="/", subprotocols=["one", "two"])
    )

    headers = normed_header_dict(request.headers)
    assert headers[b"sec-websocket-protocol"] == b"one, two"
Esempio n. 4
0
def handle_todo_post_save(sender, instance, created, **kwargs):
    if not hasattr(sender, 'APP_PORT'):
        return
    conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    conn.connect(('localhost', int(sender.APP_PORT)))

    ws = WSConnection(ConnectionType.CLIENT)
    print("hello")
    net_send(
        ws.send(Request(
            host=f"localhost:{sender.APP_PORT}",
            target=f"ws/todos")),
        conn
    )
    net_recv(ws, conn)
    handle_events(ws)

    net_send(ws.send(Message(data=str(instance.pk))), conn)
    net_recv(ws, conn)
    handle_events(ws)

    net_send(ws.send(CloseConnection(code=1000)), conn)
    net_recv(ws, conn)
    conn.shutdown(socket.SHUT_WR)
    net_recv(ws, conn)

    del sender.APP_PORT
Esempio n. 5
0
def get_case_count(server):
    uri = urlparse(server + '/getCaseCount')
    connection = WSConnection(CLIENT)
    sock = socket.socket()
    sock.connect((uri.hostname, uri.port or 80))

    sock.sendall(connection.send(Request(host=uri.netloc, target=uri.path)))

    case_count = None
    while case_count is None:
        data = sock.recv(65535)
        connection.receive_data(data)
        data = ""
        out_data = b""
        for event in connection.events():
            if isinstance(event, TextMessage):
                data += event.data
                if event.message_finished:
                    case_count = json.loads(data)
                    out_data += connection.send(CloseConnection(code=CloseReason.NORMAL_CLOSURE))
            try:
                sock.sendall(out_data)
            except CONNECTION_EXCEPTIONS:
                break

    sock.close()
    return case_count
Esempio n. 6
0
def _make_handshake(
    response_status,
    response_headers,
    subprotocols=None,
    extensions=None,
    auto_accept_key=True,
):
    client = WSConnection(CLIENT)
    server = h11.Connection(h11.SERVER)
    server.receive_data(
        client.send(
            Request(
                host="localhost",
                target="/",
                subprotocols=subprotocols or [],
                extensions=extensions or [],
            )
        )
    )
    request = server.next_event()
    if auto_accept_key:
        full_request_headers = normed_header_dict(request.headers)
        response_headers.append(
            (
                b"Sec-WebSocket-Accept",
                generate_accept_token(full_request_headers[b"sec-websocket-key"]),
            )
        )
    response = h11.InformationalResponse(
        status_code=response_status, headers=response_headers
    )
    client.receive_data(server.send(response))

    return list(client.events())
Esempio n. 7
0
    async def start_client(self,
                           sock: anyio.abc.SocketStream,
                           addr,
                           path: str,
                           headers: Optional[List] = None,
                           subprotocols: Optional[List[str]] = None):
        """Start a client WS connection on this socket.

        Returns: the AcceptConnection message.
        """
        self._sock = sock
        self._connection = WSConnection(ConnectionType.CLIENT)
        if headers is None:
            headers = []
        if subprotocols is None:
            subprotocols = []
        data = self._connection.send(
            Request(
                host=addr[0],
                target=path,
                extra_headers=headers,
                subprotocols=subprotocols))
        await self._sock.send_all(data)

        assert self._scope is None
        self._scope = True
        try:
            event = await self._next_event()
            if not isinstance(event, AcceptConnection):
                raise ConnectionError("Failed to establish a connection",
                                      event)
            return event
        finally:
            self._scope = None
Esempio n. 8
0
    async def init_for_client(
        cls: Type["Transport"], stream: Stream, host: str, keepalive: Optional[int] = None
    ) -> "Transport":
        ws = WSConnection(ConnectionType.CLIENT)
        transport = cls(stream, ws, keepalive)

        # Because this is a client WebSocket, we need to initiate the connection
        # handshake by sending a Request event.
        await transport._net_send(
            Request(
                host=host,
                target=TRANSPORT_TARGET,
                extra_headers=[(b"User-Agent", USER_AGENT.encode())],
            )
        )

        # Get handshake answer
        event = await transport._next_ws_event()

        if isinstance(event, AcceptConnection):
            transport.logger.debug("WebSocket negotiation complete", ws_event=event)

        else:
            transport.logger.warning("Unexpected event during WebSocket handshake", ws_event=event)
            reason = f"Unexpected event during WebSocket handshake: {event}"
            raise TransportError(reason)

        return transport
Esempio n. 9
0
def update_reports(server, agent):
    uri = urlparse(server + '/updateReports?agent=%s' % agent)
    connection = WSConnection(CLIENT)
    sock = socket.socket()
    sock.connect((uri.hostname, uri.port or 80))

    sock.sendall(
        connection.send(
            Request(host=uri.netloc, target='%s?%s' % (uri.path, uri.query))))
    closed = False

    while not closed:
        data = sock.recv(65535)
        connection.receive_data(data)
        for event in connection.events():
            if isinstance(event, AcceptConnection):
                sock.sendall(
                    connection.send(
                        CloseConnection(code=CloseReason.NORMAL_CLOSURE)))
                try:
                    sock.close()
                except CONNECTION_EXCEPTIONS:
                    pass
                finally:
                    closed = True
Esempio n. 10
0
    def __init__(self, ctx, handshake_flow):
        super().__init__(ctx)
        self.handshake_flow = handshake_flow
        self.flow: WebSocketFlow = None

        self.client_frame_buffer = []
        self.server_frame_buffer = []

        self.connections: dict[object, WSConnection] = {}

        client_extensions = []
        server_extensions = []
        if 'Sec-WebSocket-Extensions' in handshake_flow.response.headers:
            if PerMessageDeflate.name in handshake_flow.response.headers['Sec-WebSocket-Extensions']:
                client_extensions = [PerMessageDeflate()]
                server_extensions = [PerMessageDeflate()]
        self.connections[self.client_conn] = WSConnection(ConnectionType.SERVER)
        self.connections[self.server_conn] = WSConnection(ConnectionType.CLIENT)

        if client_extensions:
            client_extensions[0].finalize(handshake_flow.response.headers['Sec-WebSocket-Extensions'])
        if server_extensions:
            server_extensions[0].finalize(handshake_flow.response.headers['Sec-WebSocket-Extensions'])

        request = Request(extensions=client_extensions, host=handshake_flow.request.host, target=handshake_flow.request.path)
        data = self.connections[self.server_conn].send(request)
        self.connections[self.client_conn].receive_data(data)

        event = next(self.connections[self.client_conn].events())
        assert isinstance(event, events.Request)

        data = self.connections[self.client_conn].send(AcceptConnection(extensions=server_extensions))
        self.connections[self.server_conn].receive_data(data)
        assert isinstance(next(self.connections[self.server_conn].events()), events.AcceptConnection)
Esempio n. 11
0
def test_connection_request_simple_extension():
    extension = FakeExtension(offer_response=True)
    request = _make_connection_request(
        Request(host="localhost", target="/", extensions=[extension])
    )

    headers = normed_header_dict(request.headers)
    assert headers[b"sec-websocket-extensions"] == extension.name.encode("ascii")
Esempio n. 12
0
 async def connect(self, path, host, port):
     await self.socket.connect((host, port))
     request = Request(host=f'{host}:{port}', target=path)
     await self.socket.sendall(self.protocol.send(request))
     upgrade_response = await self.socket.recv(8096)
     self.protocol.receive_data(upgrade_response)
     event = next(self.protocol.events())
     if not isinstance(event, AcceptConnection):
         raise Exception('Websocket handshake failed.')
Esempio n. 13
0
 async def _do_handshake(self):
     try:
         handshake = Request(host=self.host,
                             target=self.path,
                             subprotocols=self._subprotocols or [],
                             extra_headers=self._headers or [])
         await self._send(handshake)
     except ConnectionClosed:
         self._reader_running = False
Esempio n. 14
0
 def __init__(self,
              path: str,
              *,
              framework: ASGIFramework = echo_framework) -> None:
     self.client_stream, server_stream = trio.testing.memory_stream_pair()
     server_stream.socket = MockSocket()
     self.server = WebsocketServer(framework, Config(), server_stream)
     self.connection = WSConnection(ConnectionType.CLIENT)
     self.server.connection.receive_data(
         self.connection.send(Request(target=path, host="hypercorn")))
Esempio n. 15
0
def test_connection_request_additional_headers() -> None:
    request = _make_connection_request(
        Request(
            host="localhost",
            target="/",
            extra_headers=[(b"X-Foo", b"Bar"), (b"X-Bar", b"Foo")],
        ))

    headers = normed_header_dict(request.headers)
    assert headers[b"x-foo"] == b"Bar"
    assert headers[b"x-bar"] == b"Foo"
Esempio n. 16
0
    def handshake(self):
        out_data = self.ws.send(Request(host=self.host, target=self.path))
        self.sock.send(out_data)

        in_data = self.sock.recv(self.receive_bytes)
        self.ws.receive_data(in_data)
        for event in self.ws.events():
            if isinstance(event, AcceptConnection):
                break
            elif isinstance(event, RejectConnection):
                raise ConnectionError(event.status_code)
Esempio n. 17
0
def test_connection_request_parametrised_extension():
    extension = FakeExtension(offer_response="parameter1=value1; parameter2=value2")
    request = _make_connection_request(
        Request(host="localhost", target="/", extensions=[extension])
    )

    headers = normed_header_dict(request.headers)
    assert headers[b"sec-websocket-extensions"] == b"%s; %s" % (
        extension.name.encode("ascii"),
        extension.offer_response.encode("ascii"),
    )
Esempio n. 18
0
def test_successful_handshake():
    client = H11Handshake(CLIENT)
    server = H11Handshake(SERVER)

    server.receive_data(client.send(Request(host="localhost", target="/")))
    assert isinstance(next(server.events()), Request)

    client.receive_data(server.send(AcceptConnection()))
    assert isinstance(next(client.events()), AcceptConnection)

    assert client.state is ConnectionState.OPEN
    assert server.state is ConnectionState.OPEN
Esempio n. 19
0
def test_rejected_handshake():
    client = H11Handshake(CLIENT)
    server = H11Handshake(SERVER)

    server.receive_data(client.send(Request(host="localhost", target="/")))
    assert isinstance(next(server.events()), Request)

    client.receive_data(server.send(RejectConnection()))
    assert isinstance(next(client.events()), RejectConnection)

    assert client.state is ConnectionState.CLOSED
    assert server.state is ConnectionState.CLOSED
Esempio n. 20
0
def test_connection_request():
    request = _make_connection_request(Request(host="localhost", target="/"))

    assert request.http_version == b"1.1"
    assert request.method == b"GET"
    assert request.target == b"/"
    headers = normed_header_dict(request.headers)
    assert headers[b"connection"] == b"Upgrade"
    assert headers[b"host"] == b"localhost"
    assert headers[b"sec-websocket-version"] == b"13"
    assert headers[b"upgrade"] == b"WebSocket"
    assert b"sec-websocket-key" in headers
Esempio n. 21
0
 def __init__(
     self,
     path: str,
     event_loop: asyncio.AbstractEventLoop,
     *,
     framework: Type[ASGIFramework] = EchoFramework,
 ) -> None:
     self.transport = MockTransport()
     self.server = WebsocketServer(  # type: ignore
         framework, event_loop, Config(), self.transport)
     self.connection = WSConnection(ConnectionType.CLIENT)
     self.server.data_received(
         self.connection.send(Request(target=path, host="hypercorn")))
Esempio n. 22
0
 def _establish_websocket_handshake(self, host: str, path: str,
                                    headers: Headers, extensions: List[str],
                                    sub_protocols: List[str]) -> None:
     self._ws = WSConnection(ConnectionType.CLIENT)
     headers = headers if headers is not None else []
     extensions = extensions if extensions is not None else []
     sub_protocols = sub_protocols if sub_protocols is not None else []
     request = Request(host=host,
                       target=path,
                       extra_headers=headers,
                       extensions=extensions,
                       subprotocols=sub_protocols)
     self._sock.sendall(self._ws.send(request))
Esempio n. 23
0
def wsproto_demo(host, port):
    '''
    Demonstrate wsproto:

    0) Open TCP connection
    1) Negotiate WebSocket opening handshake
    2) Send a message and display response
    3) Send ping and display pong
    4) Negotiate WebSocket closing handshake

    :param stream: a socket stream
    '''

    # 0) Open TCP connection
    print('Connecting to {}:{}'.format(host, port))
    conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    conn.connect((host, port))

    # 1) Negotiate WebSocket opening handshake
    print('Opening WebSocket')
    ws = WSConnection(ConnectionType.CLIENT)
    # Because this is a client WebSocket, we need to initiate the connection
    # handshake by sending a Request event.
    net_send(ws.send(Request(host=host, target='server')), conn)
    net_recv(ws, conn)
    handle_events(ws)

    # 2) Send a message and display response
    message = "wsproto is great"
    print('Sending message: {}'.format(message))
    net_send(ws.send(Message(data=message)), conn)
    net_recv(ws, conn)
    handle_events(ws)

    # 3) Send ping and display pong
    payload = b"table tennis"
    print('Sending ping: {}'.format(payload))
    net_send(ws.send(Ping(payload=payload)), conn)
    net_recv(ws, conn)
    handle_events(ws)

    # 4) Negotiate WebSocket closing handshake
    print('Closing WebSocket')
    net_send(ws.send(CloseConnection(code=1000, reason='sample reason')), conn)
    # After sending the closing frame, we won't get any more events. The server
    # should send a reply and then close the connection, so we need to receive
    # twice:
    net_recv(ws, conn)
    conn.shutdown(socket.SHUT_WR)
    net_recv(ws, conn)
Esempio n. 24
0
async def test_bad_framework() -> None:
    server = MockWebsocket()
    server.app = bad_framework
    headers = [
        (b"sec-websocket-key", b"ZdCqRHQRNflNt6o7yU48Pg=="),
        (b"sec-websocket-version", b"13"),
        (b"connection", b"upgrade"),
        (b"upgrade", b"connection"),
    ]
    request = Request(target="/accept",
                      host="hypercorn",
                      extra_headers=headers)
    await server.handle_websocket(request)
    assert isinstance(server.sent_events[0], AcceptConnection)
    assert server.sent_events[1:] == [CloseConnection(code=1006)]
Esempio n. 25
0
def _make_handshake_rejection(status_code, body=None):
    client = WSConnection(CLIENT)
    server = h11.Connection(h11.SERVER)
    server.receive_data(client.send(Request(host="localhost", target="/")))
    headers = []
    if body is not None:
        headers.append(("Content-Length", str(len(body))))
    client.receive_data(
        server.send(h11.Response(status_code=status_code, headers=headers))
    )
    if body is not None:
        client.receive_data(server.send(h11.Data(data=body)))
    client.receive_data(server.send(h11.EndOfMessage()))

    return list(client.events())
Esempio n. 26
0
async def test_bad_framework_http(path: str) -> None:
    server = MockWebsocket()
    server.app = bad_framework
    headers = [
        (b"sec-websocket-key", b"ZdCqRHQRNflNt6o7yU48Pg=="),
        (b"sec-websocket-version", b"13"),
        (b"connection", b"upgrade"),
        (b"upgrade", b"connection"),
    ]
    request = Request(target=path, host="hypercorn", extra_headers=headers)
    await server.handle_websocket(request)
    assert server.sent_events == [
        RejectConnection(status_code=500,
                         headers=[(b"server", b"hypercorn")],
                         has_body=False)
    ]
Esempio n. 27
0
    async def init_for_client(cls, stream: Stream, host: str) -> "Transport":
        ws = WSConnection(ConnectionType.CLIENT)
        transport = cls(stream, ws)

        # Because this is a client WebSocket, we need to initiate the connection
        # handshake by sending a Request event.
        await transport._net_send(Request(host=host, target=TRANSPORT_TARGET))

        # Get handshake answer
        event = await transport._next_ws_event()

        if isinstance(event, AcceptConnection):
            transport.logger.debug("WebSocket negotiation complete", ws_event=event)

        else:
            transport.logger.warning("Unexpected event during WebSocket handshake", ws_event=event)
            reason = f"Unexpected event during WebSocket handshake: {event}"
            raise TransportError(reason)

        return transport
Esempio n. 28
0
async def test_asgi_scope() -> None:
    server = MockWebsocket()
    connection_request = Request(target="/path?a=b", host="hypercorn")
    await server.handle_websocket(connection_request)
    scope = server.scope
    assert scope == {
        "type": "websocket",
        "asgi": {
            "version": "2.0"
        },
        "http_version": "1.1",
        "scheme": "ws",
        "path": "/path",
        "query_string": b"a=b",
        "root_path": "",
        "headers": [(b"host", b"hypercorn")],
        "client": ("127.0.0.1", 5000),
        "server": ("remote", 5000),
        "subprotocols": [],
        "extensions": {
            "websocket.http.response": {}
        },
    }
Esempio n. 29
0
def test_send_invalid_event() -> None:
    client = Connection(CLIENT)
    with pytest.raises(LocalProtocolError):
        client.send(Request(target="/", host="wsproto"))
Esempio n. 30
0
                sock.sendall(out_data)
            except CONNECTION_EXCEPTIONS:
                break

    sock.close()
    return case_count

def run_case(server, case, agent):
    uri = urlparse(server + '/runCase?case=%d&agent=%s' % (case, agent))
    connection = WSConnection(CLIENT)
    sock = socket.socket()
    sock.connect((uri.hostname, uri.port or 80))

    sock.sendall(
        connection.send(Request(
            host=uri.netloc, target='%s?%s' % (uri.path, uri.query),
            extensions=[PerMessageDeflate()],
        ))
    )
    closed = False

    while not closed:
        try:
            data = sock.recv(65535)
        except CONNECTION_EXCEPTIONS:
            data = None
        connection.receive_data(data or None)
        out_data = b""
        for event in connection.events():
            if isinstance(event, Message):
                out_data += connection.send(Message(data=event.data, message_finished=event.message_finished))
            elif isinstance(event, Ping):