diff --git a/lib/daemon.py b/lib/daemon.py index e386d8c4eee0a3ff2cc6ef60b24b521708d4a793..0e6e042b3e09dc38f989518c4454ce4dad8bc21f 100644 --- a/lib/daemon.py +++ b/lib/daemon.py @@ -91,6 +91,75 @@ class GanetiBaseAsyncoreDispatcher(asyncore.dispatcher): return False +def FormatAddress(family, address): + """Format a client's address + + @type family: integer + @param family: socket family (one of socket.AF_*) + @type address: family specific (usually tuple) + @param address: address, as reported by this class + + """ + if family == socket.AF_INET and len(address) == 2: + return "%s:%d" % address + elif family == socket.AF_UNIX and len(address) == 3: + return "pid=%s, uid=%s, gid=%s" % address + else: + return str(address) + + +class AsyncStreamServer(GanetiBaseAsyncoreDispatcher): + """A stream server to use with asyncore. + + Each request is accepted, and then dispatched to a separate asyncore + dispatcher to handle. + + """ + + _REQUEST_QUEUE_SIZE = 5 + + def __init__(self, family, address): + """Constructor for AsyncUnixStreamSocket + + @type family: integer + @param family: socket family (one of socket.AF_*) + @type address: address family dependent + @param address: address to bind the socket to + + """ + GanetiBaseAsyncoreDispatcher.__init__(self) + self.family = family + self.create_socket(self.family, socket.SOCK_STREAM) + self.set_reuse_addr() + self.bind(address) + self.listen(self._REQUEST_QUEUE_SIZE) + + # this method is overriding an asyncore.dispatcher method + def handle_accept(self): + """Accept a new client connection. + + Creates a new instance of the handler class, which will use asyncore to + serve the client. + + """ + accept_result = utils.IgnoreSignals(self.accept) + if accept_result is not None: + connected_socket, client_address = accept_result + if self.family == socket.AF_UNIX: + # override the client address, as for unix sockets nothing meaningful + # is passed in from accept anyway + client_address = utils.GetSocketCredentials(connected_socket) + logging.info("Accepted connection from %s", + FormatAddress(self.family, client_address)) + self.handle_connection(connected_socket, client_address) + + def handle_connection(self, connected_socket, client_address): + """Handle an already accepted connection. + + """ + raise NotImplementedError + + class AsyncUDPSocket(GanetiBaseAsyncoreDispatcher): """An improved asyncore udp socket.