def remove_actor(self, actor): """Remove an actor when the socket is closed.""" if _debug: TCPClientDirector._debug("remove_actor %r", actor) del self.clients[actor.peer] # tell the ASE the client has gone away if self.serviceElement: self.sap_request(delPeer=actor.peer) # see if it should be reconnected if actor.peer in self.reconnect: connect_task = FunctionTask(self.connect, actor.peer) connect_task.install_task(_time() + self.reconnect[actor.peer])
class UDPActor(Logging): def __init__(self, director, peer): if _debug: UDPActor._debug("__init__ %r %r", director, peer) # keep track of the director self.director = director # associated with a peer self.peer = peer # add a timer self.timeout = director.timeout if self.timeout > 0: self.timer = FunctionTask(self.IdleTimeout) self.timer.install_task(_time() + self.timeout) else: self.timer = None # tell the director this is a new actor self.director.AddActor(self) def IdleTimeout(self): if _debug: UDPActor._debug("IdleTimeout") # tell the director this is gone self.director.RemoveActor(self) def indication(self, pdu): if _debug: UDPActor._debug("indication %r", pdu) # reschedule the timer if self.timer: self.timer.install_task(_time() + self.timeout) # put it in the outbound queue for the director self.director.request.put(pdu) def response(self, pdu): if _debug: UDPActor._debug("response %r", pdu) # reschedule the timer if self.timer: self.timer.install_task(_time() + self.timeout) # process this as a response from the director self.director.response(pdu)
class TCPServerActor(TCPServer): def __init__(self, director, sock, peer): if _debug: TCPServerActor._debug("__init__ %r %r %r", director, sock, peer) TCPServer.__init__(self, sock, peer) # keep track of the director self.director = director # add a timer self.timeout = director.timeout if self.timeout > 0: self.timer = FunctionTask(self.idle_timeout) self.timer.install_task(_time() + self.timeout) else: self.timer = None # this may have a flush state self.flushTask = None # tell the director this is a new actor self.director.add_actor(self) def handle_close(self): if _debug: TCPServerActor._debug("handle_close") # if there's a flush task, cancel it if self.flushTask: self.flushTask.suspend_task() # tell the director this is gone self.director.remove_actor(self) # pass it down TCPServer.handle_close(self) def idle_timeout(self): if _debug: TCPServerActor._debug("idle_timeout") # shut it down self.handle_close() def indication(self, pdu): if _debug: TCPServerActor._debug("indication %r", pdu) # additional downstream data is tossed while flushing if self.flushTask: if _debug: TCPServerActor._debug(" - flushing") return # reschedule the timer if self.timer: self.timer.install_task(_time() + self.timeout) # continue as usual TCPServer.indication(self, pdu) def response(self, pdu): if _debug: TCPServerActor._debug("response %r", pdu) # upstream data is tossed while flushing if self.flushTask: if _debug: TCPServerActor._debug(" - flushing") return # save the source pdu.pduSource = self.peer # reschedule the timer if self.timer: self.timer.install_task(_time() + self.timeout) # process this as a response from the director self.director.response(pdu) def flush(self): if _debug: TCPServerActor._debug("flush") # clear out the old task self.flushTask = None # if the outgoing buffer has data, re-schedule another attempt if self.request: self.flushTask = OneShotFunction(self.flush) return # close up shop, all done self.handle_close()