]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1882 in SNORT/snort3 from ~THOPETER/snort3:h2i_streams to master
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 9 Dec 2019 17:08:40 +0000 (17:08 +0000)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 9 Dec 2019 17:08:40 +0000 (17:08 +0000)
Squashed commit of the following:

commit 3b164411655f7ec11e66c424a3783f74c11cf11e
Author: Tom Peters <thopeter@cisco.com>
Date:   Mon Dec 2 14:59:20 2019 -0500

    http2_inspect: add Stream class

src/service_inspectors/http2_inspect/CMakeLists.txt
src/service_inspectors/http2_inspect/http2_flow_data.cc
src/service_inspectors/http2_inspect/http2_flow_data.h
src/service_inspectors/http2_inspect/http2_inspect.cc
src/service_inspectors/http2_inspect/http2_inspect_impl.cc [deleted file]
src/service_inspectors/http2_inspect/http2_stream.cc [new file with mode: 0644]
src/service_inspectors/http2_inspect/http2_stream.h [new file with mode: 0644]
src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc
src/service_inspectors/http2_inspect/test/CMakeLists.txt
src/service_inspectors/http2_inspect/test/http2_flow_data_test.h [deleted file]
src/service_inspectors/http2_inspect/test/http2_stream_splitter_impl_test.cc [deleted file]

index a1ddd7c8f75f30217a13b53e4edea3a3397c3aa1..3d11259a0e480ec8e307eaa91cb9537f2ffc7fd6 100644 (file)
@@ -22,7 +22,6 @@ set (FILE_LIST
     http2_huffman_state_machine.cc
     http2_huffman_state_machine.h
     http2_inspect.cc
-    http2_inspect_impl.cc
     http2_inspect.h
     http2_module.cc
     http2_module.h
@@ -34,6 +33,8 @@ set (FILE_LIST
     http2_start_line.h
     http2_status_line.cc
     http2_status_line.h
+    http2_stream.cc
+    http2_stream.h
     http2_stream_splitter.cc
     http2_stream_splitter_impl.cc
     http2_stream_splitter.h
index 66be2c2d93eee6d44c3ce1655160afb90e55a123..57540a803ae0a5029324682c925bd5c5a6290eaf 100644 (file)
@@ -29,6 +29,7 @@
 #include "http2_frame.h"
 #include "http2_module.h"
 #include "http2_start_line.h"
+#include "http2_stream.h"
 
 using namespace snort;
 using namespace Http2Enums;
@@ -40,7 +41,7 @@ unsigned Http2FlowData::inspector_id = 0;
 uint64_t Http2FlowData::instance_count = 0;
 #endif
 
-Http2FlowData::Http2FlowData() : FlowData(inspector_id)
+Http2FlowData::Http2FlowData() : FlowData(inspector_id), stream(new Http2Stream(this))
 {
 #ifdef REG_TEST
     seq_num = ++instance_count;
@@ -74,17 +75,8 @@ Http2FlowData::~Http2FlowData()
     {
         delete infractions[k];
         delete events[k];
-        delete current_frame[k];
     }
-}
 
-void Http2FlowData::clear_frame_data(HttpCommon::SourceId source_id)
-{
-    frame_in_detection = false;
-    continuation_expected[source_id] = false;
-    num_frame_headers[source_id] = 0;
-    scan_octets_seen[source_id] = 0;
-    total_bytes_in_split[source_id] = 0;
-    delete current_frame[source_id];
-    current_frame[source_id] = nullptr;
+    delete stream;
 }
+
index 671956df2443e8a0148c14bd3c31f8daeea1c80b..ff488ecc5021d3cf1b67d044b4a39cd3b85593e6 100644 (file)
@@ -57,10 +57,8 @@ public:
     friend class Http2SettingsFrame;
     friend class Http2StartLine;
     friend class Http2StatusLine;
+    friend class Http2Stream;
     friend class Http2StreamSplitter;
-    friend void implement_eval(Http2FlowData* session_data, HttpCommon::SourceId source_id);
-    friend bool implement_get_buf(unsigned id, Http2FlowData*, HttpCommon::SourceId,
-        snort::InspectionBuffer&);
     friend const snort::StreamBuffer implement_reassemble(Http2FlowData*, unsigned, unsigned,
         const uint8_t*, unsigned, uint32_t, HttpCommon::SourceId);
     friend snort::StreamSplitter::Status implement_scan(Http2FlowData*, const uint8_t*, uint32_t,
@@ -72,7 +70,7 @@ public:
 protected:
     // 0 element refers to client frame, 1 element refers to server frame
 
-    // Reassemble() signals to eval()
+    // Reassemble() data to eval()
     uint8_t* frame_header[2] = { nullptr, nullptr };
     uint32_t frame_header_size[2] = { 0, 0 };
     uint8_t* frame_data[2] = { nullptr, nullptr };
@@ -80,9 +78,9 @@ protected:
 
     // Used in eval()
     bool frame_in_detection = false;
-    class Http2Frame* current_frame[2] = { nullptr, nullptr };
     Http2ConnectionSettings connection_settings[2];
     Http2HpackDecoder hpack_decoder[2];
+    class Http2Stream* stream;
 
     // Internal to scan()
     bool preface[2] = { true, false };
@@ -113,8 +111,6 @@ protected:
     Http2Infractions* infractions[2] = { new Http2Infractions, new Http2Infractions };
     Http2EventGen* events[2] = { new Http2EventGen, new Http2EventGen };
 
-    void clear_frame_data(HttpCommon::SourceId source_id);
-
 #ifdef REG_TEST
     static uint64_t instance_count;
     uint64_t seq_num;
index a241bdc1b9559d44bf9ff74b7ce9358901b00220..ac04e98bfcfc5c951fe3896e76ac1e7565555f8e 100644 (file)
@@ -22,6 +22,7 @@
 #endif
 
 #include "http2_inspect.h"
+
 #include "detection/detection_engine.h"
 #include "protocols/packet.h"
 #include "service_inspectors/http_inspect/http_common.h"
@@ -30,6 +31,7 @@
 #include "stream/stream.h"
 
 #include "http2_frame.h"
+#include "http2_stream.h"
 
 using namespace snort;
 using namespace HttpCommon;
@@ -79,9 +81,13 @@ bool Http2Inspect::get_buf(unsigned id, Packet* p, InspectionBuffer& b)
     if (!session_data->frame_in_detection)
         return false;
 
-    const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER;
+    const Field& buffer = session_data->stream->get_buf(id);
+    if (buffer.length() <= 0)
+        return false;
 
-    return implement_get_buf(id, session_data, source_id, b);
+    b.data = buffer.start();
+    b.len = buffer.length();
+    return true;
 }
 
 bool Http2Inspect::get_fp_buf(InspectionBuffer::Type /*ibt*/, Packet* /*p*/,
@@ -105,14 +111,20 @@ void Http2Inspect::eval(Packet* p)
     if (session_data->frame_type[source_id] == FT__NONE)
         return;
 
-    implement_eval(session_data, source_id);
+    session_data->stream->eval_frame(session_data->frame_header[source_id],
+        session_data->frame_header_size[source_id], session_data->frame_data[source_id],
+        session_data->frame_data_size[source_id], source_id);
+
+    // The current frame now owns these buffers, clear them from the flow data
+    session_data->frame_header[source_id] = nullptr;
+    session_data->frame_data[source_id] = nullptr;
 
     session_data->frame_in_detection = true;
 
 #ifdef REG_TEST
     if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
     {
-        session_data->current_frame[source_id]->print_frame(HttpTestManager::get_output_file());
+        session_data->stream->print_frame(HttpTestManager::get_output_file());
         if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
         {
             printf("Finished processing section from test %" PRIi64 "\n",
@@ -130,8 +142,7 @@ void Http2Inspect::clear(Packet* p)
     if (session_data == nullptr)
         return;
 
-    const SourceId source_id = (p->is_from_client()) ? SRC_CLIENT : SRC_SERVER;
-
-    session_data->clear_frame_data(source_id);
+    session_data->frame_in_detection = false;
+    session_data->stream->clear_frame();
 }
 
diff --git a/src/service_inspectors/http2_inspect/http2_inspect_impl.cc b/src/service_inspectors/http2_inspect/http2_inspect_impl.cc
deleted file mode 100644 (file)
index 82a1e36..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2018-2019 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-// http2_inspect_impl.cc author Tom Peters <thopeter@cisco.com>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "http2_inspect.h"
-#include "http2_enum.h"
-#include "http2_flow_data.h"
-#include "http2_frame.h"
-#include "service_inspectors/http_inspect/http_common.h"
-
-using namespace snort;
-using namespace HttpCommon;
-using namespace Http2Enums;
-
-bool implement_get_buf(unsigned id, Http2FlowData* session_data, SourceId source_id,
-    InspectionBuffer& b)
-{
-    const Field& buffer = session_data->current_frame[source_id]->get_buf(id);
-    if (buffer.length() <= 0)
-        return false;
-    b.data = buffer.start();
-    b.len = buffer.length();
-    return true;
-}
-
-void implement_eval(Http2FlowData* session_data, SourceId source_id)
-{
-    // Construct the appropriate frame class
-    session_data->current_frame[source_id] = Http2Frame::new_frame(
-        session_data->frame_header[source_id], session_data->frame_header_size[source_id],
-        session_data->frame_data[source_id], session_data->frame_data_size[source_id],
-        session_data, source_id);
-    // The current frame now owns these buffers, clear them from the flow data
-    session_data->frame_header[source_id] = nullptr;
-    session_data->frame_data[source_id] = nullptr;
-}
diff --git a/src/service_inspectors/http2_inspect/http2_stream.cc b/src/service_inspectors/http2_inspect/http2_stream.cc
new file mode 100644 (file)
index 0000000..6fed50c
--- /dev/null
@@ -0,0 +1,65 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// http2_stream.cc author Tom Peters <thopeter@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "http2_stream.h"
+
+using namespace HttpCommon;
+
+Http2Stream::Http2Stream(Http2FlowData* session_data_) : session_data(session_data_)
+{
+}
+
+Http2Stream::~Http2Stream()
+{
+    delete current_frame;
+}
+
+void Http2Stream::eval_frame(const uint8_t* header_buffer, int32_t header_len,
+    const uint8_t* data_buffer, int32_t data_len, SourceId source_id)
+{
+    delete current_frame;
+    current_frame = Http2Frame::new_frame(header_buffer, header_len, data_buffer,
+        data_len, session_data, source_id);
+}
+
+void Http2Stream::clear_frame()
+{
+    delete current_frame;
+    current_frame = nullptr;
+}
+
+const Field& Http2Stream::get_buf(unsigned id)
+{
+    if (current_frame != nullptr)
+        return current_frame->get_buf(id);
+    return Field::FIELD_NULL;
+}
+
+#ifdef REG_TEST
+void Http2Stream::print_frame(FILE* output)
+{
+    if (current_frame != nullptr)
+        current_frame->print_frame(output);
+}
+#endif
+
diff --git a/src/service_inspectors/http2_inspect/http2_stream.h b/src/service_inspectors/http2_inspect/http2_stream.h
new file mode 100644 (file)
index 0000000..9e82fef
--- /dev/null
@@ -0,0 +1,47 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// http2_stream.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef HTTP2_STREAM_H
+#define HTTP2_STREAM_H
+
+#include "service_inspectors/http_inspect/http_common.h"
+#include "service_inspectors/http_inspect/http_field.h"
+
+#include "http2_flow_data.h"
+#include "http2_frame.h"
+
+class Http2Stream
+{
+public:
+    Http2Stream(Http2FlowData* session_data_);
+    ~Http2Stream();
+    void eval_frame(const uint8_t* header_buffer, int32_t header_len, const uint8_t* data_buffer,
+        int32_t data_len, HttpCommon::SourceId source_id);
+    void clear_frame();
+    const Field& get_buf(unsigned id);
+#ifdef REG_TEST
+    void print_frame(FILE* output);
+#endif
+
+private:
+    Http2FlowData* const session_data;
+    Http2Frame* current_frame = nullptr;
+};
+
+#endif
index 8f3142b7e3e843a0aee7f8afc760d07301842446..c842295197d7328211955694ce9e009d92b5bc44 100644 (file)
@@ -220,8 +220,8 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
                     }
                     else
                     {
-                        // FIXIT-M CONTINUATION frames can also follow PUSH_PROMISE frames, which is
-                        // not currently supported
+                        // FIXIT-M CONTINUATION frames can also follow PUSH_PROMISE frames, which
+                        // are not currently supported
                         *session_data->infractions[source_id] += INF_UNEXPECTED_CONTINUATION;
                         session_data->events[source_id]->create_event(
                             EVENT_UNEXPECTED_CONTINUATION);
@@ -352,11 +352,16 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to
 
     if (flags & PKT_PDU_TAIL)
     {
+        session_data->total_bytes_in_split[source_id] = 0;
+        session_data->num_frame_headers[source_id] = 0;
+        session_data->scan_octets_seen[source_id] = 0;
+
         // Return 0-length non-null buffer to stream which signals detection required, but don't 
         // create pkt_data buffer
         frame_buf.data = (const uint8_t*)"";
     }
     session_data->frame_type[source_id] = get_frame_type(session_data->frame_header[source_id]);
+
     return frame_buf;
 }
 
index b2e42b22348721b2cec68882c959d542a201d07d..0e166380f927770a0947dc2485ab478cce7799dc 100644 (file)
@@ -1,13 +1,3 @@
-add_cpputest( http2_stream_splitter_impl_test
-    SOURCES
-        ../http2_flow_data.cc
-        ../http2_hpack_dynamic_table.cc
-        ../http2_hpack_table.cc
-        ../http2_stream_splitter_impl.cc
-        ../http2_module.cc
-        ../http2_tables.cc
-        ../../../framework/module.cc
-)
 add_cpputest( http2_hpack_int_decode_test
     SOURCES
         ../http2_hpack_int_decode.cc
diff --git a/src/service_inspectors/http2_inspect/test/http2_flow_data_test.h b/src/service_inspectors/http2_inspect/test/http2_flow_data_test.h
deleted file mode 100644 (file)
index ab902d2..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2018-2019 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// http2_flow_data_test.h author Tom Peters <thopeter@cisco.com>
-
-#ifndef HTTP2_FLOW_DATA_TEST_H
-#define HTTP2_FLOW_DATA_TEST_H
-
-#include "service_inspectors/http_inspect/http_common.h"
-//#include "service_inspectors/http2_inspect/http2_enum.h"
-#include "service_inspectors/http2_inspect/http2_flow_data.h"
-#include "service_inspectors/http2_inspect/http2_module.h"
-
-// Stubs whose sole purpose is to make the test code link
-snort::FlowData::FlowData(unsigned u, Inspector* ph) : next(nullptr), prev(nullptr), handler(ph), id(u) {}
-snort::FlowData::~FlowData() = default;
-unsigned snort::FlowData::flow_data_id = 0;
-void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }
-void show_stats(PegCount*, const PegInfo*, const IndexVec&, const char*, FILE*) { }
-
-class Http2FlowDataTest : public Http2FlowData
-{
-public:
-    bool get_preface(HttpCommon::SourceId source_id) { return preface[source_id]; }
-    void set_preface(bool value, HttpCommon::SourceId source_id) { preface[source_id] = value; }
-    bool get_num_frame_headers(HttpCommon::SourceId source_id) { return num_frame_headers[source_id]; }
-    void set_num_frame_headers(bool value, HttpCommon::SourceId source_id)
-        { num_frame_headers[source_id] = value; }
-    uint8_t* get_frame_header(HttpCommon::SourceId source_id) { return frame_header[source_id]; }
-    void set_frame_header(uint8_t* value, uint32_t length, HttpCommon::SourceId source_id)
-        { frame_header[source_id] = value; frame_header_size[source_id] = length; }
-    uint8_t* get_scan_frame_header(HttpCommon::SourceId source_id)
-        { return scan_frame_header[source_id]; }
-    uint8_t* get_frame_data(HttpCommon::SourceId source_id) { return frame_data[source_id]; }
-    void set_frame_data(uint8_t* value, HttpCommon::SourceId source_id)
-        { frame_data[source_id] = value; }
-    uint32_t get_frame_data_size(HttpCommon::SourceId source_id)
-        { return frame_data_offset[source_id]; }
-    void set_frame_data_size(uint32_t value, HttpCommon::SourceId source_id)
-        { frame_data_size[source_id] = value; }
-    uint32_t get_leftover_data(HttpCommon::SourceId source_id) { return leftover_data[source_id]; }
-    void set_leftover_data(uint32_t value, HttpCommon::SourceId source_id)
-        { leftover_data[source_id] = value; }
-    void set_total_bytes_in_split(uint32_t value, HttpCommon::SourceId source_id)
-        { total_bytes_in_split[source_id] = value; }
-    void set_octets_before_first_header(uint32_t value, HttpCommon::SourceId source_id)
-        { octets_before_first_header[source_id] = value; }
-    void cleanup()
-    {
-        for (int k = 0; k < 2; k++)
-        {
-            delete[] frame_header[k];
-            delete[] frame_data[k];
-        }
-    }
-};
-
-#endif
-
diff --git a/src/service_inspectors/http2_inspect/test/http2_stream_splitter_impl_test.cc b/src/service_inspectors/http2_inspect/test/http2_stream_splitter_impl_test.cc
deleted file mode 100644 (file)
index 1b82572..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2018-2019 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// http2_stream_splitter_test.cc author Tom Peters <thopeter@cisco.com>
-// unit test main
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-#include "protocols/packet.h"
-#include "service_inspectors/http_inspect/http_common.h"
-#include "service_inspectors/http_inspect/http_test_manager.h"
-#include "service_inspectors/http2_inspect/http2_enum.h"
-#include "service_inspectors/http2_inspect/http2_flow_data.h"
-#include "service_inspectors/http2_inspect/http2_stream_splitter.h"
-
-#include "http2_flow_data_test.h"
-
-#include <CppUTest/CommandLineTestRunner.h>
-#include <CppUTest/TestHarness.h>
-#include <CppUTestExt/MockSupport.h>
-
-using namespace snort;
-using namespace HttpCommon;
-using namespace Http2Enums;
-
-// Stubs whose sole purpose is to make the test code link
-unsigned HttpTestManager::test_input = IN_NONE;
-unsigned HttpTestManager::test_output = IN_NONE;
-FILE* HttpTestManager::test_out = nullptr ;
-int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
-void Field::set(int, unsigned char const*, bool) {}
-
-#ifdef REG_TEST
-void Field::print(_IO_FILE*, char const*) const {}
-#endif
-
-TEST_GROUP(http2_scan_test)
-{
-    Http2FlowDataTest* session_data = nullptr;
-    uint32_t flush_offset = 0;
-
-    void setup() override
-    {
-        session_data = new Http2FlowDataTest();
-        CHECK(session_data != nullptr);
-    }
-
-    void teardown() override
-    {
-        delete session_data;
-    }
-};
-
-TEST(http2_scan_test, basic_with_header)
-{
-    session_data->set_preface(false, SRC_CLIENT);
-    const StreamSplitter::Status result = implement_scan(session_data,
-        (const uint8_t*)"\x00\x00\x0A\x02\x00\x00\x00\x00\x00" "0123456789ABCDEFG",
-        26, &flush_offset, SRC_CLIENT);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == 19);
-    CHECK(session_data->get_num_frame_headers(SRC_CLIENT) == 1);
-}
-
-TEST(http2_scan_test, basic_with_header_s2c)
-{
-    const StreamSplitter::Status result = implement_scan(session_data,
-        (const uint8_t*)"\x00\x00\x0A\x02\x00\x00\x00\x00\x00" "0123456789ABCDEFG",
-        26, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == 19);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 1);
-}
-
-TEST(http2_scan_test, header_without_data)
-{
-    session_data->set_preface(false, SRC_CLIENT);
-    const StreamSplitter::Status result = implement_scan(session_data,
-        (const uint8_t*)"\x00\x00\x0A\x02\x00\x00\x00\x00\x00",
-        9, &flush_offset, SRC_CLIENT);
-    CHECK(result == StreamSplitter::SEARCH);
-    CHECK(flush_offset == 0);
-    CHECK(session_data->get_num_frame_headers(SRC_CLIENT) == 1);
-}
-
-TEST(http2_scan_test, preface_and_more)
-{
-    const StreamSplitter::Status result = implement_scan(session_data,
-        (const uint8_t*)"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\nABCDEFGHIJKLMNOPQRSTUVWXYZ",
-        50, &flush_offset, SRC_CLIENT);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == 24);
-    CHECK(session_data->get_num_frame_headers(SRC_CLIENT) == 0);
-}
-
-TEST(http2_scan_test, preface_exactly)
-{
-    const StreamSplitter::Status result = implement_scan(session_data,
-        (const uint8_t*)"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n",
-        24, &flush_offset, SRC_CLIENT);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == 24);
-    CHECK(session_data->get_num_frame_headers(SRC_CLIENT) == 0);
-}
-
-TEST(http2_scan_test, short_input)
-{
-    session_data->set_preface(false, SRC_SERVER);
-    StreamSplitter::Status result = implement_scan(session_data,
-        (const uint8_t*)"\x00\x00\x10",
-        3, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::SEARCH);
-    result = implement_scan(session_data, (const uint8_t*)"\x04\x05\x06", 3, &flush_offset,
-        SRC_SERVER);
-    CHECK(result == StreamSplitter::SEARCH);
-    result = implement_scan(session_data, (const uint8_t*)"\x07\x08\x09" "0123456789ABCDEF", 19, &flush_offset,
-        SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == 19);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 1);
-    CHECK(memcmp(session_data->get_scan_frame_header(SRC_SERVER),
-        "\x00\x00\x10\x04\x05\x06\x07\x08\x09", 9) == 0);
-}
-
-TEST(http2_scan_test, oversize_non_data_frame)
-{
-    session_data->set_preface(false, SRC_CLIENT);
-    const StreamSplitter::Status result = implement_scan(session_data,
-        (const uint8_t*)"\x00\xF9\x1C\x01" "12345678901234567",
-        21, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::ABORT);
-}
-
-TEST(http2_scan_test, maximum_frame)
-{
-    uint8_t data[63870] = { 'A' };
-    memcpy(data,"\x00\xF9\x1B\x04", 4);
-    const StreamSplitter::Status result = implement_scan(session_data,
-        data, 63780, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == 63780);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 1);
-}
-
-TEST(http2_scan_test, data_sections)
-{
-    uint8_t data[DATA_SECTION_SIZE+9] ={ 'A' };
-    memcpy(data,"\x01\x21\x3C\x00\x00\x00\x00\x00\x00", 9);
-    StreamSplitter::Status result = implement_scan(session_data,
-        data, DATA_SECTION_SIZE + 9, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == DATA_SECTION_SIZE + 9);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 1);
-    CHECK(session_data->get_leftover_data(SRC_SERVER) == 0xE13C);
-    result = implement_scan(session_data,
-        data, DATA_SECTION_SIZE, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == DATA_SECTION_SIZE);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 0);
-    result = implement_scan(session_data,
-        data, DATA_SECTION_SIZE, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == DATA_SECTION_SIZE);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 0);
-    result = implement_scan(session_data,
-        data, DATA_SECTION_SIZE, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == DATA_SECTION_SIZE);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 0);
-    result = implement_scan(session_data,
-        data, 8508, &flush_offset, SRC_SERVER);
-    CHECK(result == StreamSplitter::FLUSH);
-    CHECK(flush_offset == 8508);
-    CHECK(session_data->get_num_frame_headers(SRC_SERVER) == 0);
-    CHECK(session_data->get_leftover_data(SRC_SERVER) == 0);
-}
-
-TEST_GROUP(http2_reassemble_test)
-{
-    Http2FlowDataTest* session_data = nullptr;
-
-    void setup() override
-    {
-        session_data = new Http2FlowDataTest();
-        CHECK(session_data != nullptr);
-    }
-
-    void teardown() override
-    {
-        session_data->cleanup();
-        delete session_data;
-    }
-};
-
-TEST(http2_reassemble_test, basic_with_header)
-{
-    session_data->set_num_frame_headers(1, SRC_CLIENT);
-    session_data->set_total_bytes_in_split(19, SRC_CLIENT);
-    implement_reassemble(session_data, 19, 0,
-        (const uint8_t*)"\x00\x00\x0A\x02\x00\x00\x00\x00\x00" "0123456789",
-        19, PKT_PDU_TAIL, SRC_CLIENT);
-    CHECK(session_data->get_frame_data_size(SRC_CLIENT) == 10);
-    CHECK(memcmp(session_data->get_frame_data(SRC_CLIENT), "0123456789", 10) == 0);
-}
-
-TEST(http2_reassemble_test, basic_with_header_s2c)
-{
-    session_data->set_num_frame_headers(1, SRC_SERVER);
-    session_data->set_total_bytes_in_split(19, SRC_SERVER);
-    implement_reassemble(session_data, 19, 0,
-        (const uint8_t*)"\x00\x00\x0A\x02\x00\x00\x00\x00\x00" "0123456789",
-        19, PKT_PDU_TAIL, SRC_SERVER);
-    CHECK(session_data->get_frame_data_size(SRC_SERVER) == 10);
-    CHECK(memcmp(session_data->get_frame_data(SRC_SERVER), "0123456789", 10) == 0);
-}
-
-TEST(http2_reassemble_test, basic_without_header)
-{
-    session_data->set_num_frame_headers(0, SRC_CLIENT);
-    session_data->set_octets_before_first_header(24, SRC_CLIENT);
-    session_data->set_total_bytes_in_split(24, SRC_CLIENT);
-    implement_reassemble(session_data, 24, 0,
-        (const uint8_t*)"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n",
-        24, PKT_PDU_TAIL, SRC_CLIENT);
-    CHECK(session_data->get_frame_data_size(SRC_CLIENT) == 24);
-    CHECK(memcmp(session_data->get_frame_data(SRC_CLIENT), "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", 24) == 0);
-}
-
-TEST(http2_reassemble_test, basic_three_pieces)
-{
-    session_data->set_num_frame_headers(1, SRC_CLIENT);
-    session_data->set_total_bytes_in_split(19, SRC_CLIENT);
-    StreamBuffer buffer = implement_reassemble(session_data, 19, 0,
-        (const uint8_t*)"\x00\x00\x0A\x02\x00\x00",
-        6, 0, SRC_CLIENT);
-    CHECK(buffer.length == 0);
-    CHECK(session_data->get_frame_data_size(SRC_CLIENT) == 0);
-    implement_reassemble(session_data, 19, 6,
-        (const uint8_t*)"\x00\x00\x00" "01234",
-        8, 0, SRC_CLIENT);
-    buffer = implement_reassemble(session_data, 19, 14,
-        (const uint8_t*)"56789",
-        5, PKT_PDU_TAIL, SRC_CLIENT);
-    CHECK(buffer.length == 0);
-    CHECK(session_data->get_frame_data_size(SRC_CLIENT) == 10);
-    CHECK(memcmp(session_data->get_frame_data(SRC_CLIENT), "0123456789", 10) == 0);
-}
-
-TEST(http2_reassemble_test, basic_without_header_two_pieces)
-{
-    session_data->set_num_frame_headers(0, SRC_CLIENT);
-    session_data->set_octets_before_first_header(24, SRC_CLIENT);
-    session_data->set_total_bytes_in_split(24, SRC_CLIENT);
-    implement_reassemble(session_data, 24, 0,
-        (const uint8_t*)"P",
-        1, 0, SRC_CLIENT);
-    CHECK(session_data->get_frame_data_size(SRC_CLIENT) == 1);
-    CHECK(memcmp(session_data->get_frame_data(SRC_CLIENT), "P", 1) == 0);
-     implement_reassemble(session_data, 24, 1,
-        (const uint8_t*)"RI * HTTP/2.0\r\n\r\nSM\r\n\r\n",
-        23, PKT_PDU_TAIL, SRC_CLIENT);
-    CHECK(session_data->get_frame_data_size(SRC_CLIENT) == 24);
-    CHECK(memcmp(session_data->get_frame_data(SRC_CLIENT), "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", 24) == 0);
-}
-
-int main(int argc, char** argv)
-{
-    return CommandLineTestRunner::RunAllTests(argc, argv);
-}
-