BCode解碼練習 bittorrent 學習(一) 種子檔案分析與bitmap點陣圖
在學習BT協議中的一個小練習
參考了 https://github.com/airtrack/bitwave
具體B編碼解釋 可以自行搜尋或者參考 這篇文章
bittorrent 學習(一) 種子檔案分析與bitmap點陣圖
程式碼
1 #pragma once 2 #include "pre.h" 3 #include <string> 4 #include <vector> 5 #include <iostream> 6 #include <list> 7 #include <map> 8BCode.h9 NAMESPACE(DEF) 10 11 class BCode 12 { 13 public: 14 enum BCODE_TYPE { 15 BCODE_BASE_TYPE = 1, 16 BCODE_STRING_TYPE = 3, 17 BCODE_INTENGER_TYPE = 5, 18 BCODE_LIST_TYPE = 7, 19 BCODE_DICT_TYPE = 9 20 }; 21 22 BCode(BCODE_TYPE type);23 BCODE_TYPE GetBCodeType()const { return type_; } 24 virtual ~BCode(); 25 26 protected: 27 BCODE_TYPE type_; 28 long long begin_; 29 long long end_; 30 }; 31 32 33 class BCodeString :public BCode { 34 public: 35 explicit BCodeString(long long& begin, longlong& end, 36 const std::vector<char>& data); 37 38 bool ReadString(long long& begin,long long& end,int stringLen ); 39 int ReadStringLen(long long& begin, long long& end); 40 std::string std_string() { return bcodeStr_; } 41 private: 42 const std::vector<char>& data_; 43 std::string bcodeStr_; 44 }; 45 46 class BCodeIntenger :public BCode { 47 public: 48 explicit BCodeIntenger(long long& begin, long long& end, 49 const std::vector<char>& data); 50 51 private: 52 const std::vector<char>& data_; 53 long long bcodeInt_; 54 }; 55 56 class BCodeList :public BCode { 57 public: 58 typedef std::list<std::shared_ptr<BCode>> BCodeLists; 59 explicit BCodeList(long long& begin, long long& end, 60 const std::vector<char>& data); 61 62 private: 63 BCodeList(const BCodeList&) = delete; 64 BCodeList& operator=(const BCodeList&) = delete; 65 BCodeLists bcodeList_; 66 const std::vector<char>& data_; 67 }; 68 69 class BCodeDictionary :public BCode { 70 public: 71 typedef std::map<std::string, std::shared_ptr<BCode> > BCodemap; 72 typedef BCodemap::value_type pair_type; 73 74 explicit BCodeDictionary(long long& begin, long long& end, 75 const std::vector<char>& data); 76 private: 77 BCodeDictionary(const BCodeDictionary&) = delete; 78 BCodeDictionary& operator=(const BCodeDictionary&) = delete; 79 const std::vector<char>& data_; 80 BCodemap bcodeMap_; 81 }; 82 83 84 85 std::shared_ptr<BCode> GetBCodeObject(long long& begin, 86 long long& end,const std::vector<char>& data); 87 88 89 90 NAMESPACEEND(DEF)
1 #include "BCode.h" 2 3 NAMESPACE(DEF) 4 5 BCode::BCode(BCODE_TYPE type) 6 :type_(type),begin_(0),end_(0){} 7 8 9 BCode::~BCode(){} 10 11 12 bool BCodeString::ReadString( 13 long long& begin, 14 long long& end, 15 int stringLen) 16 { 17 bool b = false; 18 long long stringEnd = begin + stringLen; 19 if (stringEnd > end) { 20 std::cerr << __FUNCTION__ << ". string range error!" << std::endl; 21 return b; 22 } 23 bcodeStr_.assign(&data_[begin], stringLen); 24 begin = stringEnd; 25 #ifdef _DEBUG_PRINT 26 std::cout << __FUNCTION__ << ". BCodeString = " 27 << bcodeStr_ << std::endl; 28 29 #endif // DEBUG 30 31 b = true; 32 return b; 33 } 34 35 BCodeString::BCodeString(long long& begin, long long& end, 36 const std::vector<char>& data) 37 :bcodeStr_(), BCode(BCODE_STRING_TYPE), data_(data) 38 { 39 begin_ = begin; 40 int stringLen = ReadStringLen(begin, end); 41 if (stringLen <= 0 || begin >= end || data_[begin] != ':') { 42 std::cerr << __FUNCTION__ << ". string length error!" << std::endl; 43 return; 44 } 45 begin++; 46 ReadString(begin, end, stringLen); 47 end_ = begin; 48 } 49 50 51 int BCodeString::ReadStringLen( 52 long long& begin, 53 long long& end) 54 { 55 std::vector<char> tmp; 56 if (isdigit(data_[begin]) == 0) { 57 std::cerr << __FUNCTION__ << ". read num error!" << std::endl; 58 return 0; 59 } 60 while (begin != end && isdigit(data_[begin])) { 61 tmp.push_back(data_[begin++]); 62 } 63 return atoi(&tmp[0]); 64 } 65 66 BCodeIntenger::BCodeIntenger(long long& begin, long long& end, 67 const std::vector<char>& data) 68 :bcodeInt_(), BCode(BCODE_INTENGER_TYPE), data_(data) 69 { 70 begin_ = begin; 71 if (begin >= end || data_[begin] != 'i') { 72 std::cerr << __FUNCTION__ << ". intenger flag error!" << std::endl; 73 return; 74 } 75 ++begin; //skip 'i' 76 77 std::string intstr; 78 std::vector<char> tmp; 79 while (begin != end && data_[begin] != 'e' ) { 80 if (!isdigit(data_[begin])) { 81 std::cerr << __FUNCTION__ << ". get intenger error!" << std::endl; 82 return; 83 } 84 tmp.push_back(data_[begin++]); 85 } 86 end_ = begin; 87 ++begin; //skip 'e' 88 if (begin > end) { 89 std::cerr << __FUNCTION__ << ". range error!" << std::endl; 90 return; 91 } 92 93 bcodeInt_ = _atoi64(&tmp[0]); 94 95 #ifdef _DEBUG_PRINT 96 std::cout << __FUNCTION__ << ". BCodeIntenger = " 97 << bcodeInt_ << std::endl; 98 #endif // DEBUG 99 } 100 101 BCodeList::BCodeList(long long& begin, long long& end, 102 const std::vector<char>& data) 103 :bcodeList_(), BCode(BCODE_LIST_TYPE),data_(data) 104 { 105 begin_ = begin; 106 if (begin >= end || data_[begin] != 'l') { 107 std::cerr << __FUNCTION__ << ". BCodeList error!" << std::endl; 108 return; 109 } 110 ++begin; 111 #ifdef _DEBUG_PRINT 112 std::cout << "start List" << std::endl; 113 #endif // _DEBUG 114 115 while (begin != end && data_[begin] != 'e') { 116 bcodeList_.push_back(GetBCodeObject(begin,end,data_)); 117 } 118 end_ = begin; 119 if (begin >= end || data[end_] != 'e' ) { 120 std::cerr << __FUNCTION__ << ". BCodeList end error!" << std::endl; 121 return; 122 } 123 124 ++begin; 125 #ifdef _DEBUG_PRINT 126 std::cout << "end List" << std::endl; 127 #endif // _DEBUG 128 } 129 130 BCodeDictionary::BCodeDictionary(long long& begin, long long& end, 131 const std::vector<char>& data) 132 :bcodeMap_(), BCode(BCODE_DICT_TYPE), data_(data) 133 { 134 begin_ = begin; 135 if (begin >= end || data_[begin] != 'd') { 136 std::cerr << __FUNCTION__ << ". range error!" << std::endl; 137 return; 138 } 139 ++begin; //skip 'd' 140 #ifdef _DEBUG_PRINT 141 std::cout << "dict start " << std::endl; 142 #endif 143 while (begin != end && data[begin] != 'e') { 144 #ifdef _DEBUG_PRINT 145 std::cout << "key is "; 146 #endif 147 BCodeString key(begin, end,data); 148 std::shared_ptr<BCode> value = GetBCodeObject(begin,end,data); 149 if (value) { 150 bcodeMap_.insert(BCodemap::value_type(key.std_string(), value)); 151 } 152 } 153 #ifdef _DEBUG_PRINT 154 std::cout << "dict end " << std::endl; 155 #endif 156 end_ = begin; 157 if (begin >= end || data[end_] != 'e') { 158 std::cerr << __FUNCTION__ << ". BCodeDictionary end error!" << std::endl; 159 return; 160 } 161 ++begin; //skip 'e' 162 163 164 return; 165 } 166 167 std::shared_ptr<BCode> GetBCodeObject(long long& begin, 168 long long& end, const std::vector<char>& data) { 169 if (begin >= end || end > data.size()) { 170 std::cerr << __FUNCTION__ << ". Range error!" << std::endl; 171 return NULL; 172 } 173 174 switch (data[begin]) { 175 case 'i': 176 return std::shared_ptr<BCode>(new BCodeIntenger(begin, end, data)); 177 case 'l': 178 return std::make_shared<BCode>(BCodeList(begin, end, data)); 179 case 'd': 180 return std::make_shared<BCode>(BCodeDictionary(begin,end,data)); 181 default: 182 return std::make_shared<BCode>(BCodeString(begin, end, data)); 183 } 184 185 186 187 } 188 189 NAMESPACEEND(DEF)BCode.cpp
測試程式碼
#include <iostream>
#include "MetaFIleManager.h"
#include "BCode.h"
using namespace DEF;
void BCodetest() {
std::string s = "li1234e8:12345678l3:def3:abce4:1234i56789ee";
//std::string s = "8:123456783:def2:121:a";
std::vector<char> test(s.begin(), s.end());
long long size = test.size();
long long idx0 = 0;
//while (idx0 < size) {
std::shared_ptr<BCode> p = GetBCodeObject(idx0, size, test);
//}
std::cout << std::endl << std::endl;;
std::string s1 = "d4:key1d9:innerKey14:teste9:innerkey2li23456ei1234ei45678eee";
std::vector<char> test1(s1.begin(), s1.end());
long long size1 = test1.size();
long long idx1 = 0;
std::shared_ptr<BCode> p1 = GetBCodeObject(idx1, size1, test1);
}
int main()
{
BCodetest();
}
執行效果如圖: