Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import select
- import socket
- import pickle
- import re
- TCP_IP = ''
- TCP_PORT = 8080
- BUFFER_SIZE = 4096
- server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- server_socket.bind((TCP_IP, TCP_PORT))
- server_socket.listen(5)
- print("Listening on port %d" % TCP_PORT)
- # Dictionary of sockets to usernames, to stop multiple login
- # on a single account, etc
- socket_to_username = {}
- # users[username] = [socket, queue]
- # queue is a list of strings, a users messages
- users = {}
- # Create username `username` and assign it to `s`. Succeeds if `username` is
- # not already taken; returns a failure message otherwise. Rejects usernames
- # that are not alphanumeric or underscore.
- def create(s, username):
- if not re.match("^\w+$", username):
- # The username is invalid. Return failure.
- print("Username %s is invalid." % username)
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "USERNAME MUST BE ONE OR MORE ALPHANUMERICS OR UNDERSCORES"
- return response
- if username in users:
- # The username is already taken. Return failure.
- print("Username %s is already taken." % username)
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "NON UNIQUE USERNAME"
- return response
- else:
- # The username is valid. Add it to the list.
- print("Creating user %s." % username)
- users[username] = [0, []]
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = username
- return response
- # Logout socket `s` from account `username`. Returns a failure message
- # otherwise. Assumes that `s` is logged into account `username`.
- def logout(s, username=''):
- if not username and s in socket_to_username:
- username = socket_to_username[s]
- if s not in socket_to_username:
- return
- socket_to_username.pop(s)
- if username in users:
- users[username][0] = 0
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = username
- return response
- # Assign `username` to `s`. Succeeds if `username` exists and is not assigned
- # to another socket. Returns a failure message otherwise.
- def login(s, username):
- if s in socket_to_username:
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "LOGOUT FIRST"
- return response
- # Check that the username exists.
- if username in users:
- # Check that the username doesn't belong to someone else
- if users[username][0]:
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "USERNAME ALREADY LOGGED IN"
- return response
- socket_to_username[s] = username
- users[username][0] = s
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = username
- return response
- else:
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "UNKNOWN USERNAME"
- return response
- # Returns a list of usernames that satisfies regular expression `regex`.
- # Returns a failure message if the regular expression is bad.
- def grep(regex='.*'):
- try:
- ret = []
- for user in users.keys():
- if (re.match(regex, user)):
- ret.append(user)
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = ret
- return response
- except re.error:
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "INVALID REGEX"
- return response
- # Sends message `message` from `username` to `recipient`.
- def send(username, recipient, message):
- if recipient not in users:
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "UNKNOWN USERNAME"
- return response
- packet = {}
- packet["TYPE"] = "MESSAGE"
- packet["SENDER"] = username
- packet["MESSAGE"] = message
- if users[recipient][0]:
- # Recipient logged in; deliver immediately
- s = users[recipient][0]
- try:
- s.sendall(pickle.dumps(packet));
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = "USER LOGGED IN"
- return response
- except:
- # Message failed partway
- users[recipient][1].append(packet)
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = "USER NOT LOGGED IN"
- return response
- # Recipient not logged in
- users[recipient][1].append(packet)
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = "USER NOT LOGGED IN"
- return response
- # Deliver the contents of the message queue to `recipient`.
- def deliver(recipient):
- if recipient not in users:
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "UNKNOWN USERNAME"
- return response
- if users[recipient][0]:
- # Recipient logged in; deliver messages
- s = users[recipient][0]
- messages_sent = 0
- for i in range(len(users[recipient][1])):
- packet = users[recipient][1][messages_sent]
- try:
- s.sendall(pickle.dumps(packet));
- messages_sent += 1
- except:
- # Message failed partway
- break
- users[recipient][1] = users[recipient][1][messages_sent:]
- response = {}
- response["TYPE"] = "SUCCESS"
- response["MESSAGE"] = "DELIVERED USER " + str(messages_sent) + " MESSAGES"
- return response
- # Recipient not logged in
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "USER NOT LOGGED IN"
- return response
- # Delete user `to_delete`.
- def delete(to_delete):
- s = 0
- if (to_delete in users):
- s, _ = users.pop(to_delete)
- if s:
- print(s, socket_to_username[s])
- del socket_to_username[s]
- try:
- s.sendall(pickle.dumps({"TYPE": "ERROR", "MESSAGE": "YOUR ACCOUNT HAS BEEN DELETED"}))
- except:
- pass
- return {"TYPE": "SUCCESS", "MESSAGE": to_delete}
- else:
- return {"TYPE": "FAILURE", "MESSAGE": "UNKNOWN USERNAME"}
- # Handle a request from `s` for `request`.
- def handleRequest(s, request):
- if request["TYPE"] == "create":
- username = request["MESSAGE"]
- return create(s, username)
- if request["TYPE"] == "login":
- username = request["MESSAGE"]
- return login(s, username)
- if request["TYPE"] == "list":
- regex = request["MESSAGE"]
- return grep(regex)
- if s not in socket_to_username:
- # The user is not yet logged in
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "NOT LOGGED IN"
- return response
- username = socket_to_username[s]
- if request["TYPE"] == "logout":
- return logout(s, username)
- if request["TYPE"] == "send":
- recipient = request["RECIPIENT"]
- message = request["MESSAGE"]
- return send(username, recipient, message)
- if request["TYPE"] == "deliver":
- recipient = request["MESSAGE"]
- return deliver(recipient)
- if request["TYPE"] == "delete":
- to_delete = request["MESSAGE"]
- return delete(to_delete)
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = "COMMAND NOT FOUND"
- return response
- def sendError(s, message):
- try:
- response = {}
- response["TYPE"] = "FAILURE"
- response["MESSAGE"] = message
- s.sendall(pickle.dumps(response))
- except:
- pass
- read_list = [server_socket]
- while True:
- # This is how we avoid threading
- # It constantly looks to everything in readlist to read from
- readable, writable, errored = select.select(read_list, [], [])
- print(readable)
- for s in readable:
- # Somebody is trying to connect
- if s is server_socket:
- client_socket, address = server_socket.accept()
- read_list.append(client_socket)
- print("Connection from", address)
- else:
- data = s.recv(BUFFER_SIZE)
- if data:
- try:
- # Handle it and send to appropriate people
- request = pickle.loads(data)
- response = handleRequest(s, request)
- s.sendall(pickle.dumps(response))
- except Exception as e:
- print("Error encountered with %s." % data)
- print(e)
- sendError(s, "UNKNOWN ERROR")
- # They sent us a "I died" message
- else:
- s.close()
- logout(s)
- read_list.remove(s)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement