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)
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()
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))
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)
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()