读BitTorrent码日记2

来源:互联网 发布:红蜘蛛软件怎么关 编辑:程序博客网 时间:2024/05/13 05:43

# Written by Bram Cohen
# see LICENSE.txt for license information
# filename:btfield.py btformats.py

# btfield.py
#读码日记:2004-9-1 笔者:
#笔        者:zfive5(醉马不肖 之 [孤舟蓑笠翁, 独钓寒江雪])
#注        释:这个文件主要是进行字节到比特位之间的转化的

 

#功能:主要是实现的列表bits位到byte的转化
#参数:1个逻辑列表 例如:[1,1,0,1,1,1,0,1]
#返回:byte流, 例如:'a/x00'
#效果:
#>>> booleans_to_bitfield([0,1,1,0,0,0,0,1])
#'a'
#>>> booleans_to_bitfield([0,1,1,0,0,0,0,1,0])
#'a/x00'
#
def booleans_to_bitfield(booleans):
    r = []
    for i in xrange(0, len(booleans), 8):
        v = 0
        p = 0x80
        for j in booleans[i:i+8]:
            if j:
                v |= p
            p >>= 1
        r.append(chr(v))
    return ''.join(r)


#功能:主要完成位到byte流到bits列表之间的转化
#参数:byte流,byte个数 例如:'a/x00'
#返回:逻辑bits列表,例如:[False, True, True, False, False, False, False, True]
#效果:
#>>> bitfield_to_booleans('a',8)
#[False, True, True, False, False, False, False, True]
#
def bitfield_to_booleans(bitfield, l):
    extra = len(bitfield) * 8 - l
    if extra < 0 or extra >= 8:
        return None
    r = []
    for c in bitfield:
        v = ord(c)
        for i in xrange(8):
            if v & 0x80 != 0:
                r.append(True)
            else:
                r.append(False)
            v <<= 1
    if extra > 0:
        if r[-extra:] != [0] * extra:
            return None
        del r[-extra:]
    return r

#功能:测试1
def test_basic():
    x = [1, 1, 1, 0, 0, 0, 1, 1, 1]
    y = [1, 1, 1, 0, 0, 0, 1, 1]
    for a in [x, y, []]:
        assert bitfield_to_booleans(booleans_to_bitfield(a), len(a)) == a
       
#功能:测试2
def test_too_long():
    assert bitfield_to_booleans('ab', 8) == None

#功能:测试3
def test_too_short():
    assert bitfield_to_booleans('a', 9) == None
   
#功能:测试4   
def test_nonzero_in_excess():
    assert bitfield_to_booleans(chr(0xFF), 7) == None


# Written by Bram Cohen
# see LICENSE.txt for license information

# btformats.py

from types import StringType, LongType, IntType, ListType, DictType
from re import compile

reg = compile(r'^[^///.~][^///]*$')

ints = [LongType, IntType]

#功能:这里主要是检查种子文件info信息是否合法,其中包括它的子信息,
#如过不合法抛异常,从这个文件里我们可以看出种子文件的info的结构
#  info(DictType){
#          'piecelength':ints(大于零),
#          'pieces':StringType(长度为20个字节的整数倍),
#          'name':StringType(不能是/   *之类的非文件名称字符),
#          'length':ints(大于零,对单个文件) 
#       }
#
#  info(DictType){
#          'piecelength':ints(大于零),
#          'pieces':StringType(长度为20个字节的整数倍),
#          'name':StringType(不能是/   *之类的非文件名称字符),
#          'files'(ListType):[
#                     (DictType)
#                      {
#                     'length':ints(大于零)
#                     'path'(ListType):[ (例如: "1","2","4.txt" 代表 :"/1/2/4.txt"
#                              StringType,
#                              StringType,
#                              StringType,
#                              ....
#                            ]
#                      },
#
#                     (DictType)
                      {
#                     'length':ints(大于零)
#                     'path'(ListType):[
#                              StringType,
#                              StringType,
#                              StringType,
#                              ....
#                            ]
#                      }
#                      ....
#                   ]
#       }
#
#这里顺序可能是种子文件有出入
def check_info(info):
    if type(info) != DictType:
        raise ValueError, 'bad metainfo - not a dictionary'
    pieces = info.get('pieces')
    if type(pieces) != StringType or len(pieces) % 20 != 0:
        raise ValueError, 'bad metainfo - bad pieces key'
    piecelength = info.get('piece length')
    if type(piecelength) not in ints or piecelength <= 0:
        raise ValueError, 'bad metainfo - illegal piece length'
    name = info.get('name')
    if type(name) != StringType:
        raise ValueError, 'bad metainfo - bad name'
    if not reg.match(name):
        raise ValueError, 'name %s disallowed for security reasons' % name
    if info.has_key('files') == info.has_key('length'):
        raise ValueError, 'single/multiple file mix'
    if info.has_key('length'):
        length = info.get('length')
        if type(length) not in ints or length < 0:
            raise ValueError, 'bad metainfo - bad length'
    else:
        files = info.get('files')
        if type(files) != ListType:
            raise ValueError
        for f in files:
            if type(f) != DictType:
                raise ValueError, 'bad metainfo - bad file value'
            length = f.get('length')
            if type(length) not in ints or length < 0:
                raise ValueError, 'bad metainfo - bad length'
            path = f.get('path')
            if type(path) != ListType or path == []:
                raise ValueError, 'bad metainfo - bad path'
            for p in path:
                if type(p) != StringType:
                    raise ValueError, 'bad metainfo - bad path dir'
                if not reg.match(p):
                    raise ValueError, 'path %s disallowed for security reasons' % p
        for i in xrange(len(files)):
            for j in xrange(i):
                if files[i]['path'] == files[j]['path']:
                    raise ValueError, 'bad metainfo - duplicate path'

#功能:这里主要是检查种子文件message信息是否合法,其中包括它的子信息,
#如过不合法抛异常,从这个文件里我们可以看出种子文件的message的结构
#这也是种子的起始地方
#  message(DictType){
#          'info'(DictType):{ check_info(message.get('info'))同上}
#          'announce':StringType
#         }
#这里顺序可能是种子文件有出入
def check_message(message):
    if type(message) != DictType:
        raise ValueError
    check_info(message.get('info'))
    if type(message.get('announce')) != StringType:
        raise ValueError

#功能:这里主要是message信息是否合法,其中包括它的子信息,关于这个结构体,我
#还没有读到能理解的地步,先在这里打一个问号?????
#  message(DictType){
#          'failure reason':{ check_info(message.get('info'))同上}
#          'peers'(ListType):
#                         [
#                            (DictType)
#                            {
#                            'ip':StringType,
#                            'port':ints(大于零),
#                             'peer id':StringType(len(id)==20这里我猜也是sha)
#                            },
#                           
#                            (DictType)
#                            {
#                            'ip':StringType,
#                            'port':ints(大于零),
#                            'peer id':StringType(len(id)==20这里我猜也是sha)
#                            }
#                            ...                           
#
#                         ]
#           ‘interval’:ints(大于零),
#           'min interval':ints(大于零),
#           'tracker id':StringType,
#           'num peers':ints(大于零),
#           'done peers':ints(大于零),
#           'last':ints(大于零)
#         }
#这里顺序可能是实际顺序不出入
def check_peers(message):
    if type(message) != DictType:
        raise ValueError
    if message.has_key('failure reason'):
        if type(message['failure reason']) != StringType:
            raise ValueError
        return
    peers = message.get('peers')
    if type(peers) != ListType:
        raise ValueError
    for p in peers:
        if type(p) != DictType:
            raise ValueError
        if type(p.get('ip')) != StringType:
            raise ValueError
        port = p.get('port')
        if type(port) not in ints or p <= 0:
            raise ValueError
        id = p.get('peer id')
        if type(id) != StringType or len(id) != 20:
            raise ValueError
    interval = message.get('interval', 1)
    if type(interval) not in ints or interval <= 0:
        raise ValueError
    minint = message.get('min interval', 1)
    if type(minint) not in ints or minint <= 0:
        raise ValueError
    if type(message.get('tracker id', '')) != StringType:
        raise ValueError
    npeers = message.get('num peers', 0)
    if type(npeers) not in ints or npeers < 0:
        raise ValueError
    dpeers = message.get('done peers', 0)
    if type(dpeers) not in ints or dpeers < 0:
        raise ValueError
    last = message.get('last', 0)
    if type(last) not in ints or last < 0:
        raise ValueError

#写到这里大家明白bt种子文件的结构了吧!!
#(待续)

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华普超市购物卡怎么办 公司发超市购物卡怎么办 物美购物卡丢了怎么办 淘宝买肯德基电子券留错号码怎么办 京东e卡过期了怎么办 京东e卡绑定错了怎么办 手机换号京东账号绑的银行卡怎么办 京东金条激活失败怎么办 京东买的k3不能激活怎么办 优购手机光黑屏怎么办 优购手机忘记手势密码怎么办 消费卡过期了钱怎么办 超市卡过期了钱怎么办 宜家购物卡的钱怎么办 武商购物卡过期怎么办 丹尼斯卡过期了怎么办 联华ok卡过期了怎么办 汉购通过期了怎么办 天猫退货要检测报告怎么办 京东退货后发票怎么办 京东金融被盗刷怎么办 京东e卡丢了怎么办 京东e卡没有密码怎么办 同一个订单微信付款两次怎么办 京东购物卡掉了怎么办 京东购物卡丢了怎么办 京东快递丢了怎么办 京东e卡支付多了怎么办 京东帐号忘了怎么办 京东白条风控怎么办 我有个破袄…没有衣服怎么办办 轩辕传奇手游灵宠融合错了怎么办 各尧学生不能用怎么办? 山东一卡通商务卡丢了怎么办 和信通过期了怎么办 和信通过期怎么办延期 和信通过期余额怎么办 超市储蓄卡丢了怎么办 提现提到注销卡怎么办 美通卡过期2年了怎么办 物美美通卡丢失怎么办