blob: 950e3c3f255a207f77827ba52271945f4f388ef9 [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
42 virtual ipmi::Cc call(message::Request::ptr request) = 0;
43};
44
45/**
46 * @brief filter concrete class
47 *
48 * This is the base template that ipmi filters will resolve into. This is
49 * essentially just a wrapper to hold the filter callback so it can be stored in
50 * the filter list.
51 *
52 * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
53 * commands in priority order and each filter has the opportunity to reject the
54 * command (by returning an IPMI error competion code.) If all the filters
55 * return success, the actual IPMI command will be executed. Filters can reject
56 * the command for any reason, based on system state, the context, the command
57 * payload, etc.
58 */
59template <typename Filter>
60class IpmiFilter : public FilterBase
61{
62 public:
63 IpmiFilter(Filter&& filter) : filter_(std::move(filter))
64 {
65 }
66
67 ipmi::Cc call(message::Request::ptr request) override
68 {
69 return filter_(request);
70 }
71
72 private:
73 Filter filter_;
74};
75
76/**
77 * @brief helper function to construct a filter object
78 *
79 * This is called internally by the ipmi::registerFilter function.
80 */
81template <typename Filter>
82static inline auto makeFilter(Filter&& filter)
83{
84 FilterBase::ptr ptr(new IpmiFilter<Filter>(std::forward<Filter>(filter)));
85 return ptr;
86}
87template <typename Filter>
88static inline auto makeFilter(const Filter& filter)
89{
90 Filter lFilter = filter;
91 return makeFilter(std::forward<Filter>(lFilter));
92}
93
Vernon Mauerye08fbff2019-04-03 09:19:34 -070094namespace impl
95{
96
97// IPMI command filter registration implementation
98void registerFilter(int prio, ::ipmi::FilterBase::ptr filter);
99
100} // namespace impl
101
102/**
103 * @brief IPMI command filter registration function
104 *
105 * This function should be used to register IPMI command filter functions.
106 * This function just passes the callback to makeFilter, which creates a
107 * wrapper functor object that ultimately calls the callback.
108 *
109 * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
110 * commands in priority order and each filter has the opportunity to reject the
111 * command (by returning an IPMI error competion code.) If all the filters
112 * return success, the actual IPMI command will be executed. Filters can reject
113 * the command for any reason, based on system state, the context, the command
114 * payload, etc.
115 *
116 * @param prio - priority at which to register; see api.hpp
117 * @param filter - the callback function that will handle this request
118 *
119 * @return bool - success of registering the handler
120 */
121template <typename Filter>
122void registerFilter(int prio, Filter&& filter)
123{
124 auto f = ipmi::makeFilter(std::forward<Filter>(filter));
125 impl::registerFilter(prio, f);
126}
127
128template <typename Filter>
129void registerFilter(int prio, const Filter& filter)
130{
131 auto f = ipmi::makeFilter(filter);
132 impl::registerFilter(prio, f);
133}
134
Vernon Mauery08a70aa2018-11-07 09:36:22 -0800135} // namespace ipmi