async def _func(obj: Any, request: web.Request, *a: Any, **kw: Any) -> None: websocket = web.WebSocketResponse() # type: ignore request_ip = RequestHandler.get_request_ip(request, context) try: await websocket.prepare(request) except Exception: try: await websocket.close() except Exception: pass if access_log: logging.getLogger('transport.http').info('[{}] {} {} "CANCELLED {}{}" {} "{}" {}'.format( RequestHandler.colorize_status('websocket', 101), request_ip, '"{}"'.format(request._cache['auth'].login.replace('"', '')) if request._cache.get('auth') and getattr(request._cache.get('auth'), 'login', None) else '-', request.path, '?{}'.format(request.query_string) if request.query_string else '', request._cache.get('websocket_uuid', ''), request.headers.get('User-Agent', '').replace('"', ''), '-' )) return context['_http_open_websockets'] = context.get('_http_open_websockets', []) context['_http_open_websockets'].append(websocket) if access_log: logging.getLogger('transport.http').info('[{}] {} {} "OPEN {}{}" {} "{}" {}'.format( RequestHandler.colorize_status('websocket', 101), request_ip, '"{}"'.format(request._cache['auth'].login.replace('"', '')) if request._cache.get('auth') and getattr(request._cache.get('auth'), 'login', None) else '-', request.path, '?{}'.format(request.query_string) if request.query_string else '', request._cache.get('websocket_uuid', ''), request.headers.get('User-Agent', '').replace('"', ''), '-' )) result = compiled_pattern.match(request.path) values = inspect.getfullargspec(func) kwargs = {k: values.defaults[i] for i, k in enumerate(values.args[len(values.args) - len(values.defaults):])} if values.defaults else {} if result: for k, v in result.groupdict().items(): kwargs[k] = v if len(values.args) - (len(values.defaults) if values.defaults else 0) >= 3: # If the function takes a third required argument the value will be filled with the request object a = a + (request,) if 'request' in values.args and (len(values.args) - (len(values.defaults) if values.defaults else 0) < 3 or values.args[2] != 'request'): kwargs['request'] = request try: routine = func(*(obj, websocket, *a), **merge_dicts(kwargs, kw)) callback_functions = (await routine) if isinstance(routine, Awaitable) else routine # type: Optional[Union[Tuple, Callable]] except Exception as e: logging.getLogger('exception').exception('Uncaught exception: {}'.format(str(e))) try: await websocket.close() except Exception: pass try: context['_http_open_websockets'].remove(websocket) except Exception: pass if access_log: logging.getLogger('transport.http').info('[{}] {} {} "{} {}{}" {} "{}" {}'.format( RequestHandler.colorize_status('websocket', 500), request_ip, '"{}"'.format(request._cache['auth'].login.replace('"', '')) if request._cache.get('auth') and getattr(request._cache.get('auth'), 'login', None) else '-', RequestHandler.colorize_status('ERROR', 500), request.path, '?{}'.format(request.query_string) if request.query_string else '', request._cache.get('websocket_uuid', ''), request.headers.get('User-Agent', '').replace('"', ''), '-' )) return _receive_func = None _close_func = None if callback_functions and isinstance(callback_functions, tuple): try: _receive_func, _close_func = callback_functions except ValueError: _receive_func, = callback_functions elif callback_functions: _receive_func = callback_functions try: async for message in websocket: if message.type == WSMsgType.TEXT: if _receive_func: try: await _receive_func(message.data) except Exception as e: logging.getLogger('exception').exception('Uncaught exception: {}'.format(str(e))) elif message.type == WSMsgType.ERROR: if not context.get('log_level') or context.get('log_level') in ['DEBUG']: ws_exception = websocket.exception() if isinstance(ws_exception, (EofStream, RuntimeError)): pass elif isinstance(ws_exception, Exception): logging.getLogger('exception').exception('Uncaught exception: {}'.format(str(ws_exception))) else: logging.getLogger('transport.http').warning('Websocket exception: "{}"'.format(ws_exception)) elif message.type == WSMsgType.CLOSED: break # noqa except Exception as e: pass finally: if _close_func: try: await _close_func() except Exception as e: logging.getLogger('exception').exception('Uncaught exception: {}'.format(str(e))) try: await websocket.close() except Exception: pass try: context['_http_open_websockets'].remove(websocket) except Exception: pass
async def ws_handler(self, request): ws = web.WebSocketResponse() await ws.prepare(request) # Each connection will have its own input queue input_queue = queue.Queue() t_worker = None authenticated = False async for msg in ws: if authenticated: # Add content of every message received in input queue try: input_queue.put(msg.data.encode()) except UnicodeEncodeError: # Should we handle Encode error? # xterm.js seems to operate with the websocket in text mode, pass else: try: data = json.loads(msg.data) except json.decoder.JSONDecodeError: continue token = data.get('token') if not token: continue token = await self.middleware.call('auth.get_token', token) if not token: ws.send_json({ 'msg': 'failed', 'error': { 'error': errno.EACCES, 'reason': 'Invalid token', } }) continue authenticated = True ws.send_json({ 'msg': 'connected', }) t_worker = ShellWorkerThread(ws=ws, input_queue=input_queue, loop=asyncio.get_event_loop()) t_worker.start() # If connection was not authenticated, return earlier if not authenticated: return ws # If connection has been closed lets make sure shell is killed if t_worker.shell_pid: try: kqueue = select.kqueue() kevent = select.kevent(t_worker.shell_pid, select.KQ_FILTER_PROC, select.KQ_EV_ADD | select.KQ_EV_ENABLE, select.KQ_NOTE_EXIT) kqueue.control([kevent], 0) os.kill(t_worker.shell_pid, signal.SIGTERM) # If process has not died in 2 seconds, try the big gun events = await self.middleware.run_in_thread( kqueue.control, None, 1, 2) if not events: os.kill(t_worker.shell_pid, signal.SIGKILL) # If process has not died even with the big gun # There is nothing else we can do, leave it be and # release the worker thread events = await self.middleware.run_in_thread( kqueue.control, None, 1, 2) if not events: t_worker.die() except ProcessLookupError: pass # Wait thread join in yet another thread to avoid event loop blockage # There may be a simpler/better way to do this? await self.middleware.run_in_thread(t_worker.join) return ws
def handler(request): ws = web.WebSocketResponse(protocols=('foo', 'bar')) yield from ws.prepare(request) yield from ws.close() closed.set_result(None) return ws
async def handler(request): ws = web.WebSocketResponse(heartbeat=0.05) await ws.prepare(request) await ws.receive() return ws
async def handler(request): ws = web.WebSocketResponse() await ws.prepare(request) await ws.receive() await ws.close() return ws
async def websocket_handler(self, request): """Send notifications to admin client over websocket.""" ws = web.WebSocketResponse() await ws.prepare(request) socket_id = str(uuid.uuid4()) queue = BasicMessageQueue() loop = asyncio.get_event_loop() if self.admin_insecure_mode: # open to send websocket messages without api key auth queue.authenticated = True else: header_admin_api_key = request.headers.get("x-api-key") # authenticated via http header? queue.authenticated = header_admin_api_key == self.admin_api_key try: self.websocket_queues[socket_id] = queue await queue.enqueue({ "topic": "settings", "payload": { "authenticated": queue.authenticated, "label": self.context.settings.get("default_label"), "endpoint": self.context.settings.get("default_endpoint"), "no_receive_invites": self.context.settings.get("admin.no_receive_invites", False), "help_link": self.context.settings.get("admin.help_link"), }, }) closed = False receive = loop.create_task(ws.receive_json()) send = loop.create_task(queue.dequeue(timeout=5.0)) while not closed: try: await asyncio.wait((receive, send), return_when=asyncio.FIRST_COMPLETED) if ws.closed: closed = True if receive.done(): if not closed: msg_received = None msg_api_key = None try: # this call can re-raise exeptions from inside the task msg_received = receive.result() msg_api_key = msg_received.get("x-api-key") except Exception: LOGGER.exception( "Exception in websocket receiving task:") if self.admin_api_key and self.admin_api_key == msg_api_key: # authenticated via websocket message queue.authenticated = True receive = loop.create_task(ws.receive_json()) if send.done(): try: msg = send.result() except asyncio.TimeoutError: msg = None if msg is None: # we send fake pings because the JS client # can't detect real ones msg = { "topic": "ping", "authenticated": queue.authenticated, } if not closed: if msg: await ws.send_json(msg) send = loop.create_task(queue.dequeue(timeout=5.0)) except asyncio.CancelledError: closed = True if not receive.done(): receive.cancel() if not send.done(): send.cancel() finally: del self.websocket_queues[socket_id] return ws
async def handler(request): ws = web.WebSocketResponse() if not ws.can_prepare(request): raise web.HTTPUpgradeRequired() return web.Response()
async def handle(self): """Handle the websocket connection.""" request = self.request wsock = self.wsock = web.WebSocketResponse(heartbeat=55) await wsock.prepare(request) self.debug("Connected") # Get a reference to current task so we can cancel our connection self._handle_task = asyncio.Task.current_task(loop=self.hass.loop) @callback def handle_hass_stop(event): """Cancel this connection.""" self.cancel() unsub_stop = self.hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, handle_hass_stop) self._writer_task = self.hass.async_add_job(self._writer()) final_message = None msg = None authenticated = False try: if request[KEY_AUTHENTICATED]: authenticated = True else: self.debug("Request auth") await self.wsock.send_json(auth_required_message()) msg = await wsock.receive_json() msg = AUTH_MESSAGE_SCHEMA(msg) if self.hass.auth.active and 'access_token' in msg: self.debug("Received access_token") token = self.hass.auth.async_get_access_token( msg['access_token']) authenticated = token is not None elif ((not self.hass.auth.active or self.hass.auth.support_legacy) and 'api_password' in msg): self.debug("Received api_password") authenticated = validate_password(request, msg['api_password']) if not authenticated: self.debug("Authorization failed") await self.wsock.send_json( auth_invalid_message('Invalid access token or password')) await process_wrong_login(request) return wsock self.debug("Auth OK") await self.wsock.send_json(auth_ok_message()) # ---------- AUTH PHASE OVER ---------- msg = await wsock.receive_json() last_id = 0 handlers = self.hass.data[DOMAIN] while msg: self.debug("Received", msg) msg = MINIMAL_MESSAGE_SCHEMA(msg) cur_id = msg['id'] if cur_id <= last_id: self.to_write.put_nowait( error_message(cur_id, ERR_ID_REUSE, 'Identifier values have to increase.')) elif msg['type'] not in handlers: self.log_error('Received invalid command: {}'.format( msg['type'])) self.to_write.put_nowait( error_message(cur_id, ERR_UNKNOWN_COMMAND, 'Unknown command.')) else: handler, schema = handlers[msg['type']] handler(self.hass, self, schema(msg)) last_id = cur_id msg = await wsock.receive_json() except vol.Invalid as err: error_msg = "Message incorrectly formatted: " if msg: error_msg += humanize_error(msg, err) else: error_msg += str(err) self.log_error(error_msg) if not authenticated: final_message = auth_invalid_message(error_msg) else: if isinstance(msg, dict): iden = msg.get('id') else: iden = None final_message = error_message(iden, ERR_INVALID_FORMAT, error_msg) except TypeError as err: if wsock.closed: self.debug("Connection closed by client") else: _LOGGER.exception("Unexpected TypeError: %s", err) except ValueError as err: msg = "Received invalid JSON" value = getattr(err, 'doc', None) # Py3.5+ only if value: msg += ': {}'.format(value) self.log_error(msg) self._writer_task.cancel() except CANCELLATION_ERRORS: self.debug("Connection cancelled") except asyncio.QueueFull: self.log_error("Client exceeded max pending messages [1]:", MAX_PENDING_MSG) self._writer_task.cancel() except Exception: # pylint: disable=broad-except error = "Unexpected error inside websocket API. " if msg is not None: error += str(msg) _LOGGER.exception(error) finally: unsub_stop() for unsub in self.event_listeners.values(): unsub() try: if final_message is not None: self.to_write.put_nowait(final_message) self.to_write.put_nowait(None) # Make sure all error messages are written before closing await self._writer_task except asyncio.QueueFull: self._writer_task.cancel() await wsock.close() self.debug("Closed connection") return wsock
def __init__(self): super().__init__() self._subscriptions = [] self.websocket = web.WebSocketResponse(heartbeat=60)
async def init_ws(self) -> web.WebSocketResponse: ws = web.WebSocketResponse() await ws.prepare(self.request) return ws
async def job_status_ws_handler(redis_client: Redis, request: web.Request) -> web.WebSocketResponse: ws = web.WebSocketResponse() await ws.prepare(request) logging.debug('Client connected to job status') jobs = {} job_status = {} async def check_status(job: Job) -> str: await asyncio.sleep(JOB_REFRESH_PERIOD) try: job.refresh() except NoSuchJobError: jobs[job.id] = None return job.id recieve_msg_task = asyncio.ensure_future(ws.receive()) pending = set([recieve_msg_task]) while not ws.closed: done, pending = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED) # update job list when received message if recieve_msg_task in done: msg = recieve_msg_task.result() if msg.type == WSMsgType.ERROR: logging.error( f'WS connection closed with exception {ws.exception()}') elif msg.type == WSMsgType.TEXT: if msg.data == 'close': await ws.close() else: new_job_ids = json.loads(msg.data) logging.debug('Watching new job ids: %s', new_job_ids) jobs = dict( zip(new_job_ids, Job.fetch_many(new_job_ids, redis_client))) pending = set( asyncio.ensure_future(check_status(job)) for job in jobs.values() if job is not None) recieve_msg_task = asyncio.ensure_future(ws.receive()) pending.add(recieve_msg_task) job_status = { job_id: job.get_status( refresh=False) if job is not None else None for job_id, job in jobs.items() } await ws.send_json(prepare_response(jobs)) # handle job status check else: change = False for done_task in done: job_id = done_task.result() if jobs[job_id] is not None: job = jobs[job_id] new_status = job.get_status(refresh=False) pending.add(check_status(jobs[job_id])) if job_status[job_id] != new_status: job_status[job_id] = new_status change = True else: now = time.time() if ( job.is_queued or job.is_started ) and now - job.enqueued_at.timestamp() > TASK_LIMIT: jobs[job_id].exc_info = 'task time limit exceeded' change = True else: job_status[job_id] = None change = True if change: await ws.send_json(prepare_response(jobs)) logging.debug('Client disconnected from job status') return ws
async def handler(req: web.Request, service_url: str, **_kwargs): """ Redirects communication to jupyter notebook in the backend (e.g. front-end) client <---> proxy <-----> server (e.g. backend dynamic service) :param req: aiohttp request :type req: web.Request :param service_url: Resolved url pointing to backend jupyter service. Typically http:hostname:port/x/12345/. :type service_url: str :raises ValueError: Unexpected web-socket message """ # FIXME: hash of statics somehow get do not work. then neeed to be strip away # Removing query ... which not sure is a good idea target_url = URL(service_url).origin() / req.path.lstrip("/") reqH = req.headers.copy() if ( reqH.get("connection", "").lower() == "upgrade" and reqH.get("upgrade", "").lower() == "websocket" and req.method == "GET" ): ws_server = web.WebSocketResponse() available = ws_server.can_prepare(req) if available: await ws_server.prepare(req) logger.info("##### WS_SERVER %s", pprint.pformat(ws_server)) try: req.app[APP_SOCKETS_KEY].append(ws_server) async with aiohttp.ClientSession(cookies=req.cookies) as session: # websocket connection with backend async with session.ws_connect(target_url) as ws_client: logger.info("##### WS_CLIENT %s", pprint.pformat(ws_client)) await asyncio.wait( [ ws_forward(ws_server, ws_client), ws_forward(ws_client, ws_server), ], return_when=asyncio.FIRST_COMPLETED, ) return ws_server finally: req.app[APP_SOCKETS_KEY].remove(ws_server) else: target_url = URL(service_url).origin().with_path(req.path).with_query(req.query) async with client_request( req.method, target_url, headers=reqH, allow_redirects=False, data=await req.read(), ) as res: data = await res.read() response = web.Response( headers=res.headers.copy(), status=res.status, body=data ) # TODO: PC add chunks load. Mattwards takes very long to load # TODO: PC unique session or redo context management?? # TODO: should be fixed in #710 # response = web.Response( # headers=res.headers.copy(), # status=res.status # ) # await response.prepare(req) # content = res.content # whole = await content.read() # await response.write(whole) logger.debug("<-- %s", target_url) # await response.write_eof() return response
async def test_no_upgrade() -> None: ws = web.WebSocketResponse() req = make_mocked_request('GET', '/') with pytest.raises(web.HTTPBadRequest): await ws.prepare(req)
async def test_not_get() -> None: ws = web.WebSocketResponse() req = make_mocked_request('POST', '/') with pytest.raises(web.HTTPMethodNotAllowed): await ws.prepare(req)
def handle(self): """Handle the websocket connection.""" request = self.request wsock = self.wsock = web.WebSocketResponse() yield from wsock.prepare(request) self.debug("Connected") # Get a reference to current task so we can cancel our connection self._handle_task = asyncio.Task.current_task(loop=self.hass.loop) @callback def handle_hass_stop(event): """Cancel this connection.""" self.cancel() unsub_stop = self.hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, handle_hass_stop) self._writer_task = self.hass.async_add_job(self._writer()) final_message = None msg = None authenticated = False try: if request[KEY_AUTHENTICATED]: authenticated = True else: yield from self.wsock.send_json(auth_required_message()) msg = yield from wsock.receive_json() msg = AUTH_MESSAGE_SCHEMA(msg) if validate_password(request, msg['api_password']): authenticated = True else: self.debug("Invalid password") yield from self.wsock.send_json( auth_invalid_message('Invalid password')) if not authenticated: yield from process_wrong_login(request) return wsock yield from self.wsock.send_json(auth_ok_message()) # ---------- AUTH PHASE OVER ---------- msg = yield from wsock.receive_json() last_id = 0 while msg: self.debug("Received", msg) msg = BASE_COMMAND_MESSAGE_SCHEMA(msg) cur_id = msg['id'] if cur_id <= last_id: self.to_write.put_nowait( error_message(cur_id, ERR_ID_REUSE, 'Identifier values have to increase.')) else: handler_name = 'handle_{}'.format(msg['type']) getattr(self, handler_name)(msg) last_id = cur_id msg = yield from wsock.receive_json() except vol.Invalid as err: error_msg = "Message incorrectly formatted: " if msg: error_msg += humanize_error(msg, err) else: error_msg += str(err) self.log_error(error_msg) if not authenticated: final_message = auth_invalid_message(error_msg) else: if isinstance(msg, dict): iden = msg.get('id') else: iden = None final_message = error_message(iden, ERR_INVALID_FORMAT, error_msg) except TypeError as err: if wsock.closed: self.debug("Connection closed by client") else: _LOGGER.exception("Unexpected TypeError: %s", msg) except ValueError as err: msg = "Received invalid JSON" value = getattr(err, 'doc', None) # Py3.5+ only if value: msg += ': {}'.format(value) self.log_error(msg) self._writer_task.cancel() except asyncio.CancelledError: self.debug("Connection cancelled by server") except asyncio.QueueFull: self.log_error("Client exceeded max pending messages [1]:", MAX_PENDING_MSG) self._writer_task.cancel() except Exception: # pylint: disable=broad-except error = "Unexpected error inside websocket API. " if msg is not None: error += str(msg) _LOGGER.exception(error) finally: unsub_stop() for unsub in self.event_listeners.values(): unsub() try: if final_message is not None: self.to_write.put_nowait(final_message) self.to_write.put_nowait(None) # Make sure all error messages are written before closing yield from self._writer_task except asyncio.QueueFull: self._writer_task.cancel() yield from wsock.close() self.debug("Closed connection") return wsock
async def ws_handler(request): ''' Handles websocket connection''' log = request.app.logger loop = request.app.loop ws = web.WebSocketResponse() # Display error if ws fails to start if not ws.can_prepare(request): log.error("Well, websocket failed to start..") # prepare websocket await ws.prepare(request) # save ws client request.app['client'] = ws log.debug('Client has connected') ws.send_str('Well hello there Client hero!') # if we still have epubs in memory let's make a dict of the epub and send it to the client current_epubs: dict = { epub_name: { 'ready': epub.get('ready'), 'conversions': epub.get('conversions') } for (epub_name, epub) in request.app.get('epubs').items() } if len(current_epubs) > 0: ws.send_json({'do': 'show_current_epubs', 'with': current_epubs}) # and let's do the same for the conversion_unit current_conversion_unit = request.app.get('conversion_unit') if current_conversion_unit: ws.send_json({ 'do': 'show_current_conversion_unit', 'with': current_conversion_unit }) # go over received message async for msg in ws: log.debug(f'Client sent: {msg}'[:300]) # convert data to json data: Dict[str, Union[str, Dict]] = json.loads(msg.data) # handle messages if data.get('do') == 'convert_epub': file = data.get('with') # schedule task for converting epub loop.create_task(convert_epub(file, app=request.app)) elif data.get('do') == 'set_conversion_unit': # get conversion unit unit_system = data.get('with', 'metric') request.app['conversion_unit'] = unit_system log.debug(f'Conversion unit set to {unit_system}') elif data.get('do') == 'remove_epub': del request.app['epubs'][data.get('with')] log.debug('Client has disconnected') return ws
async def async_handle(self): """Handle a websocket response.""" request = self.request wsock = self.wsock = web.WebSocketResponse(heartbeat=55) await wsock.prepare(request) self._logger.debug("Connected") # Py3.7+ if hasattr(asyncio, 'current_task'): # pylint: disable=no-member self._handle_task = asyncio.current_task() else: self._handle_task = asyncio.Task.current_task(loop=self.hass.loop) @callback def handle_hass_stop(event): """Cancel this connection.""" self._cancel() unsub_stop = self.hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, handle_hass_stop) self._writer_task = self.hass.async_create_task(self._writer()) auth = AuthPhase(self._logger, self.hass, self._send_message, request) connection = None disconnect_warn = None try: self._send_message(auth_required_message()) # Auth Phase try: with async_timeout.timeout(10): msg = await wsock.receive() except asyncio.TimeoutError: disconnect_warn = \ 'Did not receive auth message within 10 seconds' raise Disconnect if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING): raise Disconnect elif msg.type != WSMsgType.TEXT: disconnect_warn = 'Received non-Text message.' raise Disconnect try: msg = msg.json() except ValueError: disconnect_warn = 'Received invalid JSON.' raise Disconnect self._logger.debug("Received %s", msg) connection = await auth.async_handle(msg) # Command phase while not wsock.closed: msg = await wsock.receive() if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING): break elif msg.type != WSMsgType.TEXT: disconnect_warn = 'Received non-Text message.' break try: msg = msg.json() except ValueError: disconnect_warn = 'Received invalid JSON.' break self._logger.debug("Received %s", msg) connection.async_handle(msg) except asyncio.CancelledError: self._logger.info("Connection closed by client") except Disconnect: pass except Exception: # pylint: disable=broad-except self._logger.exception("Unexpected error inside websocket API") finally: unsub_stop() if connection is not None: connection.async_close() try: self._to_write.put_nowait(None) # Make sure all error messages are written before closing await self._writer_task except asyncio.QueueFull: self._writer_task.cancel() await wsock.close() if disconnect_warn is None: self._logger.debug("Disconnected") else: self._logger.warning("Disconnected: %s", disconnect_warn) return wsock
async def WebSocketCmd(self, request): ws = web.WebSocketResponse() await ws.prepare(request) request.app['websocketscmd'].add(ws) await ws.send_json( {"OK": ["start connection", "event on init connection"]}) #totalFrames = cap.get(cv2.CAP_PROP_FRAME_COUNT) async for msg in ws: if msg.type == WSMsgType.TEXT: try: print("data=", type(msg.data), msg.data) msg_json = json.loads(msg.data) print("json=", type(msg_json), msg_json['cmd']) if msg_json['cmd'] == 'close': await ws.close() elif msg_json['cmd'] == 'getStreamsConfig': if "manager" in self.app: await self.app["manager"].getStreamsConfig(ws) else: await ws.send_json( {"error": ['getStreamsConfig', msg.data]}) elif msg_json['cmd'] == 'getManagerData': if "manager" in self.app: data = self.app["manager"].getConfig() # data = test_manager_config print("getManagerData", data) await ws.send_json(data) else: print(sys.exc_info()) await ws.send_json( {"error": ['getManagerData', msg.data]}) elif msg_json['cmd'] == 'saveStream': await self.saveConfig(ws, msg_json['config']) elif msg_json['cmd'] == 'stopGetStream': print("stopGetStream", msg_json['stream_id']) self.removeLiveStream(ws, msg_json['stream_id']) await ws.send_json({ "OK": ["stopGetStream", msg_json['stream_id'], "server"] }) elif msg_json['cmd'] == 'startGetStream': print("startGetStream", msg_json['stream_id']) if 'manager' in self.app: if msg_json['stream_id'] in self.app[ 'manager'].camsList: if msg_json['stream_id'] in self.live_streams: if ws not in self.live_streams[ msg_json['stream_id']]: self.live_streams[ msg_json['stream_id']].append[ws] else: self.live_streams[ msg_json['stream_id']] = [ws] print("startGetStream", self.live_streams) await ws.send_json({ "OK": [ "startGetStream", msg_json['stream_id'], "server" ] }) else: await ws.send_json({ "error": [ "startGetStream", msg_json['stream_id'], "server" ] }) else: await ws.send_json({ "error": [ "startGetStream", msg_json['stream_id'], "mamanger is not running" ] }) elif msg_json['cmd'] == 'startStream': print("startStream", msg_json['stream_id']) if 'manager' in self.app: try: self.app['manager'].startStream( msg_json['stream_id'], ws) except: print(sys.exc_info()) await ws.send_json({ "error": [ "startStream", msg_json['stream_id'], "exception on server" ] }) else: await ws.send_json({ "error": [ "startStream", msg_json['stream_id'], "mamanger is not running" ] }) elif msg_json['cmd'] == 'stopStream': print("stopStream", msg_json['stream_id']) if 'manager' in self.app: try: self.app['manager'].stopStream( msg_json['stream_id']) del self.live_streams[msg_json['stream_id']] except: print(sys.exc_info()) await ws.send_json({ "error": [ "stopStream", msg_json['stream_id'], "exception on server" ] }) else: await ws.send_json({ "error": [ "stopStream", msg_json['stream_id'], "mamanger is not running" ] }) else: print("error websocket command") await ws.send_json({"error": ['unknown', msg.data]}) except: print(sys.exc_info()) await ws.send_json( {"error": ["can not parse json", msg.data]}) elif msg.type == WSMsgType.ERROR: print('ws connection closed with exception %s' % ws.exception()) # print('websocket connection closed') #if 'manager' in self.app: # try: # await self.app['manager'].stopGetStream(ws, "all") # except: # print("server exceptption on stopGetStream on close connection") # print(sys.exc_info()) self.removeLiveStreams(ws) request.app['websocketscmd'].remove(ws) return ws
async def handle_websocket(self, request): ws = web.WebSocketResponse() await ws.prepare(request) await self.reply_to_websocket(ws) await ws.close()
async def get(self): """ Initiates the websocket connection between the bike and the server. Requires an open ticket (which can be created by posting) to succeed. """ socket = web.WebSocketResponse() await socket.prepare(self.request) remote = self.request.remote public_key = await socket.receive_bytes(timeout=0.5) signature = await socket.receive_bytes(timeout=0.5) try: ticket = self.open_tickets.pop_ticket(remote, public_key) except KeyError: await socket.send_str("fail:no_ticket") return socket # verify the signed challenge try: verify_key = VerifyKey(ticket.bike.public_key, encoder=RawEncoder) verify_key.verify(ticket.challenge, signature) except BadSignatureError: await socket.send_str("fail:invalid_sig") return socket logger.info("Bike %s connected", ticket.bike.id) await self.bike_connection_manager.add_connection(ticket.bike, socket) ticket.bike.socket = socket await socket.send_str("verified") status = await socket.receive_json() if "locked" in status: self.bike_connection_manager.update_locked(ticket.bike.id, status["locked"]) try: async for msg in socket: msg: WSMessage = msg try: data = msg.json() except JSONDecodeError: continue else: if "method" in data: valid_data = JsonRPCRequest().load(data) if "id" not in valid_data and valid_data[ "method"] == "location_update": point = Point(valid_data["params"]["long"], valid_data["params"]["lat"]) await self.bike_connection_manager.update_location( ticket.bike.id, point) self.bike_connection_manager.update_battery( ticket.bike.id, valid_data["params"]["bat"]) else: valid_data = JsonRPCResponse().load(data) await self.bike_connection_manager.resolve_command( ticket.bike.id, valid_data["id"], valid_data["result"]) finally: logger.info("Bike %s disconnected", ticket.bike.id) await socket.close() del self.bike_connection_manager._bike_connections[ticket.bike.id] del ticket del socket
async def handler(request): ws = web.WebSocketResponse(protocols=("foo", "bar")) await ws.prepare(request) await ws.close() closed.set_result(None) return ws
async def spectrogram_handler(request): print('Websocket connection - starting') ws = web.WebSocketResponse() await ws.prepare(request) print('Websocket connection - ready') fs = None guidanceController = GuidanceController() async for msg in ws: if msg.type == WSMsgType.BINARY: print('Websocket connection - received binary') try: spectrogram = guidanceController.show_spectrogram( bin2int16(msg.data), fs) print("spectrogram", np.size(spectrogram)) await ws.send_str( json.dumps({ 'dataType': 'spectrogram', 'data': spectrogram.tolist() })) except Exception as inst: print(type(inst)) # the exception instance print(inst.args) # arguments stored in .args print(inst) if msg.type == WSMsgType.TEXT: print('Websocket connection - received text') message = json.loads(msg.data) if message['action'] == 'load fs': fs = message['fs'] try: await ws.send_str( json.dumps({ 'dataType': 'message', 'data': 'fs loaded' })) except Exception as inst: print(type(inst)) # the exception instance print(inst.args) # arguments stored in .args print(inst) elif message['action'] == 'spectrogram': spectrogram = guidanceController.spectrogram( message['data'], fs) plt.imshow(spectrogram) plt.xticks([]) plt.yticks([]) fig = plt.gcf() img = fig2img(fig) in_mem_file = io.BytesIO() img.save(in_mem_file, format="PNG") # reset file pointer to start in_mem_file.seek(0) img_bytes = in_mem_file.read() base64_encoded_result_bytes = base64.b64encode(img_bytes) base64_encoded_result_str = base64_encoded_result_bytes.decode( 'ascii') try: await ws.send_str( json.dumps({ 'dataType': 'spectrogram_img', 'data': base64_encoded_result_str })) except Exception as inst: print(type(inst)) # the exception instance print(inst.args) # arguments stored in .args print(inst) else: await ws.send_str( json.dumps({ 'dataType': 'message', 'data': 'Audio buffer loading' })) else: await ws.send_str( json.dumps({ 'dataType': 'message', 'data': msg.data + '/answer' })) print('Websocket connection closed') return ws
async def handler(request): ws = web.WebSocketResponse() await ws.prepare(request) await ws.receive_bytes() await ws.send_str('test') await asyncio.sleep(10)
async def incoming_connection(self, request): if request.remote in self.banned_peers and time.time( ) < self.banned_peers[request.remote]: self.log.warning( f"Peer {request.remote} is banned, refusing connection") return None ws = web.WebSocketResponse(max_msg_size=50 * 1024 * 1024) await ws.prepare(request) close_event = asyncio.Event() cert_bytes = request.transport._ssl_protocol._extra[ "ssl_object"].getpeercert(True) der_cert = x509.load_der_x509_certificate(cert_bytes) peer_id = bytes32(der_cert.fingerprint(hashes.SHA256())) if peer_id == self.node_id: return ws connection: Optional[WSChiaConnection] = None try: connection = WSChiaConnection( self._local_type, ws, self._port, self.log, False, False, request.remote, self.incoming_messages, self.connection_closed, peer_id, self._inbound_rate_limit_percent, self._outbound_rate_limit_percent, close_event, ) handshake = await connection.perform_handshake( self._network_id, protocol_version, self._port, self._local_type, ) assert handshake is True # Limit inbound connections to config's specifications. if not self.accept_inbound_connections(connection.connection_type): self.log.info( f"Not accepting inbound connection: {connection.get_peer_info()}.Inbound limit reached." ) await connection.close() close_event.set() else: await self.connection_added(connection, self.on_connect) if self._local_type is NodeType.INTRODUCER and connection.connection_type is NodeType.FULL_NODE: self.introducer_peers.add(connection.get_peer_info()) except ProtocolError as e: if connection is not None: await connection.close(self.invalid_protocol_ban_seconds, WSCloseCode.PROTOCOL_ERROR, e.code) if e.code == Err.INVALID_HANDSHAKE: self.log.warning( "Invalid handshake with peer. Maybe the peer is running old software." ) close_event.set() elif e.code == Err.INCOMPATIBLE_NETWORK_ID: self.log.warning( "Incompatible network ID. Maybe the peer is on another network" ) close_event.set() elif e.code == Err.SELF_CONNECTION: close_event.set() else: error_stack = traceback.format_exc() self.log.error( f"Exception {e}, exception Stack: {error_stack}") close_event.set() except Exception as e: if connection is not None: await connection.close( ws_close_code=WSCloseCode.PROTOCOL_ERROR, error=Err.UNKNOWN) error_stack = traceback.format_exc() self.log.error(f"Exception {e}, exception Stack: {error_stack}") close_event.set() await close_event.wait() return ws
async def websocket(self, request: web.Request): """Initialize a WebSocket API connection.""" _LOGGER.info("Home Assistant WebSocket API request initialize") # init server server = web.WebSocketResponse(heartbeat=30) await server.prepare(request) # handle authentication try: await server.send_json({ "type": "auth_required", "ha_version": self.sys_homeassistant.version }) # Check API access response = await server.receive_json() hassio_token = response.get("api_password") or response.get( "access_token") addon = self.sys_addons.from_token(hassio_token) if not addon or not addon.access_homeassistant_api: _LOGGER.warning("Unauthorized WebSocket access!") await server.send_json({ "type": "auth_invalid", "message": "Invalid access" }) return server _LOGGER.info("WebSocket access from %s", addon.slug) await server.send_json({ "type": "auth_ok", "ha_version": self.sys_homeassistant.version }) except (RuntimeError, ValueError) as err: _LOGGER.error("Can't initialize handshake: %s", err) return server # init connection to hass try: client = await self._websocket_client() except APIError: return server _LOGGER.info("Home Assistant WebSocket API request running") try: client_read = None server_read = None while not server.closed and not client.closed: if not client_read: client_read = self.sys_create_task(client.receive_str()) if not server_read: server_read = self.sys_create_task(server.receive_str()) # wait until data need to be processed await asyncio.wait([client_read, server_read], return_when=asyncio.FIRST_COMPLETED) # server if server_read.done() and not client.closed: server_read.exception() await client.send_str(server_read.result()) server_read = None # client if client_read.done() and not server.closed: client_read.exception() await server.send_str(client_read.result()) client_read = None except asyncio.CancelledError: pass except (RuntimeError, ConnectionError, TypeError) as err: _LOGGER.info("Home Assistant WebSocket API error: %s", err) finally: if client_read: client_read.cancel() if server_read: server_read.cancel() # close connections if not client.closed: await client.close() if not server.closed: await server.close() _LOGGER.info("Home Assistant WebSocket API connection is closed") return server
def handler(request): ws = web.WebSocketResponse() yield from ws.prepare(request) yield from ws.receive_bytes() ws.send_str('test') yield from asyncio.sleep(10, loop=loop)
async def create(request): room_id = request.match_info['room_id'] user_id = request.match_info['user_id'] ws_current = web.WebSocketResponse() ws_ready = ws_current.can_prepare(request) if not ws_ready.ok: msg = "Sorry, something went wrong!" return web.json_response({'error': msg}) await ws_current.prepare(request) query = {'_id': ObjectId(room_id), 'active': True} room = await Room.find_room(query=query, db=request.app['mongodb']) # room does not exist if room is None: msg = "Room is closed, create a new room" await ws_current.send_json({ 'action': 'error', 'userId': user_id, 'msg': room_id }) await ws_current.close() return if not any(user_id == str(user['_id']) for user in room['users']): msg = "You have not joined the room" await ws_current.send_json({ 'action': 'error', 'userId': user_id, 'msg': msg }) await ws_current.close() return users = [{ 'email': user['email'], 'username': user['username'], 'userId': str(user['_id']) } for user in room['users']] await ws_current.send_json({ 'action': 'connect', 'userId': user_id, 'users': users }) current_user = next({ 'email': user['email'], 'username': user['username'], 'userId': str(user['_id']) } for user in room['users'] if user_id == str(user['_id'])) # notify current users of new user for user in room['users']: if str(user['_id']) in request.app['websockets']: user_ws = request.app['websockets'][str(user['_id'])] await user_ws.send_json({'action': 'join', 'user': current_user}) request.app['websockets'][user_id] = ws_current async for msg in ws_current: if msg.type == WSMsgType.text: if msg.data == 'close': await ws_current.close() else: for user in room['users']: if str(user['_id']) in request.app['websockets']: user_ws = request.app['websockets'][str(user['_id'])] # forward message to all users except the sender if user_ws is not ws_current: await user_ws.send_json({ 'action': 'sent', 'userId': user_id, 'text': msg.data }) elif msg.type == WSMsgType.ERROR: print('ws connection closed with exception %s' % ws_current.exception()) else: break if user_id in request.app['websockets']: del request.app['websockets'][user_id] room_filter = {'_id': ObjectId(room_id), 'active': True} game_filter = {'room_id': ObjectId(room_id), 'active': True} await room_helper.remove_user_from_room_and_game( room_filter, game_filter, user_id, request) for user in room['users']: if str(user['_id']) in request.app['websockets']: user_ws = request.app['websockets'][str(user['_id'])] await user_ws.send_json({ 'action': 'disconnect', 'userId': user_id }) return ws_current
def handler(request): ws = web.WebSocketResponse() yield from ws.prepare(request) yield from ws.receive() yield from ws.close() return ws
async def no_pong_handler(self, request): ws = web.WebSocketResponse(autoping=False) self.connections.append(ws) await ws.prepare(request) await asyncio.sleep(20) return ws
async def client_shutdown(self, request): ws = web.WebSocketResponse() self.connections.append(ws) await ws.prepare(request) await asyncio.sleep(10)