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

Refactored code related to stream/flow initialization. (#170)

- Removed client_flow().process_packet() in Stream constructor, in favor of processing on SYN in stream follower.
- Moved +1 to seq on SYN/ACK.
This commit is contained in:
Patrick Michel
2016-09-28 16:30:16 +02:00
committed by Matias Fontanini
parent e82b72e931
commit 838a4a5cb9
4 changed files with 35 additions and 39 deletions

View File

@@ -140,7 +140,6 @@ void Flow::update_state(const TCP& tcp) {
ack_tracker_ = AckTracker(tcp.ack_seq());
#endif // TINS_HAVE_ACK_TRACKER
state_ = ESTABLISHED;
data_tracker_.sequence_number(data_tracker_.sequence_number() + 1);
}
else if (state_ == UNKNOWN && (tcp.flags() & TCP::SYN) != 0) {
// This is the server's state, sending it's first SYN|ACK
@@ -148,7 +147,7 @@ void Flow::update_state(const TCP& tcp) {
ack_tracker_ = AckTracker(tcp.ack_seq());
#endif // TINS_HAVE_ACK_TRACKER
state_ = SYN_SENT;
data_tracker_.sequence_number(tcp.seq());
data_tracker_.sequence_number(tcp.seq() + 1);
const TCP::option* mss_option = tcp.search_option(TCP::MSS);
if (mss_option) {
mss_ = mss_option->to<uint16_t>();

View File

@@ -62,8 +62,6 @@ Stream::Stream(PDU& packet, const timestamp_type& ts)
: client_flow_(extract_client_flow(packet)),
server_flow_(extract_server_flow(packet)), create_time_(ts),
last_seen_(ts), auto_cleanup_client_(true), auto_cleanup_server_(true) {
// Update client flow state
client_flow().process_packet(packet);
const EthernetII* eth = packet.find_pdu<EthernetII>();
if (eth) {
client_hw_addr_ = eth->src_addr();

View File

@@ -90,7 +90,6 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
}
stream_id identifier = stream_id::make_identifier(packet);
streams_type::iterator iter = streams_.find(identifier);
bool process = true;
if (iter == streams_.end()) {
// Start tracking if they're either SYNs or they contain data (attach
// to an already running flow).
@@ -103,49 +102,49 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
else {
throw callback_not_set();
}
if (tcp->flags() == TCP::SYN) {
process = false;
}
else {
// Otherwise, assume the connection is established
if (tcp->flags() != TCP::SYN) {
// assume the connection is established
iter->second.client_flow().state(Flow::ESTABLISHED);
iter->second.server_flow().state(Flow::ESTABLISHED);
}
}
else {
process = false;
// no stream found and no stream was created
if (last_cleanup_ + stream_keep_alive_ <= ts) {
cleanup_streams(ts);
}
return;
}
}
// We'll process it if we had already seen this stream or if we just attached to
// it and it contains payload
if (process) {
Stream& stream = iter->second;
stream.process_packet(packet, ts);
// Check for different potential termination
size_t total_chunks = stream.client_flow().buffered_payload().size() +
stream.server_flow().buffered_payload().size();
uint32_t total_buffered_bytes = stream.client_flow().total_buffered_bytes() +
stream.server_flow().total_buffered_bytes();
bool terminate_stream = total_chunks > max_buffered_chunks_ ||
total_buffered_bytes > max_buffered_bytes_;
TerminationReason reason = BUFFERED_DATA;
#ifdef TINS_HAVE_ACK_TRACKER
if (!terminate_stream) {
uint32_t count = 0;
count += stream.client_flow().ack_tracker().acked_intervals().iterative_size();
count += stream.server_flow().ack_tracker().acked_intervals().iterative_size();
terminate_stream = count > DEFAULT_MAX_SACKED_INTERVALS;
reason = SACKED_SEGMENTS;
}
#endif // TINS_HAVE_ACK_TRACKER
if (stream.is_finished() || terminate_stream) {
// If we're terminating the stream, execute the termination callback
if (terminate_stream && on_stream_termination_) {
on_stream_termination_(stream, reason);
}
streams_.erase(iter);
}
Stream& stream = iter->second;
stream.process_packet(packet, ts);
// Check for different potential termination
size_t total_chunks = stream.client_flow().buffered_payload().size() +
stream.server_flow().buffered_payload().size();
uint32_t total_buffered_bytes = stream.client_flow().total_buffered_bytes() +
stream.server_flow().total_buffered_bytes();
bool terminate_stream = total_chunks > max_buffered_chunks_ ||
total_buffered_bytes > max_buffered_bytes_;
TerminationReason reason = BUFFERED_DATA;
#ifdef TINS_HAVE_ACK_TRACKER
if (!terminate_stream) {
uint32_t count = 0;
count += stream.client_flow().ack_tracker().acked_intervals().iterative_size();
count += stream.server_flow().ack_tracker().acked_intervals().iterative_size();
terminate_stream = count > DEFAULT_MAX_SACKED_INTERVALS;
reason = SACKED_SEGMENTS;
}
#endif // TINS_HAVE_ACK_TRACKER
if (stream.is_finished() || terminate_stream) {
// If we're terminating the stream, execute the termination callback
if (terminate_stream && on_stream_termination_) {
on_stream_termination_(stream, reason);
}
streams_.erase(iter);
}
if (last_cleanup_ + stream_keep_alive_ <= ts) {
cleanup_streams(ts);
}

View File

@@ -354,7 +354,7 @@ TEST_F(FlowTest, StreamFollower_ThreeWayHandshake) {
EXPECT_EQ(Flow::ESTABLISHED, stream.client_flow().state());
EXPECT_EQ(Flow::SYN_SENT, stream.server_flow().state());
EXPECT_EQ(30U, stream.client_flow().sequence_number());
EXPECT_EQ(60U, stream.server_flow().sequence_number());
EXPECT_EQ(61U, stream.server_flow().sequence_number());
EXPECT_EQ(IPv4Address("4.3.2.1"), stream.client_flow().dst_addr_v4());
EXPECT_EQ(25, stream.client_flow().dport());
EXPECT_EQ(IPv4Address("1.2.3.4"), stream.server_flow().dst_addr_v4());