From: Mike Stepanek (mstepane) Date: Thu, 4 Apr 2019 15:28:52 +0000 (-0400) Subject: Merge pull request #1567 in SNORT/snort3 from ~SMINUT/snort3:stash_publish to master X-Git-Tag: 3.0.0-252~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80b43b64fecfe5268eceb60542ed0bfb75721d34;p=thirdparty%2Fsnort3.git Merge pull request #1567 in SNORT/snort3 from ~SMINUT/snort3:stash_publish to master Squashed commit of the following: commit 85edf32e438e758638f26c854eb0b81edfdbc0d6 Author: Silviu Minut 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. --- diff --git a/src/flow/flow_cache.cc b/src/flow/flow_cache.cc index d1c800303..2224ecd28 100644 --- a/src/flow/flow_cache.cc +++ b/src/flow/flow_cache.cc @@ -352,4 +352,3 @@ unsigned FlowCache::purge() return retired; } - diff --git a/src/flow/flow_stash.cc b/src/flow/flow_stash.cc index 5ab509285..7a9681cba 100644 --- a/src/flow/flow_stash.cc +++ b/src/flow/flow_stash.cc @@ -22,6 +22,8 @@ #include +#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); } diff --git a/src/flow/test/flow_stash_test.cc b/src/flow/test/flow_stash_test.cc index 14751b04d..983d9fafd 100644 --- a/src/flow/test/flow_stash_test.cc +++ b/src/flow/test/flow_stash_test.cc @@ -21,6 +21,7 @@ #include #include "flow/flow_stash.h" +#include "pub_sub/stash_events.h" #include #include @@ -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 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(&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 +const char* DBConsumer::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* c = new DBConsumer("foo"); + DataBus::subscribe(DBConsumer::STASH_EVENT, c); + + FlowStash stash; + value_t vin, vout; + + // stash/publish 10 + vin = 10; + stash.store(DBConsumer::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::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 index 000000000..a3adafe16 --- /dev/null +++ b/src/pub_sub/stash_events.h @@ -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 + +#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