]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1567 in SNORT/snort3 from ~SMINUT/snort3:stash_publish to master
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Thu, 4 Apr 2019 15:28:52 +0000 (11:28 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Thu, 4 Apr 2019 15:28:52 +0000 (11:28 -0400)
Squashed commit of the following:

commit 85edf32e438e758638f26c854eb0b81edfdbc0d6
Author: Silviu Minut <sminut@cisco.com>
Date:   Fri Mar 29 16:06:09 2019 -0400

    flow: stash publish event.

    flow: unit test for stash publish.

    flow: address reviewers comments and add one more test to check that a handler is not getting stash events that it's not listening to.

    flow: add the override keyword to some member function to keep cppcheck happy.

src/flow/flow_cache.cc
src/flow/flow_stash.cc
src/flow/test/flow_stash_test.cc
src/pub_sub/stash_events.h [new file with mode: 0644]

index d1c80030352516354dce3f42d34009f9ee83e1c0..2224ecd28f8150cbe199a485b483905949d5f648 100644 (file)
@@ -352,4 +352,3 @@ unsigned FlowCache::purge()
 
     return retired;
 }
-
index 5ab50928540d47f193558b9639a315d073372c73..7a9681cbae35b68ea2f090727d4020071f56582b 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <cassert>
 
+#include "pub_sub/stash_events.h"
+
 using namespace snort;
 using namespace std;
 
@@ -86,6 +88,9 @@ void FlowStash::store(const string& key, StashGenericObject* &val, StashItemType
         delete it_and_status.first->second;
         it_and_status.first->second = item;
     }
+
+    StashEvent e(item);
+    DataBus::publish(key.c_str(), e);
 }
 
 void FlowStash::store(const std::string& key, std::string* val)
@@ -125,4 +130,7 @@ void FlowStash::store(const string& key, T& val, StashItemType type)
         delete it_and_status.first->second;
         it_and_status.first->second = item;
     }
+
+    StashEvent e(item);
+    DataBus::publish(key.c_str(), e);
 }
index 14751b04d1c75190ccb1a4a48c1977539d0cde50..983d9fafd2e529eb6aabb262b0085265a4d49293 100644 (file)
@@ -21,6 +21,7 @@
 #include <string>
 
 #include "flow/flow_stash.h"
+#include "pub_sub/stash_events.h"
 
 #include <CppUTest/CommandLineTestRunner.h>
 #include <CppUTest/TestHarness.h>
@@ -28,6 +29,9 @@
 using namespace snort;
 using namespace std;
 
+
+static DataBus* DB = nullptr;
+
 class TestStashObject : public StashGenericObject
 {
 public:
@@ -37,11 +41,149 @@ public:
     }
 };
 
+
+template<class Type>
+class DBConsumer : public DataHandler
+{
+public:
+
+    static const char* STASH_EVENT;
+
+    // event we'll be listening to on the DataBus:
+    // static constexpr char STASH_EVENT[] = "foo.stash.event";
+
+    DBConsumer(const char* mod_name) : DataHandler(mod_name) {}
+
+    void handle(DataEvent& e, Flow*) override
+    {
+        const StashEvent* se = static_cast<const StashEvent*>(&e);
+        se->get_item()->get_val(value);
+    }
+
+    Type get_from_stash(FlowStash& stash)
+    {
+        stash.get(STASH_EVENT, value);
+        return value;
+    }
+
+    Type get_value() const { return value; }
+
+private:
+    Type value;
+};
+
+template<class Type>
+const char* DBConsumer<Type>::STASH_EVENT = "foo.stash.event";
+
+
+
+// DataBus mock: most functions are stubs, but _subscribe() and  _publish()
+// are (close to) real.
+DataBus::DataBus() = default;
+
+DataBus::~DataBus()
+{
+    for ( auto& p : map )
+        for ( auto* h : p.second )
+            delete h;
+}
+
+void DataBus::add_mapped_module(const char*) {}
+void DataBus::clone(DataBus& ) {}
+void DataBus::subscribe(const char* key, DataHandler* h)
+{
+    DB->_subscribe(key, h);
+}
+void DataBus::subscribe_default(const char* key, DataHandler* h)
+{
+    DB->_subscribe(key, h);
+}
+
+void DataBus::unsubscribe(const char*, DataHandler*) {}
+void DataBus::unsubscribe_default(const char*, DataHandler*) {}
+
+void DataBus::publish(const char* key, DataEvent& e, Flow* f)
+{
+    DB->_publish(key, e, f);
+}
+
+void DataBus::publish(const char*, const uint8_t*, unsigned, Flow*) {}
+void DataBus::publish(const char*, Packet*, Flow*) {}
+void DataBus::publish(const char*, void*, int, const uint8_t*) {}
+
+void DataBus::_subscribe(const char* key, DataHandler* h)
+{
+    DataList& v = map[key];
+    v.emplace_back(h);
+}
+
+void DataBus::_unsubscribe(const char*, DataHandler*) {}
+
+void DataBus::_publish(const char* key, DataEvent& e, Flow* f)
+{
+    auto v = map.find(key);
+
+    if ( v != map.end() )
+    {
+        for ( auto* h : v->second )
+            h->handle(e, f);
+    }
+}
+// end DataBus mock.
+
+
+
 TEST_GROUP(stash_tests)
 {
+    void setup()
+    {
+        DB = new DataBus();
+    }
 
+    void teardown()
+    {
+        delete DB;
+    }
 };
 
+// DataBus tests
+TEST(stash_tests, data_bus_publish_test)
+{
+    typedef int32_t value_t;
+
+    // DB deletes the subscribers so make c a pointer, not a local object.
+    DBConsumer<value_t>* c = new DBConsumer<value_t>("foo");
+    DataBus::subscribe(DBConsumer<value_t>::STASH_EVENT, c);
+
+    FlowStash stash;
+    value_t vin, vout;
+
+    // stash/publish 10
+    vin = 10;
+    stash.store(DBConsumer<value_t>::STASH_EVENT, vin);
+    vout = c->get_value();
+    CHECK_EQUAL(vin, vout);
+
+    // stash/publish 20, with the same key as before
+    vin = 20;
+    stash.store(DBConsumer<value_t>::STASH_EVENT, vin);
+    vout = c->get_value();
+    CHECK_EQUAL(vin, vout);
+
+    // do we get some event that we're not listening to?
+    value_t before = c->get_value();
+    stash.store("bar.stash.event", 30);
+    value_t after = c->get_value();
+    CHECK_EQUAL(before, after);
+
+    // do we still get our own STASH_EVENT from the stash, at a later time?
+    vout = c->get_from_stash(stash);
+    CHECK_EQUAL(vin, vout);
+
+}
+
+
+// Stash tests
 TEST(stash_tests, new_int32_item)
 {
     FlowStash stash;
diff --git a/src/pub_sub/stash_events.h b/src/pub_sub/stash_events.h
new file mode 100644 (file)
index 0000000..a3adafe
--- /dev/null
@@ -0,0 +1,36 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+// stash_events.h author Silviu Minut <sminut@cisco.com>
+
+#ifndef STASH_EVENTS_H
+#define STASH_EVENTS_H
+
+#include "framework/data_bus.h"
+
+using snort::StashItem;
+
+class StashEvent : public snort::DataEvent
+{
+public:
+    StashEvent(const StashItem* it = nullptr) : item(it) {}
+    const StashItem* get_item() const { return item; }
+private:
+    const StashItem* item;
+};
+
+#endif