From 193c42df2fdcf9f29de75389ef217e0817b00054 Mon Sep 17 00:00:00 2001 From: Teddy Date: Tue, 27 Aug 2013 16:23:27 +0800 Subject: ptp v4.0a std-complaint server --- server/piztor/exc.py | 2 +- server/piztor/prober.py | 19 ++++++++++- server/piztor/server.py | 87 +++++++++++++++++++++++++++++++++++-------------- 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/server/piztor/exc.py b/server/piztor/exc.py index 390193c..26b6210 100644 --- a/server/piztor/exc.py +++ b/server/piztor/exc.py @@ -1,7 +1,7 @@ class PiztorError(Exception): pass -class DBCurruptedError(PiztorError): +class DBCorruptionError(PiztorError): pass class BadReqError(PiztorError): diff --git a/server/piztor/prober.py b/server/piztor/prober.py index 6c28364..613d667 100644 --- a/server/piztor/prober.py +++ b/server/piztor/prober.py @@ -2,6 +2,7 @@ import socket from struct import * from random import random from select import select +from time import sleep def get_hex(data): return "".join([hex(ord(c))[2:].zfill(2) for c in data]) @@ -43,6 +44,13 @@ def gen_request_user_info(token, username, uid): data += pack("!L", uid) return data +def gen_logout(token, username): + length = 4 + 1 + 32 + len(username) + 1 + data = pack("!LB32s", length, 0x04, token) + data += username + data += chr(0) + return data + def send(data): received = bytes() try: @@ -145,7 +153,16 @@ for i in xrange(10): # print (info_key, info_value) except: print "fuck6" - from time import sleep + + resp = send(gen_logout(token, username)) + try: + pl, optcode, status = unpack("!LBB", resp) + except: + print "fuck7" + if pl != len(resp): print "God!" +# print "size: " + str((pl, len(resp))) +# print "opt: " + str(optcode) +# print "status: " + str(status) sleep(10) print failed_cnt diff --git a/server/piztor/server.py b/server/piztor/server.py index 1560735..18c2e2d 100644 --- a/server/piztor/server.py +++ b/server/piztor/server.py @@ -22,7 +22,7 @@ db_path = "root:helloworld@localhost/piztor" FORMAT = "%(asctime)-15s %(message)s" logging.basicConfig(format = FORMAT) logger = logging.getLogger('piztor_server') -logger.setLevel(logging.WARN) +logger.setLevel(logging.INFO) engine = create_engine('mysql://' + db_path, echo = False, pool_size = 1024) @@ -48,8 +48,9 @@ _HEADER_SIZE = _SectionSize.LENGTH + \ class _OptCode: user_auth = 0x00 location_update = 0x01 - location_request= 0x02 - user_info_request = 0x03 + location_info= 0x02 + user_info = 0x03 + user_logout = 0x04 class _StatusCode: sucess = 0x00 @@ -85,7 +86,7 @@ class RequestHandler(object): return None except MultipleResultsFound: - raise DBCorruptedError() + raise DBCorruptionError() @classmethod def trunc_padding(cls, data): @@ -143,23 +144,23 @@ class UserAuthHandler(RequestHandler): .filter(UserModel.username == username).one() except NoResultFound: logger.info("No such user: {0}".format(username)) - return UserAuthHandler._failed_response + return self._failed_response except MultipleResultsFound: - raise DBCorruptedError() + raise DBCorruptionError() uauth = user.auth if uauth is None: - raise DBCorruptedError() + raise DBCorruptionError() if not uauth.check_password(password): logger.info("Incorrect password: {0}".format(password)) - return UserAuthHandler._failed_response + return self._failed_response else: logger.info("Logged in sucessfully: {0}".format(username)) uauth.regen_token() #logger.info("New token generated: " + get_hex(uauth.token)) self.session.commit() - return struct.pack("!LBBL32s", UserAuthHandler._response_size, + return struct.pack("!LBBL32s", self._response_size, _OptCode.user_auth, _StatusCode.sucess, user.id, @@ -197,7 +198,7 @@ class LocationUpdateHandler(RequestHandler): # Authentication failure if uauth is None: logger.warning("Authentication failure") - return struct.pack("!LBB", LocationUpdateHandler._response_size, + return struct.pack("!LBB", self._response_size, _OptCode.location_update, _StatusCode.failure) @@ -207,7 +208,7 @@ class LocationUpdateHandler(RequestHandler): logger.info("Location is updated sucessfully") self.session.commit() - return struct.pack("!LBB", LocationUpdateHandler._response_size, + return struct.pack("!LBB", self._response_size, _OptCode.location_update, _StatusCode.sucess) @@ -243,15 +244,15 @@ class LocationInfoHandler(RequestHandler): # Auth failure if uauth is None: logger.warning("Authentication failure") - return struct.pack("!LBB", LocationInfoHandler._response_size(0), - _OptCode.location_request, + return struct.pack("!LBB", self._response_size(0), + _OptCode.location_info, _StatusCode.failure) ulist = self.session.query(UserModel).filter(UserModel.gid == gid).all() reply = struct.pack( "!LBB", - LocationInfoHandler._response_size(len(ulist)), - _OptCode.location_request, + self._response_size(len(ulist)), + _OptCode.location_info, _StatusCode.sucess) for user in ulist: @@ -279,7 +280,7 @@ class UserInfoHandler(RequestHandler): _fail_response = \ struct.pack("!LBB", _failed_response_size, - _OptCode.user_info_request, + _OptCode.user_info, _StatusCode.failure) _code_map = {0x00 : ('gid', pack_int), @@ -312,35 +313,73 @@ class UserInfoHandler(RequestHandler): # Auth failure if uauth is None: logger.warning("Authentication failure") - return UserInfoHandler._fail_response + return self._fail_response # TODO: check the relationship between user and quser user = uauth.user - reply = struct.pack("!BB", _OptCode.user_info_request, + reply = struct.pack("!BB", _OptCode.user_info, _StatusCode.sucess) try: quser = self.session.query(UserModel) \ .filter(UserModel.id == uid).one() except NoResultFound: logger.info("No such user: {0}".format(username)) - return UserInfoHandler._fail_response + return self._fail_response except MultipleResultsFound: - raise DBCorruptedError() + raise DBCorruptionError() - for code in UserInfoHandler._code_map: + for code in self._code_map: reply += UserInfoHandler.pack_entry(quser, code) reply = struct.pack("!L", len(reply) + _SectionSize.LENGTH) + reply return reply - +class UserLogoutHandler(RequestHandler): + + _max_tr_data_size = _MAX_AUTH_HEAD_SIZE + + _response_size = \ + _SectionSize.LENGTH + \ + _SectionSize.OPT_ID + \ + _SectionSize.STATUS + + def handle(self, tr_data): + self.check_size(tr_data) + logger.info("Reading user logout data...") + try: + token, = struct.unpack("!32s", tr_data[:32]) + username, tail = RequestHandler.trunc_padding(tr_data[32:]) + if username is None: + raise struct.error + except struct.error: + raise BadReqError("User logout: 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)) +# + uauth = RequestHandler.get_uauth(token, username, self.session) + # Authentication failure + if uauth is None: + logger.warning("Authentication failure") + return struct.pack("!LBB", self._response_size, + _OptCode.location_update, + _StatusCode.failure) + uauth.regen_token() + logger.info("User Logged out successfully!") + self.session.commit() + return struct.pack("!LBB", self._response_size, + _OptCode.user_logout, + _StatusCode.sucess) + class PTP(Protocol, TimeoutMixin): handlers = [UserAuthHandler, LocationUpdateHandler, LocationInfoHandler, - UserInfoHandler] + UserInfoHandler, + UserLogoutHandler] handler_num = len(handlers) @@ -390,7 +429,7 @@ class PTP(Protocol, TimeoutMixin): raise BadReqError("The actual length is larger than promised") except BadReqError as e: logger.warn("Rejected a bad request: %s", str(e)) - except DBCorruptedError: + except DBCorruptionError: logger.error("*** Database corruption ***") finally: self.transport.loseConnection() -- cgit v1.2.3