import asyncore import socket import sys everyone = {} class ConnectionHandler(asyncore.dispatcher): def __init__(self, sock): asyncore.dispatcher.__init__(self, sock) self.name = "" self.state = 0 # 0: waiting for name; 1: connected; 2: closed self.readBuffer = "" self.writeBuffer = "" def handle_read(self): self.readBuffer = self.readBuffer + self.recv(4196) while True: i = self.readBuffer.find("\r\n") if i >= 0: [line, self.readBuffer] = self.readBuffer.split("\r\n", 1) self.doCommand(line) else: break def handle_write(self): n = self.send(self.writeBuffer) self.writeBuffer = self.writeBuffer[n:] def writable(self): return len(self.writeBuffer) > 0 def readable(self): return self.state < 2 def handle_close(self): if self.name in everyone: del everyone[self.name] for who in everyone: everyone[who].respond("disconnect "+self.name) self.state = 2 self.close() def respond(self, msg): self.writeBuffer = self.writeBuffer + msg + "\r\n" def invalid(self, msg): self.respond("Invalid command: '"+msg+"'") def sendMessage(self, who, msg): if self.state == 1: self.respond("FROM "+who+" "+msg) def doCommand(self, line): if self.state == 0: # not yet connected? if line.count(" ") < 1: self.invalid(line) return [cmd, arg] = line.split(" ", 1) if cmd == "login" and arg.count(" ") == 0: self.name = arg for who in everyone: everyone[who].respond("connect "+arg) everyone[arg] = self self.state = 1 self.respond("login ok") else: self.invalid("You must log in with a name without spaces") elif self.state == 1: # already connected parts = line.split(" ", 1) cmd = parts[0] if len(parts) > 1: rest = parts[1] if cmd == "message": [who, message] = rest.split(" ", 1) if who in everyone: everyone[who].sendMessage(self.name, message) self.respond("message ok") elif cmd == "broadcast": for who in everyone: everyone[who].sendMessage(self.name, rest) self.respond("broadcast ok") elif cmd == "who": arr = [] for who in everyone: arr.append(who) self.respond("who "+",".join(arr)) else: self.invalid(line) else: self.invalid("bad state? "+str(self.state)) class Listener(asyncore.dispatcher): def __init__(self, port): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.bind(("0.0.0.0", port)) self.listen(1) def handle_accept(self): c = self.accept() ConnectionHandler(c[0]) def main(): port = int(sys.argv[1]) server = Listener(port) print "listening on", port try: asyncore.loop() except KeyboardInterrupt: print "finishing" server.close() if __name__ == "__main__": main()