def newuser_notif(name): #------------------------- broadcasting for each online user ----------------------------- #if len(Global.list_user) != 0: for user in Global.list_user: if user.name != name: # not broadcasting the message to himself message = Global.message("System(broadcast)", user.name, "\"" + name + "\"" + " has just logged in.") Global.message_rep[user.name].append(message) Global.event[user.name].set() disp = "New user \"" + name + "\" logging in notification has been sent!" print disp Global.log.write(disp + "\n") return
def levuser_notif(name): # don't disclass different ways to leave for the clients #------------------------- broadcasting for each online user ----------------------------- #if len(Global.list_user) != 0: for user in Global.list_user: if user.name != name: # not broadcasting the message to himself message = Global.message("System(broadcast)", user.name, "\"" + name + "\"" + " has just logged out.") Global.message_rep[user.name].append(message) Global.event[user.name].set() disp = "User \"" + name + "\" logging out notification has been sent!" print disp Global.log.write(disp + "\n") return
def server_stop_notif(): # just like a broadcast thread, to notify every connected clients to leave for user in Global.list_user: message = Global.message("System", user.name, "serverstop") Global.message_rep[user.name].append(message) Global.event[user.name].set() disp = "The server_stop notification has been sent to all the online clients, and they will automatically log out right now." print disp Global.log.write(disp + "\n") #------------ we should do the database backup task right here ------------ Global.save_para(Global.MaxCon, Global.BLOCK_TIME, Global.LAST_HOUR, Global.TIME_OUT) disp = "[backup]MaxCon, BLOCK_TIME, LAST_HOUR, TIME_OUT all have been stored." print disp Global.log.write(disp + "\n") Global.save_u_p() disp = "[backup]user_password repository has been stored." print disp Global.log.write(disp + "\n") Global.save_message_rep() disp = "[backup]message_rep has been stored." print disp Global.log.write(disp + "\n") Global.save_file_rep() disp = "[backup]file_rep has been stored." print disp Global.log.write(disp + "\n") Global.save_block_rep() disp = "[backup]block_rep has been stored." print disp Global.log.write(disp + "\n") Global.save_list_block() disp = "[backup]list_block has been stored." print disp Global.log.write(disp + "\n") #---------------------------- backup done --------------------------------- return
def server_receiver(connect, ad, name, user): #----------------------- the main command part ----------------------- while True: #====================================== (data, quit) = check_input(connect, ad) Global.list_lastop[name] = time.time() # very important here!!! if quit: if data != "serverstop": # add a new feature: new user logging out notification levuser_notif(name) # only when the user has actually logged in, this operation can be used when he log out #------------- let his personal sending thread to terminate ---------------- message = Global.message("System", name, "logout") Global.message_rep[name].append(message) Global.event[name].set() break #====================================== data = data.split(" ") # even one word can form a ["xxx"] format reply = "You have chosen the following commands: " + data[0] + "\n" if data[0] not in Global.command: response = "But the command is not supported, please enter a supported command!\n" reply = reply + response + name + ">>" try: connect.sendall(reply) except: disp1 = "Some errors happened in the client side, because the host can't receive the data normally!" + "\n" disp2 = "Maybe the user directly close the running terminal windows!\n" disp3 = "This server-client interaction thread will terminate right now!" + "\n" disp4 = 'Disconnected with ' + ad[0] + ':' + str(ad[1]) + ' because some errors happened in the client side.' disp = disp1 + disp2 + disp3 + disp4 print disp print "here we go!!!" Global.log.write(disp + "\n") levuser_notif(name) # only when the user has actually logged in, this operation can be used when he log out #------------- let his personal sending thread to terminate ---------------- message = Global.message("System", name, "logout") Global.message_rep[name].append(message) Global.event[name].set() break disp = "User \"" + name + "\" has performed a command of \"" + data[0] + "\" on " + ad[0] + ':' + str(ad[1]) + " but this is not supported." print disp Global.log.write(disp + "\n") else: # supported command, operation should be performed Server_command.command_res(connect, data, name, ad) #---------------------- client-server interaction done, leaving now ------------------------ disp = 'Server finished communication with ' + name + '. Disconnected with ' + ad[0] + ':' + str(ad[1]) print disp Global.log.write(disp + "\n") # TODO when the server is stopping, there will be a huge data concurrency (actually not that huge). we should think about it connect.close() Global.list_user.remove(user) Global.lock_con.acquire() Global.con -= 1 Global.lock_con.release() Global.lasthr_rep[name]=time.time() # default value is None #DEBUG print "The present active users list:" print Global.list_user return
def command_res(connect, data, name, ad): #supported commands: "whoelse", "wholasthr", "broadcast", "message", "block", "unblock", "logout" if data[0] == "whoelse": # I don't check the format of this command, because other words will be dropped. reply="The other users are:\n" N = 0 for user in Global.list_user: if user.name != name: reply = reply + user.name + "\n" N += 1 if N == 0: reply = reply + "There are no other users." reply=reply.strip() connect.sendall(reply + "\n") connect.sendall(str_op_done(data[0], name)) disp = str_op_done_sys(data[0], name, ad) print disp Global.log.write(disp + "\n") return if data[0] == "message": #----------- preparing the data as "message" command format, and check the format at the same time ------------- if len(data) >1: t1=data[0] # temporary command t2=data[1] # temporary receiver del data[0:2] t3="" # temporary content for i in data: t3=t3+i+" " t3=t3.strip() if t3 == "": data = [t1, t2] connect.sendall(str_check_format_con("message <user> <message>", data[0], name)) return else: data = [t1, t2, t3] else: connect.sendall(str_check_format_con("message <user> <message>", data[0], name)) return #----------- check self message which should be avoided ------------- if data[1] == name: connect.sendall("You should not send messages to yourself. Please try another one.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #----------- check whether the targetting user exists ------------- if data[1] not in Global.u_p: connect.sendall("You surely keep the format of \"message\" command, but we can't find the targetting <user> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #------------------------- block check ----------------------------- if data[1] in Global.block_rep[name]: connect.sendall("You cannot send any message to " + data[1] + ". You have been blocked by the user.\nPlease try another one to send message!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return message = Global.message(name + "(private)", data[1], data[2]) Global.message_rep[data[1]].append(message) #------------------------- check whether the targetting user is online or not ----------------------------- bol=False for user in Global.list_user: if user.name == data[1]: bol = True break if bol: Global.event[data[1]].set() #connect.sendall("\n") connect.sendall(str_op_done(data[0], name)) disp1 = str_op_done_sys(data[0], name, ad) + "\n" disp2 = "The receiver is \"" + data[1] + "\" and the content is \"" + data[2] + "\" and the sender's ip is " + ad[0] + ':' + str(ad[1]) + "." disp =disp1 + disp2 print disp Global.log.write(disp + "\n") return else: #connect.sendall("\n") connect.sendall("The user \"" + data[1] + "\" is unfortunately not online. But the server has stored your message.\n") connect.sendall(str_op_done("off-line "+data[0], name)) disp1 = str_op_done_sys("off-line " + data[0], name, ad) + "\n" disp2 = "The receiver is \"" + data[1] + "\" and the content is \"" + data[2] + "\" and the sender's ip is " + ad[0] + ':' + str(ad[1]) + "." disp = disp1 + disp2 print disp Global.log.write(disp + "\n") return if data[0] == "wholasthr": l=[] for user in Global.list_user: if user.name != name: l.append(user.name) for user in Global.lasthr_rep: if Global.lasthr_rep[user] != None: if user not in l: if time.time() - Global.lasthr_rep[user] < Global.LAST_HOUR: l.append(user) s='\n'.join(l) reply="The wholasthr users are:\n" + s connect.sendall(reply + "\n") connect.sendall(str_op_done(data[0], name)) disp = str_op_done_sys(data[0], name, ad) print disp Global.log.write(disp + "\n") return if data[0] == "broadcast": # TODO we don't do the block check for the broadcasting #----------- preparing the data as "broadcast" command format, and check the format at the same time ------------- if len(data) >1: t1=data[0] # temporary command del data[0:1] t2="" # temporary content for i in data: t2=t2+i+" " t2=t2.strip() if t2=="": connect.sendall(str_check_format_con("broadcast <message>", data[0], name)) return else: data = [t1, t2] else: connect.sendall(str_check_format_con("broadcast <message>", data[0], name)) return #------------------------- broadcasting for each online user ----------------------------- for user in Global.u_p: message = Global.message(name+"(broadcast)", user, data[1]) Global.message_rep[user].append(message) bol=False # check whether that user is online or not for user_obj in Global.list_user: if user_obj.name == user: bol = True break if bol: # online users Global.event[user].set() disp1 = str_op_done_sys(data[0], name, ad) + "\n" disp2 = "The Content is \"" + data[1] + "\" and the sender's ip is " + ad[0] + ':' + str(ad[1]) + "." disp = disp1 + disp2 print disp Global.log.write(disp + "\n") return if data[0] == "block": #----------- preparing the data as "block" command format, and check the format at the same time ------------- if len(data) != 2: connect.sendall(str_check_format_con("block <user>", data[0], name)) return #----------- check whether the targetting user exists ------------- if data[1] not in Global.u_p: connect.sendall("You surely keep the format of \"block\" command, but we can't find the targetting <user> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #----------- self-block check --------------- if data[1] == name: connect.sendall("Error! You cannot block yourself! Please try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #----------- second-block check --------------- if name in Global.block_rep[data[1]]: connect.sendall("You have blocked this guy. Why do you block again? Please try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return Global.block_rep[data[1]].append(name) connect.sendall("You have successfully blocked " + data[1] + " from sending you messages.\n") connect.sendall(str_op_done(data[0], name)) disp1 = str_op_done_sys(data[0], name, ad) + "\n" disp2 = "He has successfully blocked \"" + data[1] + "\"." disp = disp1 + disp2 print disp Global.log.write(disp + "\n") return if data[0] == "unblock": #----------- preparing the data as "unblock" command format, and check the format at the same time ------------- if len(data) != 2: connect.sendall(str_check_format_con("block <user>", data[0], name)) return #----------- check whether the targetting user exists ------------- if data[1] not in Global.u_p: connect.sendall("You surely keep the format of \"block\" command, but we can't find the targetting <user> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return if data[1] == name: connect.sendall("You surely keep the format of \"block\" command, but as you can't block yourself, there is no probability that you can unblock yourself!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #---------- check whether the target has been blocked ------------- if name not in Global.block_rep[data[1]]: connect.sendall("You try to unblock an unblocked object. Please make another meaningful try." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return Global.block_rep[data[1]].remove(name) connect.sendall("You have successfully unblocked " + data[1] + "\n") connect.sendall(str_op_done(data[0], name)) disp1 = str_op_done_sys(data[0], name, ad) + "\n" disp2 = "He has successfully unblocked " + data[1] + "." disp =disp1 + disp2 print disp Global.log.write(disp + "\n") return if data[0] == "file": #----------- preparing the data as "message" command format, and check the format at the same time ------------- if len(data) >1: t1=data[0] # temporary command t2=data[1] # temporary receiver del data[0:2] t3="" # temporary content for i in data: t3=t3+i+" " t3=t3.strip() if t3 == "": data = [t1, t2] connect.sendall(str_check_format_con("file <receiver> <filename>", data[0], name)) return else: data = [t1, t2, t3] else: connect.sendall(str_check_format_con("file <receiver> <filename>", data[0], name)) return #----------- check whether the targetting user exists ------------- if data[1] not in Global.u_p: connect.sendall("You surely keep the format of \"message\" command, but we can't find the targetting <user> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #------------------------- block check ----------------------------- if data[1] in Global.block_rep[name]: connect.sendall("You have been blocked by this user! I'm sorry but please try another one!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return if (name, data[2].strip()) not in Global.file_rep[data[1]]: Global.file_rep[data[1]].append((name, data[2])) #DEBUG #print data[1]+data[2] connect.sendall("filetransfer " + name + " " + data[1] + " " + data[2]) # filetransfer sender receiver filename disp1 = "The system has received the file transfer request from " + data[0] + "\n" disp2 = "The receiver is \"" + data[1] + "\" and the filename is \"" + data[2] + "\" and the sender's ip is " + ad[0] + ':' + str(ad[1]) + "." disp =disp1 + disp2 print disp Global.log.write(disp + "\n") return if data[0] == "filetransferdec": # the client can't find that file Global.file_rep[data[2]].remove((data[1], data[3])) #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") connect.sendall(name + ">>") disp = "The client can't find that file. He may try again." print disp Global.log.write(disp + "\n") return if data[0] == "filetransfer": # TODO remember to block the server sender thread (I tried it and found that there is no need actually) disp = "Now user \"%s\" begins to transfer \"%s\" to user \"%s\"" %(data[1], data[3], data[2]) print disp Global.log.write(disp + "\n") #--------- predir = os.getcwd() f = open(predir + '/' + data[1] + "_" + data[2] + "_" + data[3], 'wb') # b means binary method write connect.send('ready') while True: dat = connect.recv(4096) if dat == 'EOF': disp = "server receive file success!" print disp Global.log.write(disp + "\n") break f.write(dat) f.close() #--------- disp = "Now user \"%s\" has succeeded to transfer \"%s\" to user \"%s\"" %(data[1], data[3], data[2]) print disp Global.log.write(disp + "\n") connect.sendall("file \"" + data[3] + "\" has been successfully received by the server." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") message = Global.message(data[1] + "(file_transfer)", data[2], data[3]) Global.message_rep[data[2]].append(message) #------------------------- check whether the targetting user is online or not ----------------------------- bol=False for user in Global.list_user: if user.name == data[2]: bol = True break if bol: Global.event[data[2]].set() return if data[0] == "fileget": #----------- preparing the data as "message" command format, and check the format at the same time ------------- if len(data) >1: t1=data[0] # temporary command t2=data[1] # temporary receiver del data[0:2] t3="" # temporary content for i in data: t3=t3+i+" " t3=t3.strip() if t3 == "": data = [t1, t2] connect.sendall(str_check_format_con("fileget <source> <filename>", data[0], name)) return else: data = [t1, t2, t3] else: result = "" for t in Global.file_rep[name]: result = result + "File \"%s\" from \"%s\"." %(t[1],t[0]) + "\n" if len(Global.file_rep[name]) == 0: connect.sendall("No files for you. Please continue.\n" + name + ">>") disp = "Successfully perform the \"fileget\" operation." print disp Global.log.write(disp + "\n") return result = result + name + ">>" connect.sendall(result) disp = "Successfully perform the \"fileget\" operation." print disp Global.log.write(disp + "\n") return #----------- check whether the targetting source exists ------------- if data[1] not in Global.u_p: connect.sendall("You surely keep the format of \"fileget\" command, but we can't find the targetting <source> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #----------- check whether the targetting file exists ------------- if (data[1], data[2]) not in Global.file_rep[name]: connect.sendall("You surely keep the format of \"fileget\" command, but we can't find the targetting <filename> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return # TODO check whether the file exists; this kind of thing should not happen here!! are you joking?! we are the server builder!! # TODO blocking another event signal (must) Global.lock[name].acquire() disp = "starting send file!" print disp Global.log.write(disp + "\n") connect.send("file_ready " + data[1] + " " + data[2]) # the ready to send signal for the client time.sleep(1) predir = os.getcwd() f = open(predir + '/' + data[1] + "_" + name + "_" + data[2], 'rb') # b means binary method write reply = connect.recv(1024) if reply == "ready": while True: dat = f.read(4096) if not dat: break connect.send(dat) f.close() time.sleep(1) connect.sendall('EOF') disp = "send file success!" print disp Global.log.write(disp + "\n") Global.file_rep[name].remove((data[1], data[2])) #----------------- remove the stored file in the server ------------------- predir = os.getcwd() try: os.remove(predir+'/' + data[1] + "_" + name + "_" + data[2]) except: disp = "Some errors happen during the file deletion process." print disp Global.log.write(disp + "\n") connect.sendall("Some errors happen during the file deletion process.") return connect.sendall(name + ">>") # TODO the just unblocked lock will send message and there will not be "\n", like: Columbia>>Google(private): try~ Global.lock[name].release() #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return else: disp = "The client doesn't give a ready to receive signal!" print disp Global.log.write(disp + "\n") Global.lock[name].release() return if data[0] == "filedecline": #----------- preparing the data as "message" command format, and check the format at the same time ------------- if len(data) >1: t1=data[0] # temporary command t2=data[1] # temporary receiver del data[0:2] t3="" # temporary content for i in data: t3=t3+i+" " t3=t3.strip() if t3 == "": data = [t1, t2] connect.sendall(str_check_format_con("filedecline <source> <filename>", data[0], name)) return else: data = [t1, t2, t3] else: connect.sendall(str_check_format_con("filedecline <source> <filename>", data[0], name)) return #----------- check whether the targetting source exists ------------- if data[1] not in Global.u_p: connect.sendall("You surely keep the format of \"filedecline\" command, but we can't find the targetting <source> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return #----------- check whether the targetting file exists ------------- if (data[1], data[2]) not in Global.file_rep[name]: connect.sendall("You surely keep the format of \"filedecline\" command, but we can't find the targetting <filename> in our database. You should try again!.." + "\n" + name + ">>") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return Global.file_rep[name].remove((data[1], data[2])) predir = os.getcwd() try: os.remove(predir+'/' + data[1] + "_" + name + "_" + data[2]) except: disp = "Some errors happen during the file deletion process." print disp Global.log.write(disp + "\n") connect.sendall("Some errors happen during the file deletion process.") return connect.sendall("Successfully perform the \"filedecline\" operation for you. Delete \"" + data[2] + "\" from \"" + data[1] + "\"." + "\n" + name + ">>") disp = "Successfully perform the \"filedecline\" operation for user %s. Delete \"%s\" from \"%s\"." %(name,data[2],data[1]) print disp Global.log.write(disp + "\n") #connect.sendall("Please continue with the following commands: " + "\n" + Global.CONNECT.strip() + "\n" + name + ">>") return