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 <cctype>
7 #include <fstream>
8 #include <functional>
9 #include <set>
10 #include <sstream>
11 #include <limits>
12 #include <utility>
13
14 #define WIN32_LEAN_AND_MEAN
15
16 #include <boost/algorithm/string.hpp>
17 #include <boost/filesystem.hpp>
18 #include <boost/foreach.hpp>
19 #include <boost/property_tree/json_parser.hpp>
20
21 #include <vsomeip/constants.hpp>
22 #include <vsomeip/plugins/application_plugin.hpp>
23 #include <vsomeip/plugins/pre_configuration_plugin.hpp>
24 #include <vsomeip/internal/logger.hpp>
25
26 #include "../include/client.hpp"
27 #include "../include/configuration_impl.hpp"
28 #include "../include/event.hpp"
29 #include "../include/eventgroup.hpp"
30 #include "../include/service.hpp"
31 #include "../../logger/include/logger_impl.hpp"
32 #include "../../routing/include/event.hpp"
33 #include "../../service_discovery/include/defines.hpp"
34 #include "../../utility/include/utility.hpp"
35 #include "../../plugin/include/plugin_manager.hpp"
36 #include "../../security/include/security.hpp"
37
38 namespace vsomeip_v3 {
39 namespace cfg {
40
configuration_impl()41 configuration_impl::configuration_impl()
42 : default_unicast_("local"),
43 is_loaded_(false),
44 is_logging_loaded_(false),
45 is_overlay_(false),
46 diagnosis_(VSOMEIP_DIAGNOSIS_ADDRESS),
47 diagnosis_mask_(0xFF00),
48 has_console_log_(true),
49 has_file_log_(false),
50 has_dlt_log_(false),
51 logfile_("/tmp/vsomeip.log"),
52 loglevel_(vsomeip_v3::logger::level_e::LL_INFO),
53 is_sd_enabled_(VSOMEIP_SD_DEFAULT_ENABLED),
54 sd_protocol_(VSOMEIP_SD_DEFAULT_PROTOCOL),
55 sd_multicast_(VSOMEIP_SD_DEFAULT_MULTICAST),
56 sd_port_(VSOMEIP_SD_DEFAULT_PORT),
57 sd_initial_delay_min_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN),
58 sd_initial_delay_max_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX),
59 sd_repetitions_base_delay_(VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY),
60 sd_repetitions_max_(VSOMEIP_SD_DEFAULT_REPETITIONS_MAX),
61 sd_ttl_(VSOMEIP_SD_DEFAULT_TTL),
62 sd_cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY),
63 sd_request_response_delay_(VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY),
64 sd_offer_debounce_time_(VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME),
65 max_configured_message_size_(0),
66 max_local_message_size_(0),
67 max_reliable_message_size_(0),
68 max_unreliable_message_size_(0),
69 buffer_shrink_threshold_(VSOMEIP_DEFAULT_BUFFER_SHRINK_THRESHOLD),
70 trace_(std::make_shared<trace>()),
71 watchdog_(std::make_shared<watchdog>()),
72 log_version_(true),
73 log_version_interval_(10),
74 permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
75 permissions_uds_(VSOMEIP_DEFAULT_UDS_PERMISSIONS),
76 network_("vsomeip"),
77 e2e_enabled_(false),
78 log_memory_(false),
79 log_memory_interval_(0),
80 log_status_(false),
81 log_status_interval_(0),
82 endpoint_queue_limit_external_(QUEUE_SIZE_UNLIMITED),
83 endpoint_queue_limit_local_(QUEUE_SIZE_UNLIMITED),
84 tcp_restart_aborts_max_(VSOMEIP_MAX_TCP_RESTART_ABORTS),
85 tcp_connect_time_max_(VSOMEIP_MAX_TCP_CONNECT_TIME),
86 has_issued_methods_warning_(false),
87 has_issued_clients_warning_(false),
88 udp_receive_buffer_size_(VSOMEIP_DEFAULT_UDP_RCV_BUFFER_SIZE),
89 npdu_default_debounce_requ_(VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO),
90 npdu_default_debounce_resp_(VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO),
91 npdu_default_max_retention_requ_(VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO),
92 npdu_default_max_retention_resp_(VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO),
93 shutdown_timeout_(VSOMEIP_DEFAULT_SHUTDOWN_TIMEOUT),
94 log_statistics_(true),
95 statistics_interval_(VSOMEIP_DEFAULT_STATISTICS_INTERVAL),
96 statistics_min_freq_(VSOMEIP_DEFAULT_STATISTICS_MIN_FREQ),
97 statistics_max_messages_(VSOMEIP_DEFAULT_STATISTICS_MAX_MSG),
98 max_remote_subscribers_(VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS) {
99 unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS);
100 netmask_ = netmask_.from_string(VSOMEIP_NETMASK);
101 for (auto i = 0; i < ET_MAX; i++)
102 is_configured_[i] = false;
103 }
104
configuration_impl(const configuration_impl & _other)105 configuration_impl::configuration_impl(const configuration_impl &_other)
106 : std::enable_shared_from_this<configuration_impl>(_other),
107 default_unicast_(_other.default_unicast_),
108 is_loaded_(_other.is_loaded_),
109 is_logging_loaded_(_other.is_logging_loaded_),
110 is_overlay_(_other.is_overlay_),
111 mandatory_(_other.mandatory_),
112 max_configured_message_size_(_other.max_configured_message_size_),
113 max_local_message_size_(_other.max_local_message_size_),
114 max_reliable_message_size_(_other.max_reliable_message_size_),
115 max_unreliable_message_size_(_other.max_unreliable_message_size_),
116 buffer_shrink_threshold_(_other.buffer_shrink_threshold_),
117 permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
118 permissions_uds_(VSOMEIP_DEFAULT_UDS_PERMISSIONS),
119 endpoint_queue_limit_external_(_other.endpoint_queue_limit_external_),
120 endpoint_queue_limit_local_(_other.endpoint_queue_limit_local_),
121 tcp_restart_aborts_max_(_other.tcp_restart_aborts_max_),
122 tcp_connect_time_max_(_other.tcp_connect_time_max_),
123 udp_receive_buffer_size_(_other.udp_receive_buffer_size_),
124 npdu_default_debounce_requ_(_other.npdu_default_debounce_requ_),
125 npdu_default_debounce_resp_(_other.npdu_default_debounce_resp_),
126 npdu_default_max_retention_requ_(_other.npdu_default_max_retention_requ_),
127 npdu_default_max_retention_resp_(_other.npdu_default_max_retention_resp_),
128 shutdown_timeout_(_other.shutdown_timeout_) {
129
130 applications_.insert(_other.applications_.begin(), _other.applications_.end());
131 client_identifiers_ = _other.client_identifiers_;
132 services_.insert(_other.services_.begin(), _other.services_.end());
133 clients_ = _other.clients_;
134
135 unicast_ = _other.unicast_;
136 netmask_ = _other.netmask_;
137 device_ = _other.device_;
138 diagnosis_ = _other.diagnosis_;
139 diagnosis_mask_ = _other.diagnosis_mask_;
140
141 has_console_log_ = _other.has_console_log_;
142 has_file_log_ = _other.has_file_log_;
143 has_dlt_log_ = _other.has_dlt_log_;
144 logfile_ = _other.logfile_;
145
146 loglevel_ = _other.loglevel_;
147
148 routing_host_ = _other.routing_host_;
149
150 is_sd_enabled_ = _other.is_sd_enabled_;
151 sd_multicast_ = _other.sd_multicast_;
152 sd_port_ = _other.sd_port_;
153 sd_protocol_ = _other.sd_protocol_;
154
155 sd_initial_delay_min_ = _other.sd_initial_delay_min_;
156 sd_initial_delay_max_ = _other.sd_initial_delay_max_;
157 sd_repetitions_base_delay_= _other.sd_repetitions_base_delay_;
158 sd_repetitions_max_ = _other.sd_repetitions_max_;
159 sd_ttl_ = _other.sd_ttl_;
160 sd_cyclic_offer_delay_= _other.sd_cyclic_offer_delay_;
161 sd_request_response_delay_= _other.sd_request_response_delay_;
162 sd_offer_debounce_time_ = _other.sd_offer_debounce_time_;
163
164 trace_ = std::make_shared<trace>(*_other.trace_.get());
165 supported_selective_addresses = _other.supported_selective_addresses;
166 watchdog_ = std::make_shared<watchdog>(*_other.watchdog_.get());
167 internal_service_ranges_ = _other.internal_service_ranges_;
168 log_version_ = _other.log_version_;
169 log_version_interval_ = _other.log_version_interval_;
170
171 magic_cookies_.insert(_other.magic_cookies_.begin(), _other.magic_cookies_.end());
172 message_sizes_ = _other.message_sizes_;
173
174 for (auto i = 0; i < ET_MAX; i++)
175 is_configured_[i] = _other.is_configured_[i];
176
177 network_ = _other.network_;
178 configuration_path_ = _other.configuration_path_;
179
180 e2e_enabled_ = _other.e2e_enabled_;
181 e2e_configuration_ = _other.e2e_configuration_;
182
183 log_memory_ = _other.log_memory_;
184 log_memory_interval_ = _other.log_memory_interval_;
185 log_status_ = _other.log_status_;
186 log_status_interval_ = _other.log_status_interval_;
187
188 ttl_factors_offers_ = _other.ttl_factors_offers_;
189 ttl_factors_subscriptions_ = _other.ttl_factors_subscriptions_;
190
191 debounces_ = _other.debounces_;
192 endpoint_queue_limits_ = _other.endpoint_queue_limits_;
193
194 sd_acceptance_rules_ = _other.sd_acceptance_rules_;
195
196 has_issued_methods_warning_ = _other.has_issued_methods_warning_;
197 has_issued_clients_warning_ = _other.has_issued_clients_warning_;
198
199 log_statistics_ = _other.log_statistics_;
200 statistics_interval_ = _other.statistics_interval_;
201 statistics_min_freq_ = _other.statistics_min_freq_;
202 statistics_max_messages_ = _other.statistics_max_messages_;
203 max_remote_subscribers_ = _other.max_remote_subscribers_;
204 }
205
~configuration_impl()206 configuration_impl::~configuration_impl() {
207 }
208
load(const std::string & _name)209 bool configuration_impl::load(const std::string &_name) {
210 std::lock_guard<std::mutex> its_lock(mutex_);
211 if (is_loaded_)
212 return true;
213
214 // Predefine file / folder
215 std::string its_file(VSOMEIP_DEFAULT_CONFIGURATION_FILE); // configuration file
216 std::string its_folder(VSOMEIP_DEFAULT_CONFIGURATION_FOLDER); // configuration folder
217
218 // Override with local file / folder (if existing)
219 std::string its_local_file(VSOMEIP_LOCAL_CONFIGURATION_FILE);
220 if (utility::is_file(its_local_file)) {
221 its_file = its_local_file;
222 }
223
224 std::string its_local_folder(VSOMEIP_LOCAL_CONFIGURATION_FOLDER);
225 if (utility::is_folder(its_local_folder)) {
226 its_folder = its_local_folder;
227 }
228
229 // Override with path from environment (if existing)
230 const char *its_env = getenv(VSOMEIP_ENV_CONFIGURATION);
231 if (nullptr != its_env) {
232 if (utility::is_file(its_env)) {
233 its_file = its_env;
234 its_folder = "";
235 } else if (utility::is_folder(its_env)) {
236 its_folder = its_env;
237 its_file = "";
238 }
239 }
240
241 std::set<std::string> its_input;
242 if (its_file != "") {
243 its_input.insert(its_file);
244 }
245 if (its_folder != "") {
246 its_input.insert(its_folder);
247 #ifndef _WIN32
248 // load security configuration files from UID_GID sub folder if existing
249 std::stringstream its_security_config_folder;
250 its_security_config_folder << its_folder << "/" << getuid() << "_" << getgid();
251 if (utility::is_folder(its_security_config_folder.str())) {
252 its_input.insert(its_security_config_folder.str());
253 }
254 #endif
255 }
256
257 // Determine standard configuration file
258 its_env = getenv(VSOMEIP_ENV_MANDATORY_CONFIGURATION_FILES);
259 if (nullptr != its_env) {
260 std::string its_temp(its_env);
261 set_mandatory(its_temp);
262 } else {
263 set_mandatory(VSOMEIP_MANDATORY_CONFIGURATION_FILES);
264 }
265
266 // Start reading
267 std::set<std::string> its_failed;
268
269 std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
270 std::vector<configuration_element> its_mandatory_elements;
271 std::vector<configuration_element> its_optional_elements;
272
273 // Dummy initialization; maybe we'll find no logging configuration
274 logger::logger_impl::init(shared_from_this());
275
276 // Look for the standard configuration file
277 read_data(its_input, its_mandatory_elements, its_failed, true);
278 load_data(its_mandatory_elements, true, false);
279
280 // If the configuration is incomplete, this is the routing manager configuration or
281 // the routing is yet unknown, read the full set of configuration files
282 if (its_mandatory_elements.empty() ||
283 _name == get_routing_host() ||
284 "" == get_routing_host()) {
285 read_data(its_input, its_optional_elements, its_failed, false);
286 load_data(its_mandatory_elements, false, true);
287 load_data(its_optional_elements, true, true);
288 }
289
290 // Tell, if reading of configuration file(s) failed.
291 // (This may file if the logger configuration is incomplete/missing).
292 for (auto f : its_failed)
293 VSOMEIP_WARNING << "Reading of configuration file \""
294 << f << "\" failed. Configuration may be incomplete.";
295
296 // set global unicast address for all services with magic cookies enabled
297 set_magic_cookies_unicast_address();
298
299 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
300 VSOMEIP_INFO << "Parsed vsomeip configuration in "
301 << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count()
302 << "ms";
303
304 for (auto i : its_input) {
305 if (utility::is_file(i))
306 VSOMEIP_INFO << "Using configuration file: \"" << i << "\".";
307
308 if (utility::is_folder(i))
309 VSOMEIP_INFO << "Using configuration folder: \"" << i << "\".";
310 }
311
312 is_loaded_ = true;
313
314 return is_loaded_;
315 }
316
317 bool
check_routing_credentials(client_t _client,uint32_t _uid,uint32_t _gid) const318 configuration_impl::check_routing_credentials(
319 client_t _client, uint32_t _uid, uint32_t _gid) const {
320 return (_client != get_id(routing_host_)) ||
321 security::get()->check_routing_credentials(_client, _uid, _gid);
322 }
323
remote_offer_info_add(service_t _service,instance_t _instance,std::uint16_t _port,bool _reliable,bool _magic_cookies_enabled)324 bool configuration_impl::remote_offer_info_add(service_t _service,
325 instance_t _instance,
326 std::uint16_t _port,
327 bool _reliable,
328 bool _magic_cookies_enabled) {
329 bool ret = false;
330 if (!is_loaded_) {
331 VSOMEIP_ERROR << __func__ << " shall only be called after normal"
332 "configuration has been parsed";
333 } else {
334 std::shared_ptr<service> its_service(std::make_shared<service>());
335 its_service->service_ = _service;
336 its_service->instance_ = _instance;
337 its_service->reliable_ = its_service->unreliable_ = ILLEGAL_PORT;
338 _reliable ?
339 its_service->reliable_ = _port :
340 its_service->unreliable_ = _port;
341 its_service->unicast_address_ = default_unicast_;
342 its_service->multicast_address_ = "";
343 its_service->multicast_port_ = ILLEGAL_PORT;
344 its_service->protocol_ = "someip";
345
346 {
347 std::lock_guard<std::mutex> its_lock(services_mutex_);
348 bool updated(false);
349 auto found_service = services_.find(its_service->service_);
350 if (found_service != services_.end()) {
351 auto found_instance = found_service->second.find(its_service->instance_);
352 if (found_instance != found_service->second.end()) {
353 VSOMEIP_INFO << "Updating remote configuration for service ["
354 << std::hex << std::setw(4) << std::setfill('0')
355 << its_service->service_ << "." << its_service->instance_ << "]";
356 if (_reliable) {
357 found_instance->second->reliable_ = its_service->reliable_;
358 } else {
359 found_instance->second->unreliable_ = its_service->unreliable_;
360 }
361 updated = true;
362 }
363 }
364 if (!updated) {
365 services_[_service][_instance] = its_service;
366 VSOMEIP_INFO << "Added new remote configuration for service ["
367 << std::hex << std::setw(4) << std::setfill('0')
368 << its_service->service_ << "."
369 << std::hex << std::setw(4) << std::setfill('0')
370 << its_service->instance_ << "]";
371 }
372 if (_magic_cookies_enabled) {
373 magic_cookies_[its_service->unicast_address_].insert(its_service->reliable_);
374 }
375 }
376 ret = true;
377 }
378 return ret;
379 }
380
remote_offer_info_remove(service_t _service,instance_t _instance,std::uint16_t _port,bool _reliable,bool _magic_cookies_enabled,bool * _still_offered_remote)381 bool configuration_impl::remote_offer_info_remove(service_t _service,
382 instance_t _instance,
383 std::uint16_t _port,
384 bool _reliable,
385 bool _magic_cookies_enabled,
386 bool* _still_offered_remote) {
387 (void)_port;
388 (void)_magic_cookies_enabled;
389 bool ret = false;
390 if (!is_loaded_) {
391 VSOMEIP_ERROR << __func__ << " shall only be called after normal"
392 "configuration has been parsed";
393 } else {
394 std::lock_guard<std::mutex> its_lock(services_mutex_);
395 auto found_service = services_.find(_service);
396 if (found_service != services_.end()) {
397 auto found_instance = found_service->second.find(_instance);
398 if (found_instance != found_service->second.end()) {
399 VSOMEIP_INFO << "Removing remote configuration for service ["
400 << std::hex << std::setw(4) << std::setfill('0')
401 << _service << "." << _instance << "]";
402 if (_reliable) {
403 found_instance->second->reliable_ = ILLEGAL_PORT;
404 // TODO delete from magic_cookies_map without overwriting
405 // configurations from other services offered on the same port
406 } else {
407 found_instance->second->unreliable_ = ILLEGAL_PORT;
408 }
409 *_still_offered_remote = (
410 found_instance->second->unreliable_ != ILLEGAL_PORT ||
411 found_instance->second->reliable_ != ILLEGAL_PORT);
412 ret = true;
413 }
414 }
415 }
416 return ret;
417 }
418
read_data(const std::set<std::string> & _input,std::vector<configuration_element> & _elements,std::set<std::string> & _failed,bool _mandatory_only)419 void configuration_impl::read_data(const std::set<std::string> &_input,
420 std::vector<configuration_element> &_elements, std::set<std::string> &_failed,
421 bool _mandatory_only) {
422 for (auto i : _input) {
423 if (utility::is_file(i)) {
424 if (is_mandatory(i) == _mandatory_only) {
425 boost::property_tree::ptree its_tree;
426 try {
427 boost::property_tree::json_parser::read_json(i, its_tree);
428 _elements.push_back({ i, its_tree });
429 }
430 catch (boost::property_tree::json_parser_error &e) {
431 #ifdef _WIN32
432 e; // silence MSVC warning C4101
433 #endif
434 _failed.insert(i);
435 }
436 }
437 } else if (utility::is_folder(i)) {
438 boost::filesystem::path its_path(i);
439 for (auto j = boost::filesystem::directory_iterator(its_path);
440 j != boost::filesystem::directory_iterator();
441 j++) {
442 auto its_file_path = j->path();
443 if (!boost::filesystem::is_directory(its_file_path)) {
444 const std::string& its_name = its_file_path.string();
445 if (is_mandatory(its_name) == _mandatory_only) {
446 boost::property_tree::ptree its_tree;
447 try {
448 boost::property_tree::json_parser::read_json(its_name, its_tree);
449 _elements.push_back({its_name, its_tree});
450 }
451 catch (...) {
452 _failed.insert(its_name);
453 }
454 }
455 }
456 }
457 }
458 }
459 }
460
461
load_data(const std::vector<configuration_element> & _elements,bool _load_mandatory,bool _load_optional)462 bool configuration_impl::load_data(const std::vector<configuration_element> &_elements,
463 bool _load_mandatory, bool _load_optional) {
464 // Load logging configuration data
465 std::set<std::string> its_warnings;
466
467 if (!is_logging_loaded_) {
468 for (const auto& e : _elements)
469 is_logging_loaded_
470 = load_logging(e, its_warnings) || is_logging_loaded_;
471
472 if (is_logging_loaded_) {
473 logger::logger_impl::init(shared_from_this());
474 for (auto w : its_warnings)
475 VSOMEIP_WARNING << w;
476 }
477 }
478
479 bool has_routing(false);
480 bool has_applications(false);
481 if (_load_mandatory) {
482 // Load mandatory configuration data
483 for (const auto& e : _elements) {
484 has_routing = load_routing(e) || has_routing;
485 has_applications = load_applications(e) || has_applications;
486 load_network(e);
487 load_diagnosis_address(e);
488 load_shutdown_timeout(e);
489 load_payload_sizes(e);
490 load_endpoint_queue_sizes(e);
491 load_tcp_restart_settings(e);
492 load_permissions(e);
493 load_security(e);
494 load_tracing(e);
495 load_udp_receive_buffer_size(e);
496 }
497 }
498
499 if (_load_optional) {
500 for (const auto& e : _elements) {
501 load_unicast_address(e);
502 load_netmask(e);
503 load_device(e);
504 load_service_discovery(e);
505 load_npdu_default_timings(e);
506 load_services(e);
507 load_internal_services(e);
508 load_clients(e);
509 load_watchdog(e);
510 load_selective_broadcasts_support(e);
511 load_e2e(e);
512 load_debounce(e);
513 load_acceptances(e);
514 load_secure_services(e);
515 load_partitions(e);
516 }
517 }
518
519 return is_logging_loaded_ && has_routing && has_applications;
520 }
521
load_logging(const configuration_element & _element,std::set<std::string> & _warnings)522 bool configuration_impl::load_logging(
523 const configuration_element &_element, std::set<std::string> &_warnings) {
524 try {
525 auto its_logging = _element.tree_.get_child("logging");
526 for (auto i = its_logging.begin(); i != its_logging.end(); ++i) {
527 std::string its_key(i->first);
528 if (its_key == "console") {
529 if (is_configured_[ET_LOGGING_CONSOLE]) {
530 _warnings.insert("Multiple definitions for logging.console."
531 " Ignoring definition from " + _element.name_);
532 } else {
533 std::string its_value(i->second.data());
534 has_console_log_ = (its_value == "true");
535 is_configured_[ET_LOGGING_CONSOLE] = true;
536 }
537 } else if (its_key == "file") {
538 if (is_configured_[ET_LOGGING_FILE]) {
539 _warnings.insert("Multiple definitions for logging.file."
540 " Ignoring definition from " + _element.name_);
541 } else {
542 for (auto j : i->second) {
543 std::string its_sub_key(j.first);
544 std::string its_sub_value(j.second.data());
545 if (its_sub_key == "enable") {
546 has_file_log_ = (its_sub_value == "true");
547 } else if (its_sub_key == "path") {
548 logfile_ = its_sub_value;
549 }
550 }
551 is_configured_[ET_LOGGING_FILE] = true;
552 }
553 } else if (its_key == "dlt") {
554 if (is_configured_[ET_LOGGING_DLT]) {
555 _warnings.insert("Multiple definitions for logging.dlt."
556 " Ignoring definition from " + _element.name_);
557 } else {
558 std::string its_value(i->second.data());
559 has_dlt_log_ = (its_value == "true");
560 is_configured_[ET_LOGGING_DLT] = true;
561 }
562 } else if (its_key == "level") {
563 if (is_configured_[ET_LOGGING_LEVEL]) {
564 _warnings.insert("Multiple definitions for logging.level."
565 " Ignoring definition from " + _element.name_);
566 } else {
567 std::string its_value(i->second.data());
568 loglevel_
569 = (its_value == "trace" ?
570 vsomeip_v3::logger::level_e::LL_VERBOSE :
571 (its_value == "debug" ?
572 vsomeip_v3::logger::level_e::LL_DEBUG :
573 (its_value == "info" ?
574 vsomeip_v3::logger::level_e::LL_INFO :
575 (its_value == "warning" ?
576 vsomeip_v3::logger::level_e::LL_WARNING :
577 (its_value == "error" ?
578 vsomeip_v3::logger::level_e::LL_ERROR :
579 (its_value == "fatal" ?
580 vsomeip_v3::logger::level_e::LL_FATAL :
581 vsomeip_v3::logger::level_e::LL_INFO))))));
582 is_configured_[ET_LOGGING_LEVEL] = true;
583 }
584 } else if (its_key == "version") {
585 std::stringstream its_converter;
586 for (auto j : i->second) {
587 std::string its_sub_key(j.first);
588 std::string its_sub_value(j.second.data());
589 if (its_sub_key == "enable") {
590 log_version_ = (its_sub_value == "true");
591 } else if (its_sub_key == "interval") {
592 its_converter << std::dec << its_sub_value;
593 its_converter >> log_version_interval_;
594 }
595 }
596 } else if (its_key == "memory_log_interval") {
597 std::stringstream its_converter;
598 its_converter << std::dec << i->second.data();
599 its_converter >> log_memory_interval_;
600 if (log_memory_interval_ > 0) {
601 log_memory_ = true;
602 }
603 } else if (its_key == "status_log_interval") {
604 std::stringstream its_converter;
605 its_converter << std::dec << i->second.data();
606 its_converter >> log_status_interval_;
607 if (log_status_interval_ > 0) {
608 log_status_ = true;
609 }
610 } else if (its_key == "statistics") {
611 for (auto j : i->second) {
612 std::stringstream its_converter;
613 std::string its_sub_key(j.first);
614 std::string its_sub_value(j.second.data());
615 if (its_sub_key == "interval") {
616 its_converter << std::dec << its_sub_value;
617 its_converter >> statistics_interval_;
618 if (statistics_interval_ > 0) {
619 log_statistics_ = true;
620 }
621 } else if (its_sub_key == "min-frequency") {
622 its_converter << std::dec << its_sub_value;
623 its_converter >> statistics_min_freq_;
624 } else if (its_sub_key == "max-messages") {
625 its_converter << std::dec << its_sub_value;
626 its_converter >> statistics_max_messages_;
627 }
628 }
629 }
630 }
631 } catch (...) {
632 return false;
633 }
634 return true;
635 }
636
637 bool
load_routing(const configuration_element & _element)638 configuration_impl::load_routing(const configuration_element &_element) {
639 try {
640 auto its_routing = _element.tree_.get_child("routing");
641 if (is_configured_[ET_ROUTING]) {
642 VSOMEIP_WARNING << "Multiple definitions of routing."
643 << " Ignoring definition from " << _element.name_;
644 } else {
645 routing_host_ = its_routing.data();
646 is_configured_[ET_ROUTING] = true;
647 }
648 } catch (...) {
649 return false;
650 }
651 return true;
652 }
653
654 bool
load_applications(const configuration_element & _element)655 configuration_impl::load_applications(const configuration_element &_element) {
656 try {
657 auto its_applications = _element.tree_.get_child("applications");
658 for (auto i = its_applications.begin();
659 i != its_applications.end();
660 ++i) {
661 load_application_data(i->second, _element.name_);
662 }
663 } catch (...) {
664 return false;
665 }
666 return true;
667 }
668
load_application_data(const boost::property_tree::ptree & _tree,const std::string & _file_name)669 void configuration_impl::load_application_data(
670 const boost::property_tree::ptree &_tree, const std::string &_file_name) {
671 std::string its_name("");
672 client_t its_id(VSOMEIP_CLIENT_UNSET);
673 std::size_t its_max_dispatchers(VSOMEIP_MAX_DISPATCHERS);
674 std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME);
675 std::size_t its_io_thread_count(VSOMEIP_IO_THREAD_COUNT);
676 std::size_t its_request_debounce_time(VSOMEIP_REQUEST_DEBOUNCE_TIME);
677 std::map<plugin_type_e, std::set<std::string>> plugins;
678 int its_io_thread_nice_level(VSOMEIP_IO_THREAD_NICE_LEVEL);
679 std::string its_overlay;
680 #ifdef VSOMEIP_HAS_SESSION_HANDLING_CONFIG
681 bool has_session_handling(true);
682 #endif // VSOMEIP_HAS_SESSION_HANDLING_CONFIG
683 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
684 std::string its_key(i->first);
685 std::string its_value(i->second.data());
686 std::stringstream its_converter;
687 if (its_key == "name") {
688 its_name = its_value;
689 } else if (its_key == "id") {
690 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
691 its_converter << std::hex << its_value;
692 } else {
693 its_converter << std::dec << its_value;
694 }
695 its_converter >> its_id;
696 } else if (its_key == "max_dispatchers") {
697 its_converter << std::dec << its_value;
698 its_converter >> its_max_dispatchers;
699 } else if (its_key == "max_dispatch_time") {
700 its_converter << std::dec << its_value;
701 its_converter >> its_max_dispatch_time;
702 } else if (its_key == "threads") {
703 its_converter << std::dec << its_value;
704 its_converter >> its_io_thread_count;
705 if (its_io_thread_count == 0) {
706 VSOMEIP_WARNING << "Min. number of threads per application is 1";
707 its_io_thread_count = 1;
708 } else if (its_io_thread_count > 255) {
709 VSOMEIP_WARNING << "Max. number of threads per application is 255";
710 its_io_thread_count = 255;
711 }
712 } else if (its_key == "io_thread_nice") {
713 its_converter << std::dec << its_value;
714 its_converter >> its_io_thread_nice_level;
715 } else if (its_key == "request_debounce_time") {
716 its_converter << std::dec << its_value;
717 its_converter >> its_request_debounce_time;
718 if (its_request_debounce_time > 10000) {
719 VSOMEIP_WARNING << "Max. request debounce time is 10.000ms";
720 its_request_debounce_time = 10000;
721 }
722 } else if (its_key == "plugins") {
723 plugins = load_plugins(i->second, its_name);
724 } else if (its_key == "overlay") {
725 its_overlay = its_value;
726 }
727 #ifdef VSOMEIP_HAS_SESSION_HANDLING_CONFIG
728 else if (its_key == "has_session_handling") {
729 has_session_handling = (its_value != "false");
730 }
731 #endif // VSOMEIP_HAS_SESSION_HANDLING_CONFIG
732 }
733 if (its_name != "") {
734 if (applications_.find(its_name) == applications_.end()) {
735 if (its_id != VSOMEIP_CLIENT_UNSET) {
736 if (!is_configured_client_id(its_id)) {
737 client_identifiers_.insert(its_id);
738 } else {
739 VSOMEIP_ERROR << "Multiple applications are configured to use"
740 << " client identifier " << std::hex << its_id
741 << ". Ignoring the configuration for application "
742 << its_name;
743 its_id = VSOMEIP_CLIENT_UNSET;
744 }
745 }
746 applications_[its_name]
747 = std::make_tuple(its_id, its_max_dispatchers,
748 its_max_dispatch_time, its_io_thread_count,
749 its_request_debounce_time, plugins, its_io_thread_nice_level,
750 its_overlay
751 #ifdef VSOMEIP_HAS_SESSION_HANDLING_CONFIG
752 , has_session_handling
753 #endif // VSOMEIP_HAS_SESSION_HANDLING_CONFIG
754 );
755 } else {
756 VSOMEIP_WARNING << "Multiple configurations for application "
757 << its_name << ". Ignoring a configuration from "
758 << _file_name;
759 }
760 }
761 }
762
load_plugins(const boost::property_tree::ptree & _tree,const std::string & _application_name)763 std::map<plugin_type_e, std::set<std::string>> configuration_impl::load_plugins(
764 const boost::property_tree::ptree &_tree,
765 const std::string& _application_name) {
766 std::map<plugin_type_e, std::set<std::string>> its_plugins;
767 std::string its_name("");
768 std::string its_type;
769 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
770 bool its_configured[ET_MAX] = { 0 };
771 for (auto l = i->second.begin(); l != i->second.end(); ++l) {
772 std::string its_inner_key(l->first);
773 std::string its_inner_value(l->second.data());
774
775 if (its_inner_key == "name") {
776 if (its_configured[ET_PLUGIN_NAME]) {
777 VSOMEIP_WARNING << "Multiple definitions of plugins.name."
778 << " Ignoring definition from " << its_inner_value;
779 } else {
780 its_name = its_inner_value;
781 its_configured[ET_PLUGIN_NAME] = true;
782 }
783 } else if (its_inner_key == "type") {
784 if (its_configured[ET_PLUGIN_TYPE]) {
785 VSOMEIP_WARNING << "Multiple definitions of plugins.type."
786 << " Ignoring definition from " << its_inner_value;
787 } else {
788 its_type = its_inner_value;
789 its_configured[ET_PLUGIN_TYPE] = true;
790 }
791 } else {
792 //support old config format (type : name)
793 plugin_config_data_t its_plugin_data = {
794 its_inner_value, its_inner_key };
795 add_plugin(its_plugins, its_plugin_data, _application_name);
796 }
797 }
798
799 if (its_configured[ET_PLUGIN_NAME] && its_configured[ET_PLUGIN_TYPE]) {
800 plugin_config_data_t its_plugin_data = {
801 its_name, its_type };
802 add_plugin(its_plugins, its_plugin_data, _application_name);
803 }
804 }
805
806 return its_plugins;
807 }
808
add_plugin(std::map<plugin_type_e,std::set<std::string>> & _plugins,const plugin_config_data_t & _plugin_data,const std::string & _application_name)809 void configuration_impl::add_plugin(std::map<plugin_type_e, std::set<std::string>> &_plugins,
810 const plugin_config_data_t &_plugin_data,
811 const std::string& _application_name) {
812
813 #ifdef _WIN32
814 std::string its_library(_plugin_data.name_);
815 its_library += ".dll";
816 #else
817 std::string its_library("lib");
818 its_library += _plugin_data.name_;
819 its_library += ".so";
820 #endif
821
822 if (_plugin_data.type_ == "application_plugin") {
823 #ifndef _WIN32
824 its_library += ".";
825 its_library += (VSOMEIP_APPLICATION_PLUGIN_VERSION + '0');
826 #endif
827 _plugins[plugin_type_e::APPLICATION_PLUGIN].insert(its_library);
828 } else if (_plugin_data.type_ == "configuration_plugin") {
829 #ifndef _WIN32
830 its_library += ".";
831 its_library += (VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION + '0');
832 #endif
833 _plugins[plugin_type_e::PRE_CONFIGURATION_PLUGIN].insert(its_library);
834 } else {
835 VSOMEIP_WARNING << "Unknown plug-in type ("
836 << _plugin_data.type_ << ") configured for client: "
837 << _application_name;
838 }
839 }
840
load_tracing(const configuration_element & _element)841 void configuration_impl::load_tracing(const configuration_element &_element) {
842 try {
843 auto its_trace_configuration = _element.tree_.get_child("tracing");
844 for(auto i = its_trace_configuration.begin();
845 i != its_trace_configuration.end();
846 ++i) {
847 std::string its_key(i->first);
848 std::string its_value(i->second.data());
849 if(its_key == "enable") {
850 if (is_configured_[ET_TRACING_ENABLE]) {
851 VSOMEIP_WARNING << "Multiple definitions of tracing.enable."
852 << " Ignoring definition from " << _element.name_;
853 } else {
854 trace_->is_enabled_ = (its_value == "true");
855 is_configured_[ET_TRACING_ENABLE] = true;
856 }
857 } else if (its_key == "sd_enable") {
858 if (is_configured_[ET_TRACING_SD_ENABLE]) {
859 VSOMEIP_WARNING << "Multiple definitions of tracing.sd_enable."
860 << " Ignoring definition from " << _element.name_;
861 } else {
862 trace_->is_sd_enabled_ = (its_value == "true");
863 is_configured_[ET_TRACING_SD_ENABLE] = true;
864 }
865 } else if(its_key == "channels") {
866 load_trace_channels(i->second);
867 } else if(its_key == "filters") {
868 load_trace_filters(i->second);
869 }
870 }
871 } catch (...) {
872 // intentionally left empty
873 }
874 }
875
load_trace_channels(const boost::property_tree::ptree & _tree)876 void configuration_impl::load_trace_channels(
877 const boost::property_tree::ptree &_tree) {
878 try {
879 for(auto i = _tree.begin(); i != _tree.end(); ++i) {
880 if(i == _tree.begin())
881 trace_->channels_.clear();
882 load_trace_channel(i->second);
883 }
884 } catch (...) {
885 // intentionally left empty
886 }
887 }
888
load_trace_channel(const boost::property_tree::ptree & _tree)889 void configuration_impl::load_trace_channel(
890 const boost::property_tree::ptree &_tree) {
891 std::shared_ptr<trace_channel> its_channel = std::make_shared<trace_channel>();
892 for(auto i = _tree.begin(); i != _tree.end(); ++i) {
893 std::string its_key = i->first;
894 std::string its_value = i->second.data();
895 if(its_key == "name") {
896 its_channel->name_ = its_value;
897 } else if(its_key == "id") {
898 its_channel->id_ = its_value;
899 }
900 }
901 trace_->channels_.push_back(its_channel);
902 }
903
load_trace_filters(const boost::property_tree::ptree & _tree)904 void configuration_impl::load_trace_filters(
905 const boost::property_tree::ptree &_tree) {
906 try {
907 for(auto i = _tree.begin(); i != _tree.end(); ++i) {
908 load_trace_filter(i->second);
909 }
910 } catch (...) {
911 // intentionally left empty
912 }
913 }
914
load_trace_filter(const boost::property_tree::ptree & _tree)915 void configuration_impl::load_trace_filter(
916 const boost::property_tree::ptree &_tree) {
917 std::shared_ptr<trace_filter> its_filter = std::make_shared<trace_filter>();
918 bool has_channel(false);
919 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
920 std::string its_key = i->first;
921 if (its_key == "channel") {
922 std::string its_value;
923 if (i->second.size() == 0) {
924 its_value = i->second.data();
925 its_filter->channels_.push_back(its_value);
926 } else {
927 for (auto j = i->second.begin(); j != i->second.end(); ++j) {
928 its_filter->channels_.push_back(j->second.data());
929 }
930 }
931 has_channel = true;
932 } else if(its_key == "type") {
933 std::string its_value = i->second.data();
934 its_filter->is_positive_ = (its_value == "positive");
935 } else {
936 load_trace_filter_expressions(i->second, its_key, its_filter);
937 }
938 }
939
940 if (!has_channel) {
941 its_filter->channels_.push_back("TC"); // default
942 }
943
944 if (!its_filter->is_range_ || its_filter->matches_.size() == 2) {
945 trace_->filters_.push_back(its_filter);
946 }
947 }
948
load_trace_filter_expressions(const boost::property_tree::ptree & _tree,std::string & _criteria,std::shared_ptr<trace_filter> & _filter)949 void configuration_impl::load_trace_filter_expressions(
950 const boost::property_tree::ptree &_tree,
951 std::string &_criteria,
952 std::shared_ptr<trace_filter> &_filter) {
953 if (_criteria == "services") {
954 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
955 vsomeip_v3::trace::match_t its_match;
956 load_trace_filter_match(i->second, its_match);
957 _filter->matches_.push_back(its_match);
958 }
959 } else if (_criteria == "methods") {
960 if (!has_issued_methods_warning_) {
961 VSOMEIP_WARNING << "\"method\" entry in filter configuration has no effect!";
962 has_issued_methods_warning_ = true;
963 }
964 } else if (_criteria == "clients") {
965 if (!has_issued_clients_warning_) {
966 VSOMEIP_WARNING << "\"clients\" entry in filter configuration has no effect!";
967 has_issued_clients_warning_ = true;
968 }
969 } else if (_criteria == "matches") {
970 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
971 vsomeip_v3::trace::match_t its_match;
972 load_trace_filter_match(i->second, its_match);
973 if (i->first == "from") {
974 _filter->is_range_ = true;
975 _filter->matches_.insert(_filter->matches_.begin(), its_match);
976 } else {
977 if (i->first == "to") _filter->is_range_ = true;
978 _filter->matches_.push_back(its_match);
979 }
980 }
981 }
982 }
983
load_trace_filter_match(const boost::property_tree::ptree & _data,vsomeip_v3::trace::match_t & _match)984 void configuration_impl::load_trace_filter_match(
985 const boost::property_tree::ptree &_data,
986 vsomeip_v3::trace::match_t &_match) {
987 std::stringstream its_converter;
988
989 if (_data.size() == 0) {
990 const std::string& its_value(_data.data());
991 service_t its_service(ANY_SERVICE);
992 if (its_value.find("0x") == 0) {
993 its_converter << std::hex << its_value;
994 } else {
995 its_converter << std::dec << its_value;
996 }
997 its_converter >> its_service;
998
999 std::get<0>(_match) = its_service;
1000 std::get<1>(_match) = ANY_INSTANCE;
1001 std::get<2>(_match) = ANY_METHOD;
1002 } else {
1003 std::get<0>(_match) = ANY_SERVICE;
1004 std::get<1>(_match) = ANY_INSTANCE;
1005 std::get<2>(_match) = ANY_METHOD;
1006
1007 for (auto i = _data.begin(); i != _data.end(); ++i) {
1008 std::string its_value;
1009
1010 its_converter.str("");
1011 its_converter.clear();
1012
1013 try {
1014 its_value = i->second.data();
1015 if (its_value == "any") its_value = "0xffff";
1016
1017 if (i->first == "service") {
1018 service_t its_service(ANY_SERVICE);
1019 if (its_value.find("0x") == 0) {
1020 its_converter << std::hex << its_value;
1021 } else {
1022 its_converter << std::dec << its_value;
1023 }
1024 its_converter >> its_service;
1025 std::get<0>(_match) = its_service;
1026 } else if (i->first == "instance") {
1027 instance_t its_instance(ANY_INSTANCE);
1028 if (its_value.find("0x") == 0) {
1029 its_converter << std::hex << its_value;
1030 } else {
1031 its_converter << std::dec << its_value;
1032 }
1033 its_converter >> its_instance;
1034 std::get<1>(_match) = its_instance;
1035 } else if (i->first == "method") {
1036 method_t its_method(ANY_METHOD);
1037 if (its_value.find("0x") == 0) {
1038 its_converter << std::hex << its_value;
1039 } else {
1040 its_converter << std::dec << its_value;
1041 }
1042 its_converter >> its_method;
1043 std::get<2>(_match) = its_method;
1044 }
1045 } catch (...) {
1046 // Intentionally left empty
1047 }
1048 }
1049 }
1050 }
1051
load_unicast_address(const configuration_element & _element)1052 void configuration_impl::load_unicast_address(const configuration_element &_element) {
1053 try {
1054 std::string its_value = _element.tree_.get<std::string>("unicast");
1055 if (!is_overlay_ && is_configured_[ET_UNICAST]) {
1056 VSOMEIP_WARNING << "Multiple definitions for unicast."
1057 "Ignoring definition from " << _element.name_;
1058 } else {
1059 unicast_ = unicast_.from_string(its_value);
1060 is_configured_[ET_UNICAST] = true;
1061 }
1062 } catch (...) {
1063 // intentionally left empty!
1064 }
1065 }
1066
load_netmask(const configuration_element & _element)1067 void configuration_impl::load_netmask(const configuration_element &_element) {
1068 try {
1069 std::string its_value = _element.tree_.get<std::string>("netmask");
1070 if (!is_overlay_ && is_configured_[ET_NETMASK]) {
1071 VSOMEIP_WARNING << "Multiple definitions for netmask."
1072 "Ignoring definition from " << _element.name_;
1073 } else {
1074 netmask_ = netmask_.from_string(its_value);
1075 is_configured_[ET_NETMASK] = true;
1076 }
1077 } catch (...) {
1078 // intentionally left empty!
1079 }
1080 }
1081
load_device(const configuration_element & _element)1082 void configuration_impl::load_device(const configuration_element &_element) {
1083 try {
1084 std::string its_value = _element.tree_.get<std::string>("device");
1085 if (!is_overlay_ && is_configured_[ET_DEVICE]) {
1086 VSOMEIP_WARNING << "Multiple definitions for device."
1087 "Ignoring definition from " << _element.name_;
1088 } else {
1089 device_ = its_value;
1090 is_configured_[ET_DEVICE] = true;
1091 }
1092 } catch (...) {
1093 // intentionally left empty!
1094 }
1095 }
1096
load_network(const configuration_element & _element)1097 void configuration_impl::load_network(const configuration_element &_element) {
1098 try {
1099 std::string its_value(_element.tree_.get<std::string>("network"));
1100 if (!is_overlay_ && is_configured_[ET_NETWORK]) {
1101 VSOMEIP_WARNING << "Multiple definitions for network."
1102 "Ignoring definition from " << _element.name_;
1103 } else {
1104 network_ = its_value;
1105 is_configured_[ET_NETWORK] = true;
1106 }
1107 } catch (...) {
1108 // intentionally left empty
1109 }
1110 }
1111
load_diagnosis_address(const configuration_element & _element)1112 void configuration_impl::load_diagnosis_address(const configuration_element &_element) {
1113 try {
1114 std::string its_value = _element.tree_.get<std::string>("diagnosis");
1115 if (!is_overlay_ && is_configured_[ET_DIAGNOSIS]) {
1116 VSOMEIP_WARNING << "Multiple definitions for diagnosis."
1117 "Ignoring definition from " << _element.name_;
1118 } else {
1119 std::stringstream its_converter;
1120
1121 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1122 its_converter << std::hex << its_value;
1123 } else {
1124 its_converter << std::dec << its_value;
1125 }
1126 its_converter >> diagnosis_;
1127 is_configured_[ET_DIAGNOSIS] = true;
1128 }
1129 std::string its_mask = _element.tree_.get<std::string>("diagnosis_mask");
1130 if (!is_overlay_ && is_configured_[ET_DIAGNOSIS_MASK]) {
1131 VSOMEIP_WARNING << "Multiple definitions for diagnosis_mask."
1132 "Ignoring definition from " << _element.name_;
1133 } else {
1134 std::stringstream its_converter;
1135
1136 if (its_mask.size() > 1 && its_mask[0] == '0' && its_mask[1] == 'x') {
1137 its_converter << std::hex << its_mask;
1138 } else {
1139 its_converter << std::dec << its_mask;
1140 }
1141 its_converter >> diagnosis_mask_;
1142 is_configured_[ET_DIAGNOSIS_MASK] = true;
1143 }
1144 if (is_configured_[ET_DIAGNOSIS] && is_configured_[ET_DIAGNOSIS_MASK]
1145 && (static_cast<std::uint16_t>(diagnosis_ << 8) & diagnosis_mask_)
1146 != static_cast<std::uint16_t>(diagnosis_ << 8)) {
1147 VSOMEIP_WARNING << "Diagnosis mask masks bits of diagnosis prefix! "
1148 "Client IDs will start at 0x" << std::hex <<
1149 (static_cast<std::uint16_t>(diagnosis_ << 8) & diagnosis_mask_)
1150 << " not at 0x" << static_cast<std::uint16_t>(diagnosis_ << 8);
1151 }
1152 } catch (...) {
1153 // intentionally left empty
1154 }
1155 }
1156
load_shutdown_timeout(const configuration_element & _element)1157 void configuration_impl::load_shutdown_timeout(const configuration_element &_element) {
1158 const std::string shutdown_timeout("shutdown_timeout");
1159 try {
1160 if (_element.tree_.get_child_optional(shutdown_timeout)) {
1161 std::string its_value = _element.tree_.get<std::string>("shutdown_timeout");
1162 if (is_configured_[ET_SHUTDOWN_TIMEOUT]) {
1163 VSOMEIP_WARNING << "Multiple definitions for shutdown_timeout."
1164 "Ignoring definition from " << _element.name_;
1165 } else {
1166 std::stringstream its_converter;
1167
1168 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1169 its_converter << std::hex << its_value;
1170 } else {
1171 its_converter << std::dec << its_value;
1172 }
1173 its_converter >> shutdown_timeout_;
1174 is_configured_[ET_SHUTDOWN_TIMEOUT] = true;
1175 }
1176 }
1177 } catch (...) {
1178 // intentionally left empty
1179 }
1180 }
1181
load_service_discovery(const configuration_element & _element)1182 void configuration_impl::load_service_discovery(
1183 const configuration_element &_element) {
1184 try {
1185 auto its_service_discovery = _element.tree_.get_child("service-discovery");
1186 for (auto i = its_service_discovery.begin();
1187 i != its_service_discovery.end(); ++i) {
1188 std::string its_key(i->first);
1189 std::string its_value(i->second.data());
1190 std::stringstream its_converter;
1191 if (its_key == "enable") {
1192 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_ENABLE]) {
1193 VSOMEIP_WARNING << "Multiple definitions for service_discovery.enabled."
1194 " Ignoring definition from " << _element.name_;
1195 } else {
1196 is_sd_enabled_ = (its_value == "true");
1197 is_configured_[ET_SERVICE_DISCOVERY_ENABLE] = true;
1198 }
1199 } else if (its_key == "multicast") {
1200 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_MULTICAST]) {
1201 VSOMEIP_WARNING << "Multiple definitions for service_discovery.multicast."
1202 " Ignoring definition from " << _element.name_;
1203 } else {
1204 sd_multicast_ = its_value;
1205 is_configured_[ET_SERVICE_DISCOVERY_MULTICAST] = true;
1206 }
1207 } else if (its_key == "port") {
1208 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_PORT]) {
1209 VSOMEIP_WARNING << "Multiple definitions for service_discovery.port."
1210 " Ignoring definition from " << _element.name_;
1211 } else {
1212 its_converter << its_value;
1213 its_converter >> sd_port_;
1214 if (!sd_port_) {
1215 sd_port_ = VSOMEIP_SD_DEFAULT_PORT;
1216 } else {
1217 is_configured_[ET_SERVICE_DISCOVERY_PORT] = true;
1218 }
1219 }
1220 } else if (its_key == "protocol") {
1221 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL]) {
1222 VSOMEIP_WARNING << "Multiple definitions for service_discovery.protocol."
1223 " Ignoring definition from " << _element.name_;
1224 } else {
1225 sd_protocol_ = its_value;
1226 is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL] = true;
1227 }
1228 } else if (its_key == "initial_delay_min") {
1229 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN]) {
1230 VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_min."
1231 " Ignoring definition from " << _element.name_;
1232 } else {
1233 its_converter << its_value;
1234 its_converter >> sd_initial_delay_min_;
1235 is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN] = true;
1236 }
1237 } else if (its_key == "initial_delay_max") {
1238 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX]) {
1239 VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_max."
1240 " Ignoring definition from " << _element.name_;
1241 } else {
1242 its_converter << its_value;
1243 its_converter >> sd_initial_delay_max_;
1244 is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX] = true;
1245 }
1246 } else if (its_key == "repetitions_base_delay") {
1247 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY]) {
1248 VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_base_delay."
1249 " Ignoring definition from " << _element.name_;
1250 } else {
1251 its_converter << its_value;
1252 its_converter >> sd_repetitions_base_delay_;
1253 is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY] = true;
1254 }
1255 } else if (its_key == "repetitions_max") {
1256 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX]) {
1257 VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_max."
1258 " Ignoring definition from " << _element.name_;
1259 } else {
1260 int tmp;
1261 its_converter << its_value;
1262 its_converter >> tmp;
1263 sd_repetitions_max_ = (tmp > (std::numeric_limits<std::uint8_t>::max)()) ?
1264 (std::numeric_limits<std::uint8_t>::max)() :
1265 static_cast<std::uint8_t>(tmp);
1266 is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX] = true;
1267 }
1268 } else if (its_key == "ttl") {
1269 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_TTL]) {
1270 VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl."
1271 " Ignoring definition from " << _element.name_;
1272 } else {
1273 its_converter << its_value;
1274 its_converter >> sd_ttl_;
1275 // We do _not_ accept 0 as this would mean "STOP OFFER"
1276 if (sd_ttl_ == 0) {
1277 VSOMEIP_WARNING << "TTL=0 is not allowed. Using default ("
1278 << std::dec << VSOMEIP_SD_DEFAULT_TTL << ")";
1279 sd_ttl_ = VSOMEIP_SD_DEFAULT_TTL;
1280 }
1281 else is_configured_[ET_SERVICE_DISCOVERY_TTL] = true;
1282 }
1283 } else if (its_key == "cyclic_offer_delay") {
1284 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY]) {
1285 VSOMEIP_WARNING << "Multiple definitions for service_discovery.cyclic_offer_delay."
1286 " Ignoring definition from " << _element.name_;
1287 } else {
1288 its_converter << its_value;
1289 its_converter >> sd_cyclic_offer_delay_;
1290 is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY] = true;
1291 }
1292 } else if (its_key == "request_response_delay") {
1293 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY]) {
1294 VSOMEIP_WARNING << "Multiple definitions for service_discovery.request_response_delay."
1295 " Ignoring definition from " << _element.name_;
1296 } else {
1297 its_converter << its_value;
1298 its_converter >> sd_request_response_delay_;
1299 is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY] = true;
1300 }
1301 } else if (its_key == "offer_debounce_time") {
1302 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME]) {
1303 VSOMEIP_WARNING << "Multiple definitions for service_discovery.offer_debounce."
1304 " Ignoring definition from " << _element.name_;
1305 } else {
1306 its_converter << its_value;
1307 its_converter >> sd_offer_debounce_time_;
1308 is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME] = true;
1309 }
1310 } else if (its_key == "ttl_factor_offers") {
1311 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_OFFERS]) {
1312 VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl_factor_offers."
1313 " Ignoring definition from " << _element.name_;
1314 } else {
1315 load_ttl_factors(i->second, &ttl_factors_offers_);
1316 is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_OFFERS] = true;
1317 }
1318 } else if (its_key == "ttl_factor_subscriptions") {
1319 if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_SUBSCRIPTIONS]) {
1320 VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl_factor_subscriptions."
1321 " Ignoring definition from " << _element.name_;
1322 } else {
1323 load_ttl_factors(i->second, &ttl_factors_subscriptions_);
1324 is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_SUBSCRIPTIONS] = true;
1325 }
1326 } else if (its_key == "max_remote_subscribers") {
1327 if (!is_overlay_ && is_configured_[ET_MAX_REMOTE_SUBSCRIBERS]) {
1328 VSOMEIP_WARNING << "Multiple definitions for service_discovery.max_remote_subscribers."
1329 " Ignoring definition from " << _element.name_;
1330 } else {
1331 int tmp;
1332 its_converter << its_value;
1333 its_converter >> tmp;
1334 max_remote_subscribers_ = (tmp > (std::numeric_limits<std::uint8_t>::max)()) ?
1335 (std::numeric_limits<std::uint8_t>::max)() :
1336 static_cast<std::uint8_t>(tmp);
1337 if (max_remote_subscribers_ == 0) {
1338 VSOMEIP_WARNING << "max_remote_subscribers_ = 0 is not allowed. Using default ("
1339 << std::dec << VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS << ")";
1340 max_remote_subscribers_ = VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS;
1341 }
1342 is_configured_[ET_MAX_REMOTE_SUBSCRIBERS] = true;
1343 }
1344 }
1345 }
1346 } catch (...) {
1347 }
1348 }
1349
load_delays(const boost::property_tree::ptree & _tree)1350 void configuration_impl::load_delays(
1351 const boost::property_tree::ptree &_tree) {
1352 try {
1353 std::stringstream its_converter;
1354 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1355 std::string its_key(i->first);
1356 if (its_key == "initial") {
1357 sd_initial_delay_min_ = i->second.get<uint32_t>("minimum");
1358 sd_initial_delay_max_ = i->second.get<uint32_t>("maximum");
1359 } else if (its_key == "repetition-base") {
1360 its_converter << std::dec << i->second.data();
1361 its_converter >> sd_repetitions_base_delay_;
1362 } else if (its_key == "repetition-max") {
1363 int tmp_repetition_max;
1364 its_converter << std::dec << i->second.data();
1365 its_converter >> tmp_repetition_max;
1366 sd_repetitions_max_ =
1367 (tmp_repetition_max
1368 > (std::numeric_limits<std::uint8_t>::max)()) ?
1369 (std::numeric_limits<std::uint8_t>::max)() :
1370 static_cast<std::uint8_t>(tmp_repetition_max);
1371 } else if (its_key == "cyclic-offer") {
1372 its_converter << std::dec << i->second.data();
1373 its_converter >> sd_cyclic_offer_delay_;
1374 } else if (its_key == "cyclic-request") {
1375 its_converter << std::dec << i->second.data();
1376 its_converter >> sd_request_response_delay_;
1377 } else if (its_key == "ttl") {
1378 its_converter << std::dec << i->second.data();
1379 its_converter >> sd_ttl_;
1380 }
1381 its_converter.str("");
1382 its_converter.clear();
1383 }
1384 } catch (...) {
1385 }
1386 }
1387
load_npdu_default_timings(const configuration_element & _element)1388 void configuration_impl::load_npdu_default_timings(const configuration_element &_element) {
1389 const std::string ndt("npdu-default-timings");
1390 const std::string dreq("debounce-time-request");
1391 const std::string dres("debounce-time-response");
1392 const std::string rreq("max-retention-time-request");
1393 const std::string rresp("max-retention-time-response");
1394 try {
1395 if (_element.tree_.get_child_optional(ndt)) {
1396 if (!is_overlay_ && is_configured_[ET_NPDU_DEFAULT_TIMINGS]) {
1397 VSOMEIP_WARNING << "Multiple definitions of " << ndt
1398 << " Ignoring definition from " << _element.name_;
1399 } else {
1400 for (const auto& e : _element.tree_.get_child(ndt)) {
1401 std::chrono::nanoseconds its_time(0);
1402 try {
1403 its_time = std::chrono::nanoseconds(
1404 std::strtoull(e.second.data().c_str(), NULL, 10)
1405 * 1000000);
1406 } catch (const std::exception& e) {
1407 continue;
1408 }
1409 if (e.first.data() == dreq) {
1410 npdu_default_debounce_requ_ = its_time;
1411 } else if (e.first.data() == dres) {
1412 npdu_default_debounce_resp_ = its_time;
1413 } else if (e.first.data() == rreq) {
1414 npdu_default_max_retention_requ_ = its_time;
1415 } else if (e.first.data() == rresp) {
1416 npdu_default_max_retention_resp_ = its_time;
1417 }
1418 }
1419 is_configured_[ET_NPDU_DEFAULT_TIMINGS] = true;
1420 }
1421 }
1422 } catch (...) {
1423 // intentionally left empty
1424 }
1425 }
1426
load_services(const configuration_element & _element)1427 void configuration_impl::load_services(const configuration_element &_element) {
1428 std::lock_guard<std::mutex> its_lock(services_mutex_);
1429 try {
1430 auto its_services = _element.tree_.get_child("services");
1431 for (auto i = its_services.begin(); i != its_services.end(); ++i)
1432 load_service(i->second, default_unicast_);
1433 } catch (...) {
1434 try {
1435 auto its_servicegroups = _element.tree_.get_child("servicegroups");
1436 for (auto i = its_servicegroups.begin(); i != its_servicegroups.end(); ++i)
1437 load_servicegroup(i->second);
1438 } catch (...) {
1439 // intentionally left empty
1440 }
1441 }
1442 }
1443
load_servicegroup(const boost::property_tree::ptree & _tree)1444 void configuration_impl::load_servicegroup(
1445 const boost::property_tree::ptree &_tree) {
1446 try {
1447 std::string its_unicast_address(default_unicast_);
1448
1449 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1450 std::string its_key(i->first);
1451 if (its_key == "unicast") {
1452 its_unicast_address = i->second.data();
1453 break;
1454 }
1455 }
1456
1457 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1458 std::string its_key(i->first);
1459 if (its_key == "delays") {
1460 load_delays(i->second);
1461 } else if (its_key == "services") {
1462 for (auto j = i->second.begin(); j != i->second.end(); ++j)
1463 load_service(j->second, its_unicast_address);
1464 }
1465 }
1466 } catch (...) {
1467 // Intentionally left empty
1468 }
1469 }
1470
load_service(const boost::property_tree::ptree & _tree,const std::string & _unicast_address)1471 void configuration_impl::load_service(
1472 const boost::property_tree::ptree &_tree,
1473 const std::string &_unicast_address) {
1474 try {
1475 bool is_loaded(true);
1476 bool use_magic_cookies(false);
1477
1478 std::shared_ptr<service> its_service(std::make_shared<service>());
1479 its_service->reliable_ = its_service->unreliable_ = ILLEGAL_PORT;
1480 its_service->unicast_address_ = _unicast_address;
1481 its_service->multicast_address_ = "";
1482 its_service->multicast_port_ = ILLEGAL_PORT;
1483 its_service->protocol_ = "someip";
1484 its_service->major_ = DEFAULT_MAJOR;
1485 its_service->minor_ = DEFAULT_MINOR;
1486 its_service->ttl_ = DEFAULT_TTL;
1487
1488 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1489 std::string its_key(i->first);
1490 std::string its_value(i->second.data());
1491 std::stringstream its_converter;
1492
1493 if (its_key == "unicast") {
1494 its_service->unicast_address_ = its_value;
1495 } else if (its_key == "reliable") {
1496 try {
1497 its_value = i->second.get_child("port").data();
1498 its_converter << its_value;
1499 its_converter >> its_service->reliable_;
1500 } catch (...) {
1501 its_converter << its_value;
1502 its_converter >> its_service->reliable_;
1503 }
1504 if(!its_service->reliable_) {
1505 its_service->reliable_ = ILLEGAL_PORT;
1506 }
1507 try {
1508 its_value
1509 = i->second.get_child("enable-magic-cookies").data();
1510 use_magic_cookies = ("true" == its_value);
1511 } catch (...) {
1512
1513 }
1514 } else if (its_key == "unreliable") {
1515 its_converter << its_value;
1516 its_converter >> its_service->unreliable_;
1517 if(!its_service->unreliable_) {
1518 its_service->unreliable_ = ILLEGAL_PORT;
1519 }
1520 } else if (its_key == "multicast") {
1521 try {
1522 its_value = i->second.get_child("address").data();
1523 its_service->multicast_address_ = its_value;
1524 its_value = i->second.get_child("port").data();
1525 its_converter << its_value;
1526 its_converter >> its_service->multicast_port_;
1527 } catch (...) {
1528 }
1529 } else if (its_key == "protocol") {
1530 its_service->protocol_ = its_value;
1531 } else if (its_key == "events") {
1532 load_event(its_service, i->second);
1533 } else if (its_key == "eventgroups") {
1534 load_eventgroup(its_service, i->second);
1535 } else if (its_key == "debounce-times") {
1536 load_npdu_debounce_times_configuration(its_service, i->second);
1537 } else if (its_key == "someip-tp") {
1538 load_someip_tp(its_service, i->second);
1539 } else {
1540 // Trim "its_value"
1541 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1542 its_converter << std::hex << its_value;
1543 } else {
1544 its_converter << std::dec << its_value;
1545 }
1546
1547 if (its_key == "service") {
1548 its_converter >> its_service->service_;
1549 } else if (its_key == "instance") {
1550 its_converter >> its_service->instance_;
1551 } else if (its_key == "major") {
1552 unsigned int temp;
1553 its_converter >> temp;
1554 its_service->major_ = static_cast<major_version_t>(temp);
1555 } else if (its_key == "minor") {
1556 its_converter >> its_service->minor_;
1557 } else if (its_key == "ttl") {
1558 its_converter >> its_service->ttl_;
1559 }
1560 }
1561 }
1562
1563 auto found_service = services_.find(its_service->service_);
1564 if (found_service != services_.end()) {
1565 auto found_instance = found_service->second.find(
1566 its_service->instance_);
1567 if (found_instance != found_service->second.end()) {
1568 VSOMEIP_WARNING << "Multiple configurations for service ["
1569 << std::hex << its_service->service_ << "."
1570 << its_service->instance_ << "]";
1571 is_loaded = false;
1572 }
1573 }
1574
1575 if (is_loaded) {
1576 services_[its_service->service_][its_service->instance_] =
1577 its_service;
1578 if (use_magic_cookies) {
1579 magic_cookies_[its_service->unicast_address_].insert(its_service->reliable_);
1580 }
1581
1582 if (its_service->unicast_address_ == default_unicast_) {
1583 // local services
1584 if(its_service->reliable_ != ILLEGAL_PORT) {
1585 services_by_ip_port_[unicast_.to_string()]
1586 [its_service->reliable_]
1587 [its_service->service_] = its_service;
1588 }
1589 if (its_service->unreliable_ != ILLEGAL_PORT) {
1590 services_by_ip_port_[unicast_.to_string()]
1591 [its_service->unreliable_]
1592 [its_service->service_] = its_service;
1593 // This is necessary as all udp server endpoints listen on
1594 // INADDR_ANY instead of a specific address
1595 services_by_ip_port_[boost::asio::ip::address_v4::any().to_string()]
1596 [its_service->unreliable_]
1597 [its_service->service_] = its_service;
1598 services_by_ip_port_[boost::asio::ip::address_v6::any().to_string()]
1599 [its_service->unreliable_]
1600 [its_service->service_] = its_service;
1601 }
1602 } else {
1603 // remote services
1604 if (its_service->reliable_ != ILLEGAL_PORT) {
1605 services_by_ip_port_[its_service->unicast_address_]
1606 [its_service->reliable_]
1607 [its_service->service_] = its_service;
1608 }
1609 if (its_service->unreliable_ != ILLEGAL_PORT) {
1610 services_by_ip_port_[its_service->unicast_address_]
1611 [its_service->unreliable_]
1612 [its_service->service_] = its_service;
1613 }
1614 }
1615 }
1616 } catch (...) {
1617 // Intentionally left empty
1618 }
1619 }
1620
load_event(std::shared_ptr<service> & _service,const boost::property_tree::ptree & _tree)1621 void configuration_impl::load_event(
1622 std::shared_ptr<service> &_service,
1623 const boost::property_tree::ptree &_tree) {
1624 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1625 event_t its_event_id(0);
1626 bool its_is_field(false);
1627 reliability_type_e its_reliability(reliability_type_e::RT_UNKNOWN);
1628
1629 for (auto j = i->second.begin(); j != i->second.end(); ++j) {
1630 std::string its_key(j->first);
1631 std::string its_value(j->second.data());
1632 if (its_key == "event") {
1633 std::stringstream its_converter;
1634 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1635 its_converter << std::hex << its_value;
1636 } else {
1637 its_converter << std::dec << its_value;
1638 }
1639 its_converter >> its_event_id;
1640 } else if (its_key == "is_field") {
1641 its_is_field = (its_value == "true");
1642 } else if (its_key == "is_reliable") {
1643 if (its_value == "true")
1644 its_reliability = reliability_type_e::RT_RELIABLE;
1645 else
1646 its_reliability = reliability_type_e::RT_UNRELIABLE;
1647 }
1648 }
1649
1650 if (its_event_id > 0) {
1651 std::shared_ptr<event> its_event;
1652
1653 auto found_event = _service->events_.find(its_event_id);
1654 if (found_event != _service->events_.end()) {
1655 if (found_event->second->is_placeholder_) {
1656 its_event = found_event->second;
1657 } else {
1658 VSOMEIP_ERROR << "Multiple configurations for event ["
1659 << std::hex << _service->service_ << "."
1660 << _service->instance_ << "."
1661 << its_event_id << "]";
1662 }
1663 } else {
1664 its_event = std::make_shared<event>(its_event_id);
1665 _service->events_[its_event_id] = its_event;
1666 }
1667
1668 if (its_event) {
1669 // If event reliability type was not configured,
1670 if (its_reliability == reliability_type_e::RT_UNKNOWN) {
1671 if (_service->unreliable_ != ILLEGAL_PORT) {
1672 its_reliability = reliability_type_e::RT_UNRELIABLE;
1673 } else if (_service->reliable_ != ILLEGAL_PORT) {
1674 its_reliability = reliability_type_e::RT_RELIABLE;
1675 }
1676 VSOMEIP_WARNING << "Reliability type for event ["
1677 << std::hex << _service->service_ << "."
1678 << _service->instance_ << "."
1679 << its_event_id << "] was not configured Using : "
1680 << ((its_reliability == reliability_type_e::RT_RELIABLE)
1681 ? "RT_RELIABLE" : "RT_UNRELIABLE");
1682 }
1683
1684 its_event->is_placeholder_ = false;
1685 its_event->reliability_ = its_reliability;
1686 its_event->is_field_ = its_is_field;
1687 }
1688 }
1689 }
1690 }
1691
load_eventgroup(std::shared_ptr<service> & _service,const boost::property_tree::ptree & _tree)1692 void configuration_impl::load_eventgroup(
1693 std::shared_ptr<service> &_service,
1694 const boost::property_tree::ptree &_tree) {
1695 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1696 std::shared_ptr<eventgroup> its_eventgroup =
1697 std::make_shared<eventgroup>();
1698 for (auto j = i->second.begin(); j != i->second.end(); ++j) {
1699 std::stringstream its_converter;
1700 std::string its_key(j->first);
1701 std::string its_value(j->second.data());
1702 if (its_key == "eventgroup") {
1703 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1704 its_converter << std::hex << its_value;
1705 } else {
1706 its_converter << std::dec << its_value;
1707 }
1708 its_converter >> its_eventgroup->id_;
1709 } else if (its_key == "is_multicast") {
1710 std::string its_value(j->second.data());
1711 if (its_value == "true") {
1712 its_eventgroup->multicast_address_ = _service->multicast_address_;
1713 its_eventgroup->multicast_port_ = _service->multicast_port_;
1714 }
1715 } else if (its_key == "multicast") {
1716 try {
1717 std::string its_value = j->second.get_child("address").data();
1718 its_eventgroup->multicast_address_ = its_value;
1719 its_value = j->second.get_child("port").data();
1720 its_converter << its_value;
1721 its_converter >> its_eventgroup->multicast_port_;
1722 } catch (...) {
1723 }
1724 } else if (its_key == "threshold") {
1725 int its_threshold(0);
1726 std::stringstream its_converter;
1727 its_converter << std::dec << its_value;
1728 its_converter >> std::dec >> its_threshold;
1729 its_eventgroup->threshold_ =
1730 (its_threshold > (std::numeric_limits<std::uint8_t>::max)()) ?
1731 (std::numeric_limits<std::uint8_t>::max)() :
1732 static_cast<uint8_t>(its_threshold);
1733 } else if (its_key == "events") {
1734 for (auto k = j->second.begin(); k != j->second.end(); ++k) {
1735 std::stringstream its_converter;
1736 std::string its_value(k->second.data());
1737 event_t its_event_id(0);
1738 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1739 its_converter << std::hex << its_value;
1740 } else {
1741 its_converter << std::dec << its_value;
1742 }
1743 its_converter >> its_event_id;
1744 if (0 < its_event_id) {
1745 std::shared_ptr<event> its_event(nullptr);
1746 auto find_event = _service->events_.find(its_event_id);
1747 if (find_event != _service->events_.end()) {
1748 its_event = find_event->second;
1749 } else {
1750 its_event = std::make_shared<event>(its_event_id);
1751 }
1752 if (its_event) {
1753 its_event->groups_.push_back(its_eventgroup);
1754 its_eventgroup->events_.insert(its_event);
1755 _service->events_[its_event_id] = its_event;
1756 }
1757 }
1758 }
1759 }
1760 }
1761
1762 if (its_eventgroup->id_ > 0) {
1763 _service->eventgroups_[its_eventgroup->id_] = its_eventgroup;
1764 }
1765 }
1766 }
1767
load_internal_services(const configuration_element & _element)1768 void configuration_impl::load_internal_services(const configuration_element &_element) {
1769 try {
1770 auto optional = _element.tree_.get_child_optional("internal_services");
1771 if (!optional) {
1772 return;
1773 }
1774 auto its_internal_services = _element.tree_.get_child("internal_services");
1775 for (auto found_range = its_internal_services.begin();
1776 found_range != its_internal_services.end(); ++found_range) {
1777 service_instance_range range;
1778 range.first_service_ = 0x0;
1779 range.last_service_ = 0x0;
1780 range.first_instance_ = 0x0;
1781 range.last_instance_ = 0xffff;
1782 for (auto i = found_range->second.begin();
1783 i != found_range->second.end(); ++i) {
1784 if (i->first == "first") {
1785 if (i->second.size() == 0) {
1786 std::stringstream its_converter;
1787 std::string value = i->second.data();
1788 its_converter << std::hex << value;
1789 its_converter >> range.first_service_;
1790 }
1791 for (auto n = i->second.begin();
1792 n != i->second.end(); ++n) {
1793 if (n->first == "service") {
1794 std::stringstream its_converter;
1795 std::string value = n->second.data();
1796 its_converter << std::hex << value;
1797 its_converter >> range.first_service_;
1798 } else if (n->first == "instance") {
1799 std::stringstream its_converter;
1800 std::string value = n->second.data();
1801 its_converter << std::hex << value;
1802 its_converter >> range.first_instance_;
1803 }
1804 }
1805 } else if (i->first == "last") {
1806 if (i->second.size() == 0) {
1807 std::stringstream its_converter;
1808 std::string value = i->second.data();
1809 its_converter << std::hex << value;
1810 its_converter >> range.last_service_;
1811 }
1812 for (auto n = i->second.begin();
1813 n != i->second.end(); ++n) {
1814 if (n->first == "service") {
1815 std::stringstream its_converter;
1816 std::string value = n->second.data();
1817 its_converter << std::hex << value;
1818 its_converter >> range.last_service_;
1819 } else if (n->first == "instance") {
1820 std::stringstream its_converter;
1821 std::string value = n->second.data();
1822 its_converter << std::hex << value;
1823 its_converter >> range.last_instance_;
1824 }
1825 }
1826 }
1827 }
1828 if (range.last_service_ >= range.first_service_) {
1829 if (range.last_instance_ >= range.first_instance_) {
1830 internal_service_ranges_.push_back(range);
1831 }
1832 }
1833 }
1834 } catch (...) {
1835 VSOMEIP_ERROR << "Error parsing internal service range configuration!";
1836 }
1837 }
1838
load_clients(const configuration_element & _element)1839 void configuration_impl::load_clients(const configuration_element &_element) {
1840 try {
1841 auto its_clients = _element.tree_.get_child("clients");
1842 for (auto i = its_clients.begin(); i != its_clients.end(); ++i)
1843 load_client(i->second);
1844 } catch (...) {
1845 // intentionally left empty!
1846 }
1847 }
1848
load_client(const boost::property_tree::ptree & _tree)1849 void configuration_impl::load_client(const boost::property_tree::ptree &_tree) {
1850 try {
1851 std::shared_ptr<client> its_client(std::make_shared<client>());
1852 its_client->remote_ports_[true] = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
1853 its_client->remote_ports_[false] = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
1854 its_client->client_ports_[true] = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
1855 its_client->client_ports_[false] = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
1856 its_client->last_used_specific_client_port_[true] = ILLEGAL_PORT;
1857 its_client->last_used_specific_client_port_[false] = ILLEGAL_PORT;
1858 its_client->last_used_client_port_[true] = ILLEGAL_PORT;
1859 its_client->last_used_client_port_[false] = ILLEGAL_PORT;
1860
1861 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1862 std::string its_key(i->first);
1863 std::string its_value(i->second.data());
1864 std::stringstream its_converter;
1865
1866 if (its_key == "reliable_remote_ports") {
1867 its_client->remote_ports_[true] = load_client_port_range(i->second);
1868 } else if (its_key == "unreliable_remote_ports") {
1869 its_client->remote_ports_[false] = load_client_port_range(i->second);
1870 } else if (its_key == "reliable_client_ports") {
1871 its_client->client_ports_[true] = load_client_port_range(i->second);
1872 } else if (its_key == "unreliable_client_ports") {
1873 its_client->client_ports_[false] = load_client_port_range(i->second);
1874 } else if (its_key == "reliable") {
1875 its_client->ports_[true] = load_client_ports(i->second);
1876 } else if (its_key == "unreliable") {
1877 its_client->ports_[false] = load_client_ports(i->second);
1878 } else {
1879 // Trim "its_value"
1880 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1881 its_converter << std::hex << its_value;
1882 } else {
1883 its_converter << std::dec << its_value;
1884 }
1885
1886 if (its_key == "service") {
1887 its_converter >> its_client->service_;
1888 } else if (its_key == "instance") {
1889 its_converter >> its_client->instance_;
1890 }
1891 }
1892 }
1893 clients_.push_back(its_client);
1894 } catch (...) {
1895 }
1896 }
1897
load_client_ports(const boost::property_tree::ptree & _tree)1898 std::set<uint16_t> configuration_impl::load_client_ports(
1899 const boost::property_tree::ptree &_tree) {
1900 std::set<uint16_t> its_ports;
1901 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1902 std::string its_value(i->second.data());
1903 uint16_t its_port_value;
1904
1905 std::stringstream its_converter;
1906 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1907 its_converter << std::hex << its_value;
1908 } else {
1909 its_converter << std::dec << its_value;
1910 }
1911 its_converter >> its_port_value;
1912 its_ports.insert(its_port_value);
1913 }
1914 return its_ports;
1915 }
1916
load_client_port_range(const boost::property_tree::ptree & _tree)1917 std::pair<uint16_t,uint16_t> configuration_impl::load_client_port_range(
1918 const boost::property_tree::ptree &_tree) {
1919 std::pair<uint16_t,uint16_t> its_port_range;
1920 uint16_t its_first_port = ILLEGAL_PORT;
1921 uint16_t its_last_port = ILLEGAL_PORT;
1922
1923 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1924 std::string its_key(i->first);
1925 std::string its_value(i->second.data());
1926 std::stringstream its_converter;
1927
1928 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
1929 its_converter << std::hex << its_value;
1930 } else {
1931 its_converter << std::dec << its_value;
1932 }
1933
1934 if (its_key == "first") {
1935 its_converter >> its_first_port;
1936 } else if (its_key == "last") {
1937 its_converter >> its_last_port;
1938 }
1939 }
1940
1941 if (its_last_port < its_first_port) {
1942 VSOMEIP_WARNING << "Port range invalid: first: " << std::dec << its_first_port << " last: " << its_last_port;
1943 its_port_range = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
1944 } else {
1945 its_port_range = std::make_pair(its_first_port, its_last_port);
1946 }
1947
1948 return its_port_range;
1949 }
1950
load_watchdog(const configuration_element & _element)1951 void configuration_impl::load_watchdog(const configuration_element &_element) {
1952 try {
1953 auto its_service_discovery = _element.tree_.get_child("watchdog");
1954 for (auto i = its_service_discovery.begin();
1955 i != its_service_discovery.end(); ++i) {
1956 std::string its_key(i->first);
1957 std::string its_value(i->second.data());
1958 std::stringstream its_converter;
1959 if (its_key == "enable") {
1960 if (is_configured_[ET_WATCHDOG_ENABLE]) {
1961 VSOMEIP_WARNING << "Multiple definitions of watchdog.enable."
1962 " Ignoring definition from " << _element.name_;
1963 } else {
1964 watchdog_->is_enabeled_ = (its_value == "true");
1965 is_configured_[ET_WATCHDOG_ENABLE] = true;
1966 }
1967 } else if (its_key == "timeout") {
1968 if (is_configured_[ET_WATCHDOG_TIMEOUT]) {
1969 VSOMEIP_WARNING << "Multiple definitions of watchdog.timeout."
1970 " Ignoring definition from " << _element.name_;
1971 } else {
1972 its_converter << std::dec << its_value;
1973 its_converter >> watchdog_->timeout_in_ms_;
1974 is_configured_[ET_WATCHDOG_TIMEOUT] = true;
1975 }
1976 } else if (its_key == "allowed_missing_pongs") {
1977 if (is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS]) {
1978 VSOMEIP_WARNING << "Multiple definitions of watchdog.allowed_missing_pongs."
1979 " Ignoring definition from " << _element.name_;
1980 } else {
1981 its_converter << std::dec << its_value;
1982 its_converter >> watchdog_->missing_pongs_allowed_;
1983 is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS] = true;
1984 }
1985 }
1986 }
1987 } catch (...) {
1988 }
1989 }
1990
load_payload_sizes(const configuration_element & _element)1991 void configuration_impl::load_payload_sizes(const configuration_element &_element) {
1992 const std::string payload_sizes("payload-sizes");
1993 const std::string max_local_payload_size("max-payload-size-local");
1994 const std::string buffer_shrink_threshold("buffer-shrink-threshold");
1995 const std::string max_reliable_payload_size("max-payload-size-reliable");
1996 const std::string max_unreliable_payload_size("max-payload-size-unreliable");
1997 try {
1998 for (const auto& s : { max_local_payload_size,
1999 max_reliable_payload_size, max_unreliable_payload_size }) {
2000 if (_element.tree_.get_child_optional(s)) {
2001 const std::string size_str(_element.tree_.get_child(s).data());
2002 try {
2003 // add 16 Byte for the SOME/IP header
2004 const std::uint32_t its_size = static_cast<std::uint32_t>(
2005 std::stoul(size_str.c_str(), NULL, 10) + 16);
2006 if (s == max_local_payload_size) {
2007 max_local_message_size_ = its_size;
2008 } else if (s == max_reliable_payload_size) {
2009 max_reliable_message_size_ = its_size;
2010 } else if (s == max_unreliable_payload_size) {
2011 max_unreliable_message_size_ = its_size;
2012 }
2013 } catch (const std::exception &e) {
2014 VSOMEIP_ERROR<< __func__ << ": " << s << " " << e.what();
2015 }
2016 }
2017 }
2018
2019 if (_element.tree_.get_child_optional(buffer_shrink_threshold)) {
2020 auto bst = _element.tree_.get_child(buffer_shrink_threshold);
2021 std::string s(bst.data());
2022 try {
2023 buffer_shrink_threshold_ = static_cast<std::uint32_t>(
2024 std::stoul(s.c_str(), NULL, 10));
2025 } catch (const std::exception &e) {
2026 VSOMEIP_ERROR<< __func__ << ": " << buffer_shrink_threshold
2027 << " " << e.what();
2028 }
2029 }
2030 if (_element.tree_.get_child_optional(payload_sizes)) {
2031 const std::string unicast("unicast");
2032 const std::string ports("ports");
2033 const std::string port("port");
2034 const std::string max_payload_size("max-payload-size");
2035 auto its_ps = _element.tree_.get_child(payload_sizes);
2036 for (auto i = its_ps.begin(); i != its_ps.end(); ++i) {
2037 if (!i->second.get_child_optional(unicast)
2038 || !i->second.get_child_optional(ports)) {
2039 continue;
2040 }
2041 std::string its_unicast(i->second.get_child(unicast).data());
2042 for (auto j = i->second.get_child(ports).begin();
2043 j != i->second.get_child(ports).end(); ++j) {
2044
2045 if (!j->second.get_child_optional(port)
2046 || !j->second.get_child_optional(max_payload_size)) {
2047 continue;
2048 }
2049
2050 std::uint16_t its_port = ILLEGAL_PORT;
2051 std::uint32_t its_message_size = 0;
2052
2053 try {
2054 std::string p(j->second.get_child(port).data());
2055 its_port = static_cast<std::uint16_t>(std::stoul(p.c_str(),
2056 NULL, 10));
2057 std::string s(j->second.get_child(max_payload_size).data());
2058 // add 16 Byte for the SOME/IP header
2059 its_message_size = static_cast<std::uint32_t>(
2060 std::stoul(s.c_str(), NULL, 10) + 16);
2061 } catch (const std::exception &e) {
2062 VSOMEIP_ERROR << __func__ << ":" << e.what();
2063 }
2064
2065 if (its_port == ILLEGAL_PORT || its_message_size == 0) {
2066 continue;
2067 }
2068 if (max_configured_message_size_ < its_message_size) {
2069 max_configured_message_size_ = its_message_size;
2070 }
2071
2072 message_sizes_[its_unicast][its_port] = its_message_size;
2073 }
2074 }
2075 if (max_local_message_size_ != 0
2076 && max_configured_message_size_ != 0
2077 && max_configured_message_size_ > max_local_message_size_) {
2078 VSOMEIP_WARNING << max_local_payload_size
2079 << " is configured smaller than the biggest payloadsize"
2080 << " for external communication. "
2081 << max_local_payload_size << " will be increased to "
2082 << max_configured_message_size_ - 16 << " to ensure "
2083 << "local message distribution.";
2084 max_local_message_size_ = max_configured_message_size_;
2085 }
2086 if (max_local_message_size_ != 0
2087 && max_reliable_message_size_ != 0
2088 && max_reliable_message_size_ > max_local_message_size_) {
2089 VSOMEIP_WARNING << max_local_payload_size << " ("
2090 << max_local_message_size_ - 16 << ") is configured"
2091 << " smaller than " << max_reliable_payload_size << " ("
2092 << max_reliable_message_size_ - 16 << "). "
2093 << max_local_payload_size << " will be increased to "
2094 << max_reliable_message_size_ - 16 << " to ensure "
2095 << "local message distribution.";
2096 max_local_message_size_ = max_reliable_message_size_;
2097 }
2098 if (max_local_message_size_ != 0
2099 && max_unreliable_message_size_ != 0
2100 && max_unreliable_message_size_ > max_local_message_size_) {
2101 VSOMEIP_WARNING << max_local_payload_size << " ("
2102 << max_local_message_size_ - 16 << ") is configured"
2103 << " smaller than " << max_unreliable_payload_size << " ("
2104 << max_unreliable_message_size_ - 16 << "). "
2105 << max_local_payload_size << " will be increased to "
2106 << max_unreliable_message_size_ - 16 << " to ensure "
2107 << "local message distribution.";
2108 max_local_message_size_ = max_unreliable_message_size_;
2109 }
2110 }
2111 } catch (...) {
2112 }
2113 }
2114
load_permissions(const configuration_element & _element)2115 void configuration_impl::load_permissions(const configuration_element &_element) {
2116 const std::string file_permissions("file-permissions");
2117 try {
2118 if (_element.tree_.get_child_optional(file_permissions)) {
2119 auto its_permissions = _element.tree_.get_child(file_permissions);
2120 for (auto i = its_permissions.begin(); i != its_permissions.end();
2121 ++i) {
2122 std::string its_key(i->first);
2123 std::stringstream its_converter;
2124 if (its_key == "permissions-shm") {
2125 std::string its_value(i->second.data());
2126 its_converter << std::oct << its_value;
2127 its_converter >> permissions_shm_;
2128 } else if (its_key == "permissions-uds") {
2129 std::string its_value(i->second.data());
2130 its_converter << std::oct << its_value;
2131 its_converter >> permissions_uds_;
2132
2133 }
2134 }
2135 }
2136 } catch (...) {
2137 }
2138 }
2139
load_security(const configuration_element & _element)2140 void configuration_impl::load_security(const configuration_element &_element) {
2141 security::get()->load(_element);
2142 }
2143
load_selective_broadcasts_support(const configuration_element & _element)2144 void configuration_impl::load_selective_broadcasts_support(const configuration_element &_element) {
2145 try {
2146 auto its_service_discovery = _element.tree_.get_child("supports_selective_broadcasts");
2147 for (auto i = its_service_discovery.begin();
2148 i != its_service_discovery.end(); ++i) {
2149 std::string its_value(i->second.data());
2150 supported_selective_addresses.insert(its_value);
2151 }
2152 } catch (...) {
2153 }
2154 }
2155
2156
2157 void
load_partitions(const configuration_element & _element)2158 configuration_impl::load_partitions(const configuration_element &_element) {
2159
2160 try {
2161 auto its_partitions = _element.tree_.get_child("partitions");
2162 for (auto i = its_partitions.begin(); i != its_partitions.end(); ++i) {
2163 load_partition(i->second);
2164 }
2165 } catch (...) {
2166 }
2167 }
2168
2169 void
load_partition(const boost::property_tree::ptree & _tree)2170 configuration_impl::load_partition(const boost::property_tree::ptree &_tree) {
2171
2172 static partition_id_t its_partition_id(VSOMEIP_DEFAULT_PARTITION_ID);
2173
2174 try {
2175
2176 std::stringstream its_converter;
2177 std::map<service_t, std::set<instance_t> > its_partition_members;
2178
2179 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
2180 service_t its_service(0x0);
2181 instance_t its_instance(0x0);
2182 std::string its_service_s, its_instance_s;
2183
2184 for (auto j = i->second.begin(); j != i->second.end(); ++j) {
2185 std::string its_key(j->first);
2186 std::string its_data(j->second.data());
2187
2188 its_converter.str("");
2189 its_converter.clear();
2190
2191 if (its_data.find("0x") != std::string::npos)
2192 its_converter << std::hex;
2193 else
2194 its_converter << std::dec;
2195 its_converter << its_data;
2196
2197 if (its_key == "service") {
2198 its_converter >> its_service;
2199 its_service_s = its_data;
2200 } else if (its_key == "instance") {
2201 its_converter >> its_instance;
2202 its_instance_s = its_data;
2203 }
2204 }
2205
2206 if (its_service > 0 && its_instance > 0)
2207 its_partition_members[its_service].insert(its_instance);
2208 else
2209 VSOMEIP_ERROR << "P: <" << its_service_s << "."
2210 << its_instance_s << "> is no valid service instance.";
2211
2212 }
2213
2214 if (!its_partition_members.empty()) {
2215 std::lock_guard<std::mutex> its_lock(partitions_mutex_);
2216 its_partition_id++;
2217
2218 std::stringstream its_log;
2219 its_log << "P"
2220 << std::dec << static_cast<int>(its_partition_id)
2221 << " [";
2222
2223 for (const auto &i : its_partition_members) {
2224 for (const auto j : i.second) {
2225 partitions_[i.first][j] = its_partition_id;
2226 its_log << "<"
2227 << std::setw(4) << std::setfill('0') << std::hex
2228 << i.first << "."
2229 << std::setw(4) << std::setfill('0') << std::hex
2230 << j
2231 << ">";
2232 }
2233 }
2234
2235 its_log << "]";
2236 VSOMEIP_INFO << its_log.str();
2237 }
2238 } catch (...) {
2239 }
2240 }
2241
2242 ///////////////////////////////////////////////////////////////////////////////
2243 // Internal helper
2244 ///////////////////////////////////////////////////////////////////////////////
set_magic_cookies_unicast_address()2245 void configuration_impl::set_magic_cookies_unicast_address() {
2246 // get services with static routing that have magic cookies enabled
2247 std::map<std::string, std::set<uint16_t> > its_magic_cookies_ = magic_cookies_;
2248 its_magic_cookies_.erase(default_unicast_);
2249
2250 //set unicast address of host for all services without static routing
2251 its_magic_cookies_[get_unicast_address().to_string()].insert(
2252 magic_cookies_[default_unicast_].begin(),
2253 magic_cookies_[default_unicast_].end());
2254 magic_cookies_.clear();
2255 magic_cookies_ = its_magic_cookies_;
2256 }
2257
is_internal_service(service_t _service,instance_t _instance) const2258 bool configuration_impl::is_internal_service(service_t _service,
2259 instance_t _instance) const {
2260
2261 for (auto its_range : internal_service_ranges_) {
2262 if (_service >= its_range.first_service_ &&
2263 _service <= its_range.last_service_ &&
2264 _instance >= its_range.first_instance_ &&
2265 _instance <= its_range.last_instance_) {
2266 return true;
2267 }
2268 }
2269 return false;
2270 }
2271
is_in_port_range(uint16_t _port,std::pair<uint16_t,uint16_t> _port_range) const2272 bool configuration_impl::is_in_port_range(uint16_t _port,
2273 std::pair<uint16_t, uint16_t> _port_range) const {
2274
2275 if (_port >= _port_range.first &&
2276 _port <= _port_range.second ) {
2277 return true;
2278 }
2279 return false;
2280 }
2281
2282 ///////////////////////////////////////////////////////////////////////////////
2283 // Public interface
2284 ///////////////////////////////////////////////////////////////////////////////
get_network() const2285 const std::string &configuration_impl::get_network() const {
2286 return network_;
2287 }
2288
get_unicast_address() const2289 const boost::asio::ip::address & configuration_impl::get_unicast_address() const {
2290 return unicast_;
2291 }
2292
get_netmask() const2293 const boost::asio::ip::address& configuration_impl::get_netmask() const {
2294 return netmask_;
2295 }
2296
get_device() const2297 const std::string &configuration_impl::get_device() const {
2298 return device_;
2299 }
2300
get_diagnosis_address() const2301 diagnosis_t configuration_impl::get_diagnosis_address() const {
2302 return diagnosis_;
2303 }
2304
get_diagnosis_mask() const2305 diagnosis_t configuration_impl::get_diagnosis_mask() const {
2306 return diagnosis_mask_;
2307 }
2308
is_v4() const2309 bool configuration_impl::is_v4() const {
2310 return unicast_.is_v4();
2311 }
2312
is_v6() const2313 bool configuration_impl::is_v6() const {
2314 return unicast_.is_v6();
2315 }
2316
has_console_log() const2317 bool configuration_impl::has_console_log() const {
2318 return has_console_log_;
2319 }
2320
has_file_log() const2321 bool configuration_impl::has_file_log() const {
2322 return has_file_log_;
2323 }
2324
has_dlt_log() const2325 bool configuration_impl::has_dlt_log() const {
2326 return has_dlt_log_;
2327 }
2328
get_logfile() const2329 const std::string & configuration_impl::get_logfile() const {
2330 return logfile_;
2331 }
2332
get_loglevel() const2333 vsomeip_v3::logger::level_e configuration_impl::get_loglevel() const {
2334 return loglevel_;
2335 }
2336
get_unicast_address(service_t _service,instance_t _instance) const2337 std::string configuration_impl::get_unicast_address(service_t _service,
2338 instance_t _instance) const {
2339 std::string its_unicast_address("");
2340 auto its_service = find_service(_service, _instance);
2341 if (its_service) {
2342 its_unicast_address = its_service->unicast_address_;
2343 }
2344
2345 if (its_unicast_address == default_unicast_ || its_unicast_address == "") {
2346 its_unicast_address = get_unicast_address().to_string();
2347 }
2348 return its_unicast_address;
2349 }
2350
get_reliable_port(service_t _service,instance_t _instance) const2351 uint16_t configuration_impl::get_reliable_port(service_t _service,
2352 instance_t _instance) const {
2353 std::lock_guard<std::mutex> its_lock(services_mutex_);
2354 uint16_t its_reliable(ILLEGAL_PORT);
2355 auto its_service = find_service_unlocked(_service, _instance);
2356 if (its_service)
2357 its_reliable = its_service->reliable_;
2358
2359 return its_reliable;
2360 }
2361
get_unreliable_port(service_t _service,instance_t _instance) const2362 uint16_t configuration_impl::get_unreliable_port(service_t _service,
2363 instance_t _instance) const {
2364 std::lock_guard<std::mutex> its_lock(services_mutex_);
2365 uint16_t its_unreliable = ILLEGAL_PORT;
2366 auto its_service = find_service_unlocked(_service, _instance);
2367 if (its_service)
2368 its_unreliable = its_service->unreliable_;
2369
2370 return its_unreliable;
2371 }
2372
get_configured_timing_requests(service_t _service,std::string _ip_target,std::uint16_t _port_target,method_t _method,std::chrono::nanoseconds * _debounce_time,std::chrono::nanoseconds * _max_retention_time) const2373 void configuration_impl::get_configured_timing_requests(
2374 service_t _service, std::string _ip_target,
2375 std::uint16_t _port_target, method_t _method,
2376 std::chrono::nanoseconds *_debounce_time,
2377 std::chrono::nanoseconds *_max_retention_time) const {
2378 if (_debounce_time == nullptr || _max_retention_time == nullptr) {
2379 return;
2380 }
2381 service *its_service = find_service_by_ip_port(_service, _ip_target,
2382 _port_target);
2383 if (its_service) {
2384 auto find_method = its_service->debounce_times_requests_.find(_method);
2385 if (find_method != its_service->debounce_times_requests_.end()) {
2386 *_debounce_time = find_method->second[0];
2387 *_max_retention_time = find_method->second[1];
2388 return;
2389 }
2390 }
2391 *_debounce_time = npdu_default_debounce_requ_;
2392 *_max_retention_time = npdu_default_max_retention_requ_;
2393 }
2394
get_configured_timing_responses(service_t _service,std::string _ip_service,std::uint16_t _port_service,method_t _method,std::chrono::nanoseconds * _debounce_time,std::chrono::nanoseconds * _max_retention_time) const2395 void configuration_impl::get_configured_timing_responses(
2396 service_t _service, std::string _ip_service,
2397 std::uint16_t _port_service, method_t _method,
2398 std::chrono::nanoseconds *_debounce_time,
2399 std::chrono::nanoseconds *_max_retention_time) const {
2400 if (_debounce_time == nullptr || _max_retention_time == nullptr) {
2401 return;
2402 }
2403 service *its_service = find_service_by_ip_port(_service, _ip_service,
2404 _port_service);
2405 if (its_service) {
2406 auto find_method = its_service->debounce_times_responses_.find(_method);
2407 if (find_method != its_service->debounce_times_responses_.end()) {
2408 *_debounce_time = find_method->second[0];
2409 *_max_retention_time = find_method->second[1];
2410 return;
2411 }
2412 }
2413 *_debounce_time = npdu_default_debounce_resp_;
2414 *_max_retention_time = npdu_default_max_retention_resp_;
2415 }
2416
get_major_version(service_t _service,instance_t _instance) const2417 major_version_t configuration_impl::get_major_version(service_t _service,
2418 instance_t _instance) const {
2419 std::lock_guard<std::mutex> its_lock(services_mutex_);
2420 major_version_t its_major = DEFAULT_MAJOR;
2421 auto its_service = find_service_unlocked(_service, _instance);
2422 if (its_service)
2423 its_major = its_service->major_;
2424
2425 return its_major;
2426 }
2427
get_minor_version(service_t _service,instance_t _instance) const2428 minor_version_t configuration_impl::get_minor_version(service_t _service,
2429 instance_t _instance) const {
2430 std::lock_guard<std::mutex> its_lock(services_mutex_);
2431 minor_version_t its_minor = DEFAULT_MINOR;
2432 auto its_service = find_service_unlocked(_service, _instance);
2433 if (its_service)
2434 its_minor = its_service->minor_;
2435
2436 return its_minor;
2437 }
2438
get_ttl(service_t _service,instance_t _instance) const2439 ttl_t configuration_impl::get_ttl(service_t _service,
2440 instance_t _instance) const {
2441 std::lock_guard<std::mutex> its_lock(services_mutex_);
2442 ttl_t its_ttl = DEFAULT_TTL;
2443 auto its_service = find_service_unlocked(_service, _instance);
2444 if (its_service)
2445 its_ttl = its_service->ttl_;
2446
2447 return its_ttl;
2448 }
2449
is_someip(service_t _service,instance_t _instance) const2450 bool configuration_impl::is_someip(service_t _service,
2451 instance_t _instance) const {
2452 auto its_service = find_service(_service, _instance);
2453 if (its_service)
2454 return (its_service->protocol_ == "someip");
2455 return true; // we need to explicitely configure a service to
2456 // be something else than SOME/IP
2457 }
2458
get_client_port(service_t _service,instance_t _instance,uint16_t _remote_port,bool _reliable,std::map<bool,std::set<uint16_t>> & _used_client_ports,uint16_t & _client_port) const2459 bool configuration_impl::get_client_port(
2460 service_t _service, instance_t _instance,
2461 uint16_t _remote_port, bool _reliable,
2462 std::map<bool, std::set<uint16_t> > &_used_client_ports,
2463 uint16_t &_client_port) const {
2464 bool is_configured(false);
2465 _client_port = ILLEGAL_PORT;
2466
2467 uint16_t its_specific_port(ILLEGAL_PORT);
2468 if (find_specific_port(its_specific_port, _service, _instance, _reliable, _used_client_ports)) {
2469 is_configured = true;
2470 if (its_specific_port != ILLEGAL_PORT) {
2471 _client_port = its_specific_port;
2472 return true;
2473 }
2474 }
2475
2476 // No specific port configuration found, use generic configuration
2477 uint16_t its_port(ILLEGAL_PORT);
2478 if (find_port(its_port, _remote_port, _reliable, _used_client_ports)) {
2479 is_configured = true;
2480 if (its_port != ILLEGAL_PORT) {
2481 _client_port = its_port;
2482 return true;
2483 }
2484 }
2485
2486 if (!is_configured) {
2487 // Neither specific not generic configurarion available,
2488 // use dynamic port configuration!
2489 _client_port = 0;
2490 return true;
2491 }
2492
2493 // Configured ports do exist, but they are all in use
2494 VSOMEIP_ERROR << "Cannot find free client port for communication to service: "
2495 << _service << " instance: "
2496 << _instance << " remote_port: "
2497 << _remote_port << " reliable: "
2498 << _reliable;
2499 return false;
2500 }
2501
has_enabled_magic_cookies(std::string _address,uint16_t _port) const2502 bool configuration_impl::has_enabled_magic_cookies(std::string _address,
2503 uint16_t _port) const {
2504 bool has_enabled(false);
2505 auto find_address = magic_cookies_.find(_address);
2506 if (find_address != magic_cookies_.end()) {
2507 auto find_port = find_address->second.find(_port);
2508 if (find_port != find_address->second.end()) {
2509 has_enabled = true;
2510 }
2511 }
2512 return has_enabled;
2513 }
2514
2515
get_routing_host() const2516 const std::string & configuration_impl::get_routing_host() const {
2517 return routing_host_;
2518 }
2519
get_id(const std::string & _name) const2520 client_t configuration_impl::get_id(const std::string &_name) const {
2521 client_t its_client(VSOMEIP_CLIENT_UNSET);
2522
2523 auto found_application = applications_.find(_name);
2524 if (found_application != applications_.end()) {
2525 its_client = std::get<0>(found_application->second);
2526 }
2527
2528 return its_client;
2529 }
2530
is_configured_client_id(client_t _id) const2531 bool configuration_impl::is_configured_client_id(client_t _id) const {
2532 return (client_identifiers_.find(_id) != client_identifiers_.end());
2533 }
2534
get_request_debouncing(const std::string & _name) const2535 std::size_t configuration_impl::get_request_debouncing(const std::string &_name) const {
2536 size_t debounce_time = VSOMEIP_REQUEST_DEBOUNCE_TIME;
2537 auto found_application = applications_.find(_name);
2538 if (found_application != applications_.end()) {
2539 debounce_time = std::get<4>(found_application->second);
2540 }
2541
2542 return debounce_time;
2543 }
2544
get_io_thread_count(const std::string & _name) const2545 std::size_t configuration_impl::get_io_thread_count(const std::string &_name) const {
2546 std::size_t its_io_thread_count = VSOMEIP_IO_THREAD_COUNT;
2547
2548 auto found_application = applications_.find(_name);
2549 if (found_application != applications_.end()) {
2550 its_io_thread_count = std::get<3>(found_application->second);
2551 }
2552
2553 return its_io_thread_count;
2554 }
2555
get_io_thread_nice_level(const std::string & _name) const2556 int configuration_impl::get_io_thread_nice_level(const std::string &_name) const {
2557 int its_io_thread_nice_level = VSOMEIP_IO_THREAD_NICE_LEVEL;
2558
2559 auto found_application = applications_.find(_name);
2560 if (found_application != applications_.end()) {
2561 its_io_thread_nice_level = std::get<6>(found_application->second);
2562 }
2563
2564 return its_io_thread_nice_level;
2565 }
2566
get_max_dispatchers(const std::string & _name) const2567 std::size_t configuration_impl::get_max_dispatchers(
2568 const std::string &_name) const {
2569 std::size_t its_max_dispatchers = VSOMEIP_MAX_DISPATCHERS;
2570
2571 auto found_application = applications_.find(_name);
2572 if (found_application != applications_.end()) {
2573 its_max_dispatchers = std::get<1>(found_application->second);
2574 }
2575
2576 return its_max_dispatchers;
2577 }
2578
get_max_dispatch_time(const std::string & _name) const2579 std::size_t configuration_impl::get_max_dispatch_time(
2580 const std::string &_name) const {
2581 std::size_t its_max_dispatch_time = VSOMEIP_MAX_DISPATCH_TIME;
2582
2583 auto found_application = applications_.find(_name);
2584 if (found_application != applications_.end()) {
2585 its_max_dispatch_time = std::get<2>(found_application->second);
2586 }
2587
2588 return its_max_dispatch_time;
2589 }
2590 #ifdef VSOMEIP_HAS_SESSION_HANDLING_CONFIG
has_session_handling(const std::string & _name) const2591 bool configuration_impl::has_session_handling(const std::string &_name) const {
2592
2593 bool its_value(true);
2594
2595 auto found_application = applications_.find(_name);
2596 if (found_application != applications_.end())
2597 its_value = std::get<8>(found_application->second);
2598
2599 return (its_value);
2600 }
2601 #endif // VSOMEIP_HAS_SESSION_HANDLING_CONFIG
2602
2603 std::set<std::pair<service_t, instance_t> >
get_remote_services() const2604 configuration_impl::get_remote_services() const {
2605 std::lock_guard<std::mutex> its_lock(services_mutex_);
2606 std::set<std::pair<service_t, instance_t> > its_remote_services;
2607 for (const auto& i : services_) {
2608 for (const auto& j : i.second) {
2609 if (is_remote(j.second)) {
2610 its_remote_services.insert(std::make_pair(i.first, j.first));
2611 }
2612 }
2613 }
2614 return its_remote_services;
2615 }
2616
is_mandatory(const std::string & _name) const2617 bool configuration_impl::is_mandatory(const std::string &_name) const {
2618 std::set<std::string> its_candidates;
2619 for (const auto& m : mandatory_) {
2620 if (m.size() <= _name.size()) {
2621 its_candidates.insert(m);
2622 }
2623 }
2624
2625 if (its_candidates.empty())
2626 return false;
2627
2628 for (const auto& c : its_candidates) {
2629 if (std::equal(c.rbegin(), c.rend(), _name.rbegin())) {
2630 return true;
2631 }
2632 }
2633
2634 return false;
2635 }
2636
set_mandatory(const std::string & _input)2637 void configuration_impl::set_mandatory(const std::string &_input) {
2638 if (_input.length() > 0) {
2639 auto found_separator = _input.find(',');
2640 std::string its_mandatory_file = _input.substr(0, found_separator);
2641 trim(its_mandatory_file);
2642 mandatory_.insert(its_mandatory_file);
2643 while (found_separator != std::string::npos) {
2644 auto last_separator = found_separator+1;
2645 found_separator = _input.find(',', last_separator);
2646 its_mandatory_file
2647 = _input.substr(last_separator, found_separator - last_separator);
2648 trim(its_mandatory_file);
2649 mandatory_.insert(its_mandatory_file);
2650 }
2651 }
2652 }
2653
trim(std::string & _s)2654 void configuration_impl::trim(std::string &_s) {
2655 _s.erase(
2656 _s.begin(),
2657 std::find_if(
2658 _s.begin(),
2659 _s.end(),
2660 std::not1(std::ptr_fun(isspace))
2661 )
2662 );
2663
2664 _s.erase(
2665 std::find_if(
2666 _s.rbegin(),
2667 _s.rend(),
2668 std::not1(std::ptr_fun(isspace))).base(),
2669 _s.end()
2670 );
2671 }
2672
is_remote(const std::shared_ptr<service> & _service) const2673 bool configuration_impl::is_remote(const std::shared_ptr<service>& _service) const {
2674 return (_service->unicast_address_ != default_unicast_ &&
2675 _service->unicast_address_ != "" &&
2676 _service->unicast_address_ != unicast_.to_string() &&
2677 _service->unicast_address_ != VSOMEIP_UNICAST_ADDRESS);
2678 }
2679
get_multicast(service_t _service,instance_t _instance,eventgroup_t _eventgroup,std::string & _address,uint16_t & _port) const2680 bool configuration_impl::get_multicast(service_t _service,
2681 instance_t _instance, eventgroup_t _eventgroup,
2682 std::string &_address, uint16_t &_port) const
2683 {
2684 std::shared_ptr<eventgroup> its_eventgroup
2685 = find_eventgroup(_service, _instance, _eventgroup);
2686 if (!its_eventgroup)
2687 return false;
2688
2689 if (its_eventgroup->multicast_address_.empty())
2690 return false;
2691
2692 _address = its_eventgroup->multicast_address_;
2693 _port = its_eventgroup->multicast_port_;
2694 return true;
2695 }
2696
get_threshold(service_t _service,instance_t _instance,eventgroup_t _eventgroup) const2697 uint8_t configuration_impl::get_threshold(service_t _service,
2698 instance_t _instance, eventgroup_t _eventgroup) const {
2699 std::shared_ptr<eventgroup> its_eventgroup
2700 = find_eventgroup(_service, _instance, _eventgroup);
2701 return (its_eventgroup ? its_eventgroup->threshold_ : 0);
2702 }
2703
find_client(service_t _service,instance_t _instance) const2704 std::shared_ptr<client> configuration_impl::find_client(service_t _service,
2705 instance_t _instance) const {
2706 std::list<std::shared_ptr<client>>::const_iterator it;
2707
2708 for (it = clients_.begin(); it != clients_.end(); ++it){
2709 // client was configured for specific service / instance
2710 if ((*it)->service_ == _service
2711 && (*it)->instance_ == _instance) {
2712 return *it;
2713 }
2714 }
2715 return nullptr;
2716 }
2717
find_port(uint16_t & _port,uint16_t _remote,bool _reliable,std::map<bool,std::set<uint16_t>> & _used_client_ports) const2718 bool configuration_impl::find_port(uint16_t &_port, uint16_t _remote, bool _reliable,
2719 std::map<bool, std::set<uint16_t> > &_used_client_ports) const {
2720 bool is_configured(false);
2721 std::list<std::shared_ptr<client>>::const_iterator it;
2722
2723 for (it = clients_.begin(); it != clients_.end(); ++it) {
2724 if (_remote != ILLEGAL_PORT && is_in_port_range(_remote,
2725 (*it)->remote_ports_[_reliable])) {
2726 is_configured = true;
2727 uint16_t its_port(ILLEGAL_PORT);
2728 if ((*it)->last_used_client_port_[_reliable] != ILLEGAL_PORT &&
2729 is_in_port_range(((*it)->last_used_client_port_[_reliable])++,
2730 (*it)->client_ports_[_reliable])) {
2731 its_port = ((*it)->last_used_client_port_[_reliable])++;
2732 } else {
2733 // on initial start of port search
2734 if ((*it)->last_used_client_port_[_reliable] == ILLEGAL_PORT) {
2735 its_port = (*it)->client_ports_[_reliable].first;
2736 } else {
2737 continue;
2738 }
2739 }
2740 while (its_port <= (*it)->client_ports_[_reliable].second) {
2741 if (_used_client_ports[_reliable].find(its_port)
2742 == _used_client_ports[_reliable].end()) {
2743 _port = its_port;
2744 (*it)->last_used_client_port_[_reliable] = its_port;
2745 return true;
2746 }
2747 its_port++;
2748 }
2749 }
2750 }
2751 // no free port was found in _used_client_ports or last_used_port
2752 // cannot be incremented for any client port range
2753 // -> reset last used port for all available client port ranges
2754 for (it = clients_.begin(); it != clients_.end(); ++it) {
2755 if (_remote != ILLEGAL_PORT && is_in_port_range(_remote,
2756 (*it)->remote_ports_[_reliable])) {
2757 (*it)->last_used_client_port_[_reliable] = ILLEGAL_PORT;
2758 }
2759 }
2760 // ensure that all configured client ports are checked from beginning
2761 for (it = clients_.begin(); it != clients_.end(); ++it) {
2762 if (_remote != ILLEGAL_PORT && is_in_port_range(_remote,
2763 (*it)->remote_ports_[_reliable])) {
2764 uint16_t its_port(ILLEGAL_PORT);
2765 its_port = (*it)->client_ports_[_reliable].first;
2766 while (its_port <= (*it)->client_ports_[_reliable].second) {
2767 if (_used_client_ports[_reliable].find(its_port)
2768 == _used_client_ports[_reliable].end()) {
2769 _port = its_port;
2770 (*it)->last_used_client_port_[_reliable] = its_port;
2771 return true;
2772 }
2773 its_port++;
2774 }
2775 }
2776 }
2777 return is_configured;
2778 }
2779
find_specific_port(uint16_t & _port,service_t _service,instance_t _instance,bool _reliable,std::map<bool,std::set<uint16_t>> & _used_client_ports) const2780 bool configuration_impl::find_specific_port(uint16_t &_port, service_t _service,
2781 instance_t _instance, bool _reliable,
2782 std::map<bool, std::set<uint16_t> > &_used_client_ports) const {
2783 bool is_configured(false);
2784 bool check_all(false);
2785 std::list<std::shared_ptr<client>>::const_iterator it;
2786 auto its_client = find_client(_service, _instance);
2787
2788 // Check for service, instance specific port configuration
2789 if (its_client && !its_client->ports_[_reliable].empty()) {
2790 is_configured = true;
2791 std::set<uint16_t>::const_iterator it;
2792 if (its_client->last_used_specific_client_port_[_reliable] == ILLEGAL_PORT) {
2793 it = its_client->ports_[_reliable].begin();
2794 } else {
2795 it = its_client->ports_[_reliable].find(
2796 its_client->last_used_specific_client_port_[_reliable]);
2797 auto it_next = std::next(it, 1);
2798 if (it_next != its_client->ports_[_reliable].end()) {
2799 check_all = true;
2800 it = it_next;
2801 } else {
2802 it = its_client->ports_[_reliable].begin();
2803 }
2804 }
2805 while (it != its_client->ports_[_reliable].end()) {
2806 if (_used_client_ports[_reliable].find(*it)
2807 == _used_client_ports[_reliable].end()) {
2808 _port = *it;
2809 its_client->last_used_specific_client_port_[_reliable] = *it;
2810 VSOMEIP_INFO << "configuration_impl:find_specific_port #1:"
2811 << " service: " << std::hex << _service
2812 << " instance: " << _instance
2813 << " reliable: " << std::dec << _reliable
2814 << " return specific port: " << (uint32_t)_port;
2815 return true;
2816 }
2817 ++it;
2818 }
2819 if (check_all) {
2820 // no free port was found
2821 // ensure that all configured client ports are checked from beginning
2822 for (auto its_port : _used_client_ports[_reliable]) {
2823 if (_used_client_ports[_reliable].find(its_port)
2824 == _used_client_ports[_reliable].end()) {
2825 _port = its_port;
2826 its_client->last_used_specific_client_port_[_reliable] = its_port;
2827 VSOMEIP_INFO << "configuration_impl:find_specific_port #2:"
2828 << " service: " << std::hex << _service
2829 << " instance: " << _instance
2830 << " reliable: " << std::dec << _reliable
2831 << " return specific port: " << (uint32_t)_port;
2832 return true;
2833 }
2834 }
2835 }
2836 its_client->last_used_specific_client_port_[_reliable] = ILLEGAL_PORT;
2837 }
2838 return is_configured;
2839 }
2840
2841 reliability_type_e
get_event_reliability(service_t _service,instance_t _instance,event_t _event) const2842 configuration_impl::get_event_reliability(service_t _service,
2843 instance_t _instance, event_t _event) const {
2844 std::lock_guard<std::mutex> its_lock(services_mutex_);
2845 reliability_type_e its_reliability(reliability_type_e::RT_UNKNOWN);
2846 auto its_service = find_service_unlocked(_service, _instance);
2847 if (its_service) {
2848 auto its_event = its_service->events_.find(_event);
2849 if (its_event != its_service->events_.end()) {
2850 its_reliability = its_event->second->reliability_;
2851 }
2852 }
2853 return its_reliability;
2854 }
2855
2856 reliability_type_e
get_service_reliability(service_t _service,instance_t _instance) const2857 configuration_impl::get_service_reliability(service_t _service,
2858 instance_t _instance) const {
2859 std::lock_guard<std::mutex> its_lock(services_mutex_);
2860 reliability_type_e its_reliability(reliability_type_e::RT_UNKNOWN);
2861 auto its_service = find_service_unlocked(_service, _instance);
2862 if (its_service) {
2863 if (its_service->reliable_ != ILLEGAL_PORT) {
2864 if (its_service->unreliable_ != ILLEGAL_PORT) {
2865 its_reliability = reliability_type_e::RT_BOTH;
2866 } else {
2867 its_reliability = reliability_type_e::RT_RELIABLE;
2868 }
2869 } else {
2870 its_reliability = reliability_type_e::RT_UNRELIABLE;
2871 }
2872 }
2873 return its_reliability;
2874 }
2875
find_service(service_t _service,instance_t _instance) const2876 std::shared_ptr<service> configuration_impl::find_service(service_t _service,
2877 instance_t _instance) const {
2878 std::lock_guard<std::mutex> its_lock(services_mutex_);
2879 return find_service_unlocked(_service, _instance);
2880 }
2881
find_service_unlocked(service_t _service,instance_t _instance) const2882 std::shared_ptr<service> configuration_impl::find_service_unlocked(service_t _service,
2883 instance_t _instance) const {
2884 std::shared_ptr<service> its_service;
2885 auto find_service = services_.find(_service);
2886 if (find_service != services_.end()) {
2887 auto find_instance = find_service->second.find(_instance);
2888 if (find_instance != find_service->second.end()) {
2889 its_service = find_instance->second;
2890 }
2891 }
2892 return its_service;
2893 }
2894
find_service_by_ip_port(service_t _service,const std::string & _ip,std::uint16_t _port) const2895 service* configuration_impl::find_service_by_ip_port(
2896 service_t _service, const std::string& _ip, std::uint16_t _port) const {
2897 service *its_service(0);
2898 auto find_ip = services_by_ip_port_.find(_ip);
2899 if(find_ip != services_by_ip_port_.end()) {
2900 auto find_port = find_ip->second.find(_port);
2901 if(find_port != find_ip->second.end()) {
2902 auto find_service = find_port->second.find(_service);
2903 if(find_service != find_port->second.end()) {
2904 its_service = find_service->second.get();
2905 }
2906 }
2907 }
2908 return its_service;
2909 }
2910
find_eventgroup(service_t _service,instance_t _instance,eventgroup_t _eventgroup) const2911 std::shared_ptr<eventgroup> configuration_impl::find_eventgroup(
2912 service_t _service, instance_t _instance,
2913 eventgroup_t _eventgroup) const {
2914 std::shared_ptr<eventgroup> its_eventgroup;
2915 auto its_service = find_service(_service, _instance);
2916 if (its_service) {
2917 auto find_eventgroup = its_service->eventgroups_.find(_eventgroup);
2918 if (find_eventgroup != its_service->eventgroups_.end()) {
2919 its_eventgroup = find_eventgroup->second;
2920 }
2921 }
2922 return its_eventgroup;
2923 }
2924
get_max_message_size_local() const2925 std::uint32_t configuration_impl::get_max_message_size_local() const {
2926 if (max_local_message_size_ == 0
2927 && (VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0
2928 || VSOMEIP_MAX_TCP_MESSAGE_SIZE == 0)) {
2929 // no limit specified in configuration file and
2930 // defines are set to unlimited
2931 return MESSAGE_SIZE_UNLIMITED;
2932 }
2933
2934 uint32_t its_max_message_size = max_local_message_size_;
2935 if (VSOMEIP_MAX_TCP_MESSAGE_SIZE >= its_max_message_size) {
2936 its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE;
2937 }
2938 if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) {
2939 its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE;
2940 }
2941 if (its_max_message_size < max_configured_message_size_) {
2942 its_max_message_size = max_configured_message_size_;
2943 }
2944
2945 // add sizes of the the routing_manager_proxy's messages
2946 // to the routing_manager stub
2947 return std::uint32_t(its_max_message_size + VSOMEIP_SEND_COMMAND_SIZE);
2948 }
2949
get_max_message_size_reliable(const std::string & _address,std::uint16_t _port) const2950 std::uint32_t configuration_impl::get_max_message_size_reliable(
2951 const std::string& _address, std::uint16_t _port) const {
2952 const auto its_address = message_sizes_.find(_address);
2953 if(its_address != message_sizes_.end()) {
2954 const auto its_port = its_address->second.find(_port);
2955 if(its_port != its_address->second.end()) {
2956 return its_port->second;
2957 }
2958 }
2959 return (max_reliable_message_size_ == 0) ?
2960 ((VSOMEIP_MAX_TCP_MESSAGE_SIZE == 0) ? MESSAGE_SIZE_UNLIMITED :
2961 VSOMEIP_MAX_TCP_MESSAGE_SIZE) : max_reliable_message_size_;
2962 }
2963
get_max_message_size_unreliable() const2964 std::uint32_t configuration_impl::get_max_message_size_unreliable() const {
2965 return (max_unreliable_message_size_ == 0) ?
2966 MESSAGE_SIZE_UNLIMITED : max_unreliable_message_size_;
2967 }
2968
get_buffer_shrink_threshold() const2969 std::uint32_t configuration_impl::get_buffer_shrink_threshold() const {
2970 return buffer_shrink_threshold_;
2971 }
2972
supports_selective_broadcasts(boost::asio::ip::address _address) const2973 bool configuration_impl::supports_selective_broadcasts(boost::asio::ip::address _address) const {
2974 return supported_selective_addresses.find(_address.to_string()) != supported_selective_addresses.end();
2975 }
2976
log_version() const2977 bool configuration_impl::log_version() const {
2978 return log_version_;
2979 }
2980
get_log_version_interval() const2981 uint32_t configuration_impl::get_log_version_interval() const {
2982 return log_version_interval_;
2983 }
2984
is_offered_remote(service_t _service,instance_t _instance) const2985 bool configuration_impl::is_offered_remote(service_t _service, instance_t _instance) const {
2986 uint16_t reliable_port = get_reliable_port(_service, _instance);
2987 uint16_t unreliable_port = get_unreliable_port(_service, _instance);
2988 return (reliable_port != ILLEGAL_PORT || unreliable_port != ILLEGAL_PORT);
2989 }
2990
is_local_service(service_t _service,instance_t _instance) const2991 bool configuration_impl::is_local_service(service_t _service, instance_t _instance) const {
2992 std::shared_ptr<service> s = find_service(_service, _instance);
2993 if (s && !is_remote(s)) {
2994 return true;
2995 }
2996 if (is_internal_service(_service, _instance)) {
2997 return true;
2998 }
2999
3000 return false;
3001 }
3002
3003 // Service Discovery configuration
is_sd_enabled() const3004 bool configuration_impl::is_sd_enabled() const {
3005 return is_sd_enabled_;
3006 }
3007
get_sd_multicast() const3008 const std::string & configuration_impl::get_sd_multicast() const {
3009 return sd_multicast_;
3010 }
3011
get_sd_port() const3012 uint16_t configuration_impl::get_sd_port() const {
3013 return sd_port_;
3014 }
3015
get_sd_protocol() const3016 const std::string & configuration_impl::get_sd_protocol() const {
3017 return sd_protocol_;
3018 }
3019
get_sd_initial_delay_min() const3020 uint32_t configuration_impl::get_sd_initial_delay_min() const {
3021 return sd_initial_delay_min_;
3022 }
3023
get_sd_initial_delay_max() const3024 uint32_t configuration_impl::get_sd_initial_delay_max() const {
3025 return sd_initial_delay_max_;
3026 }
3027
get_sd_repetitions_base_delay() const3028 int32_t configuration_impl::get_sd_repetitions_base_delay() const {
3029 return sd_repetitions_base_delay_;
3030 }
3031
get_sd_repetitions_max() const3032 uint8_t configuration_impl::get_sd_repetitions_max() const {
3033 return sd_repetitions_max_;
3034 }
3035
get_sd_ttl() const3036 ttl_t configuration_impl::get_sd_ttl() const {
3037 return sd_ttl_;
3038 }
3039
get_sd_cyclic_offer_delay() const3040 int32_t configuration_impl::get_sd_cyclic_offer_delay() const {
3041 return sd_cyclic_offer_delay_;
3042 }
3043
get_sd_request_response_delay() const3044 int32_t configuration_impl::get_sd_request_response_delay() const {
3045 return sd_request_response_delay_;
3046 }
3047
get_sd_offer_debounce_time() const3048 std::uint32_t configuration_impl::get_sd_offer_debounce_time() const {
3049 return sd_offer_debounce_time_;
3050 }
3051
3052 // Trace configuration
get_trace() const3053 std::shared_ptr<cfg::trace> configuration_impl::get_trace() const {
3054 return trace_;
3055 }
3056
3057 // Watchdog config
is_watchdog_enabled() const3058 bool configuration_impl::is_watchdog_enabled() const {
3059 return watchdog_->is_enabeled_;
3060 }
3061
get_watchdog_timeout() const3062 uint32_t configuration_impl::get_watchdog_timeout() const {
3063 return watchdog_->timeout_in_ms_;
3064 }
3065
get_allowed_missing_pongs() const3066 uint32_t configuration_impl::get_allowed_missing_pongs() const {
3067 return watchdog_->missing_pongs_allowed_;
3068 }
get_permissions_uds() const3069 std::uint32_t configuration_impl::get_permissions_uds() const {
3070 return permissions_uds_;
3071 }
3072
get_permissions_shm() const3073 std::uint32_t configuration_impl::get_permissions_shm() const {
3074 return permissions_shm_;
3075 }
3076
get_plugins(const std::string & _name) const3077 std::map<plugin_type_e, std::set<std::string>> configuration_impl::get_plugins(
3078 const std::string &_name) const {
3079 std::map<plugin_type_e, std::set<std::string>> result;
3080
3081 auto found_application = applications_.find(_name);
3082 if (found_application != applications_.end()) {
3083 result = std::get<5>(found_application->second);
3084 }
3085
3086 return result;
3087 }
3088
set_configuration_path(const std::string & _path)3089 void configuration_impl::set_configuration_path(const std::string &_path) {
3090 configuration_path_ = _path;
3091 }
3092
is_e2e_enabled() const3093 bool configuration_impl::is_e2e_enabled() const {
3094 return e2e_enabled_;
3095 }
3096
load_e2e(const configuration_element & _element)3097 void configuration_impl::load_e2e(const configuration_element &_element) {
3098 #ifdef _WIN32
3099 return;
3100 #endif
3101 try {
3102 auto optional = _element.tree_.get_child_optional("e2e");
3103 if (!optional) {
3104 return;
3105 }
3106 auto found_e2e = _element.tree_.get_child("e2e");
3107 for (auto its_e2e = found_e2e.begin();
3108 its_e2e != found_e2e.end(); ++its_e2e) {
3109 if (its_e2e->first == "e2e_enabled") {
3110 if (its_e2e->second.data() == "true") {
3111 e2e_enabled_ = true;
3112 }
3113 }
3114 if (its_e2e->first == "protected") {
3115 for (auto its_protected = its_e2e->second.begin();
3116 its_protected != its_e2e->second.end(); ++its_protected) {
3117 load_e2e_protected(its_protected->second);
3118 }
3119 }
3120 }
3121 } catch (...) {
3122 }
3123 }
3124
load_e2e_protected(const boost::property_tree::ptree & _tree)3125 void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_tree) {
3126
3127 std::string variant("");
3128 std::string profile("");
3129 service_t service_id(0);
3130 event_t event_id(0);
3131
3132 e2e::custom_parameters_t custom_parameters;
3133
3134 for (auto l = _tree.begin(); l != _tree.end(); ++l) {
3135 std::stringstream its_converter;
3136 if (l->first == "service_id") {
3137 std::string value = l->second.data();
3138 if (value.size() > 1 && value[0] == '0' && value[1] == 'x') {
3139 its_converter << std::hex << value;
3140 } else {
3141 its_converter << std::dec << value;
3142 }
3143 its_converter >> service_id;
3144 } else if (l->first == "event_id") {
3145 std::string value = l->second.data();
3146 if (value.size() > 1 && value[0] == '0' && value[1] == 'x') {
3147 its_converter << std::hex << value;
3148 } else {
3149 its_converter << std::dec << value;
3150 }
3151 its_converter >> event_id;
3152 } else if (l->first == "variant") {
3153 std::string value = l->second.data();
3154 its_converter << value;
3155 its_converter >> variant;
3156 } else if (l->first == "profile") {
3157 std::string value = l->second.data();
3158 its_converter << value;
3159 its_converter >> profile;
3160 } else {
3161 custom_parameters[l->first.data()] = l->second.data();
3162 }
3163 }
3164 e2e_configuration_[std::make_pair(service_id, event_id)] = std::make_shared<cfg::e2e>(
3165 variant,
3166 profile,
3167 service_id,
3168 event_id,
3169 std::move(custom_parameters)
3170 );
3171 }
3172
get_e2e_configuration() const3173 std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> configuration_impl::get_e2e_configuration() const {
3174 return e2e_configuration_;
3175 }
3176
log_memory() const3177 bool configuration_impl::log_memory() const {
3178 return log_memory_;
3179 }
3180
get_log_memory_interval() const3181 uint32_t configuration_impl::get_log_memory_interval() const {
3182 return log_memory_interval_;
3183 }
3184
log_status() const3185 bool configuration_impl::log_status() const {
3186 return log_status_;
3187 }
3188
get_log_status_interval() const3189 uint32_t configuration_impl::get_log_status_interval() const {
3190 return log_status_interval_;
3191 }
3192
load_ttl_factors(const boost::property_tree::ptree & _tree,ttl_map_t * _target)3193 void configuration_impl::load_ttl_factors(
3194 const boost::property_tree::ptree &_tree, ttl_map_t* _target) {
3195 const service_t ILLEGAL_VALUE(0xffff);
3196 for (const auto& i : _tree) {
3197 service_t its_service(ILLEGAL_VALUE);
3198 instance_t its_instance(ILLEGAL_VALUE);
3199 configuration::ttl_factor_t its_ttl_factor(0);
3200
3201 for (const auto& j : i.second) {
3202 std::string its_key(j.first);
3203 std::string its_value(j.second.data());
3204 std::stringstream its_converter;
3205
3206 if (its_key == "ttl_factor") {
3207 its_converter << its_value;
3208 its_converter >> its_ttl_factor;
3209 } else {
3210 // Trim "its_value"
3211 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
3212 its_converter << std::hex << its_value;
3213 } else {
3214 its_converter << std::dec << its_value;
3215 }
3216
3217 if (its_key == "service") {
3218 its_converter >> its_service;
3219 } else if (its_key == "instance") {
3220 its_converter >> its_instance;
3221 }
3222 }
3223 }
3224 if (its_service != ILLEGAL_VALUE
3225 && its_instance != ILLEGAL_VALUE
3226 && its_ttl_factor > 0) {
3227 (*_target)[its_service][its_instance] = its_ttl_factor;
3228 } else {
3229 VSOMEIP_ERROR << "Invalid ttl factor configuration";
3230 }
3231 }
3232 }
3233
get_ttl_factor_offers() const3234 configuration::ttl_map_t configuration_impl::get_ttl_factor_offers() const {
3235 return ttl_factors_offers_;
3236 }
3237
get_ttl_factor_subscribes() const3238 configuration::ttl_map_t configuration_impl::get_ttl_factor_subscribes() const {
3239 return ttl_factors_subscriptions_;
3240 }
3241
3242 configuration::endpoint_queue_limit_t
get_endpoint_queue_limit(const std::string & _address,std::uint16_t _port) const3243 configuration_impl::get_endpoint_queue_limit(
3244 const std::string& _address, std::uint16_t _port) const {
3245 auto found_address = endpoint_queue_limits_.find(_address);
3246 if (found_address != endpoint_queue_limits_.end()) {
3247 auto found_port = found_address->second.find(_port);
3248 if (found_port != found_address->second.end()) {
3249 return found_port->second;
3250 }
3251 }
3252 return endpoint_queue_limit_external_;
3253 }
3254
3255 configuration::endpoint_queue_limit_t
get_endpoint_queue_limit_local() const3256 configuration_impl::get_endpoint_queue_limit_local() const {
3257 return endpoint_queue_limit_local_;
3258 }
3259
3260 void
load_endpoint_queue_sizes(const configuration_element & _element)3261 configuration_impl::load_endpoint_queue_sizes(const configuration_element &_element) {
3262 const std::string endpoint_queue_limits("endpoint-queue-limits");
3263 const std::string endpoint_queue_limit_external("endpoint-queue-limit-external");
3264 const std::string endpoint_queue_limit_local("endpoint-queue-limit-local");
3265
3266 try {
3267 if (_element.tree_.get_child_optional(endpoint_queue_limit_external)) {
3268 if (is_configured_[ET_ENDPOINT_QUEUE_LIMIT_EXTERNAL]) {
3269 VSOMEIP_WARNING << "Multiple definitions for "
3270 << endpoint_queue_limit_external
3271 << " Ignoring definition from " << _element.name_;
3272 } else {
3273 is_configured_[ET_ENDPOINT_QUEUE_LIMIT_EXTERNAL] = true;
3274 auto mpsl = _element.tree_.get_child(
3275 endpoint_queue_limit_external);
3276 std::string s(mpsl.data());
3277 try {
3278 endpoint_queue_limit_external_ =
3279 static_cast<configuration::endpoint_queue_limit_t>(std::stoul(
3280 s.c_str(), NULL, 10));
3281 } catch (const std::exception &e) {
3282 VSOMEIP_ERROR<<__func__ << ": " << endpoint_queue_limit_external
3283 << " " << e.what();
3284 }
3285 }
3286 }
3287 if (_element.tree_.get_child_optional(endpoint_queue_limit_local)) {
3288 if (is_configured_[ET_ENDPOINT_QUEUE_LIMIT_LOCAL]) {
3289 VSOMEIP_WARNING << "Multiple definitions for "
3290 << endpoint_queue_limit_local
3291 << " Ignoring definition from " << _element.name_;
3292 } else {
3293 is_configured_[ET_ENDPOINT_QUEUE_LIMIT_LOCAL] = true;
3294 auto mpsl = _element.tree_.get_child(endpoint_queue_limit_local);
3295 std::string s(mpsl.data());
3296 try {
3297 endpoint_queue_limit_local_=
3298 static_cast<configuration::endpoint_queue_limit_t>(
3299 std::stoul(s.c_str(), NULL, 10));
3300 } catch (const std::exception &e) {
3301 VSOMEIP_ERROR<< __func__ << ": "<< endpoint_queue_limit_local
3302 << " " << e.what();
3303 }
3304 }
3305 }
3306
3307 if (_element.tree_.get_child_optional(endpoint_queue_limits)) {
3308 if (is_configured_[ET_ENDPOINT_QUEUE_LIMITS]) {
3309 VSOMEIP_WARNING << "Multiple definitions for "
3310 << endpoint_queue_limits
3311 << " Ignoring definition from " << _element.name_;
3312 } else {
3313 is_configured_[ET_ENDPOINT_QUEUE_LIMITS] = true;
3314 const std::string unicast("unicast");
3315 const std::string ports("ports");
3316 const std::string port("port");
3317 const std::string queue_size_limit("queue-size-limit");
3318
3319 for (const auto& i : _element.tree_.get_child(endpoint_queue_limits)) {
3320 if (!i.second.get_child_optional(unicast)
3321 || !i.second.get_child_optional(ports)) {
3322 continue;
3323 }
3324 std::string its_unicast(i.second.get_child(unicast).data());
3325 for (const auto& j : i.second.get_child(ports)) {
3326
3327 if (!j.second.get_child_optional(port)
3328 || !j.second.get_child_optional(queue_size_limit)) {
3329 continue;
3330 }
3331
3332 std::uint16_t its_port = ILLEGAL_PORT;
3333 std::uint32_t its_queue_size_limit = 0;
3334
3335 try {
3336 std::string p(j.second.get_child(port).data());
3337 its_port = static_cast<std::uint16_t>(std::stoul(p.c_str(),
3338 NULL, 10));
3339 std::string s(j.second.get_child(queue_size_limit).data());
3340 its_queue_size_limit = static_cast<std::uint32_t>(std::stoul(
3341 s.c_str(), NULL, 10));
3342 } catch (const std::exception &e) {
3343 VSOMEIP_ERROR << __func__ << ":" << e.what();
3344 }
3345
3346 if (its_port == ILLEGAL_PORT || its_queue_size_limit == 0) {
3347 continue;
3348 }
3349
3350 endpoint_queue_limits_[its_unicast][its_port] = its_queue_size_limit;
3351 }
3352 }
3353 }
3354 }
3355 } catch (...) {
3356 }
3357 }
3358
3359 void
load_debounce(const configuration_element & _element)3360 configuration_impl::load_debounce(const configuration_element &_element) {
3361 try {
3362 auto its_debounce = _element.tree_.get_child("debounce");
3363 for (auto i = its_debounce.begin(); i != its_debounce.end(); ++i) {
3364 load_service_debounce(i->second);
3365 }
3366 } catch (...) {
3367 }
3368 }
3369
3370 void
load_service_debounce(const boost::property_tree::ptree & _tree)3371 configuration_impl::load_service_debounce(const boost::property_tree::ptree &_tree) {
3372 service_t its_service(0);
3373 instance_t its_instance(0);
3374 std::map<event_t, std::shared_ptr<debounce>> its_debounces;
3375
3376 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
3377 std::string its_key(i->first);
3378 std::string its_value(i->second.data());
3379 std::stringstream its_converter;
3380
3381 if (its_key == "service") {
3382 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
3383 its_converter << std::hex << its_value;
3384 } else {
3385 its_converter << std::dec << its_value;
3386 }
3387 its_converter >> its_service;
3388 } else if (its_key == "instance") {
3389 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
3390 its_converter << std::hex << its_value;
3391 } else {
3392 its_converter << std::dec << its_value;
3393 }
3394 its_converter >> its_instance;
3395 } else if (its_key == "events") {
3396 load_events_debounce(i->second, its_debounces);
3397 }
3398 }
3399
3400 // TODO: Improve error handling!
3401 if (its_service > 0 && its_instance > 0 && !its_debounces.empty()) {
3402 auto find_service = debounces_.find(its_service);
3403 if (find_service != debounces_.end()) {
3404 auto find_instance = find_service->second.find(its_instance);
3405 if (find_instance != find_service->second.end()) {
3406 VSOMEIP_ERROR << "Multiple debounce configurations for service "
3407 << std::hex << std::setw(4) << std::setfill('0') << its_service
3408 << "."
3409 << std::hex << std::setw(4) << std::setfill('0') << its_instance;
3410 return;
3411 }
3412 }
3413 debounces_[its_service][its_instance] = its_debounces;
3414 }
3415 }
3416
load_events_debounce(const boost::property_tree::ptree & _tree,std::map<event_t,std::shared_ptr<debounce>> & _debounces)3417 void configuration_impl::load_events_debounce(
3418 const boost::property_tree::ptree &_tree,
3419 std::map<event_t, std::shared_ptr<debounce>> &_debounces) {
3420 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
3421 load_event_debounce(i->second, _debounces);
3422 }
3423 }
3424
load_event_debounce(const boost::property_tree::ptree & _tree,std::map<event_t,std::shared_ptr<debounce>> & _debounces)3425 void configuration_impl::load_event_debounce(
3426 const boost::property_tree::ptree &_tree,
3427 std::map<event_t, std::shared_ptr<debounce>> &_debounces) {
3428 event_t its_event(0);
3429 std::shared_ptr<debounce> its_debounce = std::make_shared<debounce>();
3430
3431 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
3432 std::string its_key(i->first);
3433 std::string its_value(i->second.data());
3434 std::stringstream its_converter;
3435
3436 if (its_key == "event") {
3437 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
3438 its_converter << std::hex << its_value;
3439 } else {
3440 its_converter << std::dec << its_value;
3441 }
3442 its_converter >> its_event;
3443 } else if (its_key == "on_change") {
3444 its_debounce->on_change_ = (its_value == "true");
3445 } else if (its_key == "on_change_resets_interval") {
3446 its_debounce->on_change_resets_interval_ = (its_value == "true");
3447 } else if (its_key == "ignore") {
3448 load_event_debounce_ignore(i->second, its_debounce->ignore_);
3449 } else if (its_key == "interval") {
3450 if (its_value == "never") {
3451 its_debounce->interval_ = -1;
3452 } else {
3453 its_converter << std::dec << its_value;
3454 its_converter >> its_debounce->interval_;
3455 }
3456 }
3457 }
3458
3459 // TODO: Improve error handling
3460 if (its_event > 0) {
3461 auto find_event = _debounces.find(its_event);
3462 if (find_event == _debounces.end()) {
3463 _debounces[its_event] = its_debounce;
3464 }
3465 }
3466 }
3467
load_event_debounce_ignore(const boost::property_tree::ptree & _tree,std::map<std::size_t,byte_t> & _ignore)3468 void configuration_impl::load_event_debounce_ignore(
3469 const boost::property_tree::ptree &_tree,
3470 std::map<std::size_t, byte_t> &_ignore) {
3471 std::size_t its_ignored;
3472 byte_t its_mask;
3473 std::stringstream its_converter;
3474
3475 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
3476 std::string its_value = i->second.data();
3477
3478 its_mask = 0xff;
3479
3480 if (!its_value.empty()
3481 && std::find_if(its_value.begin(), its_value.end(),
3482 [](char _c) { return !std::isdigit(_c); })
3483 == its_value.end()) {
3484 its_converter.str("");
3485 its_converter.clear();
3486 its_converter << std::dec << its_value;
3487 its_converter >> its_ignored;
3488
3489 } else {
3490 for (auto j = i->second.begin(); j != i->second.end(); ++j) {
3491 std::string its_ignore_key(j->first);
3492 std::string its_ignore_value(j->second.data());
3493
3494 if (its_ignore_key == "index") {
3495 its_converter.str("");
3496 its_converter.clear();
3497 its_converter << std::dec << its_ignore_value;
3498 its_converter >> its_ignored;
3499 } else if (its_ignore_key == "mask") {
3500 its_converter.str("");
3501 its_converter.clear();
3502
3503 int its_tmp_mask;
3504 its_converter << std::hex << its_ignore_value;
3505 its_converter >> its_tmp_mask;
3506
3507 its_mask = static_cast<byte_t>(its_tmp_mask);
3508 }
3509 }
3510 }
3511
3512 _ignore[its_ignored] = its_mask;
3513 }
3514 }
3515
3516 void
load_acceptances(const configuration_element & _element)3517 configuration_impl::load_acceptances(
3518 const configuration_element &_element) {
3519
3520 std::string its_acceptances_key("acceptances");
3521
3522 if (is_configured_[ET_SD_ACCEPTANCE_REQUIRED]) {
3523 VSOMEIP_WARNING << "Multiple definitions of " << its_acceptances_key
3524 << " Ignoring definition from " << _element.name_;
3525 return;
3526 }
3527
3528 try {
3529 auto its_acceptances = _element.tree_.get_child(its_acceptances_key);
3530 for (auto i = its_acceptances.begin(); i != its_acceptances.end(); ++i) {
3531 load_acceptance_data(i->second);
3532 }
3533
3534 is_configured_[ET_SD_ACCEPTANCE_REQUIRED] = true;
3535 } catch (...) {
3536 // Intentionally left empty
3537 }
3538 }
3539
3540 void
load_acceptance_data(const boost::property_tree::ptree & _tree)3541 configuration_impl::load_acceptance_data(
3542 const boost::property_tree::ptree &_tree) {
3543
3544 std::stringstream its_converter;
3545 try {
3546 std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
3547
3548 boost::asio::ip::address its_address;
3549 std::string its_path;
3550 std::map<bool,
3551 std::pair<boost::icl::interval_set<std::uint16_t>,
3552 boost::icl::interval_set<std::uint16_t>
3553 >
3554 > its_ports;
3555 bool has_optional, has_secure, is_reliable;
3556
3557 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
3558
3559 std::string its_key(i->first);
3560 std::string its_value(i->second.data());
3561
3562 if (its_key == "address") {
3563 boost::system::error_code ec;
3564 its_address = boost::asio::ip::address::from_string(its_value);
3565 } else if (its_key == "path") {
3566 its_path = its_value;
3567 } else if (its_key == "reliable" || its_key == "unreliable") {
3568
3569 is_reliable = (its_key == "reliable");
3570 has_optional = has_secure = false;
3571
3572 for (const auto &p : i->second) {
3573 if (p.second.size()) { // range
3574 std::uint16_t its_first(0);
3575 std::uint16_t its_last(0);
3576 port_type_e its_type(port_type_e::PT_OPTIONAL);
3577
3578 for (const auto& range : p.second) {
3579 const std::string its_key(range.first);
3580 const std::string its_value(range.second.data());
3581 if (its_key == "first" || its_key == "last" || its_key == "port") {
3582 its_converter << std::dec << its_value;
3583 std::uint16_t its_port_value(0);
3584 its_converter >> its_port_value;
3585 its_converter.str("");
3586 its_converter.clear();
3587 if (its_key == "first") {
3588 its_first = its_port_value;
3589 } else if (its_key == "last") {
3590 its_last = its_port_value;
3591 } else if (its_key == "port") {
3592 its_first = its_last = its_port_value;
3593 }
3594 } else if (its_key == "type") {
3595 if (its_value == "secure") {
3596 its_type = port_type_e::PT_SECURE;
3597 } else if (its_value == "optional") {
3598 its_type = port_type_e::PT_OPTIONAL;
3599 } else {
3600 its_type = port_type_e::PT_UNKNOWN;
3601 }
3602 }
3603 }
3604 if (its_type != port_type_e::PT_UNKNOWN) {
3605 if (its_type == port_type_e::PT_OPTIONAL) {
3606 has_optional = true;
3607 if (its_first != 0 && its_last != 0) {
3608 its_ports.operator [](is_reliable).first.insert(
3609 boost::icl::interval<std::uint16_t>::closed(its_first, its_last));
3610 }
3611 } else {
3612 has_secure = true;
3613 if (its_first != 0 && its_last != 0) {
3614 its_ports.operator [](is_reliable).second.insert(
3615 boost::icl::interval<std::uint16_t>::closed(its_first, its_last));
3616 }
3617 }
3618 }
3619 }
3620 }
3621
3622 // If optional was not set, use default!
3623 if (!has_optional) {
3624 const auto its_optional_client = boost::icl::interval<std::uint16_t>::closed(30491, 30499);
3625 const auto its_optional_client_spare = boost::icl::interval<std::uint16_t>::closed(30898, 30998);
3626 const auto its_optional_server = boost::icl::interval<std::uint16_t>::closed(30501, 30599);
3627
3628 its_ports.operator [](is_reliable).first.insert(its_optional_client);
3629 its_ports.operator [](is_reliable).first.insert(its_optional_client_spare);
3630 its_ports.operator [](is_reliable).first.insert(its_optional_server);
3631 }
3632
3633 // If secure was not set, use default!
3634 if (!has_secure) {
3635 const auto its_secure_client = boost::icl::interval<std::uint16_t>::closed(32491, 32499);
3636 const auto its_secure_client_spare = boost::icl::interval<std::uint16_t>::closed(32898, 32998);
3637 const auto its_secure_server = boost::icl::interval<std::uint16_t>::closed(32501, 32599);
3638
3639 its_ports.operator [](is_reliable).second.insert(its_secure_client);
3640 its_ports.operator [](is_reliable).second.insert(its_secure_client_spare);
3641 its_ports.operator [](is_reliable).second.insert(its_secure_server);
3642 }
3643 }
3644 }
3645
3646 // If no ports are specified, use default!
3647 if (its_ports.empty()) {
3648 const auto its_optional_client = boost::icl::interval<std::uint16_t>::closed(30491, 30499);
3649 const auto its_optional_client_spare = boost::icl::interval<std::uint16_t>::closed(30898, 30998);
3650 const auto its_optional_server = boost::icl::interval<std::uint16_t>::closed(30501, 30599);
3651
3652 // optional
3653 its_ports.operator [](false).first.insert(its_optional_client);
3654 its_ports.operator [](false).first.insert(its_optional_client_spare);
3655 its_ports.operator [](false).first.insert(its_optional_server);
3656 its_ports.operator [](true).first.insert(its_optional_client);
3657 its_ports.operator [](true).first.insert(its_optional_client_spare);
3658 its_ports.operator [](true).first.insert(its_optional_server);
3659
3660 // secure
3661 const auto its_secure_client = boost::icl::interval<std::uint16_t>::closed(32491, 32499);
3662 const auto its_secure_client_spare = boost::icl::interval<std::uint16_t>::closed(32898, 32998);
3663 const auto its_secure_server = boost::icl::interval<std::uint16_t>::closed(32501, 32599);
3664
3665 its_ports.operator [](false).second.insert(its_secure_client);
3666 its_ports.operator [](false).second.insert(its_secure_client_spare);
3667 its_ports.operator [](false).second.insert(its_secure_server);
3668 its_ports.operator [](true).second.insert(its_secure_client);
3669 its_ports.operator [](true).second.insert(its_secure_client_spare);
3670 its_ports.operator [](true).second.insert(its_secure_server);
3671 }
3672
3673 if (!its_address.is_unspecified()) {
3674 sd_acceptance_rules_.insert(
3675 std::make_pair(its_address,
3676 std::make_pair(its_path, its_ports)));
3677 }
3678 } catch (...) {
3679 // intentionally left empty
3680 }
3681 }
3682
load_npdu_debounce_times_configuration(const std::shared_ptr<service> & _service,const boost::property_tree::ptree & _tree)3683 bool configuration_impl::load_npdu_debounce_times_configuration(
3684 const std::shared_ptr<service>& _service,
3685 const boost::property_tree::ptree &_tree) {
3686 bool is_loaded(true);
3687 try {
3688 for (const auto& i : _tree) {
3689 const std::string its_key(i.first);
3690 if (its_key == "requests") {
3691 if (!load_npdu_debounce_times_for_service(_service, true, i.second)) {
3692 is_loaded = false;
3693 }
3694 } else if (its_key == "responses") {
3695 if (!load_npdu_debounce_times_for_service(_service, false, i.second)) {
3696 is_loaded = false;
3697 }
3698 }
3699 }
3700 } catch (...) {
3701 is_loaded = false;
3702 }
3703 return is_loaded;
3704 }
3705
load_npdu_debounce_times_for_service(const std::shared_ptr<service> & _service,bool _is_request,const boost::property_tree::ptree & _tree)3706 bool configuration_impl::load_npdu_debounce_times_for_service(
3707 const std::shared_ptr<service>& _service, bool _is_request,
3708 const boost::property_tree::ptree &_tree) {
3709 const std::string dtime("debounce-time");
3710 const std::string rtime("maximum-retention-time");
3711
3712 bool is_loaded(true);
3713 try {
3714 std::stringstream its_converter;
3715 for (const auto& i : _tree) {
3716 const std::string its_method_str(i.first.data());
3717 if (its_method_str.size()) {
3718 method_t its_method = 0xFFFF;
3719 if (its_method_str.size() > 1 && its_method_str[0] == '0'
3720 && its_method_str[1] == 'x') {
3721 its_converter << std::hex << its_method_str;
3722 } else {
3723 its_converter << std::dec << its_method_str;
3724 }
3725 its_converter >> its_method;
3726 its_converter.str("");
3727 its_converter.clear();
3728
3729 std::chrono::nanoseconds its_debounce_time(
3730 npdu_default_debounce_requ_);
3731 std::chrono::nanoseconds its_retention_time(
3732 npdu_default_max_retention_requ_);
3733 for (const auto& j : i.second) {
3734 const std::string& key = j.first;
3735 const std::uint64_t value = std::strtoull(
3736 j.second.data().c_str(),
3737 NULL, 10) * 1000000;
3738 if (key == dtime) {
3739 its_debounce_time = std::chrono::nanoseconds(value);
3740 } else if (key == rtime) {
3741 its_retention_time = std::chrono::nanoseconds(value);
3742 }
3743 }
3744 if (_is_request) {
3745 _service->debounce_times_requests_[its_method]
3746 = {its_debounce_time, its_retention_time};
3747 } else {
3748 _service->debounce_times_responses_[its_method]
3749 = { its_debounce_time, its_retention_time};
3750 }
3751 }
3752 }
3753 } catch (...) {
3754 is_loaded = false;
3755 }
3756 return is_loaded;
3757 }
3758
load_someip_tp(const std::shared_ptr<service> & _service,const boost::property_tree::ptree & _tree)3759 void configuration_impl::load_someip_tp(
3760 const std::shared_ptr<service>& _service,
3761 const boost::property_tree::ptree &_tree) {
3762 try {
3763 for (const auto& i : _tree) {
3764 const std::string its_key(i.first);
3765 if (its_key == "client-to-service") {
3766 load_someip_tp_for_service(_service, i.second, true);
3767 } else if (its_key == "service-to-client") {
3768 load_someip_tp_for_service(_service, i.second, false);
3769 }
3770 }
3771 } catch (...) {
3772 // intentionally left empty
3773 }
3774 }
3775
load_someip_tp_for_service(const std::shared_ptr<service> & _service,const boost::property_tree::ptree & _tree,bool _is_request)3776 void configuration_impl::load_someip_tp_for_service(
3777 const std::shared_ptr<service>& _service,
3778 const boost::property_tree::ptree &_tree, bool _is_request) {
3779 try {
3780 std::stringstream its_converter;
3781 for (const auto& method : _tree) {
3782 method_t its_method = 0xFFFF;
3783 const std::string its_value(method.second.data());
3784 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
3785 its_converter << std::hex << its_value;
3786 } else {
3787 its_converter << std::dec << its_value;
3788 }
3789 its_converter >> its_method;
3790 its_converter.str("");
3791 its_converter.clear();
3792 if (_is_request) {
3793 _service->tp_segment_messages_client_to_service_.insert(its_method);
3794 } else {
3795 _service->tp_segment_messages_service_to_client_.insert(its_method);
3796 }
3797 }
3798 } catch (...) {
3799 // intentionally left empty
3800 }
3801 }
3802
3803 void
load_udp_receive_buffer_size(const configuration_element & _element)3804 configuration_impl::load_udp_receive_buffer_size(const configuration_element &_element) {
3805 const std::string urbs("udp-receive-buffer-size");
3806 try {
3807 if (_element.tree_.get_child_optional(urbs)) {
3808 if (is_configured_[ET_UDP_RECEIVE_BUFFER_SIZE]) {
3809 VSOMEIP_WARNING << "Multiple definitions of " << urbs
3810 << " Ignoring definition from " << _element.name_;
3811 } else {
3812 const std::string s(_element.tree_.get_child(urbs).data());
3813 try {
3814 udp_receive_buffer_size_ = std::stoi(s.c_str(), NULL, 10);
3815 } catch (const std::exception &e) {
3816 VSOMEIP_ERROR<< __func__ << ": " << urbs << " " << e.what();
3817 }
3818 is_configured_[ET_UDP_RECEIVE_BUFFER_SIZE] = true;
3819 }
3820 }
3821 } catch (...) {
3822 // intentionally left empty
3823 }
3824 }
3825
load_secure_services(const configuration_element & _element)3826 void configuration_impl::load_secure_services(const configuration_element &_element) {
3827 std::lock_guard<std::mutex> its_lock(secure_services_mutex_);
3828 try {
3829 auto its_services = _element.tree_.get_child("secure-services");
3830 for (auto i = its_services.begin(); i != its_services.end(); ++i)
3831 load_secure_service(i->second);
3832 } catch (...) {
3833 // intentionally left empty
3834 }
3835 }
3836
load_secure_service(const boost::property_tree::ptree & _tree)3837 void configuration_impl::load_secure_service(const boost::property_tree::ptree &_tree) {
3838 try {
3839 service_t its_service(0);
3840 instance_t its_instance(0);
3841
3842 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
3843 std::string its_key(i->first);
3844 std::string its_value(i->second.data());
3845 std::stringstream its_converter;
3846
3847 // Trim "its_value"
3848 if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
3849 its_converter << std::hex << its_value;
3850 } else {
3851 its_converter << std::dec << its_value;
3852 }
3853
3854 if (its_key == "service") {
3855 its_converter >> its_service;
3856 } else if (its_key == "instance") {
3857 its_converter >> its_instance;
3858 }
3859 }
3860
3861 if (its_service != 0 && its_instance != 0) {
3862 auto find_service = secure_services_.find(its_service);
3863 if (find_service != secure_services_.end()) {
3864 find_service->second.insert(its_instance);
3865 } else {
3866 secure_services_[its_service].insert(its_instance);
3867 }
3868 }
3869
3870 } catch (...) {
3871 // Intentionally left empty
3872 }
3873 }
3874
get_debounce(service_t _service,instance_t _instance,event_t _event) const3875 std::shared_ptr<debounce> configuration_impl::get_debounce(
3876 service_t _service, instance_t _instance, event_t _event) const {
3877 auto found_service = debounces_.find(_service);
3878 if (found_service != debounces_.end()) {
3879 auto found_instance = found_service->second.find(_instance);
3880 if (found_instance != found_service->second.end()) {
3881 auto found_event = found_instance->second.find(_event);
3882 if (found_event != found_instance->second.end()) {
3883 return found_event->second;
3884 }
3885 }
3886 }
3887 return nullptr;
3888 }
3889
3890 void
load_tcp_restart_settings(const configuration_element & _element)3891 configuration_impl::load_tcp_restart_settings(const configuration_element &_element) {
3892 const std::string tcp_restart_aborts_max("tcp-restart-aborts-max");
3893 const std::string tcp_connect_time_max("tcp-connect-time-max");
3894
3895 try {
3896 if (_element.tree_.get_child_optional(tcp_restart_aborts_max)) {
3897 if (is_configured_[ET_TCP_RESTART_ABORTS_MAX]) {
3898 VSOMEIP_WARNING << "Multiple definitions for "
3899 << tcp_restart_aborts_max
3900 << " Ignoring definition from " << _element.name_;
3901 } else {
3902 is_configured_[ET_TCP_RESTART_ABORTS_MAX] = true;
3903 auto mpsl = _element.tree_.get_child(
3904 tcp_restart_aborts_max);
3905 std::string s(mpsl.data());
3906 try {
3907 tcp_restart_aborts_max_ =
3908 static_cast<std::uint32_t>(std::stoul(
3909 s.c_str(), NULL, 10));
3910 } catch (const std::exception &e) {
3911 VSOMEIP_ERROR<<__func__ << ": " << tcp_restart_aborts_max
3912 << " " << e.what();
3913 }
3914 }
3915 }
3916 if (_element.tree_.get_child_optional(tcp_connect_time_max)) {
3917 if (is_configured_[ET_TCP_CONNECT_TIME_MAX]) {
3918 VSOMEIP_WARNING << "Multiple definitions for "
3919 << tcp_connect_time_max
3920 << " Ignoring definition from " << _element.name_;
3921 } else {
3922 is_configured_[ET_TCP_CONNECT_TIME_MAX] = true;
3923 auto mpsl = _element.tree_.get_child(tcp_connect_time_max);
3924 std::string s(mpsl.data());
3925 try {
3926 tcp_connect_time_max_=
3927 static_cast<std::uint32_t>(
3928 std::stoul(s.c_str(), NULL, 10));
3929 } catch (const std::exception &e) {
3930 VSOMEIP_ERROR<< __func__ << ": "<< tcp_connect_time_max
3931 << " " << e.what();
3932 }
3933 }
3934 }
3935 } catch (...) {
3936 }
3937 }
3938
get_max_tcp_restart_aborts() const3939 std::uint32_t configuration_impl::get_max_tcp_restart_aborts() const {
3940 return tcp_restart_aborts_max_;
3941 }
3942
get_max_tcp_connect_time() const3943 std::uint32_t configuration_impl::get_max_tcp_connect_time() const {
3944 return tcp_connect_time_max_;
3945 }
3946
is_protected_device(const boost::asio::ip::address & _address) const3947 bool configuration_impl::is_protected_device(
3948 const boost::asio::ip::address& _address) const {
3949 std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
3950 return (sd_acceptance_rules_active_.find(_address)
3951 != sd_acceptance_rules_active_.end());
3952 }
3953
is_protected_port(const boost::asio::ip::address & _address,std::uint16_t _port,bool _reliable) const3954 bool configuration_impl::is_protected_port(
3955 const boost::asio::ip::address& _address, std::uint16_t _port,
3956 bool _reliable) const {
3957
3958 bool is_required(is_protected_device(_address));
3959
3960 std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
3961 const auto found_address = sd_acceptance_rules_.find(_address);
3962 if (found_address != sd_acceptance_rules_.end()) {
3963 const auto found_reliability = found_address->second.second.find(_reliable);
3964 if (found_reliability != found_address->second.second.end()) {
3965 const auto its_range = boost::icl::interval<std::uint16_t>::closed(_port, _port);
3966
3967 bool is_optional
3968 = (found_reliability->second.first.find(its_range)
3969 != found_reliability->second.first.end());
3970
3971 bool is_secure
3972 = (found_reliability->second.second.find(its_range)
3973 != found_reliability->second.second.end());
3974
3975 is_required = ((is_required && is_optional) || is_secure);
3976 }
3977 }
3978
3979 return (is_required);
3980 }
3981
is_secure_port(const boost::asio::ip::address & _address,std::uint16_t _port,bool _reliable) const3982 bool configuration_impl::is_secure_port(
3983 const boost::asio::ip::address& _address, std::uint16_t _port,
3984 bool _reliable) const {
3985
3986 bool is_secure(false);
3987
3988 std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
3989 const auto found_address = sd_acceptance_rules_.find(_address);
3990 if (found_address != sd_acceptance_rules_.end()) {
3991 const auto found_reliability
3992 = found_address->second.second.find(_reliable);
3993 if (found_reliability != found_address->second.second.end()) {
3994 const auto its_range
3995 = boost::icl::interval<std::uint16_t>::closed(_port, _port);
3996 return (found_reliability->second.second.find(its_range)
3997 != found_reliability->second.second.end());
3998 }
3999 }
4000
4001 return (is_secure);
4002 }
4003
set_sd_acceptance_rule(const boost::asio::ip::address & _address,port_range_t _port_range,port_type_e _type,const std::string & _path,bool _reliable,bool _enable,bool _default)4004 void configuration_impl::set_sd_acceptance_rule(
4005 const boost::asio::ip::address &_address,
4006 port_range_t _port_range, port_type_e _type,
4007 const std::string &_path, bool _reliable, bool _enable, bool _default) {
4008
4009 (void)_port_range;
4010 (void)_type;
4011
4012 std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
4013
4014 const auto its_optional_client = boost::icl::interval<std::uint16_t>::closed(30491, 30499);
4015 const auto its_optional_client_spare = boost::icl::interval<std::uint16_t>::closed(30898, 30998);
4016 const auto its_optional_server = boost::icl::interval<std::uint16_t>::closed(30501, 30599);
4017
4018 const auto its_secure_client = boost::icl::interval<std::uint16_t>::closed(32491, 32499);
4019 const auto its_secure_client_spare = boost::icl::interval<std::uint16_t>::closed(32898, 32998);
4020 const auto its_secure_server = boost::icl::interval<std::uint16_t>::closed(32501, 32599);
4021
4022 const bool rules_active = (sd_acceptance_rules_active_.find(_address)
4023 != sd_acceptance_rules_active_.end());
4024
4025 const auto found_address = sd_acceptance_rules_.find(_address);
4026 if (found_address != sd_acceptance_rules_.end()) {
4027 if (found_address->second.first.length() > 0
4028 && found_address->second.first != _path) {
4029 VSOMEIP_WARNING << __func__ << ": activation path for IP: "
4030 << _address << " differ: "
4031 << found_address->second.first << " vs. " << _path
4032 << " will use: " << found_address->second.first;
4033 } else {
4034 found_address->second.first = _path;
4035 }
4036 const auto found_reliability = found_address->second.second.find(_reliable);
4037 if (found_reliability != found_address->second.second.end()) {
4038 if (_enable) {
4039 // only insert full range interval if there are no other intervals
4040 // configured
4041 if (!_default ||
4042 (found_reliability->second.first.empty()
4043 && found_reliability->second.second.empty())) {
4044 found_reliability->second.first.add(its_optional_client);
4045 found_reliability->second.first.add(its_optional_client_spare);
4046 found_reliability->second.first.add(its_optional_server);
4047 found_reliability->second.second.add(its_secure_client);
4048 found_reliability->second.second.add(its_secure_client_spare);
4049 found_reliability->second.second.add(its_secure_server);
4050 if (!rules_active) {
4051 sd_acceptance_rules_active_.insert(_address);
4052 }
4053 VSOMEIP_INFO << "ipsec:acceptance:" << _address
4054 << ":" << (_reliable ? "tcp" : "udp") << ": using default ranges "
4055 << found_reliability->second.first << " "
4056 << found_reliability->second.second;
4057 } else {
4058 VSOMEIP_INFO << "ipsec:acceptance:" << _address
4059 << ":" << (_reliable ? "tcp" : "udp") << ": using configured ranges "
4060 << found_reliability->second.first << " "
4061 << found_reliability->second.second;
4062 }
4063 } else {
4064 found_reliability->second.first.erase(its_optional_client);
4065 found_reliability->second.first.erase(its_optional_client_spare);
4066 found_reliability->second.first.erase(its_optional_server);
4067 found_reliability->second.second.erase(its_secure_client);
4068 found_reliability->second.second.erase(its_secure_client_spare);
4069 found_reliability->second.second.erase(its_secure_server);
4070 if (found_reliability->second.first.empty()
4071 && found_reliability->second.second.empty()) {
4072 found_address->second.second.erase(found_reliability);
4073 if (found_address->second.second.empty()) {
4074 sd_acceptance_rules_.erase(found_address);
4075 if (rules_active) {// no more rules for IP present
4076 sd_acceptance_rules_active_.erase(_address);
4077 }
4078 }
4079 }
4080 }
4081 } else if (_enable) {
4082 boost::icl::interval_set<std::uint16_t> its_optional_default;
4083 its_optional_default.add(its_optional_client);
4084 its_optional_default.add(its_optional_client_spare);
4085 its_optional_default.add(its_optional_server);
4086 boost::icl::interval_set<std::uint16_t> its_secure_default;
4087 its_secure_default.add(its_secure_client);
4088 its_secure_default.add(its_secure_client_spare);
4089 its_secure_default.add(its_secure_server);
4090
4091 found_address->second.second.emplace(
4092 std::make_pair(_reliable,
4093 std::make_pair(its_optional_default, its_secure_default)));
4094 if (!rules_active) {
4095 sd_acceptance_rules_active_.insert(_address);
4096 }
4097
4098 const auto found_reliability = found_address->second.second.find(_reliable);
4099 VSOMEIP_INFO << "ipsec:acceptance:" << _address
4100 << ":" << (_reliable ? "tcp" : "udp") << ": using default ranges "
4101 << found_reliability->second.first << " "
4102 << found_reliability->second.second;
4103 }
4104 } else if (_enable) {
4105 boost::icl::interval_set<std::uint16_t> its_optional_default;
4106 its_optional_default.add(its_optional_client);
4107 its_optional_default.add(its_optional_client_spare);
4108 its_optional_default.add(its_optional_server);
4109 boost::icl::interval_set<std::uint16_t> its_secure_default;
4110 its_secure_default.add(its_secure_client);
4111 its_secure_default.add(its_secure_client_spare);
4112 its_secure_default.add(its_secure_server);
4113
4114 sd_acceptance_rules_.emplace(std::make_pair(_address,
4115 std::make_pair(
4116 _path,
4117 std::map<
4118 bool,
4119 std::pair<
4120 boost::icl::interval_set<std::uint16_t>,
4121 boost::icl::interval_set<std::uint16_t>
4122 >
4123 >({{
4124 _reliable,
4125 std::make_pair(its_optional_default, its_secure_default)
4126 }}))));
4127 if (!rules_active) {
4128 sd_acceptance_rules_active_.insert(_address);
4129 }
4130
4131 const auto found_address = sd_acceptance_rules_.find(_address);
4132 if (found_address != sd_acceptance_rules_.end()) {
4133 const auto found_reliability = found_address->second.second.find(_reliable);
4134 if (found_reliability != found_address->second.second.end()) {
4135 VSOMEIP_INFO << "ipsec:acceptance:" << _address
4136 << ":" << (_reliable ? "tcp" : "udp") << ": using default ranges "
4137 << found_reliability->second.first << " "
4138 << found_reliability->second.second;
4139 }
4140 }
4141 }
4142 }
4143
set_sd_acceptance_rules(const sd_acceptance_rules_t & _rules,bool _enable)4144 void configuration_impl::set_sd_acceptance_rules(
4145 const sd_acceptance_rules_t& _rules, bool _enable) {
4146 // Unused, only still available to preserve compatibility
4147 (void)_rules;
4148 (void)_enable;
4149 }
4150
get_sd_acceptance_rules()4151 configuration::sd_acceptance_rules_t configuration_impl::get_sd_acceptance_rules() {
4152 std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
4153 return sd_acceptance_rules_;
4154 }
4155
set_sd_acceptance_rules_active(const boost::asio::ip::address & _address,bool _enable)4156 void configuration_impl::set_sd_acceptance_rules_active(
4157 const boost::asio::ip::address& _address, bool _enable) {
4158 if (_enable) {
4159 sd_acceptance_rules_active_.insert(_address);
4160 } else {
4161 sd_acceptance_rules_active_.erase(_address);
4162 }
4163 }
4164
is_secure_service(service_t _service,instance_t _instance) const4165 bool configuration_impl::is_secure_service(service_t _service, instance_t _instance) const {
4166 std::lock_guard<std::mutex> its_lock(secure_services_mutex_);
4167 const auto its_service = secure_services_.find(_service);
4168 if (its_service != secure_services_.end())
4169 return (its_service->second.find(_instance) != its_service->second.end());
4170 return (false);
4171 }
4172
get_udp_receive_buffer_size() const4173 int configuration_impl::get_udp_receive_buffer_size() const {
4174 return udp_receive_buffer_size_;
4175 }
4176
tp_segment_messages_client_to_service(service_t _service,std::string _ip_target,std::uint16_t _port_target,method_t _method) const4177 bool configuration_impl::tp_segment_messages_client_to_service(
4178 service_t _service, std::string _ip_target, std::uint16_t _port_target,
4179 method_t _method) const {
4180 bool ret(false);
4181 const service* const its_service = find_service_by_ip_port(_service,
4182 _ip_target, _port_target);
4183 if (its_service) {
4184 ret = (its_service->tp_segment_messages_client_to_service_.find(_method)
4185 != its_service->tp_segment_messages_client_to_service_.end());
4186 }
4187 return ret;
4188 }
4189
tp_segment_messages_service_to_client(service_t _service,std::string _ip_service,std::uint16_t _port_service,method_t _method) const4190 bool configuration_impl::tp_segment_messages_service_to_client(
4191 service_t _service, std::string _ip_service,
4192 std::uint16_t _port_service, method_t _method) const {
4193 bool ret(false);
4194 const service* const its_service = find_service_by_ip_port(_service,
4195 _ip_service, _port_service);
4196 if (its_service) {
4197 ret = (its_service->tp_segment_messages_service_to_client_.find(_method)
4198 != its_service->tp_segment_messages_service_to_client_.end());
4199 }
4200 return ret;
4201 }
4202
4203 #ifdef VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
4204 bool
has_overlay(const std::string & _name) const4205 configuration_impl::has_overlay(const std::string &_name) const {
4206 auto its_application = applications_.find(_name);
4207 return (its_application != applications_.end()
4208 && !std::get<7>(its_application->second).empty());
4209 }
4210
4211 void
load_overlay(const std::string & _name)4212 configuration_impl::load_overlay(const std::string &_name) {
4213 std::set<std::string> its_input;
4214 std::vector<configuration_element> its_elements;
4215 std::set<std::string> its_failed;
4216
4217 auto its_application = applications_.find(_name);
4218 if (its_application != applications_.end()) {
4219 std::string its_overlay(std::get<7>(its_application->second));
4220
4221 its_input.insert(its_overlay);
4222 read_data(its_input, its_elements, its_failed, false);
4223
4224 for (const auto& f : its_failed)
4225 VSOMEIP_ERROR << "Reading configuration data from " << f << " failed!";
4226
4227 is_overlay_ = true;
4228 load_data(its_elements, true, true);
4229 }
4230 }
4231 #endif // VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
4232
get_shutdown_timeout() const4233 std::uint32_t configuration_impl::get_shutdown_timeout() const {
4234 return shutdown_timeout_;
4235 }
4236
log_statistics() const4237 bool configuration_impl::log_statistics() const {
4238 return log_statistics_;
4239 }
4240
get_statistics_interval() const4241 uint32_t configuration_impl::get_statistics_interval() const {
4242 return statistics_interval_;
4243 }
4244
get_statistics_min_freq() const4245 uint32_t configuration_impl::get_statistics_min_freq() const {
4246 return statistics_min_freq_;
4247 }
4248
get_statistics_max_messages() const4249 uint32_t configuration_impl::get_statistics_max_messages() const {
4250 return statistics_max_messages_;
4251 }
4252
get_max_remote_subscribers() const4253 uint8_t configuration_impl::get_max_remote_subscribers() const {
4254 return max_remote_subscribers_;
4255 }
4256
4257 partition_id_t
get_partition_id(service_t _service,instance_t _instance) const4258 configuration_impl::get_partition_id(
4259 service_t _service, instance_t _instance) const {
4260
4261 partition_id_t its_id(VSOMEIP_DEFAULT_PARTITION_ID);
4262
4263 std::lock_guard<std::mutex> its_lock(partitions_mutex_);
4264 auto find_service = partitions_.find(_service);
4265 if (find_service != partitions_.end()) {
4266 auto find_instance = find_service->second.find(_instance);
4267 if (find_instance != find_service->second.end()) {
4268 its_id = find_instance->second;
4269 }
4270 }
4271
4272 return (its_id);
4273 }
4274
4275 } // namespace cfg
4276 } // namespace vsomeip_v3
4277