diff --git a/oml/server.py b/oml/server.py index 7a3f08d..f98ed7b 100644 --- a/oml/server.py +++ b/oml/server.py @@ -22,6 +22,7 @@ import setup import state import tasks import websocket +import ui_websocket import update import logging @@ -130,6 +131,7 @@ def run(): handlers = common_handlers + [ (r'/api/upload/', UploadHandler, dict(context=db.session)), (r'/api/', oxtornado.ApiHandler, dict(context=db.session)), + (r'/ui_socket', ui_websocket.Handler), (r'/ws', websocket.Handler), (r"(.*)", MainHandler), ] diff --git a/oml/state.py b/oml/state.py index 4768e7b..606a22b 100644 --- a/oml/state.py +++ b/oml/state.py @@ -13,6 +13,7 @@ tor = False update = False shutdown = False websockets = [] +uisockets = [] peers = {} changelog_size = None diff --git a/oml/ui_websocket.py b/oml/ui_websocket.py new file mode 100644 index 0000000..7efdddd --- /dev/null +++ b/oml/ui_websocket.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 +import json + + +from tornado.websocket import WebSocketHandler +from tornado.ioloop import IOLoop + +from oxtornado import json_dumps + +import state +import settings +from websocket import trigger_event + +import logging +logger = logging.getLogger(__name__) + + +class Handler(WebSocketHandler): + + queue = [] + + 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.uisockets: + state.uisockets.append(self) + + #websocket calls + def on_message(self, message): + if self.queue: + action = self.queue.pop(0) + trigger_event(action, {'path': message}) + else: + print('no queue got:', message) + + def on_close(self): + if self in state.uisockets: + state.uisockets.remove(self) + + def post(self, message): + if self.ws_connection is None: + self.on_close() + else: + state.main.add_callback(lambda: self.write_message(message)) + +def trigger_ui(message): + for ws in state.uisockets: + try: + ws.post(message) + except: + logger.debug('failed to send to UI ws %s %s', ws, message, exc_info=True)