blob: 8b3a6524df91108431b47b3b5fd8ef65c3efcd8e [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
17#include <algorithm>
18#include <boost/callable_traits.hpp>
19#include <cstdint>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070020#include <ipmid/api-types.hpp>
Vernon Mauery08a70aa2018-11-07 09:36:22 -080021#include <ipmid/message.hpp>
22#include <memory>
23#include <tuple>
24#include <utility>
25
26namespace ipmi
27{
28
29using FilterFunction = ipmi::Cc(ipmi::message::Request::ptr);
30
31/**
32 * @brief Filter base class for dealing with IPMI request/response
33 *
34 * The subclasses are all templated so they can provide access to any type of
35 * command callback functions.
36 */
37class FilterBase
38{
39 public:
40 using ptr = std::shared_ptr<FilterBase>;
41
Patrick Williams7d7a6852022-07-25 09:53:19 -050042 virtual ~FilterBase() = default;
43
Vernon Mauery08a70aa2018-11-07 09:36:22 -080044 virtual ipmi::Cc call(message::Request::ptr request) = 0;
45};
46
47/**
48 * @brief filter concrete class
49 *
50 * This is the base template that ipmi filters will resolve into. This is
51 * essentially just a wrapper to hold the filter callback so it can be stored in
52 * the filter list.
53 *
54 * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
55 * commands in priority order and each filter has the opportunity to reject the
56 * command (by returning an IPMI error competion code.) If all the filters
57 * return success, the actual IPMI command will be executed. Filters can reject
58 * the command for any reason, based on system state, the context, the command
59 * payload, etc.
60 */
61template <typename Filter>
62class IpmiFilter : public FilterBase
63{
64 public:
65 IpmiFilter(Filter&& filter) : filter_(std::move(filter))
66 {
67 }
68
69 ipmi::Cc call(message::Request::ptr request) override
70 {
71 return filter_(request);
72 }
73
74 private:
75 Filter filter_;
76};
77
78/**
79 * @brief helper function to construct a filter object
80 *
81 * This is called internally by the ipmi::registerFilter function.
82 */
83template <typename Filter>
84static inline auto makeFilter(Filter&& filter)
85{
86 FilterBase::ptr ptr(new IpmiFilter<Filter>(std::forward<Filter>(filter)));
87 return ptr;
88}
89template <typename Filter>
90static inline auto makeFilter(const Filter& filter)
91{
92 Filter lFilter = filter;
93 return makeFilter(std::forward<Filter>(lFilter));
94}
95
Vernon Mauerye08fbff2019-04-03 09:19:34 -070096namespace impl
97{
98
99// IPMI command filter registration implementation
100void registerFilter(int prio, ::ipmi::FilterBase::ptr filter);
101
102} // namespace impl
103
104/**
105 * @brief IPMI command filter registration function
106 *
107 * This function should be used to register IPMI command filter functions.
108 * This function just passes the callback to makeFilter, which creates a
109 * wrapper functor object that ultimately calls the callback.
110 *
111 * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
112 * commands in priority order and each filter has the opportunity to reject the
113 * command (by returning an IPMI error competion code.) If all the filters
114 * return success, the actual IPMI command will be executed. Filters can reject
115 * the command for any reason, based on system state, the context, the command
116 * payload, etc.
117 *
118 * @param prio - priority at which to register; see api.hpp
119 * @param filter - the callback function that will handle this request
120 *
121 * @return bool - success of registering the handler
122 */
123template <typename Filter>
124void registerFilter(int prio, Filter&& filter)
125{
126 auto f = ipmi::makeFilter(std::forward<Filter>(filter));
127 impl::registerFilter(prio, f);
128}
129
130template <typename Filter>
131void registerFilter(int prio, const Filter& filter)
132{
133 auto f = ipmi::makeFilter(filter);
134 impl::registerFilter(prio, f);
135}
136
Vernon Mauery08a70aa2018-11-07 09:36:22 -0800137} // namespace ipmi