def handle_read(self): data = self.dispatcher.recv(4096) if not data: self.connection_lost() return Trace.trace("{} received {}", self.link.name, repr(data)) self.on_receive(data)
def start_flows(self): with self.rwlock.rlock(): snapshot = self.flows[:] for flow in snapshot: Trace.trace("hub: starting flow {}", flow.name) flow.start() Trace.debug("hub: started flow {}", flow.name)
def listen(self, host, port): factory = self.loop.create_server(self, host, port) self.server = self.loop.run_until_complete(factory) Trace.info("listening on {}:{}", host, port) self.thread.start()
def process(self, event): type_id = event.type_id() if type_id == LinkEventType.HANDSHAKE_REQ: response = None try: response = self.buffer_transform.handshake(event.data) except Exception as ex: Trace.error("{} error handshaking {}", self.link.name, ex) self.session.send(HandshakeResp().setattrs(_transform=False, data=response)) elif type_id == LinkEventType.HANDSHAKE_RESP: result = False try: result = self.buffer_transform.fini_handshake(event.data) except Exception as ex: Trace.error("{} error finishing handshake {}", self.link.name, ex) if result: self.rx_transform_ready = True self.session.send(HandshakeAck().setattrs(_transform=False, result=result)) elif type_id == LinkEventType.HANDSHAKE_ACK: result = event.result if result: self.tx_transform_ready = True self.session.link.on_connect(result, self.session) else: return False return True
def listen(self, host, port): self.dispatcher.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.dispatcher.bind((host, port)) self.dispatcher.listen(5) Trace.info("listening on {}:{}", host, port) self.thread.start()
def connect(self, host, port): self.remote_host = host self.remote_port = port Trace.info("connecting to {}:{}", host, port) factory = self.loop.create_connection(self, host, port) transport, protocol = self.loop.run_until_complete(factory) self.thread.start()
def handle_error(self): err = self.dispatcher.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) if self.connecting: Trace.error("connect error {}", errno.errorcode[err]) self.connecting = False return Trace.error("error {}", errno.errorcode[err])
def startup(): """Starts all the flows attached to the hub.""" Trace.debug("starting up") Hub.instance.setup() Hub.instance.start_flows() TimeFlow.get().reserve_repetition(Hub.heartbeat_event, \ timedelta(seconds=Config.heartbeat_interval)) Trace.info("started")
def _on_connect(self, result, context): super(TcpClient, self)._on_connect(result, context) if result: peername = context.transport.get_extra_info('peername') Trace.info("connected to {}:{}", peername[0], peername[1]) else: Trace.error("error connecting to {}:{}", self.remote_host, self.remote_port)
def on_heartbeat(self): session = self.link.session if session is None or not session.connected(): return session_strategy = self.link.session.heartbeat_strategy if session_strategy.on_heartbeat(): Trace.warn("{} {} closing due to the keepalive failure", \ self.link.name, session.handle) session.close()
def _on_connect(self, result, context): super(TcpClient, self)._on_connect(result, context) if result: peername = context.socket.getpeername() Trace.info("connected to {}:{}", peername[0], peername[1]) context.peername = peername else: Trace.error("error connecting to {}:{}", self.remote_host, self.remote_port)
def connect(self, host, port): self.connecting = True self.remote_host = host self.remote_port = port Trace.info("connecting to {}:{}", host, port) self.dispatcher.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.dispatcher.connect((host, port)) self.thread.start()
def attach(self, flow): """Attaches the specified flow to the hub.""" if flow is None or not isinstance(flow, Flow): raise TypeError() with self.rwlock.wlock(): if flow not in self.flows: self.flows.append(flow) Trace.debug("hub: attached flow {}", flow.name) return self
def detach(self, flow): """Detaches the specified flow from the hub.""" if flow is None or not isinstance(flow, Flow): raise TypeError() with self.rwlock.wlock(): if flow in self.flows: self.flows.remove(flow) Trace.debug("hub: detached flow {}", flow.name) return self
def on_heartbeat(self): sessions = list(self.link.sessions.values()) for session in sessions: if session is None or not session.connected(): continue session_strategy = session.heartbeat_strategy if session_strategy.on_heartbeat(): Trace.warn("{} {} closing due to the keepalive failure", \ self.link.name, session.handle) session.close()
def stop_flows(self): with self.rwlock.rlock(): snapshot = self.flows[::-1] for flow in snapshot: try: Trace.trace("hub: stopping flow {}", flow.name) flow.stop() Trace.debug("hub: stopped flow {}", flow.name) except: pass
def on_disconnect(self, handle, context): Trace.info("{} disconnected {} {}", self.name, handle, context) self._on_disconnect(handle, context) if handle != 0: SessionBasedLink.handle_pool.release(handle) LinkSessionDisconnected().setattrs(link_name=self.name, handle=handle, context=context).post()
def on_receive(self, data): if self.has_heartbeat_strategy: self.heartbeat_strategy.on_receive() self.rx_buffer += data deserializer = Deserializer() while True: deserializer.buffer = self.rx_buffer deserializer.pos = 0 num_bytes, length, transformed = self.parse_header(deserializer) if num_bytes == 0: return if len(self.rx_buffer) < (length + num_bytes): return buffer = self.rx_buffer[num_bytes:num_bytes + length] self.rx_buffer = self.rx_buffer[num_bytes + length:] if self.has_channel_strategy and transformed: try: buffer = self.channel_strategy.after_receive(buffer) except Exception as ex: Trace.error("{} inverse transform error {}", self.link.name, ex) continue deserializer.buffer = buffer deserializer.pos = 0 type_id = deserializer.read_int32(None) event = self.link.create_event(type_id) if event is None: Trace.Error("unknown event type id {}", type_id) continue event.deserialize(deserializer) Trace.debug("{} received {}", self.link.name, event) processed = False if self.has_channel_strategy: processed = self.channel_strategy.process(event) elif not processed and self.has_heartbeat_strategy: processed = self.heartbeat_strategy.process(event) elif not processed: processed = self._process(event) if not processed: event._handle = self.handle Hub.post(event)
def on_connect(self, result, context): Trace.info("{} connected {} {}", self.name, result, context) if result: handle = SessionBasedLink.handle_pool.acquire() context.handle = handle self._on_connect(result, context) LinkSessionConnected().setattrs(link_name=self.name, result=result, context=context).post()
def on_timeout(self, e): Flow.unbind_with(self.handler_token) Flow.unbind_with(self.timeout_token) wait_handle = self.handler_token[0]._wait_handle if wait_handle: WaitHandlePool.release(wait_handle) Trace.error("WaitForEvent timeout for {}".format( self.handler_token[0])) self.coroutine.result = None self.coroutine.next()
def init_handshake(self): challenge_length = self.key_size_in_bytes + self.block_size_in_bytes challenge = Random.new().read(challenge_length) Trace.trace("challenge: {}", repr(challenge)) n = self.key_size_in_bytes key = challenge[:n] iv = challenge[n:n + self.block_size_in_bytes] self.encryptor = AES.new(key, AES.MODE_CBC, iv) self.encryption_key = key self.encryption_iv = iv encrypted = self._rsa_encrypt(challenge) Trace.trace("encrypted challenge: {}", repr(encrypted)) return encrypted
def dispatch(self, event): event_proxy = Flow.thread_local.event_proxy handler_chain = Flow.thread_local.handler_chain if len(handler_chain) != 0: del handler_chain[:] self.binding.build_handler_chain(event, event_proxy, handler_chain) for handler in handler_chain: try: handler(event) except Exception as ex: Trace.error("flow: dispatch {}".format(ex)) traceback.print_exc(file=sys.stderr) del handler_chain[:]
def cleanup(self): with self._lock: if self._disposed: return flow = self.flow if flow is None: return try: for binding in self._bindings: flow._unsubscribe(binding[0], binding[1]) del self._bindings[:] self.flow = None except BaseException as ex: Trace.warn("eventsink: cleanup error {}", ex) finally: self_disposed = True
def on_heartbeat(self): link_strategy = self.session.link.heartbeat_strategy if link_strategy.outgoing_heartbeat_enabled: if self.has_sent: self.has_sent = False else: self.session.send(Hub.heartbeat_event) if link_strategy.incoming_heartbeat_enabled: if self.has_received: self.has_received = False self.successive_failure_count = 0 else: self.successive_failure_count = self.successive_failure_count + 1 if not self.marked and \ self.successive_failure_count > link_strategy.max_failure_count: Trace.debug("{} {} keepalive failure count {}", self.session.link.name, self.session.handle, self.successive_failure_count) return True
def _on_disconnect(self, handle, context): super(TcpServer, self)._on_disconnect(handle, context) peername = context.transport.get_extra_info('peername') Trace.info("disconnected from {}:{}", peername[0], peername[1])
def _on_connect(self, result, context): super(TcpServer, self)._on_connect(result, context) if result: peername = context.transport.get_extra_info('peername') Trace.info("accepted from {}:{}", peername[0], peername[1])
def _on_disconnect(self, handle, context): super(TcpServer, self)._on_disconnect(handle, context) peername = context.peername Trace.info("disconnected from {}:{}", peername[0], peername[1])
def _send(self, data): Trace.trace("{} sending {}", self.link.name, data) self.transport.write(data)
def data_received(self, data): if not data: self.connection_lost(self.transport) return Trace.trace("{} received {}", self.link.name, data) self.on_receive(data)
def shutdown(): """Stops all the flows attached to the hub.""" Trace.debug("shutting down") Hub.instance.stop_flows() Hub.instance.teardown() Trace.info("stopped")