classReassembler { ... private: ByteStream output_; // the Reassembler writes to this ByteStream uint64_t next_byte{}; // store the next byte's index aka. first unassembled index classsubstring { public: std::string data{}; uint64_t first_byte{}; bool is_last_substring{}; }; std::list<substring> substrings{}; uint64_tunaccept_index(); // return the first unacceptable byte index uint64_tunpopped_index(); // return the first unpopped byte index uint64_t finish_index = 0xfffffffff; voidupdate(substring &st); // scan the area and push all continous bytes in bytestream };
// in reassembler.cc #include"reassembler.hh" usingnamespace std;
voidReassembler::update(substring &st) { // since we will handler overlap every time, // we assume overlaping substrings dont exist.
// 1.find the pos and insert. list<substring>::iterator it = substrings.begin(); list<substring>::iterator backit = substrings.begin(); list<substring>::iterator fowdit = substrings.begin();
for(; it != substrings.end(); it++) if((*it).first_byte >= st.first_byte) break; it = substrings.insert(it, st);
// 2.check the substring before pos. if(it != substrings.begin()){ backit = it; backit --;
substring t = (*backit); // case 1: st totally inside the substring. delete the st. if((*backit).first_byte + (*backit).data.size() >= st.first_byte + st.data.size()){ substrings.erase(it); goto push; }
// case 2: st overlap part of it. edit the substring. if((*backit).first_byte + (*backit).data.size() < st.first_byte + st.data.size()){ (*backit).data = (*backit).data.substr(0, st.first_byte - (*backit).first_byte); }
// case 3: no overlap. do nothing. }
// 3.check the substring after pos. if(it == substrings.end()) goto push;
fowdit = it; fowdit++; for(; fowdit != substrings.end();){ // case 1: no overlap. if((*fowdit).first_byte >= st.first_byte + st.data.size()) break;
// case 2: st totally inside the substring. delete the st. if((*fowdit).first_byte == st.first_byte && (*fowdit).data.size() >= st.data.size()){ substrings.erase(it); goto push; }
// case 3: substring totally inside the st. delete the substring. if((*fowdit).first_byte + (*fowdit).data.size() <= st.first_byte + st.data.size()){ fowdit = substrings.erase(fowdit); continue; }
// case 4: st overlap part of it. edit the substring. if((*fowdit).first_byte + (*fowdit).data.size() > st.first_byte + st.data.size()){ (*fowdit).data = (*fowdit).data.substr(st.first_byte + st.data.size() - (*fowdit).first_byte); (*fowdit).first_byte = st.first_byte + st.data.size(); } fowdit++; }
push: // 4.scan the list and push possible substrings substring t; while(!substrings.empty()){ t = substrings.front();
// get the finish byte index if(st.is_last_substring){ finish_index = first_index + data.size(); } // if the substring totally outside the available area, discarded. if(first_index + data.size() < next_byte || first_index >= unaccept_index()){ return; }
// if no space for substring, discarded. if(next_byte == unaccept_index()) return;
// if the substring have bytes outside the available area, cut it. // case 1: head outbound. if(st.first_byte < next_byte){ st.data = st.data.substr(next_byte - st.first_byte); st.first_byte = next_byte; }