From 16a17a9ada40e2ea09c58287868339dd36de2184 Mon Sep 17 00:00:00 2001 From: sidya82 Date: Tue, 31 Mar 2015 11:53:24 +0200 Subject: [PATCH] Poulet --- serveur/Log.py | 100 +++++++++++++++++++++++++++++++ serveur/Server.py | 150 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 224 insertions(+), 26 deletions(-) create mode 100644 serveur/Log.py diff --git a/serveur/Log.py b/serveur/Log.py new file mode 100644 index 0000000..39cd80b --- /dev/null +++ b/serveur/Log.py @@ -0,0 +1,100 @@ +""" + Module : Log + (Realisé dans le cadre du Projet Tuteuré 2013/2014 MI Blagnac) +""" + +import logging +from logging.handlers import RotatingFileHandler + + +class bcolors: + """ + Define constant color value for different level + """ + DEBUG = '\033[94m ' + INFO = ' \033[95m ' + WARNING = ' \033[93m ' + FAIL = ' \033[91m ' + ENDC = ' \033[0m ' + + +class lvl: + """ + Define constant value for level utils + """ + NOTSET = 0 + DEBUG = 10 + INFO = 20 + WARNING = 30 + FAIL = 40 + CRITICAL = 50 + + +class SingleLevelFilter(logging.Filter): + """Filter for one level""" + + def __init__(self, passlevel, reject): + """ + Constructor + passlevel : level to filter + reject : true on reject state + """ + self.passlevel = passlevel + self.reject = reject + + def filter(self, record): + if self.reject: + return (record.levelno != self.passlevel) + else: + return (record.levelno == self.passlevel) + + +class Log(object): + """ + Log Manager + """ + + def __init__(self): + """ + Define 3 differents utils : + activity.log -> all activity + warning.log -> only warning + error.log -> error + Write all message on terminal too + """ + self.logger = logging.getLogger() + self.logger.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(asctime)-15s :: %(levelname)s :: %(message)s') + file_handler = RotatingFileHandler('log/activity.log', 'a', 1000000, 1) + file_handler.setLevel(logging.DEBUG) + file_handler.setFormatter(formatter) + self.logger.addHandler(file_handler) + file_handler_warning = RotatingFileHandler('log/warning.log', 'a', 1000000, 1) + f1 = SingleLevelFilter(logging.WARNING, False) + file_handler_warning.addFilter(f1) + file_handler_warning.setFormatter(formatter) + self.logger.addHandler(file_handler_warning) + file_handler_error = RotatingFileHandler('log/error.log', 'a', 1000000, 1) + file_handler_error.setLevel(logging.ERROR) + file_handler_error.setFormatter(formatter) + self.logger.addHandler(file_handler_error) + steam_handler = logging.StreamHandler() + steam_handler.setLevel(logging.NOTSET) + self.logger.addHandler(steam_handler) + + + def printL(self, pMsg, pLvl): + """ + Add color and write in log with an define level + pMsg : message to write in log + pLvl : level of log message + """ + if pLvl == lvl.DEBUG: + pMsg = bcolors.DEBUG + str(pMsg) + bcolors.ENDC + elif pLvl == lvl.INFO: + pMsg = bcolors.INFO + str(pMsg) + bcolors.ENDC + elif pLvl == lvl.WARNING: + pMsg = bcolors.WARNING + str(pMsg) + bcolors.ENDC + elif pLvl == lvl.FAIL: + pMsg = bcolors.FAIL + str(pMsg) + bcolors.ENDC + self.logger.log(pLvl, pMsg) \ No newline at end of file diff --git a/serveur/Server.py b/serveur/Server.py index c04ca3c..e19682e 100644 --- a/serveur/Server.py +++ b/serveur/Server.py @@ -1,7 +1,6 @@ import argparse import socket import threading -import re import sys from serveur import Log @@ -12,8 +11,8 @@ def handleConnection(connection, client_address) : while True: data = connection.recv(4096) if data: - log.printL("Request from IP -> {} \n" - "{}".format(client_address,data.decode()), Log.lvl.INFO) + log.printL("Request from IP -> {}" + " {}".format(client_address,data.decode()), Log.lvl.INFO) threading.Thread(target=handleRequest, args=(connection, data.decode())).start() else: break @@ -22,62 +21,163 @@ def handleConnection(connection, client_address) : def handleRequest(connection, data): - arrayData = data.split(" ") - if(not arrayData[0][0] == "/"): - broadcastMsg( "NEW_MSG {} {} ".format(usersConnected[connection][1], data)) - return - else : - if arrayData[0] == "/name" : - changeName(connection, arrayData[1]) + try: + arrayData = data.split(" ") + if(not arrayData[0][0] == "/"): + broadcastMsg( "NEW_MSG {} {} ".format(usersConnected[connection][1], data)) return - if arrayData[0] == "/quit" : - quit(connection) - return - connection.send("ERR_COMMAND_NOT_FOUND".encode()) + else : + if arrayData[0] == "/name" : + changeName(connection, arrayData[1]) + return + if arrayData[0] == "/quit" : + quit(connection) + return + if arrayData[0] == "/askpm" : + askPrivateMsg(connection,arrayData[1]) + return + if arrayData[0] == "/acceptpm" : + acceptPrivateMsg(connection,arrayData[1]) + return + if arrayData[0] == "/rejectpm" : + rejectPrivateMsg(connection,arrayData[1]) + return + if arrayData[0] == "/pm" : + privateMsg(connection,arrayData[1],arrayData[2:]) + return + connection.send("ERR_COMMAND_NOT_FOUND".encode()) + except Exception as e : + log.printL(str(e), Log.lvl.FAIL) -def broadcastMsg(message) : - for con, value in usersConnected.items() : - con.send(message.encode()) +def broadcastMsg(message): + sock.sendall(message.encode()) -def changeName(connection, pseudo) : +def userListActive(connection): + l = "USERLIST " + for con,value in usersConnected : + if value[2] == True : + l += value[1] + " " + connection.send(l[:-1].encode()) + + +def userListAway(connection): + l = "USERAWAY " + for con,value in usersConnected : + if value[2] == False : + l += value[1] + " " + connection.send(l[:-1].encode()) + + +def changeName(connection, pseudo): broadcastMsg("NAME_CHANGED {} {}".format(usersConnected[connection][1], pseudo)) usersConnected[connection][1] = pseudo +def askPrivateMsg(connection,pseudo): + c = getConnectionByPseudo(pseudo) + if c is None : + connection.send("ERR_USER_NOT_FOUND".encode()) + else: + pm = (connection,c) + if pm in askPM : + connection.send("ALREADY_ASKED".encode()) + else: + askPM.append(pm) + c.send("NEW_MESSAGE {0} demande une conversation privé \n" + "/acceptpm {0} pour accepter\n" + "/reject {0} pour refuser".format(pseudo)) + connection.send("SUCC_INVITED".encode()) + + +def acceptPrivateMsg(connection, pseudo): + c = getConnectionByPseudo(pseudo) + if c is None : + connection.send("ERR_USER_NOT_FOUND".encode()) + else: + pm = (connection,c) + if pm not in askPM : + connection.send("ERR_USER_HAS_NOT_ASK".encode()) + else: + askPM.remove(pm) + validatePM.append(pm) + connection.send("SUCC_PRIVATE_DISCUSSION_ACCEPTED".encode()) + + +def rejectPrivateMsg(connection, pseudo): + c = getConnectionByPseudo(pseudo) + if c is None : + connection.send("ERR_USER_NOT_FOUND".encode()) + else: + pm = (connection,c) + if pm not in askPM : + connection.send("ERR_USER_HAS_NOT_ASK".encode()) + else: + askPM.remove(pm) + connection.send("SUCC_PRIVATE_DISCUSSION_REFUSED".encode()) + + +def privateMsg(connection, pseudo, msg): + c = getConnectionByPseudo(pseudo) + if c is None : + connection.send("ERR_DEST_NOT_FOUND".encode()) + else: + pm = (connection,c) + if sorted(pm) not in sorted(validatePM) : + connection.send("ERR_NOT_ACCEPTED".encode()) + else: + c.send("NEW_PM {} {}".format(pseudo,msg).encode()) + connection.send("SUCC_PM_SENDED".encode()) + + def quit(connection) : broadcastMsg("HAS_LEFT {}".format(usersConnected[connection][1])) + connection.send("SUCCESSFUL_LOGOUT".encode()) connection.close() usersConnected.__delitem__(connection) log.printL("Disconnection from IP -> {}".format(usersConnected[connection][0]), Log.lvl.INFO) + +def getConnectionByPseudo(pseudo): + for con, value in usersConnected.items() : + if value[1] == pseudo : + return con + return None + + def main(): #Global vars - global usersConnected, log + global usersConnected, log, sock usersConnected = {} + global askPM, validatePM + global askFT, validateFT + askPM = [] + validatePM = [] log = Log.Log() - log.printL("Server start", Log.lvl.INFO) #Configuration parser = argparse.ArgumentParser(usage="usage='%(prog)s [options]",description='Server DNC') parser.add_argument('--port', type=int, dest='port', action='store', default=8000, help='port (default=8000)') + parser.add_argument('--usermax', type=int, dest='usermax', action='store', + default=None, help='usermax (default=None)') args = parser.parse_args() log.printL("Configuration load {}".format(args), Log.lvl.INFO) + log.printL("Server start", Log.lvl.INFO) #Init socket serv sock = socket.socket() sock.bind(("", args.port)) sock.listen(5) - log.printL("Server Listen on port {} ".format(args.port), Log.lvl.INFO) + log.printL("Server Listen on port {}".format(args.port), Log.lvl.INFO) try : while True : #Connection client connection, client_address = sock.accept() - usersConnected[connection] = [client_address,"Anonymous"] + usersConnected[connection] = [client_address,"Anonymous",True] # ip pseudo status threading.Thread(target=handleConnection,args=(connection,client_address)).start() except KeyboardInterrupt : # Disable to received more requests on socket @@ -91,10 +191,8 @@ def main(): t.join() #Close all clients sockets for con, value in usersConnected.items(): - con.close() - log.printL("Disconnection IP -> {}".format(value[0]), Log.lvl.INFO) - #Close the sockets server - log.printL("Sockets close", Log.lvl.INFO) + quit(con) + #Close the socket server sock.close() log.printL("Server shutdown", Log.lvl.INFO) sys.exit(0)