1. 程式人生 > >BCode解碼練習 bittorrent 學習(一) 種子檔案分析與bitmap點陣圖

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>
 8
9 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, long
long& 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)
BCode.h
  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();

}

執行效果如圖: