summaryrefslogtreecommitdiff
path: root/implementation
diff options
context:
space:
mode:
Diffstat (limited to 'implementation')
-rw-r--r--implementation/configuration/include/configuration.hpp61
-rw-r--r--implementation/configuration/include/configuration_impl.hpp136
-rw-r--r--implementation/configuration/include/e2e.hpp8
-rw-r--r--implementation/configuration/include/internal.hpp.in38
-rw-r--r--implementation/configuration/include/policy.hpp6
-rw-r--r--implementation/configuration/include/trace.hpp56
-rw-r--r--implementation/configuration/src/configuration_impl.cpp1521
-rw-r--r--implementation/e2e_protection/include/e2exf/config.hpp8
-rw-r--r--implementation/e2e_protection/src/e2exf/config.cpp2
-rw-r--r--implementation/endpoints/include/client_endpoint_impl.hpp10
-rw-r--r--implementation/endpoints/include/endpoint.hpp4
-rw-r--r--implementation/endpoints/include/local_client_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/include/local_server_endpoint_impl.hpp14
-rw-r--r--implementation/endpoints/include/netlink_connector.hpp2
-rw-r--r--implementation/endpoints/include/server_endpoint_impl.hpp3
-rw-r--r--implementation/endpoints/include/tcp_client_endpoint_impl.hpp13
-rw-r--r--implementation/endpoints/include/udp_client_endpoint_impl.hpp10
-rw-r--r--implementation/endpoints/include/udp_server_endpoint_impl.hpp7
-rw-r--r--implementation/endpoints/include/virtual_server_endpoint_impl.hpp3
-rw-r--r--implementation/endpoints/src/client_endpoint_impl.cpp64
-rw-r--r--implementation/endpoints/src/credentials.cpp10
-rw-r--r--implementation/endpoints/src/local_client_endpoint_impl.cpp45
-rw-r--r--implementation/endpoints/src/local_server_endpoint_impl.cpp154
-rw-r--r--implementation/endpoints/src/netlink_connector.cpp4
-rw-r--r--implementation/endpoints/src/server_endpoint_impl.cpp20
-rw-r--r--implementation/endpoints/src/tcp_client_endpoint_impl.cpp230
-rw-r--r--implementation/endpoints/src/tcp_server_endpoint_impl.cpp131
-rw-r--r--implementation/endpoints/src/udp_client_endpoint_impl.cpp115
-rw-r--r--implementation/endpoints/src/udp_server_endpoint_impl.cpp98
-rw-r--r--implementation/endpoints/src/virtual_server_endpoint_impl.cpp6
-rw-r--r--implementation/message/include/deserializer.hpp3
-rw-r--r--implementation/message/include/message_base_impl.hpp4
-rw-r--r--implementation/message/include/message_header_impl.hpp2
-rw-r--r--implementation/message/include/payload_impl.hpp2
-rw-r--r--implementation/message/src/deserializer.cpp11
-rw-r--r--implementation/plugin/include/plugin_manager.hpp2
-rw-r--r--implementation/plugin/src/plugin_manager.cpp6
-rw-r--r--implementation/routing/include/event.hpp5
-rw-r--r--implementation/routing/include/routing_manager.hpp7
-rw-r--r--implementation/routing/include/routing_manager_base.hpp64
-rw-r--r--implementation/routing/include/routing_manager_impl.hpp99
-rw-r--r--implementation/routing/include/routing_manager_proxy.hpp15
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp33
-rw-r--r--implementation/routing/include/routing_manager_stub_host.hpp14
-rw-r--r--implementation/routing/include/serviceinfo.hpp3
-rw-r--r--implementation/routing/include/types.hpp2
-rw-r--r--implementation/routing/src/event.cpp18
-rw-r--r--implementation/routing/src/routing_manager_base.cpp282
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp1012
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp584
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp585
-rw-r--r--implementation/routing/src/serviceinfo.cpp12
-rw-r--r--implementation/runtime/include/application_impl.hpp27
-rw-r--r--implementation/runtime/src/application_impl.cpp396
-rwxr-xr-ximplementation/service_discovery/include/entry_impl.hpp4
-rw-r--r--implementation/service_discovery/include/ip_option_impl.hpp2
-rwxr-xr-ximplementation/service_discovery/include/message_impl.hpp2
-rw-r--r--implementation/service_discovery/include/runtime.hpp5
-rw-r--r--implementation/service_discovery/include/runtime_impl.hpp3
-rw-r--r--implementation/service_discovery/include/service_discovery.hpp7
-rw-r--r--implementation/service_discovery/include/service_discovery_host.hpp3
-rw-r--r--implementation/service_discovery/include/service_discovery_impl.hpp21
-rwxr-xr-ximplementation/service_discovery/src/configuration_option_impl.cpp2
-rwxr-xr-ximplementation/service_discovery/src/eventgroupentry_impl.cpp57
-rwxr-xr-ximplementation/service_discovery/src/message_impl.cpp22
-rw-r--r--implementation/service_discovery/src/runtime_impl.cpp5
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp385
-rw-r--r--implementation/tracing/include/channel_impl.hpp62
-rw-r--r--implementation/tracing/include/connector_impl.hpp81
-rw-r--r--implementation/tracing/include/defines.hpp4
-rw-r--r--implementation/tracing/include/enumeration_types.hpp14
-rw-r--r--implementation/tracing/include/header.hpp (renamed from implementation/tracing/include/trace_header.hpp)12
-rw-r--r--implementation/tracing/include/trace_connector.hpp107
-rw-r--r--implementation/tracing/src/channel_impl.cpp273
-rw-r--r--implementation/tracing/src/connector_impl.cpp226
-rw-r--r--implementation/tracing/src/header.cpp (renamed from implementation/tracing/src/trace_header.cpp)16
-rw-r--r--implementation/tracing/src/trace_connector.cpp381
-rw-r--r--implementation/utility/include/utility.hpp47
-rw-r--r--implementation/utility/src/utility.cpp433
79 files changed, 6456 insertions, 1687 deletions
diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp
index c89ed39..9740a79 100644
--- a/implementation/configuration/include/configuration.hpp
+++ b/implementation/configuration/include/configuration.hpp
@@ -24,6 +24,7 @@
#include "../../e2e_protection/include/e2exf/config.hpp"
#include "e2e.hpp"
+#include "policy.hpp"
#include "debounce.hpp"
@@ -38,10 +39,22 @@ public:
virtual ~configuration() {}
virtual bool load(const std::string &_name) = 0;
+ virtual bool remote_offer_info_add(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled) = 0;
+ virtual bool remote_offer_info_remove(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled,
+ bool* _still_offered_remote) = 0;
virtual const std::string &get_network() const = 0;
virtual const boost::asio::ip::address & get_unicast_address() const = 0;
+ virtual const boost::asio::ip::address& get_netmask() const = 0;
virtual unsigned short get_diagnosis_address() const = 0;
virtual std::uint16_t get_diagnosis_mask() const = 0;
virtual bool is_v4() const = 0;
@@ -84,6 +97,7 @@ public:
virtual std::size_t get_max_dispatchers(const std::string &_name) const = 0;
virtual std::size_t get_max_dispatch_time(const std::string &_name) const = 0;
virtual std::size_t get_io_thread_count(const std::string &_name) const = 0;
+ virtual int get_io_thread_nice_level(const std::string &_name) const = 0;
virtual std::size_t get_request_debouncing(const std::string &_name) const = 0;
virtual std::uint32_t get_max_message_size_local() const = 0;
@@ -124,7 +138,7 @@ public:
virtual uint32_t get_allowed_missing_pongs() const = 0;
// File permissions
- virtual std::uint32_t get_umask() const = 0;
+ virtual std::uint32_t get_permissions_uds() const = 0;
virtual std::uint32_t get_permissions_shm() const = 0;
virtual bool log_version() const = 0;
@@ -133,11 +147,19 @@ public:
// Security
virtual bool is_security_enabled() const = 0;
virtual bool is_client_allowed(client_t _client, service_t _service,
- instance_t _instance) const = 0;
+ instance_t _instance, method_t _method, bool _is_request_service = false) const = 0;
virtual bool is_offer_allowed(client_t _client, service_t _service,
instance_t _instance) const = 0;
virtual bool check_credentials(client_t _client,
uint32_t _uid, uint32_t _gid) = 0;
+ virtual bool store_client_to_uid_gid_mapping(client_t _client, uint32_t _uid, uint32_t _gid) = 0;
+ virtual void store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid, client_t _client) = 0;
+
+ virtual bool get_client_to_uid_gid_mapping(client_t _client,
+ std::pair<uint32_t, uint32_t> &_uid_gid) = 0;
+ virtual bool remove_client_to_uid_gid_mapping(client_t _client) = 0;
+ virtual bool get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
+ std::set<client_t> &_clients) = 0;
// Plugins
virtual std::map<plugin_type_e, std::set<std::string>> get_plugins(
@@ -146,7 +168,7 @@ public:
virtual void set_configuration_path(const std::string &_path) = 0;
//E2E
- virtual std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const = 0;
+ virtual std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const = 0;
virtual bool is_e2e_enabled() const = 0;
virtual bool log_memory() const = 0;
@@ -170,6 +192,39 @@ public:
virtual endpoint_queue_limit_t get_endpoint_queue_limit(
const std::string& _address, std::uint16_t _port) const = 0;
virtual endpoint_queue_limit_t get_endpoint_queue_limit_local() const = 0;
+
+ virtual std::uint32_t get_max_tcp_restart_aborts() const = 0;
+ virtual std::uint32_t get_max_tcp_connect_time() const = 0;
+
+ // Offer acceptance
+ virtual bool offer_acceptance_required(
+ const boost::asio::ip::address& _address) const = 0;
+ virtual void set_offer_acceptance_required(
+ const boost::asio::ip::address& _address, const std::string& _path,
+ bool _enable) = 0;
+ virtual std::map<boost::asio::ip::address, std::string> get_offer_acceptance_required() = 0;
+
+ // Security policy
+ virtual void update_security_policy(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy) = 0;
+ virtual bool remove_security_policy(uint32_t _uid, uint32_t _gid) = 0;
+
+ virtual void add_security_credentials(uint32_t _uid, uint32_t _gid,
+ ::std::shared_ptr<policy> _credentials_policy, client_t _client) = 0;
+
+ virtual bool is_remote_client_allowed() const = 0;
+
+ virtual bool is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const = 0;
+
+ virtual bool is_policy_removal_allowed(uint32_t _uid) const = 0;
+
+ virtual std::uint32_t get_udp_receive_buffer_size() const = 0;
+
+ virtual bool is_audit_mode_enabled() const = 0;
+
+ virtual bool check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const = 0;
+
+ // routing shutdown timeout
+ virtual std::uint32_t get_shutdown_timeout() const = 0;
};
} // namespace vsomeip
diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp
index af04ce1..9bf1188 100644
--- a/implementation/configuration/include/configuration_impl.hpp
+++ b/implementation/configuration/include/configuration_impl.hpp
@@ -49,16 +49,28 @@ class configuration_impl:
public std::enable_shared_from_this<configuration_impl> {
public:
VSOMEIP_EXPORT configuration_impl();
- VSOMEIP_EXPORT configuration_impl(const configuration_impl &_cfg);
+ VSOMEIP_EXPORT configuration_impl(const configuration_impl &_other);
VSOMEIP_EXPORT virtual ~configuration_impl();
VSOMEIP_EXPORT bool load(const std::string &_name);
+ VSOMEIP_EXPORT bool remote_offer_info_add(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled);
+ VSOMEIP_EXPORT bool remote_offer_info_remove(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled,
+ bool* _still_offered_remote);
VSOMEIP_EXPORT const std::string &get_network() const;
VSOMEIP_EXPORT void set_configuration_path(const std::string &_path);
VSOMEIP_EXPORT const boost::asio::ip::address & get_unicast_address() const;
+ VSOMEIP_EXPORT const boost::asio::ip::address& get_netmask() const;
VSOMEIP_EXPORT unsigned short get_diagnosis_address() const;
VSOMEIP_EXPORT std::uint16_t get_diagnosis_mask() const;
VSOMEIP_EXPORT bool is_v4() const;
@@ -91,6 +103,7 @@ public:
VSOMEIP_EXPORT std::size_t get_max_dispatchers(const std::string &_name) const;
VSOMEIP_EXPORT std::size_t get_max_dispatch_time(const std::string &_name) const;
VSOMEIP_EXPORT std::size_t get_io_thread_count(const std::string &_name) const;
+ VSOMEIP_EXPORT int get_io_thread_nice_level(const std::string &_name) const;
VSOMEIP_EXPORT std::size_t get_request_debouncing(const std::string &_name) const;
VSOMEIP_EXPORT std::set<std::pair<service_t, instance_t> > get_remote_services() const;
@@ -140,22 +153,30 @@ public:
VSOMEIP_EXPORT uint32_t get_watchdog_timeout() const;
VSOMEIP_EXPORT uint32_t get_allowed_missing_pongs() const;
- VSOMEIP_EXPORT std::uint32_t get_umask() const;
+ VSOMEIP_EXPORT std::uint32_t get_permissions_uds() const;
VSOMEIP_EXPORT std::uint32_t get_permissions_shm() const;
// Policy
VSOMEIP_EXPORT bool is_security_enabled() const;
VSOMEIP_EXPORT bool is_client_allowed(client_t _client, service_t _service,
- instance_t _instance) const;
+ instance_t _instance, method_t _method, bool _is_request_service = false) const;
VSOMEIP_EXPORT bool is_offer_allowed(client_t _client, service_t _service,
instance_t _instance) const;
VSOMEIP_EXPORT bool check_credentials(client_t _client,
uint32_t _uid, uint32_t _gid);
+ VSOMEIP_EXPORT bool store_client_to_uid_gid_mapping(client_t _client, uint32_t _uid, uint32_t _gid);
+ VSOMEIP_EXPORT void store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid, client_t _client);
+ VSOMEIP_EXPORT bool get_client_to_uid_gid_mapping(client_t _client,
+ std::pair<uint32_t, uint32_t> &_uid_gid);
+ VSOMEIP_EXPORT bool remove_client_to_uid_gid_mapping(client_t _client);
+ VSOMEIP_EXPORT bool get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
+ std::set<client_t> &_clients);
+
VSOMEIP_EXPORT std::map<plugin_type_e, std::set<std::string>> get_plugins(
const std::string &_name) const;
// E2E
- VSOMEIP_EXPORT std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const;
+ VSOMEIP_EXPORT std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const;
VSOMEIP_EXPORT bool is_e2e_enabled() const;
VSOMEIP_EXPORT bool log_memory() const;
@@ -173,11 +194,42 @@ public:
VSOMEIP_EXPORT endpoint_queue_limit_t get_endpoint_queue_limit(
const std::string& _address, std::uint16_t _port) const;
VSOMEIP_EXPORT endpoint_queue_limit_t get_endpoint_queue_limit_local() const;
+
+ VSOMEIP_EXPORT std::uint32_t get_max_tcp_restart_aborts() const;
+ VSOMEIP_EXPORT std::uint32_t get_max_tcp_connect_time() const;
+
+ VSOMEIP_EXPORT bool offer_acceptance_required(
+ const boost::asio::ip::address& _address) const;
+
+ VSOMEIP_EXPORT void set_offer_acceptance_required(
+ const boost::asio::ip::address& _address, const std::string& _path,
+ bool _enable);
+ VSOMEIP_EXPORT std::map<boost::asio::ip::address, std::string> get_offer_acceptance_required();
+
+ VSOMEIP_EXPORT void update_security_policy(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy);
+ VSOMEIP_EXPORT bool remove_security_policy(uint32_t _uid, uint32_t _gid);
+
+ VSOMEIP_EXPORT void add_security_credentials(uint32_t _uid, uint32_t _gid,
+ ::std::shared_ptr<policy> _credentials_policy, client_t _client);
+
+ VSOMEIP_EXPORT bool is_remote_client_allowed() const;
+
+ VSOMEIP_EXPORT bool is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const;
+
+ VSOMEIP_EXPORT bool is_policy_removal_allowed(uint32_t _uid) const;
+
+ VSOMEIP_EXPORT std::uint32_t get_udp_receive_buffer_size() const;
+
+ VSOMEIP_EXPORT bool is_audit_mode_enabled() const;
+
+ VSOMEIP_EXPORT bool check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const;
+
+ VSOMEIP_EXPORT std::uint32_t get_shutdown_timeout() const;
private:
void read_data(const std::set<std::string> &_input,
std::vector<element> &_elements,
std::set<std::string> &_failed,
- bool _standard_only);
+ bool _mandatory_only);
bool load_data(const std::vector<element> &_elements,
bool _load_mandatory, bool _load_optional);
@@ -185,10 +237,11 @@ private:
bool load_logging(const element &_element,
std::set<std::string> &_warnings);
bool load_routing(const element &_element);
+ bool load_routing_credentials(const element &_element);
bool load_applications(const element &_element);
void load_application_data(const boost::property_tree::ptree &_tree,
- const std::string &_name);
+ const std::string &_file_name);
void load_tracing(const element &_element);
void load_trace_channels(const boost::property_tree::ptree &_tree);
@@ -198,12 +251,17 @@ private:
void load_trace_filter_expressions(
const boost::property_tree::ptree &_tree,
std::string &_criteria,
- std::shared_ptr<trace_filter_rule> &_filter_rule);
+ std::shared_ptr<trace_filter> &_filter);
+ void load_trace_filter_match(
+ const boost::property_tree::ptree &_data,
+ std::tuple<service_t, instance_t, method_t> &_match);
void load_network(const element &_element);
void load_unicast_address(const element &_element);
+ void load_netmask(const element &_element);
void load_diagnosis_address(const element &_element);
+ void load_shutdown_timeout(const element &_element);
void load_service_discovery(const element &_element);
void load_delays(const boost::property_tree::ptree &_tree);
@@ -234,6 +292,11 @@ private:
void load_policy(const boost::property_tree::ptree &_tree);
void load_credential(const boost::property_tree::ptree &_tree, ids_t &_ids);
void load_ranges(const boost::property_tree::ptree &_tree, ranges_t &_range);
+ void load_instance_ranges(const boost::property_tree::ptree &_tree, ranges_t &_range);
+
+ void load_security_update_whitelist(const element &_element);
+ void load_service_ranges(const boost::property_tree::ptree &_tree,
+ std::set<std::pair<service_t, service_t>> &_ranges);
void load_debounce(const element &_element);
void load_service_debounce(const boost::property_tree::ptree &_tree);
@@ -243,11 +306,15 @@ private:
std::map<event_t, std::shared_ptr<debounce>> &_debounces);
void load_event_debounce_ignore(const boost::property_tree::ptree &_tree,
std::map<std::size_t, byte_t> &_ignore);
+ void load_offer_acceptance_required(const element &_element);
+ void load_udp_receive_buffer_size(const element &_element);
+
servicegroup *find_servicegroup(const std::string &_name) const;
std::shared_ptr<client> find_client(service_t _service,
instance_t _instance) const;
std::shared_ptr<service> find_service(service_t _service, instance_t _instance) const;
+ std::shared_ptr<service> find_service_unlocked(service_t _service, instance_t _instance) const;
std::shared_ptr<eventgroup> find_eventgroup(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) const;
bool find_port(uint16_t &_port, uint16_t _remote, bool _reliable,
@@ -271,8 +338,14 @@ private:
void load_endpoint_queue_sizes(const element &_element);
+ void load_tcp_restart_settings(const element &_element);
+
+ std::shared_ptr<policy> find_client_id_policy(client_t _client) const;
+
private:
std::mutex mutex_;
+ mutable std::mutex ids_mutex_;
+ mutable std::mutex uid_to_clients_mutex_;
bool is_loaded_;
bool is_logging_loaded_;
@@ -282,6 +355,7 @@ private:
protected:
// Configuration data
boost::asio::ip::address unicast_;
+ boost::asio::ip::address netmask_;
unsigned short diagnosis_;
std::uint16_t diagnosis_mask_;
@@ -292,9 +366,10 @@ protected:
boost::log::trivial::severity_level loglevel_;
std::map<std::string, std::tuple<client_t, std::size_t, std::size_t,
- size_t, size_t, std::map<plugin_type_e, std::set<std::string>>>> applications_;
+ size_t, size_t, std::map<plugin_type_e, std::set<std::string>>, int>> applications_;
std::set<client_t> client_identifiers_;
+ mutable std::mutex services_mutex_;
std::map<service_t,
std::map<instance_t,
std::shared_ptr<service> > > services_;
@@ -368,24 +443,39 @@ protected:
ET_ENDPOINT_QUEUE_LIMITS,
ET_ENDPOINT_QUEUE_LIMIT_EXTERNAL,
ET_ENDPOINT_QUEUE_LIMIT_LOCAL,
- ET_MAX = 31
+ ET_TCP_RESTART_ABORTS_MAX,
+ ET_TCP_CONNECT_TIME_MAX,
+ ET_OFFER_ACCEPTANCE_REQUIRED,
+ ET_NETMASK,
+ ET_UDP_RECEIVE_BUFFER_SIZE,
+ ET_ROUTING_CREDENTIALS,
+ ET_SHUTDOWN_TIMEOUT,
+ ET_MAX = 38
};
bool is_configured_[ET_MAX];
std::uint32_t permissions_shm_;
- std::uint32_t umask_;
+ std::uint32_t permissions_uds_;
- std::map<client_t, std::shared_ptr<policy>> policies_;
+ std::map<std::pair<uint16_t, uint16_t>, std::shared_ptr<policy>> policies_;
std::vector<std::shared_ptr<policy> > any_client_policies_;
+
+ mutable std::mutex policies_mutex_;
+ mutable std::mutex any_client_policies_mutex_;
std::map<client_t, std::pair<uint32_t, uint32_t> > ids_;
+ std::map<std::pair<uint32_t, uint32_t>, std::set<client_t> > uid_to_clients_;
+
bool policy_enabled_;
bool check_credentials_;
+ bool check_routing_credentials_;
+ bool allow_remote_clients_;
+ bool check_whitelist_;
std::string network_;
std::string configuration_path_;
bool e2e_enabled_;
- std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> e2e_configuration_;
+ std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> e2e_configuration_;
bool log_memory_;
uint32_t log_memory_interval_;
@@ -401,6 +491,28 @@ protected:
std::map<std::string, std::map<std::uint16_t, endpoint_queue_limit_t>> endpoint_queue_limits_;
endpoint_queue_limit_t endpoint_queue_limit_external_;
endpoint_queue_limit_t endpoint_queue_limit_local_;
+
+ uint32_t tcp_restart_aborts_max_;
+ uint32_t tcp_connect_time_max_;
+
+ mutable std::mutex offer_acceptance_required_ips_mutex_;
+ std::map<boost::asio::ip::address, std::string> offer_acceptance_required_ips_;
+
+ bool has_issued_methods_warning_;
+ bool has_issued_clients_warning_;
+
+ std::uint32_t udp_receive_buffer_size_;
+
+ mutable std::mutex service_interface_whitelist_mutex_;
+ std::set<std::pair<service_t, service_t>> service_interface_whitelist_;
+
+ mutable std::mutex uid_whitelist_mutex_;
+ ranges_t uid_whitelist_;
+
+ mutable std::mutex routing_credentials_mutex_;
+ std::pair<uint32_t, uint32_t> routing_credentials_;
+
+ std::uint32_t shutdown_timeout_;
};
} // namespace cfg
diff --git a/implementation/configuration/include/e2e.hpp b/implementation/configuration/include/e2e.hpp
index 6f7bcda..94eb33d 100644
--- a/implementation/configuration/include/e2e.hpp
+++ b/implementation/configuration/include/e2e.hpp
@@ -30,8 +30,8 @@ struct e2e {
}
- e2e(uint16_t _data_id, std::string _variant, std::string _profile, uint16_t _service_id,
- uint16_t _event_id,uint16_t _crc_offset,
+ e2e(uint16_t _data_id, std::string _variant, std::string _profile, service_t _service_id,
+ event_t _event_id,uint16_t _crc_offset,
uint8_t _data_id_mode, uint16_t _data_length, uint16_t _data_id_nibble_offset, uint16_t _counter_offset) :
data_id(_data_id),
@@ -51,8 +51,8 @@ struct e2e {
uint16_t data_id;
std::string variant;
std::string profile;
- uint16_t service_id;
- uint16_t event_id;
+ service_t service_id;
+ event_t event_id;
//profile 1 specific config
// [SWS_E2E_00018]
diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in
index 1cb9895..b1a1372 100644
--- a/implementation/configuration/include/internal.hpp.in
+++ b/implementation/configuration/include/internal.hpp.in
@@ -16,11 +16,10 @@
#define VSOMEIP_ENV_MANDATORY_CONFIGURATION_FILES "VSOMEIP_MANDATORY_CONFIGURATION_FILES"
#define VSOMEIP_ENV_LOAD_PLUGINS "VSOMEIP_LOAD_PLUGINS"
#define VSOMEIP_ENV_CLIENTSIDELOGGING "VSOMEIP_CLIENTSIDELOGGING"
-#define VSOMEIP_ENV_DEBUG_CONFIGURATION "VSOMEIP_DEBUG_CONFIGURATION"
#define VSOMEIP_DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json"
#define VSOMEIP_LOCAL_CONFIGURATION_FILE "./vsomeip.json"
-#define VSOMEIP_MANDATORY_CONFIGURATION_FILES "vsomeip_std.json,vsomeip_app.json,vsomeip_plc.json,vsomeip_log.json,vsomeip_security.json"
+#define VSOMEIP_MANDATORY_CONFIGURATION_FILES "vsomeip_std.json,vsomeip_app.json,vsomeip_plc.json,vsomeip_log.json,vsomeip_security.json,vsomeip_whitelist.json"
#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip"
#define VSOMEIP_DEBUG_CONFIGURATION_FOLDER "/var/opt/public/sin/vsomeip/"
@@ -50,15 +49,26 @@
#endif
#define VSOMEIP_UNICAST_ADDRESS "@VSOMEIP_UNICAST_ADDRESS@"
+#define VSOMEIP_NETMASK "255.255.255.0"
#define VSOMEIP_DEFAULT_CONNECT_TIMEOUT 100
#define VSOMEIP_MAX_CONNECT_TIMEOUT 1600
#define VSOMEIP_DEFAULT_FLUSH_TIMEOUT 1000
+#define VSOMEIP_DEFAULT_SHUTDOWN_TIMEOUT 5000
+
+#define VSOMEIP_MAX_TCP_CONNECT_TIME 5000
+#define VSOMEIP_MAX_TCP_RESTART_ABORTS 5
+
+#define VSOMEIP_DEFAULT_BUFFER_SHRINK_THRESHOLD 5
+
#define VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT 5000
#define VSOMEIP_DEFAULT_MAX_MISSING_PONGS 3
+#define VSOMEIP_DEFAULT_UDP_RCV_BUFFER_SIZE 1703936
+
#define VSOMEIP_IO_THREAD_COUNT 2
+#define VSOMEIP_IO_THREAD_NICE_LEVEL 255
#define VSOMEIP_MAX_DISPATCHERS 10
#define VSOMEIP_MAX_DISPATCH_TIME 100
@@ -104,6 +114,14 @@
#define VSOMEIP_OFFERED_SERVICES_REQUEST 0x1F
#define VSOMEIP_OFFERED_SERVICES_RESPONSE 0x20
#define VSOMEIP_UNSUBSCRIBE_ACK 0x21
+#define VSOMEIP_RESEND_PROVIDED_EVENTS 0x22
+
+#define VSOMEIP_UPDATE_SECURITY_POLICY 0x23
+#define VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE 0x24
+#define VSOMEIP_REMOVE_SECURITY_POLICY 0x25
+#define VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE 0x26
+#define VSOMEIP_UPDATE_SECURITY_CREDENTIALS 0x27
+#define VSOMEIP_DISTRIBUTE_SECURITY_POLICIES 0x28
#define VSOMEIP_SEND_COMMAND_SIZE 14
#define VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN 7
@@ -129,6 +147,16 @@
#define VSOMEIP_ID_RESPONSE_COMMAND_SIZE 12
#define VSOMEIP_ID_REQUEST_COMMAND_SIZE 13
#define VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE 8
+#define VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE 11
+#define VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE 19
+#define VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE 11
+#define VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE 11
+#define VSOMEIP_PING_COMMAND_SIZE 7
+#define VSOMEIP_PONG_COMMAND_SIZE 7
+#define VSOMEIP_REGISTER_APPLICATION_COMMAND_SIZE 7
+#define VSOMEIP_DEREGISTER_APPLICATION_COMMAND_SIZE 7
+#define VSOMEIP_REGISTERED_ACK_COMMAND_SIZE 7
+
#ifndef _WIN32
#include <pthread.h>
@@ -138,7 +166,7 @@
#define VSOMEIP_DIAGNOSIS_ADDRESS @VSOMEIP_DIAGNOSIS_ADDRESS@
#define VSOMEIP_DEFAULT_SHM_PERMISSION 0666
-#define VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS 0000
+#define VSOMEIP_DEFAULT_UDS_PERMISSIONS 0666
#define VSOMEIP_ROUTING_READY_MESSAGE "@VSOMEIP_ROUTING_READY_MESSAGE@"
@@ -180,7 +208,7 @@ struct configuration_data_t {
unsigned short client_base_;
unsigned short max_clients_;
int max_used_client_ids_index_;
- unsigned short max_assigned_client_id_without_diagnosis_;
+ unsigned short max_assigned_client_id_;
unsigned short routing_manager_host_;
// array of used client ids here, pointer to it is kept in utility class
};
@@ -189,6 +217,8 @@ const std::uint32_t MESSAGE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>
const std::uint32_t QUEUE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
+const std::uint32_t MAX_RECONNECTS_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
+
} // namespace vsomeip
diff --git a/implementation/configuration/include/policy.hpp b/implementation/configuration/include/policy.hpp
index 9132a4d..c8f649e 100644
--- a/implementation/configuration/include/policy.hpp
+++ b/implementation/configuration/include/policy.hpp
@@ -12,7 +12,6 @@
#include <vsomeip/primitive_types.hpp>
namespace vsomeip {
-namespace cfg {
typedef std::set<std::pair<uint32_t, uint32_t>> ranges_t;
typedef std::set<std::pair<ranges_t, ranges_t>> ids_t;
@@ -23,12 +22,11 @@ struct policy {
ids_t ids_;
bool allow_who_;
- std::set<std::pair<service_t, instance_t>> services_;
- std::set<std::pair<service_t, instance_t>> offers_;
+ std::set<std::pair<service_t, ids_t>> services_;
+ std::set<std::pair<service_t, ranges_t>> offers_;
bool allow_what_;
};
-} // namespace cfg
} // namespace vsomeip
#endif // VSOMEIP_CFG_POLICY_HPP
diff --git a/implementation/configuration/include/trace.hpp b/implementation/configuration/include/trace.hpp
index db92286..3d4e1f4 100644
--- a/implementation/configuration/include/trace.hpp
+++ b/implementation/configuration/include/trace.hpp
@@ -3,67 +3,51 @@
// 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/.
-#ifndef CONFIGURATION_INCLUDE_TRACE_HPP_
-#define CONFIGURATION_INCLUDE_TRACE_HPP_
+#ifndef CFG_TRACE_HPP_
+#define CFG_TRACE_HPP_
#include <string>
#include <vector>
#include <vsomeip/primitive_types.hpp>
-
-#include "../../tracing/include/defines.hpp"
+#include <vsomeip/trace.hpp>
namespace vsomeip {
namespace cfg {
struct trace_channel {
-
- trace_channel() :
- id_(VSOMEIP_TC_DEFAULT_CHANNEL_ID),
- name_(VSOMEIP_TC_DEFAULT_CHANNEL_NAME) {
-
- }
-
trace_channel_t id_;
std::string name_;
};
-struct trace_filter_rule {
-
- trace_filter_rule() :
- channel_(VSOMEIP_TC_DEFAULT_CHANNEL_ID),
- services_(),
- methods_(),
- clients_(),
- type_(VSOMEIP_TC_DEFAULT_FILTER_TYPE) {
-
+struct trace_filter {
+ trace_filter()
+ : is_positive_(true),
+ is_range_(false) {
}
- trace_channel_t channel_;
- std::vector<service_t> services_;
- std::vector<method_t> methods_;
- std::vector<client_t> clients_;
- trace_filter_type_t type_;
+ std::vector<trace_channel_t> channels_;
+ bool is_positive_;
+ bool is_range_;
+ std::vector<vsomeip::trace::match_t> matches_;
};
struct trace {
-
- trace() :
- channels_(),
- filter_rules_(),
- is_enabled_(false),
- is_sd_enabled_(false) {
- channels_.push_back(std::make_shared<trace_channel>());
+ trace()
+ : is_enabled_(false),
+ is_sd_enabled_(false),
+ channels_(),
+ filters_() {
}
- std::vector<std::shared_ptr<trace_channel>> channels_;
- std::vector<std::shared_ptr<trace_filter_rule>> filter_rules_;
-
bool is_enabled_;
bool is_sd_enabled_;
+
+ std::vector<std::shared_ptr<trace_channel>> channels_;
+ std::vector<std::shared_ptr<trace_filter>> filters_;
};
} // namespace cfg
} // namespace vsomeip
-#endif /* CONFIGURATION_INCLUDE_TRACE_HPP_ */
+#endif // CFG_TRACE_HPP_
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index ccf3883..b574841 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -64,15 +64,18 @@ configuration_impl::configuration_impl()
max_configured_message_size_(0),
max_local_message_size_(0),
max_reliable_message_size_(0),
- buffer_shrink_threshold_(0),
+ buffer_shrink_threshold_(VSOMEIP_DEFAULT_BUFFER_SHRINK_THRESHOLD),
trace_(std::make_shared<trace>()),
watchdog_(std::make_shared<watchdog>()),
log_version_(true),
log_version_interval_(10),
permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
- umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS),
+ permissions_uds_(VSOMEIP_DEFAULT_UDS_PERMISSIONS),
policy_enabled_(false),
check_credentials_(false),
+ check_routing_credentials_(false),
+ allow_remote_clients_(true),
+ check_whitelist_(false),
network_("vsomeip"),
e2e_enabled_(false),
log_memory_(false),
@@ -80,8 +83,15 @@ configuration_impl::configuration_impl()
log_status_(false),
log_status_interval_(0),
endpoint_queue_limit_external_(QUEUE_SIZE_UNLIMITED),
- endpoint_queue_limit_local_(QUEUE_SIZE_UNLIMITED) {
+ endpoint_queue_limit_local_(QUEUE_SIZE_UNLIMITED),
+ tcp_restart_aborts_max_(VSOMEIP_MAX_TCP_RESTART_ABORTS),
+ tcp_connect_time_max_(VSOMEIP_MAX_TCP_CONNECT_TIME),
+ has_issued_methods_warning_(false),
+ has_issued_clients_warning_(false),
+ udp_receive_buffer_size_(VSOMEIP_DEFAULT_UDP_RCV_BUFFER_SIZE),
+ shutdown_timeout_(VSOMEIP_DEFAULT_SHUTDOWN_TIMEOUT) {
unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS);
+ netmask_ = netmask_.from_string(VSOMEIP_NETMASK);
for (auto i = 0; i < ET_MAX; i++)
is_configured_[i] = false;
}
@@ -97,14 +107,21 @@ 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),
+ permissions_uds_(VSOMEIP_DEFAULT_UDS_PERMISSIONS),
endpoint_queue_limit_external_(_other.endpoint_queue_limit_external_),
- endpoint_queue_limit_local_(_other.endpoint_queue_limit_local_) {
+ endpoint_queue_limit_local_(_other.endpoint_queue_limit_local_),
+ tcp_restart_aborts_max_(_other.tcp_restart_aborts_max_),
+ tcp_connect_time_max_(_other.tcp_connect_time_max_),
+ udp_receive_buffer_size_(_other.udp_receive_buffer_size_),
+ shutdown_timeout_(_other.shutdown_timeout_) {
applications_.insert(_other.applications_.begin(), _other.applications_.end());
+ client_identifiers_ = _other.client_identifiers_;
services_.insert(_other.services_.begin(), _other.services_.end());
+ clients_ = _other.clients_;
unicast_ = _other.unicast_;
+ netmask_ = _other.netmask_;
diagnosis_ = _other.diagnosis_;
diagnosis_mask_ = _other.diagnosis_mask_;
@@ -132,26 +149,48 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
sd_offer_debounce_time_ = _other.sd_offer_debounce_time_;
trace_ = std::make_shared<trace>(*_other.trace_.get());
+ supported_selective_addresses = _other.supported_selective_addresses;
watchdog_ = std::make_shared<watchdog>(*_other.watchdog_.get());
+ internal_service_ranges_ = _other.internal_service_ranges_;
log_version_ = _other.log_version_;
log_version_interval_ = _other.log_version_interval_;
magic_cookies_.insert(_other.magic_cookies_.begin(), _other.magic_cookies_.end());
+ message_sizes_ = _other.message_sizes_;
for (auto i = 0; i < ET_MAX; i++)
is_configured_[i] = _other.is_configured_[i];
+ policies_ = _other.policies_;
+ any_client_policies_ = _other.any_client_policies_;
+ ids_ = _other.ids_;
policy_enabled_ = _other.policy_enabled_;
check_credentials_ = _other.check_credentials_;
+ check_routing_credentials_ = _other.check_routing_credentials_;
+ allow_remote_clients_ = _other.allow_remote_clients_;
+ check_whitelist_ = _other.check_whitelist_;
+
network_ = _other.network_;
+ configuration_path_ = _other.configuration_path_;
+
e2e_enabled_ = _other.e2e_enabled_;
+ e2e_configuration_ = _other.e2e_configuration_;
log_memory_ = _other.log_memory_;
log_memory_interval_ = _other.log_memory_interval_;
log_status_ = _other.log_status_;
log_status_interval_ = _other.log_status_interval_;
+ ttl_factors_offers_ = _other.ttl_factors_offers_;
+ ttl_factors_subscriptions_ = _other.ttl_factors_subscriptions_;
+
debounces_ = _other.debounces_;
+ endpoint_queue_limits_ = _other.endpoint_queue_limits_;
+
+ offer_acceptance_required_ips_ = _other.offer_acceptance_required_ips_;
+
+ has_issued_methods_warning_ = _other.has_issued_methods_warning_;
+ has_issued_clients_warning_ = _other.has_issued_clients_warning_;
}
configuration_impl::~configuration_impl() {
@@ -195,14 +234,14 @@ bool configuration_impl::load(const std::string &_name) {
}
if (its_folder != "") {
its_input.insert(its_folder);
- }
-
- // Add debug configuration folder/file on top of already set input
- const char* its_debug_env = getenv(VSOMEIP_ENV_DEBUG_CONFIGURATION);
- if (nullptr != its_debug_env) {
- its_input.insert(its_debug_env);
- } else {
- its_input.insert(VSOMEIP_DEBUG_CONFIGURATION_FOLDER);
+#ifndef _WIN32
+ // load security configuration files from UID_GID sub folder if existing
+ std::stringstream its_security_config_folder;
+ its_security_config_folder << its_folder << "/" << getuid() << "_" << getgid();
+ if (utility::is_folder(its_security_config_folder.str())) {
+ its_input.insert(its_security_config_folder.str());
+ }
+#endif
}
// Determine standard configuration file
@@ -271,6 +310,101 @@ bool configuration_impl::load(const std::string &_name) {
return is_loaded_;
}
+bool configuration_impl::remote_offer_info_add(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled) {
+ bool ret = false;
+ if (!is_loaded_) {
+ VSOMEIP_ERROR << __func__ << " shall only be called after normal"
+ "configuration has been parsed";
+ } else {
+ std::shared_ptr<service> its_service(std::make_shared<service>());
+ its_service->service_ = _service;
+ its_service->instance_ = _instance;
+ its_service->reliable_ = its_service->unreliable_ = ILLEGAL_PORT;
+ _reliable ?
+ its_service->reliable_ = _port :
+ its_service->unreliable_ = _port;
+ its_service->unicast_address_ = "local";
+ its_service->multicast_address_ = "";
+ its_service->multicast_port_ = ILLEGAL_PORT;
+ its_service->protocol_ = "someip";
+
+ {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
+ bool updated(false);
+ auto found_service = services_.find(its_service->service_);
+ if (found_service != services_.end()) {
+ auto found_instance = found_service->second.find(its_service->instance_);
+ if (found_instance != found_service->second.end()) {
+ VSOMEIP_INFO << "Updating remote configuration for service ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_service->service_ << "." << its_service->instance_ << "]";
+ if (_reliable) {
+ found_instance->second->reliable_ = its_service->reliable_;
+ } else {
+ found_instance->second->unreliable_ = its_service->unreliable_;
+ }
+ updated = true;
+ }
+ }
+ if (!updated) {
+ services_[_service][_instance] = its_service;
+ VSOMEIP_INFO << "Added new remote configuration for service ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_service->service_ << "."
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_service->instance_ << "]";
+ }
+ if (_magic_cookies_enabled) {
+ magic_cookies_[its_service->unicast_address_].insert(its_service->reliable_);
+ }
+ }
+ ret = true;
+ }
+ return ret;
+}
+
+bool configuration_impl::remote_offer_info_remove(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled,
+ bool* _still_offered_remote) {
+ (void)_port;
+ (void)_magic_cookies_enabled;
+ bool ret = false;
+ if (!is_loaded_) {
+ VSOMEIP_ERROR << __func__ << " shall only be called after normal"
+ "configuration has been parsed";
+ } else {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
+ auto found_service = services_.find(_service);
+ if (found_service != services_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ VSOMEIP_INFO << "Removing remote configuration for service ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _service << "." << _instance << "]";
+ if (_reliable) {
+ found_instance->second->reliable_ = ILLEGAL_PORT;
+ // TODO delete from magic_cookies_map without overwriting
+ // configurations from other services offered on the same port
+ } else {
+ found_instance->second->unreliable_ = ILLEGAL_PORT;
+ }
+ *_still_offered_remote = (
+ found_instance->second->unreliable_ != ILLEGAL_PORT ||
+ found_instance->second->reliable_ != ILLEGAL_PORT);
+ ret = true;
+ }
+ }
+ }
+ return ret;
+}
+
void configuration_impl::read_data(const std::set<std::string> &_input,
std::vector<element> &_elements, std::set<std::string> &_failed,
bool _mandatory_only) {
@@ -339,17 +473,23 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
has_applications = load_applications(e) || has_applications;
load_network(e);
load_diagnosis_address(e);
+ load_shutdown_timeout(e);
load_payload_sizes(e);
load_endpoint_queue_sizes(e);
+ load_tcp_restart_settings(e);
load_permissions(e);
load_policies(e);
load_tracing(e);
+ load_udp_receive_buffer_size(e);
+ load_security_update_whitelist(e);
+ load_routing_credentials(e);
}
}
if (_load_optional) {
for (auto e : _elements) {
load_unicast_address(e);
+ load_netmask(e);
load_service_discovery(e);
load_services(e);
load_internal_services(e);
@@ -358,6 +498,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
load_selective_broadcasts_support(e);
load_e2e(e);
load_debounce(e);
+ load_offer_acceptance_required(e);
}
}
@@ -476,6 +617,51 @@ bool configuration_impl::load_routing(const element &_element) {
return true;
}
+bool configuration_impl::load_routing_credentials(const element &_element) {
+ try {
+ auto its_routing_cred = _element.tree_.get_child("routing-credentials");
+ if (is_configured_[ET_ROUTING_CREDENTIALS]) {
+ VSOMEIP_WARNING << "vSomeIP Security: Multiple definitions of routing-credentials."
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ for (auto i = its_routing_cred.begin();
+ i != its_routing_cred.end();
+ ++i) {
+ std::string its_key(i->first);
+ std::string its_value(i->second.data());
+ std::stringstream its_converter;
+ if (its_key == "uid") {
+ uint32_t its_uid(0);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_uid;
+ std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
+ std::get<0>(routing_credentials_) = its_uid;
+ } else if (its_key == "gid") {
+ uint32_t its_gid(0);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_gid;
+ std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
+ std::get<1>(routing_credentials_) = its_gid;
+ }
+ }
+ check_routing_credentials_ = true;
+ is_configured_[ET_ROUTING_CREDENTIALS] = true;
+ }
+ } catch (...) {
+ return false;
+ }
+ return true;
+}
+
+
bool configuration_impl::load_applications(const element &_element) {
try {
std::stringstream its_converter;
@@ -500,6 +686,7 @@ void configuration_impl::load_application_data(
std::size_t its_io_thread_count(VSOMEIP_IO_THREAD_COUNT);
std::size_t its_request_debounce_time(VSOMEIP_REQUEST_DEBOUNCE_TIME);
std::map<plugin_type_e, std::set<std::string>> plugins;
+ int its_io_thread_nice_level(VSOMEIP_IO_THREAD_NICE_LEVEL);
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
std::string its_key(i->first);
std::string its_value(i->second.data());
@@ -529,6 +716,9 @@ void configuration_impl::load_application_data(
VSOMEIP_WARNING << "Max. number of threads per application is 255";
its_io_thread_count = 255;
}
+ } else if (its_key == "io_thread_nice") {
+ its_converter << std::dec << its_value;
+ its_converter >> its_io_thread_nice_level;
} else if (its_key == "request_debounce_time") {
its_converter << std::dec << its_value;
its_converter >> its_request_debounce_time;
@@ -552,13 +742,13 @@ void configuration_impl::load_application_data(
if (its_inner_key == "application_plugin") {
#ifndef _WIN32
library += ".";
- library += (VSOMEIP_APPLICATION_PLUGIN_VERSION + '0');
+ library += std::to_string(std::uint32_t(VSOMEIP_APPLICATION_PLUGIN_VERSION));
#endif
plugins[plugin_type_e::APPLICATION_PLUGIN].insert(library);
} else if (its_inner_key == "configuration_plugin") {
#ifndef _WIN32
library += ".";
- library += (VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION + '0');
+ library += std::to_string(std::uint32_t(VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION));
#endif
plugins[plugin_type_e::PRE_CONFIGURATION_PLUGIN].insert(library);
} else {
@@ -586,7 +776,7 @@ void configuration_impl::load_application_data(
applications_[its_name]
= std::make_tuple(its_id, its_max_dispatchers,
its_max_dispatch_time, its_io_thread_count,
- its_request_debounce_time, plugins);
+ its_request_debounce_time, plugins, its_io_thread_nice_level);
} else {
VSOMEIP_WARNING << "Multiple configurations for application "
<< its_name << ". Ignoring a configuration from "
@@ -672,56 +862,137 @@ void configuration_impl::load_trace_filters(
void configuration_impl::load_trace_filter(
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::shared_ptr<trace_filter> its_filter = std::make_shared<trace_filter>();
+ bool has_channel(false);
+ 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;
+ if (its_key == "channel") {
+ std::string its_value;
+ if (i->second.size() == 0) {
+ its_value = i->second.data();
+ its_filter->channels_.push_back(its_value);
+ } else {
+ for (auto j = i->second.begin(); j != i->second.end(); ++j) {
+ its_filter->channels_.push_back(j->second.data());
+ }
+ }
+ has_channel = true;
} else if(its_key == "type") {
- its_filter_rule->type_ = its_value;
+ std::string its_value = i->second.data();
+ its_filter->is_positive_ = (its_value == "positive");
} else {
- load_trace_filter_expressions(i->second, its_key, its_filter_rule);
+ load_trace_filter_expressions(i->second, its_key, its_filter);
}
}
- trace_->filter_rules_.push_back(its_filter_rule);
+
+ if (!has_channel) {
+ its_filter->channels_.push_back("TC"); // default
+ }
+
+ if (!its_filter->is_range_ || its_filter->matches_.size() == 2) {
+ trace_->filters_.push_back(its_filter);
+ }
}
void configuration_impl::load_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;
+ std::shared_ptr<trace_filter> &_filter) {
+ if (_criteria == "services") {
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ vsomeip::trace::match_t its_match;
+ load_trace_filter_match(i->second, its_match);
+ _filter->matches_.push_back(its_match);
+ }
+ } else if (_criteria == "methods") {
+ if (!has_issued_methods_warning_) {
+ VSOMEIP_WARNING << "\"method\" entry in filter configuration has no effect!";
+ has_issued_methods_warning_ = true;
+ }
+ } else if (_criteria == "clients") {
+ if (!has_issued_clients_warning_) {
+ VSOMEIP_WARNING << "\"clients\" entry in filter configuration has no effect!";
+ has_issued_clients_warning_ = true;
+ }
+ } else if (_criteria == "matches") {
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ vsomeip::trace::match_t its_match;
+ load_trace_filter_match(i->second, its_match);
+ if (i->first == "from") {
+ _filter->is_range_ = true;
+ _filter->matches_.insert(_filter->matches_.begin(), its_match);
} else {
- its_converter << std::dec << its_value;
+ if (i->first == "to") _filter->is_range_ = true;
+ _filter->matches_.push_back(its_match);
}
- 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;
+ }
+ }
+}
+
+void configuration_impl::load_trace_filter_match(
+ const boost::property_tree::ptree &_data,
+ vsomeip::trace::match_t &_match) {
+ std::stringstream its_converter;
+
+ if (_data.size() == 0) {
+ std::string its_value(_data.data());
+ service_t its_service(ANY_SERVICE);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_service;
+
+ std::get<0>(_match) = its_service;
+ std::get<1>(_match) = ANY_INSTANCE;
+ std::get<2>(_match) = ANY_METHOD;
+ } else {
+ std::get<0>(_match) = ANY_SERVICE;
+ std::get<1>(_match) = ANY_INSTANCE;
+ std::get<2>(_match) = ANY_METHOD;
+
+ for (auto i = _data.begin(); i != _data.end(); ++i) {
+ std::string its_value;
+
+ its_converter.str("");
+ its_converter.clear();
+
+ try {
+ its_value = i->second.data();
+ if (its_value == "any") its_value = "0xffff";
+
+ if (i->first == "service") {
+ service_t its_service(ANY_SERVICE);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_service;
+ std::get<0>(_match) = its_service;
+ } else if (i->first == "instance") {
+ instance_t its_instance(ANY_INSTANCE);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_instance;
+ std::get<1>(_match) = its_instance;
+ } else if (i->first == "method") {
+ method_t its_method(ANY_METHOD);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_method;
+ std::get<2>(_match) = its_method;
+ }
+ } catch (...) {
+ // Intentionally left empty
}
- its_converter >> its_id;
- _filter_rule->clients_.push_back(its_id);
}
}
}
@@ -741,6 +1012,21 @@ void configuration_impl::load_unicast_address(const element &_element) {
}
}
+void configuration_impl::load_netmask(const element &_element) {
+ try {
+ std::string its_value = _element.tree_.get<std::string>("netmask");
+ if (is_configured_[ET_NETMASK]) {
+ VSOMEIP_WARNING << "Multiple definitions for netmask."
+ "Ignoring definition from " << _element.name_;
+ } else {
+ netmask_ = netmask_.from_string(its_value);
+ is_configured_[ET_NETMASK] = true;
+ }
+ } catch (...) {
+ // intentionally left empty!
+ }
+}
+
void configuration_impl::load_network(const element &_element) {
try {
std::string its_value(_element.tree_.get<std::string>("network"));
@@ -793,6 +1079,31 @@ void configuration_impl::load_diagnosis_address(const element &_element) {
}
}
+void configuration_impl::load_shutdown_timeout(const element &_element) {
+ const std::string shutdown_timeout("shutdown_timeout");
+ try {
+ if (_element.tree_.get_child_optional(shutdown_timeout)) {
+ std::string its_value = _element.tree_.get<std::string>("shutdown_timeout");
+ if (is_configured_[ET_SHUTDOWN_TIMEOUT]) {
+ VSOMEIP_WARNING << "Multiple definitions for shutdown_timeout."
+ "Ignoring definition from " << _element.name_;
+ } else {
+ 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 >> shutdown_timeout_;
+ is_configured_[ET_SHUTDOWN_TIMEOUT] = true;
+ }
+ }
+ } catch (...) {
+ // intentionally left empty
+ }
+}
+
void configuration_impl::load_service_discovery(
const element &_element) {
try {
@@ -978,6 +1289,7 @@ void configuration_impl::load_delays(
}
void configuration_impl::load_services(const element &_element) {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
try {
auto its_services = _element.tree_.get_child("services");
for (auto i = its_services.begin(); i != its_services.end(); ++i)
@@ -1587,10 +1899,10 @@ void configuration_impl::load_permissions(const element &_element) {
std::string its_value(i->second.data());
its_converter << std::oct << its_value;
its_converter >> permissions_shm_;
- } else if (its_key == "umask") {
+ } else if (its_key == "permissions-uds") {
std::string its_value(i->second.data());
its_converter << std::oct << its_value;
- its_converter >> umask_;
+ its_converter >> permissions_uds_;
}
}
@@ -1636,8 +1948,13 @@ void configuration_impl::load_policies(const element &_element) {
} else {
check_credentials_ = false;
}
- }
- if (its_security->first == "policies") {
+ } else if (its_security->first == "allow_remote_clients") {
+ if (its_security->second.data() == "true") {
+ allow_remote_clients_ = true;
+ } else {
+ allow_remote_clients_ = false;
+ }
+ } else if (its_security->first == "policies") {
for (auto its_policy = its_security->second.begin();
its_policy != its_security->second.end(); ++its_policy) {
load_policy(its_policy->second);
@@ -1676,16 +1993,19 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
if (firstClient < lastClient && lastClient != ANY_CLIENT) {
uint32_t overrides(0);
for (client_t c = firstClient; c <= lastClient; ++c) {
- if (policies_.find(c) != policies_.end()) {
+ if (find_client_id_policy(c)) {
overrides++;
}
- policies_[c] = policy;
}
if (overrides) {
- VSOMEIP_INFO << std::hex << "Security configuration: "
- << "Client range 0x" << firstClient
- << " - 0x" << lastClient << " overrides policy of "
- << std::dec << overrides << " clients";
+ VSOMEIP_WARNING << std::hex << "Security configuration: "
+ << "for client range 0x" << firstClient
+ << " - 0x" << lastClient
+ << " will be ignored as it would override an already existing policy of "
+ << std::dec << overrides << " clients!";
+ } else {
+ std::lock_guard<std::mutex> its_lock(policies_mutex_);
+ policies_[std::make_pair(firstClient, lastClient)] = policy;
}
has_been_inserted = true;
} else {
@@ -1699,47 +2019,63 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
its_converter << std::hex << value;
its_converter >> client;
if (client != 0x0) {
- if (policies_.find(client) != policies_.end()) {
- VSOMEIP_INFO << std::hex << "Security configuration: "
- << "Overriding policy for client 0x" << client << ".";
+ if (find_client_id_policy(client)) {
+ VSOMEIP_WARNING << std::hex << "Security configuration for client "
+ << client
+ << " will be ignored as it would overwrite an already existing policy!";
+ } else {
+ std::lock_guard<std::mutex> its_lock(policies_mutex_);
+ policies_[std::make_pair(client, client)] = policy;
}
- policies_[client] = policy;
has_been_inserted= true;
}
}
} else if (i->first == "credentials") {
std::pair<uint32_t, uint32_t> its_uid_range, its_gid_range;
+ ranges_t its_uid_ranges, its_gid_ranges;
+
bool has_uid(false), has_gid(false);
+ bool has_uid_range(false), has_gid_range(false);
for (auto n = i->second.begin();
n != i->second.end(); ++n) {
std::string its_key(n->first);
std::string its_value(n->second.data());
if (its_key == "uid") {
- if (its_value != "any") {
- uint32_t its_uid;
- std::stringstream its_converter;
- its_converter << std::dec << its_value;
- its_converter >> its_uid;
- std::get<0>(its_uid_range) = its_uid;
- std::get<1>(its_uid_range) = its_uid;
+ if(n->second.data().empty()) {
+ load_ranges(n->second, its_uid_ranges);
+ has_uid_range = true;
} else {
- std::get<0>(its_uid_range) = 0;
- std::get<1>(its_uid_range) = 0xFFFFFFFF;
+ if (its_value != "any") {
+ uint32_t its_uid;
+ std::stringstream its_converter;
+ its_converter << std::dec << its_value;
+ its_converter >> its_uid;
+ std::get<0>(its_uid_range) = its_uid;
+ std::get<1>(its_uid_range) = its_uid;
+ } else {
+ std::get<0>(its_uid_range) = 0;
+ std::get<1>(its_uid_range) = 0xFFFFFFFF;
+ }
+ has_uid = true;
}
- has_uid = true;
} else if (its_key == "gid") {
- if (its_value != "any") {
- uint32_t its_gid;
- std::stringstream its_converter;
- its_converter << std::dec << its_value;
- its_converter >> its_gid;
- std::get<0>(its_gid_range) = its_gid;
- std::get<1>(its_gid_range) = its_gid;
+ if(n->second.data().empty()) {
+ load_ranges(n->second, its_gid_ranges);
+ has_gid_range = true;
} else {
- std::get<0>(its_gid_range) = 0;
- std::get<1>(its_gid_range) = 0xFFFFFFFF;
+ if (its_value != "any") {
+ uint32_t its_gid;
+ std::stringstream its_converter;
+ its_converter << std::dec << its_value;
+ its_converter >> its_gid;
+ std::get<0>(its_gid_range) = its_gid;
+ std::get<1>(its_gid_range) = its_gid;
+ } else {
+ std::get<0>(its_gid_range) = 0;
+ std::get<1>(its_gid_range) = 0xFFFFFFFF;
+ }
+ has_gid = true;
}
- has_gid = true;
} else if (its_key == "allow" || its_key == "deny") {
policy->allow_who_ = (its_key == "allow");
load_credential(n->second, policy->ids_);
@@ -1755,10 +2091,13 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
policy->allow_who_ = true;
policy->ids_.insert(std::make_pair(its_uids, its_gids));
}
-
+ if (has_uid_range && has_gid_range) {
+ policy->allow_who_ = true;
+ policy->ids_.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
+ }
} else if (i->first == "allow") {
if (allow_deny_set) {
- VSOMEIP_WARNING << "Security configuration: \"allow\" tag overrides "
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"allow\" tag overrides "
<< "already set \"deny\" tag. "
<< "Either \"deny\" or \"allow\" is allowed.";
}
@@ -1769,49 +2108,98 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
for (auto n = l->second.begin(); n != l->second.end(); ++n) {
service_t service = 0x0;
instance_t instance = 0x0;
+ ids_t its_instance_method_ranges;
for (auto k = n->second.begin(); k != n->second.end(); ++k) {
std::stringstream its_converter;
if (k->first == "service") {
std::string value = k->second.data();
its_converter << std::hex << value;
its_converter >> service;
- } else if (k->first == "instance") {
+ } else if (k->first == "instance") { // legacy definition for instances
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> instance;
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ } else if (k->first == "instances") { // new instances definition
+ for (auto p = k->second.begin(); p != k->second.end(); ++p) {
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ for (auto m = p->second.begin(); m != p->second.end(); ++m) {
+ if (m->first == "ids") {
+ load_instance_ranges(m->second, its_instance_ranges);
+ } else if (m->first == "methods") {
+ load_instance_ranges(m->second, its_method_ranges);
+ }
+ if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ }
+ }
+ }
+ if (its_instance_method_ranges.empty()) {
+ ranges_t its_legacy_instance_ranges;
+ ranges_t its_legacy_method_ranges;
+ its_legacy_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ // try to only load instance ranges with any method to be allowed
+ load_instance_ranges(k->second, its_legacy_instance_ranges);
+ if (!its_legacy_instance_ranges.empty() && !its_legacy_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_legacy_instance_ranges,
+ its_legacy_method_ranges));
+ }
+ }
}
}
- if (service != 0x0 && instance != 0x0) {
+ if (service != 0x0 && !its_instance_method_ranges.empty()) {
policy->services_.insert(
- std::make_pair(service, instance));
+ std::make_pair(service, its_instance_method_ranges));
}
}
} else if (l->first == "offers") {
for (auto n = l->second.begin(); n != l->second.end(); ++n) {
service_t service = 0x0;
instance_t instance = 0x0;
+ ranges_t its_instance_ranges;
for (auto k = n->second.begin(); k != n->second.end(); ++k) {
std::stringstream its_converter;
if (k->first == "service") {
std::string value = k->second.data();
its_converter << std::hex << value;
its_converter >> service;
- } else if (k->first == "instance") {
+ } else if (k->first == "instance") { // legacy definition for instances
std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> instance;
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else if (k->first == "instances") { // new instances definition
+ load_instance_ranges(k->second, its_instance_ranges);
}
}
- if (service != 0x0 && instance != 0x0) {
+ if (service != 0x0 && !its_instance_ranges.empty()) {
policy->offers_.insert(
- std::make_pair(service, instance));
+ std::make_pair(service, its_instance_ranges));
}
}
}
}
} else if (i->first == "deny") {
if (allow_deny_set) {
- VSOMEIP_WARNING << "Security configuration: \"deny\" tag overrides "
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"deny\" tag overrides "
<< "already set \"allow\" tag. "
<< "Either \"deny\" or \"allow\" is allowed.";
}
@@ -1822,21 +2210,60 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
for (auto n = l->second.begin(); n != l->second.end(); ++n) {
service_t service = 0x0;
instance_t instance = 0x0;
+ ids_t its_instance_method_ranges;
for (auto k = n->second.begin(); k != n->second.end(); ++k) {
std::stringstream its_converter;
if (k->first == "service") {
std::string value = k->second.data();
its_converter << std::hex << value;
its_converter >> service;
- } else if (k->first == "instance") {
+ } else if (k->first == "instance") { // legacy definition for instances
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> instance;
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ } else if (k->first == "instances") { // new instances definition
+ for (auto p = k->second.begin(); p != k->second.end(); ++p) {
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ for (auto m = p->second.begin(); m != p->second.end(); ++m) {
+ if (m->first == "ids") {
+ load_instance_ranges(m->second, its_instance_ranges);
+ } else if (m->first == "methods") {
+ load_instance_ranges(m->second, its_method_ranges);
+ }
+ if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ }
+ }
+ }
+ if (its_instance_method_ranges.empty()) {
+ ranges_t its_legacy_instance_ranges;
+ ranges_t its_legacy_method_ranges;
+ its_legacy_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ // try to only load instance ranges with any method to be allowed
+ load_instance_ranges(k->second, its_legacy_instance_ranges);
+ if (!its_legacy_instance_ranges.empty() && !its_legacy_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_legacy_instance_ranges,
+ its_legacy_method_ranges));
+ }
+ }
}
}
- if (service != 0x0 && instance != 0x0) {
+ if (service != 0x0 && !its_instance_method_ranges.empty()) {
policy->services_.insert(
- std::make_pair(service, instance));
+ std::make_pair(service, its_instance_method_ranges));
}
}
}
@@ -1844,21 +2271,31 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
for (auto n = l->second.begin(); n != l->second.end(); ++n) {
service_t service = 0x0;
instance_t instance = 0x0;
+ ranges_t its_instance_ranges;
for (auto k = n->second.begin(); k != n->second.end(); ++k) {
std::stringstream its_converter;
if (k->first == "service") {
std::string value = k->second.data();
its_converter << std::hex << value;
its_converter >> service;
- } else if (k->first == "instance") {
+ } else if (k->first == "instance") { // legacy definition for instances
std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> instance;
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else if (k->first == "instances") { // new instances definition
+ load_instance_ranges(k->second, its_instance_ranges);
}
}
- if (service != 0x0 && instance != 0x0) {
+ if (service != 0x0 && !its_instance_ranges.empty()) {
policy->offers_.insert(
- std::make_pair(service, instance));
+ std::make_pair(service, its_instance_ranges));
}
}
}
@@ -1867,6 +2304,7 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
}
if (!has_been_inserted) {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
any_client_policies_.push_back(policy);
}
}
@@ -1882,7 +2320,7 @@ void configuration_impl::load_credential(
} else if (its_key == "gid") {
load_ranges(j->second, its_gid_ranges);
} else {
- VSOMEIP_WARNING << "Security configuration: "
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
<< "Malformed credential (contains illegal key \""
<< its_key << "\"";
}
@@ -1892,6 +2330,41 @@ void configuration_impl::load_credential(
}
}
+void configuration_impl::load_security_update_whitelist(const element &_element) {
+#ifdef _WIN32
+ return;
+#endif
+ try {
+ auto optional = _element.tree_.get_child_optional("security-update-whitelist");
+ if (!optional) {
+ return;
+ }
+ auto found_whitelist = _element.tree_.get_child("security-update-whitelist");
+ for (auto its_whitelist = found_whitelist.begin();
+ its_whitelist != found_whitelist.end(); ++its_whitelist) {
+
+ if (its_whitelist->first == "uids") {
+ {
+ std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
+ load_ranges(its_whitelist->second, uid_whitelist_);
+ }
+ } else if (its_whitelist->first == "services") {
+ {
+ std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
+ load_service_ranges(its_whitelist->second, service_interface_whitelist_);
+ }
+ } else if (its_whitelist->first == "check-whitelist") {
+ if (its_whitelist->second.data() == "true") {
+ check_whitelist_ = true;
+ } else {
+ check_whitelist_ = false;
+ }
+ }
+ }
+ } catch (...) {
+ }
+}
+
void configuration_impl::load_ranges(
const boost::property_tree::ptree &_tree, ranges_t &_range) {
ranges_t its_ranges;
@@ -1902,7 +2375,6 @@ void configuration_impl::load_ranges(
std::stringstream its_converter;
its_converter << std::dec << its_data.data();
its_converter >> its_id;
-
its_ranges.insert(std::make_pair(its_id, its_id));
} else {
uint32_t its_first, its_last;
@@ -1929,7 +2401,7 @@ void configuration_impl::load_ranges(
}
has_last = true;
} else {
- VSOMEIP_WARNING << "Security configuration: "
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
<< " Malformed range. Contains illegal key ("
<< its_key << ")";
}
@@ -1944,6 +2416,128 @@ void configuration_impl::load_ranges(
_range = its_ranges;
}
+void configuration_impl::load_instance_ranges(
+ const boost::property_tree::ptree &_tree, ranges_t &_range) {
+ ranges_t its_ranges;
+ std::string key(_tree.data());
+ if (key == "any") {
+ its_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ _range = its_ranges;
+ return;
+ }
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ auto its_data = i->second;
+ if (!its_data.data().empty()) {
+ uint32_t its_id = 0x0;
+ std::stringstream its_converter;
+ its_converter << std::hex << its_data.data();
+ its_converter >> its_id;
+ if (its_id != 0x0) {
+ its_ranges.insert(std::make_pair(its_id, its_id));
+ }
+ } else {
+ uint32_t its_first, its_last;
+ bool has_first(false), has_last(false);
+ for (auto j = its_data.begin(); j != its_data.end(); ++j) {
+ std::string its_key(j->first);
+ std::string its_value(j->second.data());
+ if (its_key == "first") {
+ if (its_value == "max") {
+ its_first = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_first;
+ }
+ has_first = true;
+ } else if (its_key == "last") {
+ if (its_value == "max") {
+ its_last = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_last;
+ }
+ has_last = true;
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
+ << " Malformed range. Contains illegal key ("
+ << its_key << ")";
+ }
+ }
+
+ if (has_first && has_last) {
+ if( its_last > its_first) {
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ }
+ }
+ }
+
+ _range = its_ranges;
+}
+
+void configuration_impl::load_service_ranges(
+ const boost::property_tree::ptree &_tree, std::set<std::pair<service_t, service_t>> &_ranges) {
+ std::set<std::pair<service_t, service_t>> its_ranges;
+ std::string key(_tree.data());
+ if (key == "any") {
+ its_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ _ranges = its_ranges;
+ return;
+ }
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ auto its_data = i->second;
+ if (!its_data.data().empty()) {
+ service_t its_id = 0x0;
+ std::stringstream its_converter;
+ its_converter << std::hex << its_data.data();
+ its_converter >> its_id;
+ if (its_id != 0x0) {
+ its_ranges.insert(std::make_pair(its_id, its_id));
+ }
+ } else {
+ service_t its_first, its_last;
+ bool has_first(false), has_last(false);
+ for (auto j = its_data.begin(); j != its_data.end(); ++j) {
+ std::string its_key(j->first);
+ std::string its_value(j->second.data());
+ if (its_key == "first") {
+ if (its_value == "max") {
+ its_first = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_first;
+ }
+ has_first = true;
+ } else if (its_key == "last") {
+ if (its_value == "max") {
+ its_last = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_last;
+ }
+ has_last = true;
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Security interface whitelist configuration: "
+ << " Malformed range. Contains illegal key ("
+ << its_key << ")";
+ }
+ }
+
+ if (has_first && has_last) {
+ if( its_last >= its_first) {
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ }
+ }
+ }
+
+ _ranges = its_ranges;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Internal helper
///////////////////////////////////////////////////////////////////////////////
@@ -1994,6 +2588,10 @@ const boost::asio::ip::address & configuration_impl::get_unicast_address() const
return unicast_;
}
+const boost::asio::ip::address& configuration_impl::get_netmask() const {
+ return netmask_;
+}
+
unsigned short configuration_impl::get_diagnosis_address() const {
return diagnosis_;
}
@@ -2046,8 +2644,9 @@ std::string configuration_impl::get_unicast_address(service_t _service,
uint16_t configuration_impl::get_reliable_port(service_t _service,
instance_t _instance) const {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
uint16_t its_reliable(ILLEGAL_PORT);
- auto its_service = find_service(_service, _instance);
+ auto its_service = find_service_unlocked(_service, _instance);
if (its_service)
its_reliable = its_service->reliable_;
@@ -2056,8 +2655,9 @@ uint16_t configuration_impl::get_reliable_port(service_t _service,
uint16_t configuration_impl::get_unreliable_port(service_t _service,
instance_t _instance) const {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
uint16_t its_unreliable = ILLEGAL_PORT;
- auto its_service = find_service(_service, _instance);
+ auto its_service = find_service_unlocked(_service, _instance);
if (its_service)
its_unreliable = its_service->unreliable_;
@@ -2174,6 +2774,17 @@ std::size_t configuration_impl::get_io_thread_count(const std::string &_name) co
return its_io_thread_count;
}
+int configuration_impl::get_io_thread_nice_level(const std::string &_name) const {
+ int its_io_thread_nice_level = VSOMEIP_IO_THREAD_NICE_LEVEL;
+
+ auto found_application = applications_.find(_name);
+ if (found_application != applications_.end()) {
+ its_io_thread_nice_level = std::get<6>(found_application->second);
+ }
+
+ return its_io_thread_nice_level;
+}
+
std::size_t configuration_impl::get_max_dispatchers(
const std::string &_name) const {
std::size_t its_max_dispatchers = VSOMEIP_MAX_DISPATCHERS;
@@ -2200,6 +2811,7 @@ std::size_t configuration_impl::get_max_dispatch_time(
std::set<std::pair<service_t, instance_t> >
configuration_impl::get_remote_services() const {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
std::set<std::pair<service_t, instance_t> > its_remote_services;
for (auto i : services_) {
for (auto j : i.second) {
@@ -2335,8 +2947,9 @@ bool configuration_impl::find_port(uint16_t &_port, uint16_t _remote, bool _reli
bool configuration_impl::is_event_reliable(service_t _service,
instance_t _instance, event_t _event) const {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
bool is_reliable(false);
- auto its_service = find_service(_service, _instance);
+ auto its_service = find_service_unlocked(_service, _instance);
if (its_service) {
auto its_event = its_service->events_.find(_event);
if (its_event != its_service->events_.end()) {
@@ -2353,6 +2966,12 @@ bool configuration_impl::is_event_reliable(service_t _service,
std::shared_ptr<service> configuration_impl::find_service(service_t _service,
instance_t _instance) const {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
+ return find_service_unlocked(_service, _instance);
+}
+
+std::shared_ptr<service> configuration_impl::find_service_unlocked(service_t _service,
+ instance_t _instance) const {
std::shared_ptr<service> its_service;
auto find_service = services_.find(_service);
if (find_service != services_.end()) {
@@ -2517,8 +3136,8 @@ uint32_t configuration_impl::get_watchdog_timeout() const {
uint32_t configuration_impl::get_allowed_missing_pongs() const {
return watchdog_->missing_pongs_allowed_;
}
-std::uint32_t configuration_impl::get_umask() const {
- return umask_;
+std::uint32_t configuration_impl::get_permissions_uds() const {
+ return permissions_uds_;
}
std::uint32_t configuration_impl::get_permissions_shm() const {
@@ -2529,24 +3148,25 @@ bool configuration_impl::is_security_enabled() const {
return policy_enabled_;
}
+bool configuration_impl::is_audit_mode_enabled() const {
+ return check_credentials_;
+}
+
bool configuration_impl::check_credentials(client_t _client, uint32_t _uid,
uint32_t _gid) {
if (!policy_enabled_) {
return true;
}
- // store the client -> (uid, gid) mapping
- ids_[_client] = std::make_pair(_uid, _gid);
-
std::vector<std::shared_ptr<policy> > its_policies;
bool has_id(false);
- auto its_client = policies_.find(_client);
-
- // Use client specific policy if it does exist
- if (its_client != policies_.end())
- its_policies.push_back(its_client->second);
- else
+ auto found_policy = find_client_id_policy(_client);
+ if (found_policy) {
+ its_policies.push_back(found_policy);
+ } else {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
its_policies = any_client_policies_;
+ }
for (const auto &p : its_policies) {
for (auto its_credential : p->ids_) {
@@ -2571,21 +3191,38 @@ bool configuration_impl::check_credentials(client_t _client, uint32_t _uid,
}
if ((has_id && p->allow_who_) || (!has_id && !p->allow_who_)) {
+ if (!store_client_to_uid_gid_mapping(_client,_uid, _gid)) {
+ std::string security_mode_text = "!";
+ if (!check_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << _uid << "/" << _gid
+ << " : Check credentials failed as existing credentials would be overwritten"
+ << security_mode_text;
+
+ return !check_credentials_;
+ }
+ store_uid_gid_to_client_mapping(_uid, _gid, _client);
return true;
}
}
+ std::string security_mode_text = " ~> Skip!";
if (!check_credentials_) {
- VSOMEIP_INFO << "vSomeIP Security: Check credentials failed for client 0x"
- << std::hex << _client << " with UID/GID=" << std::dec << _uid
- << "/" << _gid << " but will be allowed due to audit mode is active!";
+ security_mode_text = " but will be allowed due to audit mode is active!";
}
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << _uid << "/" << _gid
+ << " : Check credentials failed" << security_mode_text;
+
return !check_credentials_;
}
bool configuration_impl::is_client_allowed(client_t _client, service_t _service,
- instance_t _instance) const {
+ instance_t _instance, method_t _method, bool _is_request_service) const {
if (!policy_enabled_) {
return true;
}
@@ -2593,35 +3230,39 @@ bool configuration_impl::is_client_allowed(client_t _client, service_t _service,
uint32_t its_uid(0xffffffff), its_gid(0xffffffff);
bool must_apply(true);
std::vector<std::shared_ptr<policy> > its_policies;
- auto its_client = policies_.find(_client);
-
- // Use client specific policy if it does exist
- if (its_client != policies_.end())
- its_policies.push_back(its_client->second);
+ auto found_policy = find_client_id_policy(_client);
+ if (found_policy)
+ its_policies.push_back(found_policy);
else {
must_apply = false;
- its_policies = any_client_policies_;
+ {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ its_policies = any_client_policies_;
+ }
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
auto found_id = ids_.find(_client);
if (found_id != ids_.end()) {
its_uid = found_id->second.first;
its_gid = found_id->second.second;
} else {
+ std::string security_mode_text = " ~> Skip!";
if (!check_credentials_) {
- VSOMEIP_INFO << "vSomeIP Security: Cannot determine uid/gid for"
- "client 0x" << std::hex << _client
- << ". Therefore it isn't allowed to communicate to service/instance "
- << _service << "/" << _instance
- << " but will be allowed due to audit mode is active!";
+ security_mode_text = " but will be allowed due to audit mode is active!";
}
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : Cannot determine uid/gid. Therefore it isn't allowed to communicate to service/instance "
+ << _service << "/" << _instance
+ << security_mode_text;
+
return !check_credentials_;
}
}
for (const auto &p : its_policies) {
- bool has_uid(false), has_gid(false);
+ bool has_uid(false), has_gid(false), has_service(false), has_instance_id(false), has_method_id(false);
if (must_apply) {
- has_uid = has_gid = p->allow_what_;
+ has_uid = has_gid = p->allow_who_;
} else {
for (auto its_credential : p->ids_) {
has_uid = has_gid = false;
@@ -2643,21 +3284,68 @@ bool configuration_impl::is_client_allowed(client_t _client, service_t _service,
}
}
- auto its_service = p->services_.find(std::make_pair(_service, _instance));
- if (has_uid && has_gid && p->allow_what_ && its_service != p->services_.end()) {
- return true;
- } else if (!has_uid && !has_gid && !p->allow_what_ && its_service == p->services_.end()) {
- return true;
+ for (auto its_offer : p->services_) {
+ if (std::get<0>(its_offer) == _service) {
+ for (auto its_ids : std::get<1>(its_offer)) {
+ has_service = has_instance_id = has_method_id = false;
+ for (auto its_instance_range : std::get<0>(its_ids)) {
+ if (std::get<0>(its_instance_range) <= _instance && _instance <= std::get<1>(its_instance_range)) {
+ has_instance_id = true;
+ break;
+ }
+ }
+ if (!_is_request_service) {
+ for (auto its_method_range : std::get<1>(its_ids)) {
+ if (std::get<0>(its_method_range) <= _method && _method <= std::get<1>(its_method_range)) {
+ has_method_id = true;
+ break;
+ }
+ }
+ } else {
+ // handle VSOMEIP_REQUEST_SERVICE
+ has_method_id = true;
+ }
+
+ if (has_instance_id && has_method_id) {
+ has_service = true;
+ break;
+ }
+ }
+ if (has_service)
+ break;
+ }
+ }
+
+ if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
+ if (p->allow_what_) {
+ // allow policy
+ if (has_service) {
+ return true;
+ }
+ } else {
+ // deny policy
+ // allow client if the service / instance / !ANY_METHOD was not found
+ if ((!has_service && (_method != ANY_METHOD))
+ // allow client if the service / instance / ANY_METHOD was not found
+ // and it is a "deny nothing" policy
+ || (!has_service && (_method == ANY_METHOD) && p->services_.empty())) {
+ return true;
+ }
+ }
}
}
+ std::string security_mode_text = " ~> Skip!";
if (!check_credentials_) {
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " isn't allowed to communicate with service/instance "
- << _service << "/" << _instance
- << " but will be allowed due to audit mode is active!";
+ security_mode_text = " but will be allowed due to audit mode is active!";
}
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
+ << " : Isn't allowed to communicate with service/instance/(method / event) " << std::hex
+ << _service << "/" << _instance << "/" << _method
+ << security_mode_text;
+
return !check_credentials_;
}
@@ -2670,35 +3358,39 @@ bool configuration_impl::is_offer_allowed(client_t _client, service_t _service,
uint32_t its_uid(0xffffffff), its_gid(0xffffffff);
bool must_apply(true);
std::vector<std::shared_ptr<policy> > its_policies;
- auto its_client = policies_.find(_client);
-
- // Use client specific policy if it does exist
- if (its_client != policies_.end())
- its_policies.push_back(its_client->second);
+ auto found_policy = find_client_id_policy(_client);
+ if (found_policy)
+ its_policies.push_back(found_policy);
else {
must_apply = false;
- its_policies = any_client_policies_;
+ {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ its_policies = any_client_policies_;
+ }
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
auto found_id = ids_.find(_client);
if (found_id != ids_.end()) {
its_uid = found_id->second.first;
its_gid = found_id->second.second;
} else {
+ std::string audit_mode_text = " ~> Skip offer!";
if (!check_credentials_) {
- VSOMEIP_INFO << "vSomeIP Security: Cannot determine uid/gid for"
- "client 0x" << std::hex << _client
- << ". Therefore it isn't allowed to offer service/instance "
- << _service << "/" << _instance
- << " but will be allowed due to audit mode is active!";
+ audit_mode_text = " but will be allowed due to audit mode is active!";
}
+
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : Cannot determine uid/gid. Therefore it isn't allowed to offer service/instance "
+ << _service << "/" << _instance << audit_mode_text;
+
return !check_credentials_;
}
}
for (const auto &p : its_policies) {
- bool has_uid(false), has_gid(false);
+ bool has_uid(false), has_gid(false), has_offer(false);
if (must_apply) {
- has_uid = has_gid = p->allow_what_;
+ has_uid = has_gid = p->allow_who_;
} else {
for (auto its_credential : p->ids_) {
has_uid = has_gid = false;
@@ -2720,26 +3412,152 @@ bool configuration_impl::is_offer_allowed(client_t _client, service_t _service,
}
}
- auto its_offer = p->offers_.find(std::make_pair(_service, _instance));
- if (has_uid && has_gid
- && p->allow_what_ && its_offer != p->offers_.end()) {
- return true;
- } else if (!has_uid && !has_gid
- && !p->allow_what_ && its_offer == p->offers_.end()) {
- return true;
+ for (auto its_offer : p->offers_) {
+ has_offer = false;
+ if (std::get<0>(its_offer) == _service) {
+ for (auto its_instance_range : std::get<1>(its_offer)) {
+ if (std::get<0>(its_instance_range) <= _instance && _instance <= std::get<1>(its_instance_range)) {
+ has_offer = true;
+ break;
+ }
+ }
+ if (has_offer)
+ break;
+ }
+ }
+
+ if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
+ if (p->allow_what_ == has_offer) {
+ return true;
+ }
}
}
+ std::string security_mode_text = " ~> Skip offer!";
if (!check_credentials_) {
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " isn't allowed to offer service/instance "
- << _service << "/" << _instance
- << " but will be allowed due to audit mode is active!";
+ security_mode_text = " but will be allowed due to audit mode is active!";
}
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
+ << " isn't allowed to offer service/instance " << std::hex
+ << _service << "/" << _instance
+ << security_mode_text;
+
+
return !check_credentials_;
}
+bool configuration_impl::store_client_to_uid_gid_mapping(client_t _client,
+ uint32_t _uid, uint32_t _gid) {
+ {
+ // store the client -> (uid, gid) mapping
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
+ auto found_client = ids_.find(_client);
+ if (found_client != ids_.end()) {
+ if (found_client->second != std::make_pair(_uid, _gid)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x"
+ << std::hex << _client << " with UID/GID="
+ << std::dec << _uid << "/" << _gid << " : Overwriting existing credentials UID/GID="
+ << std::dec << std::get<0>(found_client->second) << "/"
+ << std::get<1>(found_client->second);
+ found_client->second = std::make_pair(_uid, _gid);
+ return true;
+ }
+ } else {
+ ids_[_client] = std::make_pair(_uid, _gid);
+ }
+ return true;
+ }
+}
+
+bool configuration_impl::get_client_to_uid_gid_mapping(client_t _client, std::pair<uint32_t, uint32_t> &_uid_gid) {
+ {
+ // get the UID / GID of the client
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
+ if (ids_.find(_client) != ids_.end()) {
+ _uid_gid = ids_[_client];
+ return true;
+ }
+ return false;
+ }
+}
+
+bool configuration_impl::remove_client_to_uid_gid_mapping(client_t _client) {
+ std::pair<uint32_t, uint32_t> its_uid_gid;
+ bool client_removed(false);
+ bool uid_gid_removed(false);
+ {
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
+ auto found_client = ids_.find(_client);
+ if (found_client != ids_.end()) {
+ its_uid_gid = found_client->second;
+ ids_.erase(found_client);
+ client_removed = true;
+ }
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
+ if (client_removed) {
+ auto found_uid_gid = uid_to_clients_.find(its_uid_gid);
+ if (found_uid_gid != uid_to_clients_.end()) {
+ auto its_client = found_uid_gid->second.find(_client);
+ if (its_client != found_uid_gid->second.end()) {
+ found_uid_gid->second.erase(its_client);
+ if (found_uid_gid->second.empty()) {
+ uid_to_clients_.erase(found_uid_gid);
+ }
+ uid_gid_removed = true;
+ }
+ }
+ } else {
+ for (auto its_uid_gid = uid_to_clients_.begin();
+ its_uid_gid != uid_to_clients_.end(); ++its_uid_gid) {
+ auto its_client = its_uid_gid->second.find(_client);
+ if (its_client != its_uid_gid->second.end()) {
+ its_uid_gid->second.erase(its_client);
+ if (its_uid_gid->second.empty()) {
+ uid_to_clients_.erase(its_uid_gid);
+ }
+ uid_gid_removed = true;
+ break;
+ }
+ }
+ }
+ }
+ return (client_removed && uid_gid_removed);
+}
+
+void configuration_impl::store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid,
+ client_t _client) {
+ {
+ // store the uid gid to clients mapping
+ std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
+ std::set<client_t> mapped_clients;
+ if (uid_to_clients_.find(std::make_pair(_uid, _gid)) != uid_to_clients_.end()) {
+ mapped_clients = uid_to_clients_[std::make_pair(_uid, _gid)];
+ mapped_clients.insert(_client);
+ uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
+ } else {
+ mapped_clients.insert(_client);
+ uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
+ }
+ }
+}
+
+bool configuration_impl::get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
+ std::set<client_t> &_clients) {
+ {
+ // get the clients corresponding to uid, gid
+ std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
+ if (uid_to_clients_.find(_uid_gid) != uid_to_clients_.end()) {
+ _clients = uid_to_clients_[_uid_gid];
+ return true;
+ }
+ return false;
+ }
+}
+
std::map<plugin_type_e, std::set<std::string>> configuration_impl::get_plugins(
const std::string &_name) const {
std::map<plugin_type_e, std::set<std::string>> result;
@@ -2793,8 +3611,8 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
uint16_t data_id(0);
std::string variant("");
std::string profile("");
- uint16_t service_id(0);
- uint16_t event_id(0);
+ service_t service_id(0);
+ event_t event_id(0);
uint16_t crc_offset(0);
uint8_t data_id_mode(0);
@@ -2861,8 +3679,7 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
its_converter >> data_length;
}
}
- e2exf::data_identifier its_data_identifier = {service_id, event_id};
- e2e_configuration_[its_data_identifier] = std::make_shared<cfg::e2e>(
+ e2e_configuration_[std::make_pair(service_id, event_id)] = std::make_shared<cfg::e2e>(
data_id,
variant,
profile,
@@ -2876,7 +3693,7 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
);
}
-std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> configuration_impl::get_e2e_configuration() const {
+std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> configuration_impl::get_e2e_configuration() const {
return e2e_configuration_;
}
@@ -3217,6 +4034,55 @@ void configuration_impl::load_event_debounce_ignore(
}
}
+void configuration_impl::load_offer_acceptance_required(
+ const element &_element) {
+ const std::string oar("offer_acceptance_required");
+ try {
+ std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
+ if (_element.tree_.get_child_optional(oar)) {
+ if (is_configured_[ET_OFFER_ACCEPTANCE_REQUIRED]) {
+ VSOMEIP_WARNING << "Multiple definitions of " << oar
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ for (const auto& ipe : _element.tree_.get_child(oar)) {
+ boost::system::error_code ec;
+ boost::asio::ip::address its_address =
+ boost::asio::ip::address::from_string(ipe.first.data(), ec);
+ if (!its_address.is_unspecified()) {
+ offer_acceptance_required_ips_[its_address] = ipe.second.data();
+ }
+ }
+ is_configured_[ET_OFFER_ACCEPTANCE_REQUIRED] = true;
+ }
+ }
+ } catch (...) {
+ // intentionally left empty
+ }
+}
+
+void configuration_impl::load_udp_receive_buffer_size(const element &_element) {
+ const std::string urbs("udp-receive-buffer-size");
+ try {
+ if (_element.tree_.get_child_optional(urbs)) {
+ if (is_configured_[ET_UDP_RECEIVE_BUFFER_SIZE]) {
+ VSOMEIP_WARNING << "Multiple definitions of " << urbs
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ const std::string s(_element.tree_.get_child(urbs).data());
+ try {
+ udp_receive_buffer_size_ = static_cast<std::uint32_t>(std::stoul(
+ s.c_str(), NULL, 10));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR<< __func__ << ": " << urbs << " " << e.what();
+ }
+ is_configured_[ET_UDP_RECEIVE_BUFFER_SIZE] = true;
+ }
+ }
+ } catch (...) {
+ // intentionally left empty
+ }
+}
+
std::shared_ptr<debounce> configuration_impl::get_debounce(
service_t _service, instance_t _instance, event_t _event) const {
auto found_service = debounces_.find(_service);
@@ -3232,5 +4098,296 @@ std::shared_ptr<debounce> configuration_impl::get_debounce(
return nullptr;
}
+void configuration_impl::load_tcp_restart_settings(const element &_element) {
+ const std::string tcp_restart_aborts_max("tcp-restart-aborts-max");
+ const std::string tcp_connect_time_max("tcp-connect-time-max");
+
+ try {
+ if (_element.tree_.get_child_optional(tcp_restart_aborts_max)) {
+ if (is_configured_[ET_TCP_RESTART_ABORTS_MAX]) {
+ VSOMEIP_WARNING << "Multiple definitions for "
+ << tcp_restart_aborts_max
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ is_configured_[ET_TCP_RESTART_ABORTS_MAX] = true;
+ auto mpsl = _element.tree_.get_child(
+ tcp_restart_aborts_max);
+ std::string s(mpsl.data());
+ try {
+ tcp_restart_aborts_max_ =
+ static_cast<std::uint32_t>(std::stoul(
+ s.c_str(), NULL, 10));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR<<__func__ << ": " << tcp_restart_aborts_max
+ << " " << e.what();
+ }
+ }
+ }
+ if (_element.tree_.get_child_optional(tcp_connect_time_max)) {
+ if (is_configured_[ET_TCP_CONNECT_TIME_MAX]) {
+ VSOMEIP_WARNING << "Multiple definitions for "
+ << tcp_connect_time_max
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ is_configured_[ET_TCP_CONNECT_TIME_MAX] = true;
+ auto mpsl = _element.tree_.get_child(tcp_connect_time_max);
+ std::string s(mpsl.data());
+ try {
+ tcp_connect_time_max_=
+ static_cast<std::uint32_t>(
+ std::stoul(s.c_str(), NULL, 10));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR<< __func__ << ": "<< tcp_connect_time_max
+ << " " << e.what();
+ }
+ }
+ }
+ } catch (...) {
+ }
+}
+
+std::uint32_t configuration_impl::get_max_tcp_restart_aborts() const {
+ return tcp_restart_aborts_max_;
+}
+
+std::uint32_t configuration_impl::get_max_tcp_connect_time() const {
+ return tcp_connect_time_max_;
+}
+
+bool configuration_impl::offer_acceptance_required(
+ const boost::asio::ip::address& _address) const {
+ std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
+ return offer_acceptance_required_ips_.find(_address)
+ != offer_acceptance_required_ips_.end();
+}
+
+void configuration_impl::set_offer_acceptance_required(
+ const boost::asio::ip::address& _address, const std::string& _path,
+ bool _enable) {
+ std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
+ if (_enable) {
+ const auto found_address = offer_acceptance_required_ips_.find(_address);
+ if (found_address != offer_acceptance_required_ips_.end()) {
+ boost::system::error_code ec;
+ VSOMEIP_WARNING << __func__ << " configuration for: "
+ << found_address->first.to_string(ec) << " -> "
+ << found_address->second << " already configured."
+ << " Won't update with: "<< _path;
+ } else {
+ offer_acceptance_required_ips_[_address] = _path;
+ }
+ } else {
+ offer_acceptance_required_ips_.erase(_address);
+ }
+}
+
+std::map<boost::asio::ip::address, std::string>
+configuration_impl::get_offer_acceptance_required() {
+ std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
+ return offer_acceptance_required_ips_;
+}
+
+std::uint32_t configuration_impl::get_udp_receive_buffer_size() const {
+ return udp_receive_buffer_size_;
+}
+
+std::shared_ptr<policy> configuration_impl::find_client_id_policy(client_t _client) const {
+ std::lock_guard<std::mutex> its_lock(policies_mutex_);
+ for (auto client_id_pair : policies_) {
+ if (std::get<0>(client_id_pair.first) <= _client
+ && _client <= std::get<1>(client_id_pair.first)) {
+ return client_id_pair.second;
+ }
+ }
+ return nullptr;
+}
+
+bool configuration_impl::remove_security_policy(uint32_t _uid, uint32_t _gid) {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ bool was_removed(false);
+ if (!any_client_policies_.empty()) {
+ std::vector<std::shared_ptr<policy>>::iterator p_it = any_client_policies_.begin();
+ while (p_it != any_client_policies_.end()) {
+ bool has_uid(false), has_gid(false);
+ for (auto its_credential : p_it->get()->ids_) {
+ has_uid = has_gid = false;
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
+ has_uid = true;
+ break;
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
+ has_gid = true;
+ break;
+ }
+ }
+ // only remove "credentials allow" policies to prevent removal of
+ // blacklist configured in file
+ if (has_uid && has_gid && p_it->get()->allow_who_) {
+ was_removed = true;
+ break;
+ }
+ }
+ if (was_removed) {
+ p_it = any_client_policies_.erase(p_it);
+ break;
+ } else {
+ ++p_it;
+ }
+ }
+ }
+ return was_removed;
+}
+
+void configuration_impl::update_security_policy(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy) {
+ remove_security_policy(_uid, _gid);
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ any_client_policies_.push_back(_policy);
+}
+
+void configuration_impl::add_security_credentials(uint32_t _uid, uint32_t _gid,
+ ::std::shared_ptr<policy> _credentials_policy, client_t _client) {
+
+ bool was_found(false);
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ for (auto its_policy : any_client_policies_) {
+ bool has_uid(false), has_gid(false);
+ for (auto its_credential : its_policy->ids_) {
+ has_uid = has_gid = false;
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
+ has_uid = true;
+ break;
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
+ has_gid = true;
+ break;
+ }
+ }
+ if (has_uid && has_gid && its_policy->allow_who_) {
+ was_found = true;
+ break;
+ }
+ }
+ if (was_found) {
+ break;
+ }
+ }
+ // Do not add the new (credentials-only-policy) if a allow credentials policy with same credentials was found
+ if (!was_found) {
+ any_client_policies_.push_back(_credentials_policy);
+ VSOMEIP_INFO << __func__ << " Added security credentials at client: 0x"
+ << std::hex << _client << std::dec << " with UID: " << _uid << " GID: " << _gid;
+ }
+}
+
+bool configuration_impl::is_remote_client_allowed() const {
+ if (!check_credentials_) {
+ return true;
+ }
+ return allow_remote_clients_;
+}
+
+bool configuration_impl::is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const {
+ bool uid_allowed(false);
+ {
+ std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
+ for (auto its_uid_range : uid_whitelist_) {
+ if (std::get<0>(its_uid_range) <= _uid && _uid <= std::get<1>(its_uid_range)) {
+ uid_allowed = true;
+ break;
+ }
+ }
+ }
+
+ if (uid_allowed) {
+ std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
+ for (auto its_request : _policy->services_) {
+ auto its_requested_service = std::get<0>(its_request);
+ bool has_service(false);
+ for (auto its_service_range : service_interface_whitelist_) {
+ if (std::get<0>(its_service_range) <= its_requested_service
+ && its_requested_service <= std::get<1>(its_service_range)) {
+ has_service = true;
+ break;
+ }
+ }
+ if (!has_service) {
+ if (!check_whitelist_) {
+ VSOMEIP_INFO << "vSomeIP Security: Policy update requesting service ID: "
+ << std::hex << its_requested_service
+ << " is not allowed, but will be allowed due to whitelist audit mode is active!";
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Policy update requesting service ID: "
+ << std::hex << its_requested_service
+ << " is not allowed! -> ignore update";
+ }
+ return !check_whitelist_;
+ }
+ }
+ return true;
+ } else {
+ if (!check_whitelist_) {
+ VSOMEIP_INFO << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
+ << " is not allowed, but will be allowed due to whitelist audit mode is active!";
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
+ << " is not allowed! -> ignore update";
+ }
+ return !check_whitelist_;
+ }
+}
+
+bool configuration_impl::is_policy_removal_allowed(uint32_t _uid) const {
+ std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
+ for (auto its_uid_range : uid_whitelist_) {
+ if (std::get<0>(its_uid_range) <= _uid && _uid <= std::get<1>(its_uid_range)) {
+ return true;
+ }
+ }
+
+ if (!check_whitelist_) {
+ VSOMEIP_INFO << "vSomeIP Security: Policy removal for UID: " << std::dec << _uid
+ << " is not allowed, but will be allowed due to whitelist audit mode is active!";
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Policy removal for UID: " << std::dec << _uid
+ << " is not allowed! -> ignore removal";
+ }
+ return !check_whitelist_;
+}
+
+bool configuration_impl::check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const {
+ if (_client != get_id(routing_host_)) {
+ return true;
+ } else {
+ std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
+ if ( std::get<0>(routing_credentials_) == _uid
+ && std::get<1>(routing_credentials_) == _gid) {
+ return true;
+ }
+ }
+
+ std::string security_mode_text = "!";
+ if (!check_routing_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x"
+ << std::hex << _client << " and UID/GID=" << std::dec << _uid
+ << "/" << _gid << " : Check routing credentials failed as "
+ << "configured routing manager credentials "
+ << "do not match with routing manager credentials"
+ << security_mode_text;
+
+ return !check_routing_credentials_;
+}
+
+std::uint32_t configuration_impl::get_shutdown_timeout() const {
+ return shutdown_timeout_;
+}
+
} // namespace config
} // namespace vsomeip
diff --git a/implementation/e2e_protection/include/e2exf/config.hpp b/implementation/e2e_protection/include/e2exf/config.hpp
index 3667211..bf1fb50 100644
--- a/implementation/e2e_protection/include/e2exf/config.hpp
+++ b/implementation/e2e_protection/include/e2exf/config.hpp
@@ -6,6 +6,7 @@
#ifndef VSOMEIP_E2EXF_CONFIG_HPP
#define VSOMEIP_E2EXF_CONFIG_HPP
+#include <vsomeip/primitive_types.hpp>
#include "../e2e/profile/profile_interface/checker.hpp"
#include "../e2e/profile/profile_interface/protector.hpp"
@@ -15,12 +16,9 @@
namespace vsomeip {
namespace e2exf {
-using session_id = uint16_t;
-using instance_id = uint16_t;
+using data_identifier_t = std::pair<service_t, event_t>;
-using data_identifier = std::pair<session_id, instance_id>;
-
-std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier &_data_identifier);
+std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier_t &_data_identifier);
} // namespace e2exf
} // namespace vsomeip
diff --git a/implementation/e2e_protection/src/e2exf/config.cpp b/implementation/e2e_protection/src/e2exf/config.cpp
index e210faf..c7df18a 100644
--- a/implementation/e2e_protection/src/e2exf/config.cpp
+++ b/implementation/e2e_protection/src/e2exf/config.cpp
@@ -8,7 +8,7 @@
namespace vsomeip {
-std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier &_data_identifier) {
+std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier_t &_data_identifier) {
_os << _data_identifier.first << _data_identifier.second;
return _os;
}
diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp
index 97819bc..409bba0 100644
--- a/implementation/endpoints/include/client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/client_endpoint_impl.hpp
@@ -14,6 +14,7 @@
#include <boost/array.hpp>
#include <boost/asio/io_service.hpp>
+#include <boost/asio/strand.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/utility.hpp>
#include <vsomeip/constants.hpp>
@@ -53,7 +54,8 @@ public:
bool is_client() const;
- bool is_connected() const;
+ bool is_established() const;
+ void set_established(bool _established);
void set_connected(bool _connected);
virtual bool get_remote_address(boost::asio::ip::address &_address) const;
virtual std::uint16_t get_remote_port() const;
@@ -76,6 +78,7 @@ protected:
enum class cei_state_e : std::uint8_t {
CLOSED,
CONNECTING,
+ CONNECTED,
ESTABLISHED
};
virtual void send_queued() = 0;
@@ -98,6 +101,7 @@ protected:
boost::asio::steady_timer connect_timer_;
std::atomic<uint32_t> connect_timeout_;
std::atomic<cei_state_e> state_;
+ std::atomic<std::uint32_t> reconnect_counter_;
// send data
message_buffer_ptr_t packetizer_;
@@ -110,9 +114,13 @@ protected:
std::atomic<std::uint16_t> local_port_;
+ boost::asio::io_service::strand strand_;
+
private:
virtual void set_local_port() = 0;
virtual std::string get_remote_information() const = 0;
+ virtual std::uint32_t get_max_allowed_reconnects() const = 0;
+ virtual void max_allowed_reconnects_reached() = 0;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp
index f3bf510..b1204f0 100644
--- a/implementation/endpoints/include/endpoint.hpp
+++ b/implementation/endpoints/include/endpoint.hpp
@@ -25,7 +25,7 @@ public:
virtual void start() = 0;
virtual void stop() = 0;
- virtual bool is_connected() const = 0;
+ virtual bool is_established() const = 0;
virtual bool send(const byte_t *_data, uint32_t _size,
bool _flush = true) = 0;
@@ -57,7 +57,7 @@ public:
virtual void print_status() = 0;
- virtual void set_connected(bool _connected) = 0;
+ virtual void set_established(bool _established) = 0; virtual void set_connected(bool _connected) = 0;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp
index 214a6d0..16b3af5 100644
--- a/implementation/endpoints/include/local_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp
@@ -63,6 +63,8 @@ private:
std::size_t _bytes);
void set_local_port();
std::string get_remote_information() const;
+ std::uint32_t get_max_allowed_reconnects() const;
+ void max_allowed_reconnects_reached();
message_buffer_t recv_buffer_;
};
diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp
index aee73c4..8ff8a10 100644
--- a/implementation/endpoints/include/local_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp
@@ -43,7 +43,8 @@ public:
boost::asio::io_service &_io,
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit);
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _mode);
local_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
endpoint_type _local,
@@ -51,7 +52,8 @@ public:
std::uint32_t _max_message_size,
int native_socket,
std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit);
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _mode);
virtual ~local_server_endpoint_impl();
@@ -90,12 +92,14 @@ private:
void send_queued(const queue_iterator_type _queue_iterator);
void set_bound_client(client_t _client);
+ client_t get_bound_client() const;
+
std::size_t get_recv_buffer_capacity() const;
private:
connection(std::weak_ptr<local_server_endpoint_impl> _server,
- std::uint32_t _recv_buffer_size_initial,
std::uint32_t _max_message_size,
+ std::uint32_t _recv_buffer_size_initial,
std::uint32_t _buffer_shrink_threshold,
boost::asio::io_service &_io_service);
@@ -133,6 +137,10 @@ private:
typedef std::map<endpoint_type, connection::ptr> connections_t;
std::mutex connections_mutex_;
connections_t connections_;
+
+ std::mutex client_connections_mutex_;
+ std::map<client_t, connection::ptr> client_connections_;
+
const std::uint32_t buffer_shrink_threshold_;
private:
diff --git a/implementation/endpoints/include/netlink_connector.hpp b/implementation/endpoints/include/netlink_connector.hpp
index f71ba88..730874e 100644
--- a/implementation/endpoints/include/netlink_connector.hpp
+++ b/implementation/endpoints/include/netlink_connector.hpp
@@ -67,7 +67,7 @@ public:
/// Get the underlying endpoint in the native type.
data_type* data()
{
- return &sockaddr;
+ return reinterpret_cast<struct sockaddr*>(&sockaddr);
}
/// Get the underlying endpoint in the native type.
diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp
index 60e8ff4..68e719b 100644
--- a/implementation/endpoints/include/server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/server_endpoint_impl.hpp
@@ -38,7 +38,8 @@ public:
bool is_client() const;
void restart(bool _force);
- bool is_connected() const;
+ bool is_established() const;
+ void set_established(bool _established);
void set_connected(bool _connected);
bool send(const uint8_t *_data, uint32_t _size, bool _flush);
bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
index cbadf5a..77cbd39 100644
--- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
@@ -25,9 +25,11 @@ public:
endpoint_type _remote,
boost::asio::io_service &_io,
std::uint32_t _max_message_size,
- std::uint32_t buffer_shrink_threshold,
+ std::uint32_t _buffer_shrink_threshold,
std::chrono::milliseconds _send_timeout,
- configuration::endpoint_queue_limit_t _queue_limit);
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _tcp_restart_aborts_max,
+ std::uint32_t _tcp_connect_time_max);
virtual ~tcp_client_endpoint_impl();
void start();
@@ -71,6 +73,8 @@ private:
service_t _service, method_t _method, client_t _client, session_t _session,
std::chrono::steady_clock::time_point _start);
std::string get_remote_information() const;
+ std::uint32_t get_max_allowed_reconnects() const;
+ void max_allowed_reconnects_reached();
const std::uint32_t recv_buffer_size_initial_;
message_buffer_ptr_t recv_buffer_;
@@ -82,6 +86,11 @@ private:
std::chrono::steady_clock::time_point last_cookie_sent_;
const std::chrono::milliseconds send_timeout_;
const std::chrono::milliseconds send_timeout_warning_;
+
+ std::uint32_t tcp_restart_aborts_max_;
+ std::uint32_t tcp_connect_time_max_;
+ std::atomic<uint32_t> aborted_restart_count_;
+ std::chrono::steady_clock::time_point connect_timepoint_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
index 1866d05..b11da93 100644
--- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
@@ -30,14 +30,15 @@ public:
endpoint_type _local,
endpoint_type _remote,
boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit);
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _udp_receive_buffer_size);
virtual ~udp_client_endpoint_impl();
void start();
void restart(bool _force);
void receive_cbk(boost::system::error_code const &_error,
- std::size_t _bytes);
+ std::size_t _bytes, message_buffer_ptr_t _recv_buffer);
bool get_remote_address(boost::asio::ip::address &_address) const;
std::uint16_t get_remote_port() const;
@@ -51,11 +52,12 @@ private:
const std::string get_address_port_remote() const;
const std::string get_address_port_local() const;
std::string get_remote_information() const;
-
- message_buffer_t recv_buffer_;
+ std::uint32_t get_max_allowed_reconnects() const;
+ void max_allowed_reconnects_reached();
const boost::asio::ip::address remote_address_;
const std::uint16_t remote_port_;
+ const std::uint32_t udp_receive_buffer_size_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
index 48e4935..f1b6959 100644
--- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
@@ -26,7 +26,8 @@ public:
udp_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
endpoint_type _local,
boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit);
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _udp_receive_buffer_size);
virtual ~udp_server_endpoint_impl();
void start();
@@ -64,6 +65,8 @@ private:
std::string get_remote_information(
const queue_iterator_type _queue_iterator) const;
+ const std::string get_address_port_local() const;
+
private:
socket_type socket_;
endpoint_type remote_;
@@ -75,7 +78,7 @@ private:
std::atomic<bool> joined_group_;
message_buffer_t recv_buffer_;
- std::mutex socket_mutex_;
+ mutable std::mutex socket_mutex_;
const std::uint16_t local_port_;
};
diff --git a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
index 58619cc..afe56e2 100644
--- a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
@@ -24,7 +24,8 @@ public:
void start();
void stop();
- bool is_connected() const;
+ bool is_established() const;
+ void set_established(bool _established);
void set_connected(bool _connected);
bool send(const byte_t *_data, uint32_t _size, bool _flush);
diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp
index b4a6bf9..2f521ea 100644
--- a/implementation/endpoints/src/client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/client_endpoint_impl.cpp
@@ -38,10 +38,12 @@ client_endpoint_impl<Protocol>::client_endpoint_impl(
flush_timer_(_io), connect_timer_(_io),
connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT), // TODO: use config variable
state_(cei_state_e::CLOSED),
+ reconnect_counter_(0),
packetizer_(std::make_shared<message_buffer_t>()),
queue_size_(0),
was_not_connected_(false),
- local_port_(0) {
+ local_port_(0),
+ strand_(_io) {
}
template<typename Protocol>
@@ -54,22 +56,38 @@ bool client_endpoint_impl<Protocol>::is_client() const {
}
template<typename Protocol>
-bool client_endpoint_impl<Protocol>::is_connected() const {
+bool client_endpoint_impl<Protocol>::is_established() const {
return state_ == cei_state_e::ESTABLISHED;
}
template<typename Protocol>
+void client_endpoint_impl<Protocol>::set_established(bool _established) {
+ if (_established) {
+ if (state_ != cei_state_e::CONNECTING) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ if (socket_->is_open()) {
+ state_ = cei_state_e::ESTABLISHED;
+ } else {
+ state_ = cei_state_e::CLOSED;
+ }
+ }
+ } else {
+ state_ = cei_state_e::CLOSED;
+ } }
+template<typename Protocol>
void client_endpoint_impl<Protocol>::set_connected(bool _connected) {
if (_connected) {
std::lock_guard<std::mutex> its_lock(socket_mutex_);
if (socket_->is_open()) {
- state_ = cei_state_e::ESTABLISHED;
+ state_ = cei_state_e::CONNECTED;
} else {
state_ = cei_state_e::CLOSED;
}
} else {
state_ = cei_state_e::CLOSED;
- } }
+ }
+}
+
template<typename Protocol> void client_endpoint_impl<Protocol>::stop() {
{
std::lock_guard<std::mutex> its_lock(mutex_);
@@ -159,7 +177,8 @@ bool client_endpoint_impl<Protocol>::flush() {
template<typename Protocol>
void client_endpoint_impl<Protocol>::connect_cbk(
boost::system::error_code const &_error) {
- if (_error == boost::asio::error::operation_aborted) {
+ if (_error == boost::asio::error::operation_aborted
+ || endpoint_impl<Protocol>::sending_blocked_) {
// endpoint was stopped
shutdown_and_close_socket(false);
return;
@@ -173,7 +192,12 @@ void client_endpoint_impl<Protocol>::connect_cbk(
state_ = cei_state_e::CLOSED;
its_host->on_disconnect(this->shared_from_this());
}
- start_connect_timer();
+ if (get_max_allowed_reconnects() == MAX_RECONNECTS_UNLIMITED ||
+ get_max_allowed_reconnects() >= ++reconnect_counter_) {
+ start_connect_timer();
+ } else {
+ max_allowed_reconnects_reached();
+ }
// Double the timeout as long as the maximum allowed is larger
if (connect_timeout_ < VSOMEIP_MAX_CONNECT_TIMEOUT)
connect_timeout_ = (connect_timeout_ << 1);
@@ -183,13 +207,8 @@ void client_endpoint_impl<Protocol>::connect_cbk(
connect_timer_.cancel();
}
connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT; // TODO: use config variable
+ reconnect_counter_ = 0;
set_local_port();
- if (state_ != cei_state_e::ESTABLISHED) {
- its_host->on_connect(this->shared_from_this());
- }
-
- receive();
-
if (was_not_connected_) {
was_not_connected_ = false;
std::lock_guard<std::mutex> its_lock(mutex_);
@@ -199,6 +218,10 @@ void client_endpoint_impl<Protocol>::connect_cbk(
<< get_remote_information();
}
}
+ if (state_ != cei_state_e::ESTABLISHED) {
+ its_host->on_connect(this->shared_from_this());
+ }
+ receive();
}
}
}
@@ -269,8 +292,17 @@ void client_endpoint_impl<Protocol>::send_cbk(
shutdown_and_close_socket(true);
connect();
} else if (_error == boost::asio::error::not_connected
- || _error == boost::asio::error::bad_descriptor) {
+ || _error == boost::asio::error::bad_descriptor
+ || _error == boost::asio::error::no_permission) {
state_ = cei_state_e::CLOSED;
+ if (_error == boost::asio::error::no_permission) {
+ VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information();
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ queue_.clear();
+ queue_size_ = 0;
+ }
was_not_connected_ = true;
shutdown_and_close_socket(true);
connect();
@@ -332,6 +364,12 @@ template<typename Protocol>
void client_endpoint_impl<Protocol>::shutdown_and_close_socket_unlocked(bool _recreate_socket) {
local_port_ = 0;
if (socket_->is_open()) {
+#ifndef _WIN32
+ if (-1 == fcntl(socket_->native_handle(), F_GETFD)) {
+ VSOMEIP_ERROR << "cei::shutdown_and_close_socket_unlocked: socket/handle closed already '" << std::string(std::strerror(errno))
+ << "' (" << errno << ") " << get_remote_information();
+ }
+#endif
boost::system::error_code its_error;
socket_->shutdown(Protocol::socket::shutdown_both, its_error);
socket_->close(its_error);
diff --git a/implementation/endpoints/src/credentials.cpp b/implementation/endpoints/src/credentials.cpp
index 84f7f08..411fd3f 100644
--- a/implementation/endpoints/src/credentials.cpp
+++ b/implementation/endpoints/src/credentials.cpp
@@ -17,14 +17,16 @@ namespace vsomeip {
void credentials::activate_credentials(const int _fd) {
int optval = 1;
if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
- VSOMEIP_ERROR << "Activating socket option for receiving credentials failed.";
+ VSOMEIP_ERROR << "vSomeIP Security: Activating socket option for receiving "
+ << "credentials failed.";
}
}
void credentials::deactivate_credentials(const int _fd) {
int optval = 0;
if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
- VSOMEIP_ERROR << "Deactivating socket option for receiving credentials failed.";
+ VSOMEIP_ERROR << "vSomeIP Security: Deactivating socket option for receiving "
+ << "credentials failed.";
}
}
@@ -62,13 +64,13 @@ client_t credentials::receive_credentials(const int _fd, uid_t& _uid, gid_t& _gi
// Receive client_id plus ancillary data
ssize_t nr = recvmsg(_fd, &msgh, 0);
if (nr == -1) {
- VSOMEIP_ERROR << "Receiving credentials failed. No data.";
+ VSOMEIP_ERROR << "vSomeIP Security: Receiving credentials failed. No data.";
}
cmhp = CMSG_FIRSTHDR(&msgh);
if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(struct ucred))
|| cmhp->cmsg_level != SOL_SOCKET || cmhp->cmsg_type != SCM_CREDENTIALS) {
- VSOMEIP_ERROR << "Receiving credentials failed. Invalid data.";
+ VSOMEIP_ERROR << "vSomeIP Security: Receiving credentials failed. Invalid data.";
} else {
ucredp = (struct ucred *) CMSG_DATA(cmhp);
_uid = ucredp->uid;
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp
index 29d861f..a57c831 100644
--- a/implementation/endpoints/src/local_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp
@@ -60,6 +60,8 @@ void local_client_endpoint_impl::restart(bool _force) {
std::lock_guard<std::mutex> its_lock(socket_mutex_);
shutdown_and_close_socket_unlocked(true);
}
+ was_not_connected_ = true;
+ reconnect_counter_ = 0;
start_connect_timer();
}
@@ -139,13 +141,14 @@ void local_client_endpoint_impl::connect() {
} else {
VSOMEIP_WARNING << "local_client_endpoint::connect: Error opening socket: "
- << its_error.message();
- return;
+ << its_error.message() << " (" << std::dec << its_error.value()
+ << ")";
+ its_connect_error = its_error;
}
}
// call connect_cbk asynchronously
try {
- service_.post(
+ strand_.post(
std::bind(&client_endpoint_impl::connect_cbk, shared_from_this(),
its_connect_error));
} catch (const std::exception &e) {
@@ -158,13 +161,15 @@ void local_client_endpoint_impl::receive() {
if (socket_->is_open()) {
socket_->async_receive(
boost::asio::buffer(recv_buffer_),
- std::bind(
- &local_client_endpoint_impl::receive_cbk,
- std::dynamic_pointer_cast<
- local_client_endpoint_impl
- >(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2
+ strand_.wrap(
+ std::bind(
+ &local_client_endpoint_impl::receive_cbk,
+ std::dynamic_pointer_cast<
+ local_client_endpoint_impl
+ >(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2
+ )
)
);
}
@@ -232,10 +237,6 @@ void local_client_endpoint_impl::receive_cbk(
VSOMEIP_ERROR << "Local endpoint received message ("
<< _error.message() << ")";
}
- // The error handler is set only if the endpoint is hosted by the
- // routing manager. For the routing manager proxies, the corresponding
- // client endpoint (that connect to the same client) are removed
- // after the proxy has received the routing info.
error_handler_t handler;
{
std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
@@ -290,6 +291,10 @@ std::string local_client_endpoint_impl::get_remote_information() const {
#endif
}
+std::uint32_t local_client_endpoint_impl::get_max_allowed_reconnects() const {
+ return 13;
+}
+
bool local_client_endpoint_impl::send(const std::vector<byte_t>& _cmd_header,
const byte_t *_data, uint32_t _size,
bool _flush) {
@@ -319,4 +324,16 @@ bool local_client_endpoint_impl::send(const std::vector<byte_t>& _cmd_header,
return ret;
}
+void local_client_endpoint_impl::max_allowed_reconnects_reached() {
+ VSOMEIP_ERROR << "local_client_endpoint::max_allowed_reconnects_reached: "
+ << get_remote_information();
+ error_handler_t handler;
+ {
+ std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
+ handler = error_handler_;
+ }
+ if (handler)
+ handler();
+}
+
} // namespace vsomeip
diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp
index 6ae9c6c..cfd5c0b 100644
--- a/implementation/endpoints/src/local_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp
@@ -30,7 +30,7 @@ local_server_endpoint_impl::local_server_endpoint_impl(
endpoint_type _local, boost::asio::io_service &_io,
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit)
+ configuration::endpoint_queue_limit_t _queue_limit, std::uint32_t _mode)
: local_server_endpoint_base_impl(_host, _local, _io,
_max_message_size, _queue_limit),
acceptor_(_io),
@@ -48,8 +48,11 @@ local_server_endpoint_impl::local_server_endpoint_impl(
boost::asio::detail::throw_error(ec, "acceptor listen");
#ifndef _WIN32
+ if (chmod(_local.path().c_str(), static_cast<mode_t>(_mode)) == -1) {
+ VSOMEIP_ERROR << __func__ << ": chmod: " << strerror(errno);
+ }
if (_host->get_configuration()->is_security_enabled()) {
- credentials::activate_credentials(acceptor_.native());
+ credentials::activate_credentials(acceptor_.native_handle());
}
#endif
}
@@ -60,7 +63,7 @@ local_server_endpoint_impl::local_server_endpoint_impl(
std::uint32_t _max_message_size,
int native_socket,
std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit)
+ configuration::endpoint_queue_limit_t _queue_limit, std::uint32_t _mode)
: local_server_endpoint_base_impl(_host, _local, _io,
_max_message_size, _queue_limit),
acceptor_(_io),
@@ -72,8 +75,11 @@ local_server_endpoint_impl::local_server_endpoint_impl(
boost::asio::detail::throw_error(ec, "acceptor assign native socket");
#ifndef _WIN32
+ if (chmod(_local.path().c_str(), static_cast<mode_t>(_mode)) == -1) {
+ VSOMEIP_ERROR << __func__ << ": chmod: " << strerror(errno);
+ }
if (_host->get_configuration()->is_security_enabled()) {
- credentials::activate_credentials(acceptor_.native());
+ credentials::activate_credentials(acceptor_.native_handle());
}
#endif
}
@@ -127,6 +133,12 @@ void local_server_endpoint_impl::stop() {
}
connections_.clear();
}
+#ifndef _WIN32
+ {
+ std::lock_guard<std::mutex> its_lock(client_connections_mutex_);
+ client_connections_.clear();
+ }
+#endif
}
bool local_server_endpoint_impl::send_to(
@@ -178,15 +190,31 @@ bool local_server_endpoint_impl::get_default_target(
void local_server_endpoint_impl::remove_connection(
local_server_endpoint_impl::connection *_connection) {
- std::lock_guard<std::mutex> its_lock(connections_mutex_);
- for (auto it = connections_.begin(); it != connections_.end();) {
- if (it->second.get() == _connection) {
- it = connections_.erase(it);
- break;
- } else {
- ++it;
+ {
+ std::lock_guard<std::mutex> its_lock(connections_mutex_);
+ for (auto it = connections_.begin(); it != connections_.end();) {
+ if (it->second.get() == _connection) {
+ it = connections_.erase(it);
+ break;
+ } else {
+ ++it;
+ }
}
}
+
+#ifndef _WIN32
+ {
+ std::lock_guard<std::mutex> its_lock(client_connections_mutex_);
+ for (auto it = client_connections_.begin(); it != client_connections_.end();) {
+ if (it->second.get() == _connection) {
+ it = client_connections_.erase(it);
+ break;
+ } else {
+ ++it;
+ }
+ }
+ }
+#endif
}
void local_server_endpoint_impl::accept_cbk(
@@ -196,23 +224,62 @@ void local_server_endpoint_impl::accept_cbk(
&& _error != boost::asio::error::operation_aborted
&& _error != boost::asio::error::no_descriptors) {
start();
+ } else if (_error == boost::asio::error::no_descriptors) {
+ VSOMEIP_ERROR << "local_server_endpoint_impl::accept_cbk: "
+ << _error.message() << " (" << std::dec << _error.value()
+ << ") Will try to accept again in 1000ms";
+ std::shared_ptr<boost::asio::steady_timer> its_timer =
+ std::make_shared<boost::asio::steady_timer>(service_,
+ std::chrono::milliseconds(1000));
+ auto its_ep = std::dynamic_pointer_cast<local_server_endpoint_impl>(
+ shared_from_this());
+ its_timer->async_wait([its_timer, its_ep]
+ (const boost::system::error_code& _error) {
+ if (!_error) {
+ its_ep->start();
+ }
+ });
}
if (!_error) {
#ifndef _WIN32
auto its_host = host_.lock();
+ client_t client = 0;
if (its_host) {
if (its_host->get_configuration()->is_security_enabled()) {
std::unique_lock<std::mutex> its_socket_lock(_connection->get_socket_lock());
socket_type &new_connection_socket = _connection->get_socket();
- uid_t uid(0);
- gid_t gid(0);
- client_t client = credentials::receive_credentials(
+ uid_t uid(0xffffffff);
+ gid_t gid(0xffffffff);
+ client = credentials::receive_credentials(
new_connection_socket.native(), uid, gid);
+
+ std::lock_guard<std::mutex> its_client_connection_lock(client_connections_mutex_);
+ auto found_client = client_connections_.find(client);
+ if (found_client != client_connections_.end()) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Rejecting new connection with client ID 0x" << client
+ << " uid/gid= " << std::dec << uid << "/" << gid
+ << " because of already existing connection using same client ID";
+ boost::system::error_code er;
+ new_connection_socket.shutdown(new_connection_socket.shutdown_both, er);
+ new_connection_socket.close(er);
+ return;
+ }
+
+ if (!its_host->get_configuration()->check_routing_credentials(client, uid, gid)) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Rejecting new connection with routing manager client ID 0x" << client
+ << " uid/gid= " << std::dec << uid << "/" << gid
+ << " because passed credentials do not match with routing manager credentials!";
+ boost::system::error_code er;
+ new_connection_socket.shutdown(new_connection_socket.shutdown_both, er);
+ new_connection_socket.close(er);
+ return;
+ }
+
if (!its_host->check_credentials(client, uid, gid)) {
- VSOMEIP_WARNING << std::hex << "Client 0x" << its_host->get_client()
- << " received client credentials from client 0x" << client
- << " which violates the security policy : uid/gid="
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
+ << its_host->get_client() << " received client credentials from client 0x"
+ << client << " which violates the security policy : uid/gid="
<< std::dec << uid << "/" << gid;
boost::system::error_code er;
new_connection_socket.shutdown(new_connection_socket.shutdown_both, er);
@@ -234,8 +301,16 @@ void local_server_endpoint_impl::accept_cbk(
}
if (!its_error) {
{
- std::lock_guard<std::mutex> its_lock(connections_mutex_);
- connections_[remote] = _connection;
+ {
+ std::lock_guard<std::mutex> its_lock(connections_mutex_);
+ connections_[remote] = _connection;
+ }
+#ifndef _WIN32
+ {
+ std::lock_guard<std::mutex> its_lock(client_connections_mutex_);
+ client_connections_[client] = _connection;
+ }
+#endif
}
_connection->start();
}
@@ -271,7 +346,6 @@ local_server_endpoint_impl::connection::create(
std::uint32_t _buffer_shrink_threshold,
boost::asio::io_service &_io_service) {
const std::uint32_t its_initial_buffer_size = VSOMEIP_COMMAND_HEADER_SIZE
- + VSOMEIP_MAX_LOCAL_MESSAGE_SIZE
+ static_cast<std::uint32_t>(sizeof(instance_t) + sizeof(bool)
+ sizeof(bool));
return ptr(new connection(_server, _max_message_size, its_initial_buffer_size,
@@ -334,6 +408,12 @@ void local_server_endpoint_impl::connection::start() {
void local_server_endpoint_impl::connection::stop() {
std::lock_guard<std::mutex> its_lock(socket_mutex_);
if (socket_.is_open()) {
+#ifndef _WIN32
+ if (-1 == fcntl(socket_.native_handle(), F_GETFD)) {
+ VSOMEIP_ERROR << "lse: socket/handle closed already '" << std::string(std::strerror(errno))
+ << "' (" << errno << ") " << get_path_local();
+ }
+#endif
boost::system::error_code its_error;
socket_.shutdown(socket_.shutdown_both, its_error);
socket_.close(its_error);
@@ -487,19 +567,33 @@ void local_server_endpoint_impl::connection::receive_cbk(
// start tag (4 Byte) + command (1 Byte) + client id (2 Byte)
// + command size (4 Byte) + data itself + stop tag (4 byte)
// = 15 Bytes not covered in command size.
- if (its_command_size && its_command_size + 15 > recv_buffer_size_) {
+ if (its_command_size + 15 > recv_buffer_size_) {
missing_capacity_ = its_command_size + 15 - std::uint32_t(recv_buffer_size_);
} else if (recv_buffer_size_ < 11) {
// to little data to read out the command size
// minimal amount of data needed to read out command size = 11
missing_capacity_ = 11 - static_cast<std::uint32_t>(recv_buffer_size_);
} else {
+ std::stringstream local_msg;
+ for (std::size_t i = its_iteration_gap;
+ i < recv_buffer_size_ + its_iteration_gap &&
+ i - its_iteration_gap < 32; i++) {
+ local_msg << std::setw(2) << std::setfill('0')
+ << std::hex << (int) recv_buffer_[i] << " ";
+ }
VSOMEIP_ERROR << "lse::c<" << this
<< ">rcb: recv_buffer_size is: " << std::dec
<< recv_buffer_size_ << " but couldn't read "
"out command size. recv_buffer_capacity: "
- << recv_buffer_.capacity()
- << " its_iteration_gap: " << its_iteration_gap;
+ << std::dec << recv_buffer_.capacity()
+ << " its_iteration_gap: " << std::dec
+ << its_iteration_gap << " bound client: 0x"
+ << std::hex << bound_client_ << " buffer: "
+ << local_msg.str();
+ recv_buffer_size_ = 0;
+ missing_capacity_ = 0;
+ its_iteration_gap = 0;
+ message_is_empty = true;
}
}
}
@@ -525,7 +619,7 @@ void local_server_endpoint_impl::connection::receive_cbk(
found_message = true;
its_iteration_gap = its_end + 4;
} else {
- if (!message_is_empty && its_iteration_gap) {
+ if (its_iteration_gap) {
// Message not complete and not in front of the buffer!
// Copy last part to front for consume in future receive_cbk call!
for (size_t i = 0; i < recv_buffer_size_; ++i) {
@@ -545,6 +639,7 @@ void local_server_endpoint_impl::connection::receive_cbk(
|| _error == boost::asio::error::connection_reset) {
stop();
its_server->remove_connection(this);
+ its_host->get_configuration()->remove_client_to_uid_gid_mapping(bound_client_);
} else if (_error != boost::asio::error::bad_descriptor) {
start();
}
@@ -555,6 +650,11 @@ void local_server_endpoint_impl::connection::set_bound_client(client_t _client)
bound_client_ = _client;
}
+client_t local_server_endpoint_impl::connection::get_bound_client() const {
+ return bound_client_;
+}
+
+
void local_server_endpoint_impl::connection::calculate_shrink_count() {
if (buffer_shrink_threshold_) {
if (recv_buffer_.capacity() != recv_buffer_size_initial_) {
@@ -624,6 +724,12 @@ void local_server_endpoint_impl::connection::handle_recv_buffer_exception(
VSOMEIP_ERROR << its_message.str();
recv_buffer_.clear();
if (socket_.is_open()) {
+#ifndef _WIN32
+ if (-1 == fcntl(socket_.native_handle(), F_GETFD)) {
+ VSOMEIP_ERROR << "lse: socket/handle closed already '" << std::string(std::strerror(errno))
+ << "' (" << errno << ") " << get_path_local();
+ }
+#endif
boost::system::error_code its_error;
socket_.shutdown(socket_.shutdown_both, its_error);
socket_.close(its_error);
diff --git a/implementation/endpoints/src/netlink_connector.cpp b/implementation/endpoints/src/netlink_connector.cpp
index 94b75cf..2f9e2e5 100644
--- a/implementation/endpoints/src/netlink_connector.cpp
+++ b/implementation/endpoints/src/netlink_connector.cpp
@@ -103,7 +103,7 @@ void netlink_connector::receive_cbk(boost::system::error_code const &_error,
struct nlmsghdr *nlh = (struct nlmsghdr *)&recv_buffer_[0];
while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) {
- char ifname[1024];
+ char ifname[IF_NAMESIZE];
switch (nlh->nlmsg_type) {
case RTM_NEWADDR: {
// New Address information
@@ -356,7 +356,7 @@ bool netlink_connector::check_sd_multicast_route_match(struct rtmsg* _routemsg,
struct rtattr *retrta;
retrta = static_cast<struct rtattr *>(RTM_RTA(_routemsg));
int if_index(0);
- char if_name[1024] = "n/a";
+ char if_name[IF_NAMESIZE] = "n/a";
char address[INET6_ADDRSTRLEN] = "n/a";
char gateway[INET6_ADDRSTRLEN] = "n/a";
bool matches_sd_multicast(false);
diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp
index 6da5826..915bfc9 100644
--- a/implementation/endpoints/src/server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/server_endpoint_impl.cpp
@@ -19,6 +19,7 @@
#include "../../logging/include/logger.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../service_discovery/include/defines.hpp"
namespace vsomeip {
@@ -54,12 +55,17 @@ void server_endpoint_impl<Protocol>::restart(bool _force) {
}
template<typename Protocol>
-bool server_endpoint_impl<Protocol>::is_connected() const {
+bool server_endpoint_impl<Protocol>::is_established() const {
return true;
}
template<typename Protocol>
-void server_endpoint_impl<Protocol>::set_connected(bool _connected) { (void) _connected; }
+void server_endpoint_impl<Protocol>::set_established(bool _established) { (void) _established; }
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::set_connected(bool _connected) {
+ (void) _connected;
+}
template<typename Protocol> bool server_endpoint_impl<Protocol>::send(const uint8_t *_data,
uint32_t _size, bool _flush) {
#if 0
@@ -102,6 +108,16 @@ template<typename Protocol> bool server_endpoint_impl<Protocol>::send(const uint
VSOMEIP_WARNING << "server_endpoint::send: session_id 0x"
<< std::hex << its_session
<< " not found for client 0x" << its_client;
+ const method_t its_method =
+ VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == VSOMEIP_SD_SERVICE
+ && its_method == VSOMEIP_SD_METHOD) {
+ VSOMEIP_ERROR << "Clearing clients map as a request was "
+ "received on SD port";
+ clients_.clear();
+ is_valid_target = get_default_target(its_service, its_target);
+ }
}
} else {
is_valid_target = get_default_target(its_service, its_target);
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index cb92619..41254f6 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -30,7 +30,9 @@ tcp_client_endpoint_impl::tcp_client_endpoint_impl(
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
std::chrono::milliseconds _send_timeout,
- configuration::endpoint_queue_limit_t _queue_limit)
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _tcp_restart_aborts_max,
+ std::uint32_t _tcp_connect_time_max)
: tcp_client_endpoint_base_impl(_host, _local, _remote, _io,
_max_message_size, _queue_limit),
recv_buffer_size_initial_(VSOMEIP_SOMEIP_HEADER_SIZE),
@@ -41,7 +43,10 @@ tcp_client_endpoint_impl::tcp_client_endpoint_impl(
remote_port_(_remote.port()),
last_cookie_sent_(std::chrono::steady_clock::now() - std::chrono::seconds(11)),
send_timeout_(_send_timeout),
- send_timeout_warning_(_send_timeout / 2) {
+ send_timeout_warning_(_send_timeout / 2),
+ tcp_restart_aborts_max_(_tcp_restart_aborts_max),
+ tcp_connect_time_max_(_tcp_connect_time_max),
+ aborted_restart_count_(0) {
is_supporting_magic_cookies_ = true;
}
@@ -62,7 +67,19 @@ void tcp_client_endpoint_impl::start() {
void tcp_client_endpoint_impl::restart(bool _force) {
if (!_force && state_ == cei_state_e::CONNECTING) {
- return;
+ std::chrono::steady_clock::time_point its_current
+ = std::chrono::steady_clock::now();
+ long its_connect_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
+ its_current - connect_timepoint_).count();
+ if (aborted_restart_count_ < tcp_restart_aborts_max_
+ && its_connect_duration < tcp_connect_time_max_) {
+ aborted_restart_count_++;
+ return;
+ } else {
+ VSOMEIP_WARNING << "tce::restart: maximum number of aborted restarts ["
+ << tcp_restart_aborts_max_ << "] reached! its_connect_duration: "
+ << its_connect_duration;
+ }
}
state_ = cei_state_e::CONNECTING;
std::string address_port_local;
@@ -72,6 +89,8 @@ void tcp_client_endpoint_impl::restart(bool _force) {
shutdown_and_close_socket_unlocked(true);
recv_buffer_ = std::make_shared<message_buffer_t>(recv_buffer_size_initial_, 0);
}
+ was_not_connected_ = true;
+ reconnect_counter_ = 0;
{
std::lock_guard<std::mutex> its_lock(mutex_);
for (const auto&m : queue_) {
@@ -150,7 +169,7 @@ void tcp_client_endpoint_impl::connect() {
<< " remote:" << get_address_port_remote();
try {
// don't connect on bind error to avoid using a random port
- service_.post(std::bind(&client_endpoint_impl::connect_cbk,
+ strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
shared_from_this(), its_bind_error));
} catch (const std::exception &e) {
VSOMEIP_ERROR << "tcp_client_endpoint_impl::connect: "
@@ -160,17 +179,23 @@ void tcp_client_endpoint_impl::connect() {
}
}
state_ = cei_state_e::CONNECTING;
+ connect_timepoint_ = std::chrono::steady_clock::now();
+ aborted_restart_count_ = 0;
socket_->async_connect(
remote_,
- std::bind(
- &tcp_client_endpoint_base_impl::connect_cbk,
- shared_from_this(),
- std::placeholders::_1
+ strand_.wrap(
+ std::bind(
+ &tcp_client_endpoint_base_impl::connect_cbk,
+ shared_from_this(),
+ std::placeholders::_1
+ )
)
);
} else {
VSOMEIP_WARNING << "tcp_client_endpoint::connect: Error opening socket: "
<< its_error.message() << " remote:" << get_address_port_remote();
+ strand_.post(std::bind(&tcp_client_endpoint_base_impl::connect_cbk,
+ shared_from_this(), its_error));
}
}
@@ -200,6 +225,12 @@ void tcp_client_endpoint_impl::receive(message_buffer_ptr_t _recv_buffer,
if (its_capacity < its_required_capacity) {
_recv_buffer->reserve(its_required_capacity);
_recv_buffer->resize(its_required_capacity, 0x0);
+ if (_recv_buffer->size() > 1048576) {
+ VSOMEIP_INFO << "tce: recv_buffer size is: " <<
+ _recv_buffer->size()
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
}
buffer_size = _missing_capacity;
} else if (buffer_shrink_threshold_
@@ -217,13 +248,15 @@ void tcp_client_endpoint_impl::receive(message_buffer_ptr_t _recv_buffer,
}
socket_->async_receive(
boost::asio::buffer(&(*_recv_buffer)[_recv_buffer_size], buffer_size),
- std::bind(
- &tcp_client_endpoint_impl::receive_cbk,
- std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2,
- _recv_buffer,
- _recv_buffer_size
+ strand_.wrap(
+ std::bind(
+ &tcp_client_endpoint_impl::receive_cbk,
+ std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ _recv_buffer,
+ _recv_buffer_size
+ )
)
);
}
@@ -431,7 +464,7 @@ void tcp_client_endpoint_impl::receive_cbk(
return;
}
uint32_t current_message_size = static_cast<uint32_t>(read_message_size);
- has_full_message = (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE
+ has_full_message = (current_message_size > VSOMEIP_RETURN_CODE_POS
&& current_message_size <= _recv_buffer_size);
if (has_full_message) {
bool needs_forwarding(true);
@@ -472,58 +505,125 @@ void tcp_client_endpoint_impl::receive_cbk(
_recv_buffer_size -= current_message_size;
its_iteration_gap += current_message_size;
its_missing_capacity = 0;
- } else if (max_message_size_ != MESSAGE_SIZE_UNLIMITED &&
- current_message_size > max_message_size_) {
- _recv_buffer_size = 0;
- _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
- _recv_buffer->shrink_to_fit();
- if (has_enabled_magic_cookies_) {
- VSOMEIP_ERROR << "Received a TCP message which exceeds "
- << "maximum message size ("
- << std::dec << current_message_size
- << "). Magic Cookies are enabled: "
- << "Resetting receiver. local: "
- << get_address_port_local() << " remote: "
- << get_address_port_remote();
- } else {
- VSOMEIP_ERROR << "Received a TCP message which exceeds "
- << "maximum message size ("
- << std::dec << current_message_size
- << ") Magic cookies are disabled: "
- << "Client will be disabled! local: "
- << get_address_port_local() << " remote: "
- << get_address_port_remote();
- return;
- }
- } else if (current_message_size > _recv_buffer_size) {
- its_missing_capacity = current_message_size
- - static_cast<std::uint32_t>(_recv_buffer_size);
- } else if (VSOMEIP_SOMEIP_HEADER_SIZE > _recv_buffer_size) {
- its_missing_capacity = VSOMEIP_SOMEIP_HEADER_SIZE
- - static_cast<std::uint32_t>(_recv_buffer_size);
} else if (has_enabled_magic_cookies_ && _recv_buffer_size > 0) {
- uint32_t its_offset = find_magic_cookie(&(*_recv_buffer)[its_iteration_gap], _recv_buffer_size);
+ const uint32_t its_offset = find_magic_cookie(
+ &(*_recv_buffer)[its_iteration_gap], _recv_buffer_size);
if (its_offset < _recv_buffer_size) {
_recv_buffer_size -= its_offset;
its_iteration_gap += its_offset;
has_full_message = true; // trigger next loop
- } else {
+ VSOMEIP_ERROR << "Detected Magic Cookie within message data."
+ << " Resyncing. local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
+ }
+
+ if (!has_full_message) {
+ if (_recv_buffer_size > VSOMEIP_RETURN_CODE_POS &&
+ ((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
+ !utility::is_valid_message_type(static_cast<message_type_e>((*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])) ||
+ !utility::is_valid_return_code(static_cast<return_code_e>((*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))
+ )) {
+ if ((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
+ VSOMEIP_ERROR << "tce: Wrong protocol version: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ // ensure to send back a message w/ wrong protocol version
+ its_lock.unlock();
+ its_host->on_message(&(*_recv_buffer)[its_iteration_gap],
+ VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ remote_address_,
+ remote_port_);
+ its_lock.lock();
+ } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
+ (*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS]))) {
+ VSOMEIP_ERROR << "tce: Invalid message type: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
+ (*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))) {
+ VSOMEIP_ERROR << "tce: Invalid return code: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket_unlocked(false);
+ its_lock.unlock();
+ its_host->on_disconnect(shared_from_this());
+ restart(true);
+ return;
+ } else if (max_message_size_ != MESSAGE_SIZE_UNLIMITED &&
+ current_message_size > max_message_size_) {
+ _recv_buffer_size = 0;
+ _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
+ _recv_buffer->shrink_to_fit();
+ if (has_enabled_magic_cookies_) {
+ VSOMEIP_ERROR << "Received a TCP message which exceeds "
+ << "maximum message size ("
+ << std::dec << current_message_size
+ << "). Magic Cookies are enabled: "
+ << "Resetting receiver. local: "
+ << get_address_port_local() << " remote: "
+ << get_address_port_remote();
+ } else {
+ VSOMEIP_ERROR << "Received a TCP message which exceeds "
+ << "maximum message size ("
+ << std::dec << current_message_size
+ << ") Magic cookies are disabled, "
+ << "Restarting connection. "
+ << "local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket_unlocked(false);
+ its_lock.unlock();
+ its_host->on_disconnect(shared_from_this());
+ restart(true);
+ return;
+ }
+ } else if (current_message_size > _recv_buffer_size) {
+ its_missing_capacity = current_message_size
+ - static_cast<std::uint32_t>(_recv_buffer_size);
+ } else if (VSOMEIP_SOMEIP_HEADER_SIZE > _recv_buffer_size) {
+ its_missing_capacity = VSOMEIP_SOMEIP_HEADER_SIZE
+ - static_cast<std::uint32_t>(_recv_buffer_size);
+ } else if (has_enabled_magic_cookies_ && _recv_buffer_size > 0) {
+ // no need to check for magic cookie here again: has_full_message
+ // would have been set to true if there was one present in the data
_recv_buffer_size = 0;
+ _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
+ _recv_buffer->shrink_to_fit();
its_missing_capacity = 0;
+ VSOMEIP_ERROR << "tce::c<" << this
+ << ">rcb: recv_buffer_capacity: "
+ << _recv_buffer->capacity()
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << ". Didn't find magic cookie in broken data, trying to resync.";
+ } else {
+ VSOMEIP_ERROR << "tce::c<" << this
+ << ">rcb: recv_buffer_size is: " << std::dec
+ << _recv_buffer_size << " but couldn't read "
+ "out message_size. recv_buffer_capacity: "
+ << _recv_buffer->capacity()
+ << " its_iteration_gap: " << its_iteration_gap
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << ". Restarting connection due to missing/broken data TCP stream.";
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket_unlocked(false);
+ its_lock.unlock();
+ its_host->on_disconnect(shared_from_this());
+ restart(true);
+ return;
}
- } else {
- VSOMEIP_ERROR << "tce::c<" << this
- << ">rcb: recv_buffer_size is: " << std::dec
- << _recv_buffer_size << " but couldn't read "
- "out message_size. recv_buffer_capacity: "
- << _recv_buffer->capacity()
- << " its_iteration_gap: " << its_iteration_gap
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote()
- << ". Restarting connection due to missing/broken data TCP stream.";
- its_lock.unlock();
- restart(true);
- return;
}
} while (has_full_message && _recv_buffer_size);
if (its_iteration_gap) {
@@ -555,7 +655,6 @@ void tcp_client_endpoint_impl::receive_cbk(
VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk restarting.";
state_ = cei_state_e::CONNECTING;
shutdown_and_close_socket_unlocked(false);
- was_not_connected_ = true;
its_lock.unlock();
its_host->on_disconnect(shared_from_this());
restart(true);
@@ -705,7 +804,6 @@ void tcp_client_endpoint_impl::send_cbk(boost::system::error_code const &_error,
} else {
state_ = cei_state_e::CONNECTING;
shutdown_and_close_socket(false);
- was_not_connected_ = true;
std::shared_ptr<endpoint_host> its_host = host_.lock();
if (its_host) {
its_host->on_disconnect(shared_from_this());
@@ -742,4 +840,12 @@ void tcp_client_endpoint_impl::send_cbk(boost::system::error_code const &_error,
}
}
+std::uint32_t tcp_client_endpoint_impl::get_max_allowed_reconnects() const {
+ return MAX_RECONNECTS_UNLIMITED;
+}
+
+void tcp_client_endpoint_impl::max_allowed_reconnects_reached() {
+ return;
+}
+
} // namespace vsomeip
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index 9c2998f..30402c5 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -188,6 +188,21 @@ void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection,
&& _error != boost::asio::error::operation_aborted
&& _error != boost::asio::error::no_descriptors) {
start();
+ } else if (_error == boost::asio::error::no_descriptors) {
+ VSOMEIP_ERROR<< "tcp_server_endpoint_impl::accept_cbk: "
+ << _error.message() << " (" << std::dec << _error.value()
+ << ") Will try to accept again in 1000ms";
+ std::shared_ptr<boost::asio::steady_timer> its_timer =
+ std::make_shared<boost::asio::steady_timer>(service_,
+ std::chrono::milliseconds(1000));
+ auto its_ep = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(
+ shared_from_this());
+ its_timer->async_wait([its_timer, its_ep]
+ (const boost::system::error_code& _error) {
+ if (!_error) {
+ its_ep->start();
+ }
+ });
}
}
@@ -205,7 +220,7 @@ bool tcp_server_endpoint_impl::is_reliable() const {
tcp_server_endpoint_impl::connection::connection(
std::weak_ptr<tcp_server_endpoint_impl> _server,
std::uint32_t _max_message_size,
- std::uint32_t _initial_recv_buffer_size,
+ std::uint32_t _recv_buffer_size_initial,
std::uint32_t _buffer_shrink_threshold,
bool _magic_cookies_enabled,
boost::asio::io_service &_io_service,
@@ -213,8 +228,8 @@ tcp_server_endpoint_impl::connection::connection(
socket_(_io_service),
server_(_server),
max_message_size_(_max_message_size),
- recv_buffer_size_initial_(_initial_recv_buffer_size),
- recv_buffer_(_initial_recv_buffer_size, 0),
+ recv_buffer_size_initial_(_recv_buffer_size_initial),
+ recv_buffer_(_recv_buffer_size_initial, 0),
recv_buffer_size_(0),
missing_capacity_(0),
shrink_count_(0),
@@ -235,8 +250,7 @@ tcp_server_endpoint_impl::connection::create(
boost::asio::io_service & _io_service,
std::chrono::milliseconds _send_timeout) {
const std::uint32_t its_initial_receveive_buffer_size =
- VSOMEIP_SOMEIP_HEADER_SIZE + 8 + MAGIC_COOKIE_SIZE + 8
- + VSOMEIP_MAX_TCP_MESSAGE_SIZE;
+ VSOMEIP_SOMEIP_HEADER_SIZE + 8 + MAGIC_COOKIE_SIZE + 8;
return ptr(new connection(_server, _max_message_size,
its_initial_receveive_buffer_size,
_buffer_shrink_threshold, _magic_cookies_enabled,
@@ -272,6 +286,12 @@ void tcp_server_endpoint_impl::connection::receive() {
if (its_capacity < its_required_capacity) {
recv_buffer_.reserve(its_required_capacity);
recv_buffer_.resize(its_required_capacity, 0x0);
+ if (recv_buffer_.size() > 1048576) {
+ VSOMEIP_INFO << "tse: recv_buffer size is: " <<
+ recv_buffer_.size()
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
}
buffer_size = missing_capacity_;
missing_capacity_ = 0;
@@ -412,7 +432,7 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
return;
}
uint32_t current_message_size = static_cast<uint32_t>(read_message_size);
- has_full_message = (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE
+ has_full_message = (current_message_size > VSOMEIP_RETURN_CODE_POS
&& current_message_size <= recv_buffer_size_);
if (has_full_message) {
bool needs_forwarding(true);
@@ -424,7 +444,12 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
= its_server->find_magic_cookie(&recv_buffer_[its_iteration_gap],
recv_buffer_size_);
if (its_offset < current_message_size) {
- VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing.";
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
if (!is_magic_cookie(its_iteration_gap)) {
its_host->on_error(&recv_buffer_[its_iteration_gap],
static_cast<length_t>(recv_buffer_size_),its_server.get(),
@@ -443,14 +468,16 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
std::memcpy(&its_client,
&recv_buffer_[its_iteration_gap + VSOMEIP_CLIENT_POS_MIN],
sizeof(client_t));
- session_t its_session;
- std::memcpy(&its_session,
- &recv_buffer_[its_iteration_gap + VSOMEIP_SESSION_POS_MIN],
- sizeof(session_t));
- its_server->clients_mutex_.lock();
- its_server->clients_[its_client][its_session] = remote_;
- its_server->endpoint_to_client_[remote_] = its_client;
- its_server->clients_mutex_.unlock();
+ if (its_client != MAGIC_COOKIE_NETWORK_BYTE_ORDER) {
+ session_t its_session;
+ std::memcpy(&its_session,
+ &recv_buffer_[its_iteration_gap + VSOMEIP_SESSION_POS_MIN],
+ sizeof(session_t));
+ its_server->clients_mutex_.lock();
+ its_server->clients_[its_client][its_session] = remote_;
+ its_server->endpoint_to_client_[remote_] = its_client;
+ its_server->clients_mutex_.unlock();
+ }
}
if (!magic_cookies_enabled_) {
its_host->on_message(&recv_buffer_[its_iteration_gap],
@@ -478,7 +505,12 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
its_server->find_magic_cookie(&recv_buffer_[its_iteration_gap],
recv_buffer_size_);
if (its_offset < recv_buffer_size_) {
- VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing.";
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
if (!is_magic_cookie(its_iteration_gap)) {
its_host->on_error(&recv_buffer_[its_iteration_gap],
static_cast<length_t>(recv_buffer_size_), its_server.get(),
@@ -496,7 +528,53 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
}
if (!has_full_message) {
- if (max_message_size_ != MESSAGE_SIZE_UNLIMITED
+ if (recv_buffer_size_ > VSOMEIP_RETURN_CODE_POS &&
+ (recv_buffer_[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
+ !utility::is_valid_message_type(static_cast<message_type_e>(recv_buffer_[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])) ||
+ !utility::is_valid_return_code(static_cast<return_code_e>(recv_buffer_[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))
+ )) {
+ if (recv_buffer_[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ VSOMEIP_ERROR << "tse: Wrong protocol version: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t(recv_buffer_[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << ". Closing connection due to missing/broken data TCP stream.";
+ }
+ // ensure to send back a error message w/ wrong protocol version
+ its_host->on_message(&recv_buffer_[its_iteration_gap],
+ VSOMEIP_SOMEIP_HEADER_SIZE + 8, its_server.get(),
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ remote_address_, remote_port_);
+ } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
+ recv_buffer_[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS]))) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ VSOMEIP_ERROR << "tse: Invalid message type: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t(recv_buffer_[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << ". Closing connection due to missing/broken data TCP stream.";
+ } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
+ recv_buffer_[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ VSOMEIP_ERROR << "tse: Invalid return code: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t(recv_buffer_[its_iteration_gap + VSOMEIP_RETURN_CODE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << ". Closing connection due to missing/broken data TCP stream.";
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(its_server->connections_mutex_);
+ stop();
+ }
+ its_server->remove_connection(this);
+ return;
+ } else if (max_message_size_ != MESSAGE_SIZE_UNLIMITED
&& current_message_size > max_message_size_) {
std::lock_guard<std::mutex> its_lock(socket_mutex_);
recv_buffer_size_ = 0;
@@ -517,9 +595,14 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
<< std::dec << current_message_size
<< " > " << std::dec << max_message_size_
<< ") Magic cookies are disabled: "
- << "Connection will be disabled! local: "
+ << "Connection will be closed! local: "
<< get_address_port_local() << " remote: "
<< get_address_port_remote();
+ {
+ std::lock_guard<std::mutex> its_lock(its_server->connections_mutex_);
+ stop();
+ }
+ its_server->remove_connection(this);
return;
}
} else if (current_message_size > recv_buffer_size_) {
@@ -528,6 +611,18 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
} else if (VSOMEIP_SOMEIP_HEADER_SIZE > recv_buffer_size_) {
missing_capacity_ = VSOMEIP_SOMEIP_HEADER_SIZE
- static_cast<std::uint32_t>(recv_buffer_size_);
+ } else if (magic_cookies_enabled_ && recv_buffer_size_ > 0) {
+ // no need to check for magic cookie here again: has_full_message
+ // would have been set to true if there was one present in the data
+ recv_buffer_size_ = 0;
+ recv_buffer_.resize(recv_buffer_size_initial_, 0x0);
+ recv_buffer_.shrink_to_fit();
+ missing_capacity_ = 0;
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ VSOMEIP_ERROR << "Didn't find magic cookie in broken"
+ << " data, trying to resync."
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
} else {
{
std::lock_guard<std::mutex> its_lock(socket_mutex_);
diff --git a/implementation/endpoints/src/udp_client_endpoint_impl.cpp b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
index 7be55f4..67c9703 100644
--- a/implementation/endpoints/src/udp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
@@ -20,12 +20,13 @@ udp_client_endpoint_impl::udp_client_endpoint_impl(
endpoint_type _local,
endpoint_type _remote,
boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit)
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _udp_receive_buffer_size)
: udp_client_endpoint_base_impl(_host, _local, _remote, _io,
VSOMEIP_MAX_UDP_MESSAGE_SIZE, _queue_limit),
- recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0),
remote_address_(_remote.address()),
- remote_port_(_remote.port()) {
+ remote_port_(_remote.port()),
+ udp_receive_buffer_size_(_udp_receive_buffer_size) {
}
udp_client_endpoint_impl::~udp_client_endpoint_impl() {
@@ -53,6 +54,26 @@ void udp_client_endpoint_impl::connect() {
<< "SO_REUSEADDR: " << its_error.message() << " remote:"
<< get_address_port_remote();
}
+ socket_->set_option(boost::asio::socket_base::receive_buffer_size(
+ udp_receive_buffer_size_), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't set "
+ << "SO_RCVBUF: " << its_error.message() << " to: "
+ << std::dec << udp_receive_buffer_size_ << " remote:"
+ << get_address_port_remote();
+ } else {
+ boost::asio::socket_base::receive_buffer_size its_option;
+ socket_->get_option(its_option, its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't get "
+ << "SO_RCVBUF: " << its_error.message() << " remote:"
+ << get_address_port_remote();
+ } else {
+ VSOMEIP_INFO << "udp_client_endpoint_impl::connect: SO_RCVBUF is: "
+ << std::dec << its_option.value();
+ }
+ }
+
// In case a client endpoint port was configured,
// bind to it before connecting
if (local_.port() != ILLEGAL_PORT) {
@@ -64,7 +85,7 @@ void udp_client_endpoint_impl::connect() {
<< " remote:" << get_address_port_remote();
try {
// don't connect on bind error to avoid using a random port
- service_.post(std::bind(&client_endpoint_impl::connect_cbk,
+ strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
shared_from_this(), its_bind_error));
} catch (const std::exception &e) {
VSOMEIP_ERROR << "udp_client_endpoint_impl::connect: "
@@ -76,15 +97,19 @@ void udp_client_endpoint_impl::connect() {
state_ = cei_state_e::CONNECTING;
socket_->async_connect(
remote_,
- std::bind(
- &udp_client_endpoint_base_impl::connect_cbk,
- shared_from_this(),
- std::placeholders::_1
+ strand_.wrap(
+ std::bind(
+ &udp_client_endpoint_base_impl::connect_cbk,
+ shared_from_this(),
+ std::placeholders::_1
+ )
)
);
} else {
VSOMEIP_WARNING << "udp_client_endpoint::connect: Error opening socket: "
<< its_error.message() << " remote:" << get_address_port_remote();
+ strand_.post(std::bind(&udp_client_endpoint_base_impl::connect_cbk,
+ shared_from_this(), its_error));
}
}
@@ -107,6 +132,8 @@ void udp_client_endpoint_impl::restart(bool _force) {
local = get_address_port_local();
}
shutdown_and_close_socket(false);
+ was_not_connected_ = true;
+ reconnect_counter_ = 0;
VSOMEIP_WARNING << "uce::restart: local: " << local
<< " remote: " << get_address_port_remote();
start_connect_timer();
@@ -148,16 +175,20 @@ void udp_client_endpoint_impl::receive() {
if (!socket_->is_open()) {
return;
}
+ message_buffer_ptr_t its_buffer = std::make_shared<message_buffer_t>(VSOMEIP_MAX_UDP_MESSAGE_SIZE);
socket_->async_receive_from(
- boost::asio::buffer(&recv_buffer_[0], max_message_size_),
+ boost::asio::buffer(*its_buffer),
remote_,
- std::bind(
- &udp_client_endpoint_impl::receive_cbk,
- std::dynamic_pointer_cast<
- udp_client_endpoint_impl
- >(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2
+ strand_.wrap(
+ std::bind(
+ &udp_client_endpoint_impl::receive_cbk,
+ std::dynamic_pointer_cast<
+ udp_client_endpoint_impl
+ >(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer
+ )
)
);
}
@@ -190,7 +221,8 @@ std::uint16_t udp_client_endpoint_impl::get_remote_port() const {
}
void udp_client_endpoint_impl::receive_cbk(
- boost::system::error_code const &_error, std::size_t _bytes) {
+ boost::system::error_code const &_error, std::size_t _bytes,
+ message_buffer_ptr_t _recv_buffer) {
if (_error == boost::asio::error::operation_aborted) {
// endpoint was stopped
return;
@@ -202,7 +234,7 @@ void udp_client_endpoint_impl::receive_cbk(
msg << "ucei::rcb(" << _error.message() << "): ";
for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i)
msg << std::hex << std::setw(2) << std::setfill('0')
- << (int) recv_buffer_[i] << " ";
+ << (int) (*_recv_buffer)[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
std::size_t remaining_bytes = _bytes;
@@ -210,7 +242,7 @@ void udp_client_endpoint_impl::receive_cbk(
do {
uint64_t read_message_size
- = utility::get_message_size(&this->recv_buffer_[i],
+ = utility::get_message_size(&(*_recv_buffer)[i],
remaining_bytes);
if (read_message_size > MESSAGE_SIZE_UNLIMITED) {
VSOMEIP_ERROR << "Message size exceeds allowed maximum!";
@@ -222,10 +254,45 @@ void udp_client_endpoint_impl::receive_cbk(
if (remaining_bytes - current_message_size > remaining_bytes) {
VSOMEIP_ERROR << "buffer underflow in udp client endpoint ~> abort!";
return;
+ } else if (current_message_size > VSOMEIP_RETURN_CODE_POS &&
+ ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
+ !utility::is_valid_message_type(static_cast<message_type_e>((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])) ||
+ !utility::is_valid_return_code(static_cast<return_code_e>((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))
+ )) {
+ if ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
+ VSOMEIP_ERROR << "uce: Wrong protocol version: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ // ensure to send back a message w/ wrong protocol version
+ its_host->on_message(&(*_recv_buffer)[i],
+ VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ remote_address_,
+ remote_port_);
+ } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
+ (*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS]))) {
+ VSOMEIP_ERROR << "uce: Invalid message type: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
+ (*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))) {
+ VSOMEIP_ERROR << "uce: Invalid return code: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
+ receive();
+ return;
}
remaining_bytes -= current_message_size;
- its_host->on_message(&recv_buffer_[i], current_message_size,
+ its_host->on_message(&(*_recv_buffer)[i], current_message_size,
this, boost::asio::ip::address(),
VSOMEIP_ROUTING_CLIENT, remote_address_,
remote_port_);
@@ -304,4 +371,12 @@ std::string udp_client_endpoint_impl::get_remote_information() const {
+ std::to_string(remote_.port());
}
+std::uint32_t udp_client_endpoint_impl::get_max_allowed_reconnects() const {
+ return MAX_RECONNECTS_UNLIMITED;
+}
+
+void udp_client_endpoint_impl::max_allowed_reconnects_reached() {
+ return;
+}
+
} // namespace vsomeip
diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
index 6da5b32..6ad7ce8 100644
--- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
@@ -8,6 +8,8 @@
#include <boost/asio/ip/multicast.hpp>
+#include <vsomeip/constants.hpp>
+
#include "../include/endpoint_definition.hpp"
#include "../include/endpoint_host.hpp"
#include "../include/udp_server_endpoint_impl.hpp"
@@ -25,7 +27,8 @@ udp_server_endpoint_impl::udp_server_endpoint_impl(
std::shared_ptr< endpoint_host > _host,
endpoint_type _local,
boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit)
+ configuration::endpoint_queue_limit_t _queue_limit,
+ std::uint32_t _udp_receive_buffer_size)
: server_endpoint_impl<ip::udp_ext>(
_host, _local, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE, _queue_limit),
socket_(_io, _local.protocol()),
@@ -60,6 +63,27 @@ udp_server_endpoint_impl::udp_server_endpoint_impl(
socket_.set_option(option, ec);
boost::asio::detail::throw_error(ec, "broadcast option");
+ socket_.set_option(boost::asio::socket_base::receive_buffer_size(
+ _udp_receive_buffer_size), ec);
+ if (ec) {
+ VSOMEIP_WARNING << "udp_server_endpoint_impl:: couldn't set "
+ << "SO_RCVBUF: " << ec.message() << " to: " << std::dec
+ << _udp_receive_buffer_size << " local port: " << std::dec
+ << local_port_;
+ } else {
+ boost::asio::socket_base::receive_buffer_size its_option;
+ socket_.get_option(its_option, ec);
+ if (ec) {
+ VSOMEIP_WARNING << "udp_server_endpoint_impl: couldn't get "
+ << "SO_RCVBUF: " << ec.message() << " local port:"
+ << std::dec << local_port_;
+ } else {
+ VSOMEIP_INFO << "udp_server_endpoint_impl: SO_RCVBUF is: "
+ << std::dec << its_option.value();
+ }
+ }
+
+
#ifdef _WIN32
const char* optval("0001");
::setsockopt(socket_.native(), IPPROTO_IP, IP_PKTINFO,
@@ -167,8 +191,7 @@ bool udp_server_endpoint_impl::is_joined(
void udp_server_endpoint_impl::join(const std::string &_address) {
bool has_received(false);
- std::function<void(const std::string &)> join_func =
- [this](const std::string &_address) {
+ auto join_func = [this](const std::string &_address) {
try {
bool is_v4(false);
bool is_v6(false);
@@ -318,6 +341,41 @@ void udp_server_endpoint_impl::receive_cbk(
if (remaining_bytes - current_message_size > remaining_bytes) {
VSOMEIP_ERROR << "buffer underflow in udp client endpoint ~> abort!";
return;
+ } else if (current_message_size > VSOMEIP_RETURN_CODE_POS &&
+ (recv_buffer_[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
+ !utility::is_valid_message_type(static_cast<message_type_e>(recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS])) ||
+ !utility::is_valid_return_code(static_cast<return_code_e>(recv_buffer_[i + VSOMEIP_RETURN_CODE_POS]))
+ )) {
+ if (recv_buffer_[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
+ VSOMEIP_ERROR << "use: Wrong protocol version: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t(recv_buffer_[i + VSOMEIP_PROTOCOL_VERSION_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
+ // ensure to send back a message w/ wrong protocol version
+ its_host->on_message(&recv_buffer_[i],
+ VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
+ _destination,
+ VSOMEIP_ROUTING_CLIENT,
+ its_remote_address,
+ its_remote_port);
+ } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
+ recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS]))) {
+ VSOMEIP_ERROR << "use: Invalid message type: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t(recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
+ } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
+ recv_buffer_[i + VSOMEIP_RETURN_CODE_POS]))) {
+ VSOMEIP_ERROR << "use: Invalid return code: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t(recv_buffer_[i + VSOMEIP_RETURN_CODE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
+ }
+ receive();
+ return;
}
remaining_bytes -= current_message_size;
service_t its_service = VSOMEIP_BYTES_TO_WORD(recv_buffer_[i + VSOMEIP_SERVICE_POS_MIN],
@@ -328,14 +386,16 @@ void udp_server_endpoint_impl::receive_cbk(
std::memcpy(&its_client,
&recv_buffer_[i + VSOMEIP_CLIENT_POS_MIN],
sizeof(client_t));
- session_t its_session;
- std::memcpy(&its_session,
- &recv_buffer_[i + VSOMEIP_SESSION_POS_MIN],
- sizeof(session_t));
- clients_mutex_.lock();
- clients_[its_client][its_session] = remote_;
- endpoint_to_client_[remote_] = its_client;
- clients_mutex_.unlock();
+ if (its_client != MAGIC_COOKIE_NETWORK_BYTE_ORDER) {
+ session_t its_session;
+ std::memcpy(&its_session,
+ &recv_buffer_[i + VSOMEIP_SESSION_POS_MIN],
+ sizeof(session_t));
+ clients_mutex_.lock();
+ clients_[its_client][its_session] = remote_;
+ endpoint_to_client_[remote_] = its_client;
+ clients_mutex_.unlock();
+ }
} else if (its_service != VSOMEIP_SD_SERVICE
&& utility::is_notification(recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS])
&& joined_group_) {
@@ -424,4 +484,20 @@ std::string udp_server_endpoint_impl::get_remote_information(
+ std::to_string(_queue_iterator->first.port());
}
+const std::string udp_server_endpoint_impl::get_address_port_local() const {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ std::string its_address_port;
+ its_address_port.reserve(21);
+ boost::system::error_code ec;
+ if (socket_.is_open()) {
+ endpoint_type its_local_endpoint = socket_.local_endpoint(ec);
+ if (!ec) {
+ its_address_port += its_local_endpoint.address().to_string(ec);
+ its_address_port += ":";
+ its_address_port += std::to_string(its_local_endpoint.port());
+ }
+ }
+ return its_address_port;
+}
+
} // namespace vsomeip
diff --git a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
index 30862df..20d40d7 100644
--- a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
@@ -24,10 +24,14 @@ void virtual_server_endpoint_impl::start() {
void virtual_server_endpoint_impl::stop() {
}
-bool virtual_server_endpoint_impl::is_connected() const {
+bool virtual_server_endpoint_impl::is_established() const {
return false;
}
+void virtual_server_endpoint_impl::set_established(bool _established) {
+ (void) _established;
+}
+
void virtual_server_endpoint_impl::set_connected(bool _connected) {
(void) _connected;
}
diff --git a/implementation/message/include/deserializer.hpp b/implementation/message/include/deserializer.hpp
index 7449f9b..4c01c79 100644
--- a/implementation/message/include/deserializer.hpp
+++ b/implementation/message/include/deserializer.hpp
@@ -29,7 +29,7 @@ public:
VSOMEIP_EXPORT std::size_t get_available() const;
VSOMEIP_EXPORT std::size_t get_remaining() const;
- VSOMEIP_EXPORT void set_remaining(std::size_t _length);
+ VSOMEIP_EXPORT void set_remaining(std::size_t _remaining);
// to be used by applications to deserialize a message
VSOMEIP_EXPORT message * deserialize_message();
@@ -41,6 +41,7 @@ public:
VSOMEIP_EXPORT bool deserialize(uint32_t& _value,
bool _omit_last_byte = false);
VSOMEIP_EXPORT bool deserialize(uint8_t *_data, std::size_t _length);
+ VSOMEIP_EXPORT bool deserialize(std::string& _target, std::size_t _length);
VSOMEIP_EXPORT bool deserialize(std::vector<uint8_t>& _value);
VSOMEIP_EXPORT bool look_ahead(std::size_t _index, uint8_t &_value) const;
diff --git a/implementation/message/include/message_base_impl.hpp b/implementation/message/include/message_base_impl.hpp
index ad42261..efd5ffe 100644
--- a/implementation/message/include/message_base_impl.hpp
+++ b/implementation/message/include/message_base_impl.hpp
@@ -42,10 +42,10 @@ public:
VSOMEIP_EXPORT void set_session(session_t _session);
VSOMEIP_EXPORT protocol_version_t get_protocol_version() const;
- VSOMEIP_EXPORT void set_protocol_version(protocol_version_t _version);
+ VSOMEIP_EXPORT void set_protocol_version(protocol_version_t _protocol_version);
VSOMEIP_EXPORT interface_version_t get_interface_version() const;
- VSOMEIP_EXPORT void set_interface_version(interface_version_t _version);
+ VSOMEIP_EXPORT void set_interface_version(interface_version_t _interface_version);
VSOMEIP_EXPORT message_type_e get_message_type() const;
VSOMEIP_EXPORT void set_message_type(message_type_e _type);
diff --git a/implementation/message/include/message_header_impl.hpp b/implementation/message/include/message_header_impl.hpp
index 5768bbe..8cd4b00 100644
--- a/implementation/message/include/message_header_impl.hpp
+++ b/implementation/message/include/message_header_impl.hpp
@@ -18,7 +18,7 @@ class message_base;
class message_header_impl: virtual public serializable {
public:
VSOMEIP_EXPORT message_header_impl();
- VSOMEIP_EXPORT message_header_impl(const message_header_impl& header);
+ VSOMEIP_EXPORT message_header_impl(const message_header_impl& _header);
VSOMEIP_EXPORT bool serialize(serializer *_to) const;
VSOMEIP_EXPORT bool deserialize(deserializer *_from);
diff --git a/implementation/message/include/payload_impl.hpp b/implementation/message/include/payload_impl.hpp
index f9b05a2..2eb67e9 100644
--- a/implementation/message/include/payload_impl.hpp
+++ b/implementation/message/include/payload_impl.hpp
@@ -18,7 +18,7 @@ class payload_impl: public payload {
public:
VSOMEIP_EXPORT payload_impl();
VSOMEIP_EXPORT payload_impl(const byte_t *_data, uint32_t _size);
- VSOMEIP_EXPORT payload_impl(const std::vector< byte_t > &_value);
+ VSOMEIP_EXPORT payload_impl(const std::vector< byte_t > &_data);
VSOMEIP_EXPORT payload_impl(const payload_impl& _payload);
VSOMEIP_EXPORT virtual ~payload_impl();
diff --git a/implementation/message/src/deserializer.cpp b/implementation/message/src/deserializer.cpp
index 8a3c891..b416199 100644
--- a/implementation/message/src/deserializer.cpp
+++ b/implementation/message/src/deserializer.cpp
@@ -111,6 +111,17 @@ bool deserializer::deserialize(uint8_t *_data, std::size_t _length) {
return true;
}
+bool deserializer::deserialize(std::string& _target, std::size_t _length) {
+ if (_length > remaining_ || _length > _target.capacity()) {
+ return false;
+ }
+ _target.assign(position_, position_ + _length);
+ position_ += _length;
+ remaining_ -= _length;
+
+ return true;
+}
+
bool deserializer::deserialize(std::vector< uint8_t >& _value) {
if (_value.capacity() > remaining_)
return false;
diff --git a/implementation/plugin/include/plugin_manager.hpp b/implementation/plugin/include/plugin_manager.hpp
index 98afd72..7d2d7f0 100644
--- a/implementation/plugin/include/plugin_manager.hpp
+++ b/implementation/plugin/include/plugin_manager.hpp
@@ -46,7 +46,7 @@ private:
std::map<plugin_type_e, std::map<std::string, std::shared_ptr<plugin> > > plugins_;
std::map<plugin_type_e, std::map<std::string, void*> > handles_;
- std::mutex plugins_mutex_;
+ std::recursive_mutex plugins_mutex_;
static std::shared_ptr<plugin_manager> the_plugin_manager__;
};
diff --git a/implementation/plugin/src/plugin_manager.cpp b/implementation/plugin/src/plugin_manager.cpp
index e922fd6..3b9b3f7 100644
--- a/implementation/plugin/src/plugin_manager.cpp
+++ b/implementation/plugin/src/plugin_manager.cpp
@@ -62,7 +62,7 @@ void plugin_manager::load_plugins() {
}
}
- std::lock_guard<std::mutex> its_lock_start_stop(plugins_mutex_);
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
// Load plug-in info from libraries parsed before
for (auto plugin_name : plugins) {
void* handle = load_library(plugin_name);
@@ -105,7 +105,7 @@ void plugin_manager::load_plugins() {
}
std::shared_ptr<plugin> plugin_manager::get_plugin(plugin_type_e _type, std::string _name) {
- std::lock_guard<std::mutex> its_lock_start_stop(plugins_mutex_);
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
auto its_type = plugins_.find(_type);
if (its_type != plugins_.end()) {
auto its_name = its_type->second.find(_name);
@@ -142,7 +142,7 @@ std::shared_ptr<plugin> plugin_manager::load_plugin(const std::string _library,
}
bool plugin_manager::unload_plugin(plugin_type_e _type) {
- std::lock_guard<std::mutex> its_lock_start_stop(plugins_mutex_);
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
const auto found_handle = handles_.find(_type);
if (found_handle != handles_.end()) {
for (auto its_name : found_handle->second) {
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp
index 674f41b..668bbf4 100644
--- a/implementation/routing/include/event.hpp
+++ b/implementation/routing/include/event.hpp
@@ -72,7 +72,7 @@ public:
void set_change_resets_cycle(bool _change_resets_cycle);
// SIP_RPC_358
- void set_update_on_change(bool _is_on);
+ void set_update_on_change(bool _is_active);
// SIP_RPC_359 (epsilon change)
void set_epsilon_change_function(const epsilon_change_func_t &_epsilon_change_func);
@@ -126,6 +126,9 @@ private:
bool set_payload_helper(const std::shared_ptr<payload> &_payload, bool _force);
void reset_payload(const std::shared_ptr<payload> &_payload);
+ void notify_one_unlocked(const std::shared_ptr<endpoint_definition> &_target, bool _flush);
+ void notify_one_unlocked(client_t _client, bool _flush);
+
private:
routing_manager *routing_;
mutable std::mutex mutex_;
diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp
index f02c533..9ab09f4 100644
--- a/implementation/routing/include/routing_manager.hpp
+++ b/implementation/routing/include/routing_manager.hpp
@@ -15,6 +15,7 @@
#include <vsomeip/function_types.hpp>
#include <vsomeip/message.hpp>
#include <vsomeip/handler.hpp>
+#include "types.hpp"
namespace vsomeip {
@@ -62,7 +63,9 @@ public:
bool _flush) = 0;
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable, bool _is_valid_crc = true) = 0;
+ instance_t _instance, bool _flush, bool _reliable,
+ client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
+ bool _is_valid_crc = true, bool _sent_from_remote = false) = 0;
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
std::shared_ptr<message>, bool _flush) = 0;
@@ -94,7 +97,7 @@ public:
virtual void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush) = 0;
+ client_t _client, bool _force, bool _flush, bool _remote_subscriber) = 0;
virtual void on_identify_response(client_t _client, service_t _service,
instance_t _instance, bool _reliable) = 0;
diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp
index 7bf3a4d..6bee10c 100644
--- a/implementation/routing/include/routing_manager_base.hpp
+++ b/implementation/routing/include/routing_manager_base.hpp
@@ -23,18 +23,13 @@
#include "../../configuration/include/configuration.hpp"
#include "../../endpoints/include/endpoint_host.hpp"
+namespace vsomeip {
#ifdef USE_DLT
-#include "../../tracing/include/trace_connector.hpp"
-#endif
-
-#ifdef USE_DLT
-namespace tc {
-class trace_connector;
-} // namespace tc
+namespace trace {
+class connector_impl;
+} // namespace trace
#endif
-namespace vsomeip {
-
class serializer;
class routing_manager_base : public routing_manager,
@@ -90,13 +85,15 @@ public:
virtual void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush);
+ client_t _client, bool _force, bool _flush, bool _remote_subscriber);
virtual bool send(client_t _client, std::shared_ptr<message> _message,
bool _flush);
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable, bool _is_valid_crc = true) = 0;
+ instance_t _instance, bool _flush, bool _reliable,
+ client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
+ bool _is_valid_crc = true, bool _sent_from_remote = false) = 0;
// Endpoint host ~> will be implemented by routing_manager_impl/_proxy/
virtual void on_connect(std::shared_ptr<endpoint> _endpoint) = 0;
@@ -125,6 +122,8 @@ public:
virtual void send_get_offered_services_info(client_t _client, offer_type_e _offer_type) = 0;
+ std::set<client_t> find_local_clients(service_t _service, instance_t _instance);
+
protected:
std::shared_ptr<serviceinfo> find_service(service_t _service, instance_t _instance) const;
std::shared_ptr<serviceinfo> create_service_info(service_t _service,
@@ -133,14 +132,16 @@ protected:
void clear_service_info(service_t _service, instance_t _instance, bool _reliable);
services_t get_services() const;
+ services_t get_services_remote() const;
bool is_available(service_t _service, instance_t _instance, major_version_t _major);
client_t find_local_client(service_t _service, instance_t _instance);
std::shared_ptr<endpoint> create_local(client_t _client);
std::shared_ptr<endpoint> find_or_create_local(client_t _client);
- void remove_local(client_t _client);
+ void remove_local(client_t _client, bool _remove_uid);
void remove_local(client_t _client,
- const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups);
+ const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups,
+ bool _remove_uid);
std::shared_ptr<endpoint> find_local(client_t _client);
std::shared_ptr<endpoint> find_local(service_t _service,
@@ -182,7 +183,7 @@ protected:
eventgroup_t _eventgroup, event_t _event);
void send_pending_notify_ones(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, client_t _client);
+ eventgroup_t _eventgroup, client_t _client, bool _remote_subscriber = false);
void unset_all_eventpayloads(service_t _service, instance_t _instance);
void unset_all_eventpayloads(service_t _service, instance_t _instance,
@@ -200,6 +201,23 @@ protected:
std::set<std::tuple<service_t, instance_t, eventgroup_t>>
get_subscriptions(const client_t _client);
+
+ std::vector<event_t> find_events(service_t _service, instance_t _instance) const;
+
+ bool is_response_allowed(client_t _sender, service_t _service,
+ instance_t _instance, method_t _method);
+ bool is_subscribe_to_any_event_allowed(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup);
+
+ void set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event, subscription_state_e _state);
+
+ subscription_state_e get_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event);
+
+ void erase_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event);
+
private:
std::shared_ptr<endpoint> create_local_unlocked(client_t _client);
std::shared_ptr<endpoint> find_local_unlocked(client_t _client);
@@ -224,6 +242,7 @@ protected:
std::mutex local_services_mutex_;
std::map<service_t, std::map<instance_t, std::tuple< major_version_t, minor_version_t, client_t> > > local_services_;
+ std::map<service_t, std::map<instance_t, std::set<client_t> > > local_services_history_;
// Eventgroups
mutable std::mutex eventgroups_mutex_;
@@ -236,7 +255,7 @@ protected:
std::map<instance_t, std::map<event_t, std::shared_ptr<event> > > > events_;
#ifdef USE_DLT
- std::shared_ptr<tc::trace_connector> tc_;
+ std::shared_ptr<trace::connector_impl> tc_;
#endif
struct subscription_data_t {
@@ -263,7 +282,7 @@ protected:
std::set<subscription_data_t> pending_subscriptions_;
services_t services_remote_;
- std::mutex services_remote_mutex_;
+ mutable std::mutex services_remote_mutex_;
private:
services_t services_;
@@ -276,7 +295,18 @@ private:
std::map<instance_t,
std::map<eventgroup_t,
std::shared_ptr<message> > > > pending_notify_ones_;
- std::mutex pending_notify_ones_mutex_;
+ std::recursive_mutex pending_notify_ones_mutex_;
+
+ std::mutex event_registration_mutex_;
+
+ std::map<client_t,
+ std::map<service_t,
+ std::map<instance_t,
+ std::map<eventgroup_t,
+ std::map<event_t,
+ subscription_state_e> > > > > incoming_subscription_state_;
+ std::recursive_mutex incoming_subscription_state_mutex_;
+
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index 2e90077..40abf73 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -84,8 +84,10 @@ public:
bool send(client_t _client, std::shared_ptr<message> _message, bool _flush);
- bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable, bool _is_valid_crc = true);
+ virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
+ instance_t _instance, bool _flush, bool _reliable,
+ client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
+ bool _is_valid_crc = true, bool _sent_from_remote = false);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
std::shared_ptr<message> _message, bool _flush);
@@ -115,7 +117,7 @@ public:
void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush);
+ client_t _client, bool _force, bool _flush, bool _remote_subscriber);
void on_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
@@ -137,7 +139,7 @@ public:
return routing_manager_base::find_or_create_local(_client);
}
- void remove_local(client_t _client);
+ void remove_local(client_t _client, bool _remove_uid);
void on_stop_offer_service(client_t _client, service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor);
@@ -159,18 +161,27 @@ public:
void on_error(const byte_t *_data, length_t _length, endpoint *_receiver,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
- void on_message(const byte_t *_data, length_t _length, endpoint *_receiver,
+ void on_message(const byte_t *_data, length_t _size, endpoint *_receiver,
const boost::asio::ip::address &_destination,
client_t _bound_client,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
bool on_message(service_t _service, instance_t _instance,
- const byte_t *_data, length_t _size, bool _reliable, bool _is_valid_crc = true);
+ const byte_t *_data, length_t _size, bool _reliable,
+ client_t _bound_client, bool _is_valid_crc = true,
+ bool _is_from_remote = false);
void on_notification(client_t _client, service_t _service,
instance_t _instance, const byte_t *_data, length_t _size,
bool _notify_one);
void release_port(uint16_t _port, bool _reliable);
+ bool offer_service_remotely(service_t _service, instance_t _instance,
+ std::uint16_t _port, bool _reliable,
+ bool _magic_cookies_enabled);
+ bool stop_offer_service_remotely(service_t _service, instance_t _instance,
+ std::uint16_t _port, bool _reliable,
+ bool _magic_cookies_enabled);
+
// interface "service_discovery_host"
typedef std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_t;
const servicegroups_t & get_servicegroups() const;
@@ -210,7 +221,7 @@ public:
void expire_subscriptions(const boost::asio::ip::address &_address);
void expire_services(const boost::asio::ip::address &_address);
- std::chrono::steady_clock::time_point expire_subscriptions();
+ std::chrono::steady_clock::time_point expire_subscriptions(bool _force);
bool has_identified(client_t _client, service_t _service,
instance_t _instance, bool _reliable);
@@ -230,11 +241,28 @@ public:
eventgroup_t _eventgroup,
const std::shared_ptr<endpoint_definition> &_subscriber);
+ void register_offer_acceptance_handler(offer_acceptance_handler_t _handler) const;
+ void register_reboot_notification_handler(reboot_notification_handler_t _handler) const;
+ void register_routing_ready_handler(routing_ready_handler_t _handler);
+ void register_routing_state_handler(routing_state_handler_t _handler);
+ void offer_acceptance_enabled(boost::asio::ip::address _address);
+
+ void on_resend_provided_events_response(pending_remote_offer_id_t _id);
+ bool update_security_policy_configuration(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy,
+ std::shared_ptr<payload> _payload, security_update_handler_t _handler);
+ bool remove_security_policy_configuration(uint32_t _uid, uint32_t _gid, security_update_handler_t _handler);
+ void on_security_update_response(pending_security_update_id_t _id, client_t _client);
+ std::set<client_t> find_local_clients(service_t _service, instance_t _instance);
+ bool is_subscribe_to_any_event_allowed(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup);
+
private:
- bool deliver_message(const byte_t *_data, length_t _length,
- instance_t _instance, bool _reliable, bool _is_valid_crc = true);
+ bool deliver_message(const byte_t *_data, length_t _size,
+ instance_t _instance, bool _reliable, client_t _bound_client,
+ bool _is_valid_crc = true, bool _is_from_remote = false);
bool deliver_notification(service_t _service, instance_t _instance,
- const byte_t *_data, length_t _length, bool _reliable, bool _is_valid_crc = true);
+ const byte_t *_data, length_t _length, bool _reliable, client_t _bound_client,
+ bool _is_valid_crc = true, bool _is_from_remote = false);
instance_t find_instance(service_t _service, endpoint *_endpoint);
@@ -273,6 +301,9 @@ private:
std::set<eventgroup_t> get_subscribed_eventgroups(service_t _service,
instance_t _instance);
+
+ void clear_targets_and_pending_sub_from_eventgroups(service_t _service, instance_t _instance);
+ void clear_remote_subscriber(service_t _service, instance_t _instance);
private:
return_code_e check_error(const byte_t *_data, length_t _size,
instance_t _instance);
@@ -371,7 +402,31 @@ private:
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
pending_subscription_id_t _pending_unsubscription_id);
+ void cleanup_server_endpoint(service_t _service,
+ const std::shared_ptr<endpoint>& _endpoint);
+
+ pending_remote_offer_id_t pending_remote_offer_add(service_t _service,
+ instance_t _instance);
+
+ std::pair<service_t, instance_t> pending_remote_offer_remove(
+ pending_remote_offer_id_t _id);
+
+ void on_security_update_timeout(
+ const boost::system::error_code& _error,
+ pending_security_update_id_t _id,
+ std::shared_ptr<boost::asio::steady_timer> _timer);
+
+ pending_security_update_id_t pending_security_update_add(
+ std::unordered_set<client_t> _clients);
+
+ std::unordered_set<client_t> pending_security_update_get(
+ pending_security_update_id_t _id);
+ bool pending_security_update_remove(
+ pending_security_update_id_t _id, client_t _client);
+
+ bool is_pending_security_update_finished(
+ pending_security_update_id_t _id);
std::shared_ptr<routing_manager_stub> stub_;
std::shared_ptr<sd::service_discovery> discovery_;
@@ -454,14 +509,34 @@ private:
std::map<std::tuple<service_t, instance_t, eventgroup_t, client_t>,
subscription_state_e> remote_subscription_state_;
- std::map<e2exf::data_identifier, std::shared_ptr<e2e::profile_interface::protector>> custom_protectors;
- std::map<e2exf::data_identifier, std::shared_ptr<e2e::profile_interface::checker>> custom_checkers;
+ std::map<e2exf::data_identifier_t, std::shared_ptr<e2e::profile_interface::protector>> custom_protectors;
+ std::map<e2exf::data_identifier_t, std::shared_ptr<e2e::profile_interface::checker>> custom_checkers;
std::mutex status_log_timer_mutex_;
boost::asio::steady_timer status_log_timer_;
std::mutex memory_log_timer_mutex_;
boost::asio::steady_timer memory_log_timer_;
+
+ routing_ready_handler_t routing_ready_handler_;
+ routing_state_handler_t routing_state_handler_;
+
+ std::mutex pending_remote_offers_mutex_;
+ pending_remote_offer_id_t pending_remote_offer_id_;
+ std::map<pending_remote_offer_id_t, std::pair<service_t, instance_t>> pending_remote_offers_;
+
+ std::mutex last_resume_mutex_;
+ std::chrono::steady_clock::time_point last_resume_;
+
+ std::mutex pending_security_updates_mutex_;
+ pending_security_update_id_t pending_security_update_id_;
+ std::map<pending_security_update_id_t, std::unordered_set<client_t>> pending_security_updates_;
+
+ std::recursive_mutex security_update_handlers_mutex_;
+ std::map<pending_security_update_id_t, security_update_handler_t> security_update_handlers_;
+
+ std::mutex security_update_timers_mutex_;
+ std::map<pending_security_update_id_t, std::shared_ptr<boost::asio::steady_timer>> security_update_timers_;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp
index 94d290c..fbe775d 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_proxy.hpp
@@ -61,7 +61,9 @@ public:
eventgroup_t _eventgroup, event_t _event);
bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush = true, bool _reliable = false, bool _is_valid_crc= true);
+ instance_t _instance, bool _flush, bool _reliable,
+ client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
+ bool _is_valid_crc = true, bool _sent_from_remote = false);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
std::shared_ptr<message> _message, bool _flush);
@@ -82,7 +84,7 @@ public:
void on_connect(std::shared_ptr<endpoint> _endpoint);
void on_disconnect(std::shared_ptr<endpoint> _endpoint);
- void on_message(const byte_t *_data, length_t _length, endpoint *_receiver,
+ void on_message(const byte_t *_data, length_t _size, endpoint *_receiver,
const boost::asio::ip::address &_destination,
client_t _bound_client,
const boost::asio::ip::address &_remote_address,
@@ -119,7 +121,7 @@ private:
instance_t _instance);
void send_register_event(client_t _client, service_t _service,
instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroup,
+ const std::set<eventgroup_t> &_eventgroups,
bool _is_field, bool _is_provided);
void send_subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
@@ -183,6 +185,13 @@ private:
eventgroup_t _eventgroup,
pending_subscription_id_t _subscription_id);
+ void resend_provided_event_registrations();
+ void send_resend_provided_event_response(pending_remote_offer_id_t _id);
+
+ void send_update_security_policy_response(pending_security_update_id_t _update_id);
+ void send_remove_security_policy_response(pending_security_update_id_t _update_id);
+ void on_update_security_credentials(const byte_t *_data, uint32_t _size);
+
private:
enum class inner_state_type_e : std::uint8_t {
ST_REGISTERED = 0x0,
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index f97aab5..d586518 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -14,6 +14,7 @@
#include <set>
#include <thread>
#include <atomic>
+#include <unordered_set>
#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
@@ -43,7 +44,7 @@ public:
void on_connect(std::shared_ptr<endpoint> _endpoint);
void on_disconnect(std::shared_ptr<endpoint> _endpoint);
- void on_message(const byte_t *_data, length_t _length, endpoint *_receiver,
+ void on_message(const byte_t *_data, length_t _size, endpoint *_receiver,
const boost::asio::ip::address &_destination,
client_t _bound_client,
const boost::asio::ip::address &_remote_address,
@@ -82,6 +83,7 @@ public:
bool send_ping(client_t _client);
bool is_registered(client_t _client) const;
client_t get_client() const;
+ void handle_credentials(const client_t _client, std::set<service_data_t>& _requests);
void handle_requests(const client_t _client, std::set<service_data_t>& _requests);
void send_identify_request_command(std::shared_ptr<vsomeip::endpoint> _target,
@@ -95,12 +97,31 @@ public:
void update_registration(client_t _client, registration_type_e _type);
void print_endpoint_status() const;
+
+ bool send_provided_event_resend_request(client_t _client,
+ pending_remote_offer_id_t _id);
+
+ bool is_policy_cached(uint32_t _uid);
+
+ void policy_cache_add(uint32_t _uid, std::shared_ptr<payload> _payload);
+
+ void policy_cache_remove(uint32_t _uid);
+
+ bool send_update_security_policy_request(client_t _client, pending_security_update_id_t _update_id,
+ uint32_t _uid, std::shared_ptr<payload> _payload);
+ bool send_remove_security_policy_request(client_t _client, pending_security_update_id_t _update_id,
+ uint32_t _uid, uint32_t _gid);
+
+ bool send_cached_security_policies(client_t _client);
+
private:
void broadcast(const std::vector<byte_t> &_command) const;
void on_register_application(client_t _client);
void on_deregister_application(client_t _client);
+ void distribute_credentials(client_t _hoster, service_t _service, instance_t _instance);
+
void inform_requesters(client_t _hoster, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor, routing_info_entry_e _entry,
@@ -138,6 +159,10 @@ private:
minor_version_t _minor);
void send_offered_services_info(const client_t _target);
+ void create_client_credentials_info(const client_t _target);
+ void insert_client_credentials_info(client_t _target, std::set<std::pair<uint32_t, uint32_t>> _credentials);
+ void send_client_credentials_info(const client_t _target);
+
void on_client_id_timer_expired(boost::system::error_code const &_error);
private:
@@ -182,6 +207,12 @@ private:
std::map<client_t, std::vector<byte_t>> client_routing_info_;
std::map<client_t, std::vector<byte_t>> offered_services_info_;
+ std::map<client_t, std::vector<byte_t>> client_credentials_info_;
+
+
+ std::mutex updated_security_policies_mutex_;
+ std::map<uint32_t, std::shared_ptr<payload>> updated_security_policies_;
+
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp
index a6d461e..5c474fb 100644
--- a/implementation/routing/include/routing_manager_stub_host.hpp
+++ b/implementation/routing/include/routing_manager_stub_host.hpp
@@ -61,7 +61,8 @@ public:
pending_subscription_id_t _unsubscription_id) = 0;
virtual bool on_message(service_t _service, instance_t _instance,
- const byte_t *_data, length_t _size, bool _reliable, bool _is_valid_crc = true) = 0;
+ const byte_t *_data, length_t _size, bool _reliable, client_t _bound_client,
+ bool _is_valid_crc = true, bool _is_from_remote = false) = 0;
virtual void on_notification(client_t _client,
service_t _service, instance_t _instance,
@@ -78,7 +79,7 @@ public:
virtual std::shared_ptr<endpoint> find_or_create_local(
client_t _client) = 0;
- virtual void remove_local(client_t _client) = 0;
+ virtual void remove_local(client_t _client, bool _remove_local) = 0;
virtual boost::asio::io_service & get_io() = 0;
virtual client_t get_client() const = 0;
@@ -91,6 +92,15 @@ public:
virtual void handle_client_error(client_t _client) = 0;
virtual void set_routing_state(routing_state_e _routing_state) = 0;
+
+ virtual void on_resend_provided_events_response(pending_remote_offer_id_t _id) = 0;
+
+ virtual void on_security_update_response(pending_security_update_id_t _id, client_t _client) = 0;
+
+ virtual std::set<client_t> find_local_clients(service_t _service, instance_t _instance) = 0;
+
+ virtual bool is_subscribe_to_any_event_allowed(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp
index 7eab1ec..72be585 100644
--- a/implementation/routing/include/serviceinfo.hpp
+++ b/implementation/routing/include/serviceinfo.hpp
@@ -24,6 +24,7 @@ class serviceinfo {
public:
VSOMEIP_EXPORT serviceinfo(major_version_t _major, minor_version_t _minor,
ttl_t _ttl, bool _is_local);
+ VSOMEIP_EXPORT serviceinfo(const serviceinfo& _other);
VSOMEIP_EXPORT ~serviceinfo();
VSOMEIP_EXPORT servicegroup * get_group() const;
@@ -36,7 +37,7 @@ public:
VSOMEIP_EXPORT void set_ttl(ttl_t _ttl);
VSOMEIP_EXPORT std::chrono::milliseconds get_precise_ttl() const;
- VSOMEIP_EXPORT void set_precise_ttl(std::chrono::milliseconds _ttl);
+ VSOMEIP_EXPORT void set_precise_ttl(std::chrono::milliseconds _precise_ttl);
VSOMEIP_EXPORT std::shared_ptr<endpoint> get_endpoint(bool _reliable) const;
VSOMEIP_EXPORT void set_endpoint(std::shared_ptr<endpoint> _endpoint,
diff --git a/implementation/routing/include/types.hpp b/implementation/routing/include/types.hpp
index f33a944..59acfa3 100644
--- a/implementation/routing/include/types.hpp
+++ b/implementation/routing/include/types.hpp
@@ -118,6 +118,8 @@ enum remote_subscription_state_e : std::uint8_t {
SUBSCRIPTION_ERROR
};
+typedef std::uint32_t pending_remote_offer_id_t;
+
}
// namespace vsomeip
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
index 13cd36e..ce78a65 100644
--- a/implementation/routing/src/event.cpp
+++ b/implementation/routing/src/event.cpp
@@ -138,7 +138,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _clie
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
if (is_updating_on_change_) {
- notify_one(_client, _flush);
+ notify_one_unlocked(_client, _flush);
}
}
} else {
@@ -155,7 +155,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload,
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
if (is_updating_on_change_) {
- notify_one(_target, _flush);
+ notify_one_unlocked(_target, _flush);
}
}
} else {
@@ -244,7 +244,7 @@ void event::update_cbk(boost::system::error_code const &_error) {
std::lock_guard<std::mutex> its_lock(mutex_);
cycle_timer_.expires_from_now(cycle_);
notify(true);
- std::function<void(boost::system::error_code const &)> its_handler =
+ auto its_handler =
std::bind(&event::update_cbk, shared_from_this(),
std::placeholders::_1);
cycle_timer_.async_wait(its_handler);
@@ -261,6 +261,11 @@ void event::notify(bool _flush) {
}
void event::notify_one(const std::shared_ptr<endpoint_definition> &_target, bool _flush) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ notify_one_unlocked(_target, _flush);
+}
+
+void event::notify_one_unlocked(const std::shared_ptr<endpoint_definition> &_target, bool _flush) {
if (is_set_) {
routing_->send_to(_target, message_, _flush);
} else {
@@ -270,6 +275,11 @@ void event::notify_one(const std::shared_ptr<endpoint_definition> &_target, bool
}
void event::notify_one(client_t _client, bool _flush) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ notify_one_unlocked(_client, _flush);
+}
+
+void event::notify_one_unlocked(client_t _client, bool _flush) {
if (is_set_) {
routing_->send(_client, message_, _flush);
} else {
@@ -421,7 +431,7 @@ void event::set_cache_placeholder(bool _is_cache_place_holder) {
void event::start_cycle() {
if (std::chrono::milliseconds::zero() != cycle_) {
cycle_timer_.expires_from_now(cycle_);
- std::function<void(boost::system::error_code const &)> its_handler =
+ auto its_handler =
std::bind(&event::update_cbk, shared_from_this(),
std::placeholders::_1);
cycle_timer_.async_wait(its_handler);
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index 62ae6f2..517ccdb 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -13,6 +13,9 @@
#include "../../logging/include/logger.hpp"
#include "../../endpoints/include/local_client_endpoint_impl.hpp"
#include "../../endpoints/include/local_server_endpoint_impl.hpp"
+#ifdef USE_DLT
+#include "../../tracing/include/connector_impl.hpp"
+#endif
namespace vsomeip {
@@ -25,7 +28,7 @@ routing_manager_base::routing_manager_base(routing_manager_host *_host) :
std::make_shared<serializer>(
configuration_->get_buffer_shrink_threshold()))
#ifdef USE_DLT
- , tc_(tc::trace_connector::get())
+ , tc_(trace::connector_impl::get())
#endif
{
const uint32_t its_buffer_shrink_threshold =
@@ -153,6 +156,16 @@ void routing_manager_base::release_service(client_t _client, service_t _service,
if (its_info) {
its_info->remove_client(_client);
}
+ {
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ auto found_service = local_services_history_.find(_service);
+ if (found_service != local_services_history_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ local_services_history_.erase(_service);
+ }
+ }
+ }
}
void routing_manager_base::register_event(client_t _client, service_t _service, instance_t _instance,
@@ -160,6 +173,7 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
epsilon_change_func_t _epsilon_change_func,
bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) {
+ std::lock_guard<std::mutex> its_event_reg_lock(event_registration_mutex_);
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
bool transfer_subscriptions_from_any_event(false);
if (its_event) {
@@ -438,6 +452,83 @@ std::set<std::shared_ptr<event>> routing_manager_base::find_events(
return (its_events);
}
+std::vector<event_t> routing_manager_base::find_events(
+ service_t _service, instance_t _instance) const {
+ std::vector<event_t> its_events;
+ std::lock_guard<std::mutex> its_lock(events_mutex_);
+ const auto found_service = events_.find(_service);
+ if (found_service != events_.end()) {
+ const auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (const auto& e : found_instance->second) {
+ its_events.push_back(e.first);
+ }
+ }
+ }
+ return (its_events);
+}
+
+bool routing_manager_base::is_response_allowed(client_t _sender, service_t _service,
+ instance_t _instance, method_t _method) {
+ if (!configuration_->is_security_enabled()) {
+ return true;
+ }
+
+ if (_sender == find_local_client(_service, _instance)) {
+ // sender is still offering the service
+ return true;
+ }
+
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ auto found_service = local_services_history_.find(_service);
+ if (found_service != local_services_history_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_client = found_instance->second.find(_sender);
+ if (found_client != found_instance->second.end()) {
+ // sender was offering the service and is still connected
+ return true;
+ }
+ }
+ }
+
+ // service is now offered by another client
+ // or service is not offered at all
+ std::string security_mode_text = "!";
+ if (!configuration_->is_audit_mode_enabled()) {
+ security_mode_text = ", but will be allowed due to audit mode is active!";
+ }
+
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_base::is_response_allowed: "
+ << "received a response from client 0x" << _sender
+ << " which does not offer service/instance/method "
+ << _service << "/" << _instance << "/" << _method
+ << security_mode_text;
+
+ return !configuration_->is_audit_mode_enabled();
+}
+
+bool routing_manager_base::is_subscribe_to_any_event_allowed(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+ bool is_allowed(true);
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ for (auto e : its_eventgroup->get_events()) {
+ if (!configuration_->is_client_allowed(_client, _service, _instance, e->get_event())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
+ << _client << " : routing_manager_base::is_subscribe_to_any_event_allowed: "
+ << "subscribes to service/instance/event "
+ << _service << "/" << _instance << "/" << e->get_event()
+ << " which violates the security policy!";
+ is_allowed = false;
+ break;
+ }
+ }
+ }
+ return is_allowed;
+}
+
void routing_manager_base::subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
major_version_t _major, event_t _event,
@@ -486,13 +577,14 @@ void routing_manager_base::notify(service_t _service, instance_t _instance,
void routing_manager_base::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush) {
+ client_t _client, bool _force, bool _flush, bool _remote_subscriber) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
// Event is valid for service/instance
bool found_eventgroup(false);
bool already_subscribed(false);
eventgroup_t valid_group = 0;
+ subscription_state_e its_subscription_state(subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED);
// Iterate over all groups of the event to ensure at least
// one valid eventgroup for service/instance exists.
for (auto its_group : its_event->get_eventgroups()) {
@@ -501,10 +593,13 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
// Eventgroup is valid for service/instance
found_eventgroup = true;
valid_group = its_group;
+ its_subscription_state = get_incoming_subscription_state(_client, _service,
+ _instance, valid_group, _event);
if (find_local(_client)) {
already_subscribed = its_event->has_subscriber(its_group, _client);
- } else {
- // Remotes always needs to be marked as subscribed here
+ } else if (subscription_state_e::IS_SUBSCRIBING != its_subscription_state
+ || _remote_subscriber) {
+ // Remotes always needs to be marked as subscribed here if they are not currently subscribing
already_subscribed = true;
}
break;
@@ -514,19 +609,29 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
if (already_subscribed) {
its_event->set_payload(_payload, _client, _force, _flush);
} else {
- std::shared_ptr<message> its_notification
- = runtime::get()->create_notification();
- its_notification->set_service(_service);
- its_notification->set_instance(_instance);
- its_notification->set_method(_event);
- its_notification->set_payload(_payload);
- auto service_info = find_service(_service, _instance);
- if (service_info) {
- its_notification->set_interface_version(service_info->get_major());
- }
- {
- std::lock_guard<std::mutex> its_lock(pending_notify_ones_mutex_);
- pending_notify_ones_[_service][_instance][valid_group] = its_notification;
+ // cache notification if subscription is in progress
+ if (subscription_state_e::IS_SUBSCRIBING == its_subscription_state) {
+ VSOMEIP_INFO << "routing_manager_base::notify_one("
+ << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << valid_group << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
+ << " insert pending notification!";
+ std::shared_ptr<message> its_notification
+ = runtime::get()->create_notification();
+ its_notification->set_service(_service);
+ its_notification->set_instance(_instance);
+ its_notification->set_method(_event);
+ its_notification->set_payload(_payload);
+ auto service_info = find_service(_service, _instance);
+ if (service_info) {
+ its_notification->set_interface_version(service_info->get_major());
+ }
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(pending_notify_ones_mutex_);
+ pending_notify_ones_[_service][_instance][valid_group] = its_notification;
+ }
}
}
}
@@ -538,16 +643,23 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
}
void routing_manager_base::send_pending_notify_ones(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, client_t _client) {
- std::lock_guard<std::mutex> its_lock(pending_notify_ones_mutex_);
+ eventgroup_t _eventgroup, client_t _client, bool _remote_subscriber) {
+ std::lock_guard<std::recursive_mutex> its_lock(pending_notify_ones_mutex_);
auto its_service = pending_notify_ones_.find(_service);
if (its_service != pending_notify_ones_.end()) {
auto its_instance = its_service->second.find(_instance);
if (its_instance != its_service->second.end()) {
auto its_group = its_instance->second.find(_eventgroup);
if (its_group != its_instance->second.end()) {
+ VSOMEIP_INFO << "routing_manager_base::send_pending_notify_ones("
+ << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_group->second->get_method() << "]";
+
notify_one(_service, _instance, its_group->second->get_method(),
- its_group->second->get_payload(), _client, false, true);
+ its_group->second->get_payload(), _client, false, true, _remote_subscriber);
its_instance->second.erase(_eventgroup);
}
}
@@ -623,18 +735,18 @@ void routing_manager_base::notify_one_current_value(
}
}
-bool routing_manager_base::send(client_t its_client,
+bool routing_manager_base::send(client_t _client,
std::shared_ptr<message> _message,
bool _flush) {
bool is_sent(false);
if (utility::is_request(_message->get_message_type())) {
- _message->set_client(its_client);
+ _message->set_client(_client);
}
std::lock_guard<std::mutex> its_lock(serialize_mutex_);
if (serializer_->serialize(_message.get())) {
- is_sent = send(its_client, serializer_->get_data(),
+ is_sent = send(_client, serializer_->get_data(),
serializer_->get_size(), _message->get_instance(),
- _flush, _message->is_reliable());
+ _flush, _message->is_reliable(), get_client(), true, false);
serializer_->reset();
} else {
VSOMEIP_ERROR << "Failed to serialize message. Check message size!";
@@ -715,6 +827,11 @@ services_t routing_manager_base::get_services() const {
return services_;
}
+services_t routing_manager_base::get_services_remote() const {
+ std::lock_guard<std::mutex> its_lock(services_remote_mutex_);
+ return services_remote_;
+}
+
bool routing_manager_base::is_available(service_t _service, instance_t _instance,
major_version_t _major) {
bool available(false);
@@ -737,6 +854,25 @@ bool routing_manager_base::is_available(service_t _service, instance_t _instance
return available;
}
+std::set<client_t> routing_manager_base::find_local_clients(service_t _service, instance_t _instance) {
+ std::set<client_t> its_clients;
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ auto its_service = local_services_.find(_service);
+ if (its_service != local_services_.end()) {
+ if (_instance == ANY_INSTANCE) {
+ for (auto its_instance : its_service->second) {
+ its_clients.insert(std::get<2>(its_instance.second));
+ }
+ } else {
+ auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ its_clients.insert(std::get<2>(its_instance->second));
+ }
+ }
+ }
+ return its_clients;
+}
+
client_t routing_manager_base::find_local_client(service_t _service, instance_t _instance) {
std::lock_guard<std::mutex> its_lock(local_services_mutex_);
client_t its_client(VSOMEIP_ROUTING_CLIENT);
@@ -814,12 +950,16 @@ std::shared_ptr<endpoint> routing_manager_base::find_or_create_local(client_t _c
return (its_endpoint);
}
-void routing_manager_base::remove_local(client_t _client) {
- remove_local(_client, get_subscriptions(_client));
+void routing_manager_base::remove_local(client_t _client, bool _remove_uid) {
+ remove_local(_client, get_subscriptions(_client), _remove_uid);
}
void routing_manager_base::remove_local(client_t _client,
- const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups) {
+ const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups,
+ bool _remove_uid) {
+ if (_remove_uid) {
+ configuration_->remove_client_to_uid_gid_mapping(_client);
+ }
for (auto its_subscription : _subscribed_eventgroups) {
host_->on_subscription(std::get<0>(its_subscription), std::get<1>(its_subscription),
std::get<2>(its_subscription), _client, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
@@ -854,6 +994,25 @@ void routing_manager_base::remove_local(client_t _client,
if (local_services_[si.first].size() == 0)
local_services_.erase(si.first);
}
+
+ // remove disconnected client from offer service history
+ std::set<std::tuple<service_t, instance_t, client_t>> its_clients;
+ for (auto& s : local_services_history_) {
+ for (auto& i : s.second) {
+ for (auto& c : i.second) {
+ if (c == _client) {
+ its_clients.insert(std::make_tuple(s.first, i.first, c));
+ }
+ }
+ }
+ }
+
+ for (auto& sic : its_clients) {
+ local_services_history_[std::get<0>(sic)][std::get<1>(sic)].erase(std::get<2>(sic));
+ if (local_services_history_[std::get<0>(sic)][std::get<1>(sic)].size() == 0) {
+ local_services_history_.erase(std::get<0>(sic));
+ }
+ }
}
}
@@ -985,7 +1144,7 @@ bool routing_manager_base::send_local_notification(client_t _client,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -1202,4 +1361,71 @@ routing_manager_base::get_local_endpoints() {
return local_endpoints_;
}
+void routing_manager_base::set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event, subscription_state_e _state) {
+ std::lock_guard<std::recursive_mutex> its_lock(incoming_subscription_state_mutex_);
+ incoming_subscription_state_[_client][_service][_instance][_eventgroup][_event] = _state;
+}
+
+subscription_state_e routing_manager_base::get_incoming_subscription_state(client_t _client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event) {
+ std::lock_guard<std::recursive_mutex> its_lock(incoming_subscription_state_mutex_);
+ const auto its_client = incoming_subscription_state_.find(_client);
+ if (its_client != incoming_subscription_state_.end()) {
+ const auto its_service = its_client->second.find(_service);
+ if (its_service != its_client->second.end()) {
+ const auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ const auto its_group = its_instance->second.find(_eventgroup);
+ if (its_group != its_instance->second.end()) {
+ const auto its_event = its_group->second.find(_event);
+ if (its_event != its_group->second.end()) {
+ return its_event->second;
+ }
+ // If a specific event was not found, check if there is a remote subscriber to ANY_EVENT
+ const auto its_any_event = its_group->second.find(ANY_EVENT);
+ if (its_any_event != its_group->second.end()) {
+ return its_any_event->second;
+ }
+ }
+ }
+ }
+ }
+ return subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED;
+}
+
+void routing_manager_base::erase_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event) {
+ std::lock_guard<std::recursive_mutex> its_lock(incoming_subscription_state_mutex_);
+ const auto its_client = incoming_subscription_state_.find(_client);
+ if (its_client != incoming_subscription_state_.end()) {
+ const auto its_service = its_client->second.find(_service);
+ if (its_service != its_client->second.end()) {
+ const auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ const auto its_group = its_instance->second.find(_eventgroup);
+ if (its_group != its_instance->second.end()) {
+ const auto its_event = its_group->second.find(_event);
+ if (its_event != its_group->second.end()) {
+ its_group->second.erase(_event);
+ if (its_group->second.empty()) {
+ its_instance->second.erase(its_group);
+ if (its_instance->second.empty()) {
+ its_service->second.erase(its_instance);
+ if (its_service->second.empty()) {
+ its_client->second.erase(its_service);
+ if (its_client->second.empty()) {
+ incoming_subscription_state_.erase(its_client);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index faf5282..f8dbd14 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -51,6 +51,9 @@
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
#include "../../plugin/include/plugin_manager.hpp"
+#ifdef USE_DLT
+#include "../../tracing/include/connector_impl.hpp"
+#endif
#include "../../e2e_protection/include/buffer/buffer.hpp"
#include "../../e2e_protection/include/e2exf/config.hpp"
@@ -75,7 +78,10 @@ routing_manager_impl::routing_manager_impl(routing_manager_host *_host) :
watchdog_timer_(_host->get_io()),
#endif
status_log_timer_(_host->get_io()),
- memory_log_timer_(_host->get_io())
+ memory_log_timer_(_host->get_io()),
+ pending_remote_offer_id_(0),
+ last_resume_(std::chrono::steady_clock::now().min()),
+ pending_security_update_id_(0)
{
}
@@ -90,6 +96,16 @@ client_t routing_manager_impl::get_client() const {
return routing_manager_base::get_client();
}
+std::set<client_t> routing_manager_impl::find_local_clients(service_t _service, instance_t _instance) {
+ return routing_manager_base::find_local_clients(_service, _instance);
+}
+
+bool routing_manager_impl::is_subscribe_to_any_event_allowed(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+ return routing_manager_base::is_subscribe_to_any_event_allowed(_client,
+ _service, _instance, _eventgroup);
+}
+
void routing_manager_impl::init() {
routing_manager_base::init();
@@ -106,7 +122,7 @@ void routing_manager_impl::init() {
plugin_type_e::SD_RUNTIME_PLUGIN, VSOMEIP_SD_LIBRARY);
if (its_plugin) {
VSOMEIP_INFO << "Service Discovery module loaded.";
- discovery_ = std::dynamic_pointer_cast<sd::runtime>(its_plugin)->create_service_discovery(this);
+ discovery_ = std::dynamic_pointer_cast<sd::runtime>(its_plugin)->create_service_discovery(this, configuration_);
discovery_->init();
} else {
VSOMEIP_ERROR << "Service Discovery module could not be loaded!";
@@ -116,11 +132,11 @@ void routing_manager_impl::init() {
if( configuration_->is_e2e_enabled()) {
VSOMEIP_INFO << "E2E protection enabled.";
- std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> its_e2e_configuration = configuration_->get_e2e_configuration();
+ std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> its_e2e_configuration = configuration_->get_e2e_configuration();
for (auto &identifier : its_e2e_configuration) {
auto its_cfg = identifier.second;
if(its_cfg->profile == "CRC8") {
- e2exf::data_identifier its_data_identifier = {its_cfg->service_id, its_cfg->event_id};
+ e2exf::data_identifier_t its_data_identifier = {its_cfg->service_id, its_cfg->event_id};
e2e::profile01::profile_config its_profile_config = e2e::profile01::profile_config(its_cfg->crc_offset, its_cfg->data_id,
(e2e::profile01::p01_data_id_mode) its_cfg->data_id_mode, its_cfg->data_length, its_cfg->counter_offset, its_cfg->data_id_nibble_offset);
if ((its_cfg->variant == "protector") || (its_cfg->variant == "both")) {
@@ -130,7 +146,7 @@ void routing_manager_impl::init() {
custom_checkers[its_data_identifier] = std::make_shared<e2e::profile01::profile_01_checker>(its_profile_config);
}
} else if(its_cfg->profile == "CRC32") {
- e2exf::data_identifier its_data_identifier = {its_cfg->service_id, its_cfg->event_id};
+ e2exf::data_identifier_t its_data_identifier = {its_cfg->service_id, its_cfg->event_id};
e2e::profile_custom::profile_config its_profile_config = e2e::profile_custom::profile_config(its_cfg->crc_offset);
if ((its_cfg->variant == "protector") || (its_cfg->variant == "both")) {
@@ -237,7 +253,7 @@ void routing_manager_impl::stop() {
for (auto client: get_connected_clients()) {
if (client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(client);
+ remove_local(client, true);
}
}
}
@@ -296,22 +312,35 @@ void routing_manager_impl::stop_offer_service(client_t _client,
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance
<< ":" << std::dec << int(_major) << "." << _minor << "]";
-
+ bool is_local(false);
{
- std::lock_guard<std::mutex> its_lock(pending_sd_offers_mutex_);
- for (auto it = pending_sd_offers_.begin(); it != pending_sd_offers_.end(); ) {
- if (it->first == _service && it->second == _instance) {
- it = pending_sd_offers_.erase(it);
- break;
- } else {
- ++it;
+ std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
+ is_local = (its_info && its_info->is_local());
+ }
+ if (is_local) {
+ {
+ std::lock_guard<std::mutex> its_lock(pending_sd_offers_mutex_);
+ for (auto it = pending_sd_offers_.begin(); it != pending_sd_offers_.end(); ) {
+ if (it->first == _service && it->second == _instance) {
+ it = pending_sd_offers_.erase(it);
+ break;
+ } else {
+ ++it;
+ }
}
}
- }
- on_stop_offer_service(_client, _service, _instance, _major, _minor);
- stub_->on_stop_offer_service(_client, _service, _instance, _major, _minor);
- on_availability(_service, _instance, false, _major, _minor);
+ on_stop_offer_service(_client, _service, _instance, _major, _minor);
+ stub_->on_stop_offer_service(_client, _service, _instance, _major, _minor);
+ on_availability(_service, _instance, false, _major, _minor);
+ } else {
+ VSOMEIP_WARNING << __func__ << " received STOP_OFFER("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance
+ << ":" << std::dec << int(_major) << "." << _minor << "] "
+ << "for remote service --> ignore";
+ }
}
void routing_manager_impl::request_service(client_t _client, service_t _service,
@@ -435,6 +464,8 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
<< std::dec << (uint16_t)_major << "]";
const client_t its_local_client = find_local_client(_service, _instance);
if (get_client() == its_local_client) {
+ routing_manager_base::set_incoming_subscription_state(_client, _service, _instance,
+ _eventgroup, _event, subscription_state_e::IS_SUBSCRIBING);
auto self = shared_from_this();
host_->on_subscription(_service, _instance, _eventgroup, _client, true,
[this, self, _client, _service, _instance, _eventgroup,
@@ -452,6 +483,8 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
}
routing_manager_base::subscribe(_client, _service, _instance, _eventgroup, _major, _event, _subscription_type);
send_pending_notify_ones(_service, _instance, _eventgroup, _client);
+ routing_manager_base::erase_incoming_subscription_state(_client, _service, _instance,
+ _eventgroup, _event);
});
} else {
if (discovery_) {
@@ -581,8 +614,8 @@ bool routing_manager_impl::send(client_t _client,
}
bool routing_manager_impl::send(client_t _client, const byte_t *_data,
- length_t _size, instance_t _instance,
- bool _flush, bool _reliable, bool _is_valid_crc) {
+ length_t _size, instance_t _instance, bool _flush, bool _reliable,
+ client_t _bound_client, bool _is_valid_crc, bool _sent_from_remote) {
bool is_sent(false);
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
std::shared_ptr<endpoint> its_target;
@@ -616,12 +649,12 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- deliver_message(_data, _size, _instance, _reliable, _is_valid_crc);
+ deliver_message(_data, _size, _instance, _reliable, _bound_client, _is_valid_crc, _sent_from_remote);
return true;
}
its_target = find_local(_client);
@@ -634,7 +667,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -648,7 +681,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
|| (find_local_client(its_service, _instance)
== host_->get_client() && is_request)) {
// TODO: find out how to handle session id here
- is_sent = deliver_message(_data, _size, _instance, _reliable, _is_valid_crc);
+ is_sent = deliver_message(_data, _size, _instance, _reliable, _bound_client, _is_valid_crc, _sent_from_remote);
} else {
e2e_buffer outputBuffer;
if( configuration_->is_e2e_enabled()) {
@@ -675,7 +708,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -754,7 +787,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -786,7 +819,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -869,7 +902,7 @@ bool routing_manager_impl::send_to(
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(its_endpoint, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -892,7 +925,7 @@ bool routing_manager_impl::send_to(
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(its_endpoint, true, 0x0))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -911,8 +944,10 @@ void routing_manager_impl::register_event(
bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) {
auto its_event = find_event(_service, _instance, _event);
bool is_first(false);
- if (its_event && !its_event->has_ref(_client, _is_provided)) {
- is_first = true;
+ if (its_event) {
+ if (!its_event->has_ref(_client, _is_provided)) {
+ is_first = true;
+ }
} else {
is_first = true;
}
@@ -950,10 +985,10 @@ void routing_manager_impl::unregister_shadow_event(client_t _client,
void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, client_t _client,
- bool _force, bool _flush) {
+ bool _force, bool _flush, bool _remote_subscriber) {
if (find_local(_client)) {
routing_manager_base::notify_one(_service, _instance, _event, _payload,
- _client, _force, _flush);
+ _client, _force, _flush, _remote_subscriber);
} else {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
@@ -1034,6 +1069,113 @@ void routing_manager_impl::release_port(uint16_t _port, bool _reliable) {
used_client_ports_[_reliable].erase(_port);
}
+bool routing_manager_impl::offer_service_remotely(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled) {
+ bool ret = true;
+
+ if(!is_available(_service, _instance, ANY_MAJOR)) {
+ VSOMEIP_ERROR << __func__ << ": Service ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance
+ << "] is not offered locally! Won't offer it remotely.";
+ ret = false;
+ } else {
+ // update service info in configuration
+ if (!configuration_->remote_offer_info_add(_service, _instance, _port,
+ _reliable, _magic_cookies_enabled)) {
+ ret = false;
+ } else {
+ // trigger event registration again to create shadow events
+ const client_t its_offering_client = find_local_client(_service, _instance);
+ if (its_offering_client == VSOMEIP_ROUTING_CLIENT) {
+ VSOMEIP_ERROR << __func__ << " didn't find offering client for service ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance
+ << "]";
+ ret = false;
+ } else {
+ if (!stub_->send_provided_event_resend_request(its_offering_client,
+ pending_remote_offer_add(_service, _instance))) {
+ VSOMEIP_ERROR << __func__ << ": Couldn't send event resend"
+ << "request to client 0x" << std::hex << std::setw(4)
+ << std::setfill('0') << its_offering_client << " providing service ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance
+ << "]";
+
+ ret = false;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+bool routing_manager_impl::stop_offer_service_remotely(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled) {
+ bool ret = true;
+ bool service_still_offered_remote(false);
+ // update service configuration
+ if (!configuration_->remote_offer_info_remove(_service, _instance, _port,
+ _reliable, _magic_cookies_enabled, &service_still_offered_remote)) {
+ VSOMEIP_ERROR << __func__ << " couldn't remove remote offer info for service ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance
+ << "] from configuration";
+ ret = false;
+ }
+ std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
+ std::shared_ptr<endpoint> its_server_endpoint;
+ if (its_info) {
+ its_server_endpoint = its_info->get_endpoint(_reliable);
+ }
+ // don't deregister events if the service is still offered remotely
+ if (!service_still_offered_remote) {
+ const client_t its_offering_client = find_local_client(_service, _instance);
+ major_version_t its_major(0);
+ minor_version_t its_minor(0);
+ if (its_info) {
+ its_major = its_info->get_major();
+ its_minor = its_info->get_minor();
+ }
+ // unset payload and clear subcribers
+ routing_manager_base::stop_offer_service(its_offering_client,
+ _service, _instance, its_major, its_minor);
+ // unregister events
+ for (const event_t its_event_id : find_events(_service, _instance)) {
+ unregister_shadow_event(its_offering_client, _service, _instance,
+ its_event_id, true);
+ }
+ clear_targets_and_pending_sub_from_eventgroups(_service, _instance);
+ clear_remote_subscriber(_service, _instance);
+
+ if (discovery_ && its_info) {
+ discovery_->stop_offer_service(_service, _instance, its_info);
+ its_info->set_endpoint(std::shared_ptr<endpoint>(), _reliable);
+ }
+ } else {
+ // service is still partly offered
+ if (discovery_ && its_info) {
+ std::shared_ptr<serviceinfo> its_copied_info =
+ std::make_shared<serviceinfo>(*its_info);
+ its_info->set_endpoint(std::shared_ptr<endpoint>(), _reliable);
+ // ensure to not send StopOffer for endpoint on which the service is
+ // still offered
+ its_copied_info->set_endpoint(std::shared_ptr<endpoint>(), !_reliable);
+ discovery_->stop_offer_service(_service, _instance, its_copied_info);
+ }
+ }
+
+ cleanup_server_endpoint(_service, its_server_endpoint);
+ return ret;
+}
+
void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
endpoint *_receiver, const boost::asio::ip::address &_destination,
client_t _bound_client,
@@ -1119,6 +1261,9 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
client_t requester = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_CLIENT_POS_MIN],
_data[VSOMEIP_CLIENT_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
if (!configuration_->is_offered_remote(its_service, its_instance)) {
VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
<< "for service/instance " << its_service << "/" << its_instance
@@ -1131,11 +1276,13 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
<< " which is already used locally ~> Skip message!";
return;
}
- if (!configuration_->is_client_allowed(requester, its_service, its_instance)) {
- VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
- << "from client 0x" << requester << " for service/instance "
+ if (!configuration_->is_remote_client_allowed()) {
+ // check if policy allows remote requests.
+ VSOMEIP_WARNING << "routing_manager_impl::on_message: "
+ << std::hex << "Security: Remote client with client ID 0x" << requester
+ << " is not allowed to communicate with service/instance/method "
<< its_service << "/" << its_instance
- << " which violates the security policy ~> Skip message!";
+ << "/" << its_method;
return;
}
}
@@ -1167,7 +1314,8 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
#ifdef USE_DLT
is_forwarded =
#endif
- on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(), its_is_crc_valid);
+ on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(),
+ _bound_client, its_is_crc_valid, true);
}
}
@@ -1177,14 +1325,14 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
const boost::asio::ip::address_v4 its_remote_address =
_remote_address.is_v4() ? _remote_address.to_v4() :
boost::asio::ip::address_v4::from_string("6.6.6.6");
- tc::protocol_e its_protocol =
- _receiver->is_local() ? tc::protocol_e::local :
- _receiver->is_reliable() ? tc::protocol_e::tcp :
- tc::protocol_e::udp;
+ trace::protocol_e its_protocol =
+ _receiver->is_local() ? trace::protocol_e::local :
+ _receiver->is_reliable() ? trace::protocol_e::tcp :
+ trace::protocol_e::udp;
its_header.prepare(its_remote_address, _remote_port, its_protocol, false,
its_instance);
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data,
@@ -1196,7 +1344,9 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
bool routing_manager_impl::on_message(
service_t _service, instance_t _instance,
const byte_t *_data, length_t _size,
- bool _reliable, bool _is_valid_crc) {
+ bool _reliable, client_t _bound_client,
+ bool _is_valid_crc,
+ bool _is_from_remote) {
#if 0
std::stringstream msg;
msg << "rmi::on_message("
@@ -1219,11 +1369,13 @@ bool routing_manager_impl::on_message(
if (its_client == VSOMEIP_ROUTING_CLIENT
&& utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- is_forwarded = deliver_notification(_service, _instance, _data, _size, _reliable, _is_valid_crc);
+ is_forwarded = deliver_notification(_service, _instance, _data, _size,
+ _reliable, _bound_client, _is_valid_crc, _is_from_remote);
} else if (its_client == host_->get_client()) {
- deliver_message(_data, _size, _instance, _reliable, _is_valid_crc);
+ deliver_message(_data, _size, _instance,
+ _reliable, _bound_client, _is_valid_crc, _is_from_remote);
} else {
- send(its_client, _data, _size, _instance, true, _reliable, _is_valid_crc); //send to proxy
+ send(its_client, _data, _size, _instance, true, _reliable, _bound_client, _is_valid_crc, _is_from_remote); //send to proxy
}
return is_forwarded;
}
@@ -1244,7 +1396,7 @@ void routing_manager_impl::on_notification(client_t _client,
its_length);
if (_notify_one) {
- notify_one(_service, _instance, its_event->get_event(), its_payload, _client, true, true);
+ notify_one(_service, _instance, its_event->get_event(), its_payload, _client, true, true, false);
} else {
if (its_event->is_field()) {
if (its_event->is_set()) {
@@ -1311,6 +1463,13 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
bool reliable_;
std::shared_ptr<endpoint> endpoint_;
};
+
+ // Set to state CONNECTED as connection is not yet fully established in remote side POV
+ // but endpoint is ready to send / receive. Set to ESTABLISHED after timer expires
+ // to prevent inserting subscriptions twice or send out subscription before remote side
+ // is finished with TCP 3 way handshake
+ _endpoint->set_connected(true);
+
std::forward_list<struct service_info> services_to_report_;
{
std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
@@ -1324,7 +1483,7 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
if (found_endpoint->second.get() == _endpoint.get()) {
std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first));
if (!its_info) {
- _endpoint->set_connected(true);
+ _endpoint->set_established(true);
return;
}
services_to_report_.push_front(
@@ -1340,7 +1499,7 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
if (found_endpoint->second.get() == _endpoint.get()) {
std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first));
if (!its_info) {
- _endpoint->set_connected(true);
+ _endpoint->set_established(true);
return;
}
services_to_report_.push_front(
@@ -1356,6 +1515,7 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
}
}
}
+
for (const auto &s : services_to_report_) {
on_availability(s.service_id_, s.instance_id_, true, s.major_, s.minor_);
if (s.reliable_) {
@@ -1379,7 +1539,7 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
}
}
if (services_to_report_.empty()) {
- _endpoint->set_connected(true);
+ _endpoint->set_established(true);
}
}
@@ -1488,7 +1648,6 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
if (discovery_) {
if (its_info) {
if (its_info->get_major() == _major && its_info->get_minor() == _minor) {
- its_info->set_ttl(0);
discovery_->stop_offer_service(_service, _instance, its_info);
}
}
@@ -1498,59 +1657,21 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
// Cleanup reliable & unreliable server endpoints hold before
if (its_info) {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- std::shared_ptr<endpoint> its_empty_endpoint;
- bool reliable = true;
-
- // Loop over reliable/unreliable and cleanup if needed
- for (uint8_t i = 0; i < 2; ++i) {
- std::shared_ptr<endpoint> its_endpoint;
- if (reliable) {
- its_endpoint = its_reliable_endpoint;
- } else {
- its_endpoint = its_unreliable_endpoint;
- }
- if (!its_endpoint) {
- reliable = !reliable;
- continue;
- }
-
- // Check whether any service still uses this endpoint
- its_endpoint->decrement_use_count();
- bool isLastService = (its_endpoint->get_use_count() == 0);
-
- // Clear service_instances_
- if (1 >= service_instances_[_service].size()) {
- service_instances_.erase(_service);
- } else {
- service_instances_[_service].erase(its_endpoint.get());
- }
-
- // Clear server endpoint if no service remains using it
- if (isLastService) {
- uint16_t port = its_endpoint->get_local_port();
- if (server_endpoints_.find(port) != server_endpoints_.end()) {
- server_endpoints_[port].erase(reliable);
- if (server_endpoints_[port].find(!reliable) == server_endpoints_[port].end()) {
- server_endpoints_.erase(port);
- }
- }
-
- // Stop endpoint (close socket) to release its async_handlers!
- its_endpoint->stop();
- }
-
+ if (its_unreliable_endpoint) {
+ cleanup_server_endpoint(_service, its_unreliable_endpoint);
// Clear service info and service group
- clear_service_info(_service, _instance, reliable);
-
- // Invert reliable flag and loop again
- reliable = !reliable;
+ clear_service_info(_service, _instance, false);
+ }
+ if (its_reliable_endpoint) {
+ cleanup_server_endpoint(_service, its_reliable_endpoint);
+ // Clear service info and service group
+ clear_service_info(_service, _instance, true);
}
}
}
bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
- instance_t _instance, bool _reliable, bool _is_valid_crc) {
+ instance_t _instance, bool _reliable, client_t _bound_client, bool _is_valid_crc, bool _is_from_remote) {
bool is_delivered(false);
auto a_deserializer = get_deserializer();
@@ -1563,6 +1684,109 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
its_message->set_instance(_instance);
its_message->set_reliable(_reliable);
its_message->set_is_valid_crc(_is_valid_crc);
+
+ if (!_is_from_remote) {
+ if (utility::is_notification(its_message->get_message_type())) {
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message: "
+ << std::hex << " received a notification from client 0x" << _bound_client
+ << " which does not offer service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return false;
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return false;
+ }
+ }
+ } else if (utility::is_request(its_message->get_message_type())) {
+ if (configuration_->is_security_enabled()
+ && its_message->get_client() != _bound_client) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message:"
+ << " received a request from client 0x" << std::setw(4) << std::setfill('0')
+ << its_message->get_client() << " to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method() << " which doesn't match the bound client 0x"
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return false;
+ }
+
+ if (!configuration_->is_client_allowed(its_message->get_client(),
+ its_message->get_service(), its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message: "
+ << " isn't allowed to send a request to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return false;
+ }
+ } else { // response
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message: "
+ << " received a response from client 0x" << _bound_client
+ << " which does not offer service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return false;
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message: "
+ << " isn't allowed to receive a response from service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return false;
+ }
+ }
+ }
+ } else {
+ if (!configuration_->is_remote_client_allowed()) {
+ // if the message is from remote, check if
+ // policy allows remote requests.
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message: "
+ << std::hex << "Remote clients are not allowed"
+ << " to communicate with service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively with client 0x" << get_client()
+ << " ~> Skip message!";
+ return false;
+ } else if (utility::is_notification(its_message->get_message_type())) {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_impl::deliver_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from remote client"
+ << " ~> Skip message!";
+ return false;
+ }
+ }
+ }
+
host_->on_message(std::move(its_message));
is_delivered = true;
} else {
@@ -1575,7 +1799,8 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
bool routing_manager_impl::deliver_notification(
service_t _service, instance_t _instance,
const byte_t *_data, length_t _length,
- bool _reliable, bool _is_valid_crc) {
+ bool _reliable, client_t _bound_client,
+ bool _is_valid_crc, bool _is_from_remote) {
method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
_data[VSOMEIP_METHOD_POS_MAX]);
@@ -1605,6 +1830,10 @@ bool routing_manager_impl::deliver_notification(
}
}
const uint32_t its_length(utility::get_payload_size(_data, _length));
+ if (its_length != _length - VSOMEIP_FULL_HEADER_SIZE) {
+ VSOMEIP_ERROR << "Message length mismatch, dropping message!";
+ return false;
+ }
std::shared_ptr<payload> its_payload
= runtime::get()->create_payload(&_data[VSOMEIP_PAYLOAD_POS],
its_length);
@@ -1616,7 +1845,7 @@ bool routing_manager_impl::deliver_notification(
for (const auto its_local_client : its_event->get_subscribers()) {
if (its_local_client == host_->get_client()) {
- deliver_message(_data, _length, _instance, _reliable, _is_valid_crc);
+ deliver_message(_data, _length, _instance, _reliable, _bound_client, _is_valid_crc, _is_from_remote);
} else {
std::shared_ptr<endpoint> its_local_target = find_local(its_local_client);
if (its_local_target) {
@@ -1809,9 +2038,12 @@ std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint(
configuration_->get_max_message_size_reliable(
_address.to_string(), _remote_port),
configuration_->get_buffer_shrink_threshold(),
+ // send timeout after 2/3 of configured ttl, warning after 1/3
std::chrono::milliseconds(configuration_->get_sd_ttl() * 666),
configuration_->get_endpoint_queue_limit(
- _address.to_string(), _remote_port));
+ _address.to_string(), _remote_port),
+ configuration_->get_max_tcp_restart_aborts(),
+ configuration_->get_max_tcp_connect_time());
if (configuration_->has_enabled_magic_cookies(_address.to_string(),
_remote_port)) {
@@ -1827,7 +2059,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint(
_local_port),
boost::asio::ip::udp::endpoint(_address, _remote_port),
io_, configuration_->get_endpoint_queue_limit(
- _address.to_string(), _remote_port));
+ _address.to_string(), _remote_port),
+ configuration_->get_udp_receive_buffer_size());
}
} catch (...) {
host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED);
@@ -1850,6 +2083,7 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint(
configuration_->get_max_message_size_reliable(
its_unicast.to_string(), _port),
configuration_->get_buffer_shrink_threshold(),
+ // send timeout after 2/3 of configured ttl, warning after 1/3
std::chrono::milliseconds(configuration_->get_sd_ttl() * 666),
configuration_->get_endpoint_queue_limit(
its_unicast.to_string(), _port));
@@ -1872,7 +2106,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint(
#endif
boost::asio::ip::udp::endpoint ep(its_unicast, _port);
its_endpoint = std::make_shared<udp_server_endpoint_impl>(
- shared_from_this(), ep, io_, its_limit);
+ shared_from_this(), ep, io_, its_limit,
+ configuration_->get_udp_receive_buffer_size());
}
} else {
@@ -1917,7 +2152,7 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint(
return (its_endpoint);
}
-void routing_manager_impl::remove_local(client_t _client) {
+void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) {
auto clients_subscriptions = get_subscriptions(_client);
{
std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
@@ -1925,7 +2160,7 @@ void routing_manager_impl::remove_local(client_t _client) {
remote_subscription_state_.erase(std::tuple_cat(s, std::make_tuple(_client)));
}
}
- routing_manager_base::remove_local(_client, clients_subscriptions);
+ routing_manager_base::remove_local(_client, clients_subscriptions, _remove_uid);
std::forward_list<std::pair<service_t, instance_t>> services_to_release_;
{
@@ -2300,7 +2535,7 @@ void routing_manager_impl::add_routing_info(
its_info->get_minor());
if (discovery_) {
std::shared_ptr<endpoint> ep = its_info->get_endpoint(true);
- if (ep && ep->is_connected()) {
+ if (ep && ep->is_established()) {
discovery_->on_endpoint_connected(
_service, _instance,
ep);
@@ -2361,7 +2596,7 @@ void routing_manager_impl::add_routing_info(
}
if (discovery_) {
std::shared_ptr<endpoint> ep = its_info->get_endpoint(false);
- if (ep && ep->is_connected()) {
+ if (ep && ep->is_established()) {
discovery_->on_endpoint_connected(_service, _instance, ep);
}
}
@@ -2391,7 +2626,7 @@ void routing_manager_impl::add_routing_info(
its_info->get_minor());
if (discovery_) {
std::shared_ptr<endpoint> ep = its_info->get_endpoint(false);
- if (ep && ep->is_connected()) {
+ if (ep && ep->is_established()) {
discovery_->on_endpoint_connected(
_service, _instance,
ep);
@@ -2417,33 +2652,12 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst
on_availability(_service, _instance, false, its_info->get_major(), its_info->get_minor());
stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, its_info->get_major(), its_info->get_minor());
// Implicit unsubscribe
- {
- std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
- auto found_service = eventgroups_.find(_service);
- if (found_service != eventgroups_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- for (auto &its_eventgroup : found_instance->second) {
- its_eventgroup.second->clear_targets();
- its_eventgroup.second->clear_pending_subscriptions();
- }
- }
- }
- }
+ clear_targets_and_pending_sub_from_eventgroups(_service, _instance);
clear_identified_clients( _service, _instance);
clear_identifying_clients( _service, _instance);
- {
- std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
- auto found_service = remote_subscribers_.find(_service);
- if (found_service != remote_subscribers_.end()) {
- if (found_service->second.erase(_instance) > 0 &&
- !found_service->second.size()) {
- remote_subscribers_.erase(found_service);
- }
- }
- }
+ clear_remote_subscriber(_service, _instance);
if (_has_reliable) {
clear_client_endpoints(_service, _instance, true);
@@ -2509,11 +2723,8 @@ void routing_manager_impl::update_routing_info(std::chrono::milliseconds _elapse
void routing_manager_impl::expire_services(const boost::asio::ip::address &_address) {
std::map<service_t, std::vector<instance_t> > its_expired_offers;
- for (auto &s : get_services()) {
+ for (auto &s : get_services_remote()) {
for (auto &i : s.second) {
- if (find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
- continue; //don't expire local services
- }
bool is_gone(false);
boost::asio::ip::address its_address;
std::shared_ptr<client_endpoint> its_client_endpoint =
@@ -2919,7 +3130,14 @@ void routing_manager_impl::on_subscribe_ack(client_t _client,
if (specific_endpoint_client) {
if (_client == get_client()) {
host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
- host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
+ if (_event == ANY_EVENT) {
+ for (const auto &its_event : its_eventgroup->get_events())
+ host_->on_subscription_status(_service, _instance,
+ _eventgroup, its_event->get_event(), 0x0 /*OK*/);
+ } else {
+ host_->on_subscription_status(_service, _instance,
+ _eventgroup, _event, 0x0 /*OK*/);
+ }
} else {
stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup,
_event);
@@ -3068,7 +3286,7 @@ bool routing_manager_impl::deliver_specific_endpoint_message(service_t _service,
_receiver->is_reliable(), VSOMEIP_SEND);
}
} else {
- deliver_message(_data, _size, _instance, _receiver->is_reliable());
+ deliver_message(_data, _size, _instance, _receiver->is_reliable(), VSOMEIP_ROUTING_CLIENT, true, true);
}
return true;
}
@@ -3484,7 +3702,7 @@ void routing_manager_impl::clear_remote_subscriber(
}
std::chrono::steady_clock::time_point
-routing_manager_impl::expire_subscriptions() {
+routing_manager_impl::expire_subscriptions(bool _force) {
struct subscriptions_info {
service_t service_id_;
instance_t instance_id_;
@@ -3507,10 +3725,14 @@ routing_manager_impl::expire_subscriptions() {
for (auto &its_eventgroup : its_instance.second) {
std::set<std::shared_ptr<endpoint_definition>> its_expired_endpoints;
for (auto &its_target : its_eventgroup.second->get_targets()) {
- if (its_target.expiration_ < now) {
+ if (_force) {
its_expired_endpoints.insert(its_target.endpoint_);
- } else if (its_target.expiration_ < next_expiration) {
- next_expiration = its_target.expiration_;
+ } else {
+ if (its_target.expiration_ < now) {
+ its_expired_endpoints.insert(its_target.endpoint_);
+ } else if (its_target.expiration_ < next_expiration) {
+ next_expiration = its_target.expiration_;
+ }
}
}
@@ -3576,7 +3798,8 @@ routing_manager_impl::expire_subscriptions() {
<< std::hex << std::setfill('0') << std::setw(4) << s.eventgroup_id_ << "] from "
<< s.invalid_endpoint_->get_address() << ":"
<< std::dec << s.invalid_endpoint_->get_port()
- << "(" << std::hex << std::setfill('0') << std::setw(4) << s.client_ << ")";
+ << "(" << std::hex << std::setfill('0') << std::setw(4) << s.client_ << ") "
+ << _force;
}
}
return next_expiration;
@@ -3593,8 +3816,18 @@ void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const
if (discovery_) {
is_diag_mode = discovery_->get_diagnosis_mode();
}
+ std::stringstream its_last_resume;
+ {
+ std::lock_guard<std::mutex> its_lock(last_resume_mutex_);
+ if (last_resume_ != std::chrono::steady_clock::time_point::min()) {
+ its_last_resume << " | " << std::dec
+ << std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::steady_clock::now() - last_resume_).count() << "s";
+ }
+ }
VSOMEIP_INFO << "vSomeIP " << VSOMEIP_VERSION << " | ("
- << ((is_diag_mode == true) ? "diagnosis)" : "default)");
+ << ((is_diag_mode == true) ? "diagnosis)" : "default)")
+ << its_last_resume.str();
{
std::lock_guard<std::mutex> its_lock(version_log_timer_mutex_);
version_log_timer_.expires_from_now(
@@ -3838,6 +4071,8 @@ void routing_manager_impl::register_client_error_handler(client_t _client,
}
void routing_manager_impl::handle_client_error(client_t _client) {
+ VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
+ << " handles a client error(" << std::hex << _client << ")";
if (stub_)
stub_->update_registration(_client, registration_type_e::DEREGISTER_ON_ERROR);
@@ -4023,14 +4258,26 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
// stop processing of incoming SD messages
discovery_->stop();
+ // remove all remote subscriptions to remotely offered services on this node
+ expire_subscriptions(true);
+
// send StopOffer messages for remotely offered services on this node
for (const auto &its_service : get_offered_services()) {
for (const auto &its_instance : its_service.second) {
- its_instance.second->set_ttl(0);
+ if (its_instance.second->get_endpoint(true) || its_instance.second->get_endpoint(false)) {
+ const client_t its_client(find_local_client(its_service.first, its_instance.first));
+ VSOMEIP_WARNING << "service "
+ << std::hex << std::setw(4) << std::setfill('0') << its_service.first << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance.first << " still offered by "
+ << std::hex << std::setw(4) << std::setfill('0') << its_client;
+ }
discovery_->stop_offer_service(its_service.first, its_instance.first, its_instance.second);
}
}
-
+ {
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ remote_subscription_state_.clear();
+ }
// mark all external services as offline
services_t its_remote_services;
{
@@ -4065,6 +4312,10 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
{
VSOMEIP_INFO << "Set routing to resume mode, diagnosis mode was "
<< ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
+ {
+ std::lock_guard<std::mutex> its_lock(last_resume_mutex_);
+ last_resume_ = std::chrono::steady_clock::now();
+ }
// Reset relevant in service info
for (const auto &its_service : get_offered_services()) {
@@ -4076,6 +4327,10 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
// Switch SD back to normal operation
discovery_->set_diagnosis_mode(false);
+ if (routing_state_handler_) {
+ routing_state_handler_(_routing_state);
+ }
+
// start processing of SD messages (incoming remote offers should lead to new subscribe messages)
discovery_->start();
@@ -4098,7 +4353,6 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
for (const auto &its_instance : its_service.second) {
if (host_->get_configuration()->is_someip(
its_service.first, its_instance.first)) {
- its_instance.second->set_ttl(0);
discovery_->stop_offer_service(
its_service.first, its_instance.first, its_instance.second);
}
@@ -4192,6 +4446,9 @@ void routing_manager_impl::on_net_interface_or_route_state_changed(
}
void routing_manager_impl::start_ip_routing() {
+ if (routing_ready_handler_) {
+ routing_ready_handler_();
+ }
if (discovery_) {
discovery_->start();
} else {
@@ -4262,6 +4519,62 @@ routing_manager_impl::get_subscribed_eventgroups(
return its_eventgroups;
}
+void routing_manager_impl::clear_targets_and_pending_sub_from_eventgroups(
+ service_t _service, instance_t _instance) {
+ std::vector<std::shared_ptr<event>> its_events;
+ {
+ std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
+ auto found_service = eventgroups_.find(_service);
+ if (found_service != eventgroups_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (const auto &its_eventgroup : found_instance->second) {
+ // As the service is gone, all subscriptions to its events
+ // do no longer exist and the last received payload is no
+ // longer valid.
+ for (auto &its_event : its_eventgroup.second->get_events()) {
+ const auto its_subscribers = its_event->get_subscribers();
+ for (const auto its_subscriber : its_subscribers) {
+ if (its_subscriber != get_client()) {
+ its_event->remove_subscriber(
+ its_eventgroup.first, its_subscriber);
+ }
+
+ client_t its_client = is_specific_endpoint_client(its_subscriber, _service, _instance);
+ {
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ const auto its_tuple =
+ std::make_tuple(found_service->first, found_instance->first,
+ its_eventgroup.first, its_client);
+ remote_subscription_state_.erase(its_tuple);
+ }
+ }
+ its_events.push_back(its_event);
+ }
+ its_eventgroup.second->clear_targets();
+ its_eventgroup.second->clear_pending_subscriptions();
+ }
+ }
+ }
+ }
+ for (const auto& e : its_events) {
+ e->unset_payload(true);
+ }
+}
+
+void routing_manager_impl::clear_remote_subscriber(service_t _service,
+ instance_t _instance) {
+ std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
+ auto found_service = remote_subscribers_.find(_service);
+ if (found_service != remote_subscribers_.end()) {
+ if (found_service->second.erase(_instance) > 0 &&
+ !found_service->second.size()) {
+ remote_subscribers_.erase(found_service);
+ }
+ }
+}
+
+
void routing_manager_impl::call_sd_endpoint_connected(
const boost::system::error_code& _error,
service_t _service, instance_t _instance,
@@ -4271,7 +4584,7 @@ void routing_manager_impl::call_sd_endpoint_connected(
if (_error) {
return;
}
- _endpoint->set_connected(true);
+ _endpoint->set_established(true);
if (discovery_) {
discovery_->on_endpoint_connected(_service, _instance,
_endpoint);
@@ -4423,6 +4736,39 @@ void routing_manager_impl::send_initial_events(
}
}
+void routing_manager_impl::register_offer_acceptance_handler(
+ vsomeip::offer_acceptance_handler_t _handler) const {
+ if (discovery_) {
+ discovery_->register_offer_acceptance_handler(_handler);
+ }
+}
+
+void routing_manager_impl::register_reboot_notification_handler(
+ vsomeip::reboot_notification_handler_t _handler) const {
+ if (discovery_) {
+ discovery_->register_reboot_notification_handler(_handler);
+ }
+}
+
+void routing_manager_impl::register_routing_ready_handler(
+ routing_ready_handler_t _handler) {
+ routing_ready_handler_ = _handler;
+}
+
+void routing_manager_impl::register_routing_state_handler(
+ routing_state_handler_t _handler) {
+ routing_state_handler_ = _handler;
+}
+
+void routing_manager_impl::offer_acceptance_enabled(
+ boost::asio::ip::address _address) {
+ boost::system::error_code ec;
+ VSOMEIP_INFO << "ipsec-plugin-mgu: expire subscriptions and services: "
+ << _address.to_string(ec);
+ expire_subscriptions(_address);
+ expire_services(_address);
+}
+
void routing_manager_impl::memory_log_timer_cbk(
boost::system::error_code const & _error) {
if (_error) {
@@ -4707,4 +5053,374 @@ void routing_manager_impl::send_subscription(
}
}
+void routing_manager_impl::cleanup_server_endpoint(
+ service_t _service, const std::shared_ptr<endpoint>& _endpoint) {
+ if (_endpoint) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ bool reliable = _endpoint->is_reliable();
+ // Check whether any service still uses this endpoint
+ _endpoint->decrement_use_count();
+ bool isLastService = (_endpoint->get_use_count() == 0);
+
+ // Clear service_instances_
+ if (1 >= service_instances_[_service].size()) {
+ service_instances_.erase(_service);
+ } else {
+ service_instances_[_service].erase(_endpoint.get());
+ }
+
+ // Clear server endpoint if no service remains using it
+ if (isLastService) {
+ const uint16_t port = _endpoint->get_local_port();
+ if (server_endpoints_.find(port) != server_endpoints_.end()) {
+ server_endpoints_[port].erase(reliable);
+ if (server_endpoints_[port].find(!reliable) == server_endpoints_[port].end()) {
+ server_endpoints_.erase(port);
+ }
+ }
+
+ // Stop endpoint (close socket) to release its async_handlers!
+ _endpoint->stop();
+ }
+ }
+}
+
+pending_remote_offer_id_t routing_manager_impl::pending_remote_offer_add(
+ service_t _service, instance_t _instance) {
+ std::lock_guard<std::mutex> its_lock(pending_remote_offers_mutex_);
+ if (++pending_remote_offer_id_ == 0) {
+ pending_remote_offer_id_++;
+ }
+ pending_remote_offers_[pending_remote_offer_id_] = std::make_pair(_service,
+ _instance);
+ return pending_remote_offer_id_;
+}
+
+std::pair<service_t, instance_t> routing_manager_impl::pending_remote_offer_remove(
+ pending_remote_offer_id_t _id) {
+ std::lock_guard<std::mutex> its_lock(pending_remote_offers_mutex_);
+ std::pair<service_t, instance_t> ret = std::make_pair(ANY_SERVICE,
+ ANY_INSTANCE);
+ auto found_si = pending_remote_offers_.find(_id);
+ if (found_si != pending_remote_offers_.end()) {
+ ret = found_si->second;
+ pending_remote_offers_.erase(found_si);
+ }
+ return ret;
+}
+
+void routing_manager_impl::on_resend_provided_events_response(
+ pending_remote_offer_id_t _id) {
+ const std::pair<service_t, instance_t> its_service =
+ pending_remote_offer_remove(_id);
+ if (its_service.first != ANY_SERVICE) {
+ // create server endpoint
+ std::shared_ptr<serviceinfo> its_info = find_service(its_service.first,
+ its_service.second);
+ if (its_info) {
+ its_info->set_ttl(DEFAULT_TTL);
+ init_service_info(its_service.first, its_service.second, true);
+ }
+ }
+}
+
+void routing_manager_impl::on_security_update_timeout(
+ const boost::system::error_code& _error,
+ pending_security_update_id_t _id,
+ std::shared_ptr<boost::asio::steady_timer> _timer) {
+ (void)_timer;
+ if (_error) {
+ // timer was cancelled
+ return;
+ }
+ security_update_state_e its_state = security_update_state_e::SU_UNKNOWN_USER_ID;
+ std::unordered_set<client_t> its_missing_clients = pending_security_update_get(_id);
+ {
+ // erase timer
+ std::lock_guard<std::mutex> its_lock(security_update_timers_mutex_);
+ security_update_timers_.erase(_id);
+ }
+ {
+ // print missing responses and check if some clients did not respond because they already disconnected
+ if (!its_missing_clients.empty()) {
+ for (auto its_client : its_missing_clients) {
+ VSOMEIP_INFO << __func__ << ": Client 0x" << std::hex << its_client
+ << " did not respond to the policy update / removal with ID: 0x" << std::hex << _id;
+ if (!find_local(its_client)) {
+ VSOMEIP_INFO << __func__ << ": Client 0x" << std::hex << its_client
+ << " is not connected anymore, do not expect answer for policy update / removal with ID: 0x"
+ << std::hex << _id;
+ pending_security_update_remove(_id, its_client);
+ }
+ }
+ }
+
+ its_missing_clients = pending_security_update_get(_id);
+ if (its_missing_clients.empty()) {
+ VSOMEIP_INFO << __func__ << ": Received all responses for "
+ "security update/removal ID: 0x" << std::hex << _id;
+ its_state = security_update_state_e::SU_SUCCESS;
+ }
+ {
+ // erase pending security update
+ std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
+ pending_security_updates_.erase(_id);
+ }
+
+ // call handler with error on timeout or with SUCCESS if missing clients are not connected
+ std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
+ const auto found_handler = security_update_handlers_.find(_id);
+ if (found_handler != security_update_handlers_.end()) {
+ found_handler->second(its_state);
+ security_update_handlers_.erase(found_handler);
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Callback not found for security update / removal with ID: 0x"
+ << std::hex << _id;
+ }
+ }
+}
+
+bool routing_manager_impl::update_security_policy_configuration(
+ uint32_t _uid, uint32_t _gid,
+ ::std::shared_ptr<policy> _policy, std::shared_ptr<payload> _payload, security_update_handler_t _handler) {
+ bool ret(true);
+ // cache security policy payload for later distribution to new registering clients
+ stub_->policy_cache_add(_uid, _payload);
+
+ // update security policy from configuration
+ configuration_->update_security_policy(_uid, _gid, _policy);
+
+ // determine currently connected clients
+ std::unordered_set<client_t> its_clients_to_inform = get_connected_clients();
+
+ // add handler
+ pending_security_update_id_t its_id;
+ if (!its_clients_to_inform.empty()) {
+ its_id = pending_security_update_add(its_clients_to_inform);
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
+ security_update_handlers_[its_id] = _handler;
+ }
+
+ {
+ std::shared_ptr<boost::asio::steady_timer> its_timer =
+ std::make_shared<boost::asio::steady_timer>(io_);
+ boost::system::error_code ec;
+ its_timer->expires_from_now(std::chrono::milliseconds(3000), ec);
+ if (!ec) {
+ its_timer->async_wait(
+ std::bind(
+ &routing_manager_impl::on_security_update_timeout,
+ std::static_pointer_cast<routing_manager_impl>(
+ shared_from_this()),
+ std::placeholders::_1, its_id, its_timer));
+ } else {
+ VSOMEIP_ERROR << __func__ << ": timer creation: " << ec.message();
+ }
+ std::lock_guard<std::mutex> its_lock(security_update_timers_mutex_);
+ security_update_timers_[its_id] = its_timer;
+ }
+
+ // trigger all currently connected clients to update the security policy
+ uint32_t sent_counter(0);
+ uint32_t its_tranche =
+ uint32_t(its_clients_to_inform.size() >= 10 ? (its_clients_to_inform.size() / 10) : 1);
+ VSOMEIP_INFO << __func__ << ": Informing [" << std::dec << its_clients_to_inform.size()
+ << "] currently connected clients about policy update for UID: "
+ << std::dec << _uid << " with update ID: 0x" << std::hex << its_id;
+ for (auto its_client : its_clients_to_inform) {
+ if (!stub_->send_update_security_policy_request(its_client, its_id, _uid, _payload)) {
+ VSOMEIP_INFO << __func__ << ": Couldn't send update security policy "
+ << "request to client 0x" << std::hex << std::setw(4)
+ << std::setfill('0') << its_client << " policy UID: "
+ << std::hex << std::setw(4) << std::setfill('0') << _uid << " GID: "
+ << std::hex << std::setw(4) << std::setfill('0') << _gid
+ << " with update ID: 0x" << std::hex << its_id
+ << " as client already disconnected";
+ // remove client from expected answer list
+ pending_security_update_remove(its_id, its_client);
+ }
+ sent_counter++;
+ // Prevent burst
+ if (sent_counter % its_tranche == 0) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ }
+ } else {
+ // if routing manager has no client call the handler directly
+ _handler(security_update_state_e::SU_SUCCESS);
+ }
+ return ret;
+}
+
+bool routing_manager_impl::remove_security_policy_configuration(
+ uint32_t _uid, uint32_t _gid, security_update_handler_t _handler) {
+ bool ret(true);
+
+ // remove security policy from configuration (only if there was a updateACL call before)
+ if (stub_->is_policy_cached(_uid)) {
+ if (!configuration_->remove_security_policy(_uid, _gid)) {
+ _handler(vsomeip::security_update_state_e::SU_UNKNOWN_USER_ID);
+ ret = false;
+ } else {
+ // remove policy from cache to prevent sending it to registering clients
+ stub_->policy_cache_remove(_uid);
+
+ // add handler
+ pending_security_update_id_t its_id;
+
+ // determine currently connected clients
+ std::unordered_set<client_t> its_clients_to_inform = get_connected_clients();
+
+ if (!its_clients_to_inform.empty()) {
+ its_id = pending_security_update_add(its_clients_to_inform);
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
+ security_update_handlers_[its_id] = _handler;
+ }
+
+ {
+ std::shared_ptr<boost::asio::steady_timer> its_timer =
+ std::make_shared<boost::asio::steady_timer>(io_);
+ boost::system::error_code ec;
+ its_timer->expires_from_now(std::chrono::milliseconds(3000), ec);
+ if (!ec) {
+ its_timer->async_wait(
+ std::bind(
+ &routing_manager_impl::on_security_update_timeout,
+ std::static_pointer_cast<routing_manager_impl>(
+ shared_from_this()),
+ std::placeholders::_1, its_id, its_timer));
+ } else {
+ VSOMEIP_ERROR << __func__ << ": timer creation: " << ec.message();
+ }
+ std::lock_guard<std::mutex> its_lock(security_update_timers_mutex_);
+ security_update_timers_[its_id] = its_timer;
+ }
+
+ // trigger all clients to remove the security policy
+ uint32_t sent_counter(0);
+ uint32_t its_tranche =
+ uint32_t(its_clients_to_inform.size() >= 10 ? (its_clients_to_inform.size() / 10) : 1);
+ VSOMEIP_INFO << __func__ << ": Informing [" << std::dec << its_clients_to_inform.size()
+ << "] currently connected clients about policy removal for UID: "
+ << std::dec << _uid << " with update ID: " << its_id;
+ for (auto its_client : its_clients_to_inform) {
+ if (!stub_->send_remove_security_policy_request(its_client, its_id, _uid, _gid)) {
+ VSOMEIP_INFO << __func__ << ": Couldn't send remove security policy "
+ << "request to client 0x" << std::hex << std::setw(4)
+ << std::setfill('0') << its_client << " policy UID: "
+ << std::hex << std::setw(4) << std::setfill('0') << _uid << " GID: "
+ << std::hex << std::setw(4) << std::setfill('0') << _gid
+ << " with update ID: 0x" << std::hex << its_id
+ << " as client already disconnected";
+ // remove client from expected answer list
+ pending_security_update_remove(its_id, its_client);
+ }
+ sent_counter++;
+ // Prevent burst
+ if (sent_counter % its_tranche == 0) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ }
+ } else {
+ // if routing manager has no client call the handler directly
+ _handler(security_update_state_e::SU_SUCCESS);
+ }
+ }
+ }
+ else {
+ _handler(vsomeip::security_update_state_e::SU_UNKNOWN_USER_ID);
+ ret = false;
+ }
+ return ret;
+}
+
+pending_security_update_id_t routing_manager_impl::pending_security_update_add(
+ std::unordered_set<client_t> _clients) {
+ std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
+ if (++pending_security_update_id_ == 0) {
+ pending_security_update_id_++;
+ }
+ pending_security_updates_[pending_security_update_id_] = _clients;
+ return pending_security_update_id_;
+}
+
+std::unordered_set<client_t> routing_manager_impl::pending_security_update_get(
+ pending_security_update_id_t _id) {
+ std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
+ std::unordered_set<client_t> its_missing_clients;
+ auto found_si = pending_security_updates_.find(_id);
+ if (found_si != pending_security_updates_.end()) {
+ its_missing_clients = pending_security_updates_[_id];
+ }
+ return its_missing_clients;
+}
+
+bool routing_manager_impl::pending_security_update_remove(
+ pending_security_update_id_t _id, client_t _client) {
+ std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
+ auto found_si = pending_security_updates_.find(_id);
+ if (found_si != pending_security_updates_.end()) {
+ if (found_si->second.erase(_client)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool routing_manager_impl::is_pending_security_update_finished(
+ pending_security_update_id_t _id) {
+ std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
+ bool ret(false);
+ auto found_si = pending_security_updates_.find(_id);
+ if (found_si != pending_security_updates_.end()) {
+ if (!found_si->second.size()) {
+ ret = true;
+ }
+ }
+ if (ret) {
+ pending_security_updates_.erase(_id);
+ }
+ return ret;
+}
+
+void routing_manager_impl::on_security_update_response(
+ pending_security_update_id_t _id, client_t _client) {
+ if (pending_security_update_remove(_id, _client)) {
+ if (is_pending_security_update_finished(_id)) {
+ // cancel timeout timer
+ {
+ std::lock_guard<std::mutex> its_lock(security_update_timers_mutex_);
+ auto found_timer = security_update_timers_.find(_id);
+ if (found_timer != security_update_timers_.end()) {
+ boost::system::error_code ec;
+ found_timer->second->cancel(ec);
+ security_update_timers_.erase(found_timer);
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Received all responses "
+ "for security update/removal ID: 0x"
+ << std::hex << _id << " but timeout already happened";
+ }
+ }
+
+ // call handler
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
+ auto found_handler = security_update_handlers_.find(_id);
+ if (found_handler != security_update_handlers_.end()) {
+ found_handler->second(security_update_state_e::SU_SUCCESS);
+ security_update_handlers_.erase(found_handler);
+ VSOMEIP_INFO << __func__ << ": Received all responses for "
+ "security update/removal ID: 0x" << std::hex << _id;
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Received all responses "
+ "for security update/removal ID: 0x"
+ << std::hex << _id << " but didn't find handler";
+ }
+ }
+ }
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 8d48b25..d439654 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -10,12 +10,6 @@
#include <future>
#include <forward_list>
-#ifndef _WIN32
-// for umask
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
-
#include <vsomeip/constants.hpp>
#include <vsomeip/runtime.hpp>
@@ -32,6 +26,10 @@
#include "../../service_discovery/include/runtime.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../configuration/include/policy.hpp"
+#ifdef USE_DLT
+#include "../../tracing/include/connector_impl.hpp"
+#endif
namespace vsomeip {
@@ -94,8 +92,10 @@ void routing_manager_proxy::stop() {
if (state_ == inner_state_type_e::ST_REGISTERING) {
register_application_timer_.cancel();
}
+
+ const std::chrono::milliseconds its_timeout(configuration_->get_shutdown_timeout());
while (state_ == inner_state_type_e::ST_REGISTERING) {
- std::cv_status status = state_condition_.wait_for(its_lock, std::chrono::milliseconds(1000));
+ std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
if (status == std::cv_status::timeout) {
VSOMEIP_WARNING << std::hex << client_ << " registering timeout on stop";
break;
@@ -106,7 +106,7 @@ void routing_manager_proxy::stop() {
deregister_application();
// Waiting de-register acknowledge to synchronize shutdown
while (state_ == inner_state_type_e::ST_REGISTERED) {
- std::cv_status status = state_condition_.wait_for(its_lock, std::chrono::milliseconds(1000));
+ std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
if (status == std::cv_status::timeout) {
VSOMEIP_WARNING << std::hex << client_ << " couldn't deregister application - timeout";
break;
@@ -137,7 +137,7 @@ void routing_manager_proxy::stop() {
for (auto client: get_connected_clients()) {
if (client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(client);
+ remove_local(client, true);
}
}
@@ -437,6 +437,27 @@ void routing_manager_proxy::subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
event_t _event, subscription_type_e _subscription_type) {
{
+ if (_event == ANY_EVENT) {
+ if (!is_subscribe_to_any_event_allowed(_client, _service, _instance, _eventgroup)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : routing_manager_proxy::subscribe: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << _service << "/" << _instance << "/ANY_EVENT"
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ } else {
+ if (!configuration_->is_client_allowed(_client, _service,
+ _instance, _event)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : routing_manager_proxy::subscribe: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << _service << "/" << _instance
+ << "/" << _event;
+ return;
+ }
+ }
+
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (state_ == inner_state_type_e::ST_REGISTERED && is_available(_service, _instance, _major)) {
send_subscribe(_client, _service, _instance, _eventgroup, _major,
@@ -617,8 +638,12 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
bool _flush,
bool _reliable,
- bool _is_valid_crc) {
+ client_t _bound_client,
+ bool _is_valid_crc,
+ bool _sent_from_remote) {
(void)_client;
+ (void)_bound_client;
+ (void)_sent_from_remote;
bool is_sent(false);
bool has_remote_subscribers(false);
{
@@ -697,7 +722,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -741,7 +766,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -780,6 +805,7 @@ bool routing_manager_proxy::send_to(
void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) {
_endpoint->set_connected(true);
+ _endpoint->set_established(true);
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (_endpoint != sender_) {
@@ -864,7 +890,16 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
sizeof(its_length));
- if (configuration_->is_security_enabled() && _bound_client != routing_host_id &&
+ bool message_from_routing(false);
+ if (configuration_->is_security_enabled()) {
+ // if security is enabled, client ID of routing must be configured
+ // and credential passing is active. Otherwise bound client is zero by default
+ message_from_routing = (_bound_client == routing_host_id);
+ } else {
+ message_from_routing = (its_client == routing_host_id);
+ }
+
+ if (configuration_->is_security_enabled() && !message_from_routing &&
_bound_client != its_client) {
VSOMEIP_WARNING << std::hex << "Client " << std::setw(4) << std::setfill('0') << get_client()
<< " received a message with command " << (uint32_t)its_command
@@ -877,20 +912,34 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
switch (its_command) {
case VSOMEIP_SEND: {
+ if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a SEND command with too small size -> skip!";
+ break;
+ }
instance_t its_instance;
bool its_reliable;
- bool its_is_vslid_crc;
+ bool its_is_valid_crc;
std::memcpy(&its_instance,&_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
sizeof(instance_t));
std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
sizeof(its_reliable));
- std::memcpy(&its_is_vslid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
- sizeof(its_is_vslid_crc));
+ std::memcpy(&its_is_valid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
+ sizeof(its_is_valid_crc));
// reduce by size of instance, flush, reliable, client and is_valid_crc flag
const std::uint32_t its_message_size = its_length -
(VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
+ if (its_message_size !=
+ VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
+ + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a SEND command containing message with invalid size -> skip!";
+ break;
+ }
+
auto a_deserializer = get_deserializer();
a_deserializer->set_data(&_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS],
its_message_size);
@@ -901,36 +950,110 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
if (its_message) {
its_message->set_instance(its_instance);
its_message->set_reliable(its_reliable);
- its_message->set_is_valid_crc(its_is_vslid_crc);
- if (utility::is_notification(its_message->get_message_type())) {
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
- its_message->get_instance())) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
- << " isn't allow receive a notification from to service/instance "
- << its_message->get_service() << "/" << its_message->get_instance()
- << " respectively from client 0x" << its_client
- << " : Skip message!";
- return;
- }
- cache_event_payload(its_message);
- } else if (utility::is_request(its_message->get_message_type())) {
- if (!configuration_->is_client_allowed(its_message->get_client(),
- its_message->get_service(), its_message->get_instance())) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << its_message->get_client()
- << " isn't allow to send a request to service/instance "
- << its_message->get_service() << "/" << its_message->get_instance()
- << " : Skip message!";
- return;
+ its_message->set_is_valid_crc(its_is_valid_crc);
+ if (!message_from_routing) {
+ if (utility::is_notification(its_message->get_message_type())) {
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a notification from client 0x" << _bound_client
+ << " which does not offer service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return;
+ }
+ cache_event_payload(its_message);
+ }
+ } else if (utility::is_request(its_message->get_message_type())) {
+ if (configuration_->is_security_enabled()
+ && its_message->get_client() != _bound_client) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Client 0x" << std::setw(4) << std::setfill('0') << get_client()
+ << " received a request from client 0x" << std::setw(4) << std::setfill('0')
+ << its_message->get_client() << " to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method() << " which doesn't match the bound client 0x"
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return;
+ }
+
+ if (!configuration_->is_client_allowed(its_message->get_client(),
+ its_message->get_service(), its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_message->get_client()
+ << " : routing_manager_proxy::on_message: "
+ << "isn't allowed to send a request to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ }
+ } else { // response
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a response from client 0x" << _bound_client
+ << " which does not offer service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to receive a response from service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return;
+ }
+ }
}
- } else { // response
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
- its_message->get_instance())) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
- << " isn't allow receive a response from to service/instance "
+ } else {
+ if (!configuration_->is_remote_client_allowed()) {
+ // if the message is from routing manager, check if
+ // policy allows remote requests.
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << std::hex << "Security: Remote clients via routing manager with client ID 0x" << its_client
+ << " are not allowed to communicate with service/instance/method "
<< its_message->get_service() << "/" << its_message->get_instance()
- << " respectively from client 0x" << its_client
- << " : Skip message!";
+ << "/" << its_message->get_method()
+ << " respectively with client 0x" << get_client()
+ << " ~> Skip message!";
return;
+ } else if (utility::is_notification(its_message->get_message_type())) {
+ // As subscription is sent on eventgroup level, incoming remote event ID's
+ // need to be checked as well if remote clients are allowed
+ // and the local policy only allows specific events in the eventgroup to be received.
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from remote clients via routing manager with client ID 0x"
+ << routing_host_id
+ << " ~> Skip message!";
+ return;
+ }
}
}
#ifdef USE_DLT
@@ -938,10 +1061,10 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
&& (client_side_logging_filter_.empty()
|| (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), ANY_INSTANCE)))
|| (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), its_message->get_instance()))))) {
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, false, its_instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS],
static_cast<std::uint16_t>(its_message_size));
}
#endif
@@ -950,20 +1073,29 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
VSOMEIP_ERROR << "Routing proxy: on_message: "
<< "SomeIP-Header deserialization failed!";
}
- }
break;
+ }
case VSOMEIP_ROUTING_INFO:
- if (!configuration_->is_security_enabled() ||_bound_client == routing_host_id) {
+ if (_size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "Received a ROUTING_INFO command with invalid size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
} else {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ VSOMEIP_WARNING << "routing_manager_proxy::on_message: "
+ << std::hex << "Security: Client 0x" << get_client()
<< " received an routing info from a client which isn't the routing manager"
<< " : Skip message!";
}
break;
case VSOMEIP_PING:
+ if (_size != VSOMEIP_PING_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a PING command with wrong size ~> skip!";
+ break;
+ }
send_pong();
VSOMEIP_TRACE << "PING("
<< std::hex << std::setw(4) << std::setfill('0') << client_ << ")";
@@ -990,6 +1122,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::unique_lock<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_);
if (its_subscription_id != DEFAULT_SUBSCRIPTION) {
its_lock.unlock();
+ routing_manager_base::set_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event, subscription_state_e::IS_SUBSCRIBING);
// Remote subscriber: Notify routing manager initially + count subscribes
auto self = shared_from_this();
host_->on_subscription(its_service, its_instance, its_eventgroup,
@@ -1011,6 +1145,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
notify_remote_initially(its_service, its_instance, its_eventgroup,
its_already_subscribed_events);
}
+ send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client, true);
+
std::uint32_t its_count = get_remote_subscriber_count(
its_service, its_instance, its_eventgroup, true);
VSOMEIP_INFO << "SUBSCRIBE("
@@ -1022,19 +1158,51 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< std::dec << (uint16_t)its_major << "]"
<< (bool)(its_subscription_id != DEFAULT_SUBSCRIPTION) << " "
<< std::dec << its_count;
+
+ routing_manager_base::erase_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event);
});
} else if (is_client_known(its_client)) {
its_lock.unlock();
- if (!configuration_->is_client_allowed(its_client,
- its_service, its_instance)) {
- VSOMEIP_WARNING << "Security: Client " << std::hex
- << its_client << " subscribes to service/instance "
- << its_service << "/" << its_instance
- << " which violates the security policy ~> Skip subscribe!";
- return;
+ if (!message_from_routing) {
+ if (its_event == ANY_EVENT) {
+ if (!is_subscribe_to_any_event_allowed(its_client, its_service, its_instance, its_eventgroup)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << its_service << "/" << its_instance << "/ANY_EVENT"
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ } else {
+ if (!configuration_->is_client_allowed(its_client,
+ its_service, its_instance, its_event)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_proxy::on_message: "
+ << " subscribes to service/instance/event "
+ << its_service << "/" << its_instance << "/" << its_event
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ }
+ } else {
+ if (!configuration_->is_remote_client_allowed()) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_proxy::on_message: "
+ << std::hex << "Routing manager with client ID 0x"
+ << its_client
+ << " isn't allowed to subscribe to service/instance/event "
+ << its_service << "/" << its_instance
+ << "/" << its_event
+ << " respectively to client 0x" << get_client()
+ << " ~> Skip Subscribe!";
+ return;
+ }
}
// Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
+ routing_manager_base::set_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event, subscription_state_e::IS_SUBSCRIBING);
(void) find_or_create_local(its_client);
auto self = shared_from_this();
host_->on_subscription(its_service, its_instance,
@@ -1053,6 +1221,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client);
}
+ routing_manager_base::erase_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event);
});
} else {
// Local & not yet known subscriber ~> set pending until subscriber gets known!
@@ -1182,7 +1352,11 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
break;
case VSOMEIP_OFFERED_SERVICES_RESPONSE:
- if (!configuration_->is_security_enabled() ||_bound_client == routing_host_id) {
+ if (_size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "Received a VSOMEIP_OFFERED_SERVICES_RESPONSE command with invalid size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
on_offered_services_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
} else {
VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
@@ -1190,7 +1364,148 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< " : Skip message!";
}
break;
+ case VSOMEIP_RESEND_PROVIDED_EVENTS: {
+ if (_size != VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a RESEND_PROVIDED_EVENTS command with wrong size ~> skip!";
+ break;
+ }
+ pending_remote_offer_id_t its_pending_remote_offer_id(0);
+ std::memcpy(&its_pending_remote_offer_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_remote_offer_id_t));
+ resend_provided_event_registrations();
+ send_resend_provided_event_response(its_pending_remote_offer_id);
+ VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_client << ")";
+ break;
+ }
+ case VSOMEIP_UPDATE_SECURITY_POLICY: {
+ if (_size < VSOMEIP_COMMAND_HEADER_SIZE + sizeof(pending_security_update_id_t) ||
+ _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY command with wrong size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ pending_security_update_id_t its_update_id(0);
+ uint32_t its_uid(0);
+ uint32_t its_gid(0);
+
+ std::memcpy(&its_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_security_update_id_t));
+
+ std::shared_ptr<policy> its_policy(std::make_shared<policy>());
+ const byte_t* buffer_ptr = _data + (VSOMEIP_COMMAND_PAYLOAD_POS +
+ sizeof(pending_security_update_id_t));
+ uint32_t its_size = uint32_t(_size - (VSOMEIP_COMMAND_PAYLOAD_POS
+ + sizeof(pending_security_update_id_t)));
+ utility::parse_policy(buffer_ptr, its_size, its_uid, its_gid, its_policy);
+
+ if (configuration_->is_policy_update_allowed(its_uid, its_policy)) {
+ configuration_->update_security_policy(its_uid, its_gid, its_policy);
+ send_update_security_policy_response(its_update_id);
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a security policy update from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
+ case VSOMEIP_REMOVE_SECURITY_POLICY: {
+ if (_size != VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_REMOVE_SECURITY_POLICY command with wrong size ~> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ pending_security_update_id_t its_update_id(0);
+ uint32_t its_uid(0xffffffff);
+ uint32_t its_gid(0xffffffff);
+
+ std::memcpy(&its_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_security_update_id_t));
+ std::memcpy(&its_uid, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
+ sizeof(uint32_t));
+ std::memcpy(&its_gid, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
+ sizeof(uint32_t));
+ if (configuration_->is_policy_removal_allowed(its_uid)) {
+ configuration_->remove_security_policy(its_uid, its_gid);
+ send_remove_security_policy_response(its_update_id);
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << "received a security policy removal from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
+ case VSOMEIP_DISTRIBUTE_SECURITY_POLICIES: {
+ if (_size < VSOMEIP_COMMAND_HEADER_SIZE ||
+ _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_DISTRIBUTE_SECURITY_POLICIES command with wrong size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ uint32_t its_policy_count(0);
+ uint32_t its_policy_size(0);
+ const byte_t* buffer_ptr = 0;
+
+ if (VSOMEIP_COMMAND_PAYLOAD_POS + sizeof(uint32_t) * 2 <= _size) {
+ std::memcpy(&its_policy_count, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(uint32_t));
+
+ // skip policy count field
+ buffer_ptr = _data + (VSOMEIP_COMMAND_PAYLOAD_POS +
+ sizeof(uint32_t));
+
+ for (uint32_t i = 0; i < its_policy_count; i++) {
+ uint32_t its_uid(0);
+ uint32_t its_gid(0);
+ std::shared_ptr<policy> its_policy(std::make_shared<policy>());
+ // length field of next (UID/GID + policy)
+ if (buffer_ptr + sizeof(uint32_t) <= _data + _size) {
+ std::memcpy(&its_policy_size, buffer_ptr,
+ sizeof(uint32_t));
+ buffer_ptr += sizeof(uint32_t);
+
+ if (buffer_ptr + its_policy_size <= _data + _size) {
+ if (utility::parse_policy(buffer_ptr, its_policy_size, its_uid, its_gid, its_policy)) {
+ if (configuration_->is_policy_update_allowed(its_uid, its_policy)) {
+ configuration_->update_security_policy(its_uid, its_gid, its_policy);
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client() << " could not parse policy!";
+ }
+ }
+ }
+ }
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a security policy distribution command from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
+ case VSOMEIP_UPDATE_SECURITY_CREDENTIALS: {
+ if (_size < VSOMEIP_COMMAND_HEADER_SIZE ||
+ _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_CREDENTIALS command with wrong size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ on_update_security_credentials(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << "received a security credential update from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
default:
break;
}
@@ -1237,6 +1552,17 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<< " is registered.";
+#ifndef _WIN32
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_routing_info: RIE_ADD_CLIENT: isn't allowed"
+ << " to use the server endpoint due to credential check failed!";
+ deregister_application();
+ host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
+ return;
+ }
+#endif
+
// inform host about its own registration state changes
host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_REGISTERED));
@@ -1257,6 +1583,7 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
known_clients_.erase(its_client);
}
if (its_client == get_client()) {
+ configuration_->remove_client_to_uid_gid_mapping(its_client);
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<< " is deregistered.";
@@ -1270,7 +1597,7 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
state_condition_.notify_one();
}
} else if (its_client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(its_client);
+ remove_local(its_client, true);
}
}
@@ -1325,6 +1652,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
auto found_service = local_services_.find(its_service);
if (found_service != local_services_.end()) {
found_service->second.erase(its_instance);
+ // move previously offering client to history
+ local_services_history_[its_service][its_instance].insert(its_client);
if (found_service->second.size() == 0) {
local_services_.erase(its_service);
}
@@ -1374,6 +1703,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
}
}
for (const subscription_info &si : subscription_actions) {
+ routing_manager_base::set_incoming_subscription_state(si.client_id_, si.service_id_, si.instance_id_,
+ si.eventgroup_id_, si.event_, subscription_state_e::IS_SUBSCRIBING);
(void) find_or_create_local(si.client_id_);
auto self = shared_from_this();
host_->on_subscription(
@@ -1393,6 +1724,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
send_pending_notify_ones(si.service_id_,
si.instance_id_, si.eventgroup_id_, si.client_id_);
}
+ routing_manager_base::erase_incoming_subscription_state(si.client_id_, si.service_id_,
+ si.instance_id_, si.eventgroup_id_, si.event_);
{
std::lock_guard<std::recursive_mutex> its_lock2(incoming_subscriptions_mutex_);
pending_incoming_subscripitons_.erase(si.client_id_);
@@ -1469,12 +1802,26 @@ void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clien
// Remove all local connections/endpoints
for (const auto its_client : _clients) {
if (its_client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(its_client);
+ remove_local(its_client, true);
}
}
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<<": Reconnecting to routing manager.";
+
+#ifndef _WIN32
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::reconnect: isn't allowed"
+ << " to use the server endpoint due to credential check failed!";
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->stop();
+ }
+ return;
+ }
+#endif
+
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
sender_->restart();
@@ -1509,14 +1856,10 @@ void routing_manager_proxy::register_application() {
}
void routing_manager_proxy::deregister_application() {
- uint32_t its_size = sizeof(client_);
-
- std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size);
+ std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE, 0);
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_DEREGISTER_APPLICATION;
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
sizeof(client_));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
if (is_connected_)
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
@@ -1558,7 +1901,7 @@ void routing_manager_proxy::send_request_services(std::set<service_data_t>& _req
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
sizeof(client_));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
+ sizeof(std::uint32_t));
uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t)
+ sizeof(minor_version_t) + sizeof(bool));
@@ -1788,17 +2131,13 @@ void routing_manager_proxy::init_receiver() {
::_unlink(its_client.str().c_str());
int port = VSOMEIP_INTERNAL_BASE_PORT + client_;
#else
- if (!check_credentials(get_client(), getuid(), getgid())) {
- VSOMEIP_ERROR << "routing_manager_proxy::init_receiver: "
- << std::hex << "Client " << get_client() << " isn't allow"
- << " to create a server endpoint due to credential check failed!";
- return;
- }
+ configuration_->store_client_to_uid_gid_mapping(get_client(), getuid(), getgid());
+ configuration_->store_uid_gid_to_client_mapping(getuid(), getgid(), get_client());
+
if (-1 == ::unlink(its_client.str().c_str()) && errno != ENOENT) {
VSOMEIP_ERROR << "routing_manager_proxy::init_receiver unlink failed ("
<< its_client.str() << "): "<< std::strerror(errno);
}
- const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
#endif
try {
receiver_ = std::make_shared<local_server_endpoint_impl>(shared_from_this(),
@@ -1809,7 +2148,8 @@ void routing_manager_proxy::init_receiver() {
#endif
io_, configuration_->get_max_message_size_local(),
configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local());
+ configuration_->get_endpoint_queue_limit_local(),
+ configuration_->get_permissions_uds());
#ifdef _WIN32
VSOMEIP_INFO << "Listening at " << port;
#else
@@ -1819,9 +2159,6 @@ void routing_manager_proxy::init_receiver() {
host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED);
VSOMEIP_ERROR << "Client ID: " << std::hex << client_ << ": " << e.what();
}
-#ifndef _WIN32
- ::umask(previous_mask);
-#endif
}
void routing_manager_proxy::notify_remote_initially(service_t _service, instance_t _instance,
@@ -2008,7 +2345,7 @@ void routing_manager_proxy::handle_client_error(client_t _client) {
if (_client != VSOMEIP_ROUTING_CLIENT) {
VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
<< " handles a client error(" << std::hex << _client << ")";
- remove_local(_client);
+ remove_local(_client, true);
} else {
bool should_reconnect(true);
{
@@ -2077,4 +2414,99 @@ void routing_manager_proxy::send_unsubscribe_ack(
}
}
+void routing_manager_proxy::resend_provided_event_registrations() {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ for (const event_data_t& ed : pending_event_registrations_) {
+ if (ed.is_provided_) {
+ send_register_event(client_, ed.service_, ed.instance_,
+ ed.event_, ed.eventgroups_,
+ ed.is_field_, ed.is_provided_);
+ }
+ }
+}
+
+void routing_manager_proxy::send_resend_provided_event_response(pending_remote_offer_id_t _id) {
+ byte_t its_command[VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE];
+ const std::uint32_t its_size = VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+
+ const client_t its_client = get_client();
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RESEND_PROVIDED_EVENTS;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
+ sizeof(its_client));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_id,
+ sizeof(pending_remote_offer_id_t));
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
+ }
+ }
+}
+
+void routing_manager_proxy::send_update_security_policy_response(pending_security_update_id_t _update_id) {
+ byte_t its_command[VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE];
+ const std::uint32_t its_size = VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+
+ const client_t its_client = get_client();
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
+ sizeof(its_client));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
+ sizeof(pending_security_update_id_t));
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
+ }
+ }
+}
+
+void routing_manager_proxy::send_remove_security_policy_response(pending_security_update_id_t _update_id) {
+ byte_t its_command[VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE];
+ const std::uint32_t its_size = VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+
+ const client_t its_client = get_client();
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
+ sizeof(its_client));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
+ sizeof(pending_security_update_id_t));
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
+ }
+ }
+}
+
+void routing_manager_proxy::on_update_security_credentials(const byte_t *_data, uint32_t _size) {
+ uint32_t i = 0;
+ while ( (i + sizeof(uint32_t) + sizeof(uint32_t)) <= _size) {
+ std::shared_ptr<policy> its_policy(std::make_shared<policy>());
+ ranges_t its_uid_ranges, its_gid_ranges;
+ uint32_t its_uid, its_gid;
+
+ std::memcpy(&its_uid, &_data[i], sizeof(uint32_t));
+ i += uint32_t(sizeof(uint32_t));
+ std::memcpy(&its_gid, &_data[i], sizeof(uint32_t));
+ i += uint32_t(sizeof(uint32_t));
+
+ its_uid_ranges.insert(std::make_pair(its_uid, its_uid));
+ its_gid_ranges.insert(std::make_pair(its_gid, its_gid));
+
+ its_policy->allow_who_ = true;
+ its_policy->ids_.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
+ configuration_->add_security_credentials(its_uid, its_gid, its_policy, get_client());
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 528c729..5c19af9 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -8,12 +8,6 @@
#include <iomanip>
#include <forward_list>
-#ifndef _WIN32
-// for umask
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
-
#include <boost/system/error_code.hpp>
#include <vsomeip/constants.hpp>
@@ -34,6 +28,7 @@
#include "../../logging/include/logger.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
+#include "../implementation/message/include/payload_impl.hpp"
namespace vsomeip {
@@ -162,6 +157,7 @@ const std::shared_ptr<configuration> routing_manager_stub::get_configuration() c
void routing_manager_stub::on_connect(std::shared_ptr<endpoint> _endpoint) {
_endpoint->set_connected(true);
+ _endpoint->set_established(true);
}
void routing_manager_stub::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
@@ -211,6 +207,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::string its_client_endpoint;
service_t its_service;
instance_t its_instance;
+ method_t its_method;
eventgroup_t its_eventgroup;
std::set<eventgroup_t> its_eventgroups;
event_t its_event;
@@ -235,10 +232,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_client));
if (configuration_->is_security_enabled() && _bound_client != its_client) {
- VSOMEIP_WARNING << "Security: Routing Manager received a message from client "
+ VSOMEIP_WARNING << "vSomeIP Security: routing_manager_stub::on_message: "
+ << "Routing Manager received a message from client "
<< std::hex << std::setw(4) << std::setfill('0')
- << its_client << " with command " << (uint32_t)its_command <<
- " which doesn't match the bound client "
+ << its_client << " with command " << (uint32_t)its_command
+ << " which doesn't match the bound client "
<< std::setw(4) << std::setfill('0') << _bound_client
<< " ~> skip message!";
return;
@@ -250,14 +248,26 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) {
switch (its_command) {
case VSOMEIP_REGISTER_APPLICATION:
+ if (_size != VSOMEIP_REGISTER_APPLICATION_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a REGISTER_APPLICATION command with wrong size ~> skip!";
+ break;
+ }
update_registration(its_client, registration_type_e::REGISTER);
break;
case VSOMEIP_DEREGISTER_APPLICATION:
+ if (_size != VSOMEIP_DEREGISTER_APPLICATION_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a DEREGISTER_APPLICATION command with wrong size ~> skip!";
+ break;
+ }
update_registration(its_client, registration_type_e::DEREGISTER);
break;
case VSOMEIP_PONG:
+ if (_size != VSOMEIP_PONG_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a PONG command with wrong size ~> skip!";
+ break;
+ }
on_pong(its_client);
VSOMEIP_TRACE << "PONG("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
@@ -277,8 +287,16 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_major));
std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
sizeof(its_minor));
- host_->offer_service(its_client, its_service, its_instance,
- its_major, its_minor);
+
+ if (configuration_->is_offer_allowed(its_client, its_service, its_instance)) {
+ host_->offer_service(its_client, its_service, its_instance,
+ its_major, its_minor);
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_stub::on_message: isn't allowed to offer "
+ << "the following service/instance " << its_service << "/" << its_instance
+ << " ~> Skip offer!";
+ }
break;
case VSOMEIP_STOP_OFFER_SERVICE:
@@ -317,15 +335,30 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_event));
std::memcpy(&its_subscription_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
sizeof(its_subscription_type));
- if (configuration_->is_client_allowed(its_client,
- its_service, its_instance)) {
- host_->subscribe(its_client, its_service, its_instance,
- its_eventgroup, its_major, its_event, its_subscription_type);
+
+ if (its_event == ANY_EVENT) {
+ if (host_->is_subscribe_to_any_event_allowed(its_client, its_service, its_instance, its_eventgroup)) {
+ host_->subscribe(its_client, its_service, its_instance,
+ its_eventgroup, its_major, its_event, its_subscription_type);
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_stub::on_message: "
+ << " subscribes to service/instance/event "
+ << its_service << "/" << its_instance << "/ANY_EVENT"
+ << " which violates the security policy ~> Skip subscribe!";
+ }
} else {
- VSOMEIP_WARNING << "Security: Client " << std::hex
- << its_client << " subscribes to service/instance "
- << its_service << "/" << its_instance
- << " which violates the security policy ~> Skip subscribe!";
+ if (configuration_->is_client_allowed(its_client,
+ its_service, its_instance, its_event)) {
+ host_->subscribe(its_client, its_service, its_instance,
+ its_eventgroup, its_major, its_event, its_subscription_type);
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_stub::on_message: "
+ << " subscribes to service/instance/event "
+ << its_service << "/" << its_instance << "/" << its_event
+ << " which violates the security policy ~> Skip subscribe!";
+ }
}
break;
@@ -422,6 +455,10 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "]";
break;
case VSOMEIP_SEND: {
+ if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a SEND command with too small size ~> skip!";
+ break;
+ }
its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
its_service = VSOMEIP_BYTES_TO_WORD(
its_data[VSOMEIP_SERVICE_POS_MIN],
@@ -429,6 +466,9 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
its_client_from_header = VSOMEIP_BYTES_TO_WORD(
its_data[VSOMEIP_CLIENT_POS_MIN],
its_data[VSOMEIP_CLIENT_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ its_data[VSOMEIP_METHOD_POS_MIN],
+ its_data[VSOMEIP_METHOD_POS_MAX]);
std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
sizeof(its_instance));
std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
@@ -436,34 +476,40 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_is_valid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
sizeof(its_is_valid_crc));
+ // Allow response messages from local proxies as answer to remote requests
+ // but check requests sent by local proxies to remote against policy.
if (utility::is_request(its_data[VSOMEIP_MESSAGE_TYPE_POS])) {
if (!configuration_->is_client_allowed(its_client_from_header,
- its_service, its_instance)) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << its_client_from_header
- << " isn't allow to send a request to service/instance "
- << its_service << "/" << its_instance
- << " : Skip message!";
- return;
- }
- } else {
- if (!configuration_->is_client_allowed(get_client(), its_service,
- its_instance)) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x"
- << get_client()
- << " isn't allow receive a response from to service/instance "
- << its_service << "/" << its_instance
- << " respectively from client 0x" << its_client
- << " : Skip message!";
+ its_service, its_instance, its_method)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client_from_header
+ << " : routing_manager_stub::on_message: "
+ << " isn't allowed to send a request to service/instance/method "
+ << its_service << "/" << its_instance << "/" << its_method
+ << " ~> Skip message!";
return;
}
}
// reduce by size of instance, flush, reliable, client and is_valid_crc flag
const std::uint32_t its_message_size = its_size -
(VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
- host_->on_message(its_service, its_instance, its_data, its_message_size, its_reliable, its_is_valid_crc);
+ if (its_message_size !=
+ VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
+ + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a SEND command containing message with invalid size -> skip!";
+ break;
+ }
+ host_->on_message(its_service, its_instance, its_data, its_message_size,
+ its_reliable, _bound_client, its_is_valid_crc, false);
break;
}
case VSOMEIP_NOTIFY: {
+ if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a NOTIFY command with too small size ~> skip!";
+ break;
+ }
its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
its_service = VSOMEIP_BYTES_TO_WORD(
its_data[VSOMEIP_SERVICE_POS_MIN],
@@ -473,10 +519,23 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
// reduce by size of instance, flush, reliable, is_valid_crc flag and target client
const std::uint32_t its_message_size = its_size -
(VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
+ if (its_message_size !=
+ VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
+ + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a NOTIFY command containing message with invalid size -> skip!";
+ break;
+ }
host_->on_notification(VSOMEIP_ROUTING_CLIENT, its_service, its_instance, its_data, its_message_size);
break;
}
case VSOMEIP_NOTIFY_ONE: {
+ if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a NOTIFY_ONE command with too small size ~> skip!";
+ break;
+ }
its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
its_service = VSOMEIP_BYTES_TO_WORD(
its_data[VSOMEIP_SERVICE_POS_MIN],
@@ -488,6 +547,15 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
// reduce by size of instance, flush, reliable flag, is_valid_crc and target client
const std::uint32_t its_message_size = its_size -
(VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
+ if (its_message_size !=
+ VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
+ + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a NOTIFY_ONE command containing message with invalid size -> skip!";
+ break;
+ }
host_->on_notification(its_target_client, its_service, its_instance,
its_data, its_message_size, true);
break;
@@ -496,6 +564,10 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
{
uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t)
+ sizeof(minor_version_t) + sizeof(bool));
+ if (its_size % entry_size > 0) {
+ VSOMEIP_WARNING << "Received a REQUEST_SERVICE command with invalid size -> skip!";
+ break;
+ }
uint32_t request_count(its_size / entry_size);
std::set<service_data_t> requests;
for (uint32_t i = 0; i < request_count; ++i) {
@@ -515,19 +587,23 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_minor));
std::memcpy(&use_exclusive_proxy, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9 + (i * entry_size)],
sizeof(use_exclusive_proxy));
- if (configuration_->is_client_allowed(its_client, its_service, its_instance)) {
+ if (configuration_->is_client_allowed(its_client, its_service, its_instance, 0x00, true)) {
host_->request_service(its_client, its_service, its_instance,
its_major, its_minor, use_exclusive_proxy);
service_data_t request = { its_service, its_instance,
its_major, its_minor, use_exclusive_proxy };
requests.insert(request);
} else {
- VSOMEIP_WARNING << "Security: Client " << std::hex
- << its_client << " requests service/instance "
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
+ << its_client << " : routing_manager_stub::on_message: "
+ << "requests service/instance "
<< its_service << "/" << its_instance
<< " which violates the security policy ~> Skip request!";
}
}
+ if (configuration_->is_security_enabled()) {
+ handle_credentials(its_client, requests);
+ }
handle_requests(its_client, requests);
break;
}
@@ -640,10 +716,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
break;
case VSOMEIP_REGISTERED_ACK:
+ if (_size != VSOMEIP_REGISTERED_ACK_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a REGISTERED_ACK command with wrong size ~> skip!";
+ break;
+ }
VSOMEIP_INFO << "REGISTERED_ACK("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
break;
- case VSOMEIP_OFFERED_SERVICES_REQUEST:
+ case VSOMEIP_OFFERED_SERVICES_REQUEST: {
if (_size != VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE) {
VSOMEIP_WARNING << "Received a VSOMEIP_OFFERED_SERVICES_REQUEST command with wrong size ~> skip!";
break;
@@ -694,6 +774,46 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
}
send_offered_services_info(its_client);
break;
+ }
+ case VSOMEIP_RESEND_PROVIDED_EVENTS: {
+ if (_size != VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a RESEND_PROVIDED_EVENTS command with wrong size ~> skip!";
+ break;
+ }
+ pending_remote_offer_id_t its_pending_remote_offer_id(0);
+ std::memcpy(&its_pending_remote_offer_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_remote_offer_id_t));
+ host_->on_resend_provided_events_response(its_pending_remote_offer_id);
+ VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
+ break;
+ }
+ case VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE: {
+ if (_size != VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE "
+ << "command with wrong size ~> skip!";
+ break;
+ }
+ pending_security_update_id_t its_pending_security_update_id(0);
+ std::memcpy(&its_pending_security_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_security_update_id_t));
+
+ host_->on_security_update_response(its_pending_security_update_id ,its_client);
+ break;
+ }
+ case VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE: {
+ if (_size != VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE "
+ << "command with wrong size ~> skip!";
+ break;
+ }
+ pending_security_update_id_t its_pending_security_update_id(0);
+ std::memcpy(&its_pending_security_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_security_update_id_t));
+
+ host_->on_security_update_response(its_pending_security_update_id ,its_client);
+ break;
+ }
}
}
}
@@ -778,6 +898,10 @@ void routing_manager_stub::client_registration_func(void) {
routing_info_entry_e::RIE_ADD_CLIENT :
routing_info_entry_e::RIE_DEL_CLIENT,
r.first);
+ // distribute updated security config to new clients
+ if (b == registration_type_e::REGISTER) {
+ send_cached_security_policies(r.first);
+ }
send_client_routing_info(r.first);
}
if (b != registration_type_e::REGISTER) {
@@ -802,7 +926,9 @@ void routing_manager_stub::client_registration_func(void) {
}
service_requests_.erase(r.first);
}
- host_->remove_local(r.first);
+ // Don't remove client ID to UID maping as same client
+ // could have passed its credentials again
+ host_->remove_local(r.first, false);
if (b == registration_type_e::DEREGISTER_ON_ERROR) {
utility::release_client_id(r.first);
}
@@ -819,8 +945,7 @@ void routing_manager_stub::init_routing_endpoint() {
endpoint_path_ = its_endpoint_path.str();
client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
if (configuration_->is_security_enabled() && get_client() != routing_host_id) {
- VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint: "
- << std::hex << "Client " << get_client() << " isn't allow"
+ VSOMEIP_ERROR << __func__ << std::hex << " Client " << get_client() << " isn't allowed"
<< " to create the routing endpoint due to its not configured as the routing master!";
return;
}
@@ -840,7 +965,9 @@ void routing_manager_stub::init_routing_endpoint() {
> (shared_from_this(),
boost::asio::local::stream_protocol::endpoint(endpoint_path_),
io_, configuration_->get_max_message_size_local(), native_socket_fd,
- configuration_->get_buffer_shrink_threshold());
+ configuration_->get_buffer_shrink_threshold(),
+ configuration_->get_endpoint_queue_limit_local(),
+ configuration_->get_permissions_uds());
} catch (const std::exception &e) {
VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
<< " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
@@ -860,8 +987,6 @@ void routing_manager_stub::init_routing_endpoint() {
<< endpoint_path_ << "): "<< std::strerror(errno);
}
VSOMEIP_INFO << "init_routing_endpoint Routing endpoint at " << endpoint_path_;
-
- const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
#endif
try {
@@ -875,16 +1000,14 @@ void routing_manager_stub::init_routing_endpoint() {
#endif
io_, configuration_->get_max_message_size_local(),
configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local());
+ configuration_->get_endpoint_queue_limit_local(),
+ configuration_->get_permissions_uds());
} catch (const std::exception &e) {
VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
<< " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint Client ID: "
<< std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
}
- #ifndef _WIN32
- ::umask(previous_mask);
- #endif
is_socket_activated_ = false;
}
}
@@ -899,13 +1022,17 @@ void routing_manager_stub::on_offer_service(client_t _client,
configuration_->is_offer_allowed(_client, _service, _instance)) {
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
+ if (configuration_->is_security_enabled()) {
+ distribute_credentials(_client, _service, _instance);
+ }
inform_requesters(_client, _service, _instance, _major, _minor,
routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, true);
} else {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << _client
- << " isn't allow to offer the following service/instance "
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : routing_manager_stub::on_offer_service: "
+ << "isn't allowed to offer the following service/instance "
<< _service << "/" << _instance
- << " : Skip offer!";
+ << " ~> Skip offer!";
}
}
@@ -959,6 +1086,87 @@ void routing_manager_stub::create_client_routing_info(const client_t _target) {
client_routing_info_[_target] = its_command;
}
+void routing_manager_stub::create_client_credentials_info(const client_t _target) {
+ std::vector<byte_t> its_command;
+ its_command.push_back(VSOMEIP_UPDATE_SECURITY_CREDENTIALS);
+
+ // Sender client
+ client_t client = get_client();
+ for (uint32_t i = 0; i < sizeof(client_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&client)[i]);
+ }
+
+ // Overall size placeholder
+ byte_t size_placeholder = 0x0;
+ for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
+ its_command.push_back(size_placeholder);
+ }
+
+ client_credentials_info_[_target] = its_command;
+}
+
+void routing_manager_stub::insert_client_credentials_info(client_t _target, std::set<std::pair<uint32_t, uint32_t>> _credentials) {
+ if (client_credentials_info_.find(_target) == client_credentials_info_.end()) {
+ return;
+ }
+
+ auto its_command = client_credentials_info_[_target];
+
+ // insert uid / gid credential pairs
+ for (auto its_credentials : _credentials) {
+ //uid
+ for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&std::get<0>(its_credentials))[i]);
+ }
+ //gid
+ for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&std::get<1>(its_credentials))[i]);
+ }
+ }
+
+ client_credentials_info_[_target] = its_command;
+}
+
+void routing_manager_stub::send_client_credentials_info(const client_t _target) {
+ if (client_credentials_info_.find(_target) == client_credentials_info_.end()) {
+ return;
+ }
+
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
+ if (its_endpoint) {
+ auto its_command = client_credentials_info_[_target];
+
+ // File overall size
+ std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
+ its_size += VSOMEIP_COMMAND_PAYLOAD_POS;
+
+#if 0
+ std::stringstream msg;
+ msg << "rms::send_credentials_info to (" << std::hex << _target << "): ";
+ for (uint32_t i = 0; i < its_size; ++i)
+ msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+
+ // Send routing info or error!
+ if(its_command.size() <= max_local_message_size_
+ || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
+ its_endpoint->send(&its_command[0], uint32_t(its_size), true);
+ } else {
+ VSOMEIP_ERROR << "Credentials info exceeds maximum message size: Can't send!";
+ }
+
+ client_credentials_info_.erase(_target);
+ } else {
+ VSOMEIP_ERROR << "Send credentials info to client 0x" << std::hex << _target
+ << " failed: No valid endpoint!";
+ }
+}
+
void routing_manager_stub::create_offered_services_info(const client_t _target) {
std::vector<byte_t> its_command;
its_command.push_back(VSOMEIP_OFFERED_SERVICES_RESPONSE);
@@ -1175,6 +1383,44 @@ void routing_manager_stub::insert_offered_services_info(client_t _target,
offered_services_info_[_target] = its_command;
}
+void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _service, instance_t _instance) {
+ std::set<std::pair<uint32_t, uint32_t>> its_credentials;
+ std::set<client_t> its_requesting_clients;
+ // search for clients which shall receive the credentials
+ for (auto its_requesting_client : service_requests_) {
+ auto its_service = its_requesting_client.second.find(_service);
+ if (its_service != its_requesting_client.second.end()) {
+ for (auto its_instance : its_service->second) {
+ if (its_instance.first == ANY_INSTANCE ||
+ its_instance.first == _instance) {
+ its_requesting_clients.insert(its_requesting_client.first);
+ } else {
+ auto found_instance = its_service->second.find(_instance);
+ if (found_instance != its_service->second.end()) {
+ its_requesting_clients.insert(its_requesting_client.first);
+ }
+ }
+ }
+ }
+ }
+
+ // search for UID / GID linked with the client ID that offers the requested services
+ std::pair<uint32_t, uint32_t> its_uid_gid;
+ if (configuration_->get_client_to_uid_gid_mapping(_hoster, its_uid_gid)) {
+ for (auto its_requesting_client : its_requesting_clients) {
+ std::pair<uint32_t, uint32_t> its_requester_uid_gid;
+ if (configuration_->get_client_to_uid_gid_mapping(its_requesting_client, its_requester_uid_gid)) {
+ if (its_uid_gid != its_requester_uid_gid) {
+ its_credentials.insert(std::make_pair(std::get<0>(its_uid_gid), std::get<1>(its_uid_gid)));
+ create_client_credentials_info(its_requesting_client);
+ insert_client_credentials_info(its_requesting_client, its_credentials);
+ send_client_credentials_info(its_requesting_client);
+ }
+ }
+ }
+ }
+}
+
void routing_manager_stub::inform_requesters(client_t _hoster, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor,
routing_info_entry_e _entry, bool _inform_service) {
@@ -1414,7 +1660,7 @@ void routing_manager_stub::on_pong(client_t _client) {
void routing_manager_stub::start_watchdog() {
- std::function<void(boost::system::error_code const &)> its_callback =
+ auto its_callback =
[this](boost::system::error_code const &_error) {
if (!_error)
check_watchdog();
@@ -1440,8 +1686,7 @@ void routing_manager_stub::check_watchdog() {
broadcast_ping();
- std::function<void(boost::system::error_code const &)> its_callback =
- [this](boost::system::error_code const &_error) {
+ auto its_callback = [this](boost::system::error_code const &_error) {
(void)_error;
std::list< client_t > lost;
{
@@ -1483,8 +1728,8 @@ void routing_manager_stub::create_local_receiver() {
int port = VSOMEIP_INTERNAL_BASE_PORT;
#else
if (!check_credentials(get_client(), getuid(), getgid())) {
- VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver: "
- << std::hex << "Client " << get_client() << " isn't allow"
+ VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_stub::create_local_receiver: isn't allowed"
<< " to create a server endpoint due to credential check failed!";
return;
}
@@ -1492,8 +1737,6 @@ void routing_manager_stub::create_local_receiver() {
VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver unlink (local receiver) failed ("
<< local_receiver_path_ << "): "<< std::strerror(errno);
}
-
- const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
#endif
try {
local_receiver_ =
@@ -1506,16 +1749,14 @@ void routing_manager_stub::create_local_receiver() {
#endif
io_, configuration_->get_max_message_size_local(),
configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local());
+ configuration_->get_endpoint_queue_limit_local(),
+ configuration_->get_permissions_uds());
} catch (const std::exception &e) {
VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
<< " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
VSOMEIP_ERROR << "routing_manager_stub::_local_receiver Client ID: "
<< std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
}
-#ifndef _WIN32
- ::umask(previous_mask);
-#endif
local_receiver_->start();
}
@@ -1680,6 +1921,10 @@ void routing_manager_stub::update_registration(client_t _client,
<< (_type == registration_type_e::REGISTER ?
"registering." : "deregistering.");
+ if (_type != registration_type_e::REGISTER) {
+ configuration_->remove_client_to_uid_gid_mapping(_client);
+ }
+
if (_type == registration_type_e::DEREGISTER) {
// If we receive a DEREGISTER client command
// the endpoint error handler is not longer needed
@@ -1715,6 +1960,46 @@ client_t routing_manager_stub::get_client() const {
return host_->get_client();
}
+void routing_manager_stub::handle_credentials(const client_t _client, std::set<service_data_t>& _requests) {
+ if (!_requests.size()) {
+ return;
+ }
+
+ std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
+ std::set<std::pair<uint32_t, uint32_t>> its_credentials;
+ std::pair<uint32_t, uint32_t> its_requester_uid_gid;
+ if (configuration_->get_client_to_uid_gid_mapping(_client, its_requester_uid_gid)) {
+ // determine credentials of offering clients using current routing info
+ std::set<client_t> its_offering_clients;
+
+ // search in local clients for the offering client
+ for (auto request : _requests) {
+ std::set<client_t> its_clients;
+ its_clients = host_->find_local_clients(request.service_, request.instance_);
+ for (auto its_client : its_clients) {
+ its_offering_clients.insert(its_client);
+ }
+ }
+
+ // search for UID / GID linked with the client ID that offers the requested services
+ for (auto its_offering_client : its_offering_clients) {
+ std::pair<uint32_t, uint32_t> its_uid_gid;
+ if (configuration_->get_client_to_uid_gid_mapping(its_offering_client, its_uid_gid)) {
+ if (its_uid_gid != its_requester_uid_gid) {
+ its_credentials.insert(std::make_pair(std::get<0>(its_uid_gid), std::get<1>(its_uid_gid)));
+ }
+ }
+ }
+
+ // send credentials to clients
+ if (!its_credentials.empty()) {
+ create_client_credentials_info(_client);
+ insert_client_credentials_info(_client, its_credentials);
+ send_client_credentials_info(_client);
+ }
+ }
+}
+
void routing_manager_stub::handle_requests(const client_t _client, std::set<service_data_t>& _requests) {
if (!_requests.size()) {
return;
@@ -1861,4 +2146,176 @@ void routing_manager_stub::print_endpoint_status() const {
}
}
+bool routing_manager_stub::send_provided_event_resend_request(client_t _client,
+ pending_remote_offer_id_t _id) {
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint) {
+ byte_t its_command[VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE];
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RESEND_PROVIDED_EVENTS;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
+ sizeof(client_t));
+ std::uint32_t its_size = sizeof(pending_remote_offer_id_t);
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_id,
+ sizeof(pending_remote_offer_id_t));
+ return its_endpoint->send(its_command, sizeof(its_command));
+ } else {
+ VSOMEIP_WARNING << __func__ << " Couldn't send provided event resend "
+ "request to local client: 0x"
+ << std::hex << std::setw(4) << std::setfill('0') << _client;
+ return false;
+ }
+}
+
+bool routing_manager_stub::is_policy_cached(uint32_t _uid) {
+ {
+ std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
+ if (updated_security_policies_.find(_uid)
+ != updated_security_policies_.end()) {
+ VSOMEIP_INFO << __func__ << " Policy for UID: " << std::dec
+ << _uid << " was already updated before!";
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+void routing_manager_stub::policy_cache_add(uint32_t _uid, std::shared_ptr<payload> _payload) {
+ // cache security policy payload for later distribution to new registering clients
+ {
+ std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
+ updated_security_policies_[_uid] = _payload;
+ }
+}
+
+void routing_manager_stub::policy_cache_remove(uint32_t _uid) {
+ {
+ std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
+ updated_security_policies_.erase(_uid);
+ }
+}
+
+bool routing_manager_stub::send_update_security_policy_request(client_t _client, pending_security_update_id_t _update_id,
+ uint32_t _uid, std::shared_ptr<payload> _payload) {
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint) {
+ std::vector<byte_t> its_command;
+ // command
+ its_command.push_back(VSOMEIP_UPDATE_SECURITY_POLICY);
+
+ // client ID
+ for (uint32_t i = 0; i < sizeof(client_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_client)[i]);
+ }
+ // security update id length + payload length including gid and uid
+ std::uint32_t its_size = uint32_t(sizeof(pending_security_update_id_t) + _payload->get_length());
+ for (uint32_t i = 0; i < sizeof(its_size); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&its_size)[i]);
+ }
+ // ID of update request
+ for (uint32_t i = 0; i < sizeof(pending_security_update_id_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_update_id)[i]);
+ }
+ // payload
+ for (uint32_t i = 0; i < _payload->get_length(); ++i) {
+ its_command.push_back(_payload->get_data()[i]);
+ }
+
+ return its_endpoint->send(its_command.data(), uint32_t(its_command.size()));
+ } else {
+ return false;
+ }
+}
+
+bool routing_manager_stub::send_cached_security_policies(client_t _client) {
+ std::vector<byte_t> its_command;
+ std::size_t its_size(0);
+
+ std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
+ uint32_t its_policy_count = uint32_t(updated_security_policies_.size());
+
+ if (!its_policy_count) {
+ return true;
+ }
+
+ VSOMEIP_INFO << __func__ << " Distributing ["
+ << std::dec << its_policy_count
+ << "] security policy updates to registering client: "
+ << std::hex << _client;
+
+ // command
+ its_command.push_back(VSOMEIP_DISTRIBUTE_SECURITY_POLICIES);
+
+ // client ID
+ client_t its_client = get_client();
+ for (uint32_t i = 0; i < sizeof(client_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&its_client)[i]);
+ }
+
+ //overall size (placeholder
+ for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
+ its_command.push_back(0x00);
+ }
+
+ // number of policies contained in message
+ for (uint32_t i = 0; i < sizeof(its_policy_count); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&its_policy_count)[i]);
+ }
+
+ for (auto its_uid_gid : updated_security_policies_) {
+ // policy payload length including gid and uid
+ std::uint32_t its_length = uint32_t(its_uid_gid.second->get_length());
+ for (uint32_t i = 0; i < sizeof(its_length); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&its_length)[i]);
+ }
+ // payload
+ its_command.insert(its_command.end(), its_uid_gid.second->get_data(),
+ its_uid_gid.second->get_data() + its_uid_gid.second->get_length());
+ }
+ // File overall size
+ its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
+
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint) {
+ return its_endpoint->send(its_command.data(), uint32_t(its_command.size()));
+ } else {
+ VSOMEIP_WARNING << __func__ << " Couldn't send cached security policies "
+ " to registering client: 0x"
+ << std::hex << std::setw(4) << std::setfill('0') << _client;
+ return false;
+ }
+}
+
+bool routing_manager_stub::send_remove_security_policy_request( client_t _client, pending_security_update_id_t _update_id,
+ uint32_t _uid, uint32_t _gid) {
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint) {
+ byte_t its_command[VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE];
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REMOVE_SECURITY_POLICY;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
+ sizeof(client_t));
+ std::uint32_t its_size = sizeof(_update_id) + sizeof(_uid) + sizeof(_gid);
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
+ sizeof(uint32_t));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_uid,
+ sizeof(uint32_t));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_gid,
+ sizeof(uint32_t));
+ return its_endpoint->send(its_command, sizeof(its_command));
+ } else {
+ return false;
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp
index 3afc937..42db53b 100644
--- a/implementation/routing/src/serviceinfo.cpp
+++ b/implementation/routing/src/serviceinfo.cpp
@@ -22,6 +22,18 @@ serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor,
ttl_ = std::chrono::duration_cast<std::chrono::milliseconds>(ttl);
}
+serviceinfo::serviceinfo(const serviceinfo& _other) :
+ group_(_other.group_),
+ major_(_other.major_),
+ minor_(_other.minor_),
+ ttl_(_other.ttl_),
+ reliable_(_other.reliable_),
+ unreliable_(_other.unreliable_),
+ requesters_(_other.requesters_),
+ is_local_(_other.is_local_),
+ is_in_mainphase_(_other.is_in_mainphase_)
+ {}
+
serviceinfo::~serviceinfo() {
}
diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp
index efd7d7d..fe23c90 100644
--- a/implementation/runtime/include/application_impl.hpp
+++ b/implementation/runtime/include/application_impl.hpp
@@ -61,7 +61,7 @@ public:
instance_t _instance, event_t _event,
const std::set<eventgroup_t> &_eventgroups,
bool _is_field,
- std::chrono::milliseconds _cycle, bool _change_resets_cycle_,
+ std::chrono::milliseconds _cycle, bool _change_resets_cycle,
const epsilon_change_func_t &_epsilon_change_func);
VSOMEIP_EXPORT void stop_offer_event(service_t _service,
instance_t _instance, event_t _event);
@@ -184,6 +184,31 @@ public:
VSOMEIP_EXPORT void register_async_subscription_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, async_subscription_handler_t _handler);
+ VSOMEIP_EXPORT void set_offer_acceptance_required(ip_address_t _address, const std::string _path, bool _enable);
+ VSOMEIP_EXPORT offer_acceptance_map_type_t get_offer_acceptance_required();
+
+ VSOMEIP_EXPORT void register_offer_acceptance_handler(offer_acceptance_handler_t _handler);
+
+ VSOMEIP_EXPORT void register_reboot_notification_handler(reboot_notification_handler_t _handler);
+
+ VSOMEIP_EXPORT void register_routing_ready_handler(routing_ready_handler_t _handler);
+ VSOMEIP_EXPORT void register_routing_state_handler(routing_state_handler_t _handler);
+
+ VSOMEIP_EXPORT bool update_service_configuration(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled,
+ bool _offer);
+
+ VSOMEIP_EXPORT void update_security_policy_configuration(uint32_t _uid,
+ uint32_t _gid,
+ std::shared_ptr<policy> _policy,
+ std::shared_ptr<payload> _payload,
+ security_update_handler_t _handler);
+ VSOMEIP_EXPORT void remove_security_policy_configuration(uint32_t _uid,
+ uint32_t _gid,
+ security_update_handler_t _handler);
private:
//
// Types
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index 219c8f0..a3040c3 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -27,8 +27,7 @@
#include "../../routing/include/routing_manager_impl.hpp"
#include "../../routing/include/routing_manager_proxy.hpp"
#include "../../utility/include/utility.hpp"
-#include "../../tracing/include/trace_connector.hpp"
-#include "../../tracing/include/enumeration_types.hpp"
+#include "../../tracing/include/connector_impl.hpp"
#include "../../plugin/include/plugin_manager.hpp"
#include "../../endpoints/include/endpoint.hpp"
@@ -63,6 +62,37 @@ application_impl::application_impl(const std::string &_name)
application_impl::~application_impl() {
runtime_->remove_application(name_);
+ try {
+ if (stop_thread_.joinable()) {
+ stop_thread_.detach();
+ }
+ } catch (const std::exception& e) {
+ std::cerr << __func__ << " catched exception (shutdown): " << e.what() << std::endl;
+ }
+
+ try {
+ std::lock_guard<std::mutex> its_lock_start_stop(start_stop_mutex_);
+ for (auto t : io_threads_) {
+ if (t->joinable()) {
+ t->detach();
+ }
+ }
+ io_threads_.clear();
+ } catch (const std::exception& e) {
+ std::cerr << __func__ << " catched exception (io threads): " << e.what() << std::endl;
+ }
+
+ try {
+ std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
+ for (auto its_dispatcher : dispatchers_) {
+ if (its_dispatcher.second->joinable()) {
+ its_dispatcher.second->detach();
+ }
+ }
+ dispatchers_.clear();
+ } catch (const std::exception& e) {
+ std::cerr << __func__ << " catched exception (dispatchers): " << e.what() << std::endl;
+ }
}
void application_impl::set_configuration(
@@ -102,7 +132,7 @@ bool application_impl::init() {
configuration_->load(name_);
VSOMEIP_INFO << "Default configuration module loaded.";
} else {
- std::cerr << "Service Discovery module could not be loaded!" << std::endl;
+ std::cerr << "Configuration module could not be loaded!" << std::endl;
std::exit(EXIT_FAILURE);
}
}
@@ -170,14 +200,22 @@ bool application_impl::init() {
if (!utility::auto_configuration_init(its_configuration)) {
VSOMEIP_WARNING << "Could _not_ initialize auto-configuration:"
" Cannot guarantee unique application identifiers!";
+ if (client_ == ILLEGAL_CLIENT) {
+ VSOMEIP_ERROR << "Couldn't acquire client identifier.";
+ return false;
+ }
} else {
// Client Identifier
client_t its_old_client = client_;
client_ = utility::request_client_id(its_configuration, name_, client_);
if (client_ == ILLEGAL_CLIENT) {
- VSOMEIP_ERROR << "Couldn't acquire client identifier";
+ VSOMEIP_ERROR << "Couldn't acquire client identifier from auto-configuration.";
return false;
}
+ std::string credentials = "";
+#ifndef _WIN32
+ credentials = " and UID/GID=" + std::to_string(getuid()) + "/" + std::to_string(getgid());
+#endif
VSOMEIP_INFO << "SOME/IP client identifier configured. "
<< "Using "
<< std::hex << std::setfill('0') << std::setw(4)
@@ -185,7 +223,7 @@ bool application_impl::init() {
<< " (was: "
<< std::hex << std::setfill('0') << std::setw(4)
<< its_old_client
- << ")";
+ << ")" << credentials;
// Routing
if (its_routing_host == "") {
@@ -213,47 +251,16 @@ bool application_impl::init() {
#ifdef USE_DLT
// Tracing
- std::shared_ptr<tc::trace_connector> its_trace_connector = tc::trace_connector::get();
- std::shared_ptr<cfg::trace> its_trace_cfg = its_configuration->get_trace();
-
- auto &its_channels_cfg = its_trace_cfg->channels_;
- for (auto it = its_channels_cfg.begin(); it != its_channels_cfg.end(); ++it) {
- its_trace_connector->add_channel(it->get()->id_, it->get()->name_);
- }
-
- auto &its_filter_rules_cfg = its_trace_cfg->filter_rules_;
- for (auto it = its_filter_rules_cfg.begin(); it != its_filter_rules_cfg.end(); ++it) {
- std::shared_ptr<cfg::trace_filter_rule> its_filter_rule_cfg = *it;
- tc::trace_connector::filter_rule_t its_filter_rule;
- tc::filter_type_e its_filter_type;
-
- if(its_filter_rule_cfg->type_ == "negative") {
- its_filter_type = tc::filter_type_e::NEGATIVE;
- } else {
- its_filter_type = tc::filter_type_e::POSITIVE;
- }
-
- tc::trace_connector::filter_rule_map_t its_filter_rule_map;
- its_filter_rule_map[tc::filter_criteria_e::SERVICES] = its_filter_rule_cfg->services_;
- its_filter_rule_map[tc::filter_criteria_e::METHODS] = its_filter_rule_cfg->methods_;
- its_filter_rule_map[tc::filter_criteria_e::CLIENTS] = its_filter_rule_cfg->clients_;
-
- its_filter_rule = std::make_pair(its_filter_type, its_filter_rule_map);
-
- its_trace_connector->add_filter_rule(it->get()->channel_, its_filter_rule);
- }
-
- bool enable_tracing = its_trace_cfg->is_enabled_;
- if (enable_tracing)
- its_trace_connector->init();
- its_trace_connector->set_enabled(enable_tracing);
-
- bool enable_sd_tracing = its_trace_cfg->is_sd_enabled_;
- its_trace_connector->set_sd_enabled(enable_sd_tracing);
+ std::shared_ptr<trace::connector_impl> its_connector
+ = trace::connector_impl::get();
+ std::shared_ptr<cfg::trace> its_trace_configuration
+ = its_configuration->get_trace();
+ its_connector->configure(its_trace_configuration);
#endif
VSOMEIP_INFO << "Application(" << (name_ != "" ? name_ : "unnamed")
- << ", " << std::hex << client_ << ") is initialized ("
+ << ", " << std::hex << std::setw(4) << std::setfill('0') << client_
+ << ") is initialized ("
<< std::dec << max_dispatchers_ << ", "
<< std::dec << max_dispatch_time_ << ").";
@@ -266,7 +273,7 @@ bool application_impl::init() {
signals_.add(SIGTERM);
// Register signal handler
- std::function<void(boost::system::error_code const &, int)> its_signal_handler =
+ auto its_signal_handler =
[this] (boost::system::error_code const &_error, int _signal) {
if (!_error) {
switch (_signal) {
@@ -284,19 +291,24 @@ bool application_impl::init() {
}
#endif
- auto its_plugins = configuration_->get_plugins(name_);
- auto its_app_plugin_info = its_plugins.find(plugin_type_e::APPLICATION_PLUGIN);
- if (its_app_plugin_info != its_plugins.end()) {
- for (auto its_library : its_app_plugin_info->second) {
- auto its_application_plugin = plugin_manager::get()->get_plugin(
- plugin_type_e::APPLICATION_PLUGIN, its_library);
- if (its_application_plugin) {
- VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
- << " Loading plug-in library: " << its_library << " succeeded!";
- std::dynamic_pointer_cast<application_plugin>(its_application_plugin)->
- on_application_state_change(name_, application_plugin_state_e::STATE_INITIALIZED);
+ if (configuration_) {
+ auto its_plugins = configuration_->get_plugins(name_);
+ auto its_app_plugin_info = its_plugins.find(plugin_type_e::APPLICATION_PLUGIN);
+ if (its_app_plugin_info != its_plugins.end()) {
+ for (auto its_library : its_app_plugin_info->second) {
+ auto its_application_plugin = plugin_manager::get()->get_plugin(
+ plugin_type_e::APPLICATION_PLUGIN, its_library);
+ if (its_application_plugin) {
+ VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
+ << " Loading plug-in library: " << its_library << " succeeded!";
+ std::dynamic_pointer_cast<application_plugin>(its_application_plugin)->
+ on_application_state_change(name_, application_plugin_state_e::STATE_INITIALIZED);
+ }
}
}
+ } else {
+ std::cerr << "Configuration module could not be loaded!" << std::endl;
+ std::exit(EXIT_FAILURE);
}
return is_initialized_;
@@ -313,6 +325,7 @@ void application_impl::start() {
}
#endif
const size_t io_thread_count = configuration_->get_io_thread_count(name_);
+ const int io_thread_nice_level = configuration_->get_io_thread_nice_level(name_);
{
std::lock_guard<std::mutex> its_lock(start_stop_mutex_);
if (io_.stopped()) {
@@ -336,8 +349,13 @@ void application_impl::start() {
}
stopped_ = false;
stopped_called_ = false;
- VSOMEIP_INFO << "Starting vsomeip application \"" << name_ << "\" using "
- << std::dec << io_thread_count << " threads";
+ VSOMEIP_INFO << "Starting vsomeip application \"" << name_ << "\" ("
+ << std::hex << std::setw(4) << std::setfill('0') << client_
+ << ") using " << std::dec << io_thread_count << " threads"
+#ifndef _WIN32
+ << " I/O nice " << io_thread_nice_level
+#endif
+ ;
start_caller_id_ = std::this_thread::get_id();
{
@@ -351,14 +369,14 @@ void application_impl::start() {
if (stop_thread_.joinable()) {
stop_thread_.join();
}
- stop_thread_= std::thread(&application_impl::shutdown, this);
+ stop_thread_= std::thread(&application_impl::shutdown, shared_from_this());
if (routing_)
routing_->start();
for (size_t i = 0; i < io_thread_count - 1; i++) {
std::shared_ptr<std::thread> its_thread
- = std::make_shared<std::thread>([this, i] {
+ = std::make_shared<std::thread>([this, i, io_thread_nice_level] {
VSOMEIP_INFO << "io thread id from application: "
<< std::hex << std::setw(4) << std::setfill('0')
<< client_ << " (" << name_ << ") is: " << std::hex
@@ -375,13 +393,15 @@ void application_impl::start() {
<< std::setfill('0') << i+1;
pthread_setname_np(pthread_self(),s.str().c_str());
}
+ if ((VSOMEIP_IO_THREAD_NICE_LEVEL != io_thread_nice_level) && (io_thread_nice_level != nice(io_thread_nice_level))) {
+ VSOMEIP_WARNING << "nice(" << io_thread_nice_level << ") failed " << errno << " for " << std::this_thread::get_id();
+ }
#endif
try {
io_.run();
#ifndef _WIN32
} catch (const boost::log::v2_mt_posix::system_error &e) {
- std::cerr << "catched boost::log system_error in I/O thread" << std::endl <<
- boost::current_exception_diagnostic_information();
+ std::cerr << "catched boost::log system_error in I/O thread" << std::endl;
#endif
} catch (const std::exception &e) {
VSOMEIP_ERROR << "application_impl::start() "
@@ -416,24 +436,29 @@ void application_impl::start() {
<< " TID: " << std::dec << static_cast<int>(syscall(SYS_gettid))
#endif
;
+#ifndef _WIN32
+ if ((VSOMEIP_IO_THREAD_NICE_LEVEL != io_thread_nice_level) && (io_thread_nice_level != nice(io_thread_nice_level))) {
+ VSOMEIP_WARNING << "nice(" << io_thread_nice_level << ") failed " << errno << " for " << std::this_thread::get_id();
+ }
+#endif
try {
io_.run();
+
+ if (stop_thread_.joinable()) {
+ stop_thread_.join();
+ }
+
+ utility::release_client_id(client_);
+ utility::auto_configuration_exit(client_, configuration_);
+
#ifndef _WIN32
} catch (const boost::log::v2_mt_posix::system_error &e) {
- std::cerr << "catched boost::log system_error in I/O thread" << std::endl <<
- boost::current_exception_diagnostic_information();
+ std::cerr << "catched boost::log system_error in I/O thread" << std::endl;
#endif
} catch (const std::exception &e) {
VSOMEIP_ERROR << "application_impl::start() catched exception: " << e.what();
}
- if (stop_thread_.joinable()) {
- stop_thread_.join();
- }
-
- utility::release_client_id(client_);
- utility::auto_configuration_exit(client_, configuration_);
-
{
std::lock_guard<std::mutex> its_lock_start_stop(block_stop_mutex_);
block_stopping_ = true;
@@ -460,7 +485,12 @@ void application_impl::start() {
void application_impl::stop() {
#ifndef _WIN32 // Gives serious problems under Windows.
- VSOMEIP_INFO << "Stopping vsomeip application \"" << name_ << "\".";
+ try {
+ VSOMEIP_INFO << "Stopping vsomeip application \"" << name_ << "\" ("
+ << std::hex << std::setw(4) << std::setfill('0') << client_ << ").";
+ } catch (const boost::log::v2_mt_posix::system_error &e) {
+ std::cerr << "catched boost::log system_error application_impl::stop" << std::endl;
+ }
#endif
bool block = true;
{
@@ -593,9 +623,7 @@ bool application_impl::is_available_unlocked(
bool is_available(false);
- const std::function<void(const std::map<instance_t,
- std::map<major_version_t, minor_version_t>>::const_iterator&)>
- check_major_minor = [&](const std::map<instance_t,
+ auto check_major_minor = [&](const std::map<instance_t,
std::map<major_version_t,
minor_version_t >>::const_iterator &_found_instance) {
auto found_major = _found_instance->second.find(_major);
@@ -839,7 +867,7 @@ void application_impl::notify_one(service_t _service, instance_t _instance,
client_t _client, bool _force) const {
if (routing_) {
routing_->notify_one(_service, _instance, _event, _payload, _client,
- _force, true);
+ _force, true, false);
}
}
@@ -848,7 +876,7 @@ void application_impl::notify_one(service_t _service, instance_t _instance,
client_t _client, bool _force, bool _flush) const {
if (routing_) {
routing_->notify_one(_service, _instance, _event, _payload, _client,
- _force, _flush);
+ _force, _flush, false);
}
}
@@ -1379,7 +1407,7 @@ void application_impl::on_availability(service_t _service, instance_t _instance,
}
}
- const std::function<void(const availability_major_minor_t&)> find_matching_handler =
+ auto find_matching_handler =
[&](const availability_major_minor_t& _av_ma_mi_it) {
auto found_major = _av_ma_mi_it.find(_major);
if (found_major != _av_ma_mi_it.end()) {
@@ -1650,8 +1678,8 @@ void application_impl::dispatch() {
<< " TID: " << std::dec << static_cast<int>(syscall(SYS_gettid))
#endif
;
+ std::unique_lock<std::mutex> its_lock(handlers_mutex_);
while (is_active_dispatcher(its_id)) {
- std::unique_lock<std::mutex> its_lock(handlers_mutex_);
if (is_dispatching_ && handlers_.empty()) {
dispatcher_condition_.wait(its_lock);
// Maybe woken up from main dispatcher
@@ -1680,7 +1708,6 @@ void application_impl::dispatch() {
}
}
}
- std::lock_guard<std::mutex> its_lock(handlers_mutex_);
if (is_dispatching_) {
std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
elapsed_dispatchers_.insert(its_id);
@@ -1768,29 +1795,34 @@ void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) {
its_dispatcher_timer.async_wait([this, its_id, its_sync_handler](const boost::system::error_code &_error) {
if (!_error) {
print_blocking_call(its_sync_handler);
- bool active_dispatcher_available(false);
- if (is_dispatching_) {
- std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
- active_dispatcher_available = has_active_dispatcher();
- }
- if (active_dispatcher_available) {
+ if (has_active_dispatcher()) {
std::lock_guard<std::mutex> its_lock(handlers_mutex_);
dispatcher_condition_.notify_all();
- } else if (is_dispatching_) {
+ } else {
// If possible, create a new dispatcher thread to unblock.
// If this is _not_ possible, dispatching is blocked until
// at least one of the active handler calls returns.
- std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
- if (dispatchers_.size() < max_dispatchers_ && is_dispatching_) {
- auto its_dispatcher = std::make_shared<std::thread>(
- std::bind(&application_impl::dispatch, shared_from_this()));
- dispatchers_[its_dispatcher->get_id()] = its_dispatcher;
- } else {
- VSOMEIP_ERROR << "Maximum number of dispatchers exceeded.";
+ while (is_dispatching_) {
+ if (dispatcher_mutex_.try_lock()) {
+ if (dispatchers_.size() < max_dispatchers_) {
+ if (is_dispatching_) {
+ auto its_dispatcher = std::make_shared<std::thread>(
+ std::bind(&application_impl::dispatch, shared_from_this()));
+ dispatchers_[its_dispatcher->get_id()] = its_dispatcher;
+ } else {
+ VSOMEIP_INFO << "Won't start new dispatcher "
+ "thread as Client=" << std::hex
+ << get_client() << " is shutting down";
+ }
+ } else {
+ VSOMEIP_ERROR << "Maximum number of dispatchers exceeded.";
+ }
+ dispatcher_mutex_.unlock();
+ break;
+ } else {
+ std::this_thread::yield();
+ }
}
- } else {
- VSOMEIP_INFO << "Won't start new dispatcher thread as Client="
- << std::hex << get_client() << " is shutting down";
}
}
});
@@ -1840,28 +1872,40 @@ void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) {
}
bool application_impl::has_active_dispatcher() {
- for (const auto &d : dispatchers_) {
- if (running_dispatchers_.find(d.first) == running_dispatchers_.end() &&
- elapsed_dispatchers_.find(d.first) == elapsed_dispatchers_.end()) {
- return true;
+ while (is_dispatching_) {
+ if (dispatcher_mutex_.try_lock()) {
+ for (const auto &d : dispatchers_) {
+ if (running_dispatchers_.find(d.first) == running_dispatchers_.end() &&
+ elapsed_dispatchers_.find(d.first) == elapsed_dispatchers_.end()) {
+ dispatcher_mutex_.unlock();
+ return true;
+ }
+ }
+ dispatcher_mutex_.unlock();
+ return false;
}
+ std::this_thread::yield();
}
return false;
}
bool application_impl::is_active_dispatcher(const std::thread::id &_id) {
- if (!is_dispatching_) {
- return is_dispatching_;
- }
- std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
- for (const auto &d : dispatchers_) {
- if (d.first != _id &&
- running_dispatchers_.find(d.first) == running_dispatchers_.end() &&
- elapsed_dispatchers_.find(d.first) == elapsed_dispatchers_.end()) {
- return false;
+ while (is_dispatching_) {
+ if (dispatcher_mutex_.try_lock()) {
+ for (const auto &d : dispatchers_) {
+ if (d.first != _id &&
+ running_dispatchers_.find(d.first) == running_dispatchers_.end() &&
+ elapsed_dispatchers_.find(d.first) == elapsed_dispatchers_.end()) {
+ dispatcher_mutex_.unlock();
+ return false;
+ }
+ }
+ dispatcher_mutex_.unlock();
+ return true;
}
+ std::this_thread::yield();
}
- return true;
+ return false;
}
void application_impl::remove_elapsed_dispatchers() {
@@ -1978,14 +2022,15 @@ void application_impl::shutdown() {
{
std::lock_guard<std::mutex> its_lock_start_stop(start_stop_mutex_);
for (auto t : io_threads_) {
- t->join();
+ if (t->joinable()) {
+ t->join();
+ }
}
io_threads_.clear();
}
#ifndef _WIN32
} catch (const boost::log::v2_mt_posix::system_error &e) {
- std::cerr << "catched boost::log system_error in stop thread" << std::endl <<
- boost::current_exception_diagnostic_information();
+ std::cerr << "catched boost::log system_error in stop thread" << std::endl;
#endif
} catch (const std::exception &e) {
VSOMEIP_ERROR << "application_impl::shutdown() catched exception: " << e.what();
@@ -2361,4 +2406,129 @@ void application_impl::register_async_subscription_handler(service_t _service,
register_message_handler(_service, _instance, ANY_METHOD - 1, handler);
}
+void application_impl::register_offer_acceptance_handler(
+ offer_acceptance_handler_t _handler) {
+ if (is_routing() && routing_) {
+ const auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ rm_impl->register_offer_acceptance_handler(_handler);
+ }
+}
+
+void application_impl::register_reboot_notification_handler(
+ reboot_notification_handler_t _handler) {
+ if (is_routing() && routing_) {
+ const auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ rm_impl->register_reboot_notification_handler(_handler);
+ }
+}
+
+void application_impl::set_offer_acceptance_required(
+ ip_address_t _address, const std::string _path, bool _enable) {
+ if (is_routing()) {
+ const boost::asio::ip::address its_address = _address.is_v4_ ?
+ static_cast<boost::asio::ip::address>(boost::asio::ip::address_v4(_address.address_.v4_)) :
+ static_cast<boost::asio::ip::address>(boost::asio::ip::address_v6(_address.address_.v6_));
+ configuration_->set_offer_acceptance_required(its_address, _path, _enable);
+ if (_enable && routing_) {
+ const auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ rm_impl->offer_acceptance_enabled(its_address);
+ }
+ }
+}
+
+vsomeip::application::offer_acceptance_map_type_t
+application_impl::get_offer_acceptance_required() {
+ offer_acceptance_map_type_t its_ret;
+ if (is_routing()) {
+ for (const auto& e : configuration_->get_offer_acceptance_required()) {
+ ip_address_t its_address;
+ its_address.is_v4_ = e.first.is_v4();
+ if (its_address.is_v4_) {
+ its_address.address_.v4_ = e.first.to_v4().to_bytes();
+ } else {
+ its_address.address_.v6_ = e.first.to_v6().to_bytes();
+ }
+ its_ret[its_address] = e.second;
+ }
+ }
+ return its_ret;
+}
+
+void application_impl::register_routing_ready_handler(
+ routing_ready_handler_t _handler) {
+ if (is_routing() && routing_) {
+ const auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ rm_impl->register_routing_ready_handler(_handler);
+ }
+}
+
+void application_impl::register_routing_state_handler(
+ routing_state_handler_t _handler) {
+ if (is_routing() && routing_) {
+ const auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ rm_impl->register_routing_state_handler(_handler);
+ }
+}
+
+bool application_impl::update_service_configuration(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled,
+ bool _offer) {
+ bool ret = false;
+ if (!is_routing_manager_host_) {
+ VSOMEIP_ERROR << __func__ << " is only intended to be called by "
+ "application acting as routing manager host";
+ } else if (!routing_) {
+ VSOMEIP_ERROR << __func__ << " routing is zero";
+ } else {
+ auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ if (rm_impl) {
+ if (_offer) {
+ ret = rm_impl->offer_service_remotely(_service, _instance,
+ _port, _reliable, _magic_cookies_enabled);
+ } else {
+ ret = rm_impl->stop_offer_service_remotely(_service, _instance,
+ _port, _reliable, _magic_cookies_enabled);
+ }
+ }
+ }
+ return ret;
+}
+
+void application_impl::update_security_policy_configuration(uint32_t _uid,
+ uint32_t _gid,
+ ::std::shared_ptr<policy> _policy,
+ std::shared_ptr<payload> _payload,
+ security_update_handler_t _handler) {
+ if (!is_routing()) {
+ VSOMEIP_ERROR << __func__ << " is only intended to be called by "
+ "application acting as routing manager host";
+ } else if (!routing_) {
+ VSOMEIP_ERROR << __func__ << " routing is zero";
+ } else {
+ auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ if (rm_impl) {
+ rm_impl->update_security_policy_configuration(_uid, _gid, _policy, _payload, _handler);
+ }
+ }
+}
+
+void application_impl::remove_security_policy_configuration(uint32_t _uid,
+ uint32_t _gid,
+ security_update_handler_t _handler) {
+ if (!is_routing()) {
+ VSOMEIP_ERROR << __func__ << " is only intended to be called by "
+ "application acting as routing manager host";
+ } else if (!routing_) {
+ VSOMEIP_ERROR << __func__ << " routing is zero";
+ } else {
+ auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
+ if (rm_impl) {
+ rm_impl->remove_security_policy_configuration(_uid, _gid, _handler);
+ }
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/service_discovery/include/entry_impl.hpp b/implementation/service_discovery/include/entry_impl.hpp
index db12a1e..b41a94c 100755
--- a/implementation/service_discovery/include/entry_impl.hpp
+++ b/implementation/service_discovery/include/entry_impl.hpp
@@ -40,7 +40,7 @@ public:
void set_instance(instance_t _instance);
major_version_t get_major_version() const;
- void set_major_version(major_version_t _version);
+ void set_major_version(major_version_t _major_version);
ttl_t get_ttl() const;
void set_ttl(ttl_t _ttl);
@@ -72,7 +72,7 @@ protected:
std::uint8_t index2_;
entry_impl();
- entry_impl(const entry_impl &entry_);
+ entry_impl(const entry_impl &_entry);
};
} // namespace sd
diff --git a/implementation/service_discovery/include/ip_option_impl.hpp b/implementation/service_discovery/include/ip_option_impl.hpp
index 1345835..a2a7660 100644
--- a/implementation/service_discovery/include/ip_option_impl.hpp
+++ b/implementation/service_discovery/include/ip_option_impl.hpp
@@ -17,7 +17,7 @@ class ip_option_impl: public option_impl {
public:
ip_option_impl();
virtual ~ip_option_impl();
- virtual bool operator ==(const ip_option_impl &_option) const;
+ virtual bool operator ==(const ip_option_impl &_other) const;
uint16_t get_port() const;
void set_port(uint16_t _port);
diff --git a/implementation/service_discovery/include/message_impl.hpp b/implementation/service_discovery/include/message_impl.hpp
index baca328..83d3a64 100755
--- a/implementation/service_discovery/include/message_impl.hpp
+++ b/implementation/service_discovery/include/message_impl.hpp
@@ -98,7 +98,7 @@ public:
void forced_initial_events_add(forced_initial_events_t _entry);
const std::vector<forced_initial_events_t> forced_initial_events_get();
- void set_initial_events_required(bool _initial_events);
+ void set_initial_events_required(bool _initial_events_required);
bool initial_events_required() const;
private:
diff --git a/implementation/service_discovery/include/runtime.hpp b/implementation/service_discovery/include/runtime.hpp
index f99fec8..670a7bb 100644
--- a/implementation/service_discovery/include/runtime.hpp
+++ b/implementation/service_discovery/include/runtime.hpp
@@ -10,6 +10,8 @@
namespace vsomeip {
+class configuration;
+
namespace sd {
class message_impl;
@@ -22,7 +24,8 @@ public:
}
virtual std::shared_ptr<service_discovery> create_service_discovery(
- service_discovery_host *_host) const = 0;
+ service_discovery_host *_host,
+ std::shared_ptr<vsomeip::configuration> _configuration) const = 0;
virtual std::shared_ptr<message_impl> create_message() const = 0;
};
diff --git a/implementation/service_discovery/include/runtime_impl.hpp b/implementation/service_discovery/include/runtime_impl.hpp
index dcdb7d7..0a9baaf 100644
--- a/implementation/service_discovery/include/runtime_impl.hpp
+++ b/implementation/service_discovery/include/runtime_impl.hpp
@@ -20,7 +20,8 @@ public:
virtual ~runtime_impl();
std::shared_ptr<service_discovery> create_service_discovery(
- service_discovery_host *_host) const;
+ service_discovery_host *_host,
+ std::shared_ptr<configuration> _configuration) const;
std::shared_ptr<message_impl> create_message() const;
};
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp
index 92d80d3..e1c3dc4 100644
--- a/implementation/service_discovery/include/service_discovery.hpp
+++ b/implementation/service_discovery/include/service_discovery.hpp
@@ -11,6 +11,7 @@
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/enumeration_types.hpp>
+#include <vsomeip/handler.hpp>
#include "../../routing/include/serviceinfo.hpp"
#include "../../endpoints/include/endpoint.hpp"
#include "../include/service_discovery_host.hpp"
@@ -26,7 +27,6 @@ public:
virtual ~service_discovery() {
}
- virtual std::shared_ptr<configuration> get_configuration() const = 0;
virtual boost::asio::io_service & get_io() = 0;
virtual void init() = 0;
@@ -72,6 +72,11 @@ public:
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
client_t _client, bool _accepted,
const std::shared_ptr<sd_message_identifier_t> &_sd_message_id) = 0;
+
+ virtual void register_offer_acceptance_handler(
+ vsomeip::offer_acceptance_handler_t _handler) = 0;
+ virtual void register_reboot_notification_handler(
+ reboot_notification_handler_t _handler) = 0;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index f9e8f29..9c346fd 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -31,7 +31,6 @@ public:
}
virtual boost::asio::io_service & get_io() = 0;
- virtual const std::shared_ptr<configuration> get_configuration() const = 0;
virtual std::shared_ptr<endpoint> create_service_discovery_endpoint(
const std::string &_address, uint16_t _port, bool _reliable) = 0;
@@ -90,7 +89,7 @@ public:
virtual bool has_identified(client_t _client, service_t _service,
instance_t _instance, bool _reliable) = 0;
- virtual std::chrono::steady_clock::time_point expire_subscriptions() = 0;
+ virtual std::chrono::steady_clock::time_point expire_subscriptions(bool _force) = 0;
virtual std::shared_ptr<serviceinfo> get_offered_service(
service_t _service, instance_t _instance) const = 0;
diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp
index 995cfbc..77dbae9 100644
--- a/implementation/service_discovery/include/service_discovery_impl.hpp
+++ b/implementation/service_discovery/include/service_discovery_impl.hpp
@@ -56,10 +56,10 @@ struct subscriber_t {
class service_discovery_impl: public service_discovery,
public std::enable_shared_from_this<service_discovery_impl> {
public:
- service_discovery_impl(service_discovery_host *_host);
+ service_discovery_impl(service_discovery_host *_host,
+ std::shared_ptr<configuration> _configuration);
virtual ~service_discovery_impl();
- std::shared_ptr<configuration> get_configuration() const;
boost::asio::io_service & get_io();
void init();
@@ -102,6 +102,10 @@ public:
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
client_t _client, bool _acknowledged,
const std::shared_ptr<sd_message_identifier_t> &_sd_message_id);
+
+ void register_offer_acceptance_handler(offer_acceptance_handler_t _handler);
+ void register_reboot_notification_handler(
+ reboot_notification_handler_t _handler);
private:
std::pair<session_t, bool> get_session(const boost::asio::ip::address &_address);
void increment_session(const boost::asio::ip::address &_address);
@@ -149,7 +153,9 @@ private:
void process_serviceentry(std::shared_ptr<serviceentry_impl> &_entry,
const std::vector<std::shared_ptr<option_impl> > &_options,
- bool _unicast_flag, std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes);
+ bool _unicast_flag,
+ std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes,
+ bool _accept_offers);
void process_offerservice_serviceentry(
service_t _service, instance_t _instance, major_version_t _major,
minor_version_t _minor, ttl_t _ttl,
@@ -210,7 +216,7 @@ private:
void stop_subscription_expiration_timer_unlocked();
void expire_subscriptions(const boost::system::error_code &_error);
- bool check_ipv4_address(boost::asio::ip::address its_address);
+ bool check_ipv4_address(const boost::asio::ip::address& its_address) const;
bool check_static_header_fields(
const std::shared_ptr<const message> &_message) const;
@@ -346,6 +352,7 @@ private:
private:
boost::asio::io_service &io_;
service_discovery_host *host_;
+ std::shared_ptr<configuration> configuration_;
boost::asio::ip::address unicast_;
uint16_t port_;
@@ -443,6 +450,12 @@ private:
std::mutex remote_offer_types_mutex_;
std::map<std::pair<service_t, instance_t>, remote_offer_type_e> remote_offer_types_;
std::map<boost::asio::ip::address, std::set<std::pair<service_t, instance_t>>> remote_offers_by_ip_;
+
+ reboot_notification_handler_t reboot_notification_handler_;
+ offer_acceptance_handler_t offer_acceptance_handler_;
+
+ std::mutex offer_mutex_;
+ std::mutex check_ttl_mutex_;
};
} // namespace sd
diff --git a/implementation/service_discovery/src/configuration_option_impl.cpp b/implementation/service_discovery/src/configuration_option_impl.cpp
index e9cf058..e09c7c9 100755
--- a/implementation/service_discovery/src/configuration_option_impl.cpp
+++ b/implementation/service_discovery/src/configuration_option_impl.cpp
@@ -100,7 +100,7 @@ bool configuration_option_impl::deserialize(vsomeip::deserializer *_from) {
is_successful = is_successful && _from->deserialize(l_itemLength);
if (l_itemLength > 0) {
is_successful = is_successful
- && _from->deserialize((uint8_t*) &l_item[0], l_itemLength);
+ && _from->deserialize(l_item, static_cast<std::size_t>(l_itemLength));
if (is_successful) {
size_t l_eqPos = l_item.find('='); //SWS_SD_00292
diff --git a/implementation/service_discovery/src/eventgroupentry_impl.cpp b/implementation/service_discovery/src/eventgroupentry_impl.cpp
index f5394be..17fd63b 100755
--- a/implementation/service_discovery/src/eventgroupentry_impl.cpp
+++ b/implementation/service_discovery/src/eventgroupentry_impl.cpp
@@ -150,37 +150,42 @@ bool eventgroupentry_impl::is_matching_subscribe(
// read out ip options of current and _other
std::vector<std::shared_ptr<ip_option_impl>> its_options_current;
std::vector<std::shared_ptr<ip_option_impl>> its_options_other;
+ const std::size_t its_options_size = _options.size();
for (const auto option_run : {0,1}) {
for (const auto option_index : options_[option_run]) {
- switch (_options[option_index]->get_type()) {
- case option_type_e::IP4_ENDPOINT:
- its_options_current.push_back(
- std::static_pointer_cast<ipv4_option_impl>(
- _options[option_index]));
- break;
- case option_type_e::IP6_ENDPOINT:
- its_options_current.push_back(
- std::static_pointer_cast<ipv6_option_impl>(
- _options[option_index]));
- break;
- default:
- break;
+ if (its_options_size > option_index) {
+ switch (_options[option_index]->get_type()) {
+ case option_type_e::IP4_ENDPOINT:
+ its_options_current.push_back(
+ std::static_pointer_cast<ipv4_option_impl>(
+ _options[option_index]));
+ break;
+ case option_type_e::IP6_ENDPOINT:
+ its_options_current.push_back(
+ std::static_pointer_cast<ipv6_option_impl>(
+ _options[option_index]));
+ break;
+ default:
+ break;
+ }
}
}
for (const auto option_index : _other.options_[option_run]) {
- switch (_options[option_index]->get_type()) {
- case option_type_e::IP4_ENDPOINT:
- its_options_other.push_back(
- std::static_pointer_cast<ipv4_option_impl>(
- _options[option_index]));
- break;
- case option_type_e::IP6_ENDPOINT:
- its_options_other.push_back(
- std::static_pointer_cast<ipv6_option_impl>(
- _options[option_index]));
- break;
- default:
- break;
+ if (its_options_size > option_index) {
+ switch (_options[option_index]->get_type()) {
+ case option_type_e::IP4_ENDPOINT:
+ its_options_other.push_back(
+ std::static_pointer_cast<ipv4_option_impl>(
+ _options[option_index]));
+ break;
+ case option_type_e::IP6_ENDPOINT:
+ its_options_other.push_back(
+ std::static_pointer_cast<ipv6_option_impl>(
+ _options[option_index]));
+ break;
+ default:
+ break;
+ }
}
}
}
diff --git a/implementation/service_discovery/src/message_impl.cpp b/implementation/service_discovery/src/message_impl.cpp
index 9d5c1ac..e3b54ec 100755
--- a/implementation/service_discovery/src/message_impl.cpp
+++ b/implementation/service_discovery/src/message_impl.cpp
@@ -196,17 +196,17 @@ bool message_impl::serialize(vsomeip::serializer *_to) const {
uint32_t entries_length = uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
is_successful = is_successful && _to->serialize(entries_length);
- for (auto it = entries_.begin(); it != entries_.end(); ++it)
- is_successful = is_successful && (*it)->serialize(_to);
+ for (const auto& its_entry : entries_)
+ is_successful = is_successful && its_entry && its_entry->serialize(_to);
uint32_t options_length = 0;
- for (auto its_option : options_)
- options_length += its_option->get_length()
- + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE;
+ for (const auto& its_option : options_)
+ options_length += its_option ? its_option->get_length()
+ + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE : 0;
is_successful = is_successful && _to->serialize(options_length);
- for (auto its_option : options_)
- is_successful = is_successful && its_option->serialize(_to);
+ for (const auto& its_option : options_)
+ is_successful = is_successful && its_option && its_option->serialize(_to);
return is_successful;
}
@@ -231,6 +231,14 @@ bool message_impl::deserialize(vsomeip::deserializer *_from) {
// backup the current remaining length
uint32_t save_remaining = uint32_t(_from->get_remaining());
+ if (!is_successful) {
+ // couldn't deserialize entries length
+ return is_successful;
+ } else if (entries_length > save_remaining) {
+ // not enough data available to deserialize entries array
+ is_successful = false;
+ return is_successful;
+ }
// set remaining bytes to length of entries array
_from->set_remaining(entries_length);
diff --git a/implementation/service_discovery/src/runtime_impl.cpp b/implementation/service_discovery/src/runtime_impl.cpp
index 90743b8..d72d034 100644
--- a/implementation/service_discovery/src/runtime_impl.cpp
+++ b/implementation/service_discovery/src/runtime_impl.cpp
@@ -25,8 +25,9 @@ runtime_impl::~runtime_impl() {
}
std::shared_ptr<service_discovery> runtime_impl::create_service_discovery(
- service_discovery_host *_host) const {
- return std::make_shared < service_discovery_impl > (_host);
+ service_discovery_host *_host,
+ std::shared_ptr<configuration> _configuration) const {
+ return std::make_shared < service_discovery_impl > (_host, _configuration);
}
std::shared_ptr<message_impl> runtime_impl::create_message() const {
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index 1f93559..de5f190 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -34,21 +34,22 @@
#include "../../routing/include/eventgroupinfo.hpp"
#include "../../routing/include/serviceinfo.hpp"
#include "../../plugin/include/plugin_manager.hpp"
+#include "../../utility/include/byteorder.hpp"
namespace vsomeip {
namespace sd {
-service_discovery_impl::service_discovery_impl(service_discovery_host *_host)
+service_discovery_impl::service_discovery_impl(service_discovery_host *_host,
+ std::shared_ptr<configuration> _configuration)
: io_(_host->get_io()),
host_(_host),
+ configuration_(_configuration),
port_(VSOMEIP_SD_DEFAULT_PORT),
reliable_(false),
- serializer_(
- std::make_shared<serializer>(
- host_->get_configuration()->get_buffer_shrink_threshold())),
- deserializer_(
- std::make_shared<deserializer>(
- host_->get_configuration()->get_buffer_shrink_threshold())),
+ serializer_(std::make_shared<serializer>(
+ configuration_->get_buffer_shrink_threshold())),
+ deserializer_(std::make_shared<deserializer>(
+ configuration_->get_buffer_shrink_threshold())),
ttl_timer_(_host->get_io()),
ttl_timer_runtime_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY / 2),
ttl_(VSOMEIP_SD_DEFAULT_TTL),
@@ -75,10 +76,6 @@ service_discovery_impl::service_discovery_impl(service_discovery_host *_host)
service_discovery_impl::~service_discovery_impl() {
}
-std::shared_ptr<configuration> service_discovery_impl::get_configuration() const {
- return host_->get_configuration();
-}
-
boost::asio::io_service & service_discovery_impl::get_io() {
return io_;
}
@@ -86,62 +83,55 @@ boost::asio::io_service & service_discovery_impl::get_io() {
void service_discovery_impl::init() {
runtime_ = std::dynamic_pointer_cast<sd::runtime>(plugin_manager::get()->get_plugin(plugin_type_e::SD_RUNTIME_PLUGIN, VSOMEIP_SD_LIBRARY));
- std::shared_ptr < configuration > its_configuration =
- host_->get_configuration();
- if (its_configuration) {
- unicast_ = its_configuration->get_unicast_address();
- sd_multicast_ = its_configuration->get_sd_multicast();
- boost::system::error_code ec;
- sd_multicast_address_ = boost::asio::ip::address::from_string(sd_multicast_, ec);
-
- port_ = its_configuration->get_sd_port();
- reliable_ = (its_configuration->get_sd_protocol()
- == "tcp");
- max_message_size_ = (reliable_ ? VSOMEIP_MAX_TCP_SD_PAYLOAD :
- VSOMEIP_MAX_UDP_SD_PAYLOAD);
-
- ttl_ = its_configuration->get_sd_ttl();
-
- // generate random initial delay based on initial delay min and max
- std::int32_t initial_delay_min =
- its_configuration->get_sd_initial_delay_min();
- if (initial_delay_min < 0) {
- initial_delay_min = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN;
- }
- std::int32_t initial_delay_max =
- its_configuration->get_sd_initial_delay_max();
- if (initial_delay_max < 0) {
- initial_delay_max = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX;
- }
- if (initial_delay_min > initial_delay_max) {
- const std::uint32_t tmp(initial_delay_min);
- initial_delay_min = initial_delay_max;
- initial_delay_max = tmp;
- }
-
- std::random_device r;
- std::mt19937 e(r());
- std::uniform_int_distribution<std::uint32_t> distribution(
- initial_delay_min, initial_delay_max);
- initial_delay_ = std::chrono::milliseconds(distribution(e));
-
-
- repetitions_base_delay_ = std::chrono::milliseconds(
- its_configuration->get_sd_repetitions_base_delay());
- repetitions_max_ = its_configuration->get_sd_repetitions_max();
- cyclic_offer_delay_ = std::chrono::milliseconds(
- its_configuration->get_sd_cyclic_offer_delay());
- offer_debounce_time_ = std::chrono::milliseconds(
- its_configuration->get_sd_offer_debounce_time());
- ttl_timer_runtime_ = cyclic_offer_delay_ / 2;
-
- ttl_factor_offers_ = its_configuration->get_ttl_factor_offers();
- ttl_factor_subscriptions_ = its_configuration->get_ttl_factor_subscribes();
- last_msg_received_timer_timeout_ = cyclic_offer_delay_
- + (cyclic_offer_delay_ / 10);
- } else {
- VSOMEIP_ERROR << "SD: no configuration found!";
+ unicast_ = configuration_->get_unicast_address();
+ sd_multicast_ = configuration_->get_sd_multicast();
+ boost::system::error_code ec;
+ sd_multicast_address_ = boost::asio::ip::address::from_string(sd_multicast_, ec);
+
+ port_ = configuration_->get_sd_port();
+ reliable_ = (configuration_->get_sd_protocol() == "tcp");
+ max_message_size_ = (reliable_ ? VSOMEIP_MAX_TCP_SD_PAYLOAD :
+ VSOMEIP_MAX_UDP_SD_PAYLOAD);
+
+ ttl_ = configuration_->get_sd_ttl();
+
+ // generate random initial delay based on initial delay min and max
+ std::int32_t initial_delay_min =
+ configuration_->get_sd_initial_delay_min();
+ if (initial_delay_min < 0) {
+ initial_delay_min = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN;
+ }
+ std::int32_t initial_delay_max =
+ configuration_->get_sd_initial_delay_max();
+ if (initial_delay_max < 0) {
+ initial_delay_max = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX;
}
+ if (initial_delay_min > initial_delay_max) {
+ const std::uint32_t tmp(initial_delay_min);
+ initial_delay_min = initial_delay_max;
+ initial_delay_max = tmp;
+ }
+
+ std::random_device r;
+ std::mt19937 e(r());
+ std::uniform_int_distribution<std::uint32_t> distribution(
+ initial_delay_min, initial_delay_max);
+ initial_delay_ = std::chrono::milliseconds(distribution(e));
+
+
+ repetitions_base_delay_ = std::chrono::milliseconds(
+ configuration_->get_sd_repetitions_base_delay());
+ repetitions_max_ = configuration_->get_sd_repetitions_max();
+ cyclic_offer_delay_ = std::chrono::milliseconds(
+ configuration_->get_sd_cyclic_offer_delay());
+ offer_debounce_time_ = std::chrono::milliseconds(
+ configuration_->get_sd_offer_debounce_time());
+ ttl_timer_runtime_ = cyclic_offer_delay_ / 2;
+
+ ttl_factor_offers_ = configuration_->get_ttl_factor_offers();
+ ttl_factor_subscriptions_ = configuration_->get_ttl_factor_subscribes();
+ last_msg_received_timer_timeout_ = cyclic_offer_delay_
+ + (cyclic_offer_delay_ / 10);
}
void service_discovery_impl::start() {
@@ -300,7 +290,7 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
if (its_offer_type == remote_offer_type_e::UNRELIABLE &&
!its_subscription->get_endpoint(true) &&
its_subscription->get_endpoint(false)) {
- if (its_subscription->get_endpoint(false)->is_connected()) {
+ if (its_subscription->get_endpoint(false)->is_established()) {
insert_subscription(its_message,
_service, _instance,
_eventgroup,
@@ -311,7 +301,7 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
} else if (its_offer_type == remote_offer_type_e::RELIABLE &&
its_subscription->get_endpoint(true) &&
!its_subscription->get_endpoint(false)) {
- if (its_subscription->get_endpoint(true)->is_connected()) {
+ if (its_subscription->get_endpoint(true)->is_established()) {
insert_subscription(its_message,
_service, _instance,
_eventgroup,
@@ -322,17 +312,17 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
} else if (its_offer_type == remote_offer_type_e::RELIABLE_UNRELIABLE &&
its_subscription->get_endpoint(true) &&
its_subscription->get_endpoint(false)) {
- if (its_subscription->get_endpoint(true)->is_connected() &&
- its_subscription->get_endpoint(false)->is_connected()) {
+ if (its_subscription->get_endpoint(true)->is_established() &&
+ its_subscription->get_endpoint(false)->is_established()) {
insert_subscription(its_message,
_service, _instance,
_eventgroup,
its_subscription, its_offer_type);
} else {
- if (!its_subscription->get_endpoint(true)->is_connected()) {
+ if (!its_subscription->get_endpoint(true)->is_established()) {
its_subscription->set_tcp_connection_established(false);
}
- if (!its_subscription->get_endpoint(false)->is_connected()) {
+ if (!its_subscription->get_endpoint(false)->is_established()) {
its_subscription->set_udp_connection_established(false);
}
}
@@ -446,13 +436,7 @@ void service_discovery_impl::unsubscribe_all(service_t _service, instance_t _ins
if (found_service != subscribed_.end()) {
auto found_instance = found_service->second.find(_instance);
if (found_instance != found_service->second.end()) {
- for (auto &its_eventgroup : found_instance->second) {
- for (auto its_client : its_eventgroup.second) {
- its_client.second->set_acknowledged(true);
- its_client.second->set_endpoint(nullptr, true);
- its_client.second->set_endpoint(nullptr, false);
- }
- }
+ found_instance->second.clear();
}
}
}
@@ -813,11 +797,15 @@ void service_discovery_impl::insert_offer_entries(
for (const auto its_service : _services) {
for (const auto its_instance : its_service.second) {
if ((!is_suspended_)
- && ((!is_diagnosis_) || (is_diagnosis_ && !host_->get_configuration()->is_someip(its_service.first, its_instance.first)))) {
+ && ((!is_diagnosis_)
+ || (is_diagnosis_
+ && !configuration_->is_someip(its_service.first,
+ its_instance.first)))) {
// Only insert services with configured endpoint(s)
if ((_ignore_phase || its_instance.second->is_in_mainphase())
&& (its_instance.second->get_endpoint(false)
- || its_instance.second->get_endpoint(true))) {
+ || its_instance.second->get_endpoint(true))
+ && its_instance.second->get_ttl() > 0) {
if (i >= _start) {
if (!insert_offer_service(_message, its_service.first,
its_instance.first, its_instance.second, its_size)) {
@@ -935,8 +923,7 @@ bool service_discovery_impl::insert_nack_subscription_on_resubscribe(std::shared
// Two entries: Stop subscribe & subscribe within one SD-Message
// One option: Both entries reference it
- const std::function<std::shared_ptr<eventgroupentry_impl>(ttl_t)> insert_entry
- = [&](ttl_t _ttl) {
+ auto insert_entry = [&](ttl_t _ttl) {
std::shared_ptr<eventgroupentry_impl> its_entry =
_message->create_eventgroup_entry();
// SUBSCRIBE_EVENTGROUP and STOP_SUBSCRIBE_EVENTGROUP are identical
@@ -955,7 +942,7 @@ bool service_discovery_impl::insert_nack_subscription_on_resubscribe(std::shared
if (_offer_type == remote_offer_type_e::UNRELIABLE &&
!its_reliable_endpoint && its_unreliable_endpoint) {
- if (its_unreliable_endpoint->is_connected()) {
+ if (its_unreliable_endpoint->is_established()) {
const std::uint16_t its_port = its_unreliable_endpoint->get_local_port();
if (its_port) {
std::shared_ptr<eventgroupentry_impl> its_stop_entry = insert_entry(0);
@@ -975,7 +962,7 @@ bool service_discovery_impl::insert_nack_subscription_on_resubscribe(std::shared
}
} else if (_offer_type == remote_offer_type_e::RELIABLE &&
its_reliable_endpoint && !its_unreliable_endpoint) {
- if (its_reliable_endpoint->is_connected()) {
+ if (its_reliable_endpoint->is_established()) {
const std::uint16_t its_port = its_reliable_endpoint->get_local_port();
if (its_port) {
std::shared_ptr<eventgroupentry_impl> its_stop_entry = insert_entry(0);
@@ -995,8 +982,8 @@ bool service_discovery_impl::insert_nack_subscription_on_resubscribe(std::shared
}
} else if (_offer_type == remote_offer_type_e::RELIABLE_UNRELIABLE &&
its_reliable_endpoint && its_unreliable_endpoint) {
- if (its_reliable_endpoint->is_connected() &&
- its_unreliable_endpoint->is_connected()) {
+ if (its_reliable_endpoint->is_established() &&
+ its_unreliable_endpoint->is_established()) {
const std::uint16_t its_reliable_port = its_reliable_endpoint->get_local_port();
const std::uint16_t its_unreliable_port = its_unreliable_endpoint->get_local_port();
if (its_reliable_port && its_unreliable_port) {
@@ -1021,10 +1008,10 @@ bool service_discovery_impl::insert_nack_subscription_on_resubscribe(std::shared
<< std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
}
} else {
- if (!its_reliable_endpoint->is_connected()) {
+ if (!its_reliable_endpoint->is_established()) {
_subscription->set_tcp_connection_established(false);
}
- if (!its_unreliable_endpoint->is_connected()) {
+ if (!its_unreliable_endpoint->is_established()) {
_subscription->set_udp_connection_established(false);
}
}
@@ -1127,6 +1114,7 @@ bool service_discovery_impl::send(bool _is_announcing) {
its_message = its_runtime->create_message();
its_messages.push_back(its_message);
+ std::lock_guard<std::mutex> its_lock(offer_mutex_);
services_t its_offers = host_->get_offered_services();
fill_message_with_offer_entries(its_runtime, its_message,
its_messages, its_offers, false);
@@ -1149,6 +1137,7 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
+ std::lock_guard<std::mutex> its_lock(check_ttl_mutex_);
std::lock_guard<std::mutex> its_session_lock(sessions_received_mutex_);
if(is_suspended_) {
@@ -1186,8 +1175,18 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
remove_remote_offer_type_by_ip(_sender);
host_->expire_subscriptions(_sender);
host_->expire_services(_sender);
+ if (reboot_notification_handler_) {
+ ip_address_t ip;
+ if (_sender.is_v4()) {
+ ip.address_.v4_ = _sender.to_v4().to_bytes();
+ ip.is_v4_ = true;
+ } else {
+ ip.address_.v6_ = _sender.to_v6().to_bytes();
+ ip.is_v4_ = false;
+ }
+ reboot_notification_handler_(ip);
+ }
}
-
std::vector < std::shared_ptr<option_impl> > its_options =
its_message->get_options();
@@ -1199,7 +1198,7 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
std::shared_ptr < message_impl > its_message_response
= its_runtime->create_message();
- const std::uint8_t its_required_acks =
+ std::uint8_t its_required_acks =
its_message->get_number_required_acks();
its_message_response->set_number_required_acks(its_required_acks);
std::shared_ptr<sd_message_identifier_t> its_message_id =
@@ -1215,27 +1214,66 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
const message_impl::entries_t::const_iterator its_end = its_entries.end();
bool is_stop_subscribe_subscribe(false);
+ bool offer_acceptance_queried(false);
+ bool accept_offers(false);
+ bool expired_services(false);
+
for (auto iter = its_entries.begin(); iter != its_end; iter++) {
+ if (!offer_acceptance_queried) {
+ if (offer_acceptance_handler_) {
+ ip_address_t ip;
+ if (configuration_->offer_acceptance_required(_sender)) {
+ if (_sender.is_v4()) {
+ ip.address_.v4_ = _sender.to_v4().to_bytes();
+ ip.is_v4_ = true;
+ } else {
+ ip.address_.v6_ = _sender.to_v6().to_bytes();
+ ip.is_v4_ = false;
+ }
+ accept_offers = offer_acceptance_handler_(ip);
+ if (!accept_offers && !expired_services) {
+
+ VSOMEIP_INFO << "service_discovery_impl::on_message: Do not accept offer / subscribe from: "
+ << std::hex << std::setw(4) << std::setfill('0') << _sender.to_string();
+
+ remove_remote_offer_type_by_ip(_sender);
+ host_->expire_subscriptions(_sender);
+ host_->expire_services(_sender);
+ expired_services = true;
+ }
+ } else {
+ accept_offers = true;
+ }
+ offer_acceptance_queried = true;
+ } else {
+ offer_acceptance_queried = true;
+ accept_offers = true;
+ }
+ }
if ((*iter)->is_service_entry()) {
std::shared_ptr < serviceentry_impl > its_service_entry =
std::dynamic_pointer_cast < serviceentry_impl
> (*iter);
bool its_unicast_flag = its_message->get_unicast_flag();
process_serviceentry(its_service_entry, its_options,
- its_unicast_flag, &its_resubscribes);
+ its_unicast_flag, &its_resubscribes, accept_offers);
} else {
- std::shared_ptr < eventgroupentry_impl > its_eventgroup_entry =
- std::dynamic_pointer_cast < eventgroupentry_impl
- > (*iter);
- bool force_initial_events(false);
- if (is_stop_subscribe_subscribe) {
- force_initial_events = true;
+ if (accept_offers) {
+ std::shared_ptr < eventgroupentry_impl > its_eventgroup_entry =
+ std::dynamic_pointer_cast < eventgroupentry_impl
+ > (*iter);
+ bool force_initial_events(false);
+ if (is_stop_subscribe_subscribe) {
+ force_initial_events = true;
+ }
+ is_stop_subscribe_subscribe = check_stop_subscribe_subscribe(
+ iter, its_end, its_message->get_options());
+ process_eventgroupentry(its_eventgroup_entry, its_options,
+ its_message_response, _destination,
+ its_message_id, is_stop_subscribe_subscribe, force_initial_events);
+ } else {
+ its_required_acks = 0;
}
- is_stop_subscribe_subscribe = check_stop_subscribe_subscribe(
- iter, its_end, its_message->get_options());
- process_eventgroupentry(its_eventgroup_entry, its_options,
- its_message_response, _destination,
- its_message_id, is_stop_subscribe_subscribe, force_initial_events);
}
}
@@ -1283,7 +1321,8 @@ void service_discovery_impl::process_serviceentry(
std::shared_ptr<serviceentry_impl> &_entry,
const std::vector<std::shared_ptr<option_impl> > &_options,
bool _unicast_flag,
- std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes) {
+ std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes,
+ bool _accept_offers) {
// Read service info from entry
entry_type_e its_type = _entry->get_type();
@@ -1365,17 +1404,19 @@ void service_discovery_impl::process_serviceentry(
its_major, its_minor, _unicast_flag);
break;
case entry_type_e::OFFER_SERVICE:
- process_offerservice_serviceentry(its_service, its_instance,
- its_major, its_minor, its_ttl,
- its_reliable_address, its_reliable_port,
- its_unreliable_address, its_unreliable_port, _resubscribes);
+ if (_accept_offers) {
+ process_offerservice_serviceentry(its_service, its_instance,
+ its_major, its_minor, its_ttl,
+ its_reliable_address, its_reliable_port,
+ its_unreliable_address, its_unreliable_port, _resubscribes);
+ }
break;
case entry_type_e::UNKNOWN:
default:
VSOMEIP_ERROR << "Unsupported serviceentry type";
}
- } else {
+ } else if (_accept_offers) {
std::shared_ptr<request> its_request = find_request(its_service, its_instance);
if (its_request) {
std::lock_guard<std::mutex> its_lock(requested_mutex_);
@@ -1491,7 +1532,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
if (its_subscription->is_acknowledged()) {
if (its_offer_type == remote_offer_type_e::UNRELIABLE) {
- if (its_unreliable && its_unreliable->is_connected()) {
+ if (its_unreliable && its_unreliable->is_established()) {
// 28 = 16 (subscription) + 12 (option)
check_space(28);
const std::size_t options_size_before =
@@ -1514,7 +1555,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
}
}
} else if (its_offer_type == remote_offer_type_e::RELIABLE) {
- if (its_reliable && its_reliable->is_connected()) {
+ if (its_reliable && its_reliable->is_established()) {
// 28 = 16 (subscription) + 12 (option)
check_space(28);
const std::size_t options_size_before =
@@ -1544,8 +1585,8 @@ void service_discovery_impl::process_offerservice_serviceentry(
}
} else if (its_offer_type == remote_offer_type_e::RELIABLE_UNRELIABLE) {
if (its_reliable && its_unreliable &&
- its_reliable->is_connected() &&
- its_unreliable->is_connected()) {
+ its_reliable->is_established() &&
+ its_unreliable->is_established()) {
// 40 = 16 (subscription) + 2x12 (option)
check_space(40);
const std::size_t options_size_before =
@@ -1566,7 +1607,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
static_cast<std::uint16_t>(
_resubscribes->back().first - 40);
}
- } else if (its_reliable && !its_reliable->is_connected()) {
+ } else if (its_reliable && !its_reliable->is_established()) {
its_client.second->set_tcp_connection_established(false);
// restart TCP endpoint if not connected
its_reliable->restart();
@@ -1597,7 +1638,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
}
// restart TCP endpoint if not connected
- if (its_reliable && !its_reliable->is_connected()) {
+ if (its_reliable && !its_reliable->is_established()) {
its_reliable->restart();
}
}
@@ -1735,14 +1776,14 @@ void service_discovery_impl::on_endpoint_connected(
its_subscription->get_endpoint(true));
const std::shared_ptr<const endpoint> its_unreliable_endpoint(
its_subscription->get_endpoint(false));
- if(its_reliable_endpoint && its_reliable_endpoint->is_connected()) {
+ if(its_reliable_endpoint && its_reliable_endpoint->is_established()) {
if(its_reliable_endpoint.get() == _endpoint.get()) {
// mark tcp as established
its_subscription->set_tcp_connection_established(true);
}
}
- if(its_unreliable_endpoint && its_unreliable_endpoint->is_connected()) {
- if(its_reliable_endpoint.get() == _endpoint.get()) {
+ if(its_unreliable_endpoint && its_unreliable_endpoint->is_established()) {
+ if(its_unreliable_endpoint.get() == _endpoint.get()) {
// mark udp as established
its_subscription->set_udp_connection_established(true);
}
@@ -2633,7 +2674,10 @@ void service_discovery_impl::serialize_and_send(
_message->set_session(its_session.first);
_message->set_reboot_flag(its_session.second);
if(!serializer_->serialize(_message.get())) {
- VSOMEIP_ERROR << "service_discovery_impl::serialize_and_send: serialization error.";
+ boost::system::error_code ec;
+ VSOMEIP_ERROR << "service_discovery_impl::serialize_and_send: serialization error."
+ << " Remote: " << _address.to_string(ec) << " session: 0x"
+ << std::hex << its_session.first;
return;
}
if (host_->send_to(endpoint_definition::get(_address, port_, reliable_, _message->get_service(), _message->get_instance()),
@@ -2660,7 +2704,10 @@ void service_discovery_impl::stop_ttl_timer() {
void service_discovery_impl::check_ttl(const boost::system::error_code &_error) {
if (!_error) {
- host_->update_routing_info(ttl_timer_runtime_);
+ {
+ std::lock_guard<std::mutex> its_lock(check_ttl_mutex_);
+ host_->update_routing_info(ttl_timer_runtime_);
+ }
start_ttl_timer();
}
}
@@ -2752,7 +2799,7 @@ void service_discovery_impl::send_subscriptions(service_t _service, instance_t _
= its_runtime->create_message();
if (its_reliable && its_unreliable) {
- if (its_reliable->is_connected() && its_unreliable->is_connected()) {
+ if (its_reliable->is_established() && its_unreliable->is_established()) {
insert_subscription(its_message, _service,
_instance, found_eventgroup.first,
found_client->second, its_offer_type);
@@ -2764,7 +2811,7 @@ void service_discovery_impl::send_subscriptions(service_t _service, instance_t _
}
} else {
if(_reliable) {
- if(endpoint->is_connected()) {
+ if(endpoint->is_established()) {
insert_subscription(its_message, _service,
_instance, found_eventgroup.first,
found_client->second, its_offer_type);
@@ -2775,7 +2822,7 @@ void service_discovery_impl::send_subscriptions(service_t _service, instance_t _
found_client->second->set_tcp_connection_established(false);
}
} else {
- if (endpoint->is_connected()) {
+ if (endpoint->is_established()) {
insert_subscription(its_message, _service,
_instance, found_eventgroup.first,
found_client->second, its_offer_type);
@@ -2827,47 +2874,39 @@ void service_discovery_impl::stop_subscription_expiration_timer_unlocked() {
void service_discovery_impl::expire_subscriptions(const boost::system::error_code &_error) {
if (!_error) {
- next_subscription_expiration_ = host_->expire_subscriptions();
+ next_subscription_expiration_ = host_->expire_subscriptions(false);
start_subscription_expiration_timer();
}
}
bool service_discovery_impl::check_ipv4_address(
- boost::asio::ip::address its_address) {
+ const boost::asio::ip::address& its_address) const {
//Check unallowed ipv4 address
bool is_valid = true;
- std::shared_ptr<configuration> its_configuration =
- host_->get_configuration();
-
- if(its_configuration) {
- boost::asio::ip::address_v4::bytes_type its_unicast_address =
- its_configuration.get()->get_unicast_address().to_v4().to_bytes();
- boost::asio::ip::address_v4::bytes_type endpoint_address =
- its_address.to_v4().to_bytes();
-
- //same address as unicast address of DUT not allowed
- if(its_unicast_address
- == endpoint_address) {
- VSOMEIP_ERROR << "Subscribers endpoint IP address is same as DUT's address! : "
- << its_address.to_string();
- is_valid = false;
- }
-
- // first 3 triples must match
- its_unicast_address[3] = 0x00;
- endpoint_address[3] = 0x00;
- if(its_unicast_address
- != endpoint_address) {
-#if 1
- VSOMEIP_ERROR<< "First 3 triples of subscribers endpoint IP address are not valid!";
-#endif
+ static const boost::asio::ip::address_v4::bytes_type its_unicast_address =
+ unicast_.to_v4().to_bytes();
+ const boost::asio::ip::address_v4::bytes_type endpoint_address =
+ its_address.to_v4().to_bytes();
+ static const boost::asio::ip::address_v4::bytes_type its_netmask =
+ configuration_->get_netmask().to_v4().to_bytes();
+
+ //same address as unicast address of DUT not allowed
+ if (its_unicast_address == endpoint_address) {
+ VSOMEIP_ERROR << "Subscriber's IP address is same as host's address! : "
+ << its_address;
+ is_valid = false;
+ } else {
+ const std::uint32_t self = VSOMEIP_BYTES_TO_LONG(its_unicast_address[0],
+ its_unicast_address[1], its_unicast_address[2], its_unicast_address[3]);
+ const std::uint32_t remote = VSOMEIP_BYTES_TO_LONG(endpoint_address[0],
+ endpoint_address[1], endpoint_address[2], endpoint_address[3]);
+ const std::uint32_t netmask = VSOMEIP_BYTES_TO_LONG(its_netmask[0],
+ its_netmask[1], its_netmask[2], its_netmask[3]);
+ if ((self & netmask) != (remote & netmask)) {
+ VSOMEIP_ERROR<< "Subscriber's IP isn't in the same subnet as host's IP: "
+ << its_address;
is_valid = false;
-
- } else {
-#if 0
- VSOMEIP_INFO << "First 3 triples of subscribers endpoint IP address are valid!";
-#endif
}
}
return is_valid;
@@ -3012,7 +3051,7 @@ void service_discovery_impl::on_offer_debounce_timer_expired(
for (services_t::iterator its_service = collected_offers_.begin();
its_service != collected_offers_.end(); its_service++) {
for (auto its_instance : its_service->second) {
- if (!host_->get_configuration()->is_someip(
+ if (!configuration_->is_someip(
its_service->first, its_instance.first)) {
non_someip_services.push_back(its_service);
}
@@ -3286,6 +3325,8 @@ bool service_discovery_impl::serialize_and_send_messages(
void service_discovery_impl::stop_offer_service(
service_t _service, instance_t _instance,
std::shared_ptr<serviceinfo> _info) {
+ std::lock_guard<std::mutex> its_lock(offer_mutex_);
+ _info->set_ttl(0);
bool stop_offer_required(false);
// delete from initial phase offers
{
@@ -3420,19 +3461,11 @@ bool service_discovery_impl::last_offer_shorter_half_offer_delay_ago() {
bool service_discovery_impl::check_source_address(
const boost::asio::ip::address &its_source_address) const {
bool is_valid = true;
- std::shared_ptr<configuration> its_configuration =
- host_->get_configuration();
-
- if(its_configuration) {
- boost::asio::ip::address its_unicast_address =
- its_configuration.get()->get_unicast_address();
- // check if source address is same as nodes unicast address
- if(its_unicast_address
- == its_source_address) {
- VSOMEIP_ERROR << "Source address of message is same as DUT's unicast address! : "
- << its_source_address.to_string();
- is_valid = false;
- }
+ // check if source address is same as nodes unicast address
+ if(unicast_ == its_source_address) {
+ VSOMEIP_ERROR << "Source address of message is same as DUT's unicast address! : "
+ << its_source_address.to_string();
+ is_valid = false;
}
return is_valid;
}
@@ -3502,8 +3535,10 @@ void service_discovery_impl::update_subscription_expiration_timer(
const std::chrono::steady_clock::time_point now =
std::chrono::steady_clock::now();
stop_subscription_expiration_timer_unlocked();
+
+ std::unique_lock<std::mutex> its_message_lock(_message->get_message_lock());
for (const auto &entry : _message->get_entries()) {
- if (entry->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP_ACK
+ if (entry && entry->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP_ACK
&& entry->get_ttl()) {
const std::chrono::steady_clock::time_point its_expiration = now
+ std::chrono::seconds(
@@ -3792,5 +3827,15 @@ service_discovery_impl::get_eventgroups_requiring_initial_events(
return its_acks;
}
+void service_discovery_impl::register_offer_acceptance_handler(
+ vsomeip::offer_acceptance_handler_t _handler) {
+ offer_acceptance_handler_ = _handler;
+}
+
+void service_discovery_impl::register_reboot_notification_handler(
+ reboot_notification_handler_t _handler) {
+ reboot_notification_handler_ = _handler;
+}
+
} // namespace sd
} // namespace vsomeip
diff --git a/implementation/tracing/include/channel_impl.hpp b/implementation/tracing/include/channel_impl.hpp
new file mode 100644
index 0000000..9034657
--- /dev/null
+++ b/implementation/tracing/include/channel_impl.hpp
@@ -0,0 +1,62 @@
+// Copyright (C) 2017 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/.
+
+#ifndef VSOMEIP_TRACING_CHANNEL_IMPL_HPP_
+#define VSOMEIP_TRACING_CHANNEL_IMPL_HPP_
+
+#include <atomic>
+#include <functional>
+#include <map>
+#include <mutex>
+#include <string>
+
+#include <vsomeip/trace.hpp>
+
+namespace vsomeip {
+namespace trace {
+
+typedef std::function<bool (service_t, instance_t, method_t)> filter_func_t;
+
+class channel_impl : public channel {
+public:
+ channel_impl(const std::string &_id, const std::string &_name);
+
+ std::string get_id() const;
+ std::string get_name() const;
+
+ filter_id_t add_filter(
+ const match_t &_match,
+ bool _is_positive);
+
+ filter_id_t add_filter(
+ const std::vector<match_t> &_matches,
+ bool _is_positive);
+
+ filter_id_t add_filter(
+ const match_t &_from, const match_t &_to,
+ bool _is_positive);
+
+ void remove_filter(
+ filter_id_t _id);
+
+ bool matches(service_t _service, instance_t _instance, method_t _method);
+
+private:
+ filter_id_t add_filter_intern(filter_func_t _func, bool _is_positive);
+
+ std::string id_;
+ std::string name_;
+
+ std::atomic<filter_id_t> current_filter_id_;
+
+ std::map<filter_id_t, filter_func_t> positive_;
+ std::map<filter_id_t, filter_func_t> negative_;
+ std::mutex mutex_; // protects positive_ & negative_
+};
+
+} // namespace trace
+} // namespace vsomeip
+
+#endif // VSOMEIP_TRACING_CHANNEL_IMPL_HPP_
diff --git a/implementation/tracing/include/connector_impl.hpp b/implementation/tracing/include/connector_impl.hpp
new file mode 100644
index 0000000..3234fed
--- /dev/null
+++ b/implementation/tracing/include/connector_impl.hpp
@@ -0,0 +1,81 @@
+// Copyright (C) 2014-2017 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/.
+
+#ifndef VSOMEIP_TC_TRACE_CONNECTOR_HPP
+#define VSOMEIP_TC_TRACE_CONNECTOR_HPP
+
+#ifdef USE_DLT
+#include <dlt/dlt.h>
+#endif
+
+#include <mutex>
+#include <vector>
+#include <map>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/export.hpp>
+#include <vsomeip/trace.hpp>
+
+#include "enumeration_types.hpp"
+#include "header.hpp"
+#include "../../endpoints/include/buffer.hpp"
+
+namespace vsomeip {
+
+namespace cfg {
+ struct trace;
+}
+
+namespace trace {
+
+class channel_impl;
+
+class connector_impl : public connector {
+public:
+ VSOMEIP_EXPORT static std::shared_ptr<connector_impl> get();
+
+ VSOMEIP_EXPORT connector_impl();
+ VSOMEIP_EXPORT virtual ~connector_impl();
+
+ VSOMEIP_EXPORT void configure(const std::shared_ptr<cfg::trace> &_configuration);
+ VSOMEIP_EXPORT void reset();
+
+ VSOMEIP_EXPORT void set_enabled(const bool _enabled);
+ VSOMEIP_EXPORT bool is_enabled() const;
+
+ VSOMEIP_EXPORT void set_sd_enabled(const bool _sd_enabled);
+ VSOMEIP_EXPORT bool is_sd_enabled() const;
+
+ VSOMEIP_EXPORT bool is_sd_message(const byte_t *_data, uint16_t _data_size) const;
+
+ VSOMEIP_EXPORT std::shared_ptr<channel> add_channel(const std::string &_id,
+ const std::string &_description);
+ VSOMEIP_EXPORT bool remove_channel(const std::string &_id);
+ VSOMEIP_EXPORT std::shared_ptr<channel> get_channel(const std::string &_id) const;
+
+ VSOMEIP_EXPORT void trace(const byte_t *_header, uint16_t _header_size,
+ const byte_t *_data, uint16_t _data_size);
+
+private:
+ bool is_enabled_;
+ bool is_sd_enabled_;
+ bool is_initialized_;
+
+ std::map<std::string, std::shared_ptr<channel_impl>> channels_;
+ mutable std::mutex channels_mutex_;
+
+#ifdef USE_DLT
+ std::map<std::string, std::shared_ptr<DltContext>> contexts_;
+ mutable std::mutex contexts_mutex_;
+#endif
+
+};
+
+} // namespace trace
+} // namespace vsomeip
+
+#endif // VSOMEIP_TC_TRACE_CONNECTOR_HPP
diff --git a/implementation/tracing/include/defines.hpp b/implementation/tracing/include/defines.hpp
index aadb44f..2325259 100644
--- a/implementation/tracing/include/defines.hpp
+++ b/implementation/tracing/include/defines.hpp
@@ -7,7 +7,9 @@
#define TRACING_INCLUDE_DEFINES_HPP_
#define VSOMEIP_TC_DEFAULT_CHANNEL_NAME "Trace Connector Network Logging"
-#define VSOMEIP_TC_DEFAULT_CHANNEL_ID "TC"
#define VSOMEIP_TC_DEFAULT_FILTER_TYPE "positive"
+#define VSOMEIP_TC_INSTANCE_POS_MIN 8
+#define VSOMEIP_TC_INSTANCE_POS_MAX 9
+
#endif /* TRACING_INCLUDE_DEFINES_HPP_ */
diff --git a/implementation/tracing/include/enumeration_types.hpp b/implementation/tracing/include/enumeration_types.hpp
index 82ed3c4..352ddd3 100644
--- a/implementation/tracing/include/enumeration_types.hpp
+++ b/implementation/tracing/include/enumeration_types.hpp
@@ -3,24 +3,18 @@
// 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/.
-#ifndef VSOMEIP_TC_ENUMERATION_TYPES_HPP
-#define VSOMEIP_TC_ENUMERATION_TYPES_HPP
+#ifndef VSOMEIP_TRACE_ENUMERATION_TYPES_HPP
+#define VSOMEIP_TRACE_ENUMERATION_TYPES_HPP
namespace vsomeip {
-namespace tc {
-
-enum class filter_criteria_e : uint8_t {
- SERVICES = 0x00,
- METHODS = 0x01,
- CLIENTS = 0x02,
-};
+namespace trace {
enum class filter_type_e : uint8_t {
NEGATIVE = 0x00,
POSITIVE = 0x01
};
-} // namespace tc
+} // namespace trace
} // namespace vsomeip
#endif // VSOMEIP_TC_ENUMERATION_TYPES_HPP
diff --git a/implementation/tracing/include/trace_header.hpp b/implementation/tracing/include/header.hpp
index 11ccbdd..55ec73e 100644
--- a/implementation/tracing/include/trace_header.hpp
+++ b/implementation/tracing/include/header.hpp
@@ -3,8 +3,8 @@
// 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/.
-#ifndef VSOMEIP_TC_TRACE_HEADER_HPP
-#define VSOMEIP_TC_TRACE_HEADER_HPP
+#ifndef VSOMEIP_TRACE_HEADER_HPP
+#define VSOMEIP_TRACE_HEADER_HPP
#include <memory>
@@ -18,7 +18,7 @@ namespace vsomeip {
class endpoint;
-namespace tc {
+namespace trace {
enum class protocol_e : uint8_t {
local = 0x0,
@@ -27,7 +27,7 @@ enum class protocol_e : uint8_t {
unknown = 0xFF
};
-struct trace_header {
+struct header {
bool prepare(const std::shared_ptr<endpoint> &_endpoint, bool _is_sending,
instance_t _instance);
bool prepare(const endpoint* _endpoint, bool _is_sending,
@@ -39,7 +39,7 @@ struct trace_header {
byte_t data_[VSOMEIP_TRACE_HEADER_SIZE];
};
-} // namespace tc
+} // namespace trace
} // namespace vsomeip
-#endif // VSOMEIP_TC_TRACE_HEADER_HPP
+#endif // VSOMEIP_TRACE_HEADER_HPP
diff --git a/implementation/tracing/include/trace_connector.hpp b/implementation/tracing/include/trace_connector.hpp
deleted file mode 100644
index ef36e29..0000000
--- a/implementation/tracing/include/trace_connector.hpp
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2014-2017 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/.
-
-#ifndef VSOMEIP_TC_TRACE_CONNECTOR_HPP
-#define VSOMEIP_TC_TRACE_CONNECTOR_HPP
-
-#include <vsomeip/primitive_types.hpp>
-#include <vsomeip/export.hpp>
-#include <boost/shared_ptr.hpp>
-#include <mutex>
-#include <vector>
-#include <map>
-
-#ifdef USE_DLT
-#include <dlt/dlt.h>
-#endif
-
-#include "enumeration_types.hpp"
-#include "trace_header.hpp"
-#include "../../endpoints/include/buffer.hpp"
-
-namespace vsomeip
-{
-namespace tc
-{
-
-class trace_connector {
-public:
- typedef uint16_t filter_expression_t;
- typedef std::vector<filter_expression_t> filter_expressions_t;
- typedef std::map<filter_criteria_e, filter_expressions_t> filter_rule_map_t;
- typedef std::pair<filter_type_e, filter_rule_map_t> filter_rule_t;
-
- typedef std::map<trace_channel_t, std::string> channels_t;
- typedef std::map<trace_channel_t, filter_rule_t> filter_rules_t;
-
-#ifdef USE_DLT
- typedef std::map<trace_channel_t, DltContext*> dlt_contexts_t;
-#endif
-
- VSOMEIP_EXPORT static std::shared_ptr<trace_connector> get();
-
- VSOMEIP_EXPORT trace_connector();
- VSOMEIP_EXPORT virtual ~trace_connector();
-
- VSOMEIP_EXPORT void init();
- VSOMEIP_EXPORT void reset();
-
- VSOMEIP_EXPORT void set_enabled(const bool _enabled);
- VSOMEIP_EXPORT bool is_enabled() const;
-
- VSOMEIP_EXPORT void set_sd_enabled(const bool _enabled);
- VSOMEIP_EXPORT bool is_sd_enabled() const;
-
- VSOMEIP_EXPORT bool is_sd_message(const byte_t *_data, uint16_t _data_size) const;
-
- VSOMEIP_EXPORT bool add_channel(const trace_channel_t &_id,const std::string &_name);
- VSOMEIP_EXPORT bool remove_channel(const trace_channel_t &_id);
-
- VSOMEIP_EXPORT bool add_filter_rule(const trace_channel_t &_channel_id,
- const filter_rule_t _filter_rule);
- VSOMEIP_EXPORT bool add_filter_expression(const trace_channel_t &_channel_id,
- const filter_criteria_e _criteria,
- const filter_expression_t _expression);
- VSOMEIP_EXPORT bool change_filter_expressions(const trace_channel_t &_channel_id,
- const filter_criteria_e _criteria,
- const filter_expressions_t _expressions);
- VSOMEIP_EXPORT bool remove_filter_rule(const trace_channel_t &_channel_id);
-
- VSOMEIP_EXPORT void trace(const byte_t *_header, uint16_t _header_size,
- const byte_t *_data, uint16_t _data_size);
-
- VSOMEIP_EXPORT channels_t get_channels();
- VSOMEIP_EXPORT filter_rules_t get_filter_rules();
- VSOMEIP_EXPORT filter_rule_t get_filter_rule(const trace_channel_t &_channel_id);
-
-private:
-
- bool apply_filter_rules(const byte_t *_data, const uint16_t _data_size,
- std::vector<trace_channel_t> &_send_msg_over_channels);
-
- bool filter_expressions_match(const filter_criteria_e _criteria,
- const filter_expressions_t _expressions,
- const byte_t *_data, const uint16_t _data_size);
-
- bool is_enabled_;
- bool is_sd_enabled_;
- bool is_initialized_;
-
- channels_t channels_;
- filter_rules_t filter_rules_;
-
-#ifdef USE_DLT
- dlt_contexts_t dlt_contexts_;
-#endif
-
- std::mutex channels_mutex_;
- std::mutex filter_rules_mutex_;
- std::mutex dlt_contexts_mutex;
-};
-
-} // namespace tc
-} // namespace vsomeip
-
-#endif // VSOMEIP_TC_TRACE_CONNECTOR_HPP
diff --git a/implementation/tracing/src/channel_impl.cpp b/implementation/tracing/src/channel_impl.cpp
new file mode 100644
index 0000000..58f67e6
--- /dev/null
+++ b/implementation/tracing/src/channel_impl.cpp
@@ -0,0 +1,273 @@
+// Copyright (C) 2017 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/.
+#include "../include/channel_impl.hpp"
+#include "../../logging/include/logger.hpp"
+
+namespace vsomeip {
+namespace trace {
+
+const filter_id_t FILTER_ID_ERROR(0);
+
+channel_impl::channel_impl(const std::string &_id, const std::string &_name)
+ : id_(_id), name_(_name), current_filter_id_(1) {
+}
+
+std::string channel_impl::get_id() const {
+ return id_;
+}
+
+std::string channel_impl::get_name() const {
+ return name_;
+}
+
+filter_id_t channel_impl::add_filter(
+ const match_t &_match, bool _is_positive) {
+
+ // Create a filter function
+ std::function<bool (service_t, instance_t, method_t)> its_filter_func;
+ if (std::get<0>(_match) != ANY_SERVICE) {
+ if (std::get<1>(_match) != ANY_INSTANCE) {
+ if (std::get<2>(_match) != ANY_METHOD) {
+ its_filter_func
+ = [_match](service_t _s, instance_t _i, method_t _m) {
+ return (std::get<0>(_match) == _s
+ && std::get<1>(_match) == _i
+ && std::get<2>(_match) == _m);
+ };
+ } else {
+ its_filter_func
+ = [_match](service_t _s, instance_t _i, method_t) {
+ return (std::get<0>(_match) == _s
+ && std::get<1>(_match) == _i);
+ };
+ }
+ } else {
+ if (std::get<2>(_match) != ANY_METHOD) {
+ its_filter_func
+ = [_match](service_t _s, instance_t, method_t _m) {
+ return (std::get<0>(_match) == _s
+ && std::get<1>(_match) == _m);
+ };
+ } else {
+ its_filter_func
+ = [_match](service_t _s, instance_t, method_t) {
+ return (std::get<0>(_match) == _s);
+ };
+ }
+ }
+ } else {
+ if (std::get<1>(_match) != ANY_INSTANCE) {
+ if (std::get<2>(_match) != ANY_METHOD) {
+ its_filter_func
+ = [_match](service_t, instance_t _i, method_t _m) {
+ return (std::get<1>(_match) == _i
+ && std::get<2>(_match) == _m);
+ };
+ } else {
+ its_filter_func
+ = [_match](service_t, instance_t _i, method_t) {
+ return (std::get<1>(_match) == _i);
+ };
+ }
+ } else {
+ if (std::get<2>(_match) != ANY_METHOD) {
+ its_filter_func
+ = [_match](service_t, instance_t, method_t _m) {
+ return (std::get<2>(_match) == _m);
+ };
+ } else {
+ its_filter_func
+ = [](service_t, instance_t, method_t) {
+ return true;
+ };
+ }
+ }
+ }
+
+ return add_filter_intern(its_filter_func, _is_positive);
+}
+
+filter_id_t channel_impl::add_filter(
+ const std::vector<match_t> &_matches, bool _is_positive) {
+ bool has_service(false);
+ bool has_instance(false);
+ bool has_method(false);
+
+ for (auto m : _matches) {
+ if (std::get<0>(m) != ANY_SERVICE) has_service = true;
+ if (std::get<1>(m) != ANY_INSTANCE) has_instance = true;
+ if (std::get<2>(m) != ANY_METHOD) has_method = true;
+ }
+
+ // Create a filter function
+ std::function<bool (service_t, instance_t, method_t)> its_filter_func;
+ if (has_service) {
+ if (has_instance) {
+ if (has_method) {
+ its_filter_func
+ = [_matches](service_t _s, instance_t _i, method_t _m) {
+ for (const auto &m : _matches) {
+ if ((std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE)
+ && (std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE)
+ && (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ } else {
+ its_filter_func
+ = [_matches](service_t _s, instance_t _i, method_t) {
+ for (const auto &m : _matches) {
+ if ((std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE)
+ && (std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ }
+ } else {
+ if (has_method) {
+ its_filter_func
+ = [_matches](service_t _s, instance_t, method_t _m) {
+ for (const auto &m : _matches) {
+ if ((std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE)
+ && (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ } else {
+ its_filter_func
+ = [_matches](service_t _s, instance_t, method_t) {
+ for (auto &m : _matches) {
+ if (std::get<0>(m) == _s || std::get<0>(m) == ANY_SERVICE) {
+ return true;
+ }
+ }
+ return false;
+ };
+ }
+ }
+ } else {
+ if (has_instance) {
+ if (has_method) {
+ its_filter_func
+ = [_matches](service_t, instance_t _i, method_t _m) {
+ for (auto &m : _matches) {
+ if ((std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE)
+ && (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ } else {
+ its_filter_func
+ = [_matches](service_t, instance_t _i, method_t) {
+ for (auto &m : _matches) {
+ if (std::get<1>(m) == _i || std::get<1>(m) == ANY_INSTANCE) {
+ return true;
+ }
+ }
+ return false;
+ };
+ }
+ } else {
+ if (has_method) {
+ its_filter_func
+ = [_matches](service_t, instance_t, method_t _m) {
+ for (auto &m : _matches) {
+ if (std::get<2>(m) == _m || std::get<2>(m) == ANY_METHOD) {
+ return true;
+ }
+ }
+ return false;
+ };
+ } else {
+ its_filter_func
+ = [](service_t, instance_t, method_t) {
+ return true;
+ };
+ }
+ }
+ }
+
+ return add_filter_intern(its_filter_func, _is_positive);
+}
+
+filter_id_t channel_impl::add_filter(
+ const match_t &_from, const match_t &_to, bool _is_positive) {
+
+ // Check usage of ANY_* which is forbidden here
+ if (std::get<0>(_from) == ANY_SERVICE ||
+ std::get<1>(_from) == ANY_INSTANCE ||
+ std::get<2>(_from) == ANY_METHOD ||
+ std::get<0>(_to) == ANY_SERVICE ||
+ std::get<1>(_to) == ANY_INSTANCE ||
+ std::get<2>(_to) == ANY_METHOD) {
+ VSOMEIP_ERROR << "Trace filter configuration error: "
+ "You must not use wildcards in range filters.";
+ return FILTER_ID_ERROR;
+ }
+
+ std::function<bool (service_t, instance_t, method_t)> its_filter_func
+ = [_from, _to](service_t _s, instance_t _i, method_t _m) {
+ return (std::get<0>(_from) <= _s && _s <= std::get<0>(_to)
+ && std::get<1>(_from) <= _i && _i <= std::get<1>(_to)
+ && std::get<2>(_from) <= _m && _m <= std::get<2>(_to));
+ };
+
+ return add_filter_intern(its_filter_func, _is_positive);
+}
+
+void channel_impl::remove_filter(filter_id_t _id) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ positive_.erase(_id);
+ negative_.erase(_id);
+}
+
+filter_id_t channel_impl::add_filter_intern(filter_func_t _func, bool _is_positive) {
+ filter_id_t its_id = current_filter_id_.fetch_add(1);
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (_is_positive)
+ positive_[its_id] = _func;
+ else
+ negative_[its_id] = _func;
+
+ return its_id;
+}
+
+bool channel_impl::matches(
+ service_t _service, instance_t _instance, method_t _method) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+
+ // If a negative filter matches --> drop!
+ for (auto &its_filter : negative_) {
+ if (its_filter.second(_service, _instance, _method)) {
+ return false;
+ }
+ }
+
+ // If no positive filter is defined --> forward!
+ if (positive_.size() == 0)
+ return true;
+
+ // If a positive filter matches --> forward!
+ for (auto &its_filter : positive_) {
+ if (its_filter.second(_service, _instance, _method)) {
+ return true;
+ }
+ }
+
+ // drop!
+ return false;
+}
+
+} // namespace trace
+} // namespace vsomeip
diff --git a/implementation/tracing/src/connector_impl.cpp b/implementation/tracing/src/connector_impl.cpp
new file mode 100644
index 0000000..f8655db
--- /dev/null
+++ b/implementation/tracing/src/connector_impl.cpp
@@ -0,0 +1,226 @@
+// Copyright (C) 2014-2017 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/.
+
+#include <vsomeip/constants.hpp>
+
+#include "../include/channel_impl.hpp"
+#include "../include/connector_impl.hpp"
+#include "../include/defines.hpp"
+#include "../../configuration/include/internal.hpp"
+#include "../../configuration/include/trace.hpp"
+#include "../../logging/include/logger.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+namespace vsomeip {
+namespace trace {
+
+const char *VSOMEIP_TC_DEFAULT_CHANNEL_ID = "TC";
+
+std::shared_ptr<connector_impl> connector_impl::get() {
+ static std::shared_ptr<connector_impl> instance = std::make_shared<connector_impl>();
+ return instance;
+}
+
+connector_impl::connector_impl() :
+ is_enabled_(false),
+ is_sd_enabled_(false),
+ is_initialized_(false) {
+
+ channels_[VSOMEIP_TC_DEFAULT_CHANNEL_ID]
+ = std::make_shared<channel_impl>(VSOMEIP_TC_DEFAULT_CHANNEL_ID,
+ VSOMEIP_TC_DEFAULT_CHANNEL_NAME);
+#ifdef USE_DLT
+ std::shared_ptr<DltContext> its_default_context
+ = std::make_shared<DltContext>();
+
+ contexts_[VSOMEIP_TC_DEFAULT_CHANNEL_ID] = its_default_context;
+ DLT_REGISTER_CONTEXT_LL_TS(*(its_default_context.get()),
+ VSOMEIP_TC_DEFAULT_CHANNEL_ID, VSOMEIP_TC_DEFAULT_CHANNEL_NAME,
+ DLT_LOG_INFO, DLT_TRACE_STATUS_ON);
+#endif
+}
+
+connector_impl::~connector_impl() {
+ reset();
+}
+
+void connector_impl::configure(const std::shared_ptr<cfg::trace> &_configuration) {
+ if (_configuration) {
+ is_enabled_ = _configuration->is_enabled_;
+ is_sd_enabled_ = _configuration->is_sd_enabled_;
+ }
+
+ if (is_enabled_) { // No need to create filters if tracing is disabled!
+ for (auto &its_channel : _configuration->channels_) {
+ if (!add_channel(its_channel->id_, its_channel->name_)) {
+ VSOMEIP_ERROR << "Channel " << its_channel->id_
+ << " has multiple definitions.";
+ }
+ }
+
+ for (auto &its_filter : _configuration->filters_) {
+ for (auto &its_channel : its_filter->channels_) {
+ std::shared_ptr<channel> its_channel_ptr = get_channel(its_channel);
+ if (its_channel_ptr) {
+ if (its_filter->is_range_) {
+ its_channel_ptr->add_filter(its_filter->matches_[0],
+ its_filter->matches_[1], its_filter->is_positive_);
+ } else {
+ its_channel_ptr->add_filter(its_filter->matches_,
+ its_filter->is_positive_);
+ }
+ }
+ }
+ }
+ }
+
+ VSOMEIP_INFO << "vsomeip tracing "
+ << (is_enabled_ ? "enabled " : "not enabled. ")
+ << ". vsomeip service discovery tracing "
+ << (is_sd_enabled_ ? "enabled " : "not enabled. ");
+}
+
+void connector_impl::reset() {
+#ifdef USE_DLT
+ std::lock_guard<std::mutex> its_contexts_lock(contexts_mutex_);
+ contexts_.clear();
+#endif
+ // reset to default
+ std::lock_guard<std::mutex> its_lock_channels(channels_mutex_);
+ channels_.clear();
+}
+
+void connector_impl::set_enabled(const bool _enabled) {
+ is_enabled_ = _enabled;
+}
+
+bool connector_impl::is_enabled() const {
+ return is_enabled_;
+}
+
+void connector_impl::set_sd_enabled(const bool _sd_enabled) {
+ is_sd_enabled_ = _sd_enabled;
+}
+
+bool connector_impl::is_sd_enabled() const {
+ return is_sd_enabled_;
+}
+
+bool connector_impl::is_sd_message(const byte_t *_data, uint16_t _data_size) const {
+ if (VSOMEIP_METHOD_POS_MAX < _data_size) {
+ return (_data[VSOMEIP_SERVICE_POS_MIN] == 0xFF && _data[VSOMEIP_SERVICE_POS_MAX] == 0xFF &&
+ _data[VSOMEIP_METHOD_POS_MIN] == 0x81 && _data[VSOMEIP_METHOD_POS_MAX] == 0x00);
+ }
+ return false;
+}
+
+std::shared_ptr<channel> connector_impl::add_channel(
+ const trace_channel_t &_id, const std::string &_name) {
+ std::lock_guard<std::mutex> its_channels_lock(channels_mutex_);
+
+ // check whether we already know the requested channel
+ if (channels_.find(_id) != channels_.end())
+ return nullptr;
+
+ // create new channel
+ std::shared_ptr<channel_impl> its_channel
+ = std::make_shared<channel_impl>(_id, _name);
+
+ // add channel
+ channels_[_id] = its_channel;
+
+ // register context
+#ifdef USE_DLT
+ std::lock_guard<std::mutex> its_contexts_lock(contexts_mutex_);
+ std::shared_ptr<DltContext> its_context = std::make_shared<DltContext>();
+ contexts_[_id] = its_context;
+ DLT_REGISTER_CONTEXT_LL_TS(*(its_context.get()), _id.c_str(), _name.c_str(),
+ DLT_LOG_INFO, DLT_TRACE_STATUS_ON);
+#endif
+
+ return its_channel;
+}
+
+bool connector_impl::remove_channel(const trace_channel_t &_id) {
+ if (_id == VSOMEIP_TC_DEFAULT_CHANNEL_ID) {
+ // the default channel can not be removed
+ return false;
+ }
+
+ std::lock_guard<std::mutex> its_channels_lock(channels_mutex_);
+ bool has_removed = (channels_.erase(_id) == 1);
+ if (has_removed) {
+ // unregister context
+#ifdef USE_DLT
+ std::lock_guard<std::mutex> its_contexts_lock(contexts_mutex_);
+ auto its_context = contexts_.find(_id);
+ if (its_context != contexts_.end()) {
+ DLT_UNREGISTER_CONTEXT(*(its_context->second.get()));
+ }
+#endif
+ }
+
+ return true;
+}
+
+std::shared_ptr<channel> connector_impl::get_channel(const std::string &_id) const {
+ std::lock_guard<std::mutex> its_channels_lock(channels_mutex_);
+ auto its_channel = channels_.find(_id);
+ return (its_channel != channels_.end() ? its_channel->second : nullptr);
+}
+
+void connector_impl::trace(const byte_t *_header, uint16_t _header_size,
+ const byte_t *_data, uint16_t _data_size) {
+#ifdef USE_DLT
+ if (!is_enabled_)
+ return;
+
+ if (_data_size == 0)
+ return; // no data
+
+ if (is_sd_message(_data, _data_size) && !is_sd_enabled_)
+ return; // tracing of service discovery messages is disabled!
+
+ service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+
+ // Instance is not part of the SOME/IP header, read it from the trace
+ // header
+ instance_t its_instance = VSOMEIP_BYTES_TO_WORD(
+ _header[VSOMEIP_TC_INSTANCE_POS_MIN],
+ _header[VSOMEIP_TC_INSTANCE_POS_MAX]);
+
+ method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+
+ // Forward to channel if the filter set of the channel allows
+ std::lock_guard<std::mutex> its_channels_lock(channels_mutex_);
+ std::lock_guard<std::mutex> its_contexts_lock(contexts_mutex_);
+ for (auto its_channel : channels_) {
+ if (its_channel.second->matches(its_service, its_instance, its_method)) {
+ auto its_context = contexts_.find(its_channel.second->get_id());
+ if (its_context != contexts_.end()) {
+ DLT_TRACE_NETWORK_SEGMENTED(*(its_context->second.get()),
+ DLT_NW_TRACE_IPC,
+ _header_size, static_cast<void *>(const_cast<byte_t *>(_header)),
+ _data_size, static_cast<void *>(const_cast<byte_t *>(_data)));
+ } else {
+ // This should never happen!
+ VSOMEIP_ERROR << "tracing: found channel without DLT context!";
+ }
+ }
+ }
+#else
+ (void)_header;
+ (void)_header_size;
+ (void)_data;
+ (void)_data_size;
+#endif
+}
+
+} // namespace trace
+} // namespace vsomeip
diff --git a/implementation/tracing/src/trace_header.cpp b/implementation/tracing/src/header.cpp
index 3ae1b10..2f4f3f8 100644
--- a/implementation/tracing/src/trace_header.cpp
+++ b/implementation/tracing/src/header.cpp
@@ -5,20 +5,20 @@
#include <cstring>
-#include "../include/trace_header.hpp"
+#include "../include/header.hpp"
#include "../../endpoints/include/endpoint.hpp"
#include "../../endpoints/include/client_endpoint.hpp"
#include "../../utility/include/byteorder.hpp"
namespace vsomeip {
-namespace tc {
+namespace trace {
-bool trace_header::prepare(const std::shared_ptr<endpoint> &_endpoint,
+bool header::prepare(const std::shared_ptr<endpoint> &_endpoint,
bool _is_sending, instance_t _instance) {
return prepare(_endpoint.get(), _is_sending, _instance);
}
-bool trace_header::prepare(const endpoint *_endpoint, bool _is_sending,
+bool header::prepare(const endpoint *_endpoint, bool _is_sending,
instance_t _instance) {
boost::asio::ip::address its_address;
unsigned short its_port(0);
@@ -51,9 +51,9 @@ bool trace_header::prepare(const endpoint *_endpoint, bool _is_sending,
return true;
}
-void trace_header::prepare(const boost::asio::ip::address_v4 &_address,
- std::uint16_t _port, protocol_e _protocol,
- bool _is_sending, instance_t _instance) {
+void header::prepare(const boost::asio::ip::address_v4 &_address,
+ std::uint16_t _port, protocol_e _protocol,
+ bool _is_sending, instance_t _instance) {
unsigned long its_address_as_long = _address.to_ulong();
data_[0] = VSOMEIP_LONG_BYTE3(its_address_as_long);
data_[1] = VSOMEIP_LONG_BYTE2(its_address_as_long);
@@ -67,5 +67,5 @@ void trace_header::prepare(const boost::asio::ip::address_v4 &_address,
data_[9] = VSOMEIP_WORD_BYTE0(_instance);
}
-} // namespace tc
+} // namespace trace
} // namespace vsomeip
diff --git a/implementation/tracing/src/trace_connector.cpp b/implementation/tracing/src/trace_connector.cpp
deleted file mode 100644
index 93f7d6e..0000000
--- a/implementation/tracing/src/trace_connector.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright (C) 2014-2017 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/.
-
-#include "../include/trace_connector.hpp"
-
-#include <vsomeip/constants.hpp>
-
-#include "../include/defines.hpp"
-#include "../../configuration/include/internal.hpp"
-
-namespace vsomeip {
-namespace tc {
-
-std::shared_ptr<trace_connector> trace_connector::get() {
- static std::shared_ptr<trace_connector> instance = std::make_shared<trace_connector>();
- return instance;
-}
-
-trace_connector::trace_connector() :
- is_enabled_(false),
- is_sd_enabled_(false),
- is_initialized_(false),
- channels_(),
- filter_rules_()
- {
- channels_.insert(std::make_pair(VSOMEIP_TC_DEFAULT_CHANNEL_ID, VSOMEIP_TC_DEFAULT_CHANNEL_NAME));
-}
-
-trace_connector::~trace_connector() {
- reset();
-}
-
-void trace_connector::init() {
-#ifdef USE_DLT
- if(!is_initialized_) {
- // register channels/contexts
- std::lock_guard<std::mutex> lock(dlt_contexts_mutex);
- for(auto it = channels_.begin(); it != channels_.end(); ++it) {
- DltContext *dlt_context = new DltContext();
- dlt_contexts_.insert(std::make_pair(it->first, dlt_context));
- DLT_REGISTER_CONTEXT_LL_TS(*dlt_context, it->first.c_str(), it->second.c_str(), DLT_LOG_INFO, DLT_TRACE_STATUS_ON);
- }
- }
-#endif
- is_initialized_ = true;
-}
-
-void trace_connector::reset() {
- std::lock_guard<std::mutex> its_lock_channels(channels_mutex_);
- std::lock_guard<std::mutex> its_lock_filter_rules(filter_rules_mutex_);
- std::lock_guard<std::mutex> its_lock_dlt_contexts(dlt_contexts_mutex);
-
-#ifdef USE_DLT
- // unregister channels/contexts
- for(auto it = dlt_contexts_.begin(); it != dlt_contexts_.end(); ++it) {
- DLT_UNREGISTER_CONTEXT(*it->second);
- delete it->second;
- }
- dlt_contexts_.clear();
-#endif
-
- // reset to default
-
- channels_.clear();
- channels_.insert(std::make_pair(VSOMEIP_TC_DEFAULT_CHANNEL_ID, VSOMEIP_TC_DEFAULT_CHANNEL_NAME));
-
- filter_rules_.clear();
-
- is_initialized_ = false;
-}
-
-void trace_connector::set_enabled(const bool _enabled) {
- is_enabled_ = _enabled;
-}
-
-bool trace_connector::is_enabled() const {
- return is_enabled_;
-}
-
-void trace_connector::set_sd_enabled(const bool _sd_enabled) {
- is_sd_enabled_ = _sd_enabled;
-}
-
-bool trace_connector::is_sd_enabled() const {
- return is_sd_enabled_;
-}
-
-bool trace_connector::is_sd_message(const byte_t *_data, uint16_t _data_size) const {
- if (VSOMEIP_METHOD_POS_MAX < _data_size) {
- return (_data[VSOMEIP_SERVICE_POS_MIN] == 0xFF && _data[VSOMEIP_SERVICE_POS_MAX] == 0xFF &&
- _data[VSOMEIP_METHOD_POS_MIN] == 0x81 && _data[VSOMEIP_METHOD_POS_MAX] == 0x00);
- }
- return false;
-}
-
-bool trace_connector::add_channel(const trace_channel_t &_id, const std::string &_name) {
- std::lock_guard<std::mutex> its_lock_channels(channels_mutex_);
- std::lock_guard<std::mutex> its_lock_dlt_contexts(dlt_contexts_mutex);
-
- bool channel_inserted = false;
- bool dlt_context_registered = false;
-
- // add channel
- channel_inserted = channels_.insert(std::make_pair(_id, _name)).second;
-
- // register context
-#ifdef USE_DLT
- if(channel_inserted) {
- DltContext *dlt_context = new DltContext();
- dlt_context_registered = dlt_contexts_.insert(std::make_pair(_id, dlt_context)).second;
- DLT_REGISTER_CONTEXT_LL_TS(*dlt_context, _id.c_str(), _name.c_str(), DLT_LOG_INFO, DLT_TRACE_STATUS_ON);
- }
-#endif
-
- return (channel_inserted && dlt_context_registered);
-}
-
-bool trace_connector::remove_channel(const trace_channel_t &_id) {
-
- if(_id == VSOMEIP_TC_DEFAULT_CHANNEL_ID) {
- // the default channel can not be removed
- return false;
- }
-
- std::lock_guard<std::mutex> its_lock_channels(channels_mutex_);
- std::lock_guard<std::mutex> its_lock_filter_rules(filter_rules_mutex_);
- std::lock_guard<std::mutex> its_lock_dlt_contexts(dlt_contexts_mutex);
-
- bool channel_removed = false;
- bool dlt_context_unregistered = false;
-
- // remove channel
- channel_removed = (channels_.erase(_id) == 1);
- if(channel_removed) {
-
- // unregister context
-#ifdef USE_DLT
- auto it = dlt_contexts_.find(_id);
- if(it != dlt_contexts_.end()) {
- DltContext *dlt_context = it->second;
- DLT_UNREGISTER_CONTEXT(*dlt_context);
- dlt_context_unregistered = true;
- }
-#endif
-
- // remove filter
- filter_rules_.erase(_id);
- }
- return (channel_removed && dlt_context_unregistered);
-}
-
-bool trace_connector::add_filter_rule(const trace_channel_t &_channel_id,
- const filter_rule_t _filter_rule) {
- std::lock_guard<std::mutex> its_lock_filter_rules(filter_rules_mutex_);
- std::lock_guard<std::mutex> its_lock_channels(channels_mutex_);
-
- // find channel
- auto it = channels_.find(_channel_id);
- if(it != channels_.end()) {
- // add filter rule
- return filter_rules_.insert(std::make_pair(_channel_id, _filter_rule)).second;
- }
- return false;
-}
-
-bool trace_connector::add_filter_expression(const trace_channel_t &_channel_id,
- const filter_criteria_e _criteria,
- const filter_expression_t _expression) {
- std::lock_guard<std::mutex> its_lock_filter_rules(filter_rules_mutex_);
-
- // find filter rule
- auto it_filter_rules = filter_rules_.find(_channel_id);
- if(it_filter_rules != filter_rules_.end()) {
- filter_rule_t its_filter_rule = it_filter_rules->second;
-
- // find filter criteria
- auto it_filter_rule_map = its_filter_rule.second.find(_criteria);
- if(it_filter_rule_map != its_filter_rule.second.end()) {
- // add expression
- it_filter_rule_map->second.push_back(_expression);
- return true;
- }
- }
- return false;
-}
-
-bool trace_connector::change_filter_expressions(const trace_channel_t &_channel_id,
- const filter_criteria_e _criteria,
- const filter_expressions_t _expressions) {
- std::lock_guard<std::mutex> its_lock_filter_rules(filter_rules_mutex_);
-
- // find filter rule
- auto it_filter_rules = filter_rules_.find(_channel_id);
- if(it_filter_rules != filter_rules_.end()) {
- filter_rule_t its_filter_rule = it_filter_rules->second;
-
- // find filter criteria
- auto it_filter_rule_map = its_filter_rule.second.find(_criteria);
- if(it_filter_rule_map != its_filter_rule.second.end()) {
- // change expressions
- it_filter_rule_map->second = _expressions;
- return true;
- }
- }
- return false;
-}
-
-bool trace_connector::remove_filter_rule(const trace_channel_t &_channel_id) {
- std::lock_guard<std::mutex> its_lock_filter_rules(filter_rules_mutex_);
-
- auto it = filter_rules_.find(_channel_id);
- if(it != filter_rules_.end()) {
- return (filter_rules_.erase(_channel_id) == 1);
- }
- return false;
-}
-
-void trace_connector::trace(const byte_t *_header, uint16_t _header_size,
- const byte_t *_data, uint16_t _data_size) {
-#ifdef USE_DLT
- if(!is_enabled_)
- return;
-
- std::lock_guard<std::mutex> its_lock_filter_rules(filter_rules_mutex_);
- std::lock_guard<std::mutex> its_lock_channels(channels_mutex_);
- std::lock_guard<std::mutex> its_lock_dlt_contexts(dlt_contexts_mutex);
-
- if (_data_size == 0)
- return; // no data
-
- if (is_sd_message(_data, _data_size) && !is_sd_enabled_)
- return; // tracing of service discovery messages is disabled!
-
- // check if filter rules match
- std::vector<trace_channel_t> its_channels;
- if (apply_filter_rules(_data, _data_size, its_channels)) {
- // send message over 'its_channels'
- for(auto channel_id : its_channels) {
- //find dlt context
- auto it = dlt_contexts_.find(channel_id);
- if (it != dlt_contexts_.end()) {
- DltContext *dlt_context = it->second;
- DLT_TRACE_NETWORK_SEGMENTED(*dlt_context,
- DLT_NW_TRACE_IPC,
- _header_size, static_cast<void *>(const_cast<byte_t *>(_header)),
- _data_size, static_cast<void *>(const_cast<byte_t *>(_data)));
- }
- }
- }
-#else
- (void)_header;
- (void)_header_size;
- (void)_data;
- (void)_data_size;
-#endif
-}
-
-trace_connector::channels_t trace_connector::get_channels() {
- std::lock_guard<std::mutex>its_lock_channels(channels_mutex_);
- return channels_;
-}
-
-trace_connector::filter_rules_t trace_connector::get_filter_rules() {
- std::lock_guard<std::mutex> its_lock_filters(filter_rules_mutex_);
- return filter_rules_;
-}
-
-trace_connector::filter_rule_t trace_connector::get_filter_rule(const trace_channel_t &_channel_id) {
- std::lock_guard<std::mutex> its_lock_filters(filter_rules_mutex_);
-
- // find filter
- auto it = filter_rules_.find(_channel_id);
- if (it != filter_rules_.end()) {
- return filter_rules_[_channel_id];
- } else {
- return filter_rule_t();
- }
-}
-
-bool trace_connector::apply_filter_rules(const byte_t *_data, uint16_t _data_size,
- std::vector<trace_channel_t> &_send_msg_over_channels) {
- _send_msg_over_channels.clear();
- if (filter_rules_.size() == 0) {
- // no filter rules -> send message over all channels to DLT
- for(auto it=channels_.begin(); it !=channels_.end(); ++it)
- _send_msg_over_channels.push_back(it->first);
- return true;
- }
-
- // loop through filter rules
- for(auto it_filter_rules = filter_rules_.begin(); it_filter_rules != filter_rules_.end(); ++it_filter_rules) {
- trace_channel_t its_channel = it_filter_rules->first;
- filter_rule_t its_filter_rule = it_filter_rules->second;
-
- // apply filter rule
- bool trace_message = true;
- filter_type_e its_filter_type = its_filter_rule.first;
- for(auto it_filter_rule_map = its_filter_rule.second.begin();
- it_filter_rule_map != its_filter_rule.second.end() && trace_message;
- ++it_filter_rule_map) {
-
- filter_criteria_e its_criteria = it_filter_rule_map->first;
- auto &its_filter_expressions = it_filter_rule_map->second;
-
- if(its_filter_expressions.size() != 0) {
- // check if filter expressions of filter criteria match
- const bool filter_rule_matches = filter_expressions_match(its_criteria, its_filter_expressions, _data, _data_size);
- trace_message = !(filter_rule_matches && its_filter_type == filter_type_e::NEGATIVE);
- }
- }
-
- if(trace_message) {
- //filter rule matches -> send message over 'its_channel' to DLT
- _send_msg_over_channels.push_back(its_channel);
- }
- }
- return (_send_msg_over_channels.size() != 0);
-}
-
-bool trace_connector::filter_expressions_match(
- const filter_criteria_e _criteria, const filter_expressions_t _expressions,
- const byte_t *_data, uint16_t _data_size) {
-
- // ignore empty filter expressions
- if (_expressions.size() == 0) {
- return true;
- }
-
- // extract criteria from message
- bool is_successful(false);
- byte_t first = 0;
- byte_t second = 0;
- switch (_criteria) {
- case filter_criteria_e::SERVICES:
- if (VSOMEIP_SERVICE_POS_MAX < _data_size) {
- first = _data[VSOMEIP_SERVICE_POS_MIN];
- second = _data[VSOMEIP_SERVICE_POS_MAX];
- is_successful = true;
- }
- break;
- case filter_criteria_e::METHODS:
- if (VSOMEIP_SERVICE_POS_MAX < _data_size) {
- first = _data[VSOMEIP_METHOD_POS_MIN];
- second = _data[VSOMEIP_METHOD_POS_MAX];
- is_successful = true;
- }
- break;
- case filter_criteria_e::CLIENTS:
- if (VSOMEIP_CLIENT_POS_MAX < _data_size) {
- first = _data[VSOMEIP_CLIENT_POS_MIN];
- second = _data[VSOMEIP_CLIENT_POS_MAX];
- is_successful = true;
- }
- break;
- default:
- break;
- }
-
- // if extraction is successful, filter
- if (is_successful) {
- bool filter_expressions_matches = false;
- for (auto it_expressions = _expressions.begin();
- it_expressions != _expressions.end() && !filter_expressions_matches;
- ++it_expressions) {
- filter_expression_t its_filter_expression = *it_expressions;
- uint16_t its_message_value = 0;
-
- its_message_value = (uint16_t)((its_message_value << 8) + first);
- its_message_value = (uint16_t)((its_message_value << 8) + second);
-
- filter_expressions_matches = (its_filter_expression == its_message_value);
- }
- return filter_expressions_matches;
- }
- return false;
-}
-
-} // namespace tc
-} // namespace vsomeip
diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp
index 34979a6..c5d8afe 100644
--- a/implementation/utility/include/utility.hpp
+++ b/implementation/utility/include/utility.hpp
@@ -11,13 +11,23 @@
#include <set>
#include <atomic>
+#ifdef _WIN32
+ #include <stdlib.h>
+ #define bswap_16(x) _byteswap_ushort(x)
+ #define bswap_32(x) _byteswap_ulong(x)
+#else
+ #include <byteswap.h>
+#endif
+
#include <vsomeip/enumeration_types.hpp>
#include <vsomeip/message.hpp>
#include "criticalsection.hpp"
+#include "../../../implementation/configuration/include/policy.hpp"
namespace vsomeip {
class configuration;
+struct policy;
class utility {
public:
@@ -124,13 +134,46 @@ public:
|| _type == message_type_e::MT_UNKNOWN);
}
+ static inline bool is_valid_return_code(return_code_e _code) {
+ return (_code == return_code_e::E_OK
+ || _code == return_code_e::E_NOT_OK
+ || _code == return_code_e::E_UNKNOWN_SERVICE
+ || _code == return_code_e::E_UNKNOWN_METHOD
+ || _code == return_code_e::E_NOT_READY
+ || _code == return_code_e::E_NOT_REACHABLE
+ || _code == return_code_e::E_TIMEOUT
+ || _code == return_code_e::E_WRONG_PROTOCOL_VERSION
+ || _code == return_code_e::E_WRONG_INTERFACE_VERSION
+ || _code == return_code_e::E_MALFORMED_MESSAGE
+ || _code == return_code_e::E_WRONG_MESSAGE_TYPE);
+ }
+
+ VSOMEIP_EXPORT static bool parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid, ::std::shared_ptr<policy> &_policy);
+ VSOMEIP_EXPORT static bool parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid);
+
private:
- static bool is_bigger_last_assigned_client_id(client_t _client, std::uint16_t _diagnosis_mask);
- static void set_max_assigned_client_id_without_diagnosis(client_t _client);
static void check_client_id_consistency();
+ static std::uint16_t get_max_number_of_clients(std::uint16_t _diagnosis_max);
+ static inline bool parse_range(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_first, uint16_t &_last);
+ static inline bool parse_id(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_id);
+ static inline bool get_struct_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length);
+ static inline bool get_union_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length);
+ static inline bool get_array_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length);
+ static inline bool is_range(const byte_t* &_buffer, uint32_t &_buffer_size);
+ static inline bool parse_id_item(const byte_t* &_buffer, uint32_t& parsed_ids_bytes, ranges_t& its_ranges, uint32_t &_buffer_size);
static std::atomic<std::uint16_t> its_configuration_refs__;
static std::uint16_t* used_client_ids__;
+
+ static const uint8_t uid_width_;
+ static const uint8_t gid_width_;
+ static const uint8_t id_width_;
+ static const uint8_t range_width_;
+ static const uint8_t skip_union_length_ ;
+ static const uint8_t skip_union_type_ ;
+ static const uint8_t skip_union_length_type_ ;
+ static const uint8_t skip_struct_length_;
+ static const uint8_t skip_array_length_;
};
} // namespace vsomeip
diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp
index 6b633ea..9919ea8 100644
--- a/implementation/utility/src/utility.cpp
+++ b/implementation/utility/src/utility.cpp
@@ -5,6 +5,7 @@
#ifdef _WIN32
#include <iostream>
+ #include <intrin.h>
#else
#include <dlfcn.h>
#include <signal.h>
@@ -101,9 +102,11 @@ static HANDLE its_descriptor(INVALID_HANDLE_VALUE);
bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_config) {
std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
+ const std::uint16_t its_max_clients =
+ get_max_number_of_clients(_config->get_diagnosis_mask());
const size_t its_shm_size = sizeof(configuration_data_t) +
- static_cast<std::uint16_t>(~_config->get_diagnosis_mask()) * sizeof(client_t);
+ (its_max_clients + 1) * sizeof(client_t);
#ifdef _WIN32
if (its_configuration_refs__ > 0) {
assert(configuration_data_mutex != INVALID_HANDLE_VALUE);
@@ -187,9 +190,9 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
the_configuration_data__->client_base_
= static_cast<unsigned short>((_config->get_diagnosis_address() << 8) & _config->get_diagnosis_mask());
- the_configuration_data__->max_clients_ = static_cast<std::uint16_t>(~_config->get_diagnosis_mask());
+ the_configuration_data__->max_clients_ = its_max_clients;
the_configuration_data__->max_used_client_ids_index_ = 1;
- the_configuration_data__->max_assigned_client_id_without_diagnosis_ = 0x00;
+ the_configuration_data__->max_assigned_client_id_ = 0x00;
the_configuration_data__->routing_manager_host_ = 0x0000;
// the clientid array starts right after the routing_manager_host_ struct member
used_client_ids__ = reinterpret_cast<unsigned short*>(
@@ -232,11 +235,13 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
// shm is already mapped into the process
its_configuration_refs__++;
} else {
- const mode_t previous_mask(::umask(static_cast<mode_t>(_config->get_umask())));
- int its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR | O_CREAT | O_EXCL,
+ int its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR | O_CREAT | O_EXCL,
static_cast<mode_t>(_config->get_permissions_shm()));
- ::umask(previous_mask);
- if (its_descriptor > -1) {
+ if (its_descriptor > -1) {
+ if (-1 == chmod(std::string("/dev/shm").append(utility::get_shm_name(_config)).c_str(),
+ static_cast<mode_t>(_config->get_permissions_uds()))) {
+ VSOMEIP_ERROR << __func__ << ": chmod: " << strerror(errno);
+ }
if (-1 == ftruncate(its_descriptor, its_shm_size)) {
VSOMEIP_ERROR << "utility::auto_configuration_init: "
"ftruncate failed: " << std::strerror(errno);
@@ -278,9 +283,9 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
the_configuration_data__->client_base_
= static_cast<unsigned short>((_config->get_diagnosis_address() << 8) & _config->get_diagnosis_mask());
- the_configuration_data__->max_clients_ = static_cast<std::uint16_t>(~_config->get_diagnosis_mask());
+ the_configuration_data__->max_clients_ = its_max_clients;
the_configuration_data__->max_used_client_ids_index_ = 1;
- the_configuration_data__->max_assigned_client_id_without_diagnosis_ = 0x00;
+ the_configuration_data__->max_assigned_client_id_ = 0x00;
the_configuration_data__->routing_manager_host_ = 0x0000;
// the clientid array starts right after the routing_manager_host_ struct member
used_client_ids__ = reinterpret_cast<unsigned short*>(
@@ -307,10 +312,18 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
}
}
} else if (errno == EEXIST) {
- const mode_t previous_mask(::umask(static_cast<mode_t>(_config->get_umask())));
its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR,
static_cast<mode_t>(_config->get_permissions_shm()));
- ::umask(previous_mask);
+
+ int retry_count = 8;
+ std::chrono::milliseconds retry_delay = std::chrono::milliseconds(10);
+ while (its_descriptor == -1 && retry_count-- > 0) {
+ std::this_thread::sleep_for(retry_delay);
+ its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR,
+ static_cast<mode_t>(_config->get_permissions_shm()));
+ retry_delay *= 2;
+ }
+
if (-1 == its_descriptor) {
VSOMEIP_ERROR << "utility::auto_configuration_init: "
"shm_open failed: " << std::strerror(errno);
@@ -376,8 +389,6 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
void utility::auto_configuration_exit(client_t _client,
const std::shared_ptr<configuration> &_config) {
std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
- const size_t its_shm_size = sizeof(configuration_data_t) +
- static_cast<std::uint16_t>(~_config->get_diagnosis_mask()) * sizeof(client_t);
if (the_configuration_data__) {
#ifdef _WIN32
// not manipulating data in shared memory, no need to take global mutex
@@ -412,6 +423,10 @@ void utility::auto_configuration_exit(client_t _client,
}
if (its_configuration_refs__ == 0) {
+ const std::uint16_t its_max_clients =
+ get_max_number_of_clients(_config->get_diagnosis_mask());
+ const size_t its_shm_size = sizeof(configuration_data_t) +
+ (its_max_clients + 1) * sizeof(client_t);
if (-1 == ::munmap(the_configuration_data__, its_shm_size)) {
VSOMEIP_ERROR << "utility::auto_configuration_exit: "
"munmap failed: " << std::strerror(errno);
@@ -586,16 +601,20 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
if (use_autoconfig) {
if (_client == ILLEGAL_CLIENT || is_used_client_id(_client, _config)) {
- _client = the_configuration_data__->client_base_;
+ if (the_configuration_data__->max_assigned_client_id_ != 0x00) {
+ _client = the_configuration_data__->max_assigned_client_id_;
+ } else {
+ _client = the_configuration_data__->client_base_;
+ }
}
int increase_count = 0;
- while (is_used_client_id(_client, _config)
- || !is_bigger_last_assigned_client_id(_client, _config->get_diagnosis_mask())
- || _config->is_configured_client_id(_client)) {
- if ((_client & the_configuration_data__->max_clients_)
- + 1 > the_configuration_data__->max_clients_) {
+
+ while (_client <= the_configuration_data__->max_assigned_client_id_
+ || _config->is_configured_client_id(_client)
+ || is_used_client_id(_client, _config)) {
+ if (_client + 1 > used_client_ids__[0] + the_configuration_data__->max_clients_) {
_client = the_configuration_data__->client_base_;
- the_configuration_data__->max_assigned_client_id_without_diagnosis_ = 0;
+ the_configuration_data__->max_assigned_client_id_ = the_configuration_data__->client_base_;
} else {
_client++;
increase_count++;
@@ -614,7 +633,7 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
}
}
}
- set_max_assigned_client_id_without_diagnosis(_client);
+ the_configuration_data__->max_assigned_client_id_ = _client;
}
if (set_client_as_manager_host) {
@@ -731,19 +750,343 @@ void utility::set_routing_manager_host(client_t _client) {
#endif
}
-bool utility::is_bigger_last_assigned_client_id(client_t _client, std::uint16_t _diagnosis_mask) {
- return _client
- > ((the_configuration_data__->client_base_ & _diagnosis_mask)
- + the_configuration_data__->max_assigned_client_id_without_diagnosis_);
+
+inline bool utility::get_struct_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) {
+ uint32_t its_length = 0;
+ bool length_field_deployed(false);
+ // [TR_SOMEIP_00080] d If the length of the length field is not specified, a length of 0
+ // has to be assumed and no length field is in the message.
+ if (length_field_deployed) {
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_length, _buffer, sizeof(uint32_t));
+ _length = bswap_32(its_length);
+ _buffer_size -= skip_struct_length_;
+ _buffer += skip_struct_length_;
+ return true;
+ }
+ } else {
+ _length = 0;
+ return true;
+ }
+
+ return false;
+}
+
+inline bool utility::get_union_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) {
+ uint32_t its_length = 0;
+
+ // [TR_SOMEIP_00125] d If the Interface Specification does not specify the length of the
+ // length field for a union, 32 bit length of the length field shall be used.
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_length, _buffer, sizeof(uint32_t));
+ _length = bswap_32(its_length);
+ _buffer_size -= skip_union_length_;
+ _buffer += skip_union_length_;
+ return true;
+ }
+ return false;
}
-void utility::set_max_assigned_client_id_without_diagnosis(client_t _client) {
- const std::uint16_t its_client_id_without_diagnosis =
- static_cast<std::uint16_t>(_client
- & the_configuration_data__->max_clients_);
- the_configuration_data__->max_assigned_client_id_without_diagnosis_ =
- static_cast<std::uint16_t>(its_client_id_without_diagnosis
- % the_configuration_data__->max_clients_);
+inline bool utility::get_array_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) {
+ uint32_t its_length = 0;
+
+ // [TR_SOMEIP_00106] d The layout of arrays with dynamic length basically is based on
+ // the layout of fixed length arrays. To determine the size of the array the serialization
+ // adds a length field (default length 32 bit) in front of the data, which counts the bytes
+ // of the array. The length does not include the size of the length field. Thus, when
+ // transporting an array with zero elements the length is set to zero.
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_length, _buffer, sizeof(uint32_t));
+ _length = bswap_32(its_length);
+ _buffer_size -= skip_array_length_;
+ _buffer += skip_array_length_;
+ return true;
+ }
+ return false;
+}
+
+inline bool utility::is_range(const byte_t* &_buffer, uint32_t &_buffer_size) {
+ uint32_t its_type = 0;
+
+ // [TR_SOMEIP_00128] If the Interface Specification does not specify the length of the
+ // type field of a union, 32 bit length of the type field shall be used.
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_type, _buffer, sizeof(uint32_t));
+ its_type = bswap_32(its_type);
+ _buffer_size -= skip_union_type_;
+ _buffer += skip_union_type_;
+ if (its_type == 0x02) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
+inline bool utility::parse_id_item(const byte_t* &_buffer, uint32_t& parsed_ids_bytes, ranges_t& its_ranges, uint32_t &_buffer_size) {
+ // get "union IdItem" length
+ uint32_t iditem_length = 0;
+ if (get_union_length(_buffer, _buffer_size, iditem_length)) {
+ // determine type of union
+ uint16_t its_first = 0;
+ uint16_t its_last = 0;
+ if (is_range(_buffer, _buffer_size)) {
+ // get range of instance IDs "struct IdRange" length
+ uint32_t range_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, range_length)) {
+ // read first and last instance range
+ if (parse_range(_buffer, _buffer_size, its_first, its_last)) {
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ } else {
+ return false;
+ }
+ }
+ } else {
+ // a single instance ID
+ if (parse_id(_buffer, _buffer_size, its_first)) {
+ if (its_first != ANY_METHOD) {
+ if (its_first != 0x00) {
+ its_last = its_first;
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ } else {
+ its_first = 0x01;
+ its_last = 0xFFFE;
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ }
+ }
+ parsed_ids_bytes += (skip_union_length_type_ + iditem_length);
+ }
+ return true;
+}
+
+inline bool utility::parse_range(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_first, uint16_t &_last){
+ uint16_t its_first = 0;
+ uint16_t its_last = 0;
+
+ if (_buffer_size >= sizeof(uint16_t) * 2) {
+ if (parse_id(_buffer, _buffer_size, its_first)) {
+ _first = its_first;
+ }
+ if (parse_id(_buffer, _buffer_size, its_last)) {
+ _last = its_last;
+ }
+ if (_first != _last
+ && (_first == ANY_METHOD || _last == ANY_METHOD)) {
+ return false;
+ }
+ if (_first != 0x0 && _last != 0x00
+ && _first <= _last) {
+ if (_first == ANY_METHOD &&
+ _last == ANY_METHOD) {
+ _first = 0x01;
+ _last = 0xFFFE;
+ }
+ return true;
+ } else {
+ if (_first == 0x00 && _last > _first
+ && _last != ANY_METHOD) {
+ _first = 0x01;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+}
+
+inline bool utility::parse_id(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_id) {
+ uint16_t its_id = 0;
+ if (_buffer_size >= sizeof(uint16_t)) {
+ std::memcpy(&its_id, _buffer, sizeof(uint16_t));
+ _id = bswap_16(its_id);
+ _buffer_size -= id_width_;
+ _buffer += id_width_;
+ return true;
+ }
+ return false;
+}
+
+bool utility::parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid) {
+ uint32_t its_uid = 0xffffffff;
+ uint32_t its_gid = 0xffffffff;
+
+ if (_buffer_size >= sizeof(uint32_t) * 2) {
+ std::memcpy(&its_uid, _buffer, sizeof(uint32_t));
+ _uid = bswap_32(its_uid);
+
+ std::memcpy(&its_gid, _buffer + sizeof(uint32_t), sizeof(uint32_t));
+ _gid = bswap_32(its_gid);
+
+ _buffer_size -= (uid_width_ + gid_width_);
+ _buffer += (uid_width_ + gid_width_);
+ return true;
+ }
+ return false;
+}
+
+bool utility::parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid, ::std::shared_ptr<policy> &_policy) {
+ uint32_t its_uid = 0xffffffff;
+ uint32_t its_gid = 0xffffffff;
+ bool has_error(false);
+
+ // get user ID String
+ if (parse_uid_gid(_buffer, _buffer_size, its_uid, its_gid)) {
+ _uid = its_uid;
+ _gid = its_gid;
+
+ // policy elements
+ std::pair<uint32_t, uint32_t> its_uid_range, its_gid_range;
+ std::set<std::pair<uint32_t, uint32_t>> its_uids, its_gids;
+
+ // fill uid and gid range
+ std::get<0>(its_uid_range) = its_uid;
+ std::get<1>(its_uid_range) = its_uid;
+ std::get<0>(its_gid_range) = its_gid;
+ std::get<1>(its_gid_range) = its_gid;
+ its_uids.insert(its_uid_range);
+ its_gids.insert(its_gid_range);
+
+ _policy->ids_.insert(std::make_pair(its_uids, its_gids));
+ _policy->allow_who_ = true;
+ _policy->allow_what_ = true;
+
+ // get struct AclUpdate
+ uint32_t acl_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, acl_length)) {
+ // get requests array length
+ uint32_t requests_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, requests_array_length)) {
+ // loop through requests array consisting of n x "struct Request"
+ uint32_t parsed_req_bytes = 0;
+ while (parsed_req_bytes + skip_struct_length_ <= requests_array_length) {
+ // get request struct length
+ uint32_t req_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, req_length)) {
+ if (req_length != 0)
+ parsed_req_bytes += skip_struct_length_;
+
+ uint16_t its_service_id = 0;
+ ids_t its_instance_method_ranges;
+ // get serviceID
+ if (!parse_id(_buffer, _buffer_size, its_service_id)) {
+ has_error = true;
+ } else {
+ if (its_service_id == 0x00
+ || its_service_id == 0xFFFF) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with service ID: 0x"
+ << its_service_id << " is not allowed!";
+ return false;
+ }
+ // add length of serviceID
+ parsed_req_bytes += id_width_;
+ }
+
+ // get instances array length
+ uint32_t instances_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, instances_array_length)) {
+ // loop trough instances array consisting of n x "struct Instance"
+ uint32_t parsed_inst_bytes = 0;
+ while (parsed_inst_bytes + skip_struct_length_ <= instances_array_length) {
+ // get instance struct length
+ uint32_t inst_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, inst_length)) {
+ if (inst_length != 0)
+ parsed_inst_bytes += skip_struct_length_;
+
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ // get "IdItem[] ids" array length
+ uint32_t ids_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, ids_array_length)) {
+ uint32_t parsed_ids_bytes = 0;
+ while (parsed_ids_bytes + skip_struct_length_ <= ids_array_length) {
+ if (!parse_id_item(_buffer, parsed_ids_bytes, its_instance_ranges, _buffer_size)) {
+ return false;
+ }
+ }
+ parsed_inst_bytes += (skip_array_length_ + ids_array_length);
+ }
+ // get "IdItem[] methods" array length
+ uint32_t methods_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, methods_array_length)) {
+ uint32_t parsed_method_bytes = 0;
+ while (parsed_method_bytes + skip_struct_length_ <= methods_array_length) {
+ if (!parse_id_item(_buffer, parsed_method_bytes, its_method_ranges, _buffer_size)) {
+ return false;
+ }
+ }
+ if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ }
+ parsed_inst_bytes += (skip_array_length_ + methods_array_length);
+ }
+ }
+ }
+ parsed_req_bytes += (skip_array_length_ + instances_array_length);
+ }
+ if (!its_instance_method_ranges.empty()) {
+ _policy->services_.insert(
+ std::make_pair(its_service_id, its_instance_method_ranges));
+ }
+ }
+ }
+ }
+ // get offers array length
+ uint32_t offers_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, offers_array_length)){
+ // loop through offers array
+ uint32_t parsed_offers_bytes = 0;
+ while (parsed_offers_bytes + skip_struct_length_ <= offers_array_length) {
+ // get service ID
+ uint16_t its_service_id = 0;
+ ranges_t its_instance_ranges;
+ // get serviceID
+ if (!parse_id(_buffer, _buffer_size, its_service_id)) {
+ has_error = true;
+ } else {
+ if (its_service_id == 0x00
+ || its_service_id == 0xFFFF) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with service ID: 0x"
+ << its_service_id << " is not allowed!";
+ return false;
+ }
+ // add length of serviceID
+ parsed_offers_bytes += id_width_;
+ }
+
+ // get "IdItem[] ids" array length
+ uint32_t ids_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, ids_array_length)) {
+ uint32_t parsed_ids_bytes = 0;
+ while (parsed_ids_bytes + skip_struct_length_ <= ids_array_length) {
+ if (!parse_id_item(_buffer, parsed_ids_bytes, its_instance_ranges, _buffer_size)) {
+ return false;
+ }
+ }
+ parsed_offers_bytes += (skip_array_length_ + ids_array_length);
+ }
+ if (!its_instance_ranges.empty()) {
+ _policy->offers_.insert(
+ std::make_pair(its_service_id, its_instance_ranges));
+ }
+ }
+ }
+ } else {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with empty request / offer section is not allowed!";
+ has_error = true;
+ }
+ } else {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy without UID / GID is not allowed!";
+ has_error = true;
+ }
+
+ if (!has_error)
+ return true;
+ else
+ return false;
}
void utility::check_client_id_consistency() {
@@ -767,4 +1110,30 @@ void utility::check_client_id_consistency() {
}
}
+std::uint16_t utility::get_max_number_of_clients(std::uint16_t _diagnosis_max) {
+ std::uint16_t its_max_clients(0);
+ const int bits_for_clients =
+#ifdef _WIN32
+ __popcnt(
+#else
+ __builtin_popcount(
+#endif
+ static_cast<std::uint16_t>(~_diagnosis_max));
+ for (int var = 0; var < bits_for_clients; ++var) {
+ its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
+ }
+ return its_max_clients;
+}
+
+const uint8_t utility::uid_width_ = sizeof(uint32_t);
+const uint8_t utility::gid_width_ = sizeof(uint32_t);
+const uint8_t utility::id_width_ = sizeof(uint16_t);
+const uint8_t utility::range_width_ = sizeof(uint32_t);
+
+const uint8_t utility::skip_union_length_ = sizeof(uint32_t);
+const uint8_t utility::skip_union_type_ = sizeof(uint32_t);
+const uint8_t utility::skip_union_length_type_ = sizeof(uint32_t) + sizeof(uint32_t);
+const uint8_t utility::skip_struct_length_ = sizeof(uint32_t);
+const uint8_t utility::skip_array_length_ = sizeof(uint32_t);
+
} // namespace vsomeip