예제 #1
0
    def test_parser(self, m_parse_message):
        cur = 0

        def parse_message(buf):
            nonlocal cur
            yield
            if cur == 0:
                cur = 1
                return websocket.Message(websocket.OPCODE_TEXT, b'line1', b'')
            else:
                return websocket.Message(websocket.OPCODE_CLOSE, b'', b'')

        m_parse_message.side_effect = parse_message
        out = tulip.DataBuffer()
        buf = tulip.ParserBuffer()
        p = websocket.WebSocketParser()
        next(p)
        p.send((out, buf))
        p.send(b'')
        self.assertRaises(StopIteration, p.send, b'')

        self.assertEqual(
            (websocket.OPCODE_TEXT, b'line1', b''), out._buffer[0])
        self.assertEqual(
            (websocket.OPCODE_CLOSE, b'', b''), out._buffer[1])
        self.assertTrue(out._eof)
예제 #2
0
    def heartbeat(self):
        # setup pipes
        read_transport, read_proto = yield from self.loop.connect_read_pipe(
            tulip.StreamProtocol, os.fdopen(self.up_read, 'rb'))
        write_transport, _ = yield from self.loop.connect_write_pipe(
            tulip.StreamProtocol, os.fdopen(self.down_write, 'wb'))

        reader = read_proto.set_parser(websocket.WebSocketParser())
        writer = websocket.WebSocketWriter(write_transport)

        self.start_server(writer)

        while True:
            msg = yield from reader.read()
            if msg is None:
                print('Superviser is dead, {} stopping...'.format(os.getpid()))
                self.loop.stop()
                break
            elif msg.tp == websocket.MSG_PING:
                writer.pong()
            elif msg.tp == websocket.MSG_CLOSE:
                break
            elif msg.tp == websocket.MSG_TEXT:  # broadcast message
                for wsc in self.clients:
                    wsc.send(msg.data.strip().encode())

        read_transport.close()
        write_transport.close()
예제 #3
0
 def test_parser_eof(self):
     out = tulip.DataBuffer()
     buf = tulip.ParserBuffer()
     p = websocket.WebSocketParser()
     next(p)
     p.send((out, buf))
     self.assertRaises(tulip.EofStream, p.throw, tulip.EofStream)
     self.assertEqual([], list(out._buffer))
예제 #4
0
    def connect(self, pid, up_write, down_read):
        # setup pipes
        read_transport, proto = yield from self.loop.connect_read_pipe(
            tulip.StreamProtocol, os.fdopen(down_read, 'rb'))
        write_transport, _ = yield from self.loop.connect_write_pipe(
            tulip.StreamProtocol, os.fdopen(up_write, 'wb'))

        # websocket protocol
        reader = proto.set_parser(websocket.WebSocketParser())
        writer = websocket.WebSocketWriter(write_transport)

        # store info
        self.pid = pid
        self.ping = time.monotonic()
        self.rtransport = read_transport
        self.wtransport = write_transport
        self.chat_task = self.chat(reader)
        self.heartbeat_task = self.heartbeat(writer)
예제 #5
0
def start_client(loop, url):
    name = input('Please enter your name: ').encode()

    sec_key = base64.b64encode(os.urandom(16))

    # send request
    response = yield from tulip.http.request('get',
                                             url,
                                             headers={
                                                 'UPGRADE':
                                                 'WebSocket',
                                                 'CONNECTION':
                                                 'Upgrade',
                                                 'SEC-WEBSOCKET-VERSION':
                                                 '13',
                                                 'SEC-WEBSOCKET-KEY':
                                                 sec_key.decode(),
                                             },
                                             timeout=1.0)

    # websocket handshake
    if response.status != 101:
        raise ValueError("Handshake error: Invalid response status")
    if response.get('upgrade', '').lower() != 'websocket':
        raise ValueError("Handshake error - Invalid upgrade header")
    if response.get('connection', '').lower() != 'upgrade':
        raise ValueError("Handshake error - Invalid connection header")

    key = response.get('sec-websocket-accept', '').encode()
    match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest())
    if key != match:
        raise ValueError("Handshake error - Invalid challenge response")

    # switch to websocket protocol
    stream = response.stream.set_parser(websocket.WebSocketParser())
    writer = websocket.WebSocketWriter(response.transport)

    # input reader
    def stdin_callback():
        line = sys.stdin.buffer.readline()
        if not line:
            loop.stop()
        else:
            writer.send(name + b': ' + line)

    loop.add_reader(sys.stdin.fileno(), stdin_callback)

    @tulip.coroutine
    def dispatch():
        while True:
            msg = yield from stream.read()
            if msg is None:
                break
            elif msg.tp == websocket.MSG_PING:
                writer.pong()
            elif msg.tp == websocket.MSG_TEXT:
                print(msg.data.strip())
            elif msg.tp == websocket.MSG_CLOSE:
                break

    yield from dispatch()