async def expired(self): """Guessing time expired""" self.timer = None try: log.debug('Turn timer expired, stop turn') await self.broadcast(message.Stop(reason='timer')) self.turn.explaining.lastanswer() self.turn.guessing.finish() except Exception as e: log.error(f'Exception while process timer: {e}') log.exception()
async def get(self): log.debug('websocket new connection') ws = web.WebSocketResponse() self.request.app.websockets.append(ws) await ws.prepare(self.request) async for msg in ws: log.debug( f'websocket message received: {msg.type}: {msg.data.strip()}') if msg.type == WSMsgType.text: if msg.data == 'close': await ws.close() else: try: data = json.loads(msg.data) except Exception as e: await self.error(ws, 101, f'Broken message received {e}') continue if not 'cmd' in data: await self.error(ws, 102, f'Invalid message format {msg.data}') continue else: cmdtxt = data['cmd'] cmd = getattr(self.request.app.game, cmdtxt, None) if not callable(cmd): await self.error(ws, 103, f'Unknown command {cmdtxt}') continue try: log.debug(f'Received command {cmdtxt}') await cmd(ws, data) except Exception as e: log.exception('Error executing command {cmdtxt}: {e}') await self.error( ws, 104, f'Error executing command {cmdtxt}: {e}') elif msg.type == WSMsgType.error: log.debug('ws connection closed with exception %s' % ws.exception()) self.request.app.websockets.remove(ws) log.debug('websocket connection closed') return ws
async def receive(self): while True: tmsg = await self.ws.receive() if tmsg.type == WSMsgType.text: try: data = json.loads(tmsg.data) self.logS(f'<< {json.dumps(data, ensure_ascii=False)}') except Exception as e: self.error(f'Broken message received {e}') continue if 'cmd' not in data: self.error(f'Invalid message format {tmsg.data}') continue else: cmdtxt = data['cmd'] try: msg = message.ServerMessage.msg(data) if isinstance(msg, message.Prepare): self.players = msg.players elif isinstance(msg, message.Tour): self.tour = msg elif isinstance(msg, message.Turn): self.turn = msg elif isinstance(msg, message.Finish): self.finish = msg return elif isinstance(msg, message.Explained) or isinstance( msg, message.Missed): continue self.queue.append(msg) except Exception as e: log.exception( f"Exception caught while parsing of '{cmdtxt}': {e}") self.error(f"Error executing command '{cmdtxt}': {e}") elif tmsg.type == WSMsgType.closed: break elif tmsg.type == WSMsgType.error: break self.logE('Websocket closed unexpectedly') self.finish = message.Finish() return None
async def get(self): gid = self.request.match_info.get('id', '00000000-0000-0000-0000-000000000000') if gid == 'None': # Do not ask - if parameter not found, string 'None' returned gid = '00000000-0000-0000-0000-000000000000' log.debug(f'websocket new connection for game #{gid}') try: game = self.request.app.games[gid] except KeyError: return web.Response( content_type='application/json', text=str(message.Error(code=100, message=f'Game with ID {gid} is unknown')) ) ws = web.WebSocketResponse() self.request.app.websockets.add(ws) await ws.prepare(self.request) while True: try: try: data = await ws.receive_json() except json.decoder.JSONDecodeError as e: log.debug(f'Invalid message format {e}') continue except TypeError: # TypeError might be raised if WSMsgType.CLOSED was received if ws.closed: break else: log.debug(f'ws connection closed with exception {ws.exception()}') break await game.cmd(ws, data) except CancelledError: break except Exception as e: log.exception(f"Unexpected exception was caught: {e}") break self.request.app.websockets.discard(ws) log.debug('websocket connection closed') return ws
async def cmd(self, ws, data): """Command multiplexer""" global commands try: msg = message.ClientMessage.msg(data) except Exception as e: await self.error(ws, 102, f'Invalid message format {data} - {e}') return cmdtxt = msg.cmd() cmd = getattr(self, cmdtxt, None) if msg.cmd() not in commands or not callable(cmd): await self.error(ws, 103, f'Unknown command {cmdtxt}') return try: await cmd(ws, msg) except Exception as e: log.exception( f"Exception caught while execution of '{cmdtxt}': {e}") await self.error(ws, 104, f"Error executing command '{cmdtxt}': {e}")