summaryrefslogtreecommitdiff
path: root/implementation/configuration/src/configuration_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'implementation/configuration/src/configuration_impl.cpp')
-rw-r--r--implementation/configuration/src/configuration_impl.cpp364
1 files changed, 362 insertions, 2 deletions
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index 43e3c67..0920b66 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -77,7 +77,9 @@ configuration_impl::configuration_impl()
log_memory_(false),
log_memory_interval_(0),
log_status_(false),
- log_status_interval_(0) {
+ log_status_interval_(0),
+ endpoint_queue_limit_external_(QUEUE_SIZE_UNLIMITED),
+ endpoint_queue_limit_local_(QUEUE_SIZE_UNLIMITED) {
unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS);
for (auto i = 0; i < ET_MAX; i++)
is_configured_[i] = false;
@@ -94,7 +96,9 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
max_reliable_message_size_(_other.max_reliable_message_size_),
buffer_shrink_threshold_(_other.buffer_shrink_threshold_),
permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
- umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) {
+ umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS),
+ endpoint_queue_limit_external_(_other.endpoint_queue_limit_external_),
+ endpoint_queue_limit_local_(_other.endpoint_queue_limit_local_) {
applications_.insert(_other.applications_.begin(), _other.applications_.end());
services_.insert(_other.services_.begin(), _other.services_.end());
@@ -144,6 +148,8 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
log_memory_interval_ = _other.log_memory_interval_;
log_status_ = _other.log_status_;
log_status_interval_ = _other.log_status_interval_;
+
+ debounces_ = _other.debounces_;
}
configuration_impl::~configuration_impl() {
@@ -332,6 +338,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
load_network(e);
load_diagnosis_address(e);
load_payload_sizes(e);
+ load_endpoint_queue_sizes(e);
load_permissions(e);
load_policies(e);
load_tracing(e);
@@ -348,6 +355,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
load_watchdog(e);
load_selective_broadcasts_support(e);
load_e2e(e);
+ load_debounce(e);
}
}
@@ -892,6 +900,22 @@ void configuration_impl::load_service_discovery(
its_converter >> sd_offer_debounce_time_;
is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME] = true;
}
+ } else if (its_key == "ttl_factor_offers") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_OFFERS]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl_factor_offers."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ load_ttl_factors(i->second, &ttl_factors_offers_);
+ is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_OFFERS] = true;
+ }
+ } else if (its_key == "ttl_factor_subscriptions") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_SUBSCRIPTIONS]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl_factor_subscriptions."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ load_ttl_factors(i->second, &ttl_factors_subscriptions_);
+ is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_SUBSCRIPTIONS] = true;
+ }
}
}
} catch (...) {
@@ -2636,5 +2660,341 @@ uint32_t configuration_impl::get_log_status_interval() const {
return log_status_interval_;
}
+void configuration_impl::load_ttl_factors(
+ const boost::property_tree::ptree &_tree, ttl_map_t* _target) {
+ const service_t ILLEGAL_VALUE(0xffff);
+ for (const auto& i : _tree) {
+ service_t its_service(ILLEGAL_VALUE);
+ instance_t its_instance(ILLEGAL_VALUE);
+ configuration::ttl_factor_t its_ttl_factor(0);
+
+ for (const auto& j : i.second) {
+ std::string its_key(j.first);
+ std::string its_value(j.second.data());
+ std::stringstream its_converter;
+
+ if (its_key == "ttl_factor") {
+ its_converter << its_value;
+ its_converter >> its_ttl_factor;
+ } 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_service;
+ } else if (its_key == "instance") {
+ its_converter >> its_instance;
+ }
+ }
+ }
+ if (its_service != ILLEGAL_VALUE
+ && its_instance != ILLEGAL_VALUE
+ && its_ttl_factor > 0) {
+ (*_target)[its_service][its_instance] = its_ttl_factor;
+ } else {
+ VSOMEIP_ERROR << "Invalid ttl factor configuration";
+ }
+ }
+}
+
+configuration::ttl_map_t configuration_impl::get_ttl_factor_offers() const {
+ return ttl_factors_offers_;
+}
+
+configuration::ttl_map_t configuration_impl::get_ttl_factor_subscribes() const {
+ return ttl_factors_subscriptions_;
+}
+
+configuration::endpoint_queue_limit_t
+configuration_impl::get_endpoint_queue_limit(
+ const std::string& _address, std::uint16_t _port) const {
+ auto found_address = endpoint_queue_limits_.find(_address);
+ if (found_address != endpoint_queue_limits_.end()) {
+ auto found_port = found_address->second.find(_port);
+ if (found_port != found_address->second.end()) {
+ return found_port->second;
+ }
+ }
+ return endpoint_queue_limit_external_;
+}
+
+configuration::endpoint_queue_limit_t
+configuration_impl::get_endpoint_queue_limit_local() const {
+ return endpoint_queue_limit_local_;
+}
+
+void configuration_impl::load_endpoint_queue_sizes(const element &_element) {
+ const std::string endpoint_queue_limits("endpoint-queue-limits");
+ const std::string endpoint_queue_limit_external("endpoint-queue-limit-external");
+ const std::string endpoint_queue_limit_local("endpoint-queue-limit-local");
+
+ try {
+ if (_element.tree_.get_child_optional(endpoint_queue_limit_external)) {
+ if (is_configured_[ET_ENDPOINT_QUEUE_LIMIT_EXTERNAL]) {
+ VSOMEIP_WARNING << "Multiple definitions for "
+ << endpoint_queue_limit_external
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ is_configured_[ET_ENDPOINT_QUEUE_LIMIT_EXTERNAL] = true;
+ auto mpsl = _element.tree_.get_child(
+ endpoint_queue_limit_external);
+ std::string s(mpsl.data());
+ try {
+ endpoint_queue_limit_external_ =
+ static_cast<configuration::endpoint_queue_limit_t>(std::stoul(
+ s.c_str(), NULL, 10));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR<<__func__ << ": " << endpoint_queue_limit_external
+ << " " << e.what();
+ }
+ }
+ }
+ if (_element.tree_.get_child_optional(endpoint_queue_limit_local)) {
+ if (is_configured_[ET_ENDPOINT_QUEUE_LIMIT_LOCAL]) {
+ VSOMEIP_WARNING << "Multiple definitions for "
+ << endpoint_queue_limit_local
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ is_configured_[ET_ENDPOINT_QUEUE_LIMIT_LOCAL] = true;
+ auto mpsl = _element.tree_.get_child(endpoint_queue_limit_local);
+ std::string s(mpsl.data());
+ try {
+ endpoint_queue_limit_local_=
+ static_cast<configuration::endpoint_queue_limit_t>(
+ std::stoul(s.c_str(), NULL, 10));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR<< __func__ << ": "<< endpoint_queue_limit_local
+ << " " << e.what();
+ }
+ }
+ }
+
+ if (_element.tree_.get_child_optional(endpoint_queue_limits)) {
+ if (is_configured_[ET_ENDPOINT_QUEUE_LIMITS]) {
+ VSOMEIP_WARNING << "Multiple definitions for "
+ << endpoint_queue_limits
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ is_configured_[ET_ENDPOINT_QUEUE_LIMITS] = true;
+ const std::string unicast("unicast");
+ const std::string ports("ports");
+ const std::string port("port");
+ const std::string queue_size_limit("queue-size-limit");
+
+ for (const auto i : _element.tree_.get_child(endpoint_queue_limits)) {
+ if (!i.second.get_child_optional(unicast)
+ || !i.second.get_child_optional(ports)) {
+ continue;
+ }
+ std::string its_unicast(i.second.get_child(unicast).data());
+ for (const auto j : i.second.get_child(ports)) {
+
+ if (!j.second.get_child_optional(port)
+ || !j.second.get_child_optional(queue_size_limit)) {
+ continue;
+ }
+
+ std::uint16_t its_port = ILLEGAL_PORT;
+ std::uint32_t its_queue_size_limit = 0;
+
+ try {
+ std::string p(j.second.get_child(port).data());
+ its_port = static_cast<std::uint16_t>(std::stoul(p.c_str(),
+ NULL, 10));
+ std::string s(j.second.get_child(queue_size_limit).data());
+ its_queue_size_limit = static_cast<std::uint32_t>(std::stoul(
+ s.c_str(), NULL, 10));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << __func__ << ":" << e.what();
+ }
+
+ if (its_port == ILLEGAL_PORT || its_queue_size_limit == 0) {
+ continue;
+ }
+
+ endpoint_queue_limits_[its_unicast][its_port] = its_queue_size_limit;
+ }
+ }
+ }
+ }
+ } catch (...) {
+ }
+}
+
+void configuration_impl::load_debounce(const element &_element) {
+ try {
+ auto its_debounce = _element.tree_.get_child("debounce");
+ for (auto i = its_debounce.begin(); i != its_debounce.end(); ++i) {
+ load_service_debounce(i->second);
+ }
+ } catch (...) {
+ }
+}
+
+void configuration_impl::load_service_debounce(
+ const boost::property_tree::ptree &_tree) {
+ service_t its_service(0);
+ instance_t its_instance(0);
+ std::map<event_t, std::shared_ptr<debounce>> its_debounces;
+
+ 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 == "service") {
+ 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_service;
+ } else if (its_key == "instance") {
+ 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_instance;
+ } else if (its_key == "events") {
+ load_events_debounce(i->second, its_debounces);
+ }
+ }
+
+ // TODO: Improve error handling!
+ if (its_service > 0 && its_instance > 0 && !its_debounces.empty()) {
+ auto find_service = debounces_.find(its_service);
+ if (find_service != debounces_.end()) {
+ auto find_instance = find_service->second.find(its_instance);
+ if (find_instance != find_service->second.end()) {
+ VSOMEIP_ERROR << "Multiple debounce configurations for service "
+ << std::hex << std::setw(4) << std::setfill('0') << its_service
+ << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance;
+ return;
+ }
+ }
+ debounces_[its_service][its_instance] = its_debounces;
+ }
+}
+
+void configuration_impl::load_events_debounce(
+ const boost::property_tree::ptree &_tree,
+ std::map<event_t, std::shared_ptr<debounce>> &_debounces) {
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ load_event_debounce(i->second, _debounces);
+ }
+}
+
+void configuration_impl::load_event_debounce(
+ const boost::property_tree::ptree &_tree,
+ std::map<event_t, std::shared_ptr<debounce>> &_debounces) {
+ event_t its_event(0);
+ std::shared_ptr<debounce> its_debounce = std::make_shared<debounce>();
+
+ 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 == "event") {
+ 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_event;
+ } else if (its_key == "on_change") {
+ its_debounce->on_change_ = (its_value == "true");
+ } else if (its_key == "on_change_resets_interval") {
+ its_debounce->on_change_resets_interval_ = (its_value == "true");
+ } else if (its_key == "ignore") {
+ load_event_debounce_ignore(i->second, its_debounce->ignore_);
+ } else if (its_key == "interval") {
+ if (its_value == "never") {
+ its_debounce->interval_ = -1;
+ } else {
+ its_converter << std::dec << its_value;
+ its_converter >> its_debounce->interval_;
+ }
+ }
+ }
+
+ // TODO: Improve error handling
+ if (its_event > 0) {
+ auto find_event = _debounces.find(its_event);
+ if (find_event == _debounces.end()) {
+ _debounces[its_event] = its_debounce;
+ }
+ }
+}
+
+void configuration_impl::load_event_debounce_ignore(
+ const boost::property_tree::ptree &_tree,
+ std::map<std::size_t, byte_t> &_ignore) {
+ std::size_t its_ignored;
+ byte_t its_mask;
+ std::stringstream its_converter;
+
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ std::string its_value = i->second.data();
+
+ its_mask = 0xff;
+
+ if (!its_value.empty()
+ && std::find_if(its_value.begin(), its_value.end(),
+ [](char _c) { return !std::isdigit(_c); })
+ == its_value.end()) {
+ its_converter.str("");
+ its_converter.clear();
+ its_converter << std::dec << its_value;
+ its_converter >> its_ignored;
+
+ } else {
+ for (auto j = i->second.begin(); j != i->second.end(); ++j) {
+ std::string its_ignore_key(j->first);
+ std::string its_ignore_value(j->second.data());
+
+ if (its_ignore_key == "index") {
+ its_converter.str("");
+ its_converter.clear();
+ its_converter << std::dec << its_ignore_value;
+ its_converter >> its_ignored;
+ } else if (its_ignore_key == "mask") {
+ its_converter.str("");
+ its_converter.clear();
+
+ int its_tmp_mask;
+ its_converter << std::hex << its_ignore_value;
+ its_converter >> its_tmp_mask;
+
+ its_mask = static_cast<byte_t>(its_tmp_mask);
+ }
+ }
+ }
+
+ _ignore[its_ignored] = its_mask;
+ }
+}
+
+std::shared_ptr<debounce> configuration_impl::get_debounce(
+ service_t _service, instance_t _instance, event_t _event) const {
+ auto found_service = debounces_.find(_service);
+ if (found_service != debounces_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_event = found_instance->second.find(_event);
+ if (found_event != found_instance->second.end()) {
+ return found_event->second;
+ }
+ }
+ }
+ return nullptr;
+}
+
} // namespace config
} // namespace vsomeip