1 // Copyright (C) 2014-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
6 #include <iomanip>
7
8 #include <vsomeip/runtime.hpp>
9 #include <vsomeip/internal/logger.hpp>
10
11 #include "../include/routing_manager_base.hpp"
12 #include "../../endpoints/include/local_client_endpoint_impl.hpp"
13 #include "../../endpoints/include/local_server_endpoint_impl.hpp"
14 #include "../../security/include/security.hpp"
15 #ifdef USE_DLT
16 #include "../../tracing/include/connector_impl.hpp"
17 #endif
18 #include "../../utility/include/byteorder.hpp"
19 #include "../../utility/include/utility.hpp"
20
21 namespace vsomeip_v3 {
22
routing_manager_base(routing_manager_host * _host)23 routing_manager_base::routing_manager_base(routing_manager_host *_host) :
24 host_(_host),
25 io_(host_->get_io()),
26 client_(host_->get_client()),
27 configuration_(host_->get_configuration()),
28 routing_state_(routing_state_e::RS_UNKNOWN)
29 #ifdef USE_DLT
30 , tc_(trace::connector_impl::get())
31 #endif
32 {
33 const std::size_t its_max = configuration_->get_io_thread_count(host_->get_name());
34 const uint32_t its_buffer_shrink_threshold =
35 configuration_->get_buffer_shrink_threshold();
36
37 for (std::size_t i = 0; i < its_max; ++i) {
38 serializers_.push(
39 std::make_shared<serializer>(its_buffer_shrink_threshold));
40 deserializers_.push(
41 std::make_shared<deserializer>(its_buffer_shrink_threshold));
42 }
43
44 own_uid_ = ANY_UID;
45 own_gid_ = ANY_GID;
46 #ifndef _WIN32
47 own_uid_ = getuid();
48 own_gid_ = getgid();
49 #endif
50
51 }
52
get_io()53 boost::asio::io_service & routing_manager_base::get_io() {
54 return (io_);
55 }
56
get_client() const57 client_t routing_manager_base::get_client() const {
58 return client_;
59 }
60
set_client(const client_t & _client)61 void routing_manager_base::set_client(const client_t &_client) {
62 client_ = _client;
63 }
64
get_session()65 session_t routing_manager_base::get_session() {
66 return host_->get_session();
67 }
68
init(const std::shared_ptr<endpoint_manager_base> & _endpoint_manager)69 void routing_manager_base::init(const std::shared_ptr<endpoint_manager_base>& _endpoint_manager) {
70 ep_mgr_ = _endpoint_manager;
71 }
72
offer_service(client_t _client,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor)73 bool routing_manager_base::offer_service(client_t _client,
74 service_t _service, instance_t _instance,
75 major_version_t _major, minor_version_t _minor) {
76 (void)_client;
77
78 // Remote route (incoming only)
79 auto its_info = find_service(_service, _instance);
80 if (its_info) {
81 if (!its_info->is_local()) {
82 return false;
83 } else if (its_info->get_major() == _major
84 && its_info->get_minor() == _minor) {
85 its_info->set_ttl(DEFAULT_TTL);
86 } else {
87 VSOMEIP_ERROR << "rm_base::offer_service service property mismatch ("
88 << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
89 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
90 << std::hex << std::setw(4) << std::setfill('0') << _instance << ":"
91 << std::dec << static_cast<std::uint32_t>(its_info->get_major()) << ":"
92 << std::dec << its_info->get_minor() << "] passed: "
93 << std::dec << static_cast<std::uint32_t>(_major) << ":"
94 << std::dec << _minor;
95 return false;
96 }
97 } else {
98 its_info = create_service_info(_service, _instance, _major, _minor,
99 DEFAULT_TTL, true);
100 }
101 {
102 std::lock_guard<std::mutex> its_lock(events_mutex_);
103 // Set major version for all registered events of this service and instance
104 const auto found_service = events_.find(_service);
105 if (found_service != events_.end()) {
106 const auto found_instance = found_service->second.find(_instance);
107 if (found_instance != found_service->second.end()) {
108 for (const auto &j : found_instance->second) {
109 j.second->set_version(_major);
110 }
111 }
112 }
113 }
114 return true;
115 }
116
stop_offer_service(client_t _client,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor)117 void routing_manager_base::stop_offer_service(client_t _client,
118 service_t _service, instance_t _instance,
119 major_version_t _major, minor_version_t _minor) {
120 (void)_client;
121 (void)_major;
122 (void)_minor;
123
124 std::map<event_t, std::shared_ptr<event> > events;
125 {
126 std::lock_guard<std::mutex> its_lock(events_mutex_);
127 auto its_events_service = events_.find(_service);
128 if (its_events_service != events_.end()) {
129 auto its_events_instance = its_events_service->second.find(_instance);
130 if (its_events_instance != its_events_service->second.end()) {
131 for (auto &e : its_events_instance->second)
132 events[e.first] = e.second;
133
134 }
135 }
136 }
137 for (auto &e : events) {
138 e.second->unset_payload();
139 e.second->clear_subscribers();
140 }
141 }
142
request_service(client_t _client,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor)143 void routing_manager_base::request_service(client_t _client,
144 service_t _service, instance_t _instance,
145 major_version_t _major, minor_version_t _minor) {
146 auto its_info = find_service(_service, _instance);
147 if (its_info) {
148 if ((_major == its_info->get_major()
149 || DEFAULT_MAJOR == its_info->get_major()
150 || ANY_MAJOR == _major)
151 && (_minor <= its_info->get_minor()
152 || DEFAULT_MINOR == its_info->get_minor()
153 || _minor == ANY_MINOR)) {
154 its_info->add_client(_client);
155 } else {
156 VSOMEIP_ERROR << "rm_base::request_service service property mismatch ("
157 << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
158 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
159 << std::hex << std::setw(4) << std::setfill('0') << _instance << ":"
160 << std::dec << static_cast<std::uint32_t>(its_info->get_major()) << ":"
161 << std::dec << its_info->get_minor() << "] passed: "
162 << std::dec << static_cast<std::uint32_t>(_major) << ":"
163 << std::dec << _minor;
164 }
165 }
166 }
167
release_service(client_t _client,service_t _service,instance_t _instance)168 void routing_manager_base::release_service(client_t _client,
169 service_t _service, instance_t _instance) {
170 auto its_info = find_service(_service, _instance);
171 if (its_info) {
172 its_info->remove_client(_client);
173 }
174 {
175 std::lock_guard<std::mutex> its_lock(local_services_mutex_);
176 auto found_service = local_services_history_.find(_service);
177 if (found_service != local_services_history_.end()) {
178 auto found_instance = found_service->second.find(_instance);
179 if (found_instance != found_service->second.end()) {
180 found_service->second.erase(_instance);
181 if (found_service->second.empty()) {
182 local_services_history_.erase(_service);
183 }
184 }
185 }
186 }
187 }
188
register_event(client_t _client,service_t _service,instance_t _instance,event_t _notifier,const std::set<eventgroup_t> & _eventgroups,const event_type_e _type,reliability_type_e _reliability,std::chrono::milliseconds _cycle,bool _change_resets_cycle,bool _update_on_change,epsilon_change_func_t _epsilon_change_func,bool _is_provided,bool _is_shadow,bool _is_cache_placeholder)189 void routing_manager_base::register_event(client_t _client,
190 service_t _service, instance_t _instance,
191 event_t _notifier,
192 const std::set<eventgroup_t> &_eventgroups,
193 const event_type_e _type,
194 reliability_type_e _reliability,
195 std::chrono::milliseconds _cycle, bool _change_resets_cycle,
196 bool _update_on_change,
197 epsilon_change_func_t _epsilon_change_func,
198 bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) {
199 std::lock_guard<std::mutex> its_registration_lock(event_registration_mutex_);
200
201 auto determine_event_reliability = [this, &_service, &_instance,
202 &_notifier, &_reliability]() {
203 reliability_type_e its_reliability =
204 configuration_->get_event_reliability(_service, _instance, _notifier);
205 if (its_reliability != reliability_type_e::RT_UNKNOWN) {
206 // event was explicitly configured -> overwrite value passed via API
207 return its_reliability;
208 } else if (_reliability != reliability_type_e::RT_UNKNOWN) {
209 // use value provided via API
210 return _reliability;
211 } else { // automatic mode, user service' reliability
212 return configuration_->get_service_reliability(_service, _instance);
213 }
214 };
215
216 std::shared_ptr<event> its_event = find_event(_service, _instance, _notifier);
217 bool transfer_subscriptions_from_any_event(false);
218 if (its_event) {
219 if (!its_event->is_cache_placeholder()) {
220 if (_type == its_event->get_type()
221 || its_event->get_type() == event_type_e::ET_UNKNOWN
222 #ifdef VSOMEIP_ENABLE_COMPAT
223 || (its_event->get_type() == event_type_e::ET_EVENT
224 && _type == event_type_e::ET_SELECTIVE_EVENT)
225 || (its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT
226 && _type == event_type_e::ET_EVENT && _is_provided)
227 #endif
228 ) {
229 #ifdef VSOMEIP_ENABLE_COMPAT
230 if (its_event->get_type() == event_type_e::ET_EVENT
231 && _type == event_type_e::ET_SELECTIVE_EVENT) {
232 its_event->set_type(_type);
233 VSOMEIP_INFO << "Event type changed to selective ("
234 << std::hex << std::setw(4) << std::setfill('0') << _client << ") ["
235 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
236 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
237 << std::hex << std::setw(4) << std::setfill('0') << _notifier << "]";
238 }
239 #endif
240 if (_is_provided) {
241 its_event->set_provided(true);
242 its_event->set_reliability(determine_event_reliability());
243 }
244 if (_is_shadow && _is_provided) {
245 its_event->set_shadow(_is_shadow);
246 }
247 if (_client == host_->get_client() && _is_provided) {
248 its_event->set_shadow(false);
249 its_event->set_update_on_change(_update_on_change);
250 }
251 for (auto eg : _eventgroups) {
252 its_event->add_eventgroup(eg);
253 }
254 transfer_subscriptions_from_any_event = true;
255 } else {
256 #ifdef VSOMEIP_ENABLE_COMPAT
257 if (!(its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT
258 && _type == event_type_e::ET_EVENT))
259 #endif
260 VSOMEIP_ERROR << "Event registration update failed. "
261 "Specified arguments do not match existing registration.";
262 }
263 } else {
264 // the found event was a placeholder for caching.
265 // update it with the real values
266 if (_type != event_type_e::ET_FIELD) {
267 // don't cache payload for non-fields
268 its_event->unset_payload(true);
269 }
270 if (_is_shadow && _is_provided) {
271 its_event->set_shadow(_is_shadow);
272 }
273 if (_client == host_->get_client() && _is_provided) {
274 its_event->set_shadow(false);
275 its_event->set_update_on_change(_update_on_change);
276 }
277 its_event->set_type(_type);
278 its_event->set_reliability(determine_event_reliability());
279 its_event->set_provided(_is_provided);
280 its_event->set_cache_placeholder(false);
281 std::shared_ptr<serviceinfo> its_service = find_service(_service, _instance);
282 if (its_service) {
283 its_event->set_version(its_service->get_major());
284 }
285 if (_eventgroups.size() == 0) { // No eventgroup specified
286 std::set<eventgroup_t> its_eventgroups;
287 its_eventgroups.insert(_notifier);
288 its_event->set_eventgroups(its_eventgroups);
289 } else {
290 for (auto eg : _eventgroups) {
291 its_event->add_eventgroup(eg);
292 }
293 }
294
295 its_event->set_epsilon_change_function(_epsilon_change_func);
296 its_event->set_change_resets_cycle(_change_resets_cycle);
297 its_event->set_update_cycle(_cycle);
298 }
299 } else {
300 its_event = std::make_shared<event>(this, _is_shadow);
301 its_event->set_service(_service);
302 its_event->set_instance(_instance);
303 its_event->set_event(_notifier);
304 its_event->set_type(_type);
305 its_event->set_reliability(determine_event_reliability());
306 its_event->set_provided(_is_provided);
307 its_event->set_cache_placeholder(_is_cache_placeholder);
308 std::shared_ptr<serviceinfo> its_service = find_service(_service, _instance);
309 if (its_service) {
310 its_event->set_version(its_service->get_major());
311 }
312
313 if (_eventgroups.size() == 0) { // No eventgroup specified
314 std::set<eventgroup_t> its_eventgroups;
315 its_eventgroups.insert(_notifier);
316 its_event->set_eventgroups(its_eventgroups);
317 } else {
318 its_event->set_eventgroups(_eventgroups);
319 }
320
321 if (_is_shadow && !_epsilon_change_func) {
322 std::shared_ptr<cfg::debounce> its_debounce
323 = configuration_->get_debounce(_service, _instance, _notifier);
324 if (its_debounce) {
325 VSOMEIP_WARNING << "Using debounce configuration for "
326 << " SOME/IP event "
327 << std::hex << std::setw(4) << std::setfill('0')
328 << _service << "."
329 << std::hex << std::setw(4) << std::setfill('0')
330 << _instance << "."
331 << std::hex << std::setw(4) << std::setfill('0')
332 << _notifier << ".";
333 std::stringstream its_debounce_parameters;
334 its_debounce_parameters << "(on_change="
335 << (its_debounce->on_change_ ? "true" : "false")
336 << ", ignore=[ ";
337 for (auto i : its_debounce->ignore_)
338 its_debounce_parameters << "(" << std::dec << i.first
339 << ", " << std::hex << (int)i.second << ") ";
340 its_debounce_parameters << "], interval="
341 << std::dec << its_debounce->interval_ << ")";
342 VSOMEIP_WARNING << "Debounce parameters: "
343 << its_debounce_parameters.str();
344 _epsilon_change_func = [its_debounce](
345 const std::shared_ptr<payload> &_old,
346 const std::shared_ptr<payload> &_new) {
347 bool is_changed(false), is_elapsed(false);
348
349 // Check whether we should forward because of changed data
350 if (its_debounce->on_change_) {
351 length_t its_min_length, its_max_length;
352
353 if (_old->get_length() < _new->get_length()) {
354 its_min_length = _old->get_length();
355 its_max_length = _new->get_length();
356 } else {
357 its_min_length = _new->get_length();
358 its_max_length = _old->get_length();
359 }
360
361 // Check whether all additional bytes (if any) are excluded
362 for (length_t i = its_min_length; i < its_max_length; i++) {
363 auto j = its_debounce->ignore_.find(i);
364 // A change is detected when an additional byte is not
365 // excluded at all or if its exclusion does not cover
366 // all its bits.
367 if (j == its_debounce->ignore_.end() || j->second != 0xFF) {
368 is_changed = true;
369 break;
370 }
371 }
372
373 if (!is_changed) {
374 const byte_t *its_old = _old->get_data();
375 const byte_t *its_new = _new->get_data();
376 for (length_t i = 0; i < its_min_length; i++) {
377 auto j = its_debounce->ignore_.find(i);
378 if (j == its_debounce->ignore_.end()) {
379 if (its_old[i] != its_new[i]) {
380 is_changed = true;
381 break;
382 }
383 } else if (j->second != 0xFF) {
384 if ((its_old[i] & ~(j->second)) != (its_new[i] & ~(j->second))) {
385 is_changed = true;
386 break;
387 }
388 }
389 }
390 }
391 }
392
393 if (its_debounce->interval_ > -1) {
394 // Check whether we should forward because of the elapsed time since
395 // we did last time
396 std::chrono::steady_clock::time_point its_current
397 = std::chrono::steady_clock::now();
398
399 long elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
400 its_current - its_debounce->last_forwarded_).count();
401 is_elapsed = (its_debounce->last_forwarded_ == (std::chrono::steady_clock::time_point::max)()
402 || elapsed >= its_debounce->interval_);
403 if (is_elapsed || (is_changed && its_debounce->on_change_resets_interval_))
404 its_debounce->last_forwarded_ = its_current;
405 }
406 return (is_changed || is_elapsed);
407 };
408 } else {
409 _epsilon_change_func = [](const std::shared_ptr<payload> &_old,
410 const std::shared_ptr<payload> &_new) {
411 (void)_old;
412 (void)_new;
413 return true;
414 };
415 }
416 }
417
418 its_event->set_epsilon_change_function(_epsilon_change_func);
419 its_event->set_change_resets_cycle(_change_resets_cycle);
420 its_event->set_update_cycle(_cycle);
421 its_event->set_update_on_change(_update_on_change);
422
423 if (_is_provided) {
424 transfer_subscriptions_from_any_event = true;
425 }
426 }
427
428 if (transfer_subscriptions_from_any_event) {
429 // check if someone subscribed to ANY_EVENT and the subscription
430 // was stored in the cache placeholder. Move the subscribers
431 // into new event
432 std::shared_ptr<event> its_any_event =
433 find_event(_service, _instance, ANY_EVENT);
434 if (its_any_event) {
435 std::set<eventgroup_t> any_events_eventgroups =
436 its_any_event->get_eventgroups();
437 for (eventgroup_t eventgroup : _eventgroups) {
438 auto found_eg = any_events_eventgroups.find(eventgroup);
439 if (found_eg != any_events_eventgroups.end()) {
440 std::set<client_t> its_any_event_subscribers =
441 its_any_event->get_subscribers(eventgroup);
442 for (const client_t subscriber : its_any_event_subscribers) {
443 its_event->add_subscriber(eventgroup, subscriber, true);
444 }
445 }
446 }
447 }
448 }
449
450 if (!its_event->is_cache_placeholder()) {
451 its_event->add_ref(_client, _is_provided);
452 }
453
454 for (auto eg : _eventgroups) {
455 std::shared_ptr<eventgroupinfo> its_eventgroupinfo
456 = find_eventgroup(_service, _instance, eg);
457 if (!its_eventgroupinfo) {
458 its_eventgroupinfo = std::make_shared<eventgroupinfo>();
459 its_eventgroupinfo->set_service(_service);
460 its_eventgroupinfo->set_instance(_instance);
461 its_eventgroupinfo->set_eventgroup(eg);
462 its_eventgroupinfo->set_max_remote_subscribers(
463 configuration_->get_max_remote_subscribers());
464 std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
465 eventgroups_[_service][_instance][eg] = its_eventgroupinfo;
466 }
467 its_eventgroupinfo->add_event(its_event);
468 }
469
470 std::lock_guard<std::mutex> its_lock(events_mutex_);
471 events_[_service][_instance][_notifier] = its_event;
472 }
473
unregister_event(client_t _client,service_t _service,instance_t _instance,event_t _event,bool _is_provided)474 void routing_manager_base::unregister_event(client_t _client, service_t _service, instance_t _instance,
475 event_t _event, bool _is_provided) {
476 (void)_client;
477 std::shared_ptr<event> its_unrefed_event;
478 {
479 std::lock_guard<std::mutex> its_lock(events_mutex_);
480 auto found_service = events_.find(_service);
481 if (found_service != events_.end()) {
482 auto found_instance = found_service->second.find(_instance);
483 if (found_instance != found_service->second.end()) {
484 auto found_event = found_instance->second.find(_event);
485 if (found_event != found_instance->second.end()) {
486 auto its_event = found_event->second;
487 its_event->remove_ref(_client, _is_provided);
488 if (!its_event->has_ref()) {
489 its_unrefed_event = its_event;
490 found_instance->second.erase(found_event);
491 } else if (_is_provided) {
492 its_event->set_provided(false);
493 }
494 }
495 }
496 }
497 }
498 if (its_unrefed_event) {
499 auto its_eventgroups = its_unrefed_event->get_eventgroups();
500 for (auto eg : its_eventgroups) {
501 std::shared_ptr<eventgroupinfo> its_eventgroup_info
502 = find_eventgroup(_service, _instance, eg);
503 if (its_eventgroup_info) {
504 its_eventgroup_info->remove_event(its_unrefed_event);
505 if (0 == its_eventgroup_info->get_events().size()) {
506 remove_eventgroup_info(_service, _instance, eg);
507 }
508 }
509 }
510 }
511 }
512
find_events(service_t _service,instance_t _instance,eventgroup_t _eventgroup) const513 std::set<std::shared_ptr<event>> routing_manager_base::find_events(
514 service_t _service, instance_t _instance,
515 eventgroup_t _eventgroup) const {
516 std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
517 std::set<std::shared_ptr<event> > its_events;
518 auto found_service = eventgroups_.find(_service);
519 if (found_service != eventgroups_.end()) {
520 auto found_instance = found_service->second.find(_instance);
521 if (found_instance != found_service->second.end()) {
522 auto found_eventgroup = found_instance->second.find(_eventgroup);
523 if (found_eventgroup != found_instance->second.end()) {
524 return (found_eventgroup->second->get_events());
525 }
526 }
527 }
528 return (its_events);
529 }
530
find_events(service_t _service,instance_t _instance) const531 std::vector<event_t> routing_manager_base::find_events(
532 service_t _service, instance_t _instance) const {
533 std::vector<event_t> its_events;
534 std::lock_guard<std::mutex> its_lock(events_mutex_);
535 const auto found_service = events_.find(_service);
536 if (found_service != events_.end()) {
537 const auto found_instance = found_service->second.find(_instance);
538 if (found_instance != found_service->second.end()) {
539 for (const auto& e : found_instance->second) {
540 its_events.push_back(e.first);
541 }
542 }
543 }
544 return (its_events);
545 }
546
is_response_allowed(client_t _sender,service_t _service,instance_t _instance,method_t _method)547 bool routing_manager_base::is_response_allowed(client_t _sender, service_t _service,
548 instance_t _instance, method_t _method) {
549
550 const auto its_security(security::get());
551 if (!its_security->is_enabled()) {
552 return true;
553 }
554
555 {
556 std::lock_guard<std::mutex> its_lock(local_services_mutex_);
557 if (_sender == find_local_client_unlocked(_service, _instance)) {
558 // sender is still offering the service
559 return true;
560 }
561
562 auto found_service = local_services_history_.find(_service);
563 if (found_service != local_services_history_.end()) {
564 auto found_instance = found_service->second.find(_instance);
565 if (found_instance != found_service->second.end()) {
566 auto found_client = found_instance->second.find(_sender);
567 if (found_client != found_instance->second.end()) {
568 // sender was offering the service and is still connected
569 return true;
570 }
571 }
572 }
573 }
574
575 // service is now offered by another client
576 // or service is not offered at all
577 std::string security_mode_text = "!";
578 if (!its_security->is_audit()) {
579 security_mode_text = ", but will be allowed due to audit mode is active!";
580 }
581
582 VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
583 << " : routing_manager_base::is_response_allowed: "
584 << "received a response from client 0x" << _sender
585 << " which does not offer service/instance/method "
586 << _service << "/" << _instance << "/" << _method
587 << security_mode_text;
588
589 return !its_security->is_audit();
590 }
591
is_subscribe_to_any_event_allowed(credentials_t _credentials,client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup)592 bool routing_manager_base::is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
593 service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
594
595 const auto its_security(security::get());
596 const uid_t its_uid(std::get<0>(_credentials));
597 const gid_t its_gid(std::get<1>(_credentials));
598
599 bool is_allowed(true);
600
601 auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
602 if (its_eventgroup) {
603 for (const auto& e : its_eventgroup->get_events()) {
604 if (!its_security->is_client_allowed(its_uid, its_gid,
605 _client, _service, _instance, e->get_event())) {
606 VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
607 << _client << " : routing_manager_base::is_subscribe_to_any_event_allowed: "
608 << "subscribes to service/instance/event "
609 << _service << "/" << _instance << "/" << e->get_event()
610 << " which violates the security policy!";
611 is_allowed = false;
612 break;
613 }
614 }
615 }
616
617 return is_allowed;
618 }
619
subscribe(client_t _client,uid_t _uid,gid_t _gid,service_t _service,instance_t _instance,eventgroup_t _eventgroup,major_version_t _major,event_t _event)620 void routing_manager_base::subscribe(client_t _client, uid_t _uid, gid_t _gid,
621 service_t _service, instance_t _instance, eventgroup_t _eventgroup,
622 major_version_t _major, event_t _event) {
623
624 (void) _major;
625 (void)_uid;
626 (void)_gid;
627 std::set<event_t> its_already_subscribed_events;
628 bool inserted = insert_subscription(_service, _instance, _eventgroup,
629 _event, _client, &its_already_subscribed_events);
630 if (inserted) {
631 notify_one_current_value(_client, _service, _instance, _eventgroup,
632 _event, its_already_subscribed_events);
633 }
634 }
635
unsubscribe(client_t _client,uid_t _uid,gid_t _gid,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event)636 void routing_manager_base::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
637 service_t _service, instance_t _instance, eventgroup_t _eventgroup,event_t _event) {
638 (void)_uid;
639 (void)_gid;
640 if (_event != ANY_EVENT) {
641 auto its_event = find_event(_service, _instance, _event);
642 if (its_event) {
643 its_event->remove_subscriber(_eventgroup, _client);
644 }
645 } else {
646 auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
647 if (its_eventgroup) {
648 for (const auto &e : its_eventgroup->get_events()) {
649 if (e)
650 e->remove_subscriber(_eventgroup, _client);
651 }
652 }
653 }
654 }
655
656 void
unsubscribe_all(service_t _service,instance_t _instance)657 routing_manager_base::unsubscribe_all(
658 service_t _service, instance_t _instance) {
659
660 std::lock_guard<std::mutex> its_guard(events_mutex_);
661 auto find_service = events_.find(_service);
662 if (find_service != events_.end()) {
663 auto find_instance = find_service->second.find(_instance);
664 if (find_instance != find_service->second.end()) {
665 for (auto &e : find_instance->second)
666 e.second->clear_subscribers();
667 }
668 }
669 }
670
notify(service_t _service,instance_t _instance,event_t _event,std::shared_ptr<payload> _payload,bool _force)671 void routing_manager_base::notify(service_t _service, instance_t _instance,
672 event_t _event, std::shared_ptr<payload> _payload,
673 bool _force) {
674 std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
675 if (its_event) {
676 its_event->set_payload(_payload, _force);
677 } else {
678 VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
679 << std::hex << _service << "." << _instance << "." << _event
680 << "]";
681 }
682 }
683
notify_one(service_t _service,instance_t _instance,event_t _event,std::shared_ptr<payload> _payload,client_t _client,bool _force,bool _remote_subscriber)684 void routing_manager_base::notify_one(service_t _service, instance_t _instance,
685 event_t _event, std::shared_ptr<payload> _payload,
686 client_t _client, bool _force
687 #ifdef VSOMEIP_ENABLE_COMPAT
688 , bool _remote_subscriber
689 #endif
690 ) {
691 std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
692 if (its_event) {
693 // Event is valid for service/instance
694 bool found_eventgroup(false);
695 bool already_subscribed(false);
696 #ifdef VSOMEIP_ENABLE_COMPAT
697 eventgroup_t valid_group = 0;
698 subscription_state_e its_subscription_state(subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED);
699 #endif
700 // Iterate over all groups of the event to ensure at least
701 // one valid eventgroup for service/instance exists.
702 for (auto its_group : its_event->get_eventgroups()) {
703 auto its_eventgroup = find_eventgroup(_service, _instance, its_group);
704 if (its_eventgroup) {
705 // Eventgroup is valid for service/instance
706 found_eventgroup = true;
707 #ifdef VSOMEIP_ENABLE_COMPAT
708 valid_group = its_group;
709 its_subscription_state = get_incoming_subscription_state(_client, _service,
710 _instance, valid_group, _event);
711 #endif
712 if (ep_mgr_->find_local(_client)) {
713 already_subscribed = its_event->has_subscriber(its_group, _client);
714 #ifdef VSOMEIP_ENABLE_COMPAT
715 } else if (subscription_state_e::IS_SUBSCRIBING != its_subscription_state
716 || _remote_subscriber) {
717 // Remotes always needs to be marked as subscribed here if they are not currently subscribing
718 #else
719 } else {
720 // Remotes always needs to be marked as subscribed here
721 #endif
722 already_subscribed = true;
723 }
724 break;
725 }
726 }
727 if (found_eventgroup) {
728 if (already_subscribed) {
729 its_event->set_payload(_payload, _client, _force);
730 }
731 #ifdef VSOMEIP_ENABLE_COMPAT
732 else {
733 // cache notification if subscription is in progress
734 if (subscription_state_e::IS_SUBSCRIBING == its_subscription_state) {
735 VSOMEIP_INFO << "routing_manager_base::notify_one("
736 << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
737 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
738 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
739 << std::hex << std::setw(4) << std::setfill('0') << valid_group << "."
740 << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
741 << " insert pending notification!";
742 std::shared_ptr<message> its_notification
743 = runtime::get()->create_notification();
744 its_notification->set_service(_service);
745 its_notification->set_instance(_instance);
746 its_notification->set_method(_event);
747 its_notification->set_payload(_payload);
748 auto service_info = find_service(_service, _instance);
749 if (service_info) {
750 its_notification->set_interface_version(service_info->get_major());
751 }
752 {
753 std::lock_guard<std::recursive_mutex> its_lock(pending_notify_ones_mutex_);
754 pending_notify_ones_[_service][_instance][valid_group] = its_notification;
755 }
756 }
757 }
758 #endif
759 }
760 } else {
761 VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
762 << std::hex << _service << "." << _instance << "." << _event
763 << "]";
764 }
765 }
766
767 #ifdef VSOMEIP_ENABLE_COMPAT
send_pending_notify_ones(service_t _service,instance_t _instance,eventgroup_t _eventgroup,client_t _client,bool _remote_subscriber)768 void routing_manager_base::send_pending_notify_ones(service_t _service, instance_t _instance,
769 eventgroup_t _eventgroup, client_t _client, bool _remote_subscriber) {
770 std::lock_guard<std::recursive_mutex> its_lock(pending_notify_ones_mutex_);
771 auto its_service = pending_notify_ones_.find(_service);
772 if (its_service != pending_notify_ones_.end()) {
773 auto its_instance = its_service->second.find(_instance);
774 if (its_instance != its_service->second.end()) {
775 auto its_group = its_instance->second.find(_eventgroup);
776 if (its_group != its_instance->second.end()) {
777 VSOMEIP_INFO << "routing_manager_base::send_pending_notify_ones("
778 << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
779 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
780 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
781 << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
782 << std::hex << std::setw(4) << std::setfill('0') << its_group->second->get_method() << "]";
783
784 notify_one(_service, _instance, its_group->second->get_method(),
785 its_group->second->get_payload(), _client, false, _remote_subscriber);
786 its_instance->second.erase(_eventgroup);
787 }
788 }
789 }
790 }
791 #endif
792
unset_all_eventpayloads(service_t _service,instance_t _instance)793 void routing_manager_base::unset_all_eventpayloads(service_t _service,
794 instance_t _instance) {
795 std::set<std::shared_ptr<event>> its_events;
796 {
797 std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
798 const auto found_service = eventgroups_.find(_service);
799 if (found_service != eventgroups_.end()) {
800 const auto found_instance = found_service->second.find(_instance);
801 if (found_instance != found_service->second.end()) {
802 for (const auto &eventgroupinfo : found_instance->second) {
803 for (const auto &event : eventgroupinfo.second->get_events()) {
804 its_events.insert(event);
805 }
806 }
807 }
808 }
809 }
810 for (const auto &e : its_events) {
811 e->unset_payload(true);
812 }
813 }
814
unset_all_eventpayloads(service_t _service,instance_t _instance,eventgroup_t _eventgroup)815 void routing_manager_base::unset_all_eventpayloads(service_t _service,
816 instance_t _instance,
817 eventgroup_t _eventgroup) {
818 std::set<std::shared_ptr<event>> its_events;
819 {
820 std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
821 const auto found_service = eventgroups_.find(_service);
822 if (found_service != eventgroups_.end()) {
823 const auto found_instance = found_service->second.find(_instance);
824 if (found_instance != found_service->second.end()) {
825 const auto found_eventgroup = found_instance->second.find(_eventgroup);
826 if (found_eventgroup != found_instance->second.end()) {
827 for (const auto &event : found_eventgroup->second->get_events()) {
828 its_events.insert(event);
829 }
830 }
831 }
832 }
833 }
834 for (const auto &e : its_events) {
835 e->unset_payload(true);
836 }
837 }
838
notify_one_current_value(client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event,const std::set<event_t> & _events_to_exclude)839 void routing_manager_base::notify_one_current_value(
840 client_t _client, service_t _service, instance_t _instance,
841 eventgroup_t _eventgroup, event_t _event,
842 const std::set<event_t> &_events_to_exclude) {
843 if (_event != ANY_EVENT) {
844 std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
845 if (its_event && its_event->is_field())
846 its_event->notify_one(_client);
847 } else {
848 auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
849 if (its_eventgroup) {
850 std::set<std::shared_ptr<event> > its_events = its_eventgroup->get_events();
851 for (const auto &e : its_events) {
852 if (e->is_field()
853 && _events_to_exclude.find(e->get_event())
854 == _events_to_exclude.end()) {
855 e->notify_one(_client);
856 }
857 }
858 }
859 }
860 }
861
send(client_t _client,std::shared_ptr<message> _message)862 bool routing_manager_base::send(client_t _client,
863 std::shared_ptr<message> _message) {
864 bool is_sent(false);
865 if (utility::is_request(_message->get_message_type())) {
866 _message->set_client(_client);
867 }
868
869 std::shared_ptr<serializer> its_serializer(get_serializer());
870 if (its_serializer->serialize(_message.get())) {
871 is_sent = send(_client, its_serializer->get_data(),
872 its_serializer->get_size(), _message->get_instance(),
873 _message->is_reliable(), get_client(), std::make_pair(ANY_UID, ANY_GID), 0, false);
874 its_serializer->reset();
875 put_serializer(its_serializer);
876 } else {
877 VSOMEIP_ERROR << "Failed to serialize message. Check message size!";
878 }
879 return (is_sent);
880 }
881
882 // ********************************* PROTECTED **************************************
create_service_info(service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor,ttl_t _ttl,bool _is_local_service)883 std::shared_ptr<serviceinfo> routing_manager_base::create_service_info(
884 service_t _service, instance_t _instance, major_version_t _major,
885 minor_version_t _minor, ttl_t _ttl, bool _is_local_service) {
886 std::shared_ptr<serviceinfo> its_info =
887 std::make_shared<serviceinfo>(_service, _instance,
888 _major, _minor, _ttl, _is_local_service);
889 {
890 std::lock_guard<std::mutex> its_lock(services_mutex_);
891 services_[_service][_instance] = its_info;
892 }
893 if (!_is_local_service) {
894 std::lock_guard<std::mutex> its_lock(services_remote_mutex_);
895 services_remote_[_service][_instance] = its_info;
896 }
897 return its_info;
898 }
899
find_service(service_t _service,instance_t _instance) const900 std::shared_ptr<serviceinfo> routing_manager_base::find_service(
901 service_t _service, instance_t _instance) const {
902 std::shared_ptr<serviceinfo> its_info;
903 std::lock_guard<std::mutex> its_lock(services_mutex_);
904 auto found_service = services_.find(_service);
905 if (found_service != services_.end()) {
906 auto found_instance = found_service->second.find(_instance);
907 if (found_instance != found_service->second.end()) {
908 its_info = found_instance->second;
909 }
910 }
911 return (its_info);
912 }
913
clear_service_info(service_t _service,instance_t _instance,bool _reliable)914 void routing_manager_base::clear_service_info(service_t _service, instance_t _instance,
915 bool _reliable) {
916 std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
917 if (!its_info) {
918 return;
919 }
920
921 bool deleted_instance(false);
922 bool deleted_service(false);
923 {
924 std::lock_guard<std::mutex> its_lock(services_mutex_);
925
926 // Clear service_info and service_group
927 std::shared_ptr<endpoint> its_empty_endpoint;
928 if (!its_info->get_endpoint(!_reliable)) {
929 if (1 >= services_[_service].size()) {
930 services_.erase(_service);
931 deleted_service = true;
932 } else {
933 services_[_service].erase(_instance);
934 deleted_instance = true;
935 }
936 } else {
937 its_info->set_endpoint(its_empty_endpoint, _reliable);
938 }
939 }
940
941 if ((deleted_instance || deleted_service) && !its_info->is_local()) {
942 std::lock_guard<std::mutex> its_lock(services_remote_mutex_);
943 if (deleted_service) {
944 services_remote_.erase(_service);
945 } else if (deleted_instance) {
946 services_remote_[_service].erase(_instance);
947 }
948 }
949 }
950
get_services() const951 services_t routing_manager_base::get_services() const {
952 std::lock_guard<std::mutex> its_lock(services_mutex_);
953 return services_;
954 }
955
get_services_remote() const956 services_t routing_manager_base::get_services_remote() const {
957 std::lock_guard<std::mutex> its_lock(services_remote_mutex_);
958 return services_remote_;
959 }
960
is_available(service_t _service,instance_t _instance,major_version_t _major)961 bool routing_manager_base::is_available(service_t _service, instance_t _instance,
962 major_version_t _major) {
963 bool available(false);
964 std::lock_guard<std::mutex> its_lock(local_services_mutex_);
965 auto its_service = local_services_.find(_service);
966 if (its_service != local_services_.end()) {
967 if (_instance == ANY_INSTANCE) {
968 return true;
969 }
970 auto its_instance = its_service->second.find(_instance);
971 if (its_instance != its_service->second.end()) {
972 if (_major == ANY_MAJOR) {
973 return true;
974 }
975 if (std::get<0>(its_instance->second) == _major) {
976 available = true;
977 }
978 }
979 }
980 return available;
981 }
982
find_local_clients(service_t _service,instance_t _instance)983 std::set<client_t> routing_manager_base::find_local_clients(service_t _service, instance_t _instance) {
984 std::set<client_t> its_clients;
985 std::lock_guard<std::mutex> its_lock(local_services_mutex_);
986 auto its_service = local_services_.find(_service);
987 if (its_service != local_services_.end()) {
988 if (_instance == ANY_INSTANCE) {
989 for (auto its_instance : its_service->second) {
990 its_clients.insert(std::get<2>(its_instance.second));
991 }
992 } else {
993 auto its_instance = its_service->second.find(_instance);
994 if (its_instance != its_service->second.end()) {
995 its_clients.insert(std::get<2>(its_instance->second));
996 }
997 }
998 }
999 return its_clients;
1000 }
1001
find_local_client(service_t _service,instance_t _instance) const1002 client_t routing_manager_base::find_local_client(service_t _service,
1003 instance_t _instance) const {
1004 std::lock_guard<std::mutex> its_lock(local_services_mutex_);
1005 return find_local_client_unlocked(_service, _instance);
1006 }
1007
find_local_client_unlocked(service_t _service,instance_t _instance) const1008 client_t routing_manager_base::find_local_client_unlocked(service_t _service,
1009 instance_t _instance) const {
1010 client_t its_client(VSOMEIP_ROUTING_CLIENT);
1011 auto its_service = local_services_.find(_service);
1012 if (its_service != local_services_.end()) {
1013 auto its_instance = its_service->second.find(_instance);
1014 if (its_instance != its_service->second.end()) {
1015 its_client = std::get<2>(its_instance->second);
1016 }
1017 }
1018 return its_client;
1019 }
1020
remove_local(client_t _client,bool _remove_uid)1021 void routing_manager_base::remove_local(client_t _client, bool _remove_uid) {
1022 remove_local(_client, get_subscriptions(_client), _remove_uid);
1023 }
1024
remove_local(client_t _client,const std::set<std::tuple<service_t,instance_t,eventgroup_t>> & _subscribed_eventgroups,bool _remove_uid)1025 void routing_manager_base::remove_local(client_t _client,
1026 const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups,
1027 bool _remove_uid) {
1028
1029 std::pair<uid_t, gid_t> its_uid_gid(ANY_UID, ANY_GID);
1030 security::get()->get_client_to_uid_gid_mapping(_client, its_uid_gid);
1031
1032 if (_remove_uid) {
1033 security::get()->remove_client_to_uid_gid_mapping(_client);
1034 }
1035 for (auto its_subscription : _subscribed_eventgroups) {
1036 host_->on_subscription(std::get<0>(its_subscription), std::get<1>(its_subscription),
1037 std::get<2>(its_subscription), _client, its_uid_gid.first, its_uid_gid.second, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
1038 routing_manager_base::unsubscribe(_client, its_uid_gid.first, its_uid_gid.second, std::get<0>(its_subscription),
1039 std::get<1>(its_subscription), std::get<2>(its_subscription), ANY_EVENT);
1040 }
1041 ep_mgr_->remove_local(_client);
1042 {
1043 std::lock_guard<std::mutex> its_lock(local_services_mutex_);
1044 // Finally remove all services that are implemented by the client.
1045 std::set<std::pair<service_t, instance_t>> its_services;
1046 for (auto& s : local_services_) {
1047 for (auto& i : s.second) {
1048 if (std::get<2>(i.second) == _client) {
1049 its_services.insert({ s.first, i.first });
1050 host_->on_availability(s.first, i.first, false,
1051 std::get<0>(i.second), std::get<1>(i.second));
1052 }
1053 }
1054 }
1055
1056 for (auto& si : its_services) {
1057 local_services_[si.first].erase(si.second);
1058 if (local_services_[si.first].size() == 0)
1059 local_services_.erase(si.first);
1060 }
1061
1062 // remove disconnected client from offer service history
1063 std::set<std::tuple<service_t, instance_t, client_t>> its_clients;
1064 for (auto& s : local_services_history_) {
1065 for (auto& i : s.second) {
1066 for (auto& c : i.second) {
1067 if (c == _client) {
1068 its_clients.insert(std::make_tuple(s.first, i.first, c));
1069 }
1070 }
1071 }
1072 }
1073
1074 for (auto& sic : its_clients) {
1075 local_services_history_[std::get<0>(sic)][std::get<1>(sic)].erase(std::get<2>(sic));
1076 if (local_services_history_[std::get<0>(sic)][std::get<1>(sic)].size() == 0) {
1077 local_services_history_[std::get<0>(sic)].erase(std::get<1>(sic));
1078 if (local_services_history_[std::get<0>(sic)].size() == 0)
1079 local_services_history_.erase(std::get<0>(sic));
1080 }
1081 }
1082 }
1083 }
1084
find_event(service_t _service,instance_t _instance,event_t _event) const1085 std::shared_ptr<event> routing_manager_base::find_event(service_t _service,
1086 instance_t _instance, event_t _event) const {
1087 std::lock_guard<std::mutex> its_lock(events_mutex_);
1088 std::shared_ptr<event> its_event;
1089 auto find_service = events_.find(_service);
1090 if (find_service != events_.end()) {
1091 auto find_instance = find_service->second.find(_instance);
1092 if (find_instance != find_service->second.end()) {
1093 auto find_event = find_instance->second.find(_event);
1094 if (find_event != find_instance->second.end()) {
1095 its_event = find_event->second;
1096 }
1097 }
1098 }
1099 return (its_event);
1100 }
1101
find_eventgroup(service_t _service,instance_t _instance,eventgroup_t _eventgroup) const1102 std::shared_ptr<eventgroupinfo> routing_manager_base::find_eventgroup(
1103 service_t _service, instance_t _instance,
1104 eventgroup_t _eventgroup) const {
1105 std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
1106
1107 std::shared_ptr<eventgroupinfo> its_info(nullptr);
1108 auto found_service = eventgroups_.find(_service);
1109 if (found_service != eventgroups_.end()) {
1110 auto found_instance = found_service->second.find(_instance);
1111 if (found_instance != found_service->second.end()) {
1112 auto found_eventgroup = found_instance->second.find(_eventgroup);
1113 if (found_eventgroup != found_instance->second.end()) {
1114 its_info = found_eventgroup->second;
1115 std::shared_ptr<serviceinfo> its_service_info
1116 = find_service(_service, _instance);
1117 if (its_service_info) {
1118 std::string its_multicast_address;
1119 uint16_t its_multicast_port;
1120 if (configuration_->get_multicast(_service, _instance,
1121 _eventgroup,
1122 its_multicast_address, its_multicast_port)) {
1123 try {
1124 its_info->set_multicast(
1125 boost::asio::ip::address::from_string(
1126 its_multicast_address),
1127 its_multicast_port);
1128 }
1129 catch (...) {
1130 VSOMEIP_ERROR << "Eventgroup ["
1131 << std::hex << std::setw(4) << std::setfill('0')
1132 << _service << "." << _instance << "." << _eventgroup
1133 << "] is configured as multicast, but no valid "
1134 "multicast address is configured!";
1135 }
1136 }
1137
1138 // LB: THIS IS STRANGE. A "FIND" - METHOD SHOULD NOT ADD INFORMATION...
1139 its_info->set_major(its_service_info->get_major());
1140 its_info->set_ttl(its_service_info->get_ttl());
1141 its_info->set_threshold(configuration_->get_threshold(
1142 _service, _instance, _eventgroup));
1143 }
1144 }
1145 }
1146 }
1147 return (its_info);
1148 }
1149
remove_eventgroup_info(service_t _service,instance_t _instance,eventgroup_t _eventgroup)1150 void routing_manager_base::remove_eventgroup_info(service_t _service,
1151 instance_t _instance, eventgroup_t _eventgroup) {
1152 std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
1153 auto found_service = eventgroups_.find(_service);
1154 if (found_service != eventgroups_.end()) {
1155 auto found_instance = found_service->second.find(_instance);
1156 if (found_instance != found_service->second.end()) {
1157 found_instance->second.erase(_eventgroup);
1158 }
1159 }
1160 }
1161
send_local_notification(client_t _client,const byte_t * _data,uint32_t _size,instance_t _instance,bool _reliable,uint8_t _status_check)1162 bool routing_manager_base::send_local_notification(client_t _client,
1163 const byte_t *_data, uint32_t _size, instance_t _instance,
1164 bool _reliable, uint8_t _status_check) {
1165 #ifdef USE_DLT
1166 bool has_local(false);
1167 #endif
1168 bool has_remote(false);
1169 method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
1170 _data[VSOMEIP_METHOD_POS_MAX]);
1171 service_t its_service = VSOMEIP_BYTES_TO_WORD(
1172 _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
1173
1174 std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method);
1175 if (its_event && !its_event->is_shadow()) {
1176 for (auto its_client : its_event->get_subscribers()) {
1177
1178 // local
1179 if (its_client == VSOMEIP_ROUTING_CLIENT) {
1180 has_remote = true;
1181 continue;
1182 }
1183 #ifdef USE_DLT
1184 else {
1185 has_local = true;
1186 }
1187 #endif
1188
1189 std::shared_ptr<endpoint> its_local_target = ep_mgr_->find_local(its_client);
1190 if (its_local_target) {
1191 send_local(its_local_target, _client, _data, _size,
1192 _instance, _reliable, VSOMEIP_SEND, _status_check);
1193 }
1194 }
1195 }
1196 #ifdef USE_DLT
1197 // Trace the message if a local client but will _not_ be forwarded to the routing manager
1198 if (has_local && !has_remote) {
1199 const uint16_t its_data_size
1200 = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
1201
1202 trace::header its_header;
1203 if (its_header.prepare(nullptr, true, _instance))
1204 tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
1205 _data, its_data_size);
1206 }
1207 #endif
1208 return has_remote;
1209 }
1210
send_local(std::shared_ptr<endpoint> & _target,client_t _client,const byte_t * _data,uint32_t _size,instance_t _instance,bool _reliable,uint8_t _command,uint8_t _status_check) const1211 bool routing_manager_base::send_local(
1212 std::shared_ptr<endpoint>& _target, client_t _client,
1213 const byte_t *_data, uint32_t _size, instance_t _instance,
1214 bool _reliable, uint8_t _command, uint8_t _status_check) const {
1215 const std::size_t its_complete_size = VSOMEIP_SEND_COMMAND_SIZE
1216 - VSOMEIP_COMMAND_HEADER_SIZE + _size;
1217 const client_t sender = get_client();
1218
1219 std::vector<byte_t> its_command_header(VSOMEIP_SEND_COMMAND_SIZE);
1220 its_command_header[VSOMEIP_COMMAND_TYPE_POS] = _command;
1221 std::memcpy(&its_command_header[VSOMEIP_COMMAND_CLIENT_POS],
1222 &sender, sizeof(client_t));
1223 std::memcpy(&its_command_header[VSOMEIP_COMMAND_SIZE_POS_MIN],
1224 &its_complete_size, sizeof(_size));
1225 std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
1226 &_instance, sizeof(instance_t));
1227 std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
1228 &_reliable, sizeof(bool));
1229 std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
1230 &_status_check, sizeof(uint8_t));
1231 // Add target client, only relevant for selective notifications
1232 std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN],
1233 &_client, sizeof(client_t));
1234
1235 return _target->send(its_command_header, _data, _size);
1236 }
1237
insert_subscription(service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event,client_t _client,std::set<event_t> * _already_subscribed_events)1238 bool routing_manager_base::insert_subscription(
1239 service_t _service, instance_t _instance, eventgroup_t _eventgroup,
1240 event_t _event, client_t _client, std::set<event_t> *_already_subscribed_events) {
1241 bool is_inserted(false);
1242 if (_event != ANY_EVENT) { // subscribe to specific event
1243 std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
1244 if (its_event) {
1245 is_inserted = its_event->add_subscriber(_eventgroup, _client,
1246 host_->is_routing());
1247 } else {
1248 VSOMEIP_WARNING << "routing_manager_base::insert_subscription("
1249 << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
1250 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
1251 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
1252 << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
1253 << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
1254 << " received subscription for unknown (unrequested / "
1255 << "unoffered) event. Creating placeholder event holding "
1256 << "subscription until event is requested/offered.";
1257 is_inserted = create_placeholder_event_and_subscribe(_service,
1258 _instance, _eventgroup, _event, _client);
1259 }
1260 } else { // subscribe to all events of the eventgroup
1261 std::shared_ptr<eventgroupinfo> its_eventgroup
1262 = find_eventgroup(_service, _instance, _eventgroup);
1263 bool create_place_holder(false);
1264 if (its_eventgroup) {
1265 std::set<std::shared_ptr<event>> its_events = its_eventgroup->get_events();
1266 if (!its_events.size()) {
1267 create_place_holder = true;
1268 } else {
1269 for (const auto &e : its_events) {
1270 if (e->is_subscribed(_client)) {
1271 // client is already subscribed to event from eventgroup
1272 // this can happen if events are members of multiple
1273 // eventgroups
1274 _already_subscribed_events->insert(e->get_event());
1275 }
1276 is_inserted = e->add_subscriber(_eventgroup, _client,
1277 host_->is_routing()) || is_inserted;
1278 }
1279 }
1280 } else {
1281 create_place_holder = true;
1282 }
1283 if (create_place_holder) {
1284 VSOMEIP_WARNING << "routing_manager_base::insert_subscription("
1285 << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
1286 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
1287 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
1288 << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
1289 << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
1290 << " received subscription for unknown (unrequested / "
1291 << "unoffered) eventgroup. Creating placeholder event holding "
1292 << "subscription until event is requested/offered.";
1293 is_inserted = create_placeholder_event_and_subscribe(_service,
1294 _instance, _eventgroup, _event, _client);
1295 }
1296 }
1297 return is_inserted;
1298 }
1299
get_serializer()1300 std::shared_ptr<serializer> routing_manager_base::get_serializer() {
1301
1302 std::unique_lock<std::mutex> its_lock(serializer_mutex_);
1303 while (serializers_.empty()) {
1304 VSOMEIP_INFO << __func__ << ": Client "
1305 << std::hex << std::setw(4) << std::setfill('0')
1306 << get_client()
1307 << " has no available serializer. Waiting...";
1308 serializer_condition_.wait(its_lock);
1309 VSOMEIP_INFO << __func__ << ": Client "
1310 << std::hex << std::setw(4) << std::setfill('0')
1311 << get_client()
1312 << " now checking for available serializer.";
1313 }
1314
1315 auto its_serializer = serializers_.front();
1316 serializers_.pop();
1317
1318 return (its_serializer);
1319 }
1320
put_serializer(const std::shared_ptr<serializer> & _serializer)1321 void routing_manager_base::put_serializer(
1322 const std::shared_ptr<serializer> &_serializer) {
1323
1324 std::lock_guard<std::mutex> its_lock(serializer_mutex_);
1325 serializers_.push(_serializer);
1326 serializer_condition_.notify_one();
1327 }
1328
get_deserializer()1329 std::shared_ptr<deserializer> routing_manager_base::get_deserializer() {
1330
1331 std::unique_lock<std::mutex> its_lock(deserializer_mutex_);
1332 while (deserializers_.empty()) {
1333 VSOMEIP_INFO << std::hex << "client " << get_client() <<
1334 "routing_manager_base::get_deserializer ~> all in use!";
1335 deserializer_condition_.wait(its_lock);
1336 VSOMEIP_INFO << std::hex << "client " << get_client() <<
1337 "routing_manager_base::get_deserializer ~> wait finished!";
1338 }
1339
1340 auto its_deserializer = deserializers_.front();
1341 deserializers_.pop();
1342
1343 return (its_deserializer);
1344 }
1345
put_deserializer(const std::shared_ptr<deserializer> & _deserializer)1346 void routing_manager_base::put_deserializer(
1347 const std::shared_ptr<deserializer> &_deserializer) {
1348
1349 std::lock_guard<std::mutex> its_lock(deserializer_mutex_);
1350 deserializers_.push(_deserializer);
1351 deserializer_condition_.notify_one();
1352 }
1353
send_pending_subscriptions(service_t _service,instance_t _instance,major_version_t _major)1354 void routing_manager_base::send_pending_subscriptions(service_t _service,
1355 instance_t _instance, major_version_t _major) {
1356 for (auto &ps : pending_subscriptions_) {
1357 if (ps.service_ == _service &&
1358 ps.instance_ == _instance && ps.major_ == _major) {
1359 send_subscribe(client_, ps.service_, ps.instance_,
1360 ps.eventgroup_, ps.major_, ps.event_);
1361 }
1362 }
1363 }
1364
remove_pending_subscription(service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event)1365 void routing_manager_base::remove_pending_subscription(service_t _service,
1366 instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
1367 if (_eventgroup == 0xFFFF) {
1368 for (auto it = pending_subscriptions_.begin();
1369 it != pending_subscriptions_.end();) {
1370 if (it->service_ == _service
1371 && it->instance_ == _instance) {
1372 it = pending_subscriptions_.erase(it);
1373 } else {
1374 it++;
1375 }
1376 }
1377 } else if (_event == ANY_EVENT) {
1378 for (auto it = pending_subscriptions_.begin();
1379 it != pending_subscriptions_.end();) {
1380 if (it->service_ == _service
1381 && it->instance_ == _instance
1382 && it->eventgroup_ == _eventgroup) {
1383 it = pending_subscriptions_.erase(it);
1384 } else {
1385 it++;
1386 }
1387 }
1388 } else {
1389 for (auto it = pending_subscriptions_.begin();
1390 it != pending_subscriptions_.end();) {
1391 if (it->service_ == _service
1392 && it->instance_ == _instance
1393 && it->eventgroup_ == _eventgroup
1394 && it->event_ == _event) {
1395 it = pending_subscriptions_.erase(it);
1396 break;
1397 } else {
1398 it++;
1399 }
1400 }
1401 }
1402 }
1403
1404 std::set<std::tuple<service_t, instance_t, eventgroup_t>>
get_subscriptions(const client_t _client)1405 routing_manager_base::get_subscriptions(const client_t _client) {
1406 std::set<std::tuple<service_t, instance_t, eventgroup_t>> result;
1407 std::lock_guard<std::mutex> its_lock(events_mutex_);
1408 for (const auto& its_service : events_) {
1409 for (const auto& its_instance : its_service.second) {
1410 for (const auto& its_event : its_instance.second) {
1411 auto its_eventgroups = its_event.second->get_eventgroups(_client);
1412 for (const auto& e : its_eventgroups) {
1413 result.insert(std::make_tuple(
1414 its_service.first,
1415 its_instance.first,
1416 e));
1417 }
1418 }
1419 }
1420 }
1421 return result;
1422 }
1423
1424 routing_state_e
get_routing_state()1425 routing_manager_base::get_routing_state() {
1426 return routing_state_;
1427 }
1428
1429 #ifdef VSOMEIP_ENABLE_COMPAT
set_incoming_subscription_state(client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event,subscription_state_e _state)1430 void routing_manager_base::set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
1431 eventgroup_t _eventgroup, event_t _event, subscription_state_e _state) {
1432 std::lock_guard<std::recursive_mutex> its_lock(incoming_subscription_state_mutex_);
1433 incoming_subscription_state_[_client][_service][_instance][_eventgroup][_event] = _state;
1434 }
1435
get_incoming_subscription_state(client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event)1436 subscription_state_e routing_manager_base::get_incoming_subscription_state(client_t _client,
1437 service_t _service, instance_t _instance,
1438 eventgroup_t _eventgroup, event_t _event) {
1439 std::lock_guard<std::recursive_mutex> its_lock(incoming_subscription_state_mutex_);
1440 const auto its_client = incoming_subscription_state_.find(_client);
1441 if (its_client != incoming_subscription_state_.end()) {
1442 const auto its_service = its_client->second.find(_service);
1443 if (its_service != its_client->second.end()) {
1444 const auto its_instance = its_service->second.find(_instance);
1445 if (its_instance != its_service->second.end()) {
1446 const auto its_group = its_instance->second.find(_eventgroup);
1447 if (its_group != its_instance->second.end()) {
1448 const auto its_event = its_group->second.find(_event);
1449 if (its_event != its_group->second.end()) {
1450 return its_event->second;
1451 }
1452 // If a specific event was not found, check if there is a remote subscriber to ANY_EVENT
1453 const auto its_any_event = its_group->second.find(ANY_EVENT);
1454 if (its_any_event != its_group->second.end()) {
1455 return its_any_event->second;
1456 }
1457 }
1458 }
1459 }
1460 }
1461 return subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED;
1462 }
1463
erase_incoming_subscription_state(client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event)1464 void routing_manager_base::erase_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
1465 eventgroup_t _eventgroup, event_t _event) {
1466 std::lock_guard<std::recursive_mutex> its_lock(incoming_subscription_state_mutex_);
1467 const auto its_client = incoming_subscription_state_.find(_client);
1468 if (its_client != incoming_subscription_state_.end()) {
1469 const auto its_service = its_client->second.find(_service);
1470 if (its_service != its_client->second.end()) {
1471 const auto its_instance = its_service->second.find(_instance);
1472 if (its_instance != its_service->second.end()) {
1473 const auto its_group = its_instance->second.find(_eventgroup);
1474 if (its_group != its_instance->second.end()) {
1475 const auto its_event = its_group->second.find(_event);
1476 if (its_event != its_group->second.end()) {
1477 its_group->second.erase(_event);
1478 if (its_group->second.empty()) {
1479 its_instance->second.erase(its_group);
1480 if (its_instance->second.empty()) {
1481 its_service->second.erase(its_instance);
1482 if (its_service->second.empty()) {
1483 its_client->second.erase(its_service);
1484 if (its_client->second.empty()) {
1485 incoming_subscription_state_.erase(its_client);
1486 }
1487 }
1488 }
1489 }
1490 }
1491 }
1492 }
1493 }
1494 }
1495 }
1496 #endif
1497
1498 } // namespace vsomeip_v3
1499