|
|
- import hmac
- from hashlib import sha256
- import base64
- import struct
- from zlib import crc32
- import secrets
- import time
- from collections import OrderedDict
-
- kJoinChannel = 1
- kPublishAudioStream = 2
- kPublishVideoStream = 3
- kPublishDataStream = 4
- kPublishAudiocdn = 5
- kPublishVideoCdn = 6
- kRequestPublishAudioStream = 7
- kRequestPublishVideoStream = 8
- kRequestPublishDataStream = 9
- kInvitePublishAudioStream = 10
- kInvitePublishVideoStream = 11
- kInvitePublishDataStream = 12
- kAdministrateChannel = 101
- kRtmLogin = 1000
-
- VERSION_LENGTH = 3
- APP_ID_LENGTH = 32
-
-
- def getVersion():
- return '006'
-
-
- def packUint16(x):
- return struct.pack('<H', int(x))
-
-
- def packUint32(x):
- return struct.pack('<I', int(x))
-
-
- def packInt32(x):
- return struct.pack('<i', int(x))
-
-
- def packString(string):
- return packUint16(len(string)) + string
-
-
- def packMap(m):
- ret = packUint16(len(list(m.items())))
- for k, v in list(m.items()):
- ret += packUint16(k) + packString(v)
- return ret
-
-
- def packMapUint32(m):
- ret = packUint16(len(list(m.items())))
- for k, v in list(m.items()):
- ret += packUint16(k) + packUint32(v)
- return ret
-
-
- class ReadByteBuffer:
-
- def __init__(self, bytes):
- self.buffer = bytes
- self.position = 0
-
- def unPackUint16(self):
- len = struct.calcsize('H')
- buff = self.buffer[self.position: self.position + len]
- ret = struct.unpack('<H', buff)[0]
- self.position += len
- return ret
-
- def unPackUint32(self):
- len = struct.calcsize('I')
- buff = self.buffer[self.position: self.position + len]
- ret = struct.unpack('<I', buff)[0]
- self.position += len
- return ret
-
- def unPackString(self):
- strlen = self.unPackUint16()
- buff = self.buffer[self.position: self.position + strlen]
- ret = struct.unpack('<' + str(strlen) + 's', buff)[0]
- self.position += strlen
- return ret
-
- def unPackMapUint32(self):
- messages = {}
- maplen = self.unPackUint16()
-
- for index in range(maplen):
- key = self.unPackUint16()
- value = self.unPackUint32()
- messages[key] = value
- return messages
-
-
- def unPackContent(buff):
- readbuf = ReadByteBuffer(buff)
- signature = readbuf.unPackString()
- crc_channel_name = readbuf.unPackUint32()
- crc_uid = readbuf.unPackUint32()
- m = readbuf.unPackString()
-
- return signature, crc_channel_name, crc_uid, m
-
-
- def unPackMessages(buff):
- readbuf = ReadByteBuffer(buff)
- salt = readbuf.unPackUint32()
- ts = readbuf.unPackUint32()
- messages = readbuf.unPackMapUint32()
-
- return salt, ts, messages
-
-
- class AccessToken:
-
- def __init__(self, appID='', appCertificate='', channelName='', uid=''):
- self.appID = appID
- self.appCertificate = appCertificate
- self.channelName = channelName
- self.ts = int(time.time()) + 24 * 3600
- self.salt = secrets.SystemRandom().randint(1, 99999999)
- self.messages = {}
- if (uid == 0):
- self.uidStr = ""
- else:
- self.uidStr = str(uid)
-
- def addPrivilege(self, privilege, expireTimestamp):
- self.messages[privilege] = expireTimestamp
-
- def fromString(self, originToken):
- try:
- dk6version = getVersion()
- originVersion = originToken[:VERSION_LENGTH]
- if (originVersion != dk6version):
- return False
-
- originAppID = originToken[VERSION_LENGTH:(VERSION_LENGTH + APP_ID_LENGTH)]
- originContent = originToken[(VERSION_LENGTH + APP_ID_LENGTH):]
- originContentDecoded = base64.b64decode(originContent)
-
- signature, crc_channel_name, crc_uid, m = unPackContent(originContentDecoded)
- self.salt, self.ts, self.messages = unPackMessages(m)
-
- except Exception as e:
- print("error:", str(e))
- return False
-
- return True
-
- def build(self):
-
- self.messages = OrderedDict(sorted(iter(self.messages.items()), key=lambda x: int(x[0])))
-
- m = packUint32(self.salt) + packUint32(self.ts) \
- + packMapUint32(self.messages)
-
- val = self.appID.encode('utf-8') + self.channelName.encode('utf-8') + self.uidStr.encode('utf-8') + m
-
- signature = hmac.new(self.appCertificate.encode('utf-8'), val, sha256).digest()
- crc_channel_name = crc32(self.channelName.encode('utf-8')) & 0xffffffff
- crc_uid = crc32(self.uidStr.encode('utf-8')) & 0xffffffff
-
- content = packString(signature) \
- + packUint32(crc_channel_name) \
- + packUint32(crc_uid) \
- + packString(m)
-
- version = getVersion()
- ret = version + self.appID + base64.b64encode(content).decode('utf-8')
- return ret
|