summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-30 10:08:29 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-30 10:08:29 +0800
commitfca8b55ebc85ac447daeb241063622bf79fa0910 (patch)
treec38813d1a4d0ccbaa715252c86fc9759d2c13721
parent35d91a285a22ade28638af7f7a26c2f47134ae1b (diff)
ptp v2.0 and server on the road
-rw-r--r--server/piztor/import.py51
-rw-r--r--server/piztor/model.py85
-rw-r--r--server/piztor/ptp.rst214
-rw-r--r--server/piztor/server.py46
4 files changed, 222 insertions, 174 deletions
diff --git a/server/piztor/import.py b/server/piztor/import.py
index 4896325..f5228e7 100644
--- a/server/piztor/import.py
+++ b/server/piztor/import.py
@@ -2,32 +2,49 @@ from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from model import *
-path = "root:helloworld@localhost/piztor"
+path = "root:helloworld@localhost/piztor2"
class UserData:
- def __init__(self, username, password, comp_id, sec_no, sex):
+ def __init__(self, username, nickname, password, comp_no, sec_no, sex, sub):
self.username = username
+ self.nickname = nickname
self.password = password
- self.comp_id = int(comp_id)
+ self.comp_no = int(comp_no)
self.sec_no = int(sec_no)
- self.sex = sex
+ self.sex = int(sex)
+ self.sub = sub
def create_database():
engine = create_engine('mysql://' + path, echo = True)
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
+def find_or_create_group(comp_no, sec_no, session):
+ gid = UserModel.to_gid(comp_no, sec_no)
+ q = session.query(GroupInfo).filter(GroupInfo.id == gid)
+ entry = None
+ entry = q.first()
+ if not entry:
+ entry = GroupInfo(gid = gid)
+ return entry
+
+
def import_user_data(data):
engine = create_engine('mysql://' + path, echo = True)
Session = sessionmaker(bind = engine)
session = Session()
+
for user in data:
um = UserModel(username = user.username,
- comp_id = user.comp_id,
- sec_no = user.sec_no,
- sec_id = user.comp_id * 256 + user.sec_no,
- sex = user.sex)
- print um.sec_id
+ nickname = user.nickname,
+ sex = user.sex,
+ comp_no = user.comp_no,
+ sec_no = user.sec_no)
+
+ for cn, sn in user.sub:
+ print cn, sn
+ g = find_or_create_group(int(cn), int(sn), session)
+ um.sub.append(g)
um.auth = UserAuth(user.password)
um.location = LocationInfo(lat = 0, lng = 0)
session.add(um)
@@ -45,11 +62,19 @@ if __name__ == '__main__':
while True:
line = f.readline().split()
if len(line) == 0: break
+ line2 = f.readline().split()
+ idx = 0
+ sub = list()
+ while idx < len(line2):
+ sub.append((line2[idx], line2[idx + 1]))
+ idx += 2
data.append(UserData(username = line[0],
- password = line[1],
- comp_id = line[2],
- sec_no = line[3],
- sex = line[4]))
+ nickname = line[1],
+ password = line[2],
+ comp_no = line[3],
+ sec_no = line[4],
+ sex = line[5], sub = sub))
+
create_database()
import_user_data(data)
diff --git a/server/piztor/model.py b/server/piztor/model.py
index b1a7804..03c0192 100644
--- a/server/piztor/model.py
+++ b/server/piztor/model.py
@@ -3,6 +3,7 @@ from sqlalchemy import Integer, String, Float, ForeignKey, Boolean
from sqlalchemy.dialects.mysql import BLOB, TINYINT
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
+from exc import *
Base = declarative_base()
@@ -20,18 +21,25 @@ class _TableName: # avoid typoes
UserModel = 'users'
LocationInfo = 'location_info'
UserAuth = 'user_auth'
- CompanyInfo = 'comp_info'
- SectionInfo = 'sec_info'
- CompanySub = 'comp_sub'
- SectionSub = 'sec_sub'
-
-#comp_sub_assoc = Table(_TableName.CompanySub, Base.metadata,
-# Column('uid', Integer, ForeignKey(_TableName.UserModel + '.id')),
-# Column('comp_id', Integer, ForeignKey(_TableName.CompanyInfo + '.id')))
-#
-#sec_sub_assoc = Table(_TableName.SectionSub, Base.metadata,
-# Column('uid', Integer, ForeignKey(_TableName.UserModel + '.id')),
-# Column('sec_id', Integer, ForeignKey(_TableName.SectionInfo + '.id')))
+ GroupInfo = 'group_info'
+ GroupSub = 'group_sub'
+
+
+class GroupInfo(Base):
+ __tablename__ = _TableName.GroupInfo
+ __table_args__ = _table_typical_settings
+
+ id = Column(Integer, primary_key = True)
+ subscribers = None
+
+ def __init__(self, gid):
+ self.id = gid
+
+group_sub = Table(_TableName.GroupSub, Base.metadata,
+ Column('uid', Integer, ForeignKey(_TableName.UserModel + '.id')),
+ Column('gid', Integer, ForeignKey(_TableName.GroupInfo + '.id')),
+ mysql_engine = 'InnoDB')
+
class UserModel(Base):
__tablename__ = _TableName.UserModel
@@ -39,24 +47,31 @@ class UserModel(Base):
id = Column(Integer, primary_key = True)
username = Column(String(MAX_USERNAME_SIZE),
unique = True, nullable = False)
-
+ nickname = Column(String(MAX_USERNAME_SIZE),
+ unique = False)
sex = Column(Boolean, nullable = False)
- sec_no = Column(TINYINT)
-# comp_id = Column(TINYINT, ForeignKey(_TableName.CompanyInfo + '.id'))
- comp_id = Column(TINYINT)
-# sec_id = Column(TINYINT, ForeignKey(_TableName.SectionInfo + '.id'))
+ comp_id = Column(Integer)
sec_id = Column(Integer)
-# comp_sub = relationship(_TableName.CompanyInfo,
-# secondary = comp_sub_assoc,
-# backref = "subscribers")
-# sec_sub = relationship(_TableName.SectionInfo,
-# secondary = sec_sub_assoc,
-# backref = "subscribers")
+ sub = relationship("GroupInfo",
+ secondary = group_sub,
+ backref = "subscribers")
location = None
auth = None
- sec = None
+
+ @classmethod
+ def to_gid(self, comp_no, sec_no):
+ return comp_no * 256 + sec_no
+
+ def __init__(self, username, nickname, sex, comp_no, sec_no):
+ self.username = username
+ self.nickname = nickname
+ self.sex = sex
+ self.comp_id = UserModel.to_gid(comp_no, 0xff)
+ self.sec_id = UserModel.to_gid(comp_no, sec_no)
+ self.sub = list()
+
class LocationInfo(Base):
__tablename__ = _TableName.LocationInfo
@@ -117,23 +132,5 @@ class UserAuth(Base):
def get_token(self):
return self.token
-#
-#class CompanyInfo(Base):
-# __tablename__ = _TableName.CompanyInfo
-# __table_args__ = _table_typical_settings
-#
-# id = Column(TINYINT, primary_key = True)
-# marker_lat = Column(Float(precesion = 64), nullable = False)
-# marker_lng = Column(Float(precesion = 64), nullable = False)
-#
-# subscribers = None
-#
-#class SectionInfo(Base):
-# __tablename__ = _TableName.SectionInfo
-# __table_args__ = _table_typical_settings
-#
-# id = Column(TINYINT, primary_key = True)
-# marker_lat = Column(Float(precesion = 64), nullable = False)
-# market_lng = Column(Float(precesion = 64), nullable = False)
-#
-# subscribers = None
+
+
diff --git a/server/piztor/ptp.rst b/server/piztor/ptp.rst
index 19eab65..66c1fe2 100644
--- a/server/piztor/ptp.rst
+++ b/server/piztor/ptp.rst
@@ -1,4 +1,4 @@
-Piztor Transmission Protocol v1.0b
+Piztor Transmission Protocol v2.0
----------------------------------
- Pull
@@ -23,9 +23,16 @@ Piztor Transmission Protocol v1.0b
Notice:
- - In following sections, ``LENGTH`` part is left out for clarity.
- - ``PADDING`` has value ``0``.
- - ``string`` type structure:
+ - In following sections, ``LENGTH`` and ``OPT_ID`` are left out for clarity.
+ - ``PADDING``:
+
+ ::
+
+ +--1b--+
+ | 0x00 |
+ +------+
+
+ - ``string`` type:
::
@@ -33,178 +40,193 @@ Piztor Transmission Protocol v1.0b
| STRING_CONTENT | PADDING |
+----------------+---------+
- - ``AUTH_HEAD`` structure:
+ - ``AUTH_HEAD`` :
::
+----32b-----+----?b----+
| USER_TOKEN | USERNAME |
+----raw-----+--string--+
+
+ - ``GROUP_ID`` :
+
+ ::
+
+ +---1b----+---1b---+
+ | COMP_ID | SEC_ID |
+ +--uchar--+-uchar--+
+
+ - ``USER_ENTRY`` :
+
+ ::
- - Authentication
+ +----1b---+------?b-----+-----+---------+
+ | USER_ID | INFO_ENTRY | ... | PADDING |
+ +--uchar--+-------------+-----+---------+
+
+ - ``INFO_ENTRY`` :
+
+ ::
+
+ +----1b----+-----?b-----+
+ | INFO_KEY | INFO_VALUE |
+ +--uchar---+------------+
+
+ - ``INFO_KEY`` :
+
+ :``0x01``: uid (value is a 4-byte ``integer``)
+ :``0x02``: username (value is a ``string``)
+ :``0x03``: nickname (value is a ``string``)
+ :``0x04``: sex (value is a 1-byte ``boolean``: ``0x01`` for male, ``0x00`` for female)
+ :``0x05``: gid (value is a 2-byte ``GROUP_ID``)
+ :``0x06``: latitude (value is a 8-byte ``double`` )
+ :``0x07``: longtitude( value is a 8-byte ``double`` )
+
+ - ``SUB_LIST`` :
+
+ ::
+
+ +----------+-----+
+ | GROUP_ID | ... |
+ +----------+-----+
+
+ - Authentication ``0x00``
- Request
::
- +--1b---+-----?b---+----?b----+
- | 0x00 | USERNAME | PASSWORD |
- +-uchar-+--string--+--string--+
+ +-----?b---+----?b----+
+ | USERNAME | PASSWORD |
+ +--string--+--string--+
- Response
::
- +--1b---+---1b---+---4b----+----32b-----+
- | 0x00 | STATUS | USER_ID | USER_TOKEN |
- +-uchar-+--uchar-+---int---+----raw-----+
+ +---1b---+----32b-----+------------+----------+
+ | STATUS | USER_TOKEN | USER_ENTRY | SUB_LIST |
+ +--uchar-+----raw-----+------------+----------+
``STATUS`` :
- ``0x00`` for success
- ``0x01`` for failure
- - Location Update
+ - Location Update ``0x01``
- Request
::
- +--1b---+-----?b------+----8b------+------8b-----+
- | 0x01 | AUTH_HEAD | LATITUDE | LONGITUDE |
- +-uchar-+-------------+---double---+---double----+
+ +-------------+----8b------+------8b-----+
+ | AUTH_HEAD | LATITUDE | LONGITUDE |
+ +-------------+---double---+---double----+
- Response
::
- +--1b---+---1b---+
- | 0x01 | STATUS |
- +-uchar-+--uchar-+
+ +--------+
+ | STATUS |
+ +--uchar-+
``STATUS`` :
- ``0x00`` for success
- ``0x01`` for invalid token
- - Location Information
-
- - Request
-
- ::
-
- +--1b---+------?b------+------2b-----+
- | 0x02 | AUTH_HEAD | GROUP_ID |
- +-uchar-+--------------+-------------+
- ``GROUP_ID``:
-
- ::
-
- +---1b----+---1b---+
- | COMP_ID | SEC_ID |
- +--uchar--+-uchar--+
-
- - Response
-
- ::
-
- +--1b---+---1b---+------20b-------+-----+
- | 0x02 | STATUS | LOCATION_ENTRY | ... |
- +-uchar-+-uchar--+----------------+-----+
-
- ``LOCATION_ENTRY`` :
-
- ::
-
- +---4b----+----8b----+-----8b----+
- | USER_ID | LATITUDE | LONGITUDE |
- +---int---+--double--+--double---+
-
- - User Information
+ - User Information (by group) ``0x02``
- Request
::
- +--1b---+------?b------+------4b-----+
- | 0x03 | AUTH_HEAD | USER_ID |
- +-uchar-+--------------+-----int-----+
+ +--------------+------4b-----+
+ | AUTH_HEAD | GROUP_ID |
+ +--------------+-----int-----+
- Response
::
- +--1b---+---1b---+------?b-----+-----+
- | 0x03 | STATUS | UINFO_ENTRY | ... |
- +-uchar-+-uchar--+-------------+-----+
-
- ``UINFO_ENTRY`` :
-
+ +--------+------?b-----+-----+
+ | STATUS | USER_ENTRY | ... |
+ +-uchar--+-------------+-----+
+
+
+ - Update Subscription ``0x03``
+
+ - Request
+
::
+
+ +-----------+----------+
+ | AUTH_HEAD | SUB_LIST |
+ +-----------+----------+
+
+ - Response
+
+ ::
+
+ +--------+
+ | STATUS |
+ +--------+
- +----1b----+-----?b-----+
- | INFO_KEY | INFO_VALUE |
- +--uchar---+------------+
-
- ``INFO_KEY`` :
-
- :``0x00``: gid (value is a 2-byte ``GROUP_ID``)
- :``0x01``: sex (value is a 1-byte ``boolean``: ``0x01`` for male, ``0x00`` for female)
-
- - User Logout
+ - User Logout ``0x04``
- Request
::
- +--1b--+-----?b------+
- | 0x04 | AUTH_HEAD |
- +------+-------------+
+ +-----------+
+ | AUTH_HEAD |
+ +-----------+
- Response
::
- +--1b--+---1b---+
- | 0x04 | STATUS |
- +------+--------+
+ +--------+
+ | STATUS |
+ +--------+
- - Open Push Tunnel
+ - Open Push Tunnel ``0x05``
- Request
::
- +--1b--+-----?b------+
- | 0x05 | AUTH_HEAD |
- +------+-------------+
+ +-----------+
+ | AUTH_HEAD |
+ +-----------+
- Response
::
- +--1b--+---1b---+
- | 0x05 | STATUS |
- +------+--------+
+ +--------+
+ | STATUS |
+ +--------+
- - Send Text Message
+ - Send Text Message ``0x06``
- Request
::
- +--1b--+----?b-----+----?b----+
- | 0x06 | AUTH_HEAD | MESSAGE |
- +------+-----------+--string--+
+ +-----------+----?b----+
+ | AUTH_HEAD | MESSAGE |
+ +-----------+--string--+
- Response
::
- +--1b--+---1b---+
- | 0x06 | STATUS |
- +------+--------+
+ +--------+
+ | STATUS |
+ +--------+
- Push Notification
@@ -232,11 +254,11 @@ Piztor Transmission Protocol v1.0b
... | MESSAGE |
----+--string--+
- - User Location Update
+ - Location Update
::
- ----+-------?b-------+
- ... | LOCATION_ENTRY |
- ----+----------------+
+ ----+---4b----+----8b----+----8b-----+
+ ... | USER_ID | LATITUDE | LONGITUDE |
+ ----+---------+----------+-----------+
diff --git a/server/piztor/server.py b/server/piztor/server.py
index ed4e0b9..3bd1a2c 100644
--- a/server/piztor/server.py
+++ b/server/piztor/server.py
@@ -19,10 +19,7 @@ from model import *
def get_hex(data):
return "".join([hex(ord(c))[2:].zfill(2) for c in data])
-def get_sec_id(comp_id, sec_no):
- return comp_id * 256 + sec_no
-
-db_path = "root:helloworld@localhost/piztor"
+db_path = "root:helloworld@localhost/piztor2"
#db_path = "piztor.sqlite"
FORMAT = "%(asctime)-15s %(message)s"
logging.basicConfig(format = FORMAT)
@@ -292,10 +289,22 @@ class LocationUpdateHandler(RequestHandler):
self.session.commit()
pt = RequestHandler.push_tunnels
- ulist = self.session.query(UserModel) \
- .filter(UserModel.sec_id == uauth.user.sec_id).all()
- pdata = PushLocationData(uauth.uid, lat, lng)
- for user in ulist:
+ u = uauth.user
+ comp = self.session.query(GroupInfo) \
+ .filter(GroupInfo.id == u.comp_id).one()
+ sec = self.session.query(GroupInfo) \
+ .filter(GroupInfo.id == u.sec_id).one()
+
+ pdata = PushLocationData(u.id, lat, lng)
+ for user in comp.subscribers:
+ uid = user.id
+ if uid == uauth.uid: continue
+ if pt.has_key(uid):
+ tunnel = pt[uid]
+ tunnel.add(pdata)
+ tunnel.push()
+
+ for user in sec.subscribers:
uid = user.id
if uid == uauth.uid: continue
if pt.has_key(uid):
@@ -327,13 +336,13 @@ class LocationInfoHandler(RequestHandler):
username, tail = RequestHandler.trunc_padding(tr_data[32:])
if username is None:
raise struct.error
- comp_id, sec_no = struct.unpack("!BB", tail)
+ comp_no, sec_no = struct.unpack("!BB", tail)
except struct.error:
raise BadReqError("Location request: Malformed request body")
logger.info("Trying to request locatin with " \
- "(token = {0}, comp_id = {1}, sec_no = {2})" \
- .format(get_hex(token), comp_id, sec_no))
+ "(token = {0}, comp_no = {1}, sec_no = {2})" \
+ .format(get_hex(token), comp_no, sec_no))
uauth = RequestHandler.get_uauth(token, username, self.session)
# Auth failure
@@ -343,13 +352,9 @@ class LocationInfoHandler(RequestHandler):
_OptCode.location_info,
_StatusCode.failure)
- if sec_no == 0xff: # All members in the company
- ulist = self.session.query(UserModel) \
- .filter(UserModel.comp_id == comp_id).all()
- else:
- sec_id = get_sec_id(comp_id, sec_no)
- ulist = self.session.query(UserModel) \
- .filter(UserModel.sec_id == sec_id).all()
+ ulist = self.session.query(UserModel) \
+ .filter(UserModel.sec_id ==
+ UserModel.to_gid(comp_no, sec_no)).all()
reply = struct.pack(
"!LBB",
self._response_size(len(ulist)),
@@ -363,7 +368,7 @@ class LocationInfoHandler(RequestHandler):
return reply
def pack_gid(user):
- return struct.pack("!BB", user.comp_id, user.sec_no)
+ return struct.pack("!H", user.sec_id)
def pack_sex(user):
return struct.pack("!B", 0x01 if user.sex else 0x00)
@@ -557,9 +562,8 @@ class SendTextMessageHandler(RequestHandler):
pt = RequestHandler.push_tunnels
u = uauth.user
- sec_id = get_sec_id(u.comp_id, u.sec_no)
ulist = self.session.query(UserModel) \
- .filter(UserModel.sec_id == sec_id).all()
+ .filter(UserModel.sec_id == u.sec_id).all()
for user in ulist:
uid = user.id