mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 10:45:57 +01:00
Allow asking whether segment was acked
This commit is contained in:
@@ -129,6 +129,14 @@ public:
|
||||
* \brief Retrieves all acked intervals by Selective ACKs
|
||||
*/
|
||||
const interval_set_type& acked_intervals() const;
|
||||
|
||||
/**
|
||||
* \brief Indicates whether the given segment has been already ACKed
|
||||
*
|
||||
* \param sequence_number The segment's sequence number
|
||||
* \param length The segment's length
|
||||
*/
|
||||
bool is_segment_acked(uint32_t sequence_number, uint32_t length) const;
|
||||
private:
|
||||
void process_sack(const std::vector<uint32_t>& sack);
|
||||
void cleanup_sacked_intervals(uint32_t old_ack, uint32_t new_ack);
|
||||
|
||||
@@ -282,6 +282,18 @@ public:
|
||||
* \brief Indicates whether ACK number tracking is enabled
|
||||
*/
|
||||
bool ack_tracking_enabled() const;
|
||||
|
||||
#ifdef HAVE_ACK_TRACKER
|
||||
/**
|
||||
* Retrieves the ACK tracker for this Flow (const)
|
||||
*/
|
||||
const AckTracker& ack_tracker() const;
|
||||
|
||||
/**
|
||||
* Retrieves the ACK tracker for this Flow
|
||||
*/
|
||||
AckTracker& ack_tracker();
|
||||
#endif // HAVE_ACK_TRACKER
|
||||
private:
|
||||
// Compress all flags into just one struct using bitfields
|
||||
struct flags {
|
||||
|
||||
@@ -38,11 +38,23 @@
|
||||
using std::vector;
|
||||
using std::numeric_limits;
|
||||
|
||||
using boost::icl::interval_bounds;
|
||||
using boost::icl::contains;
|
||||
|
||||
using Tins::Internals::seq_compare;
|
||||
|
||||
namespace Tins {
|
||||
namespace TCPIP {
|
||||
|
||||
uint32_t interval_end(const AckedRange::interval_type& interval) {
|
||||
if (interval.bounds() == interval_bounds::right_open()) {
|
||||
return interval.upper() - 1;
|
||||
}
|
||||
else {
|
||||
return interval.upper();
|
||||
}
|
||||
}
|
||||
|
||||
// AckedRange
|
||||
|
||||
AckedRange::AckedRange(uint32_t first, uint32_t last)
|
||||
@@ -140,6 +152,22 @@ const AckTracker::interval_set_type& AckTracker::acked_intervals() const {
|
||||
return acked_intervals_;
|
||||
}
|
||||
|
||||
bool AckTracker::is_segment_acked(uint32_t sequence_number, uint32_t length) const {
|
||||
if (length == 0) {
|
||||
return true;
|
||||
}
|
||||
AckedRange range(sequence_number, sequence_number + length - 1);
|
||||
while (range.has_next()) {
|
||||
AckedRange::interval_type interval = range.next();
|
||||
const int comparison = seq_compare(interval_end(interval), ack_number_);
|
||||
// Only check for SACKed intervals if the segment finishes after our ACK number
|
||||
if (comparison >= 0 && !contains(acked_intervals_, interval)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // TCPIP
|
||||
} // Tins
|
||||
|
||||
|
||||
@@ -319,6 +319,17 @@ bool Flow::ack_tracking_enabled() const {
|
||||
return flags_.ack_tracking;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ACK_TRACKER
|
||||
const AckTracker& Flow::ack_tracker() const {
|
||||
return ack_tracker_;
|
||||
}
|
||||
|
||||
AckTracker& Flow::ack_tracker() {
|
||||
return ack_tracker_;
|
||||
}
|
||||
|
||||
#endif // HAVE_ACK_TRACKER
|
||||
|
||||
} // TCPIP
|
||||
} // Tins
|
||||
|
||||
|
||||
@@ -601,9 +601,14 @@ TEST_F(AckTrackerTest, AckedRange_WrapAround) {
|
||||
|
||||
TEST_F(AckTrackerTest, AckingTcp1) {
|
||||
AckTracker tracker(0, false);
|
||||
EXPECT_EQ(0, tracker.ack_number());
|
||||
EXPECT_EQ(0, tracker.ack_number());
|
||||
tracker.process_packet(make_tcp_ack(100));
|
||||
EXPECT_EQ(100, tracker.ack_number());
|
||||
EXPECT_TRUE(tracker.is_segment_acked(0, 10));
|
||||
EXPECT_TRUE(tracker.is_segment_acked(50, 10));
|
||||
EXPECT_TRUE(tracker.is_segment_acked(99, 1));
|
||||
EXPECT_FALSE(tracker.is_segment_acked(90, 20));
|
||||
EXPECT_FALSE(tracker.is_segment_acked(99, 2));
|
||||
tracker.process_packet(make_tcp_ack(50));
|
||||
EXPECT_EQ(100, tracker.ack_number());
|
||||
tracker.process_packet(make_tcp_ack(150));
|
||||
@@ -635,6 +640,9 @@ TEST_F(AckTrackerTest, AckingTcp_Sack1) {
|
||||
AckTracker tracker(0, true);
|
||||
tracker.process_packet(make_tcp_ack(0, make_pair(2, 5), make_pair(9, 11)));
|
||||
EXPECT_EQ(3 + 2, tracker.acked_intervals().size());
|
||||
EXPECT_TRUE(tracker.is_segment_acked(2, 3));
|
||||
EXPECT_TRUE(tracker.is_segment_acked(9, 2));
|
||||
EXPECT_FALSE(tracker.is_segment_acked(2, 9));
|
||||
|
||||
tracker.process_packet(make_tcp_ack(9));
|
||||
EXPECT_EQ(1, tracker.acked_intervals().size());
|
||||
@@ -652,6 +660,10 @@ TEST_F(AckTrackerTest, AckingTcp_Sack2) {
|
||||
make_pair(0, 10)
|
||||
));
|
||||
EXPECT_EQ(3 + 10, tracker.acked_intervals().size());
|
||||
EXPECT_TRUE(tracker.is_segment_acked(maximum - 12, 2));
|
||||
EXPECT_TRUE(tracker.is_segment_acked(maximum - 2, 1));
|
||||
EXPECT_TRUE(tracker.is_segment_acked(2, 3));
|
||||
EXPECT_FALSE(tracker.is_segment_acked(maximum - 10, 10));
|
||||
|
||||
tracker.process_packet(make_tcp_ack(maximum - 2));
|
||||
EXPECT_EQ(1 + 10, tracker.acked_intervals().size());
|
||||
|
||||
Reference in New Issue
Block a user