Bläddra i källkod

improved connection handlers, added documentation and rewrote a few parts

digital 7 år sedan
förälder
incheckning
ad47535129
1 ändrade filer med 111 tillägg och 25 borttagningar
  1. 111 25
      network/__init__.py

+ 111 - 25
network/__init__.py

@@ -40,42 +40,93 @@ lcchat = logging.getLogger(__name__+".client.chat")
 _tasks = []
 
 class ConnHandlerBase(object):
+    """
+    ConnectionHandlerBase is the base class for all connection handlers.
+    It provides basic methodes. Consider inheriting form ConnectionHandler
+    instead, as it provides better functionality.
+    """
+    addr = None
+    block_size = 1024
+    server = None
     def __init__(self, socket, addr, server):
-        self.status = "init"
         super(ConnHandlerBase, self).__init__()
         self.socket = socket
         self.addr = addr
         self.server = server
-        self.block_size = 1024
-        # self.welcome_client()
-        self.status="connected"
 
-    async def welcome_client(self):
-        pass
+    async def disconnect(self):
+        """
+        disconenct explicitely disconnects the client, shuts the socket down
+        and closes it.
+        """
+        try:
+            await self.send(bytes())
+        except:
+            lserver.debug("error during disconenct")
+        try:
+            await self.socket.shutdown(0)
+        except:
+            lserver.debug("error during socket shutdown")
+        try:
+            await self.socket.close()
+        except:
+            lserver.debug("error closing socket")
 
     async def handle(self, data):
-        return
+        """
+        This method is called for every message the server receives from the
+        client. It should handle the data. Performing asynchronous blocking
+        actions is ok, as the client loop does not wait for this method to
+        finish. therefore, this method can be called multiple times at once,
+        use curio locks if appropriate.
+        """
+        raise NotImplemented()
 
     async def recv(self):
+        """
+        This method waits for the client to send something and returns bytes!
+        """
         data_received = await self.socket.recv(self.block_size)
-        data_decoded = data_received.decode("utf-8")
-        return data_decoded
+        return data_received
 
-    async def send(self, msg, log_msg=False):
-        msg_encoded = bytes(msg, "utf-8")
+    async def send(self, data, log_msg=None):
+        """
+        This method sends bytes to the client. Returns False if an exception
+        was raised during sending, otherwise True.
+        """
         if log_msg:
-            lschat.info("server:"+log_msg)
+            lschat.info("server:"+str(log_msg))
         else:
-            lschat.info("Server:"+msg)
+            lschat.info("Server:"+str(data))
         try:
-            await self.socket.send(msg_encoded)
+            await self.socket.send(data)
             return True
         except Exception as e:
             lserver.error(e, exc_info=True)
             return False
 
-    async def close(self):
-        self.status = "closed"
+
+class ConnHandler(object):
+        """
+        More advanced connection handler than ConnectionHandlerBase. For
+        instance, sends() takes a string and encodes it, recv() decodes
+        the client's and returns a string and welcome_client is called after
+        the ConnHandler is initialized (Not after the inheriting class is
+        initialized though!)
+        """
+    def __init__(self, socket, addr, server):
+        super(ConnHandlerBase, self).__init__(socket,addr,server)
+        await self.welcome_client()
+
+    async def disconnect(self):
+        """
+        disconenct() explicitely disconnects the client, performes a proper
+        the shutdow on the socket and closes it.
+        """
+        try:
+            await self.send("")
+        except:
+            lserver.debug("error during disconenct")
         try:
             await self.socket.shutdown(0)
         except:
@@ -85,18 +136,53 @@ class ConnHandlerBase(object):
         except:
             lserver.debug("error closing socket")
 
+    async def handle(self, data):
+        return
 
-class ConnHandlerEcho(ConnHandlerBase):
+    async def recv(self):
+        """
+        This method waits for the client to send something, decodes it and
+        returns a string.
+        """
+        data_received = await self.socket.recv(self.block_size)
+        data_decoded = data_received.decode("utf-8")
+        return data_decoded
+
+    async def send(self, data, log_msg=False):
+        """
+        This method takes a string, encodes it and sends it to the client.
+        Returns False if an exception was raised during sending, otherwise True.
+        """
+        if log_msg:
+            lschat.info("server:"+log_msg)
+        else:
+            lschat.info("Server:"+data)
+        data_encoded = bytes(data, "utf-8")
+        try:
+            await self.socket.send(data_encoded)
+            return True
+        except Exception as e:
+            lserver.error(e, exc_info=True)
+            return False
+
+    async def welcome_client(self):
+        """
+        This method can be used to send a welcome message to the client.
+        """
+        pass
+
+
+class ConnHandlerEcho(ConnHandler):
+    """
+    A Conn handler which sends everything it receives to every other client
+    connected to the server
+    """
     def __init__(self, socket, addr, server):
-        self.status = "init"
-        self.super_class = super(ConnHandlerEcho, self)
-        self.super_class.__init__(socket, addr, server)
-        self.server = server
-    def welcome_client(self):
-        self.send("welcome to the client")
+        super(ConnHandlerEcho, self).__init__(socket, addr, server)
+
     def handle(self, data):
-        lschat.info("Client:"+data)
-        for h in list(set(self.server.connection_handler)-{self}):
+        for h in self.server.connection_handler:
+            if not h is self:
             h.send(data)
 
 class Server(object):