Torrent文件

    技术2022-05-11  65

     BitTorrent下载时,用户必须下载一个.torrent文件,它就是所谓"Metainfo file",里面存储有关于下载内容的announce地址,长度,大小,SHA1杂凑项等内容。它由Bencode编码组成.而且字符串是用UTF-8编码的。不过在中国,常常使用GBK编码。它由如下几项组成: Info:描述下载内容的信息,是一个字典.有两种可能,一种是"单文件"模式:当BitTorrent只下载一个文件的时候使用.另一种是"多文件"模式,是在下载多个内容的时候使用.两种情况下Info各有不同.          单文件模式: length:整数,指文件的大小.  md5sum:(可选),字符串,含有32字节md5校验码.BitTorrent没有使用MD5而是使用了SHA1作为自已的签名算法.这是为其他P2P软件兼容而设置的可选内容.  name:字符串,这是下载文件的名字,纯粹是建议.  piece length:整数,是BitTorrent文件块的大小.  pieces:字符串,连续的存放着所有块的SHA1杂凑值,每一个文件块的杂凑值为20字节.          多文件模式: files: 一个由字典组成的列表,每个字典表示一个文件,字典的键值有如下内容:  length:整数,指当前文件的大小.  md5sum:(可选),字符串,同单文件模式,指当前文件.  path:由字符串组成的列表,每个列表元素指一个路径名中的一个目录或文件名.比如说:"l3:abc3:abc:6abc.txte",指文件路径"abc/abc/abc.txt". name:字符串,BitTorrent下载路径中最上层的目录名  piece length:整数,是BitTorrent文件块的大小.  pieces:字符串,连续的存放着所有块的SHA1杂凑值,每一个文件块的杂凑值为20字节. announce:字符串,指向tracker的URL.  announce-list:(可选),字典,这是一个对官方协议的扩展,支持"多Tracker".  creation date:(可选),整数,创建日期(UNIX创世纪格式:1970-1-1日00:00UTC到当时的秒数)  comment:(可选),字符串,注释  created by:可选,字符串,创建此.torrent文件的BT下载端程序名和版本号  encoding:BitComet对Metafile的扩展,一般用来指出不使用utf-8而使用gbk.

      具体文件结构如下: 全部内容必须都为bencoding编码类型。 整个文件为一个字典结构,包含如下关键字 announce:tracker服务器的URL(字符串) announce-list(可选):备用tracker服务器列表(列表) creation date(可选):种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数) comment(可选):备注(字符串) created by(可选):创建人或创建程序的信息(字符串)  info:一个字典结构,包含文件的主要信息,为分二种情况:单文件结构或多文件结构 单文件结构如下:       length:文件长度,单位字节(整数)       md5sum(可选):长32个字符的文件的MD5校验和,BT不使用这个值,只是为了兼容一些程序所保留!(字符串)       name:文件名(字符串)       piece length:每个块的大小,单位字节(整数)       pieces:每个块的20个字节的SHA1 Hash的值(二进制格式) 多文件结构如下:       files:一个字典结构           length:文件长度,单位字节(整数)           md5sum(可选):同单文件结构中相同          path:文件的路径和名字,是一个列表结构,如/test/test.txt 列表为l4:test8test.txte 

    程序如下:

    class CBTCode{public: CBTCode(); ~CBTCode();public: BOOL   BTEnCode(const BYTE* pData, int nLeftLen); BOOL   BTDeCode(BYTE* pData, int nLeftLen); BTItemType  GetType(); void   SetType(BTItemType ItemType); CBTBaseItem* GetValue(); void   SetValue(CBTBaseItem*  pBaseItem); int    GetBufSize();private: BOOL         BTEnCode(const BYTE* pData, int nLeftLen, int& nLen); BOOL         BTDeCode(BYTE* pData, int nLeftLen, int& nLen);private: BTItemType    m_ItemType; union {  CBTIntItem*   m_pBTInt;  CBTStrItem*   m_pBTStr;  CBTListItem*  m_pBTList;  CBTDicItem*   m_pBTDic; };

    };

    CBTCode::CBTCode(){ m_ItemType = BT_ITEM_UNKNOWN;}

    CBTCode::~CBTCode(){ switch(m_ItemType) { case BT_ITEM_INT:  m_pBTInt->Release();  break; case BT_ITEM_STR:  m_pBTStr->Release();  break; case BT_ITEM_LIST:  m_pBTList->Release();  break; case BT_ITEM_DIC:  m_pBTDic->Release();  break; default:  break; }}

    void CBTCode::SetType(BTItemType ItemType){ m_ItemType = ItemType;}

    BTItemType CBTCode::GetType(){ return m_ItemType;}

    void CBTCode::SetValue(CBTBaseItem* pBaseItem){ switch(m_ItemType) { case BT_ITEM_INT:  m_pBTInt = (CBTIntItem*)pBaseItem;  m_pBTInt->AddRef();  break; case BT_ITEM_STR:  m_pBTStr = (CBTStrItem*)pBaseItem;  m_pBTStr->AddRef();  break; case BT_ITEM_LIST:  m_pBTList = (CBTListItem*)pBaseItem;  m_pBTList->AddRef();  break; case BT_ITEM_DIC:  m_pBTDic = (CBTDicItem*)pBaseItem;  m_pBTDic->AddRef(); default:  break; }}

    CBTBaseItem* CBTCode::GetValue(){ switch(m_ItemType) { case BT_ITEM_INT:  return m_pBTInt; case BT_ITEM_STR:  return m_pBTStr; case BT_ITEM_LIST:  return m_pBTList; case BT_ITEM_DIC:  return m_pBTDic; default:  return NULL; }}

    int CBTCode::GetBufSize(){ switch(m_ItemType) { case BT_ITEM_INT:  return m_pBTInt->GetBufSize(); case BT_ITEM_STR:  return m_pBTStr->GetBufSize(); case BT_ITEM_LIST:  return m_pBTList->GetBufSize(); case BT_ITEM_DIC:  return m_pBTDic->GetBufSize(); default:  return 0; }}

    //传内存的大小BOOL CBTCode::BTEnCode(const BYTE* pData, int nLeftLen){ if (NULL == pData || *pData == 0 || nLeftLen <= 1)  return FALSE; int nLen = 0; const BYTE* pTemp = pData; BOOL bRes = BTEnCode(pTemp, nLeftLen, nLen); if (bRes && nLeftLen == nLen)  return TRUE; return FALSE;}

    BOOL CBTCode::BTEnCode(const BYTE* pData, int nLeftLen, int& nLen){ const BYTE* pTemp = pData; switch(*pTemp++) { case 'i':  {   char nVal[50] = {0};   int i = 0;   while(*pTemp >= '0' && *pTemp <= '9')   {    nVal[i++] = *pTemp++;   }   if (*pTemp == 'e')   {    m_ItemType = BT_ITEM_INT;    m_pBTInt = new CBTIntItem;    m_pBTInt->SetValue(_atoi64(nVal));    nLen = pTemp - pData + 1;     //加1的原因是*pTemp = 'e'    return TRUE;   }   else   {    return FALSE;   }  } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':  {   pTemp--;   char nVal[50] = {0};   int i = 0;   while(*pTemp >= '0' && *pTemp <= '9')   {    nVal[i++] = *pTemp++;   }   int nStrLen = atoi(nVal);      if (*pTemp == ':')   {    pTemp++;    m_ItemType = BT_ITEM_STR;    m_pBTStr = new CBTStrItem;        m_pBTStr->SetValue(string((char*)pTemp, nStrLen));    pTemp = pTemp + nStrLen;    nLen = pTemp - pData;      //字符串不是以e结束    return TRUE;   }   else   {    return FALSE;   }  } case 'l':  {   m_ItemType = BT_ITEM_LIST;   m_pBTList = new CBTListItem;   int nTempLen = 0;   int nTempLeft = nLeftLen - 1;   while(*pTemp != 0 && *pTemp != 'e')   {    CBTCode btCode;        if (!btCode.BTEnCode(pTemp, nTempLeft, nTempLen))        return FALSE;    nTempLeft = nTempLeft - nTempLen;    pTemp = pTemp + nTempLen;        CBTBaseItem* pValue = btCode.GetValue();    m_pBTList->AddValue(pValue);   }   if (*pTemp == 'e')   {    nLen = pTemp - pData + 1;    return TRUE;   }   else   {    return FALSE;   }  } case 'd':  {   m_ItemType = BT_ITEM_DIC;   m_pBTDic = new CBTDicItem;   int nTempLen =0;   int nTempLeft = nLeftLen - 1;   while(*pTemp != 0 && *pTemp != 'e')   {    CBTCode key;    if (!key.BTEnCode(pTemp, nTempLeft, nTempLen) || key.GetType() != BT_ITEM_STR)     return FALSE;    nTempLeft = nTempLeft - nTempLen;    pTemp = pTemp + nTempLen;    CBTCode value;    if (!value.BTEnCode(pTemp, nTempLeft, nTempLen))     return FALSE;    nTempLeft = nTempLeft - nTempLen;    pTemp = pTemp + nTempLen;        CBTStrItem* pKey = (CBTStrItem*)key.GetValue();    CBTBaseItem* pValue = value.GetValue();    m_pBTDic->AddValue(pKey->GetValue(), pValue);   }   if (*pTemp == 'e')   {    nLen = pTemp - pData + 1;    return TRUE;   }   else   {    return FALSE;   }  }   } return FALSE;}

    //将数据结构内的值写到pData上BOOL CBTCode::BTDeCode(BYTE* pData, int nLeftLen){ BYTE* pTemp = pData; int nLen = 0; return BTDeCode(pTemp, nLeftLen, nLen);}

    BOOL CBTCode::BTDeCode(BYTE* pData, int nLeftLen, int& nLen){ if (nLeftLen == 0)  return TRUE; BYTE* pTemp = pData; switch(m_ItemType) { case BT_ITEM_INT:  {   sprintf((char*)pTemp, "i%I64d", m_pBTInt->GetValue());   pTemp += strlen((char*)pTemp);   *pTemp++ = 'e';   nLen = pTemp - pData;   if (m_pBTInt->GetBufSize() != nLen)    return FALSE;   return TRUE;  } case BT_ITEM_STR:  {   int strLen = m_pBTStr->GetValue().size();   sprintf((char*)pTemp, "%d:", strLen);   pTemp += Int2String(strLen).size() + 1;   memcpy(pTemp, m_pBTStr->GetValue().c_str(), strLen);   pTemp += strLen;   nLen = pTemp - pData;   if (m_pBTStr->GetBufSize() != nLen)    return FALSE;   return TRUE;  } case BT_ITEM_LIST:  {   *pTemp++ = 'l';   nLeftLen--;   int AllLen = 0;   int nTempLen = 0;   for (int index = 0; index < m_pBTList->GetSize(); ++index)   {     nTempLen = 0;    CBTBaseItem* pBase = m_pBTList->GetValue(index);    CBTCode btCode;    btCode.SetType(pBase->GetItemType());    btCode.SetValue(pBase);    if (!btCode.BTDeCode(pTemp, nLeftLen - nTempLen, nTempLen))     return FALSE;    pTemp += nTempLen;    AllLen += nTempLen;   }   *pTemp++ = 'e';   nLeftLen--;   nLen = pTemp - pData;   if (m_pBTList->GetBufSize() != AllLen + 2)    return FALSE;   return TRUE;  } case BT_ITEM_DIC:  {   *pTemp++ = 'd';   nLeftLen--;   int nTempLen = 0;   int nTempLeft = 0;   for (Map::iterator pos = m_pBTDic->m_MapValue.begin(); pos != m_pBTDic->m_MapValue.end(); ++pos)   {    nTempLeft = 0;    nTempLen = 0;    string strKey(pos->first);    int strLen = strKey.size();    sprintf((char*)pTemp, "%d:", strLen);    nTempLeft += Int2String(strLen).size() + 1;    pTemp += nTempLeft;    memcpy(pTemp, strKey.c_str(), strLen);    pTemp += strLen;     //字符串个数    nTempLeft += strLen;        CBTBaseItem * pBase = pos->second;    CBTCode btCode;    btCode.SetType(pBase->GetItemType());    btCode.SetValue(pBase);    if (!btCode.BTDeCode(pTemp, nLeftLen - nTempLeft, nTempLen))     return FALSE;    pTemp += nTempLen;   }   *pTemp++ = 'e';   nLeftLen--;   nLen = pTemp - pData;   if (m_pBTDic->GetBufSize() != nLen)    return FALSE;   return TRUE;  } default:  break; } return FALSE;}

     

     


    最新回复(0)