# -*- coding: utf-8 -*- from tornado.websocket import WebSocketHandler, WebSocketClosedError from tornado.ioloop import IOLoop from tornado.iostream import StreamClosedError import json from oxtornado import json_dumps import state import settings import logging logger = logging.getLogger(__name__) class Handler(WebSocketHandler): def initialize(self, public=False): self._public = public def check_origin(self, origin): # allow access to websocket from site, installer and loader (local file) return self.request.host in origin or \ origin in ( 'http://127.0.0.1:9841', 'http://127.0.0.1:9842', 'file://', 'null' ) def open(self): if self.request.headers['origin'] not in ('null', 'file://', 'http://127.0.0.1:9842') \ and self.request.host not in self.request.headers['origin']: logger.debug('reject cross site attempt to open websocket %s', self.request) self.close() if self not in state.websockets: state.websockets.append(self) if state.update: trigger_event('updatestatus', state.update._status) else: from user.models import User trigger_event('status', { 'id': settings.USER_ID, 'online': state.online }) for u in User.query.filter(User.id!=settings.USER_ID).filter_by(peered=True).all(): u.trigger_status() #websocket calls def on_message(self, message): try: action, data = json.loads(message) except json.decoder.JSONDecodeError: logger.debug('invalid websocket message: %s', message) return if state.tasks: state.tasks.queue(action, data) def on_close(self): if self in state.websockets: state.websockets.remove(self) def post(self, event, data): message = json_dumps([event, data]) if self.ws_connection is None: self.on_close() else: state.main.add_callback(lambda: self._write_message(message)) async def _write_message(self, message): try: task = self.write_message(message) await task except StreamClosedError as e: self.on_close() except WebSocketClosedError as e: self.on_close() def trigger_event(event, data): #if len(state.websockets): # logger.debug('trigger event %s %s %s', event, data, len(state.websockets)) for ws in state.websockets: try: ws.post(event, data) except: logger.debug('failed to send to ws %s %s %s', ws, event, data, exc_info=True)