|
@@ -40,42 +40,93 @@ lcchat = logging.getLogger(__name__+".client.chat")
|
|
_tasks = []
|
|
_tasks = []
|
|
|
|
|
|
class ConnHandlerBase(object):
|
|
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):
|
|
def __init__(self, socket, addr, server):
|
|
- self.status = "init"
|
|
|
|
super(ConnHandlerBase, self).__init__()
|
|
super(ConnHandlerBase, self).__init__()
|
|
self.socket = socket
|
|
self.socket = socket
|
|
self.addr = addr
|
|
self.addr = addr
|
|
self.server = server
|
|
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):
|
|
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):
|
|
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_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:
|
|
if log_msg:
|
|
- lschat.info("server:"+log_msg)
|
|
|
|
|
|
+ lschat.info("server:"+str(log_msg))
|
|
else:
|
|
else:
|
|
- lschat.info("Server:"+msg)
|
|
|
|
|
|
+ lschat.info("Server:"+str(data))
|
|
try:
|
|
try:
|
|
- await self.socket.send(msg_encoded)
|
|
|
|
|
|
+ await self.socket.send(data)
|
|
return True
|
|
return True
|
|
except Exception as e:
|
|
except Exception as e:
|
|
lserver.error(e, exc_info=True)
|
|
lserver.error(e, exc_info=True)
|
|
return False
|
|
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:
|
|
try:
|
|
await self.socket.shutdown(0)
|
|
await self.socket.shutdown(0)
|
|
except:
|
|
except:
|
|
@@ -85,18 +136,53 @@ class ConnHandlerBase(object):
|
|
except:
|
|
except:
|
|
lserver.debug("error closing socket")
|
|
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):
|
|
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):
|
|
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)
|
|
h.send(data)
|
|
|
|
|
|
class Server(object):
|
|
class Server(object):
|