blob: d57b838aac4c08391872d5ed8941a0468a088569 [file] [log] [blame]
Vernon Mauery08a70aa2018-11-07 09:36:22 -08001/**
2 * Copyright © 2018 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
Vernon Mauery08a70aa2018-11-07 09:36:22 -080017#include <boost/callable_traits.hpp>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070018#include <ipmid/api-types.hpp>
Vernon Mauery08a70aa2018-11-07 09:36:22 -080019#include <ipmid/message.hpp>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050020
21#include <algorithm>
22#include <cstdint>
Vernon Mauery08a70aa2018-11-07 09:36:22 -080023#include <memory>
24#include <tuple>
25#include <utility>
26
27namespace ipmi
28{
29
30using FilterFunction = ipmi::Cc(ipmi::message::Request::ptr);
31
32/**
33 * @brief Filter base class for dealing with IPMI request/response
34 *
35 * The subclasses are all templated so they can provide access to any type of
36 * command callback functions.
37 */
38class FilterBase
39{
40 public:
41 using ptr = std::shared_ptr<FilterBase>;
42
Patrick Williams7d7a6852022-07-25 09:53:19 -050043 virtual ~FilterBase() = default;
44
Vernon Mauery08a70aa2018-11-07 09:36:22 -080045 virtual ipmi::Cc call(message::Request::ptr request) = 0;
46};
47
48/**
49 * @brief filter concrete class
50 *
51 * This is the base template that ipmi filters will resolve into. This is
52 * essentially just a wrapper to hold the filter callback so it can be stored in
53 * the filter list.
54 *
55 * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
56 * commands in priority order and each filter has the opportunity to reject the
57 * command (by returning an IPMI error competion code.) If all the filters
58 * return success, the actual IPMI command will be executed. Filters can reject
59 * the command for any reason, based on system state, the context, the command
60 * payload, etc.
61 */
62template <typename Filter>
63class IpmiFilter : public FilterBase
64{
65 public:
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050066 IpmiFilter(Filter&& filter) : filter_(std::move(filter)) {}
Vernon Mauery08a70aa2018-11-07 09:36:22 -080067
68 ipmi::Cc call(message::Request::ptr request) override
69 {
70 return filter_(request);
71 }
72
73 private:
74 Filter filter_;
75};
76
77/**
78 * @brief helper function to construct a filter object
79 *
80 * This is called internally by the ipmi::registerFilter function.
81 */
82template <typename Filter>
83static inline auto makeFilter(Filter&& filter)
84{
85 FilterBase::ptr ptr(new IpmiFilter<Filter>(std::forward<Filter>(filter)));
86 return ptr;
87}
88template <typename Filter>
89static inline auto makeFilter(const Filter& filter)
90{
91 Filter lFilter = filter;
92 return makeFilter(std::forward<Filter>(lFilter));
93}
94
Vernon Mauerye08fbff2019-04-03 09:19:34 -070095namespace impl
96{
97
98// IPMI command filter registration implementation
99void registerFilter(int prio, ::ipmi::FilterBase::ptr filter);
100
101} // namespace impl
102
103/**
104 * @brief IPMI command filter registration function
105 *
106 * This function should be used to register IPMI command filter functions.
107 * This function just passes the callback to makeFilter, which creates a
108 * wrapper functor object that ultimately calls the callback.
109 *
110 * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
111 * commands in priority order and each filter has the opportunity to reject the
112 * command (by returning an IPMI error competion code.) If all the filters
113 * return success, the actual IPMI command will be executed. Filters can reject
114 * the command for any reason, based on system state, the context, the command
115 * payload, etc.
116 *
117 * @param prio - priority at which to register; see api.hpp
118 * @param filter - the callback function that will handle this request
119 *
120 * @return bool - success of registering the handler
121 */
122template <typename Filter>
123void registerFilter(int prio, Filter&& filter)
124{
125 auto f = ipmi::makeFilter(std::forward<Filter>(filter));
126 impl::registerFilter(prio, f);
127}
128
129template <typename Filter>
130void registerFilter(int prio, const Filter& filter)
131{
132 auto f = ipmi::makeFilter(filter);
133 impl::registerFilter(prio, f);
134}
135
Vernon Mauery08a70aa2018-11-07 09:36:22 -0800136} // namespace ipmi