diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/Makefile.am | 1 | ||||
-rw-r--r-- | include/ipmid/filter.hpp | 94 | ||||
-rw-r--r-- | include/ipmid/registration.hpp | 36 |
3 files changed, 131 insertions, 0 deletions
diff --git a/include/Makefile.am b/include/Makefile.am index 4c0e899..852b26b 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,6 @@ nobase_include_HEADERS = \ ipmid/api.hpp \ + ipmid/filter.hpp \ ipmid/handler.hpp \ ipmid/message.hpp \ ipmid/message/pack.hpp \ diff --git a/include/ipmid/filter.hpp b/include/ipmid/filter.hpp new file mode 100644 index 0000000..3cd5d21 --- /dev/null +++ b/include/ipmid/filter.hpp @@ -0,0 +1,94 @@ +/** + * Copyright © 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once +#include <algorithm> +#include <boost/callable_traits.hpp> +#include <cstdint> +#include <ipmid/api.hpp> +#include <ipmid/message.hpp> +#include <memory> +#include <tuple> +#include <utility> + +namespace ipmi +{ + +using FilterFunction = ipmi::Cc(ipmi::message::Request::ptr); + +/** + * @brief Filter base class for dealing with IPMI request/response + * + * The subclasses are all templated so they can provide access to any type of + * command callback functions. + */ +class FilterBase +{ + public: + using ptr = std::shared_ptr<FilterBase>; + + virtual ipmi::Cc call(message::Request::ptr request) = 0; +}; + +/** + * @brief filter concrete class + * + * This is the base template that ipmi filters will resolve into. This is + * essentially just a wrapper to hold the filter callback so it can be stored in + * the filter list. + * + * Filters are called with a ipmi::message::Request shared_ptr on all IPMI + * commands in priority order and each filter has the opportunity to reject the + * command (by returning an IPMI error competion code.) If all the filters + * return success, the actual IPMI command will be executed. Filters can reject + * the command for any reason, based on system state, the context, the command + * payload, etc. + */ +template <typename Filter> +class IpmiFilter : public FilterBase +{ + public: + IpmiFilter(Filter&& filter) : filter_(std::move(filter)) + { + } + + ipmi::Cc call(message::Request::ptr request) override + { + return filter_(request); + } + + private: + Filter filter_; +}; + +/** + * @brief helper function to construct a filter object + * + * This is called internally by the ipmi::registerFilter function. + */ +template <typename Filter> +static inline auto makeFilter(Filter&& filter) +{ + FilterBase::ptr ptr(new IpmiFilter<Filter>(std::forward<Filter>(filter))); + return ptr; +} +template <typename Filter> +static inline auto makeFilter(const Filter& filter) +{ + Filter lFilter = filter; + return makeFilter(std::forward<Filter>(lFilter)); +} + +} // namespace ipmi diff --git a/include/ipmid/registration.hpp b/include/ipmid/registration.hpp index af89bc8..45391ec 100644 --- a/include/ipmid/registration.hpp +++ b/include/ipmid/registration.hpp @@ -16,6 +16,7 @@ #pragma once #include <ipmid/api.hpp> +#include <ipmid/filter.hpp> #include <ipmid/handler.hpp> namespace ipmi @@ -32,6 +33,9 @@ bool registerGroupHandler(int prio, Group group, Cmd cmd, Privilege priv, bool registerOemHandler(int prio, Iana iana, Cmd cmd, Privilege priv, ::ipmi::HandlerBase::ptr handler); +// IPMI command filter registration implementation +void registerFilter(int prio, ::ipmi::FilterBase::ptr filter); + } // namespace impl /** @@ -132,6 +136,38 @@ void registerOemHandler(int prio, Iana iana, Cmd cmd, Privilege priv, impl::registerOemHandler(prio, iana, cmd, priv, h); } +/** + * @brief IPMI command filter registration function + * + * This function should be used to register IPMI command filter functions. + * This function just passes the callback to makeFilter, which creates a + * wrapper functor object that ultimately calls the callback. + * + * Filters are called with a ipmi::message::Request shared_ptr on all IPMI + * commands in priority order and each filter has the opportunity to reject the + * command (by returning an IPMI error competion code.) If all the filters + * return success, the actual IPMI command will be executed. Filters can reject + * the command for any reason, based on system state, the context, the command + * payload, etc. + * + * @param prio - priority at which to register; see api.hpp + * @param filter - the callback function that will handle this request + * + * @return bool - success of registering the handler + */ +template <typename Filter> +void registerFilter(int prio, Filter&& filter) +{ + auto f = ipmi::makeFilter(std::forward<Filter>(filter)); + impl::registerFilter(prio, f); +} + +template <typename Filter> +void registerFilter(int prio, const Filter& filter) +{ + auto f = ipmi::makeFilter(filter); + impl::registerFilter(prio, f); +} } // namespace ipmi #ifdef ALLOW_DEPRECATED_API |