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