using namespace HttpCommon;
// Stubs to make the code link
+Field::Field(int32_t length, const uint8_t* start, bool own_the_buffer_) :
+ strt(start), len(length), own_the_buffer(own_the_buffer_)
+{}
+
void Field::set(const Field& input)
{
strt = input.strt;
#include "service_inspectors/http_inspect/http_common.h"
#include "service_inspectors/http_inspect/http_field.h"
+#include "http2_enum.h"
+
/* This class is called Http2Frame, but an object of this class may not represent exactly one
* HTTP/2 frame as received on the wire. For HEADERS frames, the Http2Frame object contains the
* initial HEADERS frame plus any following CONTINUATION frames grouped together. For DATA frames,
static Http2Frame* new_frame(const uint8_t* header_buffer, const int32_t header_len,
const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* session_data,
HttpCommon::SourceId source_id, Http2Stream* stream);
+ virtual bool valid_sequence(Http2Enums::StreamState state)
+ { return state != Http2Enums::STREAM_ERROR; }
+ virtual void analyze_http1() { }
virtual void clear() { }
virtual const Field& get_buf(unsigned id);
virtual uint32_t get_xtradata_mask() { return 0; }
// FIXIT-E set stream state to error
return;
}
-
- StreamBuffer stream_buf;
- HttpFlowData* http_flow;
+}
+
+Http2HeadersFrameHeader::~Http2HeadersFrameHeader()
+{
+ delete start_line;
+ delete start_line_generator;
+}
+
+void Http2HeadersFrameHeader::analyze_http1()
+{
+ if (!process_frame || start_line == nullptr)
+ return;
// http_inspect scan() of start line
{
assert((int64_t)flush_offset == start_line->length());
}
+ StreamBuffer stream_buf;
+
// http_inspect reassemble() of start line
{
unsigned copied;
assert(copied == (unsigned)start_line->length());
}
- http_flow = session_data->get_current_stream(source_id)->get_hi_flow_data();
+ HttpFlowData* const http_flow =
+ session_data->get_current_stream(source_id)->get_hi_flow_data();
// http_inspect eval() and clear() of start line
{
Http2DummyPacket dummy_pkt;
process_decoded_headers(http_flow);
}
-Http2HeadersFrameHeader::~Http2HeadersFrameHeader()
-{
- delete start_line;
- delete start_line_generator;
-}
-
#ifdef REG_TEST
void Http2HeadersFrameHeader::print_frame(FILE* output)
{
class Http2HeadersFrameHeader : public Http2HeadersFrame
{
public:
- ~Http2HeadersFrameHeader();
+ ~Http2HeadersFrameHeader() override;
friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*,
const int32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream);
+ void analyze_http1() override;
+
#ifdef REG_TEST
void print_frame(FILE* output) override;
#endif
if (!process_frame)
return;
- StreamBuffer stream_buf;
- HttpFlowData* http_flow;
+ // Decode trailers
+ if (!hpack_decoder->decode_headers((data.start() + hpack_headers_offset), data.length() -
+ hpack_headers_offset, decoded_headers, nullptr, true))
+ {
+ session_data->frame_type[source_id] = FT__ABORT;
+ error_during_decode = true;
+ }
+}
- http_flow = session_data->get_current_stream(source_id)->get_hi_flow_data();
+void Http2HeadersFrameTrailer::analyze_http1()
+{
+ if (!process_frame)
+ return;
+
+ HttpFlowData* const http_flow =
+ session_data->get_current_stream(source_id)->get_hi_flow_data();
assert(http_flow);
+
if (http_flow->get_type_expected(source_id) != HttpEnums::SEC_TRAILER)
{
// If there was no unflushed data on this stream when the trailers arrived, http_inspect
stream->finish_msg_body(source_id, true, true); // calls http_inspect scan()
unsigned copied;
- stream_buf = session_data->hi_ss[source_id]->reassemble(session_data->flow,
+ const StreamBuffer stream_buf =
+ session_data->hi_ss[source_id]->reassemble(session_data->flow,
0, 0, nullptr, 0, PKT_PDU_TAIL, copied);
assert(stream_buf.data != nullptr);
assert(copied == 0);
session_data->hi->clear(&dummy_pkt);
}
- // Decode headers
- if (!hpack_decoder->decode_headers((data.start() + hpack_headers_offset), data.length() -
- hpack_headers_offset, decoded_headers, nullptr, true))
- {
- session_data->frame_type[source_id] = FT__ABORT;
- error_during_decode = true;
- }
-
process_decoded_headers(http_flow);
}
friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*,
const int32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream);
+ void analyze_http1() override;
+
#ifdef REG_TEST
void print_frame(FILE* output) override;
#endif
assert(current_frame == nullptr);
current_frame = Http2Frame::new_frame(header_buffer, header_len, data_buffer,
data_len, session_data, source_id, this);
+ valid_frame_order[source_id] = valid_frame_order[source_id] &&
+ current_frame->valid_sequence(state[source_id]);
+ current_frame->analyze_http1();
current_frame->update_stream_state();
}
private:
const uint32_t stream_id;
Http2FlowData* const session_data;
+ bool valid_frame_order[2] = { true, true };
Http2Frame* current_frame = nullptr;
HttpFlowData* hi_flow_data = nullptr;
HttpMsgSection* hi_msg_section = nullptr;
const Field Field::FIELD_NULL { STAT_NO_SOURCE };
+Field::Field(int32_t length, const uint8_t* start, bool own_the_buffer_) :
+ strt(start), len(length), own_the_buffer(own_the_buffer_)
+{
+ assert(!((start == nullptr) && (length > 0)));
+ assert(!((start != nullptr) && (length < 0)));
+}
+
void Field::set(int32_t length, const uint8_t* start, bool own_the_buffer_)
{
assert(len == STAT_NOT_COMPUTE);
public:
static const Field FIELD_NULL;
- Field(int32_t length, const uint8_t* start, bool own_the_buffer_ = false) : strt(start),
- len(length), own_the_buffer(own_the_buffer_) { }
+ Field(int32_t length, const uint8_t* start, bool own_the_buffer_ = false);
explicit Field(int32_t length) : len(length) { assert(length<=0); }
Field() = default;
~Field() { if (own_the_buffer) delete[] strt; }