diff options
Diffstat (limited to 'implementation/configuration/src/configuration_impl.cpp')
-rw-r--r-- | implementation/configuration/src/configuration_impl.cpp | 907 |
1 files changed, 746 insertions, 161 deletions
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp index 66a1219..3c78de0 100644 --- a/implementation/configuration/src/configuration_impl.cpp +++ b/implementation/configuration/src/configuration_impl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -9,10 +9,6 @@ #define WIN32_LEAN_AND_MEAN -#if defined ( WIN32 ) -#define __func__ __FUNCTION__ -#endif - #include <boost/algorithm/string.hpp> #include <boost/filesystem.hpp> #include <boost/foreach.hpp> @@ -20,6 +16,7 @@ #include <vsomeip/constants.hpp> +#include "../include/client.hpp" #include "../include/configuration_impl.hpp" #include "../include/event.hpp" #include "../include/eventgroup.hpp" @@ -41,9 +38,12 @@ std::shared_ptr<configuration> configuration_impl::get( std::shared_ptr<configuration> its_configuration; std::lock_guard<std::mutex> its_lock(mutex_); + std::set<std::string> failed_files; + static bool has_reading_failed(false); + if (!the_configuration) { the_configuration = std::make_shared<configuration_impl>(); - std::vector<boost::property_tree::ptree> its_tree_set; + std::vector<element> its_configuration_elements; // Load logger configuration first for (auto i : _input) { @@ -51,9 +51,13 @@ std::shared_ptr<configuration> configuration_impl::get( boost::property_tree::ptree its_tree; try { boost::property_tree::json_parser::read_json(i, its_tree); - its_tree_set.push_back(its_tree); + its_configuration_elements.push_back({ i, its_tree }); } - catch (...) { + catch (boost::property_tree::json_parser_error &e) { +#ifdef WIN32 + e; // silence MSVC warining C4101 +#endif + failed_files.insert(i); } } else if (utility::is_folder(i)) { boost::filesystem::path its_path(i); @@ -66,9 +70,10 @@ std::shared_ptr<configuration> configuration_impl::get( boost::property_tree::ptree its_tree; try { boost::property_tree::json_parser::read_json(its_name, its_tree); - its_tree_set.push_back(its_tree); + its_configuration_elements.push_back({its_name, its_tree}); } catch (...) { + failed_files.insert(its_name); } } } @@ -76,13 +81,28 @@ std::shared_ptr<configuration> configuration_impl::get( } // Load log configuration - the_configuration->load_log(its_tree_set); - - // Load other configuration parts - for (auto t : its_tree_set) - the_configuration->load(t); + the_configuration->load_log(its_configuration_elements); + + // Check whether reading of configuration file(s) succeeded. + if (!failed_files.empty()) { + has_reading_failed = true; + for (auto its_failed : failed_files) + VSOMEIP_ERROR << "Reading of configuration file \"" + << its_failed << "\" failed."; + } else { + // Load other configuration parts + std::sort(its_configuration_elements.begin(), + its_configuration_elements.end()); + for (auto e : its_configuration_elements) + the_configuration->load(e); + } } + // There is only one attempt to read the configuration file(s). + // If it has failed, we must not return the configuration object. + if (has_reading_failed) + return nullptr; + return the_configuration; } @@ -91,6 +111,7 @@ void configuration_impl::reset() { } configuration_impl::configuration_impl() : + diagnosis_(VSOMEIP_DIAGNOSIS_ADDRESS), has_console_log_(true), has_file_log_(false), has_dlt_log_(false), @@ -107,18 +128,26 @@ configuration_impl::configuration_impl() : sd_ttl_(VSOMEIP_SD_DEFAULT_TTL), sd_cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY), sd_request_response_delay_(VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY), - max_configured_message_size_(0) { - + max_configured_message_size_(0), + trace_(std::make_shared<trace>()), + watchdog_(std::make_shared<watchdog>()), + permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION), + umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) { unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS); + for (auto i = 0; i < ET_MAX; i++) + is_configured_[i] = false; } configuration_impl::configuration_impl(const configuration_impl &_other) : - max_configured_message_size_(0) { + max_configured_message_size_(0), + permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION), + umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) { applications_.insert(_other.applications_.begin(), _other.applications_.end()); services_.insert(_other.services_.begin(), _other.services_.end()); unicast_ = _other.unicast_; + diagnosis_ = _other.diagnosis_; has_console_log_ = _other.has_console_log_; has_file_log_ = _other.has_file_log_; @@ -142,72 +171,116 @@ configuration_impl::configuration_impl(const configuration_impl &_other) : sd_cyclic_offer_delay_= _other.sd_cyclic_offer_delay_; sd_request_response_delay_= _other.sd_request_response_delay_; + trace_ = std::make_shared<trace>(*_other.trace_.get()); + watchdog_ = std::make_shared<watchdog>(*_other.watchdog_.get()); + magic_cookies_.insert(_other.magic_cookies_.begin(), _other.magic_cookies_.end()); + + for (auto i = 0; i < ET_MAX; i++) + is_configured_[i] = _other.is_configured_[i]; } configuration_impl::~configuration_impl() { } -void configuration_impl::load(const boost::property_tree::ptree &_tree) { +void configuration_impl::load(const element &_element) { try { // Read the configuration data - get_someip_configuration(_tree); - get_services_configuration(_tree); - get_payload_sizes_configuration(_tree); - get_routing_configuration(_tree); - get_service_discovery_configuration(_tree); - get_applications_configuration(_tree); + get_someip_configuration(_element); + get_services_configuration(_element.tree_); + get_clients_configuration(_element.tree_); + get_payload_sizes_configuration(_element.tree_); + get_routing_configuration(_element); + get_permission_configuration(_element); + get_service_discovery_configuration(_element); + get_applications_configuration(_element); + get_trace_configuration(_element); + get_supports_selective_broadcasts(_element.tree_); + get_watchdog_configuration(_element); } catch (std::exception &e) { +#ifdef WIN32 + e; // silence MSVC warning C4101 +#endif } } -void configuration_impl::load_log(const std::vector<boost::property_tree::ptree> &_trees) { +void configuration_impl::load_log(const std::vector<element> &_elements) { + std::set<std::string> its_warnings; + // Read the logger configuration(s) - for (auto t : _trees) - get_logging_configuration(t); + for (auto e : _elements) + get_logging_configuration(e, its_warnings); // Initialize logger logger_impl::init(the_configuration); + + // Print warnings after(!) logger initialization + for (auto w : its_warnings) + VSOMEIP_WARNING << w; } void configuration_impl::get_logging_configuration( - const boost::property_tree::ptree &_tree) { + const element &_element, std::set<std::string> &_warnings) { try { - auto its_logging = _tree.get_child("logging"); + auto its_logging = _element.tree_.get_child("logging"); for (auto i = its_logging.begin(); i != its_logging.end(); ++i) { std::string its_key(i->first); if (its_key == "console") { - std::string its_value(i->second.data()); - has_console_log_ = (its_value == "true"); + if (is_configured_[ET_LOGGING_CONSOLE]) { + _warnings.insert("Multiple definitions for logging.console." + " Ignoring definition from " + _element.name_); + } else { + std::string its_value(i->second.data()); + has_console_log_ = (its_value == "true"); + is_configured_[ET_LOGGING_CONSOLE] = true; + } } else if (its_key == "file") { - for (auto j : i->second) { - std::string its_sub_key(j.first); - std::string its_sub_value(j.second.data()); - if (its_sub_key == "enable") { - has_file_log_ = (its_sub_value == "true"); - } else if (its_sub_key == "path") { - logfile_ = its_sub_value; + if (is_configured_[ET_LOGGING_FILE]) { + _warnings.insert("Multiple definitions for logging.file." + " Ignoring definition from " + _element.name_); + } else { + for (auto j : i->second) { + std::string its_sub_key(j.first); + std::string its_sub_value(j.second.data()); + if (its_sub_key == "enable") { + has_file_log_ = (its_sub_value == "true"); + } else if (its_sub_key == "path") { + logfile_ = its_sub_value; + } } + is_configured_[ET_LOGGING_FILE] = true; } } else if (its_key == "dlt") { - std::string its_value(i->second.data()); - has_dlt_log_ = (its_value == "true"); + if (is_configured_[ET_LOGGING_DLT]) { + _warnings.insert("Multiple definitions for logging.dlt." + " Ignoring definition from " + _element.name_); + } else { + std::string its_value(i->second.data()); + has_dlt_log_ = (its_value == "true"); + is_configured_[ET_LOGGING_DLT] = true; + } } else if (its_key == "level") { - std::string its_value(i->second.data()); - loglevel_ - = (its_value == "trace" ? - boost::log::trivial::severity_level::trace : - (its_value == "debug" ? - boost::log::trivial::severity_level::debug : - (its_value == "info" ? - boost::log::trivial::severity_level::info : - (its_value == "warning" ? - boost::log::trivial::severity_level::warning : - (its_value == "error" ? - boost::log::trivial::severity_level::error : - (its_value == "fatal" ? - boost::log::trivial::severity_level::fatal : - boost::log::trivial::severity_level::info)))))); + if (is_configured_[ET_LOGGING_LEVEL]) { + _warnings.insert("Multiple definitions for logging.level." + " Ignoring definition from " + _element.name_); + } else { + std::string its_value(i->second.data()); + loglevel_ + = (its_value == "trace" ? + boost::log::trivial::severity_level::trace : + (its_value == "debug" ? + boost::log::trivial::severity_level::debug : + (its_value == "info" ? + boost::log::trivial::severity_level::info : + (its_value == "warning" ? + boost::log::trivial::severity_level::warning : + (its_value == "error" ? + boost::log::trivial::severity_level::error : + (its_value == "fatal" ? + boost::log::trivial::severity_level::fatal : + boost::log::trivial::severity_level::info)))))); + is_configured_[ET_LOGGING_LEVEL] = true; + } } } } catch (...) { @@ -215,10 +288,34 @@ void configuration_impl::get_logging_configuration( } void configuration_impl::get_someip_configuration( - const boost::property_tree::ptree &_tree) { + const element &_element) { + try { + if (is_configured_[ET_UNICAST]) { + VSOMEIP_WARNING << "Multiple definitions for unicast." + "Ignoring definition from " << _element.name_; + } else { + std::string its_value = _element.tree_.get<std::string>("unicast"); + unicast_ = unicast_.from_string(its_value); + is_configured_[ET_UNICAST] = true; + } + } catch (...) { + } try { - std::string its_value = _tree.get<std::string>("unicast"); - unicast_ = unicast_.from_string(its_value); + if (is_configured_[ET_DIAGNOSIS]) { + VSOMEIP_WARNING << "Multiple definitions for diagnosis." + "Ignoring definition from " << _element.name_; + } else { + std::string its_value = _element.tree_.get<std::string>("diagnosis"); + std::stringstream its_converter; + + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { + its_converter << std::hex << its_value; + } else { + its_converter << std::dec << its_value; + } + its_converter >> diagnosis_; + is_configured_[ET_DIAGNOSIS] = true; + } } catch (...) { } } @@ -240,6 +337,17 @@ void configuration_impl::get_services_configuration( } } +void configuration_impl::get_clients_configuration( + const boost::property_tree::ptree &_tree) { + try { + auto its_clients = _tree.get_child("clients"); + for (auto i = its_clients.begin(); i != its_clients.end(); ++i) + get_client_configuration(i->second); + } catch (...) { + // intentionally left empty! + } +} + void configuration_impl::get_payload_sizes_configuration( const boost::property_tree::ptree &_tree) { const std::string payload_sizes("payload-sizes"); @@ -364,7 +472,6 @@ void configuration_impl::get_service_configuration( its_service->unicast_address_ = _unicast_address; its_service->multicast_address_ = ""; its_service->multicast_port_ = ILLEGAL_PORT; - its_service->multicast_group_ = 0xFFFF; // TODO: use symbolic constant its_service->protocol_ = "someip"; for (auto i = _tree.begin(); i != _tree.end(); ++i) { @@ -383,6 +490,9 @@ void configuration_impl::get_service_configuration( its_converter << its_value; its_converter >> its_service->reliable_; } + if(!its_service->reliable_) { + its_service->reliable_ = ILLEGAL_PORT; + } try { its_value = i->second.get_child("enable-magic-cookies").data(); @@ -393,6 +503,9 @@ void configuration_impl::get_service_configuration( } else if (its_key == "unreliable") { its_converter << its_value; its_converter >> its_service->unreliable_; + if(!its_service->unreliable_) { + its_service->unreliable_ = ILLEGAL_PORT; + } } else if (its_key == "multicast") { try { its_value = i->second.get_child("address").data(); @@ -410,7 +523,7 @@ void configuration_impl::get_service_configuration( get_eventgroup_configuration(its_service, i->second); } else { // Trim "its_value" - if (its_value[0] == '0' && its_value[1] == 'x') { + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { its_converter << std::hex << its_value; } else { its_converter << std::dec << its_value; @@ -429,6 +542,9 @@ void configuration_impl::get_service_configuration( auto found_instance = found_service->second.find( its_service->instance_); if (found_instance != found_service->second.end()) { + VSOMEIP_WARNING << "Multiple configurations for service [" + << std::hex << its_service->service_ << "." + << its_service->instance_ << "]"; is_loaded = false; } } @@ -437,14 +553,84 @@ void configuration_impl::get_service_configuration( services_[its_service->service_][its_service->instance_] = its_service; if (use_magic_cookies) { - magic_cookies_[its_service->unicast_address_].insert( - its_service->reliable_); + magic_cookies_[get_unicast_address(its_service->service_, + its_service->instance_)].insert(its_service->reliable_); } } } catch (...) { } } +void configuration_impl::get_client_configuration( + const boost::property_tree::ptree &_tree) { + try { + bool is_loaded(true); + + std::shared_ptr<client> its_client(std::make_shared<client>()); + + for (auto i = _tree.begin(); i != _tree.end(); ++i) { + std::string its_key(i->first); + std::string its_value(i->second.data()); + std::stringstream its_converter; + + if (its_key == "reliable") { + its_client->ports_[true] = get_client_port_configuration(i->second); + } else if (its_key == "unreliable") { + its_client->ports_[false] = get_client_port_configuration(i->second); + } else { + // Trim "its_value" + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { + its_converter << std::hex << its_value; + } else { + its_converter << std::dec << its_value; + } + + if (its_key == "service") { + its_converter >> its_client->service_; + } else if (its_key == "instance") { + its_converter >> its_client->instance_; + } + } + } + + auto found_service = clients_.find(its_client->service_); + if (found_service != clients_.end()) { + auto found_instance = found_service->second.find( + its_client->instance_); + if (found_instance != found_service->second.end()) { + VSOMEIP_ERROR << "Multiple client configurations for service [" + << std::hex << its_client->service_ << "." + << its_client->instance_ << "]"; + is_loaded = false; + } + } + + if (is_loaded) { + clients_[its_client->service_][its_client->instance_] = its_client; + } + } catch (...) { + } +} + +std::set<uint16_t> configuration_impl::get_client_port_configuration( + const boost::property_tree::ptree &_tree) { + std::set<uint16_t> its_ports; + for (auto i = _tree.begin(); i != _tree.end(); ++i) { + std::string its_value(i->second.data()); + uint16_t its_port_value; + + std::stringstream its_converter; + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { + its_converter << std::hex << its_value; + } else { + its_converter << std::dec << its_value; + } + its_converter >> its_port_value; + its_ports.insert(its_port_value); + } + return its_ports; +} + void configuration_impl::get_event_configuration( std::shared_ptr<service> &_service, const boost::property_tree::ptree &_tree) { @@ -458,7 +644,7 @@ void configuration_impl::get_event_configuration( std::string its_value(j->second.data()); if (its_key == "event") { std::stringstream its_converter; - if (its_value[0] == '0' && its_value[1] == 'x') { + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { its_converter << std::hex << its_value; } else { its_converter << std::dec << its_value; @@ -474,7 +660,10 @@ void configuration_impl::get_event_configuration( if (its_event_id > 0) { auto found_event = _service->events_.find(its_event_id); if (found_event != _service->events_.end()) { - found_event->second->is_field_ = its_is_field; + VSOMEIP_ERROR << "Multiple configurations for event [" + << std::hex << _service->service_ << "." + << _service->instance_ << "." + << its_event_id << "]"; } else { std::shared_ptr<event> its_event = std::make_shared<event>( its_event_id, its_is_field, its_is_reliable); @@ -487,17 +676,16 @@ void configuration_impl::get_event_configuration( void configuration_impl::get_eventgroup_configuration( std::shared_ptr<service> &_service, const boost::property_tree::ptree &_tree) { - bool is_multicast; for (auto i = _tree.begin(); i != _tree.end(); ++i) { - is_multicast = false; std::shared_ptr<eventgroup> its_eventgroup = std::make_shared<eventgroup>(); for (auto j = i->second.begin(); j != i->second.end(); ++j) { + std::stringstream its_converter; std::string its_key(j->first); if (its_key == "eventgroup") { - std::stringstream its_converter; + std::string its_value(j->second.data()); - if (its_value[0] == '0' && its_value[1] == 'x') { + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { its_converter << std::hex << its_value; } else { its_converter << std::dec << its_value; @@ -505,13 +693,25 @@ void configuration_impl::get_eventgroup_configuration( its_converter >> its_eventgroup->id_; } else if (its_key == "is_multicast") { std::string its_value(j->second.data()); - is_multicast = (its_value == "true"); + if (its_value == "true") { + its_eventgroup->multicast_address_ = _service->multicast_address_; + its_eventgroup->multicast_port_ = _service->multicast_port_; + } + } else if (its_key == "multicast") { + try { + std::string its_value = j->second.get_child("address").data(); + its_eventgroup->multicast_address_ = its_value; + its_value = j->second.get_child("port").data(); + its_converter << its_value; + its_converter >> its_eventgroup->multicast_port_; + } catch (...) { + } } else if (its_key == "events") { for (auto k = j->second.begin(); k != j->second.end(); ++k) { std::stringstream its_converter; std::string its_value(k->second.data()); event_t its_event_id(0); - if (its_value[0] == '0' && its_value[1] == 'x') { + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { its_converter << std::hex << its_value; } else { its_converter << std::dec << its_value; @@ -537,64 +737,170 @@ void configuration_impl::get_eventgroup_configuration( } if (its_eventgroup->id_ > 0) { - if (is_multicast) { - _service->multicast_group_ = its_eventgroup->id_; - } _service->eventgroups_[its_eventgroup->id_] = its_eventgroup; } } } -void configuration_impl::get_routing_configuration( - const boost::property_tree::ptree &_tree) { +void configuration_impl::get_routing_configuration(const element &_element) { try { - auto its_routing = _tree.get_child("routing"); - routing_host_ = its_routing.data(); + if (is_configured_[ET_ROUTING]) { + VSOMEIP_WARNING << "Multiple definitions of routing." + << " Ignoring definition from " << _element.name_; + } else { + auto its_routing = _element.tree_.get_child("routing"); + routing_host_ = its_routing.data(); + is_configured_[ET_ROUTING] = true; + } } catch (...) { } } +void configuration_impl::get_permission_configuration(const element &_element) { + const std::string file_permissions("file-permissions"); + try { + if (_element.tree_.get_child_optional(file_permissions)) { + auto its_permissions = _element.tree_.get_child(file_permissions); + for (auto i = its_permissions.begin(); i != its_permissions.end(); + ++i) { + std::string its_key(i->first); + std::stringstream its_converter; + if (its_key == "permissions-shm") { + std::string its_value(i->second.data()); + its_converter << std::oct << its_value; + its_converter >> permissions_shm_; + } else if (its_key == "umask") { + std::string its_value(i->second.data()); + its_converter << std::oct << its_value; + its_converter >> umask_; + } + } + } + } catch (...) { + } +} + +std::uint32_t configuration_impl::get_umask() const { + return umask_; +} + +std::uint32_t configuration_impl::get_permissions_shm() const { + return permissions_shm_; +} + void configuration_impl::get_service_discovery_configuration( - const boost::property_tree::ptree &_tree) { + const element &_element) { try { - auto its_service_discovery = _tree.get_child("service-discovery"); + auto its_service_discovery = _element.tree_.get_child("service-discovery"); for (auto i = its_service_discovery.begin(); i != its_service_discovery.end(); ++i) { std::string its_key(i->first); std::string its_value(i->second.data()); std::stringstream its_converter; if (its_key == "enable") { - is_sd_enabled_ = (its_value == "true"); + if (is_configured_[ET_SERVICE_DISCOVERY_ENABLE]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.enabled." + " Ignoring definition from " << _element.name_; + } else { + is_sd_enabled_ = (its_value == "true"); + is_configured_[ET_SERVICE_DISCOVERY_ENABLE] = true; + } } else if (its_key == "multicast") { - sd_multicast_ = its_value; + if (is_configured_[ET_SERVICE_DISCOVERY_MULTICAST]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.multicast." + " Ignoring definition from " << _element.name_; + } else { + sd_multicast_ = its_value; + is_configured_[ET_SERVICE_DISCOVERY_MULTICAST] = true; + } } else if (its_key == "port") { - its_converter << its_value; - its_converter >> sd_port_; + if (is_configured_[ET_SERVICE_DISCOVERY_PORT]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.port." + " Ignoring definition from " << _element.name_; + } else { + its_converter << its_value; + its_converter >> sd_port_; + if (!sd_port_) { + sd_port_ = VSOMEIP_SD_DEFAULT_PORT; + } else { + is_configured_[ET_SERVICE_DISCOVERY_PORT] = true; + } + } } else if (its_key == "protocol") { - sd_protocol_ = its_value; + if (is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.protocol." + " Ignoring definition from " << _element.name_; + } else { + sd_protocol_ = its_value; + is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL] = true; + } } else if (its_key == "initial_delay_min") { - its_converter << its_value; - its_converter >> sd_initial_delay_min_; + if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_min." + " Ignoring definition from " << _element.name_; + } else { + its_converter << its_value; + its_converter >> sd_initial_delay_min_; + is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN] = true; + } } else if (its_key == "initial_delay_max") { - its_converter << its_value; - its_converter >> sd_initial_delay_max_; + if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_max." + " Ignoring definition from " << _element.name_; + } else { + its_converter << its_value; + its_converter >> sd_initial_delay_max_; + is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX] = true; + } } else if (its_key == "repetitions_base_delay") { - its_converter << its_value; - its_converter >> sd_repetitions_base_delay_; + if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_base_delay." + " Ignoring definition from " << _element.name_; + } else { + its_converter << its_value; + its_converter >> sd_repetitions_base_delay_; + is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY] = true; + } } else if (its_key == "repetitions_max") { - int tmp; - its_converter << its_value; - its_converter >> tmp; - sd_repetitions_max_ = (uint8_t)tmp; + if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_max." + " Ignoring definition from " << _element.name_; + } else { + int tmp; + its_converter << its_value; + its_converter >> tmp; + sd_repetitions_max_ = (uint8_t)tmp; + is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX] = true; + } } else if (its_key == "ttl") { - its_converter << its_value; - its_converter >> sd_ttl_; + if (is_configured_[ET_SERVICE_DISCOVERY_TTL]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl." + " Ignoring definition from " << _element.name_; + } else { + its_converter << its_value; + its_converter >> sd_ttl_; + // We do _not_ accept 0 as this would mean "STOP OFFER" + if (sd_ttl_ == 0) sd_ttl_ = VSOMEIP_SD_DEFAULT_TTL; + else is_configured_[ET_SERVICE_DISCOVERY_TTL] = true; + } } else if (its_key == "cyclic_offer_delay") { - its_converter << its_value; - its_converter >> sd_cyclic_offer_delay_; + if (is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.cyclic_offer_delay." + " Ignoring definition from " << _element.name_; + } else { + its_converter << its_value; + its_converter >> sd_cyclic_offer_delay_; + is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY] = true; + } } else if (its_key == "request_response_delay") { - its_converter << its_value; - its_converter >> sd_request_response_delay_; + if (is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY]) { + VSOMEIP_WARNING << "Multiple definitions for service_discovery.request_response_delay." + " Ignoring definition from " << _element.name_; + } else { + its_converter << its_value; + its_converter >> sd_request_response_delay_; + is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY] = true; + } } } } catch (...) { @@ -602,24 +908,25 @@ void configuration_impl::get_service_discovery_configuration( } void configuration_impl::get_applications_configuration( - const boost::property_tree::ptree &_tree) { + const element &_element) { try { std::stringstream its_converter; - auto its_applications = _tree.get_child("applications"); + auto its_applications = _element.tree_.get_child("applications"); for (auto i = its_applications.begin(); i != its_applications.end(); ++i) { - get_application_configuration(i->second); + get_application_configuration(i->second, _element.name_); } } catch (...) { } } void configuration_impl::get_application_configuration( - const boost::property_tree::ptree &_tree) { + const boost::property_tree::ptree &_tree, const std::string &_file_name) { std::string its_name(""); - client_t its_id; - std::size_t its_num_dispatchers(0); + client_t its_id(0); + std::size_t its_max_dispatchers(VSOMEIP_MAX_DISPATCHERS); + std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME); for (auto i = _tree.begin(); i != _tree.end(); ++i) { std::string its_key(i->first); std::string its_value(i->second.data()); @@ -627,23 +934,213 @@ void configuration_impl::get_application_configuration( if (its_key == "name") { its_name = its_value; } else if (its_key == "id") { - if (its_value[0] == '0' && its_value[1] == 'x') { + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { its_converter << std::hex << its_value; } else { its_converter << std::dec << its_value; } its_converter >> its_id; - } else if (its_key == "num_dispatchers") { - if (its_value[0] == '0' && its_value[1] == 'x') { + } else if (its_key == "max_dispatchers") { + its_converter << std::dec << its_value; + its_converter >> its_max_dispatchers; + } else if (its_key == "max_dispatch_time") { + its_converter << std::dec << its_value; + its_converter >> its_max_dispatch_time; + } + } + if (its_name != "" && its_id != 0) { + if (applications_.find(its_name) == applications_.end()) { + if (!is_configured_client_id(its_id)) { + applications_[its_name] + = std::make_tuple(its_id, its_max_dispatchers, its_max_dispatch_time); + client_identifiers_.insert(its_id); + } else { + VSOMEIP_WARNING << "Multiple configurations for application " + << its_name << ". Ignoring a configuration from " + << _file_name; + } + } else { + VSOMEIP_WARNING << "Multiple configurations for application " + << its_name << ". Ignoring a configuration from " + << _file_name; + } + } +} + +void configuration_impl::get_trace_configuration(const element &_element) { + try { + std::stringstream its_converter; + auto its_trace_configuration = _element.tree_.get_child("tracing"); + for(auto i = its_trace_configuration.begin(); + i != its_trace_configuration.end(); + ++i) { + std::string its_key(i->first); + std::string its_value(i->second.data()); + if(its_key == "enable") { + if (is_configured_[ET_TRACING_ENABLE]) { + VSOMEIP_WARNING << "Multiple definitions of tracing.enable." + << " Ignoring definition from " << _element.name_; + } else { + trace_->is_enabled_ = (its_value == "true"); + is_configured_[ET_TRACING_ENABLE] = true; + } + } else if(its_key == "channels") { + get_trace_channels_configuration(i->second); + } else if(its_key == "filters") { + get_trace_filters_configuration(i->second); + } + } + } catch (...) { + } +} + +void configuration_impl::get_trace_channels_configuration( + const boost::property_tree::ptree &_tree) { + try { + for(auto i = _tree.begin(); i != _tree.end(); ++i) { + if(i == _tree.begin()) + trace_->channels_.clear(); + get_trace_channel_configuration(i->second); + } + } catch (...) { + } +} + +void configuration_impl::get_trace_channel_configuration( + const boost::property_tree::ptree &_tree) { + std::shared_ptr<trace_channel> its_channel = std::make_shared<trace_channel>(); + for(auto i = _tree.begin(); i != _tree.end(); ++i) { + std::string its_key = i->first; + std::string its_value = i->second.data(); + if(its_key == "name") { + its_channel->name_ = its_value; + } else if(its_key == "id") { + its_channel->id_ = its_value; + } + } + trace_->channels_.push_back(its_channel); +} + +void configuration_impl::get_trace_filters_configuration( + const boost::property_tree::ptree &_tree) { + try { + for(auto i = _tree.begin(); i != _tree.end(); ++i) { + get_trace_filter_configuration(i->second); + } + } catch (...) { + } +} + +void configuration_impl::get_trace_filter_configuration( + const boost::property_tree::ptree &_tree) { + std::shared_ptr<trace_filter_rule> its_filter_rule = std::make_shared<trace_filter_rule>(); + for(auto i = _tree.begin(); i != _tree.end(); ++i) { + std::string its_key = i->first; + std::string its_value = i->second.data(); + if(its_key == "channel") { + its_filter_rule->channel_ = its_value; + } else { + get_trace_filter_expressions(i->second, its_key, its_filter_rule); + } + } + trace_->filter_rules_.push_back(its_filter_rule); +} + +void configuration_impl::get_trace_filter_expressions( + const boost::property_tree::ptree &_tree, + std::string &_criteria, + std::shared_ptr<trace_filter_rule> &_filter_rule) { + for(auto i = _tree.begin(); i != _tree.end(); ++i) { + std::string its_value = i->second.data(); + std::stringstream its_converter; + + if(_criteria == "services") { + service_t its_id = NO_TRACE_FILTER_EXPRESSION; + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { + its_converter << std::hex << its_value; + } else { + its_converter << std::dec << its_value; + } + its_converter >> its_id; + _filter_rule->services_.push_back(its_id); + } else if(_criteria == "methods") { + method_t its_id = NO_TRACE_FILTER_EXPRESSION; + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { + its_converter << std::hex << its_value; + } else { + its_converter << std::dec << its_value; + } + its_converter >> its_id; + _filter_rule->methods_.push_back(its_id); + } else if(_criteria == "clients") { + client_t its_id = NO_TRACE_FILTER_EXPRESSION; + if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') { its_converter << std::hex << its_value; } else { its_converter << std::dec << its_value; } - its_converter >> its_num_dispatchers; + its_converter >> its_id; + _filter_rule->clients_.push_back(its_id); } } - if (its_name != "" && its_id != 0) { - applications_[its_name] = {its_id, its_num_dispatchers}; +} + +void configuration_impl::get_supports_selective_broadcasts(const boost::property_tree::ptree &_tree) { + try { + auto its_service_discovery = _tree.get_child("supports_selective_broadcasts"); + for (auto i = its_service_discovery.begin(); + i != its_service_discovery.end(); ++i) { + std::string its_key(i->first); + std::string its_value(i->second.data()); + std::stringstream its_converter; + if (its_key == "address") { + supported_selective_addresses.insert(its_value); + } + } + } catch (...) { + } +} + +void configuration_impl::get_watchdog_configuration(const element &_element) { + watchdog_->is_enabeled_ = false; + watchdog_->timeout_in_ms_ = VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT; + watchdog_->missing_pongs_allowed_ = VSOMEIP_DEFAULT_MAX_MISSING_PONGS; + try { + auto its_service_discovery = _element.tree_.get_child("watchdog"); + for (auto i = its_service_discovery.begin(); + i != its_service_discovery.end(); ++i) { + std::string its_key(i->first); + std::string its_value(i->second.data()); + std::stringstream its_converter; + if (its_key == "enable") { + if (is_configured_[ET_WATCHDOG_ENABLE]) { + VSOMEIP_WARNING << "Multiple definitions of watchdog.enable." + " Ignoring definition from " << _element.name_; + } else { + watchdog_->is_enabeled_ = (its_value == "true"); + is_configured_[ET_WATCHDOG_ENABLE] = true; + } + } else if (its_key == "timeout") { + if (is_configured_[ET_WATCHDOG_TIMEOUT]) { + VSOMEIP_WARNING << "Multiple definitions of watchdog.timeout." + " Ignoring definition from " << _element.name_; + } else { + its_converter << std::dec << its_value; + its_converter >> watchdog_->timeout_in_ms_; + is_configured_[ET_WATCHDOG_TIMEOUT] = true; + } + } else if (its_key == "allowed_missing_pongs") { + if (is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS]) { + VSOMEIP_WARNING << "Multiple definitions of watchdog.allowed_missing_pongs." + " Ignoring definition from " << _element.name_; + } else { + its_converter << std::dec << its_value; + its_converter >> watchdog_->missing_pongs_allowed_; + is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS] = true; + } + } + } + } catch (...) { } } @@ -652,6 +1149,10 @@ const boost::asio::ip::address & configuration_impl::get_unicast_address() const return unicast_; } +unsigned short configuration_impl::get_diagnosis_address() const { + return diagnosis_; +} + bool configuration_impl::is_v4() const { return unicast_.is_v4(); } @@ -683,7 +1184,7 @@ boost::log::trivial::severity_level configuration_impl::get_loglevel() const { std::string configuration_impl::get_unicast_address(service_t _service, instance_t _instance) const { std::string its_unicast_address(""); - service *its_service = find_service(_service, _instance); + auto its_service = find_service(_service, _instance); if (its_service) { its_unicast_address = its_service->unicast_address_; } @@ -694,52 +1195,60 @@ std::string configuration_impl::get_unicast_address(service_t _service, return its_unicast_address; } -std::string configuration_impl::get_multicast_address(service_t _service, - instance_t _instance) const { - std::string its_multicast_address(""); - service *its_service = find_service(_service, _instance); - if (its_service) - its_multicast_address = its_service->multicast_address_; - return its_multicast_address; -} - -uint16_t configuration_impl::get_multicast_port(service_t _service, +uint16_t configuration_impl::get_reliable_port(service_t _service, instance_t _instance) const { - uint16_t its_multicast_port(ILLEGAL_PORT); - service *its_service = find_service(_service, _instance); + uint16_t its_reliable(ILLEGAL_PORT); + auto its_service = find_service(_service, _instance); if (its_service) - its_multicast_port = its_service->multicast_port_; - return its_multicast_port; -} + its_reliable = its_service->reliable_; -uint16_t configuration_impl::get_multicast_group(service_t _service, - instance_t _instance) const { - uint16_t its_multicast_group(0xFFFF); - service *its_service = find_service(_service, _instance); - if (its_service) - its_multicast_group = its_service->multicast_group_; - return its_multicast_group; + return its_reliable; } -uint16_t configuration_impl::get_reliable_port(service_t _service, +uint16_t configuration_impl::get_unreliable_port(service_t _service, instance_t _instance) const { - uint16_t its_reliable(ILLEGAL_PORT); - service *its_service = find_service(_service, _instance); + uint16_t its_unreliable = ILLEGAL_PORT; + auto its_service = find_service(_service, _instance); if (its_service) - its_reliable = its_service->reliable_; + its_unreliable = its_service->unreliable_; - return its_reliable; + return its_unreliable; } bool configuration_impl::is_someip(service_t _service, instance_t _instance) const { - service *its_service = find_service(_service, _instance); + auto its_service = find_service(_service, _instance); if (its_service) return (its_service->protocol_ == "someip"); return true; // we need to explicitely configure a service to // be something else than SOME/IP } +bool configuration_impl::get_client_port( + service_t _service, instance_t _instance, bool _reliable, + std::map<bool, std::set<uint16_t> > &_used, + uint16_t &_port) const { + _port = ILLEGAL_PORT; + auto its_client = find_client(_service, _instance); + + // If no client ports are configured, return true + if (!its_client || its_client->ports_[_reliable].empty()) { + return true; + } + + for (auto its_port : its_client->ports_[_reliable]) { + // Found free configured port + if (_used[_reliable].find(its_port) == _used[_reliable].end()) { + _port = its_port; + return true; + } + } + + // Configured ports do exist, but they are all in use + VSOMEIP_ERROR << "Cannot find free client port!"; + return false; +} + bool configuration_impl::has_enabled_magic_cookies(std::string _address, uint16_t _port) const { bool has_enabled(false); @@ -753,16 +1262,6 @@ bool configuration_impl::has_enabled_magic_cookies(std::string _address, return has_enabled; } -uint16_t configuration_impl::get_unreliable_port(service_t _service, - instance_t _instance) const { - uint16_t its_unreliable = ILLEGAL_PORT; - - service *its_service = find_service(_service, _instance); - if (its_service) - its_unreliable = its_service->unreliable_; - - return its_unreliable; -} const std::string & configuration_impl::get_routing_host() const { return routing_host_; @@ -773,22 +1272,38 @@ client_t configuration_impl::get_id(const std::string &_name) const { auto found_application = applications_.find(_name); if (found_application != applications_.end()) { - its_client = found_application->second.first; + its_client = std::get<0>(found_application->second); } return its_client; } -std::size_t configuration_impl::get_num_dispatchers( +bool configuration_impl::is_configured_client_id(client_t _id) const { + return (client_identifiers_.find(_id) != client_identifiers_.end()); +} + +std::size_t configuration_impl::get_max_dispatchers( + const std::string &_name) const { + std::size_t its_max_dispatchers = VSOMEIP_MAX_DISPATCHERS; + + auto found_application = applications_.find(_name); + if (found_application != applications_.end()) { + its_max_dispatchers = std::get<1>(found_application->second); + } + + return its_max_dispatchers; +} + +std::size_t configuration_impl::get_max_dispatch_time( const std::string &_name) const { - std::size_t its_num_dispatchers = 0; + std::size_t its_max_dispatch_time = VSOMEIP_MAX_DISPATCH_TIME; auto found_application = applications_.find(_name); if (found_application != applications_.end()) { - its_num_dispatchers = found_application->second.second; + its_max_dispatch_time = std::get<2>(found_application->second); } - return its_num_dispatchers; + return its_max_dispatch_time; } std::set<std::pair<service_t, instance_t> > @@ -796,26 +1311,73 @@ configuration_impl::get_remote_services() const { std::set<std::pair<service_t, instance_t> > its_remote_services; for (auto i : services_) { for (auto j : i.second) { - if (j.second->unicast_address_ != "local" && j.second->unicast_address_ != "") + if (j.second->unicast_address_ != "local" && + j.second->unicast_address_ != "" && + j.second->unicast_address_ != unicast_.to_string() && + j.second->unicast_address_ != VSOMEIP_UNICAST_ADDRESS) its_remote_services.insert(std::make_pair(i.first, j.first)); } } return its_remote_services; } -service *configuration_impl::find_service(service_t _service, +bool configuration_impl::get_multicast(service_t _service, + instance_t _instance, eventgroup_t _eventgroup, + std::string &_address, uint16_t &_port) const +{ + std::shared_ptr<eventgroup> its_eventgroup + = find_eventgroup(_service, _instance, _eventgroup); + if (!its_eventgroup) + return false; + + if (its_eventgroup->multicast_address_.empty()) + return false; + + _address = its_eventgroup->multicast_address_; + _port = its_eventgroup->multicast_port_; + return true; +} + +std::shared_ptr<client> configuration_impl::find_client(service_t _service, + instance_t _instance) const { + std::shared_ptr<client> its_client; + auto find_service = clients_.find(_service); + if (find_service != clients_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) { + its_client = find_instance->second; + } + } + return its_client; +} + +std::shared_ptr<service> configuration_impl::find_service(service_t _service, instance_t _instance) const { - service *its_service(0); + std::shared_ptr<service> its_service; auto find_service = services_.find(_service); if (find_service != services_.end()) { auto find_instance = find_service->second.find(_instance); if (find_instance != find_service->second.end()) { - its_service = find_instance->second.get(); + its_service = find_instance->second; } } return its_service; } +std::shared_ptr<eventgroup> configuration_impl::find_eventgroup( + service_t _service, instance_t _instance, + eventgroup_t _eventgroup) const { + std::shared_ptr<eventgroup> its_eventgroup; + auto its_service = find_service(_service, _instance); + if (its_service) { + auto find_eventgroup = its_service->eventgroups_.find(_eventgroup); + if (find_eventgroup != its_service->eventgroups_.end()) { + its_eventgroup = find_eventgroup->second; + } + } + return its_eventgroup; +} + std::uint32_t configuration_impl::get_max_message_size_local() const { uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) { @@ -832,7 +1394,7 @@ std::uint32_t configuration_impl::get_max_message_size_local() const { // to the routing_manager stub return std::uint32_t(its_max_message_size + VSOMEIP_COMMAND_HEADER_SIZE + sizeof(instance_t) - + sizeof(bool) + sizeof(bool)); + + sizeof(bool) + sizeof(bool) + sizeof(bool)); } std::uint32_t configuration_impl::get_message_size_reliable( @@ -847,6 +1409,10 @@ std::uint32_t configuration_impl::get_message_size_reliable( return VSOMEIP_MAX_TCP_MESSAGE_SIZE; } +bool configuration_impl::supports_selective_broadcasts(boost::asio::ip::address _address) const { + return supported_selective_addresses.find(_address.to_string()) != supported_selective_addresses.end(); +} + // Service Discovery configuration bool configuration_impl::is_sd_enabled() const { return is_sd_enabled_; @@ -892,5 +1458,24 @@ int32_t configuration_impl::get_sd_request_response_delay() const { return sd_request_response_delay_; } +// Trace configuration +std::shared_ptr<cfg::trace> configuration_impl::get_trace() const { + return trace_; +} + +// Watchdog config +bool configuration_impl::is_watchdog_enabled() const { + return watchdog_->is_enabeled_; +} + +uint32_t configuration_impl::get_watchdog_timeout() const { + return watchdog_->timeout_in_ms_; +} + +uint32_t configuration_impl::get_allowed_missing_pongs() const { + return watchdog_->missing_pongs_allowed_; +} + + } // namespace config } // namespace vsomeip |