import json from tornado.websocket import WebSocketHandler from .serialization import deserialize_all from ..util import parse_anchor_from_message from .event_handler_connector import EventHandlerConnector from ..config.logs import logging log = logging.getLogger(__name__) class ZMQWebSocketHandler(WebSocketHandler): _event_handler_connector = EventHandlerConnector() #----. # TODO: investigate thread safety! <-----------------' # ZMQ sockets shared between several WebSocketHandler instances # http://pyzmq.readthedocs.io/en/latest/morethanbindings.html#thread-safety def __init__(self, application, request, **kwargs): super().__init__(application, request, **kwargs) def open(self, *args, **kwargs): log.debug('WebSocket connection initiated') self._event_handler_connector.register_callback(self.zmq_callback) def zmq_callback(self, msg_parts): anchor, data = deserialize_all(*msg_parts) log.debug('Received on pull socket: {}'.format(data)) self.write_message(data) def on_message(self, message): log.debug('Received on WebSocket: {}'.format(message)) self.send_message(*self.make_response(message)) def make_response(self, message): raise NotImplementedError def send_message(self, message: str, anchor: str = None): self._event_handler_connector.send_message(message, anchor) def on_close(self): pass # much secure, very cors, wow def check_origin(self, origin): return True class FSMManagingSocketHandler(ZMQWebSocketHandler): def __init__(self, FSM, application, request, **kwargs): super().__init__(application, request, **kwargs) self.fsm = FSM() self.fsm.subscribe_message_handler(self.handle_fsm_message) def handle_fsm_message(self, message): self._event_handler_connector.send_message(message) def make_response(self, message): self.fsm.trigger(parse_anchor_from_message(message), message=message) anchor = 'FSMUpdate' response = {'anchor': anchor, 'data': {'current_state': self.fsm.state, 'valid_transitions': [{'trigger': trigger} for trigger in self.fsm.machine.get_triggers()]}} return json.dumps(response), anchor