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> 20*e08fbffcSVernon 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 4208a70aa5SVernon Mauery virtual ipmi::Cc call(message::Request::ptr request) = 0; 4308a70aa5SVernon Mauery }; 4408a70aa5SVernon Mauery 4508a70aa5SVernon Mauery /** 4608a70aa5SVernon Mauery * @brief filter concrete class 4708a70aa5SVernon Mauery * 4808a70aa5SVernon Mauery * This is the base template that ipmi filters will resolve into. This is 4908a70aa5SVernon Mauery * essentially just a wrapper to hold the filter callback so it can be stored in 5008a70aa5SVernon Mauery * the filter list. 5108a70aa5SVernon Mauery * 5208a70aa5SVernon Mauery * Filters are called with a ipmi::message::Request shared_ptr on all IPMI 5308a70aa5SVernon Mauery * commands in priority order and each filter has the opportunity to reject the 5408a70aa5SVernon Mauery * command (by returning an IPMI error competion code.) If all the filters 5508a70aa5SVernon Mauery * return success, the actual IPMI command will be executed. Filters can reject 5608a70aa5SVernon Mauery * the command for any reason, based on system state, the context, the command 5708a70aa5SVernon Mauery * payload, etc. 5808a70aa5SVernon Mauery */ 5908a70aa5SVernon Mauery template <typename Filter> 6008a70aa5SVernon Mauery class IpmiFilter : public FilterBase 6108a70aa5SVernon Mauery { 6208a70aa5SVernon Mauery public: 6308a70aa5SVernon Mauery IpmiFilter(Filter&& filter) : filter_(std::move(filter)) 6408a70aa5SVernon Mauery { 6508a70aa5SVernon Mauery } 6608a70aa5SVernon Mauery 6708a70aa5SVernon Mauery ipmi::Cc call(message::Request::ptr request) override 6808a70aa5SVernon Mauery { 6908a70aa5SVernon Mauery return filter_(request); 7008a70aa5SVernon Mauery } 7108a70aa5SVernon Mauery 7208a70aa5SVernon Mauery private: 7308a70aa5SVernon Mauery Filter filter_; 7408a70aa5SVernon Mauery }; 7508a70aa5SVernon Mauery 7608a70aa5SVernon Mauery /** 7708a70aa5SVernon Mauery * @brief helper function to construct a filter object 7808a70aa5SVernon Mauery * 7908a70aa5SVernon Mauery * This is called internally by the ipmi::registerFilter function. 8008a70aa5SVernon Mauery */ 8108a70aa5SVernon Mauery template <typename Filter> 8208a70aa5SVernon Mauery static inline auto makeFilter(Filter&& filter) 8308a70aa5SVernon Mauery { 8408a70aa5SVernon Mauery FilterBase::ptr ptr(new IpmiFilter<Filter>(std::forward<Filter>(filter))); 8508a70aa5SVernon Mauery return ptr; 8608a70aa5SVernon Mauery } 8708a70aa5SVernon Mauery template <typename Filter> 8808a70aa5SVernon Mauery static inline auto makeFilter(const Filter& filter) 8908a70aa5SVernon Mauery { 9008a70aa5SVernon Mauery Filter lFilter = filter; 9108a70aa5SVernon Mauery return makeFilter(std::forward<Filter>(lFilter)); 9208a70aa5SVernon Mauery } 9308a70aa5SVernon Mauery 94*e08fbffcSVernon Mauery namespace impl 95*e08fbffcSVernon Mauery { 96*e08fbffcSVernon Mauery 97*e08fbffcSVernon Mauery // IPMI command filter registration implementation 98*e08fbffcSVernon Mauery void registerFilter(int prio, ::ipmi::FilterBase::ptr filter); 99*e08fbffcSVernon Mauery 100*e08fbffcSVernon Mauery } // namespace impl 101*e08fbffcSVernon Mauery 102*e08fbffcSVernon Mauery /** 103*e08fbffcSVernon Mauery * @brief IPMI command filter registration function 104*e08fbffcSVernon Mauery * 105*e08fbffcSVernon Mauery * This function should be used to register IPMI command filter functions. 106*e08fbffcSVernon Mauery * This function just passes the callback to makeFilter, which creates a 107*e08fbffcSVernon Mauery * wrapper functor object that ultimately calls the callback. 108*e08fbffcSVernon Mauery * 109*e08fbffcSVernon Mauery * Filters are called with a ipmi::message::Request shared_ptr on all IPMI 110*e08fbffcSVernon Mauery * commands in priority order and each filter has the opportunity to reject the 111*e08fbffcSVernon Mauery * command (by returning an IPMI error competion code.) If all the filters 112*e08fbffcSVernon Mauery * return success, the actual IPMI command will be executed. Filters can reject 113*e08fbffcSVernon Mauery * the command for any reason, based on system state, the context, the command 114*e08fbffcSVernon Mauery * payload, etc. 115*e08fbffcSVernon Mauery * 116*e08fbffcSVernon Mauery * @param prio - priority at which to register; see api.hpp 117*e08fbffcSVernon Mauery * @param filter - the callback function that will handle this request 118*e08fbffcSVernon Mauery * 119*e08fbffcSVernon Mauery * @return bool - success of registering the handler 120*e08fbffcSVernon Mauery */ 121*e08fbffcSVernon Mauery template <typename Filter> 122*e08fbffcSVernon Mauery void registerFilter(int prio, Filter&& filter) 123*e08fbffcSVernon Mauery { 124*e08fbffcSVernon Mauery auto f = ipmi::makeFilter(std::forward<Filter>(filter)); 125*e08fbffcSVernon Mauery impl::registerFilter(prio, f); 126*e08fbffcSVernon Mauery } 127*e08fbffcSVernon Mauery 128*e08fbffcSVernon Mauery template <typename Filter> 129*e08fbffcSVernon Mauery void registerFilter(int prio, const Filter& filter) 130*e08fbffcSVernon Mauery { 131*e08fbffcSVernon Mauery auto f = ipmi::makeFilter(filter); 132*e08fbffcSVernon Mauery impl::registerFilter(prio, f); 133*e08fbffcSVernon Mauery } 134*e08fbffcSVernon Mauery 13508a70aa5SVernon Mauery } // namespace ipmi 136