#!/usr/bin/env python import socket import sys import re import select _linesep_regexp = re.compile("\r?\n") users = {} # users[alice] = (alice, secret) conns = [] # conns[i] = [sock, addr, buf, user, authenticated] def disconnect(conn, msg): global conns print "disconnect ", repr(conn), repr(msg) conns = filter(lambda x: x != conn, conns) def process_conn_data(conn): global conns, users print "conns ", repr(conns) print "users ", repr(users) try: new_data = conn[0].recv(2**14) except socket.error, x: # The server hung up. disconnect(conn, "Connection reset by peer") return if not new_data: # Read nothing: connection must be down. disconnect(conn, "Connection reset by peer") return lines = _linesep_regexp.split(conn[2] + new_data) # Save the last, unfinished line. conn[2] = lines[-1] lines = lines[:-1] for line in lines: # print "FROM SERVER:", line if not line: continue words = line.split(" ") if words[0] == "USER": if conn[3] != None: conn[0].send("503 Already logged in\n") else: conn[3] = words[1] elif words[0] == "PASS": if conn[4] == True: conn[0].send("504 Already authenticated\n") else: if conn[3] not in users: users[conn[3]] = (conn[3], words[1]) if conn[3] in map(lambda x: x[3], filter(lambda y: y[4] == True, conns)): conn[0].send("506 Authenticated using another connection\n") elif users[conn[3]][1] == words[1]: conn[4] = True else: conn[0].send("505 Wrong password\n") elif words[0] == "PING": conn[0].send("PONG " + " ".join(words[1:]) + "\n") elif conn[4] == False: conn[0].send("506 Not authenticated\n") elif words[0] == "MSG": if words[1] not in users: conn[0].send("507 Unknown user\n") elif words[1] not in map(lambda x: x[3], filter(lambda y: y[4] == True, conns)): conn[0].send("508 User offline\n") else: for c in conns: if words[1] == c[3]: c[0].send("100 " + conn[3] + " " + " ".join(words[2:]) + "\n") def main(): global conns sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('', 8080)) sock.listen(5) while True: sockets = map(lambda x: x[0], conns) sockets = filter(lambda x: x != None, sockets) sockets += [sock] (i, o, e) = select.select(sockets, [], [], None) for s in i: if s == sock: conn, addr = sock.accept() conns += [[conn, addr, "", None, False]] else: for c in conns: if s == c[0]: process_conn_data(c) main()