diff options
author | goblin911 <[email protected]> | 2013-08-25 21:16:45 +0800 |
---|---|---|
committer | goblin911 <[email protected]> | 2013-08-25 21:16:45 +0800 |
commit | 2efdc2f20f0306791ced5ec78a1acddfaf086f42 (patch) | |
tree | a85f2b32d6e6da9d7329ab975fea3bd79e1b94b6 /server | |
parent | e5599da7fdd344fdcb49e8d6780a1e2ad358ee2d (diff) | |
parent | 263967cbb477983ae8680b431c1d93f102971c30 (diff) |
Merge branch 'master' of https://github.com/Determinant/piztor
Conflicts:
client/Piztor/bin/classes/com/macaroon/piztor/ActMgr.class
client/Piztor/bin/classes/com/macaroon/piztor/AppMgr.class
client/Piztor/bin/classes/com/macaroon/piztor/R$drawable.class
client/Piztor/bin/classes/com/macaroon/piztor/R$id.class
client/Piztor/bin/classes/com/macaroon/piztor/R$layout.class
client/Piztor/bin/classes/com/macaroon/piztor/R$menu.class
client/Piztor/bin/classes/com/macaroon/piztor/R$string.class
client/Piztor/gen/com/macaroon/piztor/R.java
client/Piztor/res/values/strings.xml
client/bin/classes/com/macaroon/piztor/ActStatus.class
client/bin/classes/com/macaroon/piztor/EmptyStatus.class
client/bin/classes/com/macaroon/piztor/Setting.class
client/src/com/macaroon/piztor/AppMgr.java
client/src/com/macaroon/piztor/Setting.java
Diffstat (limited to 'server')
-rw-r--r-- | server/README.rst | 1 | ||||
-rw-r--r-- | server/client.py | 58 | ||||
-rw-r--r-- | server/piztor/exc.py | 5 | ||||
-rw-r--r-- | server/piztor/import.py | 7 | ||||
-rw-r--r-- | server/piztor/model.py | 6 | ||||
-rw-r--r-- | server/piztor/prob.py | 81 | ||||
-rw-r--r-- | server/piztor/ptp.rst | 135 | ||||
-rw-r--r-- | server/piztor/server.py | 321 | ||||
-rw-r--r-- | server/piztor_server.py | 234 | ||||
-rw-r--r-- | server/ptp.rst | 93 | ||||
-rw-r--r-- | server/rush.py | 14 |
11 files changed, 549 insertions, 406 deletions
diff --git a/server/README.rst b/server/README.rst deleted file mode 100644 index e88c745..0000000 --- a/server/README.rst +++ /dev/null @@ -1 +0,0 @@ -Here is the folder of server-side implementation diff --git a/server/client.py b/server/client.py deleted file mode 100644 index 15f4bbc..0000000 --- a/server/client.py +++ /dev/null @@ -1,58 +0,0 @@ -import socket -import sys -from struct import * -from random import random -from time import sleep - -def get_hex(data): - return "".join([hex(ord(c))[2:].zfill(2) for c in data]) - -HOST, PORT = "localhost", 9990 - -def gen_auth(username, password): - data = pack("!B", 0) - data += username - data += "\0" - data += password - return data - -def gen_update_location(token, lat, lont): - return pack("!BLdd", 2, token, lat, lont) - -def gen_request_location(token, gid): - return pack("!BLL", 3, token, gid) - -def send(data): - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((HOST, PORT)) -# print "Client " + str(sys.argv[1]) + ": connected" - sock.sendall(data) - print get_hex(data) -# print "Client " + str(sys.argv[1]) + ": sent" -# sock.shutdown(socket.SHUT_WR) -# print "Client " + str(sys.argv[1]) + ": shutdown" - received = sock.recv(1024) - finally: - print "adf" - sock.close() - - print "Sent {}".format(get_hex(data)) - print "Received: {}".format(get_hex(data)) - return received - -#print "Client spawned:" + str(sys.argv[1]) -rec = send(gen_auth("hello", "world")) -opt, token, status = unpack("!BLB", rec) - -rec = send(gen_update_location(token, random(), random())) -opc, status = unpack("!BB", rec) - -rec = send(gen_request_location(token, 1)) -opc, length = unpack("!BL", rec[:5]) -idx = 5 -for i in xrange(length): - uid, lat, lng = unpack("!Ldd", rec[idx:idx + 20]) - print (uid, lat, lng) - idx += 20 -# sleep(60) diff --git a/server/piztor/exc.py b/server/piztor/exc.py index 5daf420..2c53dbf 100644 --- a/server/piztor/exc.py +++ b/server/piztor/exc.py @@ -1,6 +1,9 @@ class PiztorError(Exception): pass +class DBCurruptedError(PiztorError): + pass + class ConnectionError(PiztorError): pass @@ -10,5 +13,5 @@ class ReqReadError(ConnectionError): class BadReqError(ConnectionError): pass -class InvalidTokenError(ConnectionError): +class BadTokenError(ConnectionError): pass diff --git a/server/piztor/import.py b/server/piztor/import.py index 1521849..84c990f 100644 --- a/server/piztor/import.py +++ b/server/piztor/import.py @@ -5,9 +5,10 @@ from model import * path = "piztor.sqlite" class UserData: - def __init__(self, username, password, sex): + def __init__(self, username, password, gid, sex): self.username = username self.password = password + self.gid = gid self.sex = sex def create_database(): @@ -20,7 +21,7 @@ def import_user_data(data): Session = sessionmaker(bind = engine) session = Session() for user in data: - um = UserModel(username = user.username, sex = user.sex) + um = UserModel(username = user.username, gid = user.gid, sex = user.sex) um.auth = UserAuth(user.password) um.location = LocationInfo(lat = 0, lng = 0) session.add(um) @@ -38,7 +39,7 @@ if __name__ == '__main__': while True: line = f.readline().split() if len(line) == 0: break - data.append(UserData(line[0], line[1], line[2])) + data.append(UserData(line[0], line[1], line[2], line[3])) create_database() import_user_data(data) diff --git a/server/piztor/model.py b/server/piztor/model.py index d869c32..4621bbe 100644 --- a/server/piztor/model.py +++ b/server/piztor/model.py @@ -3,6 +3,7 @@ from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship, backref Base = declarative_base() + _SALT_LEN = 16 _TOKEN_LEN = 16 @@ -15,6 +16,7 @@ class UserModel(Base): __tablename__ = _TableName.UserModel id = Column(Integer, primary_key = True) + gid = Column(Integer) username = Column(String) sex = Column(Boolean) location = None @@ -23,7 +25,7 @@ class UserModel(Base): class LocationInfo(Base): __tablename__ = _TableName.LocationInfo - uid = Column(Integer, ForeignKey('users.id'), primary_key = True) + uid = Column(Integer, ForeignKey(_TableName.UserModel + '.id'), primary_key = True) lat = Column(Float(precesion = 64)) lng = Column(Float(precesion = 64)) user = relationship("UserModel", uselist = False, @@ -47,7 +49,7 @@ def _random_binary_string(length): class UserAuth(Base): __tablename__ = _TableName.UserAuth - uid = Column(Integer, ForeignKey('users.id'), primary_key = True) + uid = Column(Integer, ForeignKey(_TableName.UserModel + '.id'), primary_key = True) password = Column(LargeBinary) salt = Column(LargeBinary) token = Column(LargeBinary) diff --git a/server/piztor/prob.py b/server/piztor/prob.py new file mode 100644 index 0000000..4ccc957 --- /dev/null +++ b/server/piztor/prob.py @@ -0,0 +1,81 @@ +import socket +from struct import * +from random import random + +def get_hex(data): + return "".join([hex(ord(c))[2:].zfill(2) for c in data]) + +host = "localhost" +port = 9990 + +def gen_auth(username, password): + length = 4 + 1 + len(username) + 1 + len(password) + data = pack("!LB", length, 0x00) + data += username + data += "\0" + data += password + return data + +def gen_update_location(token, username, lat, lng): + length = 4 + 1 + 32 + 8 + 8 + len(username) + 1 + data = pack("!LB32s", length, 0x01, token) + data += username + data += chr(0) + data += pack("!dd", lat, lng) + return data + +def gen_request_location(token, username, gid): + length = 4 + 1 + 32 + 4 + len(username) + 1 + data = pack("!LB32s", length, 0x02, token) + data += username + data += chr(0) + data += pack("!L", gid) + return data + + +def send(data): + received = None + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((host, port)) + print len(data) + sock.sendall(data) + received = sock.recv(1024) + finally: + sock.close() + return received + +from sys import argv + +if len(argv) == 2: + host = argv[1] + +username = "hello" +password = "world" +gid = 1 + +resp = send(gen_auth(username, password)) +pl, optcode, status, uid, token = unpack("!LBBL32s", resp) +print "size: " + str((pl, len(resp))) +print "opt: " + str(optcode) +print "status: " + str(status) +print "uid: " + str(uid) +print "token: " + get_hex(token) + +resp = send(gen_update_location(token, username, random(), random())) +pl, optcode, status = unpack("!LBB", resp) +print "size: " + str((pl, len(resp))) +print "opt: " + str(optcode) +print "status: " + str(status) + +resp = send(gen_request_location(token, username, gid)) +print len(resp) +pl, optcode, status, length = unpack("!LBBL", resp[:10]) +print "size: " + str((pl, len(resp))) +idx = 10 +print "length: " + str(len(resp[10:])) +for i in xrange(length): + print len(resp[idx:idx + 20]) + uid, lat, lng = unpack("!Ldd", resp[idx:idx + 20]) + idx += 20 + print (uid, lat, lng) diff --git a/server/piztor/ptp.rst b/server/piztor/ptp.rst new file mode 100644 index 0000000..004bbd9 --- /dev/null +++ b/server/piztor/ptp.rst @@ -0,0 +1,135 @@ +Piztor Transmission Protocol v0.3a +---------------------------------- + +- General + + - Request + + :: + + +---4b---+---1b---+-------?b--------+ + | LENGTH | OPT_ID | SPECIFIC DATA | + +--int---+-uchar--+-----------------+ + + - Response + + :: + + +---4b---+---1b---+------?b---------+ + | LENGTH | OPT_ID | SPECIFIC DATA | + +--int---+-uchar--+-----------------+ + + Notice: + + - In following sections, ``LENGTH`` part is left out for clarity. + - ``PADDING`` has value ``0``. + - ``AUTH_HEAD`` structure: + + :: + + +----32b-----+----?b----+----1b---+ + | USER_TOKEN | USERNAME | PADDING | + +----raw-----+----------+---------+ + +- Authentication + + - Request + + :: + + +--1b---+-----?b------+----1b----+-----?b-----+ + | 0x00 | USERNAME | PADDING | PASSWORD | + +-uchar-+-------------+----------+------------+ + + - Response + + :: + + +--1b---+---1b---+---4b----+----32b-----+ + | 0x00 | STATUS | USER_ID | USER_TOKEN | + +-uchar-+--uchar-+---int---+----raw-----+ + + ``STATUS`` : + + - ``0x00`` for success + - ``0x01`` for failure + +- Location Update + + - Request + + :: + + +--1b---+-----?b------+----8b------+------8b-----+ + | 0x01 | AUTH_HEAD | LATITUDE | LONGITUDE | + +-uchar-+-------------+---double---+---double----+ + + - Response + + :: + + +--1b---+---1b---+ + | 0x01 | STATUS | + +-uchar-+--uchar-+ + + ``STATUS`` : + + - ``0x00`` for success + - ``0x01`` for invalid token + +- Location Information + + - Request + + :: + + +--1b---+------?b------+------4b-----+ + | 0x02 | AUTH_HEAD | GROUP_ID | + +-uchar-+--------------+-----int-----+ + + - Response + + :: + + +--1b---+---1b---+-----4b----+------20b-------+-----+ + | 0x02 | STATUS | ENTRY_CNT | LOCATION_ENTRY | ... | + +-uchar-+-uchar--+----int----+----------------+-----+ + + ``LOCATION_ENTRY`` : + + :: + + +---4b----+----8b----+-----8b----+ + | USER_ID | LATITUDE | LONGITUDE | + +---int---+--double--+--double---+ + +- User Information + + - Request + + :: + + +--1b---+------?b------+------4b-----+ + | 0x02 | AUTH_HEAD | USER_ID | + +-uchar-+--------------+-----int-----+ + + - Response + + :: + + +--1b---+---1b---+------?b-----+-----+ + | 0x03 | STATUS | UINFO_ENTRY | ... | + +-uchar-+-uchar--+-------------+-----+ + + ``UINFO_ENTRY`` : + + :: + + +----1b----+-----?b-----+---1b----+ + | INFO_KEY | INFO_VALUE | PADDING | + +--uchar---+------------+---------+ + + ``INFO_KEY`` : + + :``0x00``: gid (value is a 4-byte ``long int``) + :``0x01``: sex (value is a 1-byte ``boolean``: ``True`` for male, ``False`` for female) diff --git a/server/piztor/server.py b/server/piztor/server.py new file mode 100644 index 0000000..2397225 --- /dev/null +++ b/server/piztor/server.py @@ -0,0 +1,321 @@ +from twisted.internet.protocol import Protocol +from twisted.internet.protocol import Factory +from twisted.internet.endpoints import TCP4ServerEndpoint +from twisted.internet import reactor +from twisted.protocols.policies import TimeoutMixin + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound + +import struct +import os +import logging + +from exc import * +from model import * + +def get_hex(data): + return "".join([hex(ord(c))[2:].zfill(2) for c in data]) + +def print_datagram(data): + print "==================================" + print "Received datagram:" + print get_hex(data) + print "==================================" + +db_path = "piztor.sqlite" +FORMAT = "%(asctime)-15s %(message)s" +logging.basicConfig(format = FORMAT) +logger = logging.getLogger('piztor_server') +logger.setLevel(logging.INFO) + + +class _SectionSize: + LENGTH = 4 + OPT_ID = 1 + STATUS = 1 + USER_ID = 4 + USER_TOKEN = 32 + GROUP_ID = 4 + ENTRY_CNT = 4 + LATITUDE = 8 + LONGITUDE = 8 + LOCATION_ENTRY = USER_ID + LATITUDE + LONGITUDE + PADDING = 1 + +class _OptCode: + user_auth = 0x00 + location_update = 0x01 + location_request= 0x02 + +class _StatusCode: + sucess = 0x00 + failure = 0x01 + +class RequestHandler(object): + def __init__(self): + self.engine = create_engine('sqlite:///' + db_path, echo = False) + self.Session = sessionmaker(bind = self.engine) + + @classmethod + def get_uauth(cls, token, username, session): + try: + uauth = session.query(UserAuth) \ + .filter(UserAuth.token == token).one() + + if uauth.user.username != username: + logger.warning("Toke and username mismatch") + return None + + return uauth + + except NoResultFound: + logger.warning("Incorrect token") + return None + + except MultipleResultsFound: + raise DBCorruptedError() + + @classmethod + def trunc_padding(cls, data): + leading = bytes() + for i in xrange(len(data)): + ch = data[i] + if ch == '\x00': + print get_hex(leading), get_hex(data[i + 1:]) + return (leading, data[i + 1:]) + else: + leading += ch + # padding not found + return (None, data) + +class UserAuthHandler(RequestHandler): + + _user_auth_response_size = \ + _SectionSize.LENGTH + \ + _SectionSize.OPT_ID + \ + _SectionSize.STATUS + \ + _SectionSize.USER_ID + \ + _SectionSize.USER_TOKEN + + def handle(self, tr_data): + logger.info("Reading auth data...") + pos = -1 + for i in xrange(0, len(tr_data)): + if tr_data[i] == '\x00': + pos = i + break + if pos == -1: + raise BadReqError("Authentication: Malformed request body") + + username = tr_data[0:pos] + password = tr_data[pos + 1:] + logger.info("Trying to login with " \ + "(username = {0}, password = {1})" \ + .format(username, password)) + + session = self.Session() + try: + user = session.query(UserModel) \ + .filter(UserModel.username == username).one() + except NoResultFound: + logger.info("No such user: {0}".format(username)) + return struct.pack("!LBBL32s", UserAuthHandler \ + ._user_auth_response_size, + _OptCode.user_auth, + _StatusCode.failure, + 0, + bytes('\x00' * 32)) + + except MultipleResultsFound: + raise DBCorruptedError() + + uauth = user.auth + if uauth is None: + raise DBCorruptedError() + if not uauth.check_password(password): + logger.info("Incorrect password: {0}".format(username)) + return struct.pack("!LBBL32s", UserAuthHandler \ + ._user_auth_response_size, + _OptCode.user_auth, + _StatusCode.failure, + 0, + bytes('\x00' * 32)) + else: + logger.info("Logged in sucessfully: {0}".format(username)) + uauth.regen_token() + session.commit() + print "new token generated: " + get_hex(uauth.token) + return struct.pack("!LBBL32s", UserAuthHandler \ + ._user_auth_response_size, + _OptCode.user_auth, + _StatusCode.sucess, + user.id, + uauth.token) + + +class LocationUpdateHandler(RequestHandler): + +# _location_update_size = \ +# _SectionSize.AUTH_HEAD + \ +# _SectionSize.LATITUDE + \ +# _SectionSize.LONGITUDE + + _location_update_response_size = \ + _SectionSize.LENGTH + \ + _SectionSize.OPT_ID + \ + _SectionSize.STATUS + + def handle(self, tr_data): + logger.info("Reading location update data...") + + try: + token, = struct.unpack("!32s", tr_data[:32]) + username, tail = RequestHandler.trunc_padding(tr_data[32:]) + if username is None: + raise struct.error + lat, lng = struct.unpack("!dd", tail) + except struct.error: + raise BadReqError("Location update: Malformed request body") + + logger.info("Trying to update location with " + "(token = {0}, username = {1}, lat = {2}, lng = {3})"\ + .format(get_hex(token), username, lat, lng)) + + session = self.Session() + uauth = RequestHandler.get_uauth(token, username, session) + # Authentication failure + if uauth is None: + logger.warning("Authentication failure") + return struct.pack("!LBB", LocationUpdateHandler \ + ._location_update_response_size, + _OptCode.location_update, + _StatusCode.failure) + + ulocation = uauth.user.location + ulocation.lat = lat + ulocation.lng = lng + session.commit() + + logger.info("Location is updated sucessfully") + return struct.pack("!LBB", LocationUpdateHandler \ + ._location_update_response_size, + _OptCode.location_update, + _StatusCode.sucess) + +class LocationRequestHandler(RequestHandler): + +# _location_request_size = \ +# _SectionSize.AUTH_HEAD + \ +# _SectionSize.GROUP_ID + + @classmethod + def _location_request_response_size(cls, item_num): + return _SectionSize.LENGTH + \ + _SectionSize.OPT_ID + \ + _SectionSize.STATUS + \ + _SectionSize.ENTRY_CNT + \ + _SectionSize.LOCATION_ENTRY * item_num + + def handle(self, tr_data): + logger.info("Reading location request data..") + + try: + token, = struct.unpack("!32s", tr_data[:32]) + username, tail = RequestHandler.trunc_padding(tr_data[32:]) + if username is None: + raise struct.error + gid, = struct.unpack("!L", tail) + except struct.error: + raise BadReqError("Location request: Malformed request body") + + logger.info("Trying to request locatin with " \ + "(token = {0}, gid = {1})" \ + .format(get_hex(token), gid)) + + session = self.Session() + uauth = RequestHandler.get_uauth(token, username, session) + # Auth failure + if uauth is None: + logger.warning("Authentication failure") + return struct.pack("!LBBL", LocationRequestHandler \ + ._location_request_response_size(0), + _OptCode.location_request, + _StatusCode.failure, + 0) + + ulist = session.query(UserModel).filter(UserModel.gid == gid).all() + reply = struct.pack( + "!LBBL", + LocationRequestHandler._location_request_response_size(len(ulist)), + _OptCode.location_request, + _StatusCode.sucess, + len(ulist)) + + for user in ulist: + loc = user.location + reply += struct.pack("!Ldd", user.id, loc.lat, loc.lng) + + return reply + +handlers = [UserAuthHandler, + LocationUpdateHandler, + LocationRequestHandler] + +def check_header(header): + return 0 <= header < len(handlers) + +class PTP(Protocol, TimeoutMixin): + + def __init__(self, factory): + self.buff = bytes() + self.length = -1 + self.factory = factory + + def timeoutConnection(self): + logger.info("The connection times out") + + def connectionMade(self): + logger.info("A new connection is made") + self.setTimeout(self.factory.timeout) + + def dataReceived(self, data): + self.buff += data + self.resetTimeout() + print len(self.buff) + if len(self.buff) > 4: + try: + self.length, self.optcode = struct.unpack("!LB", self.buff[:5]) + if not check_header(self.optcode): # invalid header + raise struct.error + except struct.error: + logger.warning("Invalid request header") + raise BadReqError("Malformed request header") + print self.length + if self.length == -1: + return + if len(self.buff) == self.length: + h = handlers[self.optcode]() + reply = h.handle(self.buff[5:]) + logger.info("Wrote: %s", get_hex(reply)) + self.transport.write(reply) + self.transport.loseConnection() + + elif len(self.buff) > self.length: + self.transport.loseConnection() + + + def connectionLost(self, reason): + logger.info("The connection is lost") + self.setTimeout(None) + +class PTPFactory(Factory): + def __init__(self, timeout = 10): + self.timeout = timeout + def buildProtocol(self, addr): + return PTP(self) + +endpoint = TCP4ServerEndpoint(reactor, 9990) +endpoint.listen(PTPFactory()) +reactor.run() diff --git a/server/piztor_server.py b/server/piztor_server.py deleted file mode 100644 index 514f95f..0000000 --- a/server/piztor_server.py +++ /dev/null @@ -1,234 +0,0 @@ -import sqlalchemy -import SocketServer, socket, select -import struct -import os - -from sqlalchemy import create_engine -from sqlalchemy import Column, Integer, String, Float -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker -from random import randint - -engine = create_engine('sqlite:///t.sqlite', echo = False) -Base = declarative_base() -Session = sessionmaker(bind=engine) - -def get_hex(data): - return "".join([hex(ord(c))[2:].zfill(2) for c in data]) - -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(TokenInvalidError, self).__init__("Invalid token") - -class DataManager(object): - def __init__(self, piz_srv): - self.piz_srv = piz_srv - -class UserManager(DataManager): - - class User(Base): - __tablename__ = 'users' - id = Column(Integer, primary_key = True) - gid = Column(Integer) - username = Column(String) - password = Column(String) - token = Column(Integer) - - def get_user_by_token(self, token): - session = Session() - User = UserManager.User - entries = session.query(User).filter(User.token == token).all() - if len(entries) == 0: - raise TokenInvalidError() - return entries[0] - - def authentication_handle(self, opt_type, data): - 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() - entries = session.query(UserManager.User). \ - filter(UserManager.User.username == username).all() - if len(entries) == 0: - return struct.pack("!BLB", 0, 0, 1) - entry = entries[0] - if entry.password != password: # Auth failed - print "Login failed!" - return struct.pack("!BLB", 0, 0, 1) - else: # Succeeded - print "Logged in sucessfully!" - entry.token = randint(0, 2147483647) - session.commit() - return struct.pack("!BLB", 0, entry.token, 0) - - -class MesgManager(DataManager): - def mesg_sending_handle(self, opt_type, data): - 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): - - class LocationInfo(Base): - __tablename__ = "location_info" - uid = Column(Integer, primary_key = True) - lat = Column(Float(precesion = 64)) - lng = Column(Float(precesion = 64)) - # More: last_update - - def location_update_handle(self, opt_type, data): - print "Parsing a Location Update" - try: - if len(data) < 8: - raise ReqInvalidError() - sender_token, lat, lng = struct.unpack("!Ldd", data) - print "Updating location data with following info:" - print (sender_token, lat, lng) - - user = self.piz_srv. \ - user_mgr.get_user_by_token(sender_token) - session = Session() - LInfo = LocationManager.LocationInfo - q = session.query(LInfo).filter(LInfo.uid == user.id) - entry = q.first() - entry.lat = lat - entry.lng = lng - session.commit() - print "Location update succeeded!" - return struct.pack("!BB", 2, 0) - except TokenInvalidError: - print "Location update failed!" - return struct.pack("!BB", 2, 1) - except struct.error: - raise ReqInvalidError() - - def location_request_handle(self, opt_type, data): - print "Parsing a Location Request" - try: - if len(data) != 8: - raise ReqInvalidError() - sender_token, gid = struct.unpack("!LL", data) - print "Requesting location data with following info:" - print (sender_token, gid) - session = Session() - UInfo = UserManager.User - LInfo = LocationManager.LocationInfo - user_list = session.query(UInfo).filter(UInfo.gid == gid).all() - reply = struct.pack("!BL", 3, len(user_list)) - for user in user_list: - loc = session.query(LInfo).filter(LInfo.uid == user.id).first() - reply += struct.pack("!Ldd", user.id, loc.lat, loc.lng) - print get_hex(reply) - return reply - except struct.error: - raise ReqInvalidError() - -class PiztorServer(): - - - class GenericHandler(SocketServer.StreamRequestHandler): - - def handle(self): - print self.piz_srv - sock = self.request - sock.settimeout(100) -# sock.setblocking(0) - data = "" - try: - while True: -# ready = select.select([sock], [], [], 10) -# 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:" + get_hex(data) - - if len(data) < 1: - print "invalid length" - raise ReqInvalidError() - opt_id = struct.unpack("!B", data[0])[0] - print opt_id - reply = self.piz_srv.mgr_map[opt_id](opt_id, data[1:]) - sock.sendall(reply) - finally: - sock.close() - - class ForkingEchoServer(SocketServer.ForkingMixIn, SocketServer.TCPServer): - pass - - def __init__(self, host, port): - PiztorServer.GenericHandler.piz_srv = self - srv = PiztorServer.ForkingEchoServer((host, port), - PiztorServer.GenericHandler) - srv.request_queue_size = 100 -# srv.timeout = 2 - self.server = srv - - self.user_mgr = UserManager(self) - self.mesg_mgr = MesgManager(self) - self.location_mgr = LocationManager(self) - - self.mgr_map = [ self.user_mgr.authentication_handle, - self.mesg_mgr.mesg_sending_handle, - self.location_mgr.location_update_handle, - self.location_mgr.location_request_handle] - - Base.metadata.create_all(engine) - - - def run(self): - try: - self.server.serve_forever() - except KeyboardInterrupt: - print "Exiting..." - self.server.shutdown() - print "Server shutdown" - -if __name__ == "__main__": - - ps = PiztorServer("localhost", 9990) - ps.run() diff --git a/server/ptp.rst b/server/ptp.rst deleted file mode 100644 index 4092399..0000000 --- a/server/ptp.rst +++ /dev/null @@ -1,93 +0,0 @@ -Piztor Transmission Protocol v0.1 ---------------------------------- - -- General - - - Request - - :: - - +---1b---+-------?b--------+ - | OPT ID | SPECIFIC DATA | - +-uchar--+-----------------+ - - - Response - - :: - - +---1b---+------?b---------+ - | OPT ID | SPECIFIC DATA | - +-uchar--+-----------------+ - -- Authentication - - - Request - - :: - - +--1b---+-----?b------+-----?b-----+ - | 0x00 | USERNAME | PASSWORD | - +-uchar-+-------------+------------+ - - - Response - - :: - - +--1b---+-----4b-----+---1b----+ - | 0x00 | USER_TOKEN | STATUS | - +-uchar-+-----int----+--uchar--+ - - ``STATUS`` : - - - 0x00 for success - - 0x01 for failure - -- Location Update - - - Request - - :: - - +--1b---+------4b------+-----8b-----+------8b-----+ - | 0x02 | SENDER_TOKEN | LATITUDE | LONGITUDE | - +-uchar-+------int-----+---double---+---double----+ - - - Response - - :: - - +--1b---+---1b---+ - | 0x02 | STATUS | - +-uchar-+--uchar-+ - - ``STATUS`` : - - - 0x00 for success - - 0x01 for invalid token - -- Location Information - - - Request - - :: - - +--1b---+-----4b-------+------4b-----+ - | 0x03 | SENDER_TOKEN | GROUP_ID | - +-uchar-+-----int------+-----int-----+ - - - Response - - :: - - +--1b---+-----4b----+------20b-------+-----+ - | 0x03 | ENTRY_CNT | LOCATION_ENTRY | ... | - +-uchar-+---int-----+----------------+-----+ - - ``LOCATION_ENTRY`` : - - :: - - +---4b----+----8b----+-----8b----+ - | USER_ID | LATITUDE | LONGITUDE | - +---int---+--double--+--double---+ - diff --git a/server/rush.py b/server/rush.py deleted file mode 100644 index f01804c..0000000 --- a/server/rush.py +++ /dev/null @@ -1,14 +0,0 @@ -from subprocess import Popen -procs = [] - -try: - for i in xrange(10): - p = Popen(["python", "client.py", str(i)]) - procs.append(p) - #p.wait() - print "done" - -except KeyboardInterrupt: - print "killing" - for p in procs: - p.kill() |