import sqlalchemy import SocketServer, socket, select import struct from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker engine = create_engine('sqlite:///t.sqlite', echo = True) Base = declarative_base() Session = sessionmaker(bind=engine) class PiztorError(Exception): def __init__(self, msg): self.err_msg = msg def __str__(self, msg): return self.err_msg class ConnectionError(PiztorError): pass class ReqReadError(ConnectionError): def __init__(self): super(ReqReadError, self).__init__("Error while reading request") class ReqInvalidError(ConnectionError): def __init__(self): super(ReqInvalidError, self).__init__("Invalid request") class TokenInvalidError(ConnectionError): def __init__(self): super(ReqInvalidError, self).__init__("Invalid token") class DataManager(object): pass class UserManager(DataManager): class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key = True) username = Column(String) password = Column(String) def get_uid_by_token(self, token): try: return self.active_sessions[token] except: raise TokenInvalidError() def __init__(self): Base.metadata.create_all(engine) self.active_sessions = dict() def authentication_handle(self, opt_type, data, srv): print "Parsing User Data" pos = -1 for i in xrange(0, len(data)): if data[i] == '\0': print i if pos != -1: raise ReqInvalidError() pos = i break if pos == -1: raise ReqInvalidError() username = data[0:pos] password = data[pos + 1:] print "Trying to login with following info:" print (username, password) session = Session() q = session.query(User).filter(User.username == username) entry = q.first() if entry.password != password: # Auth failed return struct.pack("!BL" return struct.pack("!BL", 0, 1234) class MesgManager(DataManager): def mesg_sending_handle(self, opt_type, data, srv): print "Parsing Mesg Data" try: if len(data) < 8: raise ReqInvalidError() sender_token, recv_id = struct.unpack("!LL", data[:8]) msg = data[8:] print (sender_token, recv_id, msg) return struct.pack("!B", 1) except struct.error: raise ReqInvalidError() class LocationManager(DataManager): def location_update_handle(self, opt_type, data, srv): print "Parsing Loc Data" try: if len(data) < 8: raise ReqInvalidError() sender_token, lat, lont = struct.unpack("!Ldd", data) print (sender_token, lat, lont) return struct.pack("!B", 2) except struct.error: raise ReqInvalidError() class PiztorServer(): user_mgr = UserManager() mesg_mgr = MesgManager() location_mgr = LocationManager() mgr_map = [ user_mgr.authentication_handle, mesg_mgr.mesg_sending_handle, location_mgr.location_update_handle ] class GenericHandler(SocketServer.StreamRequestHandler): def handle(self): sock = self.request sock.setblocking(0) data = "" while True: ready = select.select([sock], [], [], 1) if not ready[0]: raise ReqReadError() buff = sock.recv(4096) if len(buff) == 0: break # terminated else: data += buff sock.shutdown(socket.SHUT_RD) print "Got the data:" print data print "====" if len(data) < 1: raise ReqInvalidError() opt_id = struct.unpack("!B", data[0])[0] reply = PiztorServer.mgr_map[opt_id](opt_id, data[1:], self) sock.sendall(reply) sock.close() def __init__(self, host, port): srv = SocketServer.TCPServer((host, port), PiztorServer.GenericHandler) srv.timeout = 2 self.server = srv def run(self): try: self.server.serve_forever() except KeyboardInterrupt: print "Exiting..." self.server.shutdown() print "Server shutdown" if __name__ == "__main__": ps = PiztorServer("localhost", 9999) ps.run()