1 // Copyright (C) 2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 #include "../include/channel_impl.hpp"
6 #include <vsomeip/internal/logger.hpp>
7
8 namespace vsomeip_v3 {
9 namespace trace {
10
11 const filter_id_t FILTER_ID_ERROR(0);
12
channel_impl(const std::string & _id,const std::string & _name)13 channel_impl::channel_impl(const std::string &_id, const std::string &_name)
14 : id_(_id), name_(_name), current_filter_id_(1) {
15 }
16
get_id() const17 std::string channel_impl::get_id() const {
18 return id_;
19 }
20
get_name() const21 std::string channel_impl::get_name() const {
22 return name_;
23 }
24
add_filter(const match_t & _match,bool _is_positive)25 filter_id_t channel_impl::add_filter(
26 const match_t &_match, bool _is_positive) {
27
28 // Create a filter function
29 std::function<bool (service_t, instance_t, method_t)> its_filter_func;
30 if (std::get<0>(_match) != ANY_SERVICE) {
31 if (std::get<1>(_match) != ANY_INSTANCE) {
32 if (std::get<2>(_match) != ANY_METHOD) {
33 its_filter_func
34 = [_match](service_t _s, instance_t _i, method_t _m) {
35 return (std::get<0>(_match) == _s
36 && std::get<1>(_match) == _i
37 && std::get<2>(_match) == _m);
38 };
39 } else {
40 its_filter_func
41 = [_match](service_t _s, instance_t _i, method_t) {
42 return (std::get<0>(_match) == _s
43 && std::get<1>(_match) == _i);
44 };
45 }
46 } else {
47 if (std::get<2>(_match) != ANY_METHOD) {
48 its_filter_func
49 = [_match](service_t _s, instance_t, method_t _m) {
50 return (std::get<0>(_match) == _s
51 && std::get<1>(_match) == _m);
52 };
53 } else {
54 its_filter_func
55 = [_match](service_t _s, instance_t, method_t) {
56 return (std::get<0>(_match) == _s);
57 };
58 }
59 }
60 } else {
61 if (std::get<1>(_match) != ANY_INSTANCE) {
62 if (std::get<2>(_match) != ANY_METHOD) {
63 its_filter_func
64 = [_match](service_t, instance_t _i, method_t _m) {
65 return (std::get<1>(_match) == _i
66 && std::get<2>(_match) == _m);
67 };
68 } else {
69 its_filter_func
70 = [_match](service_t, instance_t _i, method_t) {
71 return (std::get<1>(_match) == _i);
72 };
73 }
74 } else {
75 if (std::get<2>(_match) != ANY_METHOD) {
76 its_filter_func
77 = [_match](service_t, instance_t, method_t _m) {
78 return (std::get<2>(_match) == _m);
79 };
80 } else {
81 its_filter_func
82 = [](service_t, instance_t, method_t) {
83 return true;
84 };
85 }
86 }
87 }
88
89 return add_filter_intern(its_filter_func, _is_positive);
90 }
91
add_filter(const std::vector<match_t> & _matches,bool _is_positive)92 filter_id_t channel_impl::add_filter(
93 const std::vector<match_t> &_matches, bool _is_positive) {
94 bool has_service(false);
95 bool has_instance(false);
96 bool has_method(false);
97
98 for (auto m : _matches) {
99 if (std::get<0>(m) != ANY_SERVICE) has_service = true;
100 if (std::get<1>(m) != ANY_INSTANCE) has_instance = true;
101 if (std::get<2>(m) != ANY_METHOD) has_method = true;
102 }
103
104 // Create a filter function
105 std::function<bool (service_t, instance_t, method_t)> its_filter_func;
106 if (has_service) {
107 if (has_instance) {
108 if (has_method) {
109 its_filter_func
110 = [_matches](service_t _s, instance_t _i, method_t _m) {
111 for (const auto &m : _matches) {
112 if ((std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE)
113 && (std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE)
114 && (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD)) {
115 return true;
116 }
117 }
118 return false;
119 };
120 } else {
121 its_filter_func
122 = [_matches](service_t _s, instance_t _i, method_t) {
123 for (const auto &m : _matches) {
124 if ((std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE)
125 && (std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE)) {
126 return true;
127 }
128 }
129 return false;
130 };
131 }
132 } else {
133 if (has_method) {
134 its_filter_func
135 = [_matches](service_t _s, instance_t, method_t _m) {
136 for (const auto &m : _matches) {
137 if ((std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE)
138 && (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD)) {
139 return true;
140 }
141 }
142 return false;
143 };
144 } else {
145 its_filter_func
146 = [_matches](service_t _s, instance_t, method_t) {
147 for (auto &m : _matches) {
148 if (std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE) {
149 return true;
150 }
151 }
152 return false;
153 };
154 }
155 }
156 } else {
157 if (has_instance) {
158 if (has_method) {
159 its_filter_func
160 = [_matches](service_t, instance_t _i, method_t _m) {
161 for (auto &m : _matches) {
162 if ((std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE)
163 && (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD)) {
164 return true;
165 }
166 }
167 return false;
168 };
169 } else {
170 its_filter_func
171 = [_matches](service_t, instance_t _i, method_t) {
172 for (auto &m : _matches) {
173 if (std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE) {
174 return true;
175 }
176 }
177 return false;
178 };
179 }
180 } else {
181 if (has_method) {
182 its_filter_func
183 = [_matches](service_t, instance_t, method_t _m) {
184 for (auto &m : _matches) {
185 if (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD) {
186 return true;
187 }
188 }
189 return false;
190 };
191 } else {
192 its_filter_func
193 = [](service_t, instance_t, method_t) {
194 return true;
195 };
196 }
197 }
198 }
199
200 return add_filter_intern(its_filter_func, _is_positive);
201 }
202
add_filter(const match_t & _from,const match_t & _to,bool _is_positive)203 filter_id_t channel_impl::add_filter(
204 const match_t &_from, const match_t &_to, bool _is_positive) {
205
206 // Check usage of ANY_* which is forbidden here
207 if (std::get<0>(_from) == ANY_SERVICE ||
208 std::get<1>(_from) == ANY_INSTANCE ||
209 std::get<2>(_from) == ANY_METHOD ||
210 std::get<0>(_to) == ANY_SERVICE ||
211 std::get<1>(_to) == ANY_INSTANCE ||
212 std::get<2>(_to) == ANY_METHOD) {
213 VSOMEIP_ERROR << "Trace filter configuration error: "
214 "You must not use wildcards in range filters.";
215 return FILTER_ID_ERROR;
216 }
217
218 std::function<bool (service_t, instance_t, method_t)> its_filter_func
219 = [_from, _to](service_t _s, instance_t _i, method_t _m) {
220 return (std::get<0>(_from) <= _s && _s <= std::get<0>(_to)
221 && std::get<1>(_from) <= _i && _i <= std::get<1>(_to)
222 && std::get<2>(_from) <= _m && _m <= std::get<2>(_to));
223 };
224
225 return add_filter_intern(its_filter_func, _is_positive);
226 }
227
remove_filter(filter_id_t _id)228 void channel_impl::remove_filter(filter_id_t _id) {
229 std::lock_guard<std::mutex> its_lock(mutex_);
230 positive_.erase(_id);
231 negative_.erase(_id);
232 }
233
add_filter_intern(const filter_func_t & _func,bool _is_positive)234 filter_id_t channel_impl::add_filter_intern(const filter_func_t& _func, bool _is_positive) {
235 filter_id_t its_id = current_filter_id_.fetch_add(1);
236
237 std::lock_guard<std::mutex> its_lock(mutex_);
238 if (_is_positive)
239 positive_[its_id] = _func;
240 else
241 negative_[its_id] = _func;
242
243 return its_id;
244 }
245
matches(service_t _service,instance_t _instance,method_t _method)246 bool channel_impl::matches(
247 service_t _service, instance_t _instance, method_t _method) {
248 std::lock_guard<std::mutex> its_lock(mutex_);
249
250 // If a negative filter matches --> drop!
251 for (auto &its_filter : negative_) {
252 if (its_filter.second(_service, _instance, _method)) {
253 return false;
254 }
255 }
256
257 // If no positive filter is defined --> forward!
258 if (positive_.size() == 0)
259 return true;
260
261 // If a positive filter matches --> forward!
262 for (auto &its_filter : positive_) {
263 if (its_filter.second(_service, _instance, _method)) {
264 return true;
265 }
266 }
267
268 // drop!
269 return false;
270 }
271
272 } // namespace trace
273 } // namespace vsomeip_v3
274