TEST_F(FlowTest, StreamFollower_CleanupWorks) { using std::placeholders::_1; bool timed_out = false; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); follower.stream_termination_callback([&](Stream&, StreamFollower::TerminationReason reason) { timed_out = (reason == StreamFollower::TIMEOUT); }); packets[2].rfind_pdu<IP>().src_addr("6.6.6.6"); auto base_time = duration_cast<Stream::timestamp_type>(system_clock::now().time_since_epoch()); Packet packet1(packets[0], base_time); Packet packet2(packets[1], base_time + seconds(50)); Packet packet3(packets[2], base_time + minutes(10)); follower.process_packet(packet1); Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); EXPECT_EQ(base_time, stream.create_time()); follower.process_packet(packet2); follower.process_packet(packet3); // At this point, it should be cleaned up EXPECT_THROW( follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25), stream_not_found ); EXPECT_TRUE(timed_out); }
TEST_F(FlowTest, StreamFollower_FINClosesStream) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } Stream stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); IP server_packet = IP("1.2.3.4", "4.3.2.1") / TCP(22, 25); server_packet.rfind_pdu<TCP>().flags(TCP::FIN | TCP::ACK); stream.process_packet(server_packet); EXPECT_EQ(Flow::FIN_SENT, stream.server_flow().state()); EXPECT_FALSE(stream.is_finished()); IP client_packet = IP("4.3.2.1", "1.2.3.4") / TCP(25, 22); client_packet.rfind_pdu<TCP>().flags(TCP::FIN | TCP::ACK); stream.process_packet(client_packet); EXPECT_EQ(Flow::FIN_SENT, stream.client_flow().state()); EXPECT_TRUE(stream.is_finished()); }
TEST_F(FlowTest, AckNumbersAreCorrect) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); // Server's ACK number is 9898 packets[1].rfind_pdu<TCP>().ack_seq(9898); // Client's ACK number is 1717 packets[2].rfind_pdu<TCP>().ack_seq(1717); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); EXPECT_EQ(1717U, stream.client_flow().ack_tracker().ack_number()); EXPECT_EQ(9898U, stream.server_flow().ack_tracker().ack_number()); }
TEST_F(FlowTest, StreamFollower_ThreeWayHandshake) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); packets[0].src_addr("00:01:02:03:04:05"); packets[0].dst_addr("05:04:03:02:01:00"); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); Stream::timestamp_type ts(10000); Stream::timestamp_type create_time = ts; for (size_t i = 0; i < packets.size(); ++i) { if (i != 0) { ts += milliseconds(100); } Packet packet(packets[i], duration_cast<microseconds>(ts)); follower.process_packet(packet); } Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); 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(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()); EXPECT_EQ(22, stream.server_flow().dport()); EXPECT_EQ(IPv4Address("1.2.3.4"), stream.client_addr_v4()); EXPECT_EQ(IPv4Address("4.3.2.1"), stream.server_addr_v4()); EXPECT_EQ(HWAddress<6>("00:01:02:03:04:05"), stream.client_hw_addr()); EXPECT_EQ(HWAddress<6>("05:04:03:02:01:00"), stream.server_hw_addr()); EXPECT_EQ(22, stream.client_port()); EXPECT_EQ(25, stream.server_port()); EXPECT_EQ(create_time, stream.create_time()); EXPECT_EQ(ts, stream.last_seen()); IP server_packet = IP("1.2.3.4", "4.3.2.1") / TCP(22, 25); server_packet.rfind_pdu<TCP>().flags(TCP::ACK); follower.process_packet(server_packet); EXPECT_EQ(Flow::ESTABLISHED, stream.server_flow().state()); EXPECT_EQ(61U, stream.server_flow().sequence_number()); }
TEST_F(FlowTest, StreamFollower_StreamIsRemovedWhenFinished) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } IP server_packet = IP("1.2.3.4", "4.3.2.1") / TCP(22, 25); server_packet.rfind_pdu<TCP>().flags(TCP::RST); follower.process_packet(server_packet); // We shouldn't be able to find it EXPECT_THROW( follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25), stream_not_found ); }
TEST_F(FlowTest, StreamFollower_TCPOptions) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); // Client's mss is 1220 packets[0].rfind_pdu<TCP>().mss(1220); // Server's mss is 1460 packets[1].rfind_pdu<TCP>().mss(1460); // Server supports SACK packets[1].rfind_pdu<TCP>().sack_permitted(); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); EXPECT_EQ(1220, stream.client_flow().mss()); EXPECT_EQ(1460, stream.server_flow().mss()); EXPECT_FALSE(stream.client_flow().sack_permitted()); EXPECT_TRUE(stream.server_flow().sack_permitted()); }