108a70aa5SVernon Mauery /** 208a70aa5SVernon Mauery * Copyright © 2018 Intel Corporation 308a70aa5SVernon Mauery * 408a70aa5SVernon Mauery * Licensed under the Apache License, Version 2.0 (the "License"); 508a70aa5SVernon Mauery * you may not use this file except in compliance with the License. 608a70aa5SVernon Mauery * You may obtain a copy of the License at 708a70aa5SVernon Mauery * 808a70aa5SVernon Mauery * http://www.apache.org/licenses/LICENSE-2.0 908a70aa5SVernon Mauery * 1008a70aa5SVernon Mauery * Unless required by applicable law or agreed to in writing, software 1108a70aa5SVernon Mauery * distributed under the License is distributed on an "AS IS" BASIS, 1208a70aa5SVernon Mauery * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1308a70aa5SVernon Mauery * See the License for the specific language governing permissions and 1408a70aa5SVernon Mauery * limitations under the License. 1508a70aa5SVernon Mauery */ 1608a70aa5SVernon Mauery #pragma once 1708a70aa5SVernon Mauery #include <algorithm> 1808a70aa5SVernon Mauery #include <boost/callable_traits.hpp> 1908a70aa5SVernon Mauery #include <cstdint> 20e08fbffcSVernon Mauery #include <ipmid/api-types.hpp> 2108a70aa5SVernon Mauery #include <ipmid/message.hpp> 2208a70aa5SVernon Mauery #include <memory> 2308a70aa5SVernon Mauery #include <tuple> 2408a70aa5SVernon Mauery #include <utility> 2508a70aa5SVernon Mauery 2608a70aa5SVernon Mauery namespace ipmi 2708a70aa5SVernon Mauery { 2808a70aa5SVernon Mauery 2908a70aa5SVernon Mauery using FilterFunction = ipmi::Cc(ipmi::message::Request::ptr); 3008a70aa5SVernon Mauery 3108a70aa5SVernon Mauery /** 3208a70aa5SVernon Mauery * @brief Filter base class for dealing with IPMI request/response 3308a70aa5SVernon Mauery * 3408a70aa5SVernon Mauery * The subclasses are all templated so they can provide access to any type of 3508a70aa5SVernon Mauery * command callback functions. 3608a70aa5SVernon Mauery */ 3708a70aa5SVernon Mauery class FilterBase 3808a70aa5SVernon Mauery { 3908a70aa5SVernon Mauery public: 4008a70aa5SVernon Mauery using ptr = std::shared_ptr<FilterBase>; 4108a70aa5SVernon Mauery 42*7d7a6858SPatrick Williams virtual ~FilterBase() = default; 43*7d7a6858SPatrick Williams 4408a70aa5SVernon Mauery virtual ipmi::Cc call(message::Request::ptr request) = 0; 4508a70aa5SVernon Mauery }; 4608a70aa5SVernon Mauery 4708a70aa5SVernon Mauery /** 4808a70aa5SVernon Mauery * @brief filter concrete class 4908a70aa5SVernon Mauery * 5008a70aa5SVernon Mauery * This is the base template that ipmi filters will resolve into. This is 5108a70aa5SVernon Mauery * essentially just a wrapper to hold the filter callback so it can be stored in 5208a70aa5SVernon Mauery * the filter list. 5308a70aa5SVernon Mauery * 5408a70aa5SVernon Mauery * Filters are called with a ipmi::message::Request shared_ptr on all IPMI 5508a70aa5SVernon Mauery * commands in priority order and each filter has the opportunity to reject the 5608a70aa5SVernon Mauery * command (by returning an IPMI error competion code.) If all the filters 5708a70aa5SVernon Mauery * return success, the actual IPMI command will be executed. Filters can reject 5808a70aa5SVernon Mauery * the command for any reason, based on system state, the context, the command 5908a70aa5SVernon Mauery * payload, etc. 6008a70aa5SVernon Mauery */ 6108a70aa5SVernon Mauery template <typename Filter> 6208a70aa5SVernon Mauery class IpmiFilter : public FilterBase 6308a70aa5SVernon Mauery { 6408a70aa5SVernon Mauery public: 6508a70aa5SVernon Mauery IpmiFilter(Filter&& filter) : filter_(std::move(filter)) 6608a70aa5SVernon Mauery { 6708a70aa5SVernon Mauery } 6808a70aa5SVernon Mauery 6908a70aa5SVernon Mauery ipmi::Cc call(message::Request::ptr request) override 7008a70aa5SVernon Mauery { 7108a70aa5SVernon Mauery return filter_(request); 7208a70aa5SVernon Mauery } 7308a70aa5SVernon Mauery 7408a70aa5SVernon Mauery private: 7508a70aa5SVernon Mauery Filter filter_; 7608a70aa5SVernon Mauery }; 7708a70aa5SVernon Mauery 7808a70aa5SVernon Mauery /** 7908a70aa5SVernon Mauery * @brief helper function to construct a filter object 8008a70aa5SVernon Mauery * 8108a70aa5SVernon Mauery * This is called internally by the ipmi::registerFilter function. 8208a70aa5SVernon Mauery */ 8308a70aa5SVernon Mauery template <typename Filter> 8408a70aa5SVernon Mauery static inline auto makeFilter(Filter&& filter) 8508a70aa5SVernon Mauery { 8608a70aa5SVernon Mauery FilterBase::ptr ptr(new IpmiFilter<Filter>(std::forward<Filter>(filter))); 8708a70aa5SVernon Mauery return ptr; 8808a70aa5SVernon Mauery } 8908a70aa5SVernon Mauery template <typename Filter> 9008a70aa5SVernon Mauery static inline auto makeFilter(const Filter& filter) 9108a70aa5SVernon Mauery { 9208a70aa5SVernon Mauery Filter lFilter = filter; 9308a70aa5SVernon Mauery return makeFilter(std::forward<Filter>(lFilter)); 9408a70aa5SVernon Mauery } 9508a70aa5SVernon Mauery 96e08fbffcSVernon Mauery namespace impl 97e08fbffcSVernon Mauery { 98e08fbffcSVernon Mauery 99e08fbffcSVernon Mauery // IPMI command filter registration implementation 100e08fbffcSVernon Mauery void registerFilter(int prio, ::ipmi::FilterBase::ptr filter); 101e08fbffcSVernon Mauery 102e08fbffcSVernon Mauery } // namespace impl 103e08fbffcSVernon Mauery 104e08fbffcSVernon Mauery /** 105e08fbffcSVernon Mauery * @brief IPMI command filter registration function 106e08fbffcSVernon Mauery * 107e08fbffcSVernon Mauery * This function should be used to register IPMI command filter functions. 108e08fbffcSVernon Mauery * This function just passes the callback to makeFilter, which creates a 109e08fbffcSVernon Mauery * wrapper functor object that ultimately calls the callback. 110e08fbffcSVernon Mauery * 111e08fbffcSVernon Mauery * Filters are called with a ipmi::message::Request shared_ptr on all IPMI 112e08fbffcSVernon Mauery * commands in priority order and each filter has the opportunity to reject the 113e08fbffcSVernon Mauery * command (by returning an IPMI error competion code.) If all the filters 114e08fbffcSVernon Mauery * return success, the actual IPMI command will be executed. Filters can reject 115e08fbffcSVernon Mauery * the command for any reason, based on system state, the context, the command 116e08fbffcSVernon Mauery * payload, etc. 117e08fbffcSVernon Mauery * 118e08fbffcSVernon Mauery * @param prio - priority at which to register; see api.hpp 119e08fbffcSVernon Mauery * @param filter - the callback function that will handle this request 120e08fbffcSVernon Mauery * 121e08fbffcSVernon Mauery * @return bool - success of registering the handler 122e08fbffcSVernon Mauery */ 123e08fbffcSVernon Mauery template <typename Filter> 124e08fbffcSVernon Mauery void registerFilter(int prio, Filter&& filter) 125e08fbffcSVernon Mauery { 126e08fbffcSVernon Mauery auto f = ipmi::makeFilter(std::forward<Filter>(filter)); 127e08fbffcSVernon Mauery impl::registerFilter(prio, f); 128e08fbffcSVernon Mauery } 129e08fbffcSVernon Mauery 130e08fbffcSVernon Mauery template <typename Filter> 131e08fbffcSVernon Mauery void registerFilter(int prio, const Filter& filter) 132e08fbffcSVernon Mauery { 133e08fbffcSVernon Mauery auto f = ipmi::makeFilter(filter); 134e08fbffcSVernon Mauery impl::registerFilter(prio, f); 135e08fbffcSVernon Mauery } 136e08fbffcSVernon Mauery 13708a70aa5SVernon Mauery } // namespace ipmi 138