Beispiel #1
0
def handle_data(data):

    if len(data) < 24:
        return

    decode_Data = OutputStream(data)

    data_header = MiniDataHead(decode_Data.readBytes(24))

    if data_header.id == 8888:
        data_header.type |= 0x0A

    # 加密种类
    enc_type = data_header.type & 0xF0000000

    # 数据包被DES加密
    if enc_type == 0x10000000:
        plain_data = Des.des(decode_Data.readBytes(decode_Data.available()), globals()['server_key'], False)
        decode_Data.__init__(plain_data)

    # 数据包被RSA_短密钥加密,这种情况暂时未遇到,不能上线正式环境,如果出现,尝试解密后抛出异常以便分析
    if enc_type == 0x20000000:
        if constants.debug == 1:
            assert False, 'RSA!!!'

    # 数据包被AES加密,这种情况暂时未遇到,不能上线正式环境,如果出现,抛出异常以便分析
    if enc_type == 0x70000000:
        if constants.debug == 1:
            assert False, 'AES!!!'

    # 数据包被压缩
    if data_header.type & 0xF000 == 0x1000:
        uncompress_data = snappy.uncompress(decode_Data.readBytes(data_header.pageId))
        data = uncompress_data + decode_Data.readBytes(decode_Data.available())
        decode_Data.__init__(data)

    # 进程数据各类情况,暂时未遇到,先直接无视,以后有时间再完善
    if data_header.id == -3:
        if constants.debug == 1:
            if data_header.type & 15 == 11:
                assert False, 'data_header.id == -3'

    mark = data_header.type & 15  # 采用字典代替switch

    if constants.log == 1:
        print('data_mark={}'.format(mark))

    ret_data = ''

    # 主要包含StuffCurveStruct以及StuffTableStruct两种格式数据的处理
    # StuffCurveStruct应该包含的是股票的详细信息, 这部分暂未完成解析, 感觉用处不大
    # StuffTableStruct包含了除股票信息之类, 比如个人持仓之类的信息
    def case_0():
        nonlocal ret_data
        ret_data = dataHelper.handle_case_0(data_header, decode_Data)

    # 系统消息
    def case_1():
        nonlocal ret_data
        stuffTextData_data = stuffTextData(data_header.type, decode_Data.readBytes(decode_Data.available()))
        ret_data = stuffTextData_data.title + ':' + stuffTextData_data.content

    def case_3():
        nonlocal ret_data
        number = decode_Data.readByte()
        decode_Data.skipBytes(1)
        for _ in range(number):
            dataId = decode_Data.readUnsignedShort()
            ctrlType = decode_Data.readInt()
            colorIndex = decode_Data.readByte()
            content = decode_Data.readUTF()
            ret_data += 'stuffCtrlData:' + 'dataId=' + str(dataId) + ',ctrlType=' + str(ctrlType) + ',colorIndex=' + str(
                colorIndex) + ',content=' + content + '\n'

    # 券商登录成功返回
    def case_4():
        nonlocal ret_data
        if data_header.type == 0x10000004:
            ret_data = '证券登录成功'
            return
        if data_header.type == 0x30000004:
            ret_data = '连接中断'
            return
        ret_data = '证券登录失败'

    # 同花顺连接认证以及登录返回
    def case_6():
        nonlocal ret_data
        content_header = decode_Data.readByte()
        if content_header == 128:
            globals()['qs_login_header'] = decode_Data.readBytes(2)
            data_length = decode_Data.readShort()
            # 这部分数据用于二次登录的使用, 手机上的登录保持就是由于该数据.
            if data_length > 0:
                passport_dat = decode_Data.readBytes(data_length)
                # 写出passport.dat内容, 下一次直接加载登录就可以
                passport_dat = b'\x00\x00' + passport_dat[0:2] + passport_dat
                with open("passport.dat", mode='wb') as f:
                    f.write(passport_dat)
            # 以下数据是服务器返回的帐号登录信息
            data_length = decode_Data.readShort()
            if data_length > 0:
                data_bytes = decode_Data.readBytes(data_length)
                data_str = str(data_bytes, encoding='gbk')
                # 判断一下手机号是否已经登录
                if data_str[-4:] != 'sid=':
                    nonlocal ret_data
                    ret_data = '登录成功'
                    return

            ret_data = decode_Data.readUTF()
            if ret_data == "":
                ret_data = '需要手机号登录'


            # 这部分数据没必要解析, 主要包含sessid以及服务器地址和端口等
            '''
            decode_Data.skipBytes(5)
            data_length = decode_Data.readShort()
            if data_length > 0:
                data_bytes = decode_Data.readBytes(data_length)
                data_str = str(data_bytes, encoding='gbk')
                print('server data: ' + data_str)

            decode_Data.skipBytes(2)
            data_length = decode_Data.readShort()
            if data_length > 0:
                data_bytes = decode_Data.readBytes(data_length)
                data_str = str(data_bytes, encoding='gbk')
                print('server data: ' + data_str)

            data_length = decode_Data.readShort()
            if data_length > 0:
                data_bytes = decode_Data.readBytes(data_length)
                data_str = str(data_bytes, encoding='gbk')
                print('server data: ' + data_str)
            '''

    def case_7():
        nonlocal ret_data
        server_data = decode_Data.readBytes(decode_Data.available())
        ret_data = str(server_data, encoding='gbk')
        if constants.debug == 1:
            assert False, 'case_7'

    def case_9():
        nonlocal ret_data
        server_data = decode_Data.readBytes(decode_Data.available())
        ret_data = str(server_data, encoding='gbk')

    # 同花顺或证券登录成功后返回的个人数据或自选
    def case_11():
        nonlocal ret_data
        server_data = decode_Data.readBytes(data_header.pageId)
        ret_data = str(server_data, encoding='gbk')

    def case_13():
        nonlocal ret_data
        stuffInteractData_data = stuffInteractData(decode_Data.readBytes(decode_Data.available()))
        ret_data = stuffInteractData_data.title + ':' + stuffInteractData_data.content

    def case_15():
        nonlocal ret_data
        stuffTextData_data = stuffTextData(data_header.type, decode_Data.readBytes(decode_Data.available()))
        ret_data = stuffTextData_data.title + ':' + stuffTextData_data.content

    def default():
        nonlocal ret_data
        ret_data = "出错"
        if constants.log == 1:
            print('No such case:' + str(mark))

    # python没有switch, 通过这样的方式曲线救国
    switch = {0: case_0,
              1: case_1,
              3: case_3,
              4: case_4,
              6: case_6,
              7: case_7,
              9: case_9,
              11: case_11,
              13: case_13,
              14: case_15,
              15: case_15,
              }
    switch.get(mark, default)()
    return ret_data, data_header.id