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 <chrono>
7 #include <functional>
8 #include <iomanip>
9 #include <forward_list>
10 
11 #include <boost/system/error_code.hpp>
12 
13 #include <vsomeip/constants.hpp>
14 #include <vsomeip/primitive_types.hpp>
15 #include <vsomeip/runtime.hpp>
16 #include <vsomeip/error.hpp>
17 #include <vsomeip/internal/logger.hpp>
18 
19 #include "../include/routing_manager_stub.hpp"
20 #include "../include/routing_manager_stub_host.hpp"
21 #include "../include/remote_subscription.hpp"
22 #include "../../configuration/include/configuration.hpp"
23 #include "../../security/include/security.hpp"
24 
25 #include "../../endpoints/include/local_server_endpoint_impl.hpp"
26 #include "../../endpoints/include/endpoint_manager_impl.hpp"
27 #include "../../utility/include/byteorder.hpp"
28 #include "../../utility/include/utility.hpp"
29 #include "../implementation/message/include/payload_impl.hpp"
30 
31 namespace vsomeip_v3 {
32 
33 const std::vector<byte_t> routing_manager_stub::its_ping_(
34     { VSOMEIP_PING, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
35 
routing_manager_stub(routing_manager_stub_host * _host,const std::shared_ptr<configuration> & _configuration)36 routing_manager_stub::routing_manager_stub(
37         routing_manager_stub_host *_host,
38         const std::shared_ptr<configuration>& _configuration) :
39         host_(_host),
40         io_(_host->get_io()),
41         watchdog_timer_(_host->get_io()),
42         client_id_timer_(_host->get_io()),
43         endpoint_(nullptr),
44         local_receiver_(nullptr),
45         configuration_(_configuration),
46         is_socket_activated_(false),
47         client_registration_running_(false),
48         max_local_message_size_(configuration_->get_max_message_size_local()),
49         configured_watchdog_timeout_(configuration_->get_watchdog_timeout()),
50         pinged_clients_timer_(io_),
51         pending_security_update_id_(0) {
52 }
53 
~routing_manager_stub()54 routing_manager_stub::~routing_manager_stub() {
55 }
56 
init()57 void routing_manager_stub::init() {
58     init_routing_endpoint();
59 }
60 
start()61 void routing_manager_stub::start() {
62     {
63         std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
64         used_client_ids_ = utility::get_used_client_ids();
65         // Wait VSOMEIP_MAX_CONNECT_TIMEOUT * 2 and expect after that time
66         // that all client_ids are used have to be connected to the routing.
67         // Otherwise they can be marked as "erroneous client".
68         client_id_timer_.expires_from_now(std::chrono::milliseconds(VSOMEIP_MAX_CONNECT_TIMEOUT * 2));
69         client_id_timer_.async_wait(
70             std::bind(
71                     &routing_manager_stub::on_client_id_timer_expired,
72                     std::dynamic_pointer_cast<routing_manager_stub>(shared_from_this()),
73                     std::placeholders::_1));
74     }
75 
76     if (!endpoint_) {
77         // application has been stopped and started again
78         init_routing_endpoint();
79     }
80     if (endpoint_) {
81         endpoint_->start();
82     }
83 
84     client_registration_running_ = true;
85     client_registration_thread_ = std::make_shared<std::thread>(
86             std::bind(&routing_manager_stub::client_registration_func, this));
87 
88     if (configuration_->is_watchdog_enabled()) {
89         VSOMEIP_INFO << "Watchdog is enabled : Timeout in ms = "
90                      << configuration_->get_watchdog_timeout()
91                      << " : Allowed missing pongs = "
92                      << configuration_->get_allowed_missing_pongs()
93                      << ".";
94         start_watchdog();
95     } else {
96         VSOMEIP_INFO << "Watchdog is disabled!";
97     }
98 
99     {
100         std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
101         routing_info_[host_->get_client()].first = 0;
102     }
103 }
104 
stop()105 void routing_manager_stub::stop() {
106     {
107         std::lock_guard<std::mutex> its_lock(client_registration_mutex_);
108         client_registration_running_ = false;
109         client_registration_condition_.notify_one();
110     }
111     if (client_registration_thread_->joinable()) {
112         client_registration_thread_->join();
113     }
114 
115     {
116         std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_);
117         watchdog_timer_.cancel();
118     }
119 
120     {
121         std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
122         client_id_timer_.cancel();
123     }
124 
125     if( !is_socket_activated_) {
126         endpoint_->stop();
127         endpoint_ = nullptr;
128         std::stringstream its_endpoint_path;
129         its_endpoint_path << utility::get_base_path(configuration_) << std::hex
130                 << VSOMEIP_ROUTING_CLIENT;
131 #ifdef _WIN32
132         ::_unlink(its_endpoint_path.str().c_str());
133 #else
134         if (-1 == ::unlink(its_endpoint_path.str().c_str())) {
135             VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
136                     << its_endpoint_path.str() << "): "<< std::strerror(errno);
137         }
138 #endif
139     }
140 
141     if(local_receiver_) {
142         local_receiver_->stop();
143         local_receiver_ = nullptr;
144         std::stringstream its_local_receiver_path;
145         its_local_receiver_path << utility::get_base_path(configuration_)
146                 << std::hex << host_->get_client();
147 #ifdef _WIN32
148         ::_unlink(its_local_receiver_path.str().c_str());
149 #else
150         if (-1 == ::unlink(its_local_receiver_path.str().c_str())) {
151             VSOMEIP_ERROR << "routing_manager_stub::stop() unlink (local receiver) failed ("
152                     << its_local_receiver_path.str() << "): "<< std::strerror(errno);
153         }
154 #endif
155     }
156 }
157 
on_message(const byte_t * _data,length_t _size,endpoint * _receiver,const boost::asio::ip::address & _destination,client_t _bound_client,credentials_t _credentials,const boost::asio::ip::address & _remote_address,std::uint16_t _remote_port)158 void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
159         endpoint *_receiver, const boost::asio::ip::address &_destination,
160         client_t _bound_client,
161         credentials_t _credentials,
162         const boost::asio::ip::address &_remote_address,
163         std::uint16_t _remote_port) {
164     (void)_receiver;
165     (void)_destination;
166     (void)_remote_address;
167     (void) _remote_port;
168 #if 0
169     std::stringstream msg;
170     msg << "rms::on_message: ";
171     for (length_t i = 0; i < _size; ++i)
172         msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
173     VSOMEIP_INFO << msg.str();
174 #endif
175 
176     std::uint32_t its_sender_uid = std::get<0>(_credentials);
177     std::uint32_t its_sender_gid = std::get<1>(_credentials);
178 
179     if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) {
180         byte_t its_command;
181         client_t its_client;
182         std::string its_client_endpoint;
183         service_t its_service;
184         instance_t its_instance;
185         method_t its_method;
186         eventgroup_t its_eventgroup;
187         event_t its_notifier;
188         event_type_e its_event_type;
189         bool is_provided(false);
190         major_version_t its_major;
191         minor_version_t its_minor;
192         std::shared_ptr<payload> its_payload;
193         const byte_t *its_data;
194         uint32_t its_size;
195         bool its_reliable(false);
196         client_t its_client_from_header;
197         client_t its_target_client;
198         client_t its_subscriber;
199         uint8_t its_check_status(0);
200         std::uint16_t its_subscription_id(PENDING_SUBSCRIPTION_ID);
201         offer_type_e its_offer_type;
202 
203         its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
204         std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS],
205                 sizeof(its_client));
206 
207         if (security::get()->is_enabled() && _bound_client != its_client) {
208             VSOMEIP_WARNING << "vSomeIP Security: routing_manager_stub::on_message: "
209                     << "Routing Manager received a message from client "
210                     << std::hex << std::setw(4) << std::setfill('0')
211                     << its_client << " with command " << (uint32_t)its_command
212                     << " which doesn't match the bound client "
213                     << std::setw(4) << std::setfill('0') << _bound_client
214                     << " ~> skip message!";
215             return;
216         }
217 
218         std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
219                 sizeof(its_size));
220 
221         if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) {
222             switch (its_command) {
223             case VSOMEIP_REGISTER_APPLICATION:
224                 if (_size != VSOMEIP_REGISTER_APPLICATION_COMMAND_SIZE) {
225                     VSOMEIP_WARNING << "Received a REGISTER_APPLICATION command with wrong size ~> skip!";
226                     break;
227                 }
228                 update_registration(its_client, registration_type_e::REGISTER);
229                 break;
230 
231             case VSOMEIP_DEREGISTER_APPLICATION:
232                 if (_size != VSOMEIP_DEREGISTER_APPLICATION_COMMAND_SIZE) {
233                     VSOMEIP_WARNING << "Received a DEREGISTER_APPLICATION command with wrong size ~> skip!";
234                     break;
235                 }
236                 update_registration(its_client, registration_type_e::DEREGISTER);
237                 break;
238 
239             case VSOMEIP_PONG:
240                 if (_size != VSOMEIP_PONG_COMMAND_SIZE) {
241                     VSOMEIP_WARNING << "Received a PONG command with wrong size ~> skip!";
242                     break;
243                 }
244                 on_pong(its_client);
245                 VSOMEIP_TRACE << "PONG("
246                     << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
247                 break;
248 
249             case VSOMEIP_OFFER_SERVICE:
250                 if (_size != VSOMEIP_OFFER_SERVICE_COMMAND_SIZE) {
251                     VSOMEIP_WARNING << "Received a OFFER_SERVICE command with wrong size ~> skip!";
252                     break;
253                 }
254 
255                 std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
256                         sizeof(its_service));
257                 std::memcpy(&its_instance,
258                         &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
259                         sizeof(its_instance));
260                 std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
261                         sizeof(its_major));
262                 std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
263                         sizeof(its_minor));
264 
265                 if (security::get()->is_offer_allowed(its_sender_uid, its_sender_gid,
266                         its_client, its_service, its_instance)) {
267                     host_->offer_service(its_client, its_service, its_instance,
268                             its_major, its_minor);
269                 } else {
270                     VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
271                             << " : routing_manager_stub::on_message: isn't allowed to offer "
272                             << "the following service/instance " << its_service << "/" << its_instance
273                             << " ~> Skip offer!";
274                 }
275                 break;
276 
277             case VSOMEIP_STOP_OFFER_SERVICE:
278                 if (_size != VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE) {
279                     VSOMEIP_WARNING << "Received a STOP_OFFER_SERVICE command with wrong size ~> skip!";
280                     break;
281                 }
282                 std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
283                         sizeof(its_service));
284                 std::memcpy(&its_instance,
285                         &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
286                         sizeof(its_instance));
287 
288                 std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
289                         sizeof(its_major));
290                 std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
291                         sizeof(its_minor));
292 
293                 host_->stop_offer_service(its_client, its_service, its_instance, its_major, its_minor);
294                 break;
295 
296             case VSOMEIP_SUBSCRIBE:
297                 if (_size != VSOMEIP_SUBSCRIBE_COMMAND_SIZE) {
298                     VSOMEIP_WARNING << "Received a SUBSCRIBE command with wrong size ~> skip!";
299                     break;
300                 }
301                 std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
302                         sizeof(its_service));
303                 std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
304                         sizeof(its_instance));
305                 std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
306                         sizeof(its_eventgroup));
307                 std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
308                         sizeof(its_major));
309                 std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
310                         sizeof(its_notifier));
311 
312                 if (its_notifier == ANY_EVENT) {
313                     if (host_->is_subscribe_to_any_event_allowed(_credentials, its_client, its_service,
314                             its_instance, its_eventgroup)) {
315                         host_->subscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance,
316                                 its_eventgroup, its_major, its_notifier);
317                     } else {
318                         VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
319                                 << " :  routing_manager_stub::on_message: "
320                                 << " subscribes to service/instance/event "
321                                 << its_service << "/" << its_instance << "/ANY_EVENT"
322                                 << " which violates the security policy ~> Skip subscribe!";
323                     }
324                 } else {
325                     if (security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
326                             its_client, its_service, its_instance, its_notifier)) {
327                         host_->subscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance,
328                                 its_eventgroup, its_major, its_notifier);
329                     } else {
330                         VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
331                                 << " :  routing_manager_stub::on_message: "
332                                 << " subscribes to service/instance/event "
333                                 << its_service << "/" << its_instance << "/" << its_notifier
334                                 << " which violates the security policy ~> Skip subscribe!";
335                     }
336                 }
337                 break;
338 
339             case VSOMEIP_UNSUBSCRIBE:
340                 if (_size != VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE) {
341                     VSOMEIP_WARNING << "Received a UNSUBSCRIBE command with wrong size ~> skip!";
342                     break;
343                 }
344                 std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
345                         sizeof(its_service));
346                 std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
347                         sizeof(its_instance));
348                 std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
349                         sizeof(its_eventgroup));
350                 std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
351                         sizeof(its_notifier));
352 
353                 host_->unsubscribe(its_client, its_sender_uid, its_sender_gid, its_service,
354                         its_instance, its_eventgroup, its_notifier);
355                 break;
356 
357             case VSOMEIP_SUBSCRIBE_ACK:
358                 if (_size != VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE) {
359                     VSOMEIP_WARNING << "Received a SUBSCRIBE_ACK command with wrong size ~> skip!";
360                     break;
361                 }
362                 std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
363                         sizeof(its_service));
364                 std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
365                         sizeof(its_instance));
366                 std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
367                         sizeof(its_eventgroup));
368                 std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
369                         sizeof(its_subscriber));
370                 std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
371                         sizeof(its_notifier));
372                 std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
373                         sizeof(its_subscription_id));
374                 host_->on_subscribe_ack(its_subscriber, its_service,
375                         its_instance, its_eventgroup, its_notifier, its_subscription_id);
376                 VSOMEIP_INFO << "SUBSCRIBE ACK("
377                     << std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
378                     << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
379                     << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
380                     << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "."
381                     << std::hex << std::setw(4) << std::setfill('0') << its_notifier << "]";
382                 break;
383 
384             case VSOMEIP_SUBSCRIBE_NACK:
385                 if (_size != VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE) {
386                     VSOMEIP_WARNING << "Received a SUBSCRIBE_NACK command with wrong size ~> skip!";
387                     break;
388                 }
389                 std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
390                         sizeof(its_service));
391                 std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
392                         sizeof(its_instance));
393                 std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
394                         sizeof(its_eventgroup));
395                 std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
396                         sizeof(its_subscriber));
397                 std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
398                         sizeof(its_notifier));
399                 std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
400                         sizeof(its_subscription_id));
401                 host_->on_subscribe_nack(its_subscriber, its_service,
402                         its_instance, its_eventgroup, its_notifier,
403                         its_subscription_id, false);
404                 VSOMEIP_INFO << "SUBSCRIBE NACK("
405                     << std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
406                     << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
407                     << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
408                     << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "."
409                     << std::hex << std::setw(4) << std::setfill('0') << its_notifier << "]";
410                 break;
411             case VSOMEIP_UNSUBSCRIBE_ACK:
412                 if (_size != VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE) {
413                     VSOMEIP_WARNING << "Received a VSOMEIP_UNSUBSCRIBE_ACK command with wrong size ~> skip!";
414                     break;
415                 }
416                 std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
417                         sizeof(its_service));
418                 std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
419                         sizeof(its_instance));
420                 std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
421                         sizeof(its_eventgroup));
422                 std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
423                         sizeof(its_subscription_id));
424                 host_->on_unsubscribe_ack(its_client, its_service,
425                         its_instance, its_eventgroup, its_subscription_id);
426                 VSOMEIP_INFO << "UNSUBSCRIBE ACK("
427                     << std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
428                     << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
429                     << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
430                     << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "]";
431                 break;
432             case VSOMEIP_SEND: {
433                 if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
434                     VSOMEIP_WARNING << "Received a SEND command with too small size ~> skip!";
435                     break;
436                 }
437                 its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
438                 its_service = VSOMEIP_BYTES_TO_WORD(
439                                 its_data[VSOMEIP_SERVICE_POS_MIN],
440                                 its_data[VSOMEIP_SERVICE_POS_MAX]);
441                 its_client_from_header = VSOMEIP_BYTES_TO_WORD(
442                         its_data[VSOMEIP_CLIENT_POS_MIN],
443                         its_data[VSOMEIP_CLIENT_POS_MAX]);
444                 its_method = VSOMEIP_BYTES_TO_WORD(
445                         its_data[VSOMEIP_METHOD_POS_MIN],
446                         its_data[VSOMEIP_METHOD_POS_MAX]);
447                 std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
448                             sizeof(its_instance));
449                 std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
450                             sizeof(its_reliable));
451                 std::memcpy(&its_check_status, &_data[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
452                             sizeof(its_check_status));
453 
454                 // Allow response messages from local proxies as answer to remote requests
455                 // but check requests sent by local proxies to remote against policy.
456                 if (utility::is_request(its_data[VSOMEIP_MESSAGE_TYPE_POS])) {
457                     if (!security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
458                             its_client_from_header, its_service, its_instance, its_method)) {
459                         VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client_from_header
460                                 << " : routing_manager_stub::on_message: "
461                                 << " isn't allowed to send a request to service/instance/method "
462                                 << its_service << "/" << its_instance << "/" << its_method
463                                 << " ~> Skip message!";
464                         return;
465                     }
466                 }
467                 // reduce by size of instance, flush, reliable, client and is_valid_crc flag
468                 const std::uint32_t its_message_size = its_size -
469                         (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
470                 if (its_message_size !=
471                         VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
472                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
473                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
474                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
475                         + VSOMEIP_SOMEIP_HEADER_SIZE) {
476                     VSOMEIP_WARNING << "Received a SEND command containing message with invalid size -> skip!";
477                     break;
478                 }
479                 host_->on_message(its_service, its_instance, its_data, its_message_size,
480                         its_reliable, _bound_client, _credentials, its_check_status, false);
481                 break;
482             }
483             case VSOMEIP_NOTIFY: {
484                 if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
485                     VSOMEIP_WARNING << "Received a NOTIFY command with too small size ~> skip!";
486                     break;
487                 }
488                 its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
489                 its_service = VSOMEIP_BYTES_TO_WORD(
490                                 its_data[VSOMEIP_SERVICE_POS_MIN],
491                                 its_data[VSOMEIP_SERVICE_POS_MAX]);
492                 std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
493                             sizeof(its_instance));
494                 // reduce by size of instance, flush, reliable, is_valid_crc flag and target client
495                 const std::uint32_t its_message_size = its_size -
496                         (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
497                 if (its_message_size !=
498                         VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
499                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
500                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
501                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
502                         + VSOMEIP_SOMEIP_HEADER_SIZE) {
503                     VSOMEIP_WARNING << "Received a NOTIFY command containing message with invalid size -> skip!";
504                     break;
505                 }
506                 host_->on_notification(VSOMEIP_ROUTING_CLIENT, its_service, its_instance, its_data, its_message_size);
507                 break;
508             }
509             case VSOMEIP_NOTIFY_ONE: {
510                 if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
511                     VSOMEIP_WARNING << "Received a NOTIFY_ONE command with too small size ~> skip!";
512                     break;
513                 }
514                 its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
515                 its_service = VSOMEIP_BYTES_TO_WORD(
516                                 its_data[VSOMEIP_SERVICE_POS_MIN],
517                                 its_data[VSOMEIP_SERVICE_POS_MAX]);
518                 std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
519                             sizeof(its_instance));
520                 std::memcpy(&its_target_client, &_data[VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN],
521                             sizeof(client_t));
522                 // reduce by size of instance, flush, reliable flag, is_valid_crc and target client
523                 const std::uint32_t its_message_size = its_size -
524                         (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
525                 if (its_message_size !=
526                         VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
527                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
528                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
529                                               _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
530                         + VSOMEIP_SOMEIP_HEADER_SIZE) {
531                     VSOMEIP_WARNING << "Received a NOTIFY_ONE command containing message with invalid size -> skip!";
532                     break;
533                 }
534                 host_->on_notification(its_target_client, its_service, its_instance,
535                         its_data, its_message_size, true);
536                 break;
537             }
538             case VSOMEIP_REQUEST_SERVICE:
539                 {
540                     uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t)
541                             + sizeof(major_version_t) + sizeof(minor_version_t));
542                     if (its_size % entry_size > 0) {
543                         VSOMEIP_WARNING << "Received a REQUEST_SERVICE command with invalid size -> skip!";
544                         break;
545                     }
546                     uint32_t request_count(its_size / entry_size);
547                     std::set<service_data_t> requests;
548                     for (uint32_t i = 0; i < request_count; ++i) {
549                         service_t its_service;
550                         instance_t its_instance;
551                         major_version_t its_major;
552                         minor_version_t its_minor;
553                         std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)],
554                                 sizeof(its_service));
555                         std::memcpy(&its_instance,
556                                 &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)],
557                                 sizeof(its_instance));
558                         std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4 + (i * entry_size)],
559                                 sizeof(its_major));
560                         std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)],
561                                 sizeof(its_minor));
562                         if (security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
563                                 its_client, its_service, its_instance, 0x00, true)) {
564                             host_->request_service(its_client, its_service, its_instance,
565                                     its_major, its_minor );
566                             service_data_t request = {
567                                     its_service, its_instance,
568                                     its_major, its_minor
569                             };
570                             requests.insert(request);
571                         } else {
572                             VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
573                                     << its_client << " : routing_manager_stub::on_message: "
574                                     << "requests service/instance "
575                                     << its_service << "/" << its_instance
576                                     << " which violates the security policy ~> Skip request!";
577                         }
578                     }
579                     if (security::get()->is_enabled()) {
580                         handle_credentials(its_client, requests);
581                     }
582                     handle_requests(its_client, requests);
583                     break;
584                 }
585 
586                 case VSOMEIP_RELEASE_SERVICE:
587                     if (_size != VSOMEIP_RELEASE_SERVICE_COMMAND_SIZE) {
588                         VSOMEIP_WARNING << "Received a RELEASE_SERVICE command with wrong size ~> skip!";
589                         break;
590                     }
591                     std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
592                             sizeof(its_service));
593                     std::memcpy(&its_instance,
594                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
595                             sizeof(its_instance));
596 
597                     host_->release_service(its_client, its_service, its_instance);
598                     break;
599 
600                 case VSOMEIP_REGISTER_EVENT: {
601                     if (_size < VSOMEIP_REGISTER_EVENT_COMMAND_SIZE) {
602                         VSOMEIP_WARNING << "Received a REGISTER_EVENT command with wrong size ~> skip!";
603                         break;
604                     }
605 
606                     std::set<eventgroup_t> its_eventgroups;
607                     reliability_type_e its_reliability = reliability_type_e::RT_UNKNOWN;
608 
609                     std::memcpy(&its_service,
610                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
611                             sizeof(its_service));
612                     std::memcpy(&its_instance,
613                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
614                             sizeof(its_instance));
615                     std::memcpy(&its_notifier,
616                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
617                             sizeof(its_notifier));
618                     std::memcpy(&its_event_type,
619                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
620                             sizeof(its_event_type));
621                     std::memcpy(&is_provided,
622                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
623                             sizeof(is_provided));
624                     std::memcpy(&its_reliability,
625                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
626                             sizeof(its_reliability));
627                     if (is_provided
628                             && !configuration_->is_offered_remote(its_service,
629                                     its_instance)) {
630                         break;
631                     }
632                     for (std::size_t i = 9; i+1 < its_size; i++) {
633                         std::memcpy(&its_eventgroup,
634                                 &_data[VSOMEIP_COMMAND_PAYLOAD_POS + i],
635                                 sizeof(its_eventgroup));
636                         its_eventgroups.insert(its_eventgroup);
637                     }
638                     host_->register_shadow_event(its_client,
639                             its_service, its_instance,
640                             its_notifier, its_eventgroups, its_event_type,
641                             its_reliability,
642                             is_provided);
643                     VSOMEIP_INFO << "REGISTER EVENT("
644                         << std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
645                         << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
646                         << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
647                         << std::hex << std::setw(4) << std::setfill('0') << its_notifier
648                         << ":is_provider=" << is_provided << ":reliability="
649                         << (std::uint32_t)(its_reliability) << "]";
650                     break;
651                 }
652                 case VSOMEIP_UNREGISTER_EVENT:
653                     if (_size != VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE) {
654                         VSOMEIP_WARNING << "Received a UNREGISTER_EVENT command with wrong size ~> skip!";
655                         break;
656                     }
657                     std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
658                             sizeof(its_service));
659                     std::memcpy(&its_instance,
660                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
661                             sizeof(its_instance));
662                     std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
663                             sizeof(its_notifier));
664                     std::memcpy(&is_provided,
665                             &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
666                             sizeof(is_provided));
667                     if (is_provided
668                             && !configuration_->is_offered_remote(its_service,
669                                     its_instance)) {
670                         break;
671                     }
672                     host_->unregister_shadow_event(its_client, its_service, its_instance,
673                             its_notifier, is_provided);
674                     VSOMEIP_INFO << "UNREGISTER EVENT("
675                         << std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
676                         << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
677                         << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
678                         << std::hex << std::setw(4) << std::setfill('0') << its_notifier
679                         << ":is_provider=" << is_provided << "]";
680                     break;
681 
682                 case VSOMEIP_REGISTERED_ACK:
683                     if (_size != VSOMEIP_REGISTERED_ACK_COMMAND_SIZE) {
684                         VSOMEIP_WARNING << "Received a REGISTERED_ACK command with wrong size ~> skip!";
685                         break;
686                     }
687                     VSOMEIP_INFO << "REGISTERED_ACK("
688                         << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
689                     break;
690                 case VSOMEIP_OFFERED_SERVICES_REQUEST: {
691                     if (_size != VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE) {
692                         VSOMEIP_WARNING << "Received a VSOMEIP_OFFERED_SERVICES_REQUEST command with wrong size ~> skip!";
693                         break;
694                     }
695 
696                     std::memcpy(&its_offer_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
697                             sizeof(its_offer_type));
698 
699                     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
700                     create_offered_services_info(its_client);
701 
702                     for (const auto& found_client : routing_info_) {
703                         // skip services which are offered on remote hosts
704                         if (found_client.first != VSOMEIP_ROUTING_CLIENT) {
705                             for (const auto &its_service : found_client.second.second) {
706                                 for (const auto &its_instance : its_service.second) {
707                                     uint16_t its_reliable_port = configuration_->get_reliable_port(its_service.first,
708                                             its_instance.first);
709                                     uint16_t its_unreliable_port = configuration_->get_unreliable_port(
710                                             its_service.first, its_instance.first);
711 
712                                     if (its_offer_type == offer_type_e::OT_LOCAL) {
713                                         if (its_reliable_port == ILLEGAL_PORT
714                                                 && its_unreliable_port == ILLEGAL_PORT) {
715                                             insert_offered_services_info(its_client,
716                                                     routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
717                                                     its_service.first, its_instance.first,
718                                                     its_instance.second.first, its_instance.second.second);
719                                         }
720                                     }
721                                     else if (its_offer_type == offer_type_e::OT_REMOTE) {
722                                         if (its_reliable_port != ILLEGAL_PORT
723                                                 || its_unreliable_port != ILLEGAL_PORT) {
724                                             insert_offered_services_info(its_client,
725                                                     routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
726                                                     its_service.first, its_instance.first,
727                                                     its_instance.second.first, its_instance.second.second);
728                                         }
729                                     } else if (its_offer_type == offer_type_e::OT_ALL) {
730                                         insert_offered_services_info(its_client,
731                                                 routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
732                                                 its_service.first, its_instance.first,
733                                                 its_instance.second.first, its_instance.second.second);
734                                     }
735                                 }
736                             }
737                         }
738                     }
739                     send_offered_services_info(its_client);
740                     break;
741                 }
742                 case VSOMEIP_RESEND_PROVIDED_EVENTS: {
743                     if (_size != VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE) {
744                         VSOMEIP_WARNING << "Received a RESEND_PROVIDED_EVENTS command with wrong size ~> skip!";
745                         break;
746                     }
747                     pending_remote_offer_id_t its_pending_remote_offer_id(0);
748                     std::memcpy(&its_pending_remote_offer_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
749                             sizeof(pending_remote_offer_id_t));
750                     host_->on_resend_provided_events_response(its_pending_remote_offer_id);
751                     VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
752                         << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
753                     break;
754                 }
755                 case VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE: {
756                     if (_size != VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE) {
757                         VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE "
758                                 << "command with wrong size ~> skip!";
759                         break;
760                     }
761                     pending_security_update_id_t its_pending_security_update_id(0);
762                     std::memcpy(&its_pending_security_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
763                             sizeof(pending_security_update_id_t));
764 
765                     on_security_update_response(its_pending_security_update_id ,its_client);
766                     break;
767                 }
768                 case VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE: {
769                     if (_size != VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE) {
770                         VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE "
771                                 << "command with wrong size ~> skip!";
772                         break;
773                     }
774                     pending_security_update_id_t its_pending_security_update_id(0);
775                     std::memcpy(&its_pending_security_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
776                             sizeof(pending_security_update_id_t));
777 
778                     on_security_update_response(its_pending_security_update_id ,its_client);
779                     break;
780                 }
781             }
782         }
783     }
784 }
785 
on_register_application(client_t _client)786 void routing_manager_stub::on_register_application(client_t _client) {
787     auto endpoint = host_->find_local(_client);
788     if (endpoint) {
789         VSOMEIP_WARNING << "Reregistering application: " << std::hex << _client
790                 << ". Last registration might have been taken too long.";
791     } else {
792         endpoint = host_->find_or_create_local(_client);
793         {
794             std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
795             routing_info_[_client].first = 0;
796         }
797 
798         std::pair<uid_t, gid_t> its_uid_gid;
799         std::set<std::shared_ptr<policy> > its_policies;
800 
801         security::get()->get_client_to_uid_gid_mapping(_client, its_uid_gid);
802         get_requester_policies(its_uid_gid.first, its_uid_gid.second, its_policies);
803 
804         if (!its_policies.empty())
805             send_requester_policies({ _client }, its_policies);
806     }
807 }
808 
on_deregister_application(client_t _client)809 void routing_manager_stub::on_deregister_application(client_t _client) {
810     std::vector<
811             std::tuple<service_t, instance_t,
812                        major_version_t, minor_version_t>> services_to_report;
813     {
814         std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
815         auto its_info = routing_info_.find(_client);
816         if (its_info != routing_info_.end()) {
817             for (const auto &its_service : its_info->second.second) {
818                 for (const auto &its_instance : its_service.second) {
819                     const auto its_version = its_instance.second;
820                     services_to_report.push_back(
821                             std::make_tuple(its_service.first,
822                                     its_instance.first, its_version.first,
823                                     its_version.second));
824                 }
825             }
826         }
827         routing_info_.erase(_client);
828     }
829     for (const auto &s : services_to_report) {
830         host_->on_availability(std::get<0>(s), std::get<1>(s), false,
831                 std::get<2>(s), std::get<3>(s));
832         host_->on_stop_offer_service(_client, std::get<0>(s), std::get<1>(s),
833                 std::get<2>(s), std::get<3>(s));
834     }
835 }
836 
client_registration_func(void)837 void routing_manager_stub::client_registration_func(void) {
838 #ifndef _WIN32
839     {
840         std::stringstream s;
841         s << std::hex << std::setw(4) << std::setfill('0')
842             << host_->get_client() << "_client_reg";
843         pthread_setname_np(pthread_self(),s.str().c_str());
844     }
845 #endif
846     std::unique_lock<std::mutex> its_lock(client_registration_mutex_);
847     while (client_registration_running_) {
848         while (!pending_client_registrations_.size() && client_registration_running_) {
849             client_registration_condition_.wait(its_lock);
850         }
851 
852         std::map<client_t, std::vector<registration_type_e>> its_registrations(
853                 pending_client_registrations_);
854         pending_client_registrations_.clear();
855         its_lock.unlock();
856 
857         for (const auto& r : its_registrations) {
858             for (auto b : r.second) {
859                 if (b == registration_type_e::REGISTER) {
860                     on_register_application(r.first);
861                 } else {
862                     on_deregister_application(r.first);
863                 }
864                 // Inform (de)registered client. All others will be informed after
865                 // the client acknowledged its registered state!
866                 // Don't inform client if we deregister because of an client
867                 // endpoint error to avoid writing in an already closed socket
868                 if (b != registration_type_e::DEREGISTER_ON_ERROR) {
869                     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
870                     create_client_routing_info(r.first);
871                     insert_client_routing_info(r.first,
872                             b == registration_type_e::REGISTER ?
873                             routing_info_entry_e::RIE_ADD_CLIENT :
874                             routing_info_entry_e::RIE_DEL_CLIENT,
875                             r.first);
876                     // distribute updated security config to new clients
877                     if (b == registration_type_e::REGISTER) {
878                         send_cached_security_policies(r.first);
879                     }
880                     send_client_routing_info(r.first);
881                 }
882                 if (b != registration_type_e::REGISTER) {
883                     {
884                         std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
885                         auto its_connection = connection_matrix_.find(r.first);
886                         if (its_connection != connection_matrix_.end()) {
887                             for (auto its_client : its_connection->second) {
888                                 if (its_client != r.first &&
889                                         its_client != VSOMEIP_ROUTING_CLIENT &&
890                                         its_client != get_client()) {
891                                     create_client_routing_info(its_client);
892                                     insert_client_routing_info(its_client,
893                                             routing_info_entry_e::RIE_DEL_CLIENT, r.first);
894                                     send_client_routing_info(its_client);
895                                 }
896                             }
897                             connection_matrix_.erase(r.first);
898                         }
899                         for (const auto& its_client : connection_matrix_) {
900                             connection_matrix_[its_client.first].erase(r.first);
901                         }
902                         service_requests_.erase(r.first);
903                     }
904                     // Don't remove client ID to UID maping as same client
905                     // could have passed its credentials again
906                     host_->remove_local(r.first, false);
907                     utility::release_client_id(r.first);
908                 }
909             }
910         }
911         its_lock.lock();
912     }
913 }
914 
init_routing_endpoint()915 void routing_manager_stub::init_routing_endpoint() {
916     endpoint_ = host_->get_endpoint_manager()->create_local_server(
917             &is_socket_activated_, shared_from_this());
918 }
919 
on_offer_service(client_t _client,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor)920 void routing_manager_stub::on_offer_service(client_t _client,
921         service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) {
922     if (_client == host_->get_client()) {
923         create_local_receiver();
924     }
925 
926     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
927     routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
928     if (security::get()->is_enabled()) {
929         distribute_credentials(_client, _service, _instance);
930     }
931     inform_requesters(_client, _service, _instance, _major, _minor,
932             routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, true);
933 }
934 
on_stop_offer_service(client_t _client,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor)935 void routing_manager_stub::on_stop_offer_service(client_t _client,
936         service_t _service, instance_t _instance,  major_version_t _major, minor_version_t _minor) {
937     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
938     auto found_client = routing_info_.find(_client);
939     if (found_client != routing_info_.end()) {
940         auto found_service = found_client->second.second.find(_service);
941         if (found_service != found_client->second.second.end()) {
942             auto found_instance = found_service->second.find(_instance);
943             if (found_instance != found_service->second.end()) {
944                 auto found_version = found_instance->second;
945                 if( _major == found_version.first && _minor == found_version.second) {
946                     found_service->second.erase(_instance);
947                     if (0 == found_service->second.size()) {
948                         found_client->second.second.erase(_service);
949                     }
950                     inform_provider(_client, _service, _instance, _major, _minor,
951                             routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE);
952                     inform_requesters(_client, _service, _instance, _major, _minor,
953                             routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE, false);
954                 } else if( _major == DEFAULT_MAJOR && _minor == DEFAULT_MINOR) {
955                     found_service->second.erase(_instance);
956                     if (0 == found_service->second.size()) {
957                         found_client->second.second.erase(_service);
958                     }
959                     inform_provider(_client, _service, _instance, _major, _minor,
960                             routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE);
961                     inform_requesters(_client, _service, _instance, _major, _minor,
962                             routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE, false);
963                 }
964             }
965         }
966     }
967 }
968 
create_client_routing_info(const client_t _target)969 void routing_manager_stub::create_client_routing_info(const client_t _target) {
970     std::vector<byte_t> its_command;
971     its_command.push_back(VSOMEIP_ROUTING_INFO);
972 
973     // Sender client
974     client_t client = get_client();
975     for (uint32_t i = 0; i < sizeof(client_t); ++i) {
976         its_command.push_back(
977                 reinterpret_cast<const byte_t*>(&client)[i]);
978     }
979 
980     // Overall size placeholder
981     byte_t size_placeholder = 0x0;
982     for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
983         its_command.push_back(size_placeholder);
984     }
985 
986     client_routing_info_[_target] = its_command;
987 }
988 
create_client_credentials_info(const client_t _target)989 void routing_manager_stub::create_client_credentials_info(const client_t _target) {
990     std::vector<byte_t> its_command;
991     its_command.push_back(VSOMEIP_UPDATE_SECURITY_CREDENTIALS);
992 
993     // Sender client
994     client_t client = get_client();
995     for (uint32_t i = 0; i < sizeof(client_t); ++i) {
996         its_command.push_back(
997                 reinterpret_cast<const byte_t*>(&client)[i]);
998     }
999 
1000     // Overall size placeholder
1001     byte_t size_placeholder = 0x0;
1002     for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
1003         its_command.push_back(size_placeholder);
1004     }
1005 
1006     client_credentials_info_[_target] = its_command;
1007 }
1008 
insert_client_credentials_info(client_t _target,std::set<std::pair<uint32_t,uint32_t>> _credentials)1009 void routing_manager_stub::insert_client_credentials_info(client_t _target, std::set<std::pair<uint32_t, uint32_t>> _credentials) {
1010     if (client_credentials_info_.find(_target) == client_credentials_info_.end()) {
1011         return;
1012     }
1013 
1014     auto its_command = client_credentials_info_[_target];
1015 
1016     // insert uid / gid credential pairs
1017     for (auto its_credentials : _credentials) {
1018         //uid
1019         for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
1020             its_command.push_back(
1021                     reinterpret_cast<const byte_t*>(&std::get<0>(its_credentials))[i]);
1022         }
1023         //gid
1024         for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
1025             its_command.push_back(
1026                     reinterpret_cast<const byte_t*>(&std::get<1>(its_credentials))[i]);
1027         }
1028     }
1029 
1030     client_credentials_info_[_target] = its_command;
1031 }
1032 
send_client_credentials_info(const client_t _target)1033 void routing_manager_stub::send_client_credentials_info(const client_t _target) {
1034     if (client_credentials_info_.find(_target) == client_credentials_info_.end()) {
1035         return;
1036     }
1037 
1038     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
1039     if (its_endpoint) {
1040         auto its_command = client_credentials_info_[_target];
1041 
1042         // File overall size
1043         std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
1044         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
1045         its_size += VSOMEIP_COMMAND_PAYLOAD_POS;
1046 
1047 #if 0
1048         std::stringstream msg;
1049         msg << "rms::send_credentials_info to (" << std::hex << _target << "): ";
1050         for (uint32_t i = 0; i < its_size; ++i)
1051             msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " ";
1052         VSOMEIP_INFO << msg.str();
1053 #endif
1054 
1055         // Send routing info or error!
1056         if(its_command.size() <= max_local_message_size_
1057                 || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
1058             its_endpoint->send(&its_command[0], uint32_t(its_size));
1059         } else {
1060             VSOMEIP_ERROR << "Credentials info exceeds maximum message size: Can't send!";
1061         }
1062 
1063         client_credentials_info_.erase(_target);
1064     } else {
1065         VSOMEIP_ERROR << "Send credentials info to client 0x" << std::hex << _target
1066                 << " failed: No valid endpoint!";
1067     }
1068 }
1069 
create_offered_services_info(const client_t _target)1070 void routing_manager_stub::create_offered_services_info(const client_t _target) {
1071     std::vector<byte_t> its_command;
1072     its_command.push_back(VSOMEIP_OFFERED_SERVICES_RESPONSE);
1073 
1074     // Sender client
1075     client_t client = get_client();
1076     for (uint32_t i = 0; i < sizeof(client_t); ++i) {
1077         its_command.push_back(
1078                 reinterpret_cast<const byte_t*>(&client)[i]);
1079     }
1080 
1081     // Overall size placeholder
1082     byte_t size_placeholder = 0x0;
1083     for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
1084         its_command.push_back(size_placeholder);
1085     }
1086 
1087     offered_services_info_[_target] = its_command;
1088 }
1089 
1090 
send_client_routing_info(const client_t _target)1091 void routing_manager_stub::send_client_routing_info(const client_t _target) {
1092     if (client_routing_info_.find(_target) == client_routing_info_.end()) {
1093         return;
1094     }
1095     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
1096     if (its_endpoint) {
1097         auto its_command = client_routing_info_[_target];
1098 
1099         // File overall size
1100         std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
1101         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
1102         its_size += VSOMEIP_COMMAND_PAYLOAD_POS;
1103 
1104 #if 0
1105         std::stringstream msg;
1106         msg << "rms::send_routing_info to (" << std::hex << _target << "): ";
1107         for (uint32_t i = 0; i < its_size; ++i)
1108             msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " ";
1109         VSOMEIP_INFO << msg.str();
1110 #endif
1111 
1112         // Send routing info or error!
1113         if(its_command.size() <= max_local_message_size_
1114                 || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
1115             its_endpoint->send(&its_command[0], uint32_t(its_size));
1116         } else {
1117             VSOMEIP_ERROR << "Routing info exceeds maximum message size: Can't send!";
1118         }
1119 
1120         client_routing_info_.erase(_target);
1121     } else {
1122         VSOMEIP_ERROR << "Send routing info to client 0x" << std::hex << _target
1123                 << " failed: No valid endpoint!";
1124     }
1125 }
1126 
1127 
send_offered_services_info(const client_t _target)1128 void routing_manager_stub::send_offered_services_info(const client_t _target) {
1129     if (offered_services_info_.find(_target) == offered_services_info_.end()) {
1130         return;
1131     }
1132     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
1133     if (its_endpoint) {
1134         auto its_command = offered_services_info_[_target];
1135 
1136         // File overall size
1137         std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
1138         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
1139         its_size += VSOMEIP_COMMAND_PAYLOAD_POS;
1140 
1141 #if 0
1142         std::stringstream msg;
1143         msg << "rms::send_offered_services_info to (" << std::hex << _target << "): ";
1144         for (uint32_t i = 0; i < its_size; ++i)
1145             msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " ";
1146         VSOMEIP_INFO << msg.str();
1147 #endif
1148 
1149         // Send routing info or error!
1150         if(its_command.size() <= max_local_message_size_
1151                 || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
1152             its_endpoint->send(&its_command[0], uint32_t(its_size));
1153         } else {
1154             VSOMEIP_ERROR << "Offered services info exceeds maximum message size: Can't send!";
1155         }
1156 
1157         offered_services_info_.erase(_target);
1158     } else {
1159         VSOMEIP_ERROR << "Send offered services info to client 0x" << std::hex << _target
1160                 << " failed: No valid endpoint!";
1161     }
1162 }
1163 
insert_client_routing_info(client_t _target,routing_info_entry_e _entry,client_t _client,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor)1164 void routing_manager_stub::insert_client_routing_info(client_t _target,
1165         routing_info_entry_e _entry,
1166         client_t _client, service_t _service,
1167         instance_t _instance,
1168         major_version_t _major,
1169         minor_version_t _minor) {
1170 
1171     if (client_routing_info_.find(_target) == client_routing_info_.end()) {
1172         return;
1173     }
1174 
1175     connection_matrix_[_target].insert(_client);
1176 
1177     auto its_command = client_routing_info_[_target];
1178 
1179     // Routing Info State Change
1180     for (uint32_t i = 0; i < sizeof(routing_info_entry_e); ++i) {
1181         its_command.push_back(
1182                 reinterpret_cast<const byte_t*>(&_entry)[i]);
1183     }
1184 
1185     std::size_t its_size_pos = its_command.size();
1186     std::size_t its_entry_size = its_command.size();
1187 
1188     // Client size placeholder
1189     byte_t placeholder = 0x0;
1190     for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
1191         its_command.push_back(placeholder);
1192     }
1193     // Client
1194     for (uint32_t i = 0; i < sizeof(client_t); ++i) {
1195          its_command.push_back(
1196                  reinterpret_cast<const byte_t*>(&_client)[i]);
1197     }
1198 
1199     if (_entry == routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE ||
1200             _entry == routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE) {
1201         //Service
1202         uint32_t its_service_entry_size = uint32_t(sizeof(service_t)
1203                 + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t));
1204         for (uint32_t i = 0; i < sizeof(its_service_entry_size); ++i) {
1205             its_command.push_back(
1206                     reinterpret_cast<const byte_t*>(&its_service_entry_size)[i]);
1207         }
1208         for (uint32_t i = 0; i < sizeof(service_t); ++i) {
1209             its_command.push_back(
1210                     reinterpret_cast<const byte_t*>(&_service)[i]);
1211         }
1212         // Instance
1213         for (uint32_t i = 0; i < sizeof(instance_t); ++i) {
1214             its_command.push_back(
1215                     reinterpret_cast<const byte_t*>(&_instance)[i]);
1216         }
1217         // Major version
1218         for (uint32_t i = 0; i < sizeof(major_version_t); ++i) {
1219             its_command.push_back(
1220                     reinterpret_cast<const byte_t*>(&_major)[i]);
1221         }
1222         // Minor version
1223         for (uint32_t i = 0; i < sizeof(minor_version_t); ++i) {
1224             its_command.push_back(
1225                     reinterpret_cast<const byte_t*>(&_minor)[i]);
1226         }
1227     }
1228 
1229     // File client size
1230     its_entry_size = its_command.size() - its_entry_size - uint32_t(sizeof(uint32_t));
1231     std::memcpy(&its_command[its_size_pos], &its_entry_size, sizeof(uint32_t));
1232 
1233     client_routing_info_[_target] = its_command;
1234 }
1235 
insert_offered_services_info(client_t _target,routing_info_entry_e _entry,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor)1236 void routing_manager_stub::insert_offered_services_info(client_t _target,
1237         routing_info_entry_e _entry,
1238         service_t _service,
1239         instance_t _instance,
1240         major_version_t _major,
1241         minor_version_t _minor) {
1242 
1243     if (offered_services_info_.find(_target) == offered_services_info_.end()) {
1244         return;
1245     }
1246 
1247     auto its_command = offered_services_info_[_target];
1248 
1249     // Routing Info State Change
1250     for (uint32_t i = 0; i < sizeof(routing_info_entry_e); ++i) {
1251         its_command.push_back(
1252                 reinterpret_cast<const byte_t*>(&_entry)[i]);
1253     }
1254 
1255     // entry size
1256     uint32_t its_service_entry_size = uint32_t(sizeof(service_t)
1257             + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t));
1258     for (uint32_t i = 0; i < sizeof(its_service_entry_size); ++i) {
1259         its_command.push_back(
1260                 reinterpret_cast<const byte_t*>(&its_service_entry_size)[i]);
1261     }
1262     //Service
1263     for (uint32_t i = 0; i < sizeof(service_t); ++i) {
1264         its_command.push_back(
1265                 reinterpret_cast<const byte_t*>(&_service)[i]);
1266     }
1267     // Instance
1268     for (uint32_t i = 0; i < sizeof(instance_t); ++i) {
1269         its_command.push_back(
1270                 reinterpret_cast<const byte_t*>(&_instance)[i]);
1271     }
1272     // Major version
1273     for (uint32_t i = 0; i < sizeof(major_version_t); ++i) {
1274         its_command.push_back(
1275                 reinterpret_cast<const byte_t*>(&_major)[i]);
1276     }
1277     // Minor version
1278     for (uint32_t i = 0; i < sizeof(minor_version_t); ++i) {
1279         its_command.push_back(
1280                 reinterpret_cast<const byte_t*>(&_minor)[i]);
1281     }
1282 
1283     offered_services_info_[_target] = its_command;
1284 }
1285 
distribute_credentials(client_t _hoster,service_t _service,instance_t _instance)1286 void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _service, instance_t _instance) {
1287     std::set<std::pair<uint32_t, uint32_t>> its_credentials;
1288     std::set<client_t> its_requesting_clients;
1289     // search for clients which shall receive the credentials
1290     for (auto its_requesting_client : service_requests_) {
1291         auto its_service = its_requesting_client.second.find(_service);
1292         if (its_service != its_requesting_client.second.end()) {
1293             if (its_service->second.find(_instance) != its_service->second.end()
1294                     || its_service->second.find(ANY_INSTANCE) != its_service->second.end()) {
1295                  its_requesting_clients.insert(its_requesting_client.first);
1296             }
1297         }
1298     }
1299 
1300     // search for UID / GID linked with the client ID that offers the requested services
1301     std::pair<uint32_t, uint32_t> its_uid_gid;
1302     if (security::get()->get_client_to_uid_gid_mapping(_hoster, its_uid_gid)) {
1303         its_credentials.insert(its_uid_gid);
1304         for (auto its_requesting_client : its_requesting_clients) {
1305             std::pair<uint32_t, uint32_t> its_requester_uid_gid;
1306             if (security::get()->get_client_to_uid_gid_mapping(its_requesting_client, its_requester_uid_gid)) {
1307                 if (its_uid_gid != its_requester_uid_gid) {
1308                     create_client_credentials_info(its_requesting_client);
1309                     insert_client_credentials_info(its_requesting_client, its_credentials);
1310                     send_client_credentials_info(its_requesting_client);
1311                 }
1312             }
1313         }
1314     }
1315 }
1316 
inform_provider(client_t _hoster,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor,routing_info_entry_e _entry)1317 void routing_manager_stub::inform_provider(client_t _hoster, service_t _service,
1318         instance_t _instance, major_version_t _major, minor_version_t _minor,
1319         routing_info_entry_e _entry) {
1320 
1321 	if (_hoster != VSOMEIP_ROUTING_CLIENT
1322 			&& _hoster != host_->get_client()) {
1323 		create_client_routing_info(_hoster);
1324 		insert_client_routing_info(_hoster, _entry, _hoster,
1325 				_service, _instance, _major, _minor);
1326 		send_client_routing_info(_hoster);
1327 	}
1328 };
1329 
inform_requesters(client_t _hoster,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor,routing_info_entry_e _entry,bool _inform_service)1330 void routing_manager_stub::inform_requesters(client_t _hoster, service_t _service,
1331         instance_t _instance, major_version_t _major, minor_version_t _minor,
1332         routing_info_entry_e _entry, bool _inform_service) {
1333     for (auto its_client : service_requests_) {
1334         auto its_service = its_client.second.find(_service);
1335         if (its_service != its_client.second.end()) {
1336             if (its_service->second.find(_instance) != its_service->second.end()
1337                     || its_service->second.find(ANY_INSTANCE) != its_service->second.end()) {
1338                 if (_inform_service) {
1339                     if (_hoster != VSOMEIP_ROUTING_CLIENT &&
1340                             _hoster != host_->get_client()) {
1341                         if (!is_already_connected(_hoster, its_client.first)) {
1342                             create_client_routing_info(_hoster);
1343                             insert_client_routing_info(_hoster,
1344                                     routing_info_entry_e::RIE_ADD_CLIENT,
1345                                     its_client.first);
1346                             send_client_routing_info(_hoster);
1347                         }
1348                     }
1349                 }
1350                 if (its_client.first != VSOMEIP_ROUTING_CLIENT &&
1351                         its_client.first != get_client()) {
1352                     create_client_routing_info(its_client.first);
1353                     insert_client_routing_info(its_client.first, _entry, _hoster,
1354                             _service, _instance, _major, _minor);
1355                     send_client_routing_info(its_client.first);
1356                 }
1357             }
1358         }
1359     }
1360 }
1361 
is_already_connected(client_t _source,client_t _sink)1362 bool routing_manager_stub::is_already_connected(client_t _source, client_t _sink) {
1363     return connection_matrix_[_source].find(_sink) != connection_matrix_[_source].end();
1364 }
1365 
broadcast(const std::vector<byte_t> & _command) const1366 void routing_manager_stub::broadcast(const std::vector<byte_t> &_command) const {
1367     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
1368     for (const auto& a : routing_info_) {
1369         if (a.first != VSOMEIP_ROUTING_CLIENT && a.first != host_->get_client()) {
1370             std::shared_ptr<endpoint> its_endpoint
1371                 = host_->find_local(a.first);
1372             if (its_endpoint) {
1373                 its_endpoint->send(&_command[0], uint32_t(_command.size()));
1374             }
1375         }
1376     }
1377 }
1378 
send_subscribe(const std::shared_ptr<endpoint> & _target,client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,major_version_t _major,event_t _event,remote_subscription_id_t _id)1379 bool routing_manager_stub::send_subscribe(const std::shared_ptr<endpoint>& _target,
1380         client_t _client, service_t _service, instance_t _instance,
1381         eventgroup_t _eventgroup, major_version_t _major,
1382         event_t _event, remote_subscription_id_t _id) {
1383     if (_target) {
1384         byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE];
1385         uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE
1386                 - VSOMEIP_COMMAND_HEADER_SIZE;
1387         its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE;
1388         std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
1389                 sizeof(_client));
1390         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
1391                 sizeof(its_size));
1392         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
1393                 sizeof(_service));
1394         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
1395                 sizeof(_instance));
1396         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
1397                 sizeof(_eventgroup));
1398         its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major;
1399         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_event,
1400                 sizeof(_event));
1401         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_id,
1402                 sizeof(_id));
1403 
1404         return _target->send(its_command, sizeof(its_command));
1405     } else {
1406         VSOMEIP_WARNING << __func__ << " Couldn't send subscription to local client ["
1407                 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
1408                 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
1409                 << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
1410                 << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
1411                 << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
1412                 << _client;
1413         return false;
1414     }
1415 }
1416 
send_unsubscribe(const std::shared_ptr<endpoint> & _target,client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event,remote_subscription_id_t _id)1417 bool routing_manager_stub::send_unsubscribe(
1418         const std::shared_ptr<endpoint>& _target,
1419         client_t _client, service_t _service, instance_t _instance,
1420         eventgroup_t _eventgroup, event_t _event,
1421         remote_subscription_id_t _id) {
1422     if (_target) {
1423         byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE];
1424         uint32_t its_size = VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE
1425                 - VSOMEIP_COMMAND_HEADER_SIZE;
1426         its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNSUBSCRIBE;
1427         std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
1428                 sizeof(_client));
1429         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
1430                 sizeof(its_size));
1431         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
1432                 sizeof(_service));
1433         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
1434                 sizeof(_instance));
1435         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
1436                 sizeof(_eventgroup));
1437         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
1438                 sizeof(_event));
1439         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_id,
1440                 sizeof(_id));
1441 
1442         return _target->send(its_command, sizeof(its_command));
1443     } else {
1444         VSOMEIP_WARNING << __func__ << " Couldn't send unsubscription to local client ["
1445                 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
1446                 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
1447                 << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
1448                 << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
1449                 << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
1450                 << _client;
1451         return false;
1452     }
1453 }
1454 
send_expired_subscription(const std::shared_ptr<endpoint> & _target,client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event,remote_subscription_id_t _id)1455 bool routing_manager_stub::send_expired_subscription(
1456         const std::shared_ptr<endpoint>& _target,
1457         client_t _client, service_t _service, instance_t _instance,
1458         eventgroup_t _eventgroup, event_t _event,
1459         remote_subscription_id_t _id) {
1460     if (_target) {
1461         byte_t its_command[VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE];
1462         uint32_t its_size = VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE
1463                 - VSOMEIP_COMMAND_HEADER_SIZE;
1464         its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_EXPIRED_SUBSCRIPTION;
1465         std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
1466                 sizeof(_client));
1467         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
1468                 sizeof(its_size));
1469         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
1470                 sizeof(_service));
1471         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
1472                 sizeof(_instance));
1473         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
1474                 sizeof(_eventgroup));
1475         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
1476                 sizeof(_event));
1477         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_id,
1478                 sizeof(_id));
1479 
1480         return _target->send(its_command, sizeof(its_command));
1481     } else {
1482         VSOMEIP_WARNING << __func__ << " Couldn't send expired subscription to local client ["
1483                 << std::hex << std::setw(4) << std::setfill('0') << _service << "."
1484                 << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
1485                 << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
1486                 << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
1487                 << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
1488                 << _client;
1489         return false;
1490     }
1491 }
1492 
send_subscribe_ack(client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event)1493 void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _service,
1494             instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
1495 
1496     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
1497     if (its_endpoint) {
1498         byte_t its_command[VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE];
1499         uint32_t its_size = VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE
1500                 - VSOMEIP_COMMAND_HEADER_SIZE;
1501 
1502         client_t this_client = get_client();
1503         its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_ACK;
1504         std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
1505                 sizeof(this_client));
1506         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
1507                 sizeof(its_size));
1508         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
1509                 sizeof(_service));
1510         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
1511                 sizeof(_instance));
1512         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
1513                 sizeof(_eventgroup));
1514         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_client,
1515                 sizeof(_client));
1516         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
1517                 sizeof(_event));
1518         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
1519                 &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
1520 
1521         its_endpoint->send(&its_command[0], sizeof(its_command));
1522     }
1523 }
1524 
send_subscribe_nack(client_t _client,service_t _service,instance_t _instance,eventgroup_t _eventgroup,event_t _event)1525 void routing_manager_stub::send_subscribe_nack(client_t _client, service_t _service,
1526             instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
1527 
1528     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
1529     if (its_endpoint) {
1530         byte_t its_command[VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE];
1531         uint32_t its_size = VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE
1532                 - VSOMEIP_COMMAND_HEADER_SIZE;
1533 
1534         client_t this_client = get_client();
1535         its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_NACK;
1536         std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
1537                 sizeof(this_client));
1538         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
1539                 sizeof(its_size));
1540         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
1541                 sizeof(_service));
1542         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
1543                 sizeof(_instance));
1544         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
1545                 sizeof(_eventgroup));
1546         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_client,
1547                 sizeof(_client));
1548         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
1549                 sizeof(_event));
1550         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
1551                 &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
1552 
1553         its_endpoint->send(&its_command[0], sizeof(its_command));
1554     }
1555 }
1556 
contained_in_routing_info(client_t _client,service_t _service,instance_t _instance,major_version_t _major,minor_version_t _minor) const1557 bool routing_manager_stub::contained_in_routing_info(
1558         client_t _client, service_t _service, instance_t _instance,
1559         major_version_t _major, minor_version_t _minor) const {
1560     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
1561     auto found_client = routing_info_.find(_client);
1562     if (found_client != routing_info_.end()) {
1563         auto found_service = found_client->second.second.find(_service);
1564         if (found_service != found_client->second.second.end()) {
1565             auto found_instance = found_service->second.find(_instance);
1566             if (found_instance != found_service->second.end()) {
1567                 if (found_instance->second.first == _major
1568                         && found_instance->second.second == _minor) {
1569                     return true;
1570                 }
1571             }
1572         }
1573     }
1574     return false;
1575 }
1576 
1577 // Watchdog
broadcast_ping() const1578 void routing_manager_stub::broadcast_ping() const {
1579     broadcast(its_ping_);
1580 }
1581 
on_pong(client_t _client)1582 void routing_manager_stub::on_pong(client_t _client) {
1583     {
1584         std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
1585         auto found_info = routing_info_.find(_client);
1586         if (found_info != routing_info_.end()) {
1587             found_info->second.first = 0;
1588         } else {
1589             VSOMEIP_ERROR << "Received PONG from unregistered application: "
1590                     << std::hex << std::setw(4) << std::setfill('0') << _client;
1591         }
1592     }
1593     remove_from_pinged_clients(_client);
1594     host_->on_pong(_client);
1595 }
1596 
start_watchdog()1597 void routing_manager_stub::start_watchdog() {
1598 
1599     auto its_callback =
1600             [this](boost::system::error_code const &_error) {
1601                 if (!_error)
1602                     check_watchdog();
1603             };
1604     {
1605         std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_);
1606         // Divide / 2 as start and check sleep each
1607         watchdog_timer_.expires_from_now(
1608                 std::chrono::milliseconds(
1609                         configuration_->get_watchdog_timeout() / 2));
1610 
1611         watchdog_timer_.async_wait(its_callback);
1612     }
1613 }
1614 
check_watchdog()1615 void routing_manager_stub::check_watchdog() {
1616     {
1617         std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
1618         for (auto i = routing_info_.begin(); i != routing_info_.end(); ++i) {
1619             i->second.first++;
1620         }
1621     }
1622     broadcast_ping();
1623 
1624 
1625     auto its_callback = [this](boost::system::error_code const &_error) {
1626                 (void)_error;
1627                 std::list< client_t > lost;
1628                 {
1629                     std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
1630                     for (const auto& i : routing_info_) {
1631                         if (i.first > 0 && i.first != host_->get_client()) {
1632                             if (i.second.first > configuration_->get_allowed_missing_pongs()) {
1633                                 VSOMEIP_WARNING << "Lost contact to application " << std::hex << (int)i.first;
1634                                 lost.push_back(i.first);
1635                             }
1636                         }
1637                     }
1638                 }
1639                 for (auto i : lost) {
1640                     host_->handle_client_error(i);
1641                 }
1642                 start_watchdog();
1643             };
1644     {
1645         std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_);
1646         watchdog_timer_.expires_from_now(
1647                 std::chrono::milliseconds(
1648                         configuration_->get_watchdog_timeout() / 2));
1649         watchdog_timer_.async_wait(its_callback);
1650     }
1651 }
1652 
create_local_receiver()1653 void routing_manager_stub::create_local_receiver() {
1654     std::lock_guard<std::mutex> its_lock(local_receiver_mutex_);
1655 
1656     if (local_receiver_) {
1657         return;
1658     }
1659 #ifndef _WIN32
1660     else if (!security::get()->check_credentials(get_client(), getuid(), getgid())) {
1661         VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
1662                 << " : routing_manager_stub::create_local_receiver:  isn't allowed"
1663                 << " to create a server endpoint due to credential check failed!";
1664         return;
1665     }
1666 #endif
1667     local_receiver_ = std::static_pointer_cast<endpoint_manager_base>(
1668             host_->get_endpoint_manager())->create_local_server(shared_from_this());
1669     local_receiver_->start();
1670 }
1671 
send_ping(client_t _client)1672 bool routing_manager_stub::send_ping(client_t _client) {
1673     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
1674     if (!its_endpoint) {
1675         return false;
1676     }
1677 
1678     {
1679         std::lock_guard<std::mutex> its_lock(pinged_clients_mutex_);
1680 
1681         if (pinged_clients_.find(_client) != pinged_clients_.end()) {
1682             // client was already pinged: don't ping again and wait for answer
1683             // or timeout of previous ping.
1684             return true;
1685         }
1686 
1687         boost::system::error_code ec;
1688         pinged_clients_timer_.cancel(ec);
1689         if (ec) {
1690             VSOMEIP_ERROR << "routing_manager_stub::send_ping cancellation of "
1691                     "timer failed: " << ec.message();
1692         }
1693         const std::chrono::steady_clock::time_point now(
1694                 std::chrono::steady_clock::now());
1695 
1696         std::chrono::milliseconds next_timeout(configured_watchdog_timeout_);
1697         for (const auto &tp : pinged_clients_) {
1698             const std::chrono::milliseconds its_clients_timeout =
1699                     std::chrono::duration_cast<std::chrono::milliseconds>(
1700                             now - tp.second);
1701             if (next_timeout > its_clients_timeout) {
1702                 next_timeout = its_clients_timeout;
1703             }
1704         }
1705 
1706         pinged_clients_[_client] = now;
1707 
1708         ec.clear();
1709         pinged_clients_timer_.expires_from_now(next_timeout, ec);
1710         if (ec) {
1711             VSOMEIP_ERROR<< "routing_manager_stub::send_ping setting "
1712             "expiry time of timer failed: " << ec.message();
1713         }
1714         pinged_clients_timer_.async_wait(
1715                 std::bind(&routing_manager_stub::on_ping_timer_expired, this,
1716                         std::placeholders::_1));
1717         return its_endpoint->send(&its_ping_[0], uint32_t(its_ping_.size()));
1718     }
1719 }
1720 
on_ping_timer_expired(boost::system::error_code const & _error)1721 void routing_manager_stub::on_ping_timer_expired(
1722         boost::system::error_code const &_error) {
1723     if(_error) {
1724         return;
1725     }
1726     std::forward_list<client_t> timed_out_clients;
1727     std::chrono::milliseconds next_timeout(configured_watchdog_timeout_);
1728     bool pinged_clients_remaining(false);
1729 
1730     {
1731         // remove timed out clients
1732         std::lock_guard<std::mutex> its_lock(pinged_clients_mutex_);
1733         const std::chrono::steady_clock::time_point now(
1734                 std::chrono::steady_clock::now());
1735 
1736         for (auto client_iter = pinged_clients_.begin();
1737                   client_iter != pinged_clients_.end(); ) {
1738             if ((now - client_iter->second) >= configured_watchdog_timeout_) {
1739                 timed_out_clients.push_front(client_iter->first);
1740                 client_iter = pinged_clients_.erase(client_iter);
1741             } else {
1742                 ++client_iter;
1743             }
1744         }
1745         pinged_clients_remaining = (pinged_clients_.size() > 0);
1746 
1747         if(pinged_clients_remaining) {
1748             // find out next timeout
1749             for (const auto &tp : pinged_clients_) {
1750                 const std::chrono::milliseconds its_clients_timeout =
1751                         std::chrono::duration_cast<std::chrono::milliseconds>(
1752                                 now - tp.second);
1753                 if (next_timeout > its_clients_timeout) {
1754                     next_timeout = its_clients_timeout;
1755                 }
1756             }
1757         }
1758     }
1759 
1760     for (const client_t client : timed_out_clients) {
1761         // Client did not respond to ping. Report client_error in order to
1762         // accept pending offers trying to replace the offers of the client
1763         // that seems to be gone.
1764         host_->handle_client_error(client);
1765     }
1766     if (pinged_clients_remaining) {
1767         boost::system::error_code ec;
1768         pinged_clients_timer_.expires_from_now(next_timeout, ec);
1769         if (ec) {
1770             VSOMEIP_ERROR<< "routing_manager_stub::on_ping_timer_expired "
1771             "setting expiry time of timer failed: " << ec.message();
1772         }
1773         pinged_clients_timer_.async_wait(
1774                 std::bind(&routing_manager_stub::on_ping_timer_expired, this,
1775                         std::placeholders::_1));
1776     }
1777 }
1778 
remove_from_pinged_clients(client_t _client)1779 void routing_manager_stub::remove_from_pinged_clients(client_t _client) {
1780     std::lock_guard<std::mutex> its_lock(pinged_clients_mutex_);
1781     if (!pinged_clients_.size()) {
1782         return;
1783     }
1784     boost::system::error_code ec;
1785     pinged_clients_timer_.cancel(ec);
1786     if (ec) {
1787         VSOMEIP_ERROR << "routing_manager_stub::remove_from_pinged_clients "
1788                 "cancellation of timer failed: " << ec.message();
1789     }
1790     pinged_clients_.erase(_client);
1791 
1792     if (!pinged_clients_.size()) {
1793             return;
1794     }
1795     const std::chrono::steady_clock::time_point now(
1796             std::chrono::steady_clock::now());
1797     std::chrono::milliseconds next_timeout(configured_watchdog_timeout_);
1798     // find out next timeout
1799     for (const auto &tp : pinged_clients_) {
1800         const std::chrono::milliseconds its_clients_timeout =
1801                 std::chrono::duration_cast<std::chrono::milliseconds>(
1802                         now - tp.second);
1803         if (next_timeout > its_clients_timeout) {
1804             next_timeout = its_clients_timeout;
1805         }
1806     }
1807     ec.clear();
1808     pinged_clients_timer_.expires_from_now(next_timeout, ec);
1809     if (ec) {
1810         VSOMEIP_ERROR<< "routing_manager_stub::remove_from_pinged_clients "
1811         "setting expiry time of timer failed: " << ec.message();
1812     }
1813     pinged_clients_timer_.async_wait(
1814             std::bind(&routing_manager_stub::on_ping_timer_expired, this,
1815                       std::placeholders::_1));
1816 }
1817 
is_registered(client_t _client) const1818 bool routing_manager_stub::is_registered(client_t _client) const {
1819     std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
1820     return (routing_info_.find(_client) != routing_info_.end());
1821 }
1822 
update_registration(client_t _client,registration_type_e _type)1823 void routing_manager_stub::update_registration(client_t _client,
1824         registration_type_e _type) {
1825 
1826     VSOMEIP_INFO << "Application/Client "
1827         << std::hex << std::setw(4) << std::setfill('0') << _client
1828         << " is "
1829         << (_type == registration_type_e::REGISTER ?
1830                 "registering." : "deregistering.");
1831 
1832     if (_type != registration_type_e::REGISTER) {
1833         security::get()->remove_client_to_uid_gid_mapping(_client);
1834     }
1835 
1836     if (_type == registration_type_e::DEREGISTER) {
1837         // If we receive a DEREGISTER client command
1838         // the endpoint error handler is not longer needed
1839         // as the client is going down anyways.
1840 
1841         // Normally the handler is removed in "remove_local"
1842         // anyways, but as some time takes place until
1843         // the client DEREGISTER command is consumed
1844         // and therefore "remove_local" is finally called
1845         // it was possible the same client registers itself
1846         // again in very short time and then could "overtake"
1847         // the occurring error in the endpoint and was then
1848         // erroneously unregistered even that error has
1849         // nothing to do with the newly registered client.
1850 
1851         auto its_endpoint = host_->find_local(_client);
1852         if (its_endpoint) {
1853             its_endpoint->register_error_handler(nullptr);
1854         }
1855     }
1856 
1857     std::lock_guard<std::mutex> its_lock(client_registration_mutex_);
1858     pending_client_registrations_[_client].push_back(_type);
1859     client_registration_condition_.notify_one();
1860 
1861     if (_type != registration_type_e::REGISTER) {
1862         std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
1863         used_client_ids_.erase(_client);
1864     }
1865 }
1866 
get_client() const1867 client_t routing_manager_stub::get_client() const {
1868     return host_->get_client();
1869 }
1870 
handle_credentials(const client_t _client,std::set<service_data_t> & _requests)1871 void routing_manager_stub::handle_credentials(const client_t _client, std::set<service_data_t>& _requests) {
1872     if (!_requests.size()) {
1873         return;
1874     }
1875 
1876     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
1877     std::set<std::pair<uint32_t, uint32_t>> its_credentials;
1878     std::pair<uint32_t, uint32_t> its_requester_uid_gid;
1879     if (security::get()->get_client_to_uid_gid_mapping(_client, its_requester_uid_gid)) {
1880         // determine credentials of offering clients using current routing info
1881         std::set<client_t> its_offering_clients;
1882 
1883         // search in local clients for the offering client
1884         for (auto request : _requests) {
1885             std::set<client_t> its_clients;
1886             its_clients = host_->find_local_clients(request.service_, request.instance_);
1887             for (auto its_client : its_clients) {
1888                 its_offering_clients.insert(its_client);
1889             }
1890         }
1891 
1892         // search for UID / GID linked with the client ID that offers the requested services
1893         for (auto its_offering_client : its_offering_clients) {
1894             std::pair<uint32_t, uint32_t> its_uid_gid;
1895             if (security::get()->get_client_to_uid_gid_mapping(its_offering_client, its_uid_gid)) {
1896                 if (its_uid_gid != its_requester_uid_gid) {
1897                     its_credentials.insert(std::make_pair(std::get<0>(its_uid_gid), std::get<1>(its_uid_gid)));
1898                 }
1899             }
1900         }
1901 
1902         // send credentials to clients
1903         if (!its_credentials.empty()) {
1904             create_client_credentials_info(_client);
1905             insert_client_credentials_info(_client, its_credentials);
1906             send_client_credentials_info(_client);
1907         }
1908     }
1909 }
1910 
handle_requests(const client_t _client,std::set<service_data_t> & _requests)1911 void routing_manager_stub::handle_requests(const client_t _client, std::set<service_data_t>& _requests) {
1912     if (!_requests.size()) {
1913         return;
1914     }
1915     bool service_available(false);
1916     std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
1917     create_client_routing_info(_client);
1918     for (auto request : _requests) {
1919         service_requests_[_client][request.service_][request.instance_]
1920                                                      = std::make_pair(request.major_, request.minor_);
1921         if (request.instance_ == ANY_INSTANCE) {
1922             std::set<client_t> its_clients = host_->find_local_clients(request.service_, request.instance_);
1923             // insert VSOMEIP_ROUTING_CLIENT to check wether service is remotely offered
1924             its_clients.insert(VSOMEIP_ROUTING_CLIENT);
1925             for (const client_t c : its_clients) {
1926                 if (c != VSOMEIP_ROUTING_CLIENT &&
1927                         c != host_->get_client()) {
1928                     if (!is_already_connected(c, _client)) {
1929                         if (_client == c) {
1930                             service_available = true;
1931                             insert_client_routing_info(c,
1932                                 routing_info_entry_e::RIE_ADD_CLIENT, _client);
1933                         } else {
1934                             create_client_routing_info(c);
1935                             insert_client_routing_info(c,
1936                                     routing_info_entry_e::RIE_ADD_CLIENT, _client);
1937                             send_client_routing_info(c);
1938                         }
1939                     }
1940                 }
1941                 if (_client != VSOMEIP_ROUTING_CLIENT &&
1942                         _client != host_->get_client()) {
1943                     const auto found_client = routing_info_.find(c);
1944                     if (found_client != routing_info_.end()) {
1945                         const auto found_service = found_client->second.second.find(request.service_);
1946                         if (found_service != found_client->second.second.end()) {
1947                             for (auto instance : found_service->second) {
1948                                 service_available = true;
1949                                 insert_client_routing_info(_client,
1950                                         routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
1951                                         c, request.service_, instance.first,
1952                                         instance.second.first, instance.second.second);
1953                             }
1954                         }
1955                     }
1956                 }
1957             }
1958         } else {
1959             const client_t c = host_->find_local_client(request.service_, request.instance_);
1960             const auto found_client = routing_info_.find(c);
1961             if (found_client != routing_info_.end()) {
1962                 const auto found_service = found_client->second.second.find(request.service_);
1963                 if (found_service != found_client->second.second.end()) {
1964                     const auto found_instance = found_service->second.find(request.instance_);
1965                     if (found_instance != found_service->second.end()) {
1966                         if (c != VSOMEIP_ROUTING_CLIENT &&
1967                                 c != host_->get_client()) {
1968                             if (!is_already_connected(c, _client)) {
1969                                 if (_client == c) {
1970                                     service_available = true;
1971                                     insert_client_routing_info(c,
1972                                             routing_info_entry_e::RIE_ADD_CLIENT, _client);
1973                                 } else {
1974                                     create_client_routing_info(c);
1975                                     insert_client_routing_info(c,
1976                                         routing_info_entry_e::RIE_ADD_CLIENT, _client);
1977                                     send_client_routing_info(c);
1978                                 }
1979                             }
1980                         }
1981                         if (_client != VSOMEIP_ROUTING_CLIENT &&
1982                                 _client != host_->get_client()) {
1983                             service_available = true;
1984                             insert_client_routing_info(_client,
1985                                     routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
1986                                     c, request.service_, request.instance_,
1987                                     found_instance->second.first,
1988                                     found_instance->second.second);
1989                         }
1990                     }
1991                 }
1992             }
1993         }
1994     }
1995     if (service_available) {
1996         send_client_routing_info(_client);
1997     }
1998 }
1999 
on_client_id_timer_expired(boost::system::error_code const & _error)2000 void routing_manager_stub::on_client_id_timer_expired(boost::system::error_code const &_error) {
2001     std::set<client_t> used_client_ids;
2002     {
2003         std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
2004         used_client_ids = used_client_ids_;
2005         used_client_ids_.clear();
2006     }
2007 
2008     std::set<client_t> erroneous_clients;
2009     if (!_error) {
2010         std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
2011         for (auto client : used_client_ids) {
2012             if (client != VSOMEIP_ROUTING_CLIENT && client != get_client()) {
2013                 if (routing_info_.find(client) == routing_info_.end()) {
2014                     erroneous_clients.insert(client);
2015                 }
2016             }
2017         }
2018     }
2019     for (auto client : erroneous_clients) {
2020         VSOMEIP_WARNING << "Releasing client identifier "
2021                 << std::hex << std::setw(4) << std::setfill('0') << client << ". "
2022                 << "Its corresponding application went offline while no "
2023                 << "routing manager was running.";
2024         host_->handle_client_error(client);
2025     }
2026 }
2027 
print_endpoint_status() const2028 void routing_manager_stub::print_endpoint_status() const {
2029     if (local_receiver_) {
2030         local_receiver_->print_status();
2031     }
2032     if (endpoint_) {
2033         endpoint_->print_status();
2034     }
2035 }
2036 
send_provided_event_resend_request(client_t _client,pending_remote_offer_id_t _id)2037 bool routing_manager_stub::send_provided_event_resend_request(client_t _client,
2038                                                               pending_remote_offer_id_t _id) {
2039     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
2040     if (its_endpoint) {
2041         byte_t its_command[VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE];
2042         its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RESEND_PROVIDED_EVENTS;
2043         const client_t routing_client(VSOMEIP_ROUTING_CLIENT);
2044         std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &routing_client,
2045                 sizeof(routing_client));
2046         std::uint32_t its_size = sizeof(pending_remote_offer_id_t);
2047         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
2048                 sizeof(its_size));
2049         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_id,
2050                         sizeof(pending_remote_offer_id_t));
2051         return its_endpoint->send(its_command, sizeof(its_command));
2052     } else {
2053         VSOMEIP_WARNING << __func__ << " Couldn't send provided event resend "
2054                 "request to local client: 0x"
2055                 << std::hex << std::setw(4) << std::setfill('0') << _client;
2056         return false;
2057     }
2058 }
2059 
is_policy_cached(uint32_t _uid)2060 bool routing_manager_stub::is_policy_cached(uint32_t _uid) {
2061     {
2062         std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
2063         if (updated_security_policies_.find(_uid)
2064                 != updated_security_policies_.end()) {
2065             VSOMEIP_INFO << __func__ << " Policy for UID: " << std::dec
2066                     << _uid << " was already updated before!";
2067             return true;
2068         } else {
2069             return false;
2070         }
2071     }
2072 }
2073 
policy_cache_add(uint32_t _uid,const std::shared_ptr<payload> & _payload)2074 void routing_manager_stub::policy_cache_add(uint32_t _uid, const std::shared_ptr<payload>& _payload) {
2075     // cache security policy payload for later distribution to new registering clients
2076     {
2077         std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
2078         updated_security_policies_[_uid] = _payload;
2079     }
2080 }
2081 
policy_cache_remove(uint32_t _uid)2082 void routing_manager_stub::policy_cache_remove(uint32_t _uid) {
2083     {
2084         std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
2085         updated_security_policies_.erase(_uid);
2086     }
2087 }
2088 
send_update_security_policy_request(client_t _client,pending_security_update_id_t _update_id,uint32_t _uid,const std::shared_ptr<payload> & _payload)2089 bool routing_manager_stub::send_update_security_policy_request(client_t _client, pending_security_update_id_t _update_id,
2090                                                                uint32_t _uid, const std::shared_ptr<payload>& _payload) {
2091     (void)_uid;
2092     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
2093     if (its_endpoint) {
2094         std::vector<byte_t> its_command;
2095         // command
2096         its_command.push_back(VSOMEIP_UPDATE_SECURITY_POLICY);
2097 
2098         // client ID
2099         for (uint32_t i = 0; i < sizeof(client_t); ++i) {
2100              its_command.push_back(
2101                      reinterpret_cast<const byte_t*>(&_client)[i]);
2102         }
2103         // security update id length + payload length including gid and uid
2104         std::uint32_t its_size = uint32_t(sizeof(pending_security_update_id_t) + _payload->get_length());
2105         for (uint32_t i = 0; i < sizeof(its_size); ++i) {
2106              its_command.push_back(
2107                      reinterpret_cast<const byte_t*>(&its_size)[i]);
2108         }
2109         // ID of update request
2110         for (uint32_t i = 0; i < sizeof(pending_security_update_id_t); ++i) {
2111              its_command.push_back(
2112                      reinterpret_cast<const byte_t*>(&_update_id)[i]);
2113         }
2114         // payload
2115         for (uint32_t i = 0; i < _payload->get_length(); ++i) {
2116              its_command.push_back(_payload->get_data()[i]);
2117         }
2118 
2119         return its_endpoint->send(its_command.data(), uint32_t(its_command.size()));
2120     } else {
2121         return false;
2122     }
2123 }
2124 
send_cached_security_policies(client_t _client)2125 bool routing_manager_stub::send_cached_security_policies(client_t _client) {
2126     std::vector<byte_t> its_command;
2127     std::size_t its_size(0);
2128 
2129     std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
2130     uint32_t its_policy_count = uint32_t(updated_security_policies_.size());
2131 
2132     if (!its_policy_count) {
2133         return true;
2134     }
2135 
2136     VSOMEIP_INFO << __func__ << " Distributing ["
2137             << std::dec << its_policy_count
2138             << "] security policy updates to registering client: "
2139             << std::hex << _client;
2140 
2141     // command
2142     its_command.push_back(VSOMEIP_DISTRIBUTE_SECURITY_POLICIES);
2143 
2144     // client ID
2145     client_t its_client = get_client();
2146     for (uint32_t i = 0; i < sizeof(client_t); ++i) {
2147          its_command.push_back(
2148                  reinterpret_cast<const byte_t*>(&its_client)[i]);
2149     }
2150 
2151     //overall size (placeholder
2152     for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
2153          its_command.push_back(0x00);
2154     }
2155 
2156     // number of policies contained in message
2157     for (uint32_t i = 0; i < sizeof(its_policy_count); ++i) {
2158          its_command.push_back(
2159                  reinterpret_cast<const byte_t*>(&its_policy_count)[i]);
2160     }
2161 
2162     for (const auto& its_uid_gid : updated_security_policies_) {
2163         // policy payload length including gid and uid
2164         std::uint32_t its_length = uint32_t(its_uid_gid.second->get_length());
2165         for (uint32_t i = 0; i < sizeof(its_length); ++i) {
2166              its_command.push_back(
2167                      reinterpret_cast<const byte_t*>(&its_length)[i]);
2168         }
2169         // payload
2170         its_command.insert(its_command.end(), its_uid_gid.second->get_data(),
2171                 its_uid_gid.second->get_data() + its_uid_gid.second->get_length());
2172     }
2173     // File overall size
2174     its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
2175     std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
2176 
2177     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
2178     if (its_endpoint) {
2179         return its_endpoint->send(its_command.data(), uint32_t(its_command.size()));
2180     } else {
2181         VSOMEIP_WARNING << __func__ << " Couldn't send cached security policies "
2182                 " to registering client: 0x"
2183                 << std::hex << std::setw(4) << std::setfill('0') << _client;
2184         return false;
2185     }
2186 }
2187 
send_remove_security_policy_request(client_t _client,pending_security_update_id_t _update_id,uint32_t _uid,uint32_t _gid)2188 bool routing_manager_stub::send_remove_security_policy_request( client_t _client, pending_security_update_id_t _update_id,
2189                                                                 uint32_t _uid, uint32_t _gid) {
2190     std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
2191     if (its_endpoint) {
2192         byte_t its_command[VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE];
2193         its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REMOVE_SECURITY_POLICY;
2194         std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
2195                 sizeof(client_t));
2196         std::uint32_t its_size = sizeof(_update_id) + sizeof(_uid) + sizeof(_gid);
2197         std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
2198                 sizeof(its_size));
2199         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
2200                         sizeof(uint32_t));
2201         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_uid,
2202                         sizeof(uint32_t));
2203         std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_gid,
2204                         sizeof(uint32_t));
2205         return its_endpoint->send(its_command, sizeof(its_command));
2206     } else {
2207         return false;
2208     }
2209 }
2210 
2211 bool
add_requester_policies(uid_t _uid,gid_t _gid,const std::set<std::shared_ptr<policy>> & _policies)2212 routing_manager_stub::add_requester_policies(uid_t _uid, gid_t _gid,
2213         const std::set<std::shared_ptr<policy> > &_policies) {
2214 
2215     std::lock_guard<std::mutex> its_lock(requester_policies_mutex_);
2216     auto found_uid = requester_policies_.find(_uid);
2217     if (found_uid != requester_policies_.end()) {
2218         auto found_gid = found_uid->second.find(_gid);
2219         if (found_gid != found_uid->second.end()) {
2220             found_gid->second.insert(_policies.begin(), _policies.end());
2221         } else {
2222             found_uid->second.insert(std::make_pair(_gid, _policies));
2223         }
2224     } else {
2225         requester_policies_[_uid][_gid] = _policies;
2226     }
2227 
2228     // Check whether clients with uid/gid are already registered.
2229     // If yes, update their policy
2230     std::unordered_set<client_t> its_clients;
2231     security::get()->get_clients(_uid, _gid, its_clients);
2232 
2233     if (!its_clients.empty())
2234         return send_requester_policies(its_clients, _policies);
2235 
2236     return (true);
2237 }
2238 
2239 void
remove_requester_policies(uid_t _uid,gid_t _gid)2240 routing_manager_stub::remove_requester_policies(uid_t _uid, gid_t _gid) {
2241 
2242     std::lock_guard<std::mutex> its_lock(requester_policies_mutex_);
2243     auto found_uid = requester_policies_.find(_uid);
2244     if (found_uid != requester_policies_.end()) {
2245         found_uid->second.erase(_gid);
2246         if (found_uid->second.empty())
2247             requester_policies_.erase(_uid);
2248     }
2249 }
2250 
2251 void
get_requester_policies(uid_t _uid,gid_t _gid,std::set<std::shared_ptr<policy>> & _policies) const2252 routing_manager_stub::get_requester_policies(uid_t _uid, gid_t _gid,
2253         std::set<std::shared_ptr<policy> > &_policies) const {
2254 
2255     std::lock_guard<std::mutex> its_lock(requester_policies_mutex_);
2256     auto found_uid = requester_policies_.find(_uid);
2257     if (found_uid != requester_policies_.end()) {
2258         auto found_gid = found_uid->second.find(_gid);
2259         if (found_gid != found_uid->second.end())
2260             _policies = found_gid->second;
2261     }
2262 }
2263 
2264 void
add_pending_security_update_handler(pending_security_update_id_t _id,security_update_handler_t _handler)2265 routing_manager_stub::add_pending_security_update_handler(
2266         pending_security_update_id_t _id, security_update_handler_t _handler) {
2267 
2268     std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
2269     security_update_handlers_[_id] = _handler;
2270 }
2271 
2272 void
add_pending_security_update_timer(pending_security_update_id_t _id)2273 routing_manager_stub::add_pending_security_update_timer(
2274         pending_security_update_id_t _id) {
2275 
2276     std::shared_ptr<boost::asio::steady_timer> its_timer
2277         = std::make_shared<boost::asio::steady_timer>(io_);
2278 
2279     boost::system::error_code ec;
2280     its_timer->expires_from_now(std::chrono::milliseconds(3000), ec);
2281     if (!ec) {
2282         its_timer->async_wait(
2283                 std::bind(
2284                         &routing_manager_stub::on_security_update_timeout,
2285                         shared_from_this(),
2286                         std::placeholders::_1, _id, its_timer));
2287     } else {
2288         VSOMEIP_ERROR << __func__
2289                 << "[" << std::dec << _id << "]: timer creation: "
2290                 << ec.message();
2291     }
2292     std::lock_guard<std::mutex> its_lock(security_update_timers_mutex_);
2293     security_update_timers_[_id] = its_timer;
2294 }
2295 
2296 bool
send_requester_policies(const std::unordered_set<client_t> & _clients,const std::set<std::shared_ptr<policy>> & _policies)2297 routing_manager_stub::send_requester_policies(const std::unordered_set<client_t> &_clients,
2298         const std::set<std::shared_ptr<policy> > &_policies) {
2299 
2300     pending_security_update_id_t its_policy_id;
2301 
2302     // serialize the policies and send them...
2303     for (const auto &p : _policies) {
2304         std::vector<byte_t> its_policy_data;
2305         if (p->serialize(its_policy_data)) {
2306             std::vector<byte_t> its_message;
2307             its_message.push_back(VSOMEIP_UPDATE_SECURITY_POLICY_INT);
2308             its_message.push_back(0);
2309             its_message.push_back(0);
2310 
2311             uint32_t its_policy_size = static_cast<uint32_t>(its_policy_data.size() + sizeof(uint32_t));
2312             its_message.push_back(VSOMEIP_LONG_BYTE0(its_policy_size));
2313             its_message.push_back(VSOMEIP_LONG_BYTE1(its_policy_size));
2314             its_message.push_back(VSOMEIP_LONG_BYTE2(its_policy_size));
2315             its_message.push_back(VSOMEIP_LONG_BYTE3(its_policy_size));
2316 
2317             its_policy_id = pending_security_update_add(_clients);
2318             its_message.push_back(VSOMEIP_LONG_BYTE0(its_policy_id));
2319             its_message.push_back(VSOMEIP_LONG_BYTE1(its_policy_id));
2320             its_message.push_back(VSOMEIP_LONG_BYTE2(its_policy_id));
2321             its_message.push_back(VSOMEIP_LONG_BYTE3(its_policy_id));
2322 
2323             its_message.insert(its_message.end(), its_policy_data.begin(), its_policy_data.end());
2324 
2325             for (const auto& c : _clients) {
2326                 std::shared_ptr<endpoint> its_endpoint = host_->find_local(c);
2327                 if (its_endpoint)
2328                     its_endpoint->send(&its_message[0], static_cast<uint32_t>(its_message.size()));
2329             }
2330         }
2331     }
2332 
2333     return (true);
2334 }
2335 
on_security_update_timeout(const boost::system::error_code & _error,pending_security_update_id_t _id,std::shared_ptr<boost::asio::steady_timer> _timer)2336 void routing_manager_stub::on_security_update_timeout(
2337         const boost::system::error_code& _error,
2338         pending_security_update_id_t _id,
2339         std::shared_ptr<boost::asio::steady_timer> _timer) {
2340     (void)_timer;
2341     if (_error) {
2342         // timer was cancelled
2343         return;
2344     }
2345     security_update_state_e its_state = security_update_state_e::SU_UNKNOWN_USER_ID;
2346     std::unordered_set<client_t> its_missing_clients = pending_security_update_get(_id);
2347     {
2348         // erase timer
2349         std::lock_guard<std::mutex> its_lock(security_update_timers_mutex_);
2350         security_update_timers_.erase(_id);
2351     }
2352     {
2353         //  print missing responses and check if some clients did not respond because they already disconnected
2354         if (!its_missing_clients.empty()) {
2355             for (auto its_client : its_missing_clients) {
2356                 VSOMEIP_INFO << __func__ << ": Client 0x" << std::hex << its_client
2357                         << " did not respond to the policy update / removal with ID: 0x" << std::hex << _id;
2358                 if (!host_->find_local(its_client)) {
2359                     VSOMEIP_INFO << __func__ << ": Client 0x" << std::hex << its_client
2360                             << " is not connected anymore, do not expect answer for policy update / removal with ID: 0x"
2361                             << std::hex << _id;
2362                     pending_security_update_remove(_id, its_client);
2363                 }
2364             }
2365         }
2366 
2367         its_missing_clients = pending_security_update_get(_id);
2368         if (its_missing_clients.empty()) {
2369             VSOMEIP_INFO << __func__ << ": Received all responses for "
2370                     "security update/removal ID: 0x" << std::hex << _id;
2371             its_state = security_update_state_e::SU_SUCCESS;
2372         }
2373         {
2374             // erase pending security update
2375             std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
2376             pending_security_updates_.erase(_id);
2377         }
2378 
2379         // call handler with error on timeout or with SUCCESS if missing clients are not connected
2380         std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
2381         const auto found_handler = security_update_handlers_.find(_id);
2382         if (found_handler != security_update_handlers_.end()) {
2383             found_handler->second(its_state);
2384             security_update_handlers_.erase(found_handler);
2385         } else {
2386             VSOMEIP_WARNING << __func__ << ": Callback not found for security update / removal with ID: 0x"
2387                     << std::hex << _id;
2388         }
2389     }
2390 }
2391 
update_security_policy_configuration(uint32_t _uid,uint32_t _gid,const std::shared_ptr<policy> & _policy,const std::shared_ptr<payload> & _payload,const security_update_handler_t & _handler)2392 bool routing_manager_stub::update_security_policy_configuration(
2393         uint32_t _uid, uint32_t _gid,
2394         const std::shared_ptr<policy> &_policy,
2395         const std::shared_ptr<payload> &_payload,
2396         const security_update_handler_t &_handler) {
2397 
2398     bool ret(true);
2399 
2400     // cache security policy payload for later distribution to new registering clients
2401     policy_cache_add(_uid, _payload);
2402 
2403     // update security policy from configuration
2404     security::get()->update_security_policy(_uid, _gid, _policy);
2405 
2406     // Build requester policies for the services offered by the new policy
2407     std::set<std::shared_ptr<policy> > its_requesters;
2408     security::get()->get_requester_policies(_policy, its_requesters);
2409 
2410     // and add them to the requester policy cache
2411     add_requester_policies(_uid, _gid, its_requesters);
2412 
2413     // determine currently connected clients
2414     std::unordered_set<client_t> its_clients_to_inform;
2415     auto its_epm = host_->get_endpoint_manager();
2416     if (its_epm)
2417         its_clients_to_inform = its_epm->get_connected_clients();
2418 
2419     // add handler
2420     pending_security_update_id_t its_id;
2421     if (!its_clients_to_inform.empty()) {
2422         its_id = pending_security_update_add(its_clients_to_inform);
2423 
2424         add_pending_security_update_handler(its_id, _handler);
2425         add_pending_security_update_timer(its_id);
2426 
2427         // trigger all currently connected clients to update the security policy
2428         uint32_t sent_counter(0);
2429         uint32_t its_tranche =
2430                 uint32_t(its_clients_to_inform.size() >= 10 ? (its_clients_to_inform.size() / 10) : 1);
2431         VSOMEIP_INFO << __func__ << ": Informing [" << std::dec << its_clients_to_inform.size()
2432                 << "] currently connected clients about policy update for UID: "
2433                 << std::dec << _uid << " with update ID: 0x" << std::hex << its_id;
2434         for (auto its_client : its_clients_to_inform) {
2435             if (!send_update_security_policy_request(its_client, its_id, _uid, _payload)) {
2436                 VSOMEIP_INFO << __func__ << ": Couldn't send update security policy "
2437                                         << "request to client 0x" << std::hex << std::setw(4)
2438                                         << std::setfill('0') << its_client << " policy UID: "
2439                                         << std::hex << std::setw(4) << std::setfill('0') << _uid << " GID: "
2440                                         << std::hex << std::setw(4) << std::setfill('0') << _gid
2441                                         << " with update ID: 0x" << std::hex << its_id
2442                                         << " as client already disconnected";
2443                 // remove client from expected answer list
2444                 pending_security_update_remove(its_id, its_client);
2445             }
2446             sent_counter++;
2447             // Prevent burst
2448             if (sent_counter % its_tranche == 0) {
2449                 std::this_thread::sleep_for(std::chrono::milliseconds(10));
2450             }
2451         }
2452     } else {
2453         // if routing manager has no client call the handler directly
2454         _handler(security_update_state_e::SU_SUCCESS);
2455     }
2456 
2457     return ret;
2458 }
2459 
remove_security_policy_configuration(uint32_t _uid,uint32_t _gid,const security_update_handler_t & _handler)2460 bool routing_manager_stub::remove_security_policy_configuration(
2461         uint32_t _uid, uint32_t _gid, const security_update_handler_t &_handler) {
2462 
2463     bool ret(true);
2464 
2465     // remove security policy from configuration (only if there was a updateACL call before)
2466     if (is_policy_cached(_uid)) {
2467         if (!security::get()->remove_security_policy(_uid, _gid)) {
2468             _handler(security_update_state_e::SU_UNKNOWN_USER_ID);
2469             ret = false;
2470         } else {
2471             // remove policy from cache to prevent sending it to registering clients
2472             policy_cache_remove(_uid);
2473 
2474             // add handler
2475             pending_security_update_id_t its_id;
2476 
2477             // determine currently connected clients
2478             std::unordered_set<client_t> its_clients_to_inform;
2479             auto its_epm = host_->get_endpoint_manager();
2480             if (its_epm)
2481                 its_clients_to_inform = its_epm->get_connected_clients();
2482 
2483             if (!its_clients_to_inform.empty()) {
2484                 its_id = pending_security_update_add(its_clients_to_inform);
2485 
2486                 add_pending_security_update_handler(its_id, _handler);
2487                 add_pending_security_update_timer(its_id);
2488 
2489                 // trigger all clients to remove the security policy
2490                 uint32_t sent_counter(0);
2491                 uint32_t its_tranche =
2492                         uint32_t(its_clients_to_inform.size() >= 10 ? (its_clients_to_inform.size() / 10) : 1);
2493                 VSOMEIP_INFO << __func__ << ": Informing [" << std::dec << its_clients_to_inform.size()
2494                         << "] currently connected clients about policy removal for UID: "
2495                         << std::dec << _uid << " with update ID: " << its_id;
2496                 for (auto its_client : its_clients_to_inform) {
2497                     if (!send_remove_security_policy_request(its_client, its_id, _uid, _gid)) {
2498                         VSOMEIP_INFO << __func__ << ": Couldn't send remove security policy "
2499                                                 << "request to client 0x" << std::hex << std::setw(4)
2500                                                 << std::setfill('0') << its_client << " policy UID: "
2501                                                 << std::hex << std::setw(4) << std::setfill('0') << _uid << " GID: "
2502                                                 << std::hex << std::setw(4) << std::setfill('0') << _gid
2503                                                 << " with update ID: 0x" << std::hex << its_id
2504                                                 << " as client already disconnected";
2505                         // remove client from expected answer list
2506                         pending_security_update_remove(its_id, its_client);
2507                     }
2508                     sent_counter++;
2509                     // Prevent burst
2510                     if (sent_counter % its_tranche == 0) {
2511                         std::this_thread::sleep_for(std::chrono::milliseconds(10));
2512                     }
2513                 }
2514             } else {
2515                 // if routing manager has no client call the handler directly
2516                 _handler(security_update_state_e::SU_SUCCESS);
2517             }
2518         }
2519     }
2520     else {
2521         _handler(security_update_state_e::SU_UNKNOWN_USER_ID);
2522         ret = false;
2523     }
2524     return ret;
2525 }
2526 
pending_security_update_add(const std::unordered_set<client_t> & _clients)2527 pending_security_update_id_t routing_manager_stub::pending_security_update_add(
2528         const std::unordered_set<client_t>& _clients) {
2529     std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
2530     if (++pending_security_update_id_ == 0) {
2531         pending_security_update_id_++;
2532     }
2533     pending_security_updates_[pending_security_update_id_] = _clients;
2534 
2535     return pending_security_update_id_;
2536 }
2537 
pending_security_update_get(pending_security_update_id_t _id)2538 std::unordered_set<client_t> routing_manager_stub::pending_security_update_get(
2539         pending_security_update_id_t _id) {
2540     std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
2541     std::unordered_set<client_t> its_missing_clients;
2542     auto found_si = pending_security_updates_.find(_id);
2543     if (found_si != pending_security_updates_.end()) {
2544         its_missing_clients = pending_security_updates_[_id];
2545     }
2546     return its_missing_clients;
2547 }
2548 
pending_security_update_remove(pending_security_update_id_t _id,client_t _client)2549 bool routing_manager_stub::pending_security_update_remove(
2550         pending_security_update_id_t _id, client_t _client) {
2551     std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
2552     auto found_si = pending_security_updates_.find(_id);
2553     if (found_si != pending_security_updates_.end()) {
2554         if (found_si->second.erase(_client)) {
2555             return true;
2556         }
2557     }
2558     return false;
2559 }
2560 
is_pending_security_update_finished(pending_security_update_id_t _id)2561 bool routing_manager_stub::is_pending_security_update_finished(
2562         pending_security_update_id_t _id) {
2563     std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
2564     bool ret(false);
2565     auto found_si = pending_security_updates_.find(_id);
2566     if (found_si != pending_security_updates_.end()) {
2567         if (!found_si->second.size()) {
2568             ret = true;
2569         }
2570     }
2571     if (ret) {
2572         pending_security_updates_.erase(_id);
2573     }
2574     return ret;
2575 }
2576 
on_security_update_response(pending_security_update_id_t _id,client_t _client)2577 void routing_manager_stub::on_security_update_response(
2578         pending_security_update_id_t _id, client_t _client) {
2579     if (pending_security_update_remove(_id, _client)) {
2580         if (is_pending_security_update_finished(_id)) {
2581             // cancel timeout timer
2582             {
2583                 std::lock_guard<std::mutex> its_lock(security_update_timers_mutex_);
2584                 auto found_timer = security_update_timers_.find(_id);
2585                 if (found_timer != security_update_timers_.end()) {
2586                     boost::system::error_code ec;
2587                     found_timer->second->cancel(ec);
2588                     security_update_timers_.erase(found_timer);
2589                 } else {
2590                     VSOMEIP_WARNING << __func__ << ": Received all responses "
2591                             "for security update/removal ID: 0x"
2592                             << std::hex << _id << " but timeout already happened";
2593                 }
2594             }
2595 
2596             // call handler
2597             {
2598                 std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
2599                 auto found_handler = security_update_handlers_.find(_id);
2600                 if (found_handler != security_update_handlers_.end()) {
2601                     found_handler->second(security_update_state_e::SU_SUCCESS);
2602                     security_update_handlers_.erase(found_handler);
2603                     VSOMEIP_INFO << __func__ << ": Received all responses for "
2604                             "security update/removal ID: 0x" << std::hex << _id;
2605                 } else {
2606                     VSOMEIP_WARNING << __func__ << ": Received all responses "
2607                             "for security update/removal ID: 0x"
2608                             << std::hex << _id << " but didn't find handler";
2609                 }
2610             }
2611         }
2612     }
2613 }
2614 
send_suspend() const2615 void routing_manager_stub::send_suspend() const {
2616 
2617     static const std::vector<byte_t> its_suspend(
2618         { VSOMEIP_SUSPEND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
2619 
2620     broadcast(its_suspend);
2621 }
2622 
2623 } // namespace vsomeip_v3
2624