1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Feature - Skipping ahead in TCP flows. (#163)

* Skipping forward in TCP streams, from an out-of-order callback.

- Added the ability to skip forward in a flow to a sequence number, with the intention of doing so in an out of order callback.
- Re-ordered Flow packet processing, to allow skipTo in out of order callback on stream start (flow sequence number is 0).
- Fixed missing seq_compare in flow code.

* Renamed skipTo to advance_sequence.
This commit is contained in:
Patrick Michel
2016-10-23 18:47:56 +02:00
committed by Matias Fontanini
parent 2e013847d9
commit aaba3dd46a
4 changed files with 75 additions and 14 deletions

View File

@@ -87,6 +87,29 @@ public:
*/
bool process_payload(uint32_t seq, payload_type payload);
/**
* \brief Skip forward to a sequence number
*
* This allows to recover from packetloss, if we just do not see all packets of
* an original stream. This recovery can only sensibly triggered from the application
* layer.
*
* The method does nothing, if the sequence number is smaller or equal to the
* current number.
*
* This method is particularly useful to call from an out of order callback, if
* the application wants to skip forward to this out of order block. The application
* will then get the normal data callback!
*
* The method cleans the buffer from all no longer needed fragments.
*
* IMPORTANT: If you call this method with a sequence number that is not exactly a
* TCP fragment boundary, the flow will never recover from this.
*
* \param seq The seqeunce number to skip to.
*/
void advance_sequence(uint32_t seq);
/**
* Retrieves the current sequence number
*/

View File

@@ -165,6 +165,24 @@ public:
*/
void process_packet(PDU& pdu);
/**
* \brief Skip forward to a sequence number
*
* This allows to recover from packet loss, if we just do not see all packets of
* an original stream. This recovery can only sensibly triggered from the application
* layer.
*
* This method is particularly useful to call from an out of order callback, if
* the application wants to skip forward to this out of order block. The application
* will then get the normal data callback!
*
* IMPORTANT: If you call this method with a sequence number that is not exactly a
* TCP fragment boundary, the flow will never recover from this.
*
* \param seq The sequence number to skip to.
*/
void advance_sequence(uint32_t seq);
/**
* Indicates whether this flow uses IPv6 addresses
*/

View File

@@ -108,6 +108,23 @@ bool DataTracker::process_payload(uint32_t seq, payload_type payload) {
return added_some;
}
void DataTracker::advance_sequence(uint32_t seq) {
if (seq_compare(seq, seq_number_) <= 0) {
return;
}
for (auto it = buffered_payload_.begin(); it != buffered_payload_.end();) {
if (seq_compare(it->first, seq) <= 0) {
total_buffered_bytes_ -= it->second.size();
it = buffered_payload_.erase(it);
} else {
it++;
}
}
seq_number_ = seq;
}
uint32_t DataTracker::sequence_number() const {
return seq_number_;
}

View File

@@ -110,22 +110,25 @@ void Flow::process_packet(PDU& pdu) {
}
const uint32_t chunk_end = tcp->seq() + raw->payload_size();
const uint32_t current_seq = data_tracker_.sequence_number();
// If the end of the chunk ends after our current sequence number, process it.
if (seq_compare(chunk_end, current_seq) >= 0) {
uint32_t seq = tcp->seq();
// If we're going to buffer this and we have a buffering callback, execute it
if (seq > current_seq && on_out_of_order_callback_) {
on_out_of_order_callback_(*this, seq, raw->payload());
// If the end of the chunk ends before the current sequence number or
// if we're going to buffer this and we have a buffering callback, execute it
if (seq_compare(chunk_end, current_seq) < 0 ||
seq_compare(tcp->seq(), current_seq) > 0){
if (on_out_of_order_callback_) {
on_out_of_order_callback_(*this, tcp->seq(), raw->payload());
}
if (data_tracker_.process_payload(seq, move(raw->payload()))) {
}
// can process either way, since it will abort immediately if not needed
if (data_tracker_.process_payload(tcp->seq(), move(raw->payload()))) {
if (on_data_callback_) {
on_data_callback_(*this);
}
}
}
else if (on_out_of_order_callback_) {
on_out_of_order_callback_(*this, tcp->seq(), raw->payload());
}
}
void Flow::advance_sequence(uint32_t seq) {
data_tracker_.advance_sequence(seq);
}
void Flow::update_state(const TCP& tcp) {