tcp_init = false;
tcpStats.released++;
- client.ooo_packet_seen = false;
- server.ooo_packet_seen = false;
-
if ( flush_segments )
{
client.reassembler.flush_queued_segments(flow, true, p);
void TcpSession::update_stream_order(const TcpSegmentDescriptor& tsd, bool aligned)
{
TcpStreamTracker* listener = tsd.get_listener();
+ uint32_t seq = tsd.get_seq();
switch ( listener->order )
{
- case 0:
- if ( aligned )
- tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
- else
- listener->order = 1;
- break;
+ case TcpStreamTracker::IN_SEQUENCE:
+ if ( aligned )
+ tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
+ else if ( SEQ_GT(seq, listener->rcv_nxt) )
+ {
+ listener->order = TcpStreamTracker::NONE;
+ listener->hole_left_edge = listener->rcv_nxt;
+ listener->hole_right_edge = seq - 1;
+ }
+ break;
- case 1:
- if ( aligned )
- {
- tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
- listener->order = 2;
- }
- break;
+ case TcpStreamTracker::NONE:
+ if ( aligned )
+ {
+ tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
+ if ( SEQ_GT(tsd.get_end_seq(), listener->hole_right_edge) )
+ listener->order = TcpStreamTracker::OUT_OF_SEQUENCE;
+ else
+ listener->hole_left_edge = tsd.get_end_seq();
+ }
+ else
+ {
+ if ( SEQ_LEQ(seq, listener->hole_right_edge) )
+ {
+ if ( SEQ_GT(seq, listener->hole_left_edge) )
+ listener->hole_right_edge = seq - 1;
+ else if ( SEQ_GT(tsd.get_end_seq(), listener->hole_left_edge) )
+ {
+ listener->hole_left_edge = tsd.get_end_seq();
+ tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
+ }
+ }
+ // accounting for overlaps when not aligned
+ if ( SEQ_GT(listener->hole_left_edge, listener->hole_right_edge) )
+ listener->order = TcpStreamTracker::OUT_OF_SEQUENCE;
+ }
+ break;
- default:
- if ( aligned )
- tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
- else
- {
- if ( !(flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD) )
- flow->set_session_flags(SSNFLAG_STREAM_ORDER_BAD);
+ case TcpStreamTracker::OUT_OF_SEQUENCE:
tsd.set_packet_flags(PKT_STREAM_ORDER_BAD);
- }
}
}
if ( tsd.is_data_segment() )
{
- update_stream_order(tsd, !listener->ooo_packet_seen);
+ update_stream_order(tsd, true);
process_tcp_stream(tsd);
return STREAM_ALIGNED;
}
TCP_MAX_EVENTS
};
+ enum PacketOrder : uint8_t { OUT_OF_SEQUENCE, IN_SEQUENCE, NONE };
+
enum FinSeqNumStatus : uint8_t { FIN_NOT_SEEN, FIN_WITH_SEQ_SEEN, FIN_WITH_SEQ_ACKED };
TcpStreamTracker(bool client);
uint16_t rcv_up = 0; // RCV.UP - receive urgent pointer
uint32_t held_pkt_seq = 0;
+ uint32_t hole_left_edge = 0; // First left hole
+ uint32_t hole_right_edge = 0;
+
TcpState tcp_state;
TcpEvent tcp_event = TCP_MAX_EVENTS;
bool client_tracker;
bool require_3whs = false;
bool rst_pkt_sent = false;
- bool ooo_packet_seen = false;
bool midstream_initial_ack_flush = false;
// FIXIT-L make these non-public
uint32_t small_seg_count = 0;
uint32_t max_queue_seq_nxt = 0; // next expected sequence once queue limit is exceeded
uint8_t max_queue_exceeded = MQ_NONE;
- uint8_t order = 0;
+ uint8_t order = IN_SEQUENCE;
FinSeqNumStatus fin_seq_status = TcpStreamTracker::FIN_NOT_SEEN;
protected: