summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorgoblin911 <[email protected]>2013-08-25 21:16:45 +0800
committergoblin911 <[email protected]>2013-08-25 21:16:45 +0800
commit2efdc2f20f0306791ced5ec78a1acddfaf086f42 (patch)
treea85f2b32d6e6da9d7329ab975fea3bd79e1b94b6 /server
parente5599da7fdd344fdcb49e8d6780a1e2ad358ee2d (diff)
parent263967cbb477983ae8680b431c1d93f102971c30 (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.rst1
-rw-r--r--server/client.py58
-rw-r--r--server/piztor/exc.py5
-rw-r--r--server/piztor/import.py7
-rw-r--r--server/piztor/model.py6
-rw-r--r--server/piztor/prob.py81
-rw-r--r--server/piztor/ptp.rst135
-rw-r--r--server/piztor/server.py321
-rw-r--r--server/piztor_server.py234
-rw-r--r--server/ptp.rst93
-rw-r--r--server/rush.py14
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()