import json from tornado.websocket import WebSocketHandler from tfw.networking.serialization import deserialize_all from tfw.networking.server.event_handler_connector import EventHandlerConnector from tfw.config.logs import logging log = logging.getLogger(__name__) class ZMQWebSocketHandler(WebSocketHandler): _event_handler_connector = EventHandlerConnector() instances = set() def prepare(self): ZMQWebSocketHandler.instances.add(self) def on_close(self): ZMQWebSocketHandler.instances.remove(self) 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) @staticmethod def zmq_callback(msg_parts): anchor, data = deserialize_all(*msg_parts) log.debug('Received on pull socket: {}'.format(data)) for instance in ZMQWebSocketHandler.instances: instance.write_message(data) def on_message(self, message): log.debug('Received on WebSocket: {}'.format(message)) self.send_message(*self.make_response(json.loads(message))) def send_message(self, message: dict, anchor: str = None): self._event_handler_connector.send_message(message, anchor) # much secure, very cors, wow def check_origin(self, origin): return True class FSMManagingSocketHandler(ZMQWebSocketHandler): def initialize(self, fsm): self.fsm = fsm self.fsm.subscribe_message_handler(self.handle_fsm_message) def on_close(self): super().on_close() self.fsm.unsubscribe_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(message['anchor'], 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 response, anchor