В нашем назначении мы должны построить наш собственный обработчик TCP (предоставляется структура). Сейчас я нахожусь в той точке, когда мне нужно собрать все сегменты TCP и сохранить их в векторе, чтобы я мог собрать поток после получения последнего сегмента и переслать его на следующий уровень (например, HTTP). Для этого мы должны реализовать void handle_packet()
. В нашей структуре есть несколько структур и классов, которые должны «помочь» нам.
Это то, что я до сих пор придумал:
tcp.h
#include <iostream>
#include <cstdint>
#include <vector>
#include <netinet/tcp.h> // struct tcphdr
using Header = struct tcphdr;
struct Segment {
const Header * hdr;
uint8_t payload[];
};
struct Stream {
std::vector<Segment> segments;
void add_segment(Segment new_segment);
};
void Stream::add_segment(Segment new_segment) {
segments.push_back(new_segment);
// testing: print all sequence numbers of each segment
for(size_t i = 0; i < segments.size(); i++)
std::cout << ntohl(segments[i].hdr->seq) << std::endl;
}
class Protocol {
private:
Stream streams;
public:
void handle_packet(const Header* tcp_segment_hdr, uint8_t* tcp_payload, size_t tcp_payload_len);
};
tcp. cpp
#include "tcp.h"
void handle_packet(const Header* tcp_segment_hdr, uint8_t* tcp_payload, size_t tcp_payload_len) {
// "struct hack" to copy content
Segment* segment = reinterpret_cast<Segment *>(malloc(sizeof(struct Segment) + buffer_len * sizeof(uint8_t)) );
// store the header
segment->hdr = tcp_segment_hdr; // add the header
// store the payload
for(size_t i = 0; i < tcp_payload_len; i++)
segment->payload[i] = tcp_payload[i];
streams.add_segment(*segment);
free(segment);
}
Я копирую заголовок и полезную нагрузку, используя "взлом структуры", в структуру Segment *
(это был единственный рабочий способ, который я придумал). После этого я сохраняю новый сегмент в streams
(член класса Protocol
) переменной-члена vector<Segments>
. Затем я освобождаю память.
После этого я хотел посмотреть, сохранено ли все в segments
(для тестирования я попытался напечатать каждый порядковый номер сегмента) - и это не так. Однако размер по-прежнему правильный.
Я полагаю, это потому, что я free'd
структура в handle_packet()
впоследствии, и это также влияет на мою запись в std::vector<Segment>segments
.. Но как я могу добиться, чтобы записи все еще были в там без каких-либо утечек памяти? Я погуглил, но не нашел удовлетворительного решения, как решить мою проблему.
Любая помощь приветствуется! Спасибо
Редактировать : Я также получаю следующую ошибку в AddressSanitizer:
==22658==ERROR: AddressSanitizer: stack-buffer-overflow on address
0x7fff5288b66c at pc 0x559511b2f7bc bp 0x7fff5288b2b0 sp 0x7fff5288b2a0
WRITE of size 1 at 0x7fff5288b66c thread T0
В IPv4 у нас была следующая структура:
struct Fragment : public std::vector<uint8_t> {
using std::vector<uint8_t>::vector;
const Header *getHeader() { return (const Header *)data(); }
};
Но я этого не делал, так как не мог понять, как «заполнить» значения и добавить запись. Любые идеи, как я могу принять struct Fragment
до struct Segment
и заполнить / добавить (постоянные) значения?
Редактировать 2: В качестве временного результата, я дал полезную нагрузку фиксированного размера (1500) и удалите «struct hack» и отредактируйте его обратно до простого Segment segment
.
Edit 3: Хорошо, он по-прежнему не работает даже с фиксированным размером.
Редактировать 4: Я нашел рабочее решение! Однако я опишу свое решение в субботу (после крайнего срока), чтобы избежать плагиата.