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