Http2DummyPacket dummy_pkt;
dummy_pkt.flow = session_data->flow;
uint32_t unused = 0;
+ if ((data_bytes_read == data_len) && (frame_flags & END_STREAM))
+ {
+ Http2Stream* const stream =
+ session_data->find_stream(session_data->current_stream[source_id]);
+ HttpFlowData* const hi_flow = stream->get_hi_flow_data();
+ hi_flow->set_h2_body_state(source_id, HttpEnums::H2_BODY_LAST_SEG);
+ }
scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, data + cur_data_offset,
cur_data, unused, &http_flush_offset);
{
Http2Stream* const stream = session_data->find_stream(
session_data->current_stream[source_id]);
- stream->finish_msg_body(source_id, false, bytes_sent_http == 0);
+ assert(scan_result == StreamSplitter::FLUSH || data_len == 0);
+ stream->finish_msg_body(source_id, false, data_len == 0);
+
// FIXIT-E this flag seems to mean both END_STREAM and the end of this frame
stream->set_end_stream_on_data_flush(source_id);
session_data->stream_in_hi = NO_STREAM_ID;
uint32_t http_flush_offset = 0;
Http2DummyPacket dummy_pkt;
dummy_pkt.flow = session_data->flow;
- uint32_t unused = 0;
const H2BodyState body_state = expect_trailers ?
H2_BODY_COMPLETE_EXPECT_TRAILERS : H2_BODY_COMPLETE;
get_hi_flow_data()->finish_h2_body(source_id, body_state, clear_partial_buffer);
- const snort::StreamSplitter::Status scan_result = session_data->hi_ss[source_id]->scan(
- &dummy_pkt, nullptr, 0, unused, &http_flush_offset);
- assert(scan_result == snort::StreamSplitter::FLUSH);
- UNUSED(scan_result);
+ if (clear_partial_buffer)
+ {
+ uint32_t unused = 0;
+ const snort::StreamSplitter::Status scan_result = session_data->hi_ss[source_id]->scan(
+ &dummy_pkt, nullptr, 0, unused, &http_flush_offset);
+ assert(scan_result == snort::StreamSplitter::FLUSH);
+ UNUSED(scan_result);
+ }
}
return SCAN_FOUND_PIECE;
}
}
+ else if (state == H2_BODY_LAST_SEG)
+ {
+ if (octets_seen + length <= flow_target)
+ num_flush = length;
+ else
+ num_flush = flow_target - octets_seen;
+
+ total_octets_scanned += num_flush;
+ if (num_flush == length)
+ return SCAN_FOUND;
+ else
+ return SCAN_FOUND_PIECE;
+ }
else
{
- // For now if end_stream is set for scan, a zero-length buffer is always sent to flush
+ // To end message body when trailers are received or a 0 length data frame with
+ // end of stream set is received, a zero-length buffer is sent to flush
assert(length == 0);
num_flush = 0;
return SCAN_FOUND;
extern const bool is_print_char[256]; // printable includes SP, tab, CR, LF
extern const bool is_sp_comma[256];
-enum H2BodyState { H2_BODY_NOT_COMPLETE, H2_BODY_COMPLETE, H2_BODY_COMPLETE_EXPECT_TRAILERS,
- H2_BODY_NO_BODY };
+enum H2BodyState { H2_BODY_NOT_COMPLETE, H2_BODY_LAST_SEG, H2_BODY_COMPLETE,
+ H2_BODY_COMPLETE_EXPECT_TRAILERS, H2_BODY_NO_BODY };
} // end namespace HttpEnums
void HttpFlowData::finish_h2_body(HttpCommon::SourceId source_id, HttpEnums::H2BodyState state,
bool clear_partial_buffer)
{
- assert(h2_body_state[source_id] == H2_BODY_NOT_COMPLETE);
+ assert((h2_body_state[source_id] == H2_BODY_NOT_COMPLETE) ||
+ (h2_body_state[source_id] == H2_BODY_LAST_SEG));
h2_body_state[source_id] = state;
partial_flush[source_id] = false;
if (clear_partial_buffer)
void finish_h2_body(HttpCommon::SourceId source_id, HttpEnums::H2BodyState state,
bool clear_partial_buffer);
+ void set_h2_body_state(HttpCommon::SourceId source_id, HttpEnums::H2BodyState state)
+ { h2_body_state[source_id] = state; }
+
void reset_partial_flush(HttpCommon::SourceId source_id)
{ partial_flush[source_id] = false; }
if ((session_data->section_offset[source_id] == 0) &&
(session_data->octets_expected[source_id] != partial_raw_bytes + total))
{
+ assert(!session_data->for_http2);
+
if (session_data->octets_expected[source_id] == 0)
{
// FIXIT-E This is a known problem. No data was scanned and yet somehow stream can