diff options
Diffstat (limited to 'implementation/routing')
23 files changed, 3696 insertions, 4187 deletions
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp index 668bbf4..684a49b 100644 --- a/implementation/routing/include/event.hpp +++ b/implementation/routing/include/event.hpp @@ -3,9 +3,10 @@ // 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_EVENT_IMPL_HPP -#define VSOMEIP_EVENT_IMPL_HPP +#ifndef VSOMEIP_V3_EVENT_IMPL_HPP_ +#define VSOMEIP_V3_EVENT_IMPL_HPP_ +#include <list> #include <map> #include <memory> #include <mutex> @@ -20,7 +21,13 @@ #include <vsomeip/function_types.hpp> #include <vsomeip/payload.hpp> -namespace vsomeip { +#ifdef ANDROID +#include "../../configuration/include/internal_android.hpp" +#else +#include "../../configuration/include/internal.hpp" +#endif // ANDROID + +namespace vsomeip_v3 { class endpoint; class endpoint_definition; @@ -28,7 +35,8 @@ class message; class payload; class routing_manager; -class event: public std::enable_shared_from_this<event> { +class event + : public std::enable_shared_from_this<event> { public: event(routing_manager *_routing, bool _is_shadow = false); @@ -47,21 +55,25 @@ public: const std::shared_ptr<payload> get_payload() const; void set_payload(const std::shared_ptr<payload> &_payload, - const client_t _client, bool _force, bool _flush); + const client_t _client, bool _force); void set_payload(const std::shared_ptr<payload> &_payload, - const std::shared_ptr<endpoint_definition> _target, - bool _force, bool _flush); + const client_t _client, + const std::shared_ptr<endpoint_definition>& _target, bool _force); bool set_payload_dont_notify(const std::shared_ptr<payload> &_payload); + bool set_payload_notify_pending(const std::shared_ptr<payload> &_payload); - void set_payload(const std::shared_ptr<payload> &_payload, - bool _force, bool _flush); + void set_payload(const std::shared_ptr<payload> &_payload, bool _force); void unset_payload(bool _force = false); - bool is_field() const; - void set_field(bool _is_field); + event_type_e get_type() const; + void set_type(const event_type_e _type); + + reliability_type_e get_reliability() const; + void set_reliability(const reliability_type_e _reliability); + bool is_field() const; bool is_provided() const; void set_provided(bool _is_provided); @@ -75,25 +87,30 @@ public: 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); + void set_epsilon_change_function( + const epsilon_change_func_t &_epsilon_change_func); const std::set<eventgroup_t> get_eventgroups() const; std::set<eventgroup_t> get_eventgroups(client_t _client) const; void add_eventgroup(eventgroup_t _eventgroup); void set_eventgroups(const std::set<eventgroup_t> &_eventgroups); - void notify_one(const std::shared_ptr<endpoint_definition> &_target, bool _flush); - void notify_one(client_t _client, bool _flush); + void notify_one(client_t _client, + const std::shared_ptr<endpoint_definition> &_target); + void notify_one(client_t _client); + bool add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _force); void remove_subscriber(eventgroup_t _eventgroup, client_t _client); bool has_subscriber(eventgroup_t _eventgroup, client_t _client); std::set<client_t> get_subscribers(); + std::set<client_t> get_subscribers(eventgroup_t _eventgroup); void clear_subscribers(); void add_ref(client_t _client, bool _is_provided); void remove_ref(client_t _client, bool _is_provided); bool has_ref(); + bool has_ref(client_t _client, bool _is_provided); bool is_shadow() const; void set_shadow(bool _shadow); @@ -101,40 +118,36 @@ public: bool is_cache_placeholder() const; void set_cache_placeholder(bool _is_cache_place_holder); - bool has_ref(client_t _client, bool _is_provided); - - std::set<client_t> get_subscribers(eventgroup_t _eventgroup); - bool is_subscribed(client_t _client); - bool is_reliable() const; - void set_reliable(bool _is_reliable); - - bool get_remote_notification_pending(); - void set_remote_notification_pending(bool _value); + void remove_pending(const std::shared_ptr<endpoint_definition> &_target); private: void update_cbk(boost::system::error_code const &_error); - void notify(bool _flush); - void notify(client_t _client, const std::shared_ptr<endpoint_definition> &_target); + void notify(); + void notify(client_t _client, + const std::shared_ptr<endpoint_definition> &_target); void start_cycle(); void stop_cycle(); - bool compare(const std::shared_ptr<payload> &_lhs, const std::shared_ptr<payload> &_rhs) const; + bool compare(const std::shared_ptr<payload> &_lhs, + const std::shared_ptr<payload> &_rhs) const; - bool set_payload_helper(const std::shared_ptr<payload> &_payload, bool _force); + 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); + void notify_one_unlocked(client_t _client); + void notify_one_unlocked(client_t _client, + const std::shared_ptr<endpoint_definition> &_target); private: routing_manager *routing_; mutable std::mutex mutex_; std::shared_ptr<message> message_; - std::atomic<bool> is_field_; + std::atomic<event_type_e> type_; boost::asio::steady_timer cycle_timer_; std::chrono::milliseconds cycle_; @@ -143,7 +156,7 @@ private: std::atomic<bool> is_updating_on_change_; mutable std::mutex eventgroups_mutex_; - std::map<eventgroup_t, std::set<client_t>> eventgroups_; + std::map<eventgroup_t, std::set<client_t> > eventgroups_; std::atomic<bool> is_set_; std::atomic<bool> is_provided_; @@ -156,11 +169,11 @@ private: epsilon_change_func_t epsilon_change_func_; - std::atomic<bool> is_reliable_; + std::atomic<reliability_type_e> reliability_; - std::atomic<bool> remote_notification_pending_; + std::set<std::shared_ptr<endpoint_definition> > pending_; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_EVENT_IMPL_HPP +#endif // VSOMEIP_V3_EVENT_IMPL_HPP_ diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp index d6244b5..65f7e89 100644 --- a/implementation/routing/include/eventgroupinfo.hpp +++ b/implementation/routing/include/eventgroupinfo.hpp @@ -3,48 +3,62 @@ // 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_EVENTGROUPINFO_HPP -#define VSOMEIP_EVENTGROUPINFO_HPP +#ifndef VSOMEIP_V3_EVENTGROUPINFO_HPP_ +#define VSOMEIP_V3_EVENTGROUPINFO_HPP_ +#include <atomic> #include <chrono> #include <list> #include <memory> -#include <set> #include <mutex> -#include <atomic> +#include <set> +#include <vector> #include <boost/asio/ip/address.hpp> #include <vsomeip/export.hpp> #include <vsomeip/primitive_types.hpp> +#include "remote_subscription.hpp" #include "types.hpp" -namespace vsomeip { +namespace vsomeip_v3 { class endpoint_definition; class event; class eventgroupinfo { public: - struct target_t { - std::shared_ptr<endpoint_definition> endpoint_; + struct subscription_t { + std::shared_ptr<remote_subscription> subscription_; std::chrono::steady_clock::time_point expiration_; - bool operator==(const target_t &_other) const { - return (endpoint_ == _other.endpoint_); + bool operator==(const subscription_t &_other) const { + return (subscription_ == _other.subscription_); } }; VSOMEIP_EXPORT eventgroupinfo(); - VSOMEIP_EXPORT eventgroupinfo(major_version_t _major, ttl_t _ttl); + VSOMEIP_EXPORT eventgroupinfo( + const service_t _service, const service_t _instance, + const eventgroup_t _eventgroup, const major_version_t _major, + const ttl_t _ttl); VSOMEIP_EXPORT ~eventgroupinfo(); + VSOMEIP_EXPORT service_t get_service() const; + VSOMEIP_EXPORT void set_service(const service_t _service); + + VSOMEIP_EXPORT instance_t get_instance() const; + VSOMEIP_EXPORT void set_instance(const instance_t _instance); + + VSOMEIP_EXPORT eventgroup_t get_eventgroup() const; + VSOMEIP_EXPORT void set_eventgroup(const eventgroup_t _eventgroup); + VSOMEIP_EXPORT major_version_t get_major() const; - VSOMEIP_EXPORT void set_major(major_version_t _major); + VSOMEIP_EXPORT void set_major(const major_version_t _major); VSOMEIP_EXPORT ttl_t get_ttl() const; - VSOMEIP_EXPORT void set_ttl(ttl_t _ttl); + VSOMEIP_EXPORT void set_ttl(const ttl_t _ttl); VSOMEIP_EXPORT bool is_multicast() const; VSOMEIP_EXPORT bool get_multicast(boost::asio::ip::address &_address, @@ -54,39 +68,48 @@ public: VSOMEIP_EXPORT bool is_sending_multicast() const; VSOMEIP_EXPORT const std::set<std::shared_ptr<event> > get_events() const; - VSOMEIP_EXPORT void add_event(std::shared_ptr<event> _event); - VSOMEIP_EXPORT void remove_event(std::shared_ptr<event> _event); - VSOMEIP_EXPORT void get_reliability(bool& _has_reliable, bool& _has_unreliable) const; - - VSOMEIP_EXPORT const std::list<target_t> get_targets() const; - VSOMEIP_EXPORT uint32_t get_unreliable_target_count() const; - - VSOMEIP_EXPORT bool add_target(const target_t &_target); - VSOMEIP_EXPORT bool add_target(const target_t &_target, const target_t &_subscriber); - VSOMEIP_EXPORT bool update_target( - const std::shared_ptr<endpoint_definition> &_target, - const std::chrono::steady_clock::time_point &_expiration); - VSOMEIP_EXPORT bool remove_target( - const std::shared_ptr<endpoint_definition> &_target); - VSOMEIP_EXPORT void clear_targets(); - - VSOMEIP_EXPORT void add_multicast_target(const target_t &_multicast_target); - VSOMEIP_EXPORT void clear_multicast_targets(); - VSOMEIP_EXPORT const std::list<target_t> get_multicast_targets() const; + VSOMEIP_EXPORT void add_event(const std::shared_ptr<event>& _event); + VSOMEIP_EXPORT void remove_event(const std::shared_ptr<event>& _event); + VSOMEIP_EXPORT reliability_type_e get_reliability() const; - VSOMEIP_EXPORT uint8_t get_threshold() const; - VSOMEIP_EXPORT void set_threshold(uint8_t _threshold); + VSOMEIP_EXPORT std::set<std::shared_ptr<remote_subscription>> + get_remote_subscriptions() const; + + std::shared_ptr<remote_subscription> get_remote_subscription( + const remote_subscription_id_t _id); + + bool update_remote_subscription( + const std::shared_ptr<remote_subscription> &_subscription, + const std::chrono::steady_clock::time_point &_expiration, + std::set<client_t> &_changed, remote_subscription_id_t &_id, + const bool _is_subscribe); + + remote_subscription_id_t add_remote_subscription( + const std::shared_ptr<remote_subscription> &_subscription); - VSOMEIP_EXPORT std::unique_lock<std::mutex> get_subscription_lock(); + VSOMEIP_EXPORT void remove_remote_subscription( + const remote_subscription_id_t _id); - VSOMEIP_EXPORT pending_subscription_id_t add_pending_subscription( - pending_subscription_t _pending_subscription); + VSOMEIP_EXPORT std::set<std::shared_ptr<endpoint_definition> > + get_unicast_targets() const; + VSOMEIP_EXPORT std::set<std::shared_ptr<endpoint_definition> > + get_multicast_targets() const; - VSOMEIP_EXPORT std::vector<pending_subscription_t> remove_pending_subscription( - pending_subscription_id_t _subscription_id); + VSOMEIP_EXPORT uint8_t get_threshold() const; + VSOMEIP_EXPORT void set_threshold(uint8_t _threshold); - VSOMEIP_EXPORT void clear_pending_subscriptions(); + VSOMEIP_EXPORT bool is_selective() const; + + VSOMEIP_EXPORT void send_initial_events( + const std::shared_ptr<endpoint_definition> &_reliable, + const std::shared_ptr<endpoint_definition> &_unreliable) const; private: + void update_id(); + uint32_t get_unreliable_target_count() const; + + std::atomic<service_t> service_; + std::atomic<instance_t> instance_; + std::atomic<eventgroup_t> eventgroup_; std::atomic<major_version_t> major_; std::atomic<ttl_t> ttl_; @@ -96,24 +119,18 @@ private: mutable std::mutex events_mutex_; std::set<std::shared_ptr<event> > events_; - mutable std::mutex targets_mutex_; - std::list<target_t> targets_; - mutable std::mutex multicast_targets_mutex_; - std::list<target_t> multicast_targets_; std::atomic<uint8_t> threshold_; - std::mutex subscription_mutex_; - std::atomic<bool> has_reliable_; - std::atomic<bool> has_unreliable_; + mutable std::mutex subscriptions_mutex_; + std::map<remote_subscription_id_t, + std::shared_ptr<remote_subscription> + > subscriptions_; + remote_subscription_id_t id_; - std::mutex pending_subscriptions_mutex_; - std::map<pending_subscription_id_t, pending_subscription_t> pending_subscriptions_; - std::map<std::tuple<boost::asio::ip::address, std::uint16_t, bool>, - std::vector<pending_subscription_id_t>> pending_subscriptions_by_remote_; - pending_subscription_id_t subscription_id_; + std::atomic<reliability_type_e> reliability_; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_EVENTGROUPINFO_HPP +#endif // VSOMEIP_V3_EVENTGROUPINFO_HPP_ diff --git a/implementation/routing/include/function_types.hpp b/implementation/routing/include/function_types.hpp new file mode 100644 index 0000000..3f89c08 --- /dev/null +++ b/implementation/routing/include/function_types.hpp @@ -0,0 +1,19 @@ +// Copyright (C) 2018 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_V3_ROUTING_FUNCTION_TYPES_HPP_ +#define VSOMEIP_V3_ROUTING_FUNCTION_TYPES_HPP_ + +namespace vsomeip_v3 { + +class remote_subscription; + +typedef std::function< + void (const std::shared_ptr<remote_subscription> &_subscription) +> remote_subscription_callback_t; + +} // namespace vsomeip_v3 + +#endif // VSOMEIP_V3_ROUTING_FUNCTION_TYPES_HPP_ diff --git a/implementation/routing/include/remote_subscription.hpp b/implementation/routing/include/remote_subscription.hpp new file mode 100644 index 0000000..00f2b57 --- /dev/null +++ b/implementation/routing/include/remote_subscription.hpp @@ -0,0 +1,129 @@ +// Copyright (C) 2018 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_V3_REMOTE_SUBSCRIPTION_HPP_ +#define VSOMEIP_V3_REMOTE_SUBSCRIPTION_HPP_ + +#include <atomic> +#include <map> +#include <mutex> +#include <set> + +#include <vsomeip/primitive_types.hpp> + +#include "../../endpoints/include/endpoint_definition.hpp" +#include "types.hpp" +#include <vsomeip/export.hpp> + + +namespace vsomeip_v3 { + +class eventgroupinfo; + +const remote_subscription_id_t PENDING_SUBSCRIPTION_ID(0); + +class remote_subscription { +public: + VSOMEIP_EXPORT remote_subscription(); + VSOMEIP_EXPORT ~remote_subscription(); + + bool operator==(const remote_subscription &_other) const; + bool equals(const std::shared_ptr<remote_subscription> &_other) const; + + VSOMEIP_EXPORT void reset(const std::set<client_t> &_clients); + + VSOMEIP_EXPORT bool is_initial() const; + VSOMEIP_EXPORT void set_initial(const bool _is_initial); + + VSOMEIP_EXPORT bool force_initial_events() const; + VSOMEIP_EXPORT void set_force_initial_events(const bool _force_initial_events); + + remote_subscription_id_t get_id() const; + void set_id(const remote_subscription_id_t _id); + + std::shared_ptr<remote_subscription> get_parent() const; + void set_parent(const std::shared_ptr<remote_subscription> &_parent); + + VSOMEIP_EXPORT std::shared_ptr<eventgroupinfo> get_eventgroupinfo() const; + VSOMEIP_EXPORT void set_eventgroupinfo(const std::shared_ptr<eventgroupinfo> &_info); + + VSOMEIP_EXPORT ttl_t get_ttl() const; + VSOMEIP_EXPORT void set_ttl(const ttl_t _ttl); + + uint16_t get_reserved() const; + void set_reserved(const uint16_t _reserved); + + uint8_t get_counter() const; + void set_counter(uint8_t _counter); + + VSOMEIP_EXPORT std::set<client_t> get_clients() const; + bool has_client() const; + bool has_client(const client_t _client) const; + void remove_client(const client_t _client); + + VSOMEIP_EXPORT remote_subscription_state_e get_client_state(const client_t _client) const; + void set_client_state(const client_t _client, + remote_subscription_state_e _state); + void set_all_client_states(remote_subscription_state_e _state); + + std::chrono::steady_clock::time_point get_expiration(const client_t _client) const; + + VSOMEIP_EXPORT std::shared_ptr<endpoint_definition> get_subscriber() const; + VSOMEIP_EXPORT void set_subscriber(const std::shared_ptr<endpoint_definition> &_subscriber); + + VSOMEIP_EXPORT std::shared_ptr<endpoint_definition> get_reliable() const; + VSOMEIP_EXPORT void set_reliable(const std::shared_ptr<endpoint_definition> &_reliable); + + VSOMEIP_EXPORT std::shared_ptr<endpoint_definition> get_unreliable() const; + VSOMEIP_EXPORT void set_unreliable(const std::shared_ptr<endpoint_definition> &_unreliable); + + VSOMEIP_EXPORT bool is_pending() const; + bool is_acknowledged() const; + + std::set<client_t> update(const std::set<client_t> &_clients, + const std::chrono::steady_clock::time_point &_timepoint, + const bool _is_subscribe); + + VSOMEIP_EXPORT std::uint32_t get_answers() const; + void set_answers(const std::uint32_t _answers); + +private: + std::atomic<remote_subscription_id_t> id_; + std::atomic<bool> is_initial_; + std::atomic<bool> force_initial_events_; + std::weak_ptr<remote_subscription> parent_; + + std::weak_ptr<eventgroupinfo> eventgroupinfo_; + + major_version_t major_; + ttl_t ttl_; + std::uint16_t reserved_; + std::uint8_t counter_; + + std::map<client_t, + std::pair<remote_subscription_state_e, + std::chrono::steady_clock::time_point + > + > clients_; + + // The endpoint that sent(!) the subscription + std::shared_ptr<endpoint_definition> subscriber_; + + // The endpoints defined by the endpoint options + std::shared_ptr<endpoint_definition> reliable_; + std::shared_ptr<endpoint_definition> unreliable_; + + // Number of acknowledgements that must be sent + // for the subscriptions. This is usally 1, but + // may be larger if a matching subscription arrived + // before the subscription could be acknowledged + std::uint32_t answers_; + + mutable std::mutex mutex_; +}; + +} // namespace vsomeip_v3 + +#endif // VSOMEIP_V3_REMOTE_SUBSCRIPTION_HPP_ diff --git a/implementation/routing/include/routing_host.hpp b/implementation/routing/include/routing_host.hpp new file mode 100644 index 0000000..337e4a7 --- /dev/null +++ b/implementation/routing/include/routing_host.hpp @@ -0,0 +1,44 @@ +// 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_V3_ROUTING_HOST_ +#define VSOMEIP_V3_ROUTING_HOST_ + +#include <memory> + +#include <boost/asio/ip/address.hpp> + +#include <vsomeip/primitive_types.hpp> + +#ifdef ANDROID +#include "../../configuration/include/internal_android.hpp" +#else +#include "../../configuration/include/internal.hpp" +#endif // ANDROID + +namespace vsomeip_v3 { + +class endpoint; + +class routing_host { +public: + virtual ~routing_host() = default; + + virtual void on_message(const byte_t *_data, length_t _length, + endpoint *_receiver, + const boost::asio::ip::address &_destination = + boost::asio::ip::address(), + client_t _bound_client = VSOMEIP_ROUTING_CLIENT, + credentials_t _credentials = {ANY_UID, ANY_GID}, + const boost::asio::ip::address &_remote_address = + boost::asio::ip::address(), + std::uint16_t _remote_port = 0) = 0; + + virtual client_t get_client() const = 0; +}; + +} // namespace vsomeip_v3 + +#endif // VSOMEIP_V3_ROUTING_HOST_ diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp index 9ab09f4..fa0e675 100644 --- a/implementation/routing/include/routing_manager.hpp +++ b/implementation/routing/include/routing_manager.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_ROUTING_MANAGER -#define VSOMEIP_ROUTING_MANAGER +#ifndef VSOMEIP_V3_ROUTING_MANAGER_ +#define VSOMEIP_V3_ROUTING_MANAGER_ #include <memory> #include <set> @@ -17,12 +17,13 @@ #include <vsomeip/handler.hpp> #include "types.hpp" -namespace vsomeip { +namespace vsomeip_v3 { class endpoint; class endpoint_definition; class event; class payload; +class security; class routing_manager { public: @@ -31,6 +32,8 @@ public: virtual boost::asio::io_service & get_io() = 0; virtual client_t get_client() const = 0; + virtual void set_client(const client_t &_client) = 0; + virtual session_t get_session() = 0; virtual void init() = 0; virtual void start() = 0; @@ -46,38 +49,41 @@ public: virtual void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, bool _use_exclusive_proxy) = 0; + minor_version_t _minor) = 0; virtual void release_service(client_t _client, service_t _service, instance_t _instance) = 0; - virtual void subscribe(client_t _client, service_t _service, + virtual void subscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, event_t _event, - subscription_type_e _subscription_type) = 0; + major_version_t _major, event_t _event) = 0; - virtual void unsubscribe(client_t _client, service_t _service, + virtual void unsubscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) = 0; - virtual bool send(client_t _client, std::shared_ptr<message> _message, - bool _flush) = 0; + virtual bool send(client_t _client, std::shared_ptr<message> _message) = 0; virtual bool send(client_t _client, const byte_t *_data, uint32_t _size, - instance_t _instance, bool _flush, bool _reliable, + instance_t _instance, bool _reliable, client_t _bound_client = VSOMEIP_ROUTING_CLIENT, - bool _is_valid_crc = true, bool _sent_from_remote = false) = 0; + credentials_t _credentials = {ANY_UID, ANY_GID}, + uint8_t _status_check = 0, bool _sent_from_remote = false) = 0; - virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target, - std::shared_ptr<message>, bool _flush) = 0; + virtual bool send_to(const client_t _client, + const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message>) = 0; virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target, - const byte_t *_data, uint32_t _size, instance_t _instance, - bool _flush) = 0; - - virtual void register_event(client_t _client, service_t _service, - instance_t _instance, event_t _event, - const std::set<eventgroup_t> &_eventgroups, bool _is_field, + const byte_t *_data, uint32_t _size, instance_t _instance) = 0; + + virtual void register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, + const event_type_e _type, + reliability_type_e _reliability, std::chrono::milliseconds _cycle, bool _change_resets_cycle, + bool _update_on_change, epsilon_change_func_t _epsilon_change_func, bool _is_provided, bool _is_shadow = false, bool _is_cache_placeholder = false) = 0; @@ -93,20 +99,21 @@ public: virtual void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload, - bool _force, bool _flush) = 0; + bool _force) = 0; 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, bool _remote_subscriber) = 0; - - virtual void on_identify_response(client_t _client, service_t _service, - instance_t _instance, bool _reliable) = 0; + client_t _client, bool _force +#ifdef VSOMEIP_ENABLE_COMPAT + , bool _remote_subscriber +#endif + ) = 0; virtual void set_routing_state(routing_state_e _routing_state) = 0; virtual void send_get_offered_services_info(client_t _client, offer_type_e _offer_type) = 0; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif +#endif // VSOMEIP_V3_ROUTING_MANAGER_ diff --git a/implementation/routing/include/routing_manager_adapter.hpp b/implementation/routing/include/routing_manager_adapter.hpp index 3d81120..a2195ee 100644 --- a/implementation/routing/include/routing_manager_adapter.hpp +++ b/implementation/routing/include/routing_manager_adapter.hpp @@ -3,10 +3,10 @@ // 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_ROUTING_MANAGER_ADAPTER -#define VSOMEIP_ROUTING_MANAGER_ADAPTER +#ifndef VSOMEIP_V3_ROUTING_MANAGER_ADAPTER_ +#define VSOMEIP_V3_ROUTING_MANAGER_ADAPTER_ -namespace vsomeip { +namespace vsomeip_v3 { class routing_manager; @@ -19,6 +19,6 @@ public: virtual void process_command(const byte_t *_data, length_t _length) = 0; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_ROUTING_MANAGER_ADAPTER_HPP +#endif // VSOMEIP_V3_ROUTING_MANAGER_ADAPTER_HPP_ diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp index 6bee10c..acd57fe 100644 --- a/implementation/routing/include/routing_manager_base.hpp +++ b/implementation/routing/include/routing_manager_base.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_ROUTING_MANAGER_BASE -#define VSOMEIP_ROUTING_MANAGER_BASE +#ifndef VSOMEIP_V3_ROUTING_MANAGER_BASE_ +#define VSOMEIP_V3_ROUTING_MANAGER_BASE_ #include <mutex> #include <unordered_set> @@ -12,6 +12,8 @@ #include <condition_variable> #include <vsomeip/constants.hpp> + +#include "routing_host.hpp" #include "routing_manager.hpp" #include "routing_manager_host.hpp" #include "types.hpp" @@ -21,9 +23,10 @@ #include "../../message/include/serializer.hpp" #include "../../message/include/deserializer.hpp" #include "../../configuration/include/configuration.hpp" -#include "../../endpoints/include/endpoint_host.hpp" +#include "../../endpoints/include/endpoint_manager_base.hpp" + +namespace vsomeip_v3 { -namespace vsomeip { #ifdef USE_DLT namespace trace { class connector_impl; @@ -33,90 +36,91 @@ class connector_impl; class serializer; class routing_manager_base : public routing_manager, - public endpoint_host, - public std::enable_shared_from_this<routing_manager_base>{ + public routing_host, + public std::enable_shared_from_this<routing_manager_base> { public: routing_manager_base(routing_manager_host *_host); - virtual ~routing_manager_base(); + virtual ~routing_manager_base() = default; virtual boost::asio::io_service & get_io(); virtual client_t get_client() const; + virtual void set_client(const client_t &_client); + virtual session_t get_session(); - virtual void init(); + virtual void init() = 0; + void init(const std::shared_ptr<endpoint_manager_base>& _endpoint_manager); - virtual bool offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor); + virtual bool offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - virtual void stop_offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor); + virtual void stop_offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - virtual void request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor, bool _use_exclusive_proxy); + virtual void request_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - virtual void release_service(client_t _client, service_t _service, - instance_t _instance); + virtual void release_service(client_t _client, + service_t _service, instance_t _instance); - virtual void register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field, + virtual void register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, + const event_type_e _type, reliability_type_e _reliability, std::chrono::milliseconds _cycle, bool _change_resets_cycle, - epsilon_change_func_t _epsilon_change_func, - bool _is_provided, bool _is_shadow = false, bool _is_cache_placeholder = false); + bool _update_on_change, epsilon_change_func_t _epsilon_change_func, + bool _is_provided, bool _is_shadow = false, + bool _is_cache_placeholder = false); - virtual void unregister_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, bool _is_provided); + virtual void unregister_event(client_t _client, + service_t _service, instance_t _instance, event_t _event, + bool _is_provided); virtual std::set<std::shared_ptr<event>> find_events(service_t _service, instance_t _instance, eventgroup_t _eventgroup) const; - virtual void 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); + virtual void subscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, + eventgroup_t _eventgroup, major_version_t _major, event_t _event); - virtual void unsubscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, event_t _event); + virtual void unsubscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, + eventgroup_t _eventgroup, event_t _event); virtual void notify(service_t _service, instance_t _instance, - event_t _event, std::shared_ptr<payload> _payload, - bool _force, bool _flush); + event_t _event, std::shared_ptr<payload> _payload, bool _force); 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, bool _remote_subscriber); + client_t _client, bool _force +#ifdef VSOMEIP_ENABLE_COMPAT + , bool _remote_subscriber +#endif + ); - virtual bool send(client_t _client, std::shared_ptr<message> _message, - bool _flush); + virtual bool send(client_t _client, std::shared_ptr<message> _message); virtual bool send(client_t _client, const byte_t *_data, uint32_t _size, - instance_t _instance, bool _flush, bool _reliable, + instance_t _instance, bool _reliable, client_t _bound_client = VSOMEIP_ROUTING_CLIENT, - bool _is_valid_crc = true, bool _sent_from_remote = false) = 0; + credentials_t _credentials = {ANY_UID, ANY_GID}, + uint8_t _status_check = 0, 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; - virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0; + // routing host -> will be implemented by routing_manager_impl/_proxy/ virtual void on_message(const byte_t *_data, length_t _length, endpoint *_receiver, const boost::asio::ip::address &_destination = boost::asio::ip::address(), client_t _bound_client = VSOMEIP_ROUTING_CLIENT, + credentials_t _credentials = {ANY_UID, ANY_GID}, const boost::asio::ip::address &_remote_address = boost::asio::ip::address(), std::uint16_t _remote_port = 0) = 0; - virtual void on_error(const byte_t *_data, length_t _length, - endpoint *_receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port) = 0; -#ifndef _WIN32 - virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid); -#endif virtual void set_routing_state(routing_state_e _routing_state) = 0; - virtual std::shared_ptr<event> find_event(service_t _service, instance_t _instance, - event_t _event) const; - virtual void register_client_error_handler(client_t _client, const std::shared_ptr<endpoint> &_endpoint) = 0; @@ -124,8 +128,16 @@ public: 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; + + client_t find_local_client(service_t _service, instance_t _instance) const; + + std::shared_ptr<event> find_event(service_t _service, instance_t _instance, + event_t _event) const; + + virtual void on_connect(const std::shared_ptr<endpoint>& _endpoint) = 0; + virtual void on_disconnect(const std::shared_ptr<endpoint>& _endpoint) = 0; +protected: std::shared_ptr<serviceinfo> create_service_info(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, ttl_t _ttl, bool _is_local_service); @@ -134,21 +146,12 @@ protected: 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, bool _remove_uid); void remove_local(client_t _client, 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, - instance_t _instance); - - std::unordered_set<client_t> get_connected_clients(); - std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service, instance_t _instance, eventgroup_t _eventgroup) const; @@ -157,33 +160,35 @@ protected: bool send_local_notification(client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, - bool _flush = true, bool _reliable = false, bool _is_valid_crc = true); + bool _reliable = false, uint8_t _status_check = 0); bool send_local( std::shared_ptr<endpoint> &_target, client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, - bool _flush, bool _reliable, uint8_t _command, bool _is_valid_crc = true) const; + bool _reliable, uint8_t _command, uint8_t _status_check = 0) const; bool insert_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, client_t _client, std::set<event_t> *_already_subscribed_events); + std::shared_ptr<serializer> get_serializer(); + void put_serializer(const std::shared_ptr<serializer> &_serializer); std::shared_ptr<deserializer> get_deserializer(); - void put_deserializer(std::shared_ptr<deserializer>); + void put_deserializer(const std::shared_ptr<deserializer> &_deserializer); void send_pending_subscriptions(service_t _service, instance_t _instance, major_version_t _major); virtual void send_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) = 0; + major_version_t _major, event_t _event) = 0; void remove_pending_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event); - +#ifdef VSOMEIP_ENABLE_COMPAT void send_pending_notify_ones(service_t _service, instance_t _instance, eventgroup_t _eventgroup, client_t _client, bool _remote_subscriber = false); +#endif void unset_all_eventpayloads(service_t _service, instance_t _instance); void unset_all_eventpayloads(service_t _service, instance_t _instance, @@ -194,11 +199,6 @@ protected: eventgroup_t _eventgroup, event_t _event, const std::set<event_t> &_events_to_exclude); - void send_identify_request(service_t _service, instance_t _instance, - major_version_t _major, bool _reliable); - - std::map<client_t, std::shared_ptr<endpoint>> get_local_endpoints(); - std::set<std::tuple<service_t, instance_t, eventgroup_t>> get_subscriptions(const client_t _client); @@ -206,9 +206,9 @@ protected: 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, + bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); - +#ifdef VSOMEIP_ENABLE_COMPAT void set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, subscription_state_e _state); @@ -217,12 +217,9 @@ protected: void erase_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event); +#endif private: - std::shared_ptr<endpoint> create_local_unlocked(client_t _client); - std::shared_ptr<endpoint> find_local_unlocked(client_t _client); - - virtual bool create_placeholder_event_and_subscribe( service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, client_t _client) = 0; @@ -230,18 +227,22 @@ private: protected: routing_manager_host *host_; boost::asio::io_service &io_; - client_t client_; + std::atomic<client_t> client_; std::shared_ptr<configuration> configuration_; - std::shared_ptr<serializer> serializer_; - std::mutex serialize_mutex_; + + std::queue<std::shared_ptr<serializer>> serializers_; + std::mutex serializer_mutex_; + std::condition_variable serializer_condition_; std::queue<std::shared_ptr<deserializer>> deserializers_; std::mutex deserializer_mutex_; std::condition_variable deserializer_condition_; - 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_; + mutable std::mutex local_services_mutex_; + typedef std::map<service_t, std::map<instance_t, + std::tuple<major_version_t, minor_version_t, client_t>>> local_services_map_t; + local_services_map_t local_services_; std::map<service_t, std::map<instance_t, std::set<client_t> > > local_services_history_; // Eventgroups @@ -252,7 +253,11 @@ protected: // Events (part of one or more eventgroups) mutable std::mutex events_mutex_; std::map<service_t, - std::map<instance_t, std::map<event_t, std::shared_ptr<event> > > > events_; + std::map<instance_t, + std::map<event_t, + std::shared_ptr<event> > > > events_; + + std::mutex event_registration_mutex_; #ifdef USE_DLT std::shared_ptr<trace::connector_impl> tc_; @@ -264,7 +269,8 @@ protected: eventgroup_t eventgroup_; major_version_t major_; event_t event_; - subscription_type_e subscription_type_; + uid_t uid_; + gid_t gid_; bool operator<(const subscription_data_t &_other) const { return (service_ < _other.service_ @@ -284,21 +290,21 @@ protected: services_t services_remote_; mutable std::mutex services_remote_mutex_; + std::shared_ptr<endpoint_manager_base> ep_mgr_; + + std::uint32_t own_uid_; + std::uint32_t own_gid_; + private: services_t services_; mutable std::mutex services_mutex_; - std::map<client_t, std::shared_ptr<endpoint> > local_endpoints_; - mutable std::mutex local_endpoint_mutex_; - +#ifdef VSOMEIP_ENABLE_COMPAT std::map<service_t, std::map<instance_t, std::map<eventgroup_t, std::shared_ptr<message> > > > pending_notify_ones_; std::recursive_mutex pending_notify_ones_mutex_; - - std::mutex event_registration_mutex_; - std::map<client_t, std::map<service_t, std::map<instance_t, @@ -306,9 +312,10 @@ private: std::map<event_t, subscription_state_e> > > > > incoming_subscription_state_; std::recursive_mutex incoming_subscription_state_mutex_; +#endif }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif //VSOMEIP_ROUTING_MANAGER_BASE +#endif // VSOMEIP_V3_ROUTING_MANAGER_BASE_ diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp index 7aa767a..69133e2 100644 --- a/implementation/routing/include/routing_manager_host.hpp +++ b/implementation/routing/include/routing_manager_host.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_ROUTING_MANAGER_HOST -#define VSOMEIP_ROUTING_MANAGER_HOST +#ifndef VSOMEIP_V3_ROUTING_MANAGER_HOST_ +#define VSOMEIP_V3_ROUTING_MANAGER_HOST_ #include <memory> @@ -12,7 +12,7 @@ #include <vsomeip/error.hpp> -namespace vsomeip { +namespace vsomeip_v3 { class configuration; class message; @@ -23,6 +23,8 @@ public: } virtual client_t get_client() const = 0; + virtual void set_client(const client_t &_client) = 0; + virtual session_t get_session() = 0; virtual const std::string & get_name() const = 0; virtual std::shared_ptr<configuration> get_configuration() const = 0; virtual boost::asio::io_service & get_io() = 0; @@ -30,19 +32,17 @@ public: virtual void on_availability(service_t _service, instance_t _instance, bool _is_available, major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) = 0; virtual void on_state(state_type_e _state) = 0; - virtual void on_message(const std::shared_ptr<message> &&_message) = 0; - virtual void on_error(error_code_e _error) = 0; + virtual void on_message(std::shared_ptr<message> &&_message) = 0; virtual void on_subscription(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, client_t _client, bool _subscribed, std::function<void(bool)> _accepted_cb) = 0; - virtual void on_subscription_error(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, uint16_t _error) = 0; + eventgroup_t _eventgroup, client_t _client, uid_t _uid, gid_t _gid, bool _subscribed, + std::function<void(bool)> _accepted_cb) = 0; virtual void on_subscription_status(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, uint16_t _error) = 0; - virtual void send(std::shared_ptr<message> _message, bool _flush) = 0; + virtual void send(std::shared_ptr<message> _message) = 0; virtual void on_offered_services_info(std::vector<std::pair<service_t, instance_t>> &_services) = 0; virtual bool is_routing() const = 0; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_ROUTING_MANAGER_HOST +#endif // VSOMEIP_V3_ROUTING_MANAGER_HOST_ diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp index 40abf73..bead207 100644 --- a/implementation/routing/include/routing_manager_impl.hpp +++ b/implementation/routing/include/routing_manager_impl.hpp @@ -1,10 +1,10 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2018 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_ROUTING_MANAGER_IMPL_HPP -#define VSOMEIP_ROUTING_MANAGER_IMPL_HPP +#ifndef VSOMEIP_V3_ROUTING_MANAGER_IMPL_HPP_ +#define VSOMEIP_V3_ROUTING_MANAGER_IMPL_HPP_ #include <map> #include <memory> @@ -26,8 +26,10 @@ #include "../../endpoints/include/netlink_connector.hpp" #include "../../service_discovery/include/service_discovery_host.hpp" +#include "../../endpoints/include/endpoint_manager_impl.hpp" -namespace vsomeip { + +namespace vsomeip_v3 { class configuration; class deserializer; @@ -42,9 +44,9 @@ namespace sd { class service_discovery; } // namespace sd - -// TODO: encapsulate common parts of classes "routing_manager_impl" -// and "routing_manager_proxy" into a base class. +namespace e2e { +class e2e_provider; +} // namespace e2e class routing_manager_impl: public routing_manager_base, public routing_manager_stub_host, @@ -55,61 +57,70 @@ public: boost::asio::io_service & get_io(); client_t get_client() const; - const std::shared_ptr<configuration> get_configuration() const; void init(); void start(); void stop(); - bool offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor); + bool offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - void stop_offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor); + void stop_offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - void request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor, bool _use_exclusive_proxy); + void request_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - void release_service(client_t _client, service_t _service, - instance_t _instance); + void release_service(client_t _client, + service_t _service, instance_t _instance); - void 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); + void subscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, + eventgroup_t _eventgroup, major_version_t _major, event_t _event); - void unsubscribe(client_t _client, service_t _service, instance_t _instance, + void unsubscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event); - bool send(client_t _client, std::shared_ptr<message> _message, bool _flush); + bool send(client_t _client, std::shared_ptr<message> _message); - virtual bool send(client_t _client, const byte_t *_data, uint32_t _size, - instance_t _instance, bool _flush, bool _reliable, + bool send(client_t _client, const byte_t *_data, uint32_t _size, + instance_t _instance, bool _reliable, client_t _bound_client = VSOMEIP_ROUTING_CLIENT, - bool _is_valid_crc = true, bool _sent_from_remote = false); + credentials_t _credentials = {ANY_UID, ANY_GID}, + uint8_t _status_check = 0, bool _sent_from_remote = false); - bool send_to(const std::shared_ptr<endpoint_definition> &_target, - std::shared_ptr<message> _message, bool _flush); + bool send_to(const client_t _client, + const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message> _message); bool send_to(const std::shared_ptr<endpoint_definition> &_target, const byte_t *_data, uint32_t _size, - instance_t _instance, bool _flush); + instance_t _instance); - bool send_to(const std::shared_ptr<endpoint_definition> &_target, + bool send_via_sd(const std::shared_ptr<endpoint_definition> &_target, const byte_t *_data, uint32_t _size, uint16_t _sd_port); - void register_event(client_t _client, service_t _service, - instance_t _instance, event_t _event, - const std::set<eventgroup_t> &_eventgroups, bool _is_field, + void register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, + const event_type_e _type, + reliability_type_e _reliability, std::chrono::milliseconds _cycle, bool _change_resets_cycle, + bool _update_on_change, epsilon_change_func_t _epsilon_change_func, bool _is_provided, bool _is_shadow, bool _is_cache_placeholder); - void register_shadow_event(client_t _client, service_t _service, - instance_t _instance, event_t _event, + void register_shadow_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, const std::set<eventgroup_t> &_eventgroups, - bool _is_field, bool _is_provided); + event_type_e _type, reliability_type_e _reliability, + bool _is_provided); void unregister_shadow_event(client_t _client, service_t _service, instance_t _instance, event_t _event, @@ -117,63 +128,68 @@ 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, bool _remote_subscriber); + client_t _client, bool _force +#ifdef VSOMEIP_ENABLE_COMPAT + , bool _remote_subscriber +#endif + ); - void on_subscribe_nack(client_t _client, service_t _service, + void on_subscribe_ack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, - pending_subscription_id_t _subscription_id); + remote_subscription_id_t _id); - void on_subscribe_ack(client_t _client, service_t _service, + void on_subscribe_nack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, - pending_subscription_id_t _subscription_id); + remote_subscription_id_t _id); - void on_identify_response(client_t _client, service_t _service, instance_t _instance, - bool _reliable); // interface to stub inline std::shared_ptr<endpoint> find_local(client_t _client) { - return routing_manager_base::find_local(_client); + return ep_mgr_->find_local(_client); } inline std::shared_ptr<endpoint> find_or_create_local( client_t _client) { - return routing_manager_base::find_or_create_local(_client); + return ep_mgr_->find_or_create_local(_client); } + std::shared_ptr<endpoint> find_or_create_remote_client( + service_t _service, instance_t _instance, bool _reliable, + 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, + void on_stop_offer_service(client_t _client, + service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor); void on_availability(service_t _service, instance_t _instance, - bool _is_available, major_version_t _major, minor_version_t _minor); + bool _is_available, + major_version_t _major, minor_version_t _minor); void on_pong(client_t _client); + void on_subscribe_ack_with_multicast( + service_t _service, instance_t _instance, + const boost::asio::ip::address &_address, uint16_t _port); void on_unsubscribe_ack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - pending_subscription_id_t _unsubscription_id); - - // interface "endpoint_host" - std::shared_ptr<endpoint> find_or_create_remote_client(service_t _service, - instance_t _instance, - bool _reliable, client_t _client); - void on_connect(std::shared_ptr<endpoint> _endpoint); - void on_disconnect(std::shared_ptr<endpoint> _endpoint); - void on_error(const byte_t *_data, length_t _length, endpoint *_receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port); + remote_subscription_id_t _id); + + void on_connect(const std::shared_ptr<endpoint>& _endpoint); + void on_disconnect(const std::shared_ptr<endpoint>& _endpoint); + void on_message(const byte_t *_data, length_t _size, endpoint *_receiver, const boost::asio::ip::address &_destination, - client_t _bound_client, + client_t _bound_client, credentials_t _credentials, 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, - client_t _bound_client, bool _is_valid_crc = true, + client_t _bound_client, credentials_t _credentials, + uint8_t _check_status = 0, 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, @@ -206,29 +222,22 @@ public: bool _has_reliable, bool _has_unreliable); void update_routing_info(std::chrono::milliseconds _elapsed); - void on_remote_subscription( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - const std::shared_ptr<endpoint_definition> &_subscriber, - const std::shared_ptr<endpoint_definition> &_target, ttl_t _ttl, - const std::shared_ptr<sd_message_identifier_t> &_sd_message_id, - const std::function<void(remote_subscription_state_e, client_t)>& _callback); - void on_unsubscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, - std::shared_ptr<endpoint_definition> _target); - void on_subscribe_ack(service_t _service, instance_t _instance, - const boost::asio::ip::address &_address, uint16_t _port); + // Handle remote subscriptions / subscription acks + void on_remote_subscribe( + std::shared_ptr<remote_subscription> &_subscription, + const remote_subscription_callback_t& _callback); + void on_remote_unsubscribe( + std::shared_ptr<remote_subscription> &_subscription); 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(bool _force); - bool has_identified(client_t _client, service_t _service, - instance_t _instance, bool _reliable); - void register_client_error_handler(client_t _client, const std::shared_ptr<endpoint> &_endpoint); void handle_client_error(client_t _client); + std::shared_ptr<endpoint_manager_impl> get_endpoint_manager() const; void set_routing_state(routing_state_e _routing_state); @@ -241,46 +250,61 @@ 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 print_stub_status() const; + + void send_error(return_code_e _return_code, const byte_t *_data, + length_t _size, instance_t _instance, bool _reliable, + endpoint* const _receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); + void service_endpoint_connected(service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, + const std::shared_ptr<endpoint>& _endpoint, + bool _unreliable_only); + void service_endpoint_disconnected(service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, + const std::shared_ptr<endpoint>& _endpoint); + + void register_sd_acceptance_handler(const sd_acceptance_handler_t& _handler) const; + void register_reboot_notification_handler(const reboot_notification_handler_t& _handler) const; + void register_routing_ready_handler(const routing_ready_handler_t& _handler); + void register_routing_state_handler(const routing_state_handler_t& _handler); + void sd_acceptance_enabled(const 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); + bool update_security_policy_configuration(uint32_t _uid, uint32_t _gid, const std::shared_ptr<policy>& _policy, + const std::shared_ptr<payload>& _payload, const security_update_handler_t& _handler); + bool remove_security_policy_configuration(uint32_t _uid, uint32_t _gid, const security_update_handler_t& _handler); + client_t find_local_client(service_t _service, instance_t _instance); 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, + bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); private: + bool offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, + bool _must_queue); + + void stop_offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, + bool _must_queue); + 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); + credentials_t _credentials, + uint8_t _status_check = 0, bool _is_from_remote = false); bool deliver_notification(service_t _service, instance_t _instance, const byte_t *_data, length_t _length, bool _reliable, client_t _bound_client, - bool _is_valid_crc = true, bool _is_from_remote = false); + credentials_t _credentials, + uint8_t _status_check = 0, bool _is_from_remote = false); - instance_t find_instance(service_t _service, endpoint *_endpoint); void init_service_info(service_t _service, instance_t _instance, bool _is_local_service); - std::shared_ptr<endpoint> create_client_endpoint( - const boost::asio::ip::address &_address, - uint16_t _local_port, uint16_t _remote_port, - bool _reliable, client_t _client); - - std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port, - bool _reliable, bool _start); - std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port, - bool _reliable) const; - std::shared_ptr<endpoint> find_or_create_server_endpoint(uint16_t _port, - bool _reliable, bool _start); - bool is_field(service_t _service, instance_t _instance, event_t _event) const; @@ -290,74 +314,32 @@ private: std::shared_ptr<endpoint> create_remote_client(service_t _service, instance_t _instance, bool _reliable, client_t _client); - bool deliver_specific_endpoint_message(service_t _service, instance_t _instance, - const byte_t *_data, length_t _size, endpoint *_receiver); - void clear_client_endpoints(service_t _service, instance_t _instance, bool _reliable); void clear_multicast_endpoints(service_t _service, instance_t _instance); - bool is_identifying(client_t _client, service_t _service, - instance_t _instance, bool _reliable); - 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); - void send_error(return_code_e _return_code, const byte_t *_data, - length_t _size, instance_t _instance, bool _reliable, - endpoint *_receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port); - - void identify_for_subscribe(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - subscription_type_e _subscription_type); - bool send_identify_message(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - bool _reliable); - bool supports_selective(service_t _service, instance_t _instance); - client_t find_client(service_t _service, instance_t _instance, - const std::shared_ptr<eventgroupinfo> &_eventgroup, - const std::shared_ptr<endpoint_definition> &_target) const; - void clear_remote_subscriber(service_t _service, instance_t _instance, client_t _client, const std::shared_ptr<endpoint_definition> &_target); void log_version_timer_cbk(boost::system::error_code const & _error); - void clear_remote_service_info(service_t _service, instance_t _instance, bool _reliable); - bool handle_local_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major,minor_version_t _minor); - void remove_specific_client_endpoint(client_t _client, service_t _service, instance_t _instance, bool _reliable); - - void clear_identified_clients( service_t _service, instance_t _instance); - - void clear_identifying_clients( service_t _service, instance_t _instance); - - void remove_identified_client(service_t _service, instance_t _instance, client_t _client); - - void remove_identifying_client(service_t _service, instance_t _instance, client_t _client); - - void unsubscribe_specific_client_at_sd(service_t _service, instance_t _instance, client_t _client); - - inline std::shared_ptr<endpoint> find_local(service_t _service, instance_t _instance) { - return routing_manager_base::find_local(_service, _instance); - } - void send_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); + major_version_t _major, event_t _event); void on_net_interface_or_route_state_changed(bool _is_interface, std::string _if, @@ -373,7 +355,7 @@ private: void call_sd_endpoint_connected(const boost::system::error_code& _error, service_t _service, instance_t _instance, - std::shared_ptr<endpoint> _endpoint, + const std::shared_ptr<endpoint>& _endpoint, std::shared_ptr<boost::asio::steady_timer> _timer); bool create_placeholder_event_and_subscribe(service_t _service, @@ -385,29 +367,26 @@ private: void handle_subscription_state(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event); - client_t is_specific_endpoint_client(client_t _client, service_t _service, instance_t _instance); - std::unordered_set<client_t> get_specific_endpoint_clients(service_t _service, instance_t _instance); - void memory_log_timer_cbk(boost::system::error_code const & _error); void status_log_timer_cbk(boost::system::error_code const & _error); - void send_subscription(client_t _offering_client, - client_t _subscribing_client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, - pending_subscription_id_t _pending_subscription_id); + void send_subscription(const client_t _offering_client, + const service_t _service, const instance_t _instance, + const eventgroup_t _eventgroup, const major_version_t _major, + const std::set<client_t> &_clients, + const remote_subscription_id_t _id); - void send_unsubscription( - client_t _offering_client, client_t _subscribing_client, - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - pending_subscription_id_t _pending_unsubscription_id); + void send_unsubscription(client_t _offering_client, + const service_t _service, const instance_t _instance, + const eventgroup_t _eventgroup, const major_version_t _major, + const std::set<client_t> &_removed, + const remote_subscription_id_t _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); @@ -417,7 +396,7 @@ private: std::shared_ptr<boost::asio::steady_timer> _timer); pending_security_update_id_t pending_security_update_add( - std::unordered_set<client_t> _clients); + const std::unordered_set<client_t>& _clients); std::unordered_set<client_t> pending_security_update_get( pending_security_update_id_t _id); @@ -428,54 +407,28 @@ private: 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_; - - // Server endpoints for local services - typedef std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint>>> server_endpoints_t; - server_endpoints_t server_endpoints_; - std::map<service_t, std::map<endpoint *, instance_t> > service_instances_; + bool insert_offer_command(service_t _service, instance_t _instance, uint8_t _command, + client_t _client, major_version_t _major, minor_version_t _minor); + bool erase_offer_command(service_t _service, instance_t _instance); - // Multicast endpoint info (notifications) - std::map<service_t, std::map<instance_t, std::shared_ptr<endpoint_definition> > > multicast_info; + bool is_last_stop_callback(const uint32_t _callback_id); - // Client endpoints for remote services - std::map<service_t, - std::map<instance_t, std::map<bool, std::shared_ptr<endpoint_definition> > > > remote_service_info_; - - typedef std::map<service_t, std::map<instance_t, std::map<client_t, - std::map<bool, std::shared_ptr<endpoint>>>>> remote_services_t; - remote_services_t remote_services_; +private: + std::shared_ptr<routing_manager_stub> stub_; + std::shared_ptr<sd::service_discovery> discovery_; - typedef std::map<boost::asio::ip::address, std::map<uint16_t, - std::map<bool, std::shared_ptr<endpoint>>>> client_endpoints_by_ip_t; - client_endpoints_by_ip_t client_endpoints_by_ip_; + std::mutex requested_services_mutex_; std::map<client_t, std::map<service_t, std::map<instance_t, std::set<std::pair<major_version_t, minor_version_t>>>>> requested_services_; - // Mutexes - mutable std::recursive_mutex endpoint_mutex_; - std::mutex identified_clients_mutex_; - std::mutex requested_services_mutex_; - std::mutex remote_subscribers_mutex_; std::map<service_t, std::map<instance_t, std::map<client_t, std::set<std::shared_ptr<endpoint_definition>>>>> remote_subscribers_; - std::mutex specific_endpoint_clients_mutex_; - std::map<service_t, std::map<instance_t, std::unordered_set<client_t>>>specific_endpoint_clients_; - std::map<service_t, std::map<instance_t, - std::map<bool, std::unordered_set<client_t> > > > identified_clients_; - std::map<service_t, std::map<instance_t, - std::map<bool, std::unordered_set<client_t> > > > identifying_clients_; - std::shared_ptr<serviceinfo> sd_info_; - std::map<bool, std::set<uint16_t>> used_client_ports_; - std::mutex used_client_ports_mutex_; - std::mutex version_log_timer_mutex_; boost::asio::steady_timer version_log_timer_; @@ -488,12 +441,6 @@ private: std::shared_ptr<netlink_connector> netlink_connector_; #endif -#ifndef WITHOUT_SYSTEMD - std::mutex watchdog_timer_mutex_; - boost::asio::steady_timer watchdog_timer_; - void watchdog_cbk(boost::system::error_code const &_error); -#endif - std::mutex pending_offers_mutex_; // map to store pending offers. // 1st client id in tuple: client id of new offering application @@ -509,8 +456,7 @@ private: std::map<std::tuple<service_t, instance_t, eventgroup_t, client_t>, subscription_state_e> remote_subscription_state_; - 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::shared_ptr<e2e::e2e_provider> e2e_provider_; std::mutex status_log_timer_mutex_; boost::asio::steady_timer status_log_timer_; @@ -518,6 +464,10 @@ private: std::mutex memory_log_timer_mutex_; boost::asio::steady_timer memory_log_timer_; + std::shared_ptr<endpoint_manager_impl> ep_mgr_impl_; + + reboot_notification_handler_t reboot_notification_handler_; + routing_ready_handler_t routing_ready_handler_; routing_state_handler_t routing_state_handler_; @@ -537,8 +487,14 @@ private: std::mutex security_update_timers_mutex_; std::map<pending_security_update_id_t, std::shared_ptr<boost::asio::steady_timer>> security_update_timers_; + + std::mutex offer_serialization_mutex_; + std::map<std::pair<service_t, instance_t>, std::deque<std::tuple<uint8_t, client_t, major_version_t, minor_version_t>>> offer_commands_; + + std::mutex callback_counts_mutex_; + std::map<uint32_t, uint16_t> callback_counts_; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_ROUTING_MANAGER_IMPL_HPP +#endif // VSOMEIP_V3_ROUTING_MANAGER_IMPL_HPP_ diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp index fbe775d..d1a29df 100644 --- a/implementation/routing/include/routing_manager_proxy.hpp +++ b/implementation/routing/include/routing_manager_proxy.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_ROUTING_MANAGER_PROXY_HPP -#define VSOMEIP_ROUTING_MANAGER_PROXY_HPP +#ifndef VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP +#define VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP #include <map> #include <mutex> @@ -19,7 +19,7 @@ #include <vsomeip/enumeration_types.hpp> #include <vsomeip/handler.hpp> -namespace vsomeip { +namespace vsomeip_v3 { class configuration; class event; @@ -37,68 +37,70 @@ public: void start(); void stop(); - const std::shared_ptr<configuration> get_configuration() const; + std::shared_ptr<configuration> get_configuration() const; - bool offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor); + bool offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - void stop_offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor); + void stop_offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - void request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor, bool _use_exclusive_proxy); + void request_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor); - void release_service(client_t _client, service_t _service, - instance_t _instance); + void release_service(client_t _client, + service_t _service, instance_t _instance); - void 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); + void subscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, + eventgroup_t _eventgroup, major_version_t _major, + event_t _event); - void unsubscribe(client_t _client, service_t _service, instance_t _instance, + void unsubscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event); bool send(client_t _client, const byte_t *_data, uint32_t _size, - instance_t _instance, bool _flush, bool _reliable, + instance_t _instance, bool _reliable, client_t _bound_client = VSOMEIP_ROUTING_CLIENT, - bool _is_valid_crc = true, bool _sent_from_remote = false); + credentials_t _credentials = {ANY_UID, ANY_GID}, + uint8_t _status_check = 0, bool _sent_from_remote = false); - bool send_to(const std::shared_ptr<endpoint_definition> &_target, - std::shared_ptr<message> _message, bool _flush); + bool send_to(const client_t _client, + const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message> _message); bool send_to(const std::shared_ptr<endpoint_definition> &_target, - const byte_t *_data, uint32_t _size, instance_t _instance, bool _flush); + const byte_t *_data, uint32_t _size, instance_t _instance); - void register_event(client_t _client, service_t _service, - instance_t _instance, event_t _event, - const std::set<eventgroup_t> &_eventgroups, bool _is_field, + void register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, + const event_type_e _type, + reliability_type_e _reliability, std::chrono::milliseconds _cycle, bool _change_resets_cycle, + bool _update_on_change, epsilon_change_func_t _epsilon_change_func, bool _is_provided, bool _is_shadow, bool _is_cache_placeholder); void unregister_event(client_t _client, service_t _service, - instance_t _instance, event_t _event, - bool _is_provided); + instance_t _instance, event_t _notifier, bool _is_provided); - void on_connect(std::shared_ptr<endpoint> _endpoint); - void on_disconnect(std::shared_ptr<endpoint> _endpoint); + void on_connect(const std::shared_ptr<endpoint>& _endpoint); + void on_disconnect(const std::shared_ptr<endpoint>& _endpoint); void on_message(const byte_t *_data, length_t _size, endpoint *_receiver, const boost::asio::ip::address &_destination, client_t _bound_client, + credentials_t _credentials, const boost::asio::ip::address &_remote_address, std::uint16_t _remote_port); - 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 release_port(uint16_t _port, bool _reliable); void on_routing_info(const byte_t *_data, uint32_t _size); - void on_identify_response(client_t _client, service_t _service, instance_t _instance, - bool _reliable); - void register_client_error_handler(client_t _client, const std::shared_ptr<endpoint> &_endpoint); void handle_client_error(client_t _client); @@ -108,6 +110,7 @@ public: void send_get_offered_services_info(client_t _client, offer_type_e _offer_type); private: + void assign_client(); void register_application(); void deregister_application(); @@ -117,24 +120,25 @@ private: void send_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor); - void send_release_service(client_t _client, service_t _service, - instance_t _instance); - void send_register_event(client_t _client, service_t _service, - instance_t _instance, event_t _event, + void send_release_service(client_t _client, + service_t _service, instance_t _instance); + void send_register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, const std::set<eventgroup_t> &_eventgroups, - bool _is_field, bool _is_provided); + const event_type_e _type, reliability_type_e _reliability, + bool _is_provided); void send_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); + major_version_t _major, event_t _event); void send_subscribe_nack(client_t _subscriber, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, - pending_subscription_id_t _subscription_id); + remote_subscription_id_t _id); void send_subscribe_ack(client_t _subscriber, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, - pending_subscription_id_t _subscription_id); + remote_subscription_id_t _id); bool is_field(service_t _service, instance_t _instance, event_t _event) const; @@ -161,6 +165,8 @@ private: eventgroup_t _eventgroup, bool _increment); void clear_remote_subscriber_count(service_t _service, instance_t _instance); + void assign_client_timeout_cbk(boost::system::error_code const &_error); + void register_application_timeout_cbk(boost::system::error_code const &_error); void send_registered_ack(); @@ -171,19 +177,16 @@ private: bool is_client_known(client_t _client); - bool create_placeholder_event_and_subscribe(service_t _service, - instance_t _instance, - eventgroup_t _eventgroup, - event_t _event, - client_t _client); + bool create_placeholder_event_and_subscribe( + service_t _service, instance_t _instance, + eventgroup_t _eventgroup, event_t _notifier, client_t _client); void request_debounce_timeout_cbk(boost::system::error_code const &_error); void send_request_services(std::set<service_data_t>& _requests); void send_unsubscribe_ack(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, - pending_subscription_id_t _subscription_id); + eventgroup_t _eventgroup, remote_subscription_id_t _id); void resend_provided_event_registrations(); void send_resend_provided_event_response(pending_remote_offer_id_t _id); @@ -191,12 +194,15 @@ private: 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); + void on_client_assign_ack(const client_t &_client); private: enum class inner_state_type_e : std::uint8_t { ST_REGISTERED = 0x0, ST_DEREGISTERED = 0x1, - ST_REGISTERING = 0x2 + ST_REGISTERING = 0x2, + ST_ASSIGNING = 0x3, + ST_ASSIGNED = 0x4 }; std::atomic<bool> is_connected_; @@ -216,17 +222,18 @@ private: struct event_data_t { service_t service_; instance_t instance_; - event_t event_; - bool is_field_; + event_t notifier_; + event_type_e type_; + reliability_type_e reliability_; bool is_provided_; std::set<eventgroup_t> eventgroups_; bool operator<(const event_data_t &_other) const { - return std::tie(service_, instance_, event_, is_field_, - is_provided_, eventgroups_) - < std::tie(_other.service_, _other.instance_, _other.event_, - _other.is_field_, _other.is_provided_, - _other.eventgroups_); + return std::tie(service_, instance_, notifier_, + type_, reliability_, is_provided_, eventgroups_) + < std::tie(_other.service_, _other.instance_, + _other.notifier_, _other.type_, _other.reliability_, + _other.is_provided_, _other.eventgroups_); } }; std::set<event_data_t> pending_event_registrations_; @@ -255,6 +262,6 @@ private: const std::set<std::tuple<service_t, instance_t> > client_side_logging_filter_; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_ROUTING_MANAGER_PROXY_HPP +#endif // VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP_ diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp index d586518..4a37644 100644 --- a/implementation/routing/include/routing_manager_stub.hpp +++ b/implementation/routing/include/routing_manager_stub.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_ROUTING_MANAGER_STUB -#define VSOMEIP_ROUTING_MANAGER_STUB +#ifndef VSOMEIP_V3_ROUTING_MANAGER_STUB_ +#define VSOMEIP_V3_ROUTING_MANAGER_STUB_ #include <condition_variable> #include <list> @@ -20,54 +20,48 @@ #include <boost/asio/steady_timer.hpp> #include "../../endpoints/include/endpoint_host.hpp" -#include "../../configuration/include/internal.hpp" +#include "../include/routing_host.hpp" + #include "types.hpp" -namespace vsomeip { +namespace vsomeip_v3 { class configuration; class routing_manager_stub_host; -class routing_manager_stub: public endpoint_host, +class routing_manager_stub: public routing_host, public std::enable_shared_from_this<routing_manager_stub> { public: routing_manager_stub( routing_manager_stub_host *_host, - std::shared_ptr<configuration> _configuration); + const std::shared_ptr<configuration>& _configuration); virtual ~routing_manager_stub(); void init(); void start(); void stop(); - const std::shared_ptr<configuration> get_configuration() const; - - 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 _size, endpoint *_receiver, const boost::asio::ip::address &_destination, client_t _bound_client, + credentials_t _credentials, const boost::asio::ip::address &_remote_address, std::uint16_t _remote_port); - 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 release_port(uint16_t _port, bool _reliable); void on_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor); void on_stop_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor); - bool send_subscribe(std::shared_ptr<vsomeip::endpoint> _target, + bool send_subscribe(const std::shared_ptr<endpoint>& _target, client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, - event_t _event, pending_subscription_id_t _subscription_id); + eventgroup_t _eventgroup, major_version_t _major, event_t _event, + remote_subscription_id_t _id); - bool send_unsubscribe(std::shared_ptr<vsomeip::endpoint> _target, + bool send_unsubscribe(const std::shared_ptr<endpoint>& _target, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - event_t _event, pending_subscription_id_t _unsubscription_id); + event_t _event, remote_subscription_id_t _id); void send_subscribe_nack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event); @@ -86,14 +80,6 @@ public: 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, - service_t _service, instance_t _instance, major_version_t _major, - bool _reliable); - -#ifndef _WIN32 - virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid); -#endif - void update_registration(client_t _client, registration_type_e _type); void print_endpoint_status() const; @@ -103,12 +89,12 @@ public: bool is_policy_cached(uint32_t _uid); - void policy_cache_add(uint32_t _uid, std::shared_ptr<payload> _payload); + void policy_cache_add(uint32_t _uid, const 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); + uint32_t _uid, const 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); @@ -131,7 +117,6 @@ private: void on_pong(client_t _client); void start_watchdog(); void check_watchdog(); - void send_application_lost(std::list<client_t> &_lost); void client_registration_func(void); void init_routing_endpoint(); @@ -175,8 +160,6 @@ private: std::set<client_t> used_client_ids_; std::mutex used_client_ids_mutex_; - std::string endpoint_path_; - std::string local_receiver_path_; std::shared_ptr<endpoint> endpoint_; std::shared_ptr<endpoint> local_receiver_; std::mutex local_receiver_mutex_; @@ -186,8 +169,6 @@ private: mutable std::mutex routing_info_mutex_; std::shared_ptr<configuration> configuration_; - size_t routingCommandSize_; - bool is_socket_activated_; std::atomic<bool> client_registration_running_; std::shared_ptr<std::thread> client_registration_thread_; @@ -215,7 +196,6 @@ private: }; -} // namespace vsomeip - -#endif // VSOMEIP_ROUTING_MANAGER_STUB +} // namespace vsomeip_v3 +#endif // VSOMEIP_V3_ROUTING_MANAGER_STUB_ diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp index 5c474fb..b89134d 100644 --- a/implementation/routing/include/routing_manager_stub_host.hpp +++ b/implementation/routing/include/routing_manager_stub_host.hpp @@ -3,15 +3,17 @@ // 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_ROUTING_MANAGER_STUB_HOST -#define VSOMEIP_ROUTING_MANAGER_STUB_HOST +#ifndef VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_ +#define VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_ #include <boost/asio/io_service.hpp> #include <vsomeip/handler.hpp> #include "types.hpp" -namespace vsomeip { +namespace vsomeip_v3 { + +class endpoint_manager_impl; class routing_manager_stub_host { public: @@ -20,49 +22,52 @@ public: virtual bool offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor) = 0; + minor_version_t _minor, bool _must_queue = true) = 0; virtual void stop_offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor) = 0; - - virtual void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, bool _use_exclusive_proxy) = 0; + minor_version_t _minor, bool _must_queue = true) = 0; + + virtual void request_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) = 0; - virtual void release_service(client_t _client, service_t _service, - instance_t _instance) = 0; + virtual void release_service(client_t _client, + service_t _service, instance_t _instance) = 0; - virtual void register_shadow_event(client_t _client, service_t _service, - instance_t _instance, event_t _event, + virtual void register_shadow_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, const std::set<eventgroup_t> &_eventgroups, - bool _is_field, bool _is_provided) = 0; + event_type_e _type, reliability_type_e _reliability, + bool _is_provided) = 0; virtual void unregister_shadow_event(client_t _client, service_t _service, instance_t _instance, event_t _event, bool _is_provided) = 0; - virtual void subscribe(client_t _client, service_t _service, + virtual void subscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, event_t _event, - subscription_type_e _subscription_type) = 0; + major_version_t _major, event_t _event) = 0; virtual void on_subscribe_nack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, - pending_subscription_id_t _subscription_id) = 0; + remote_subscription_id_t _subscription_id) = 0; virtual void on_subscribe_ack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, - pending_subscription_id_t _subscription_id) = 0; + remote_subscription_id_t _subscription_id) = 0; - virtual void unsubscribe(client_t _client, service_t _service, + virtual void unsubscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) = 0; virtual void on_unsubscribe_ack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - pending_subscription_id_t _unsubscription_id) = 0; + remote_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, client_t _bound_client, - bool _is_valid_crc = true, bool _is_from_remote = false) = 0; + credentials_t _credentials, + uint8_t _status_check = 0, bool _is_from_remote = false) = 0; virtual void on_notification(client_t _client, service_t _service, instance_t _instance, @@ -84,25 +89,24 @@ public: virtual boost::asio::io_service & get_io() = 0; virtual client_t get_client() const = 0; - virtual void on_identify_response(client_t _client, service_t _service, instance_t _instance, - bool _reliable) = 0; - virtual void on_pong(client_t _client) = 0; virtual void handle_client_error(client_t _client) = 0; - virtual void set_routing_state(routing_state_e _routing_state) = 0; + virtual std::shared_ptr<endpoint_manager_impl> get_endpoint_manager() const = 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 client_t find_local_client(service_t _service, instance_t _instance) = 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, + virtual bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_ROUTING_MANAGER_STUB_HOST +#endif // VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_ diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp index 72be585..a405cf0 100644 --- a/implementation/routing/include/serviceinfo.hpp +++ b/implementation/routing/include/serviceinfo.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_SERVICEINFO_HPP -#define VSOMEIP_SERVICEINFO_HPP +#ifndef VSOMEIP_V3_SERVICEINFO_HPP_ +#define VSOMEIP_V3_SERVICEINFO_HPP_ #include <memory> #include <set> @@ -15,14 +15,15 @@ #include <vsomeip/export.hpp> #include <vsomeip/primitive_types.hpp> -namespace vsomeip { +namespace vsomeip_v3 { class endpoint; class servicegroup; class serviceinfo { public: - VSOMEIP_EXPORT serviceinfo(major_version_t _major, minor_version_t _minor, + VSOMEIP_EXPORT serviceinfo(service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, ttl_t _ttl, bool _is_local); VSOMEIP_EXPORT serviceinfo(const serviceinfo& _other); VSOMEIP_EXPORT ~serviceinfo(); @@ -30,6 +31,9 @@ public: VSOMEIP_EXPORT servicegroup * get_group() const; VSOMEIP_EXPORT void set_group(servicegroup *_group); + VSOMEIP_EXPORT service_t get_service() const; + VSOMEIP_EXPORT instance_t get_instance() const; + VSOMEIP_EXPORT major_version_t get_major() const; VSOMEIP_EXPORT minor_version_t get_minor() const; @@ -40,7 +44,7 @@ public: 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, + VSOMEIP_EXPORT void set_endpoint(const std::shared_ptr<endpoint>& _endpoint, bool _reliable); VSOMEIP_EXPORT void add_client(client_t _client); @@ -55,6 +59,9 @@ public: private: servicegroup *group_; + service_t service_; + instance_t instance_; + major_version_t major_; minor_version_t minor_; @@ -72,6 +79,6 @@ private: bool is_in_mainphase_; }; -} // namespace vsomeip +} // namespace vsomeip_v3 -#endif // VSOMEIP_SERVICEINFO_HPP +#endif // VSOMEIP_V3_SERVICEINFO_HPP_ diff --git a/implementation/routing/include/types.hpp b/implementation/routing/include/types.hpp index 59acfa3..389b226 100644 --- a/implementation/routing/include/types.hpp +++ b/implementation/routing/include/types.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_ROUTING_TYPES_HPP -#define VSOMEIP_ROUTING_TYPES_HPP +#ifndef VSOMEIP_V3_ROUTING_TYPES_HPP_ +#define VSOMEIP_V3_ROUTING_TYPES_HPP_ #include <map> #include <memory> @@ -13,10 +13,7 @@ #include <vsomeip/primitive_types.hpp> #include <vsomeip/constants.hpp> -#include "../../service_discovery/include/message_impl.hpp" -#include "../../configuration/include/internal.hpp" - -namespace vsomeip { +namespace vsomeip_v3 { class serviceinfo; class endpoint_definition; @@ -40,87 +37,20 @@ enum class registration_type_e : std::uint8_t { DEREGISTER_ON_ERROR = 0x3 }; -struct sd_message_identifier_t { - sd_message_identifier_t(session_t _session, - boost::asio::ip::address _sender, - boost::asio::ip::address _destination, - const std::shared_ptr<sd::message_impl> &_response) : - session_(_session), - sender_(_sender), - destination_(_destination), - response_(_response) { - } - - sd_message_identifier_t() : - session_(0), - sender_(boost::asio::ip::address()), - destination_(boost::asio::ip::address()), - response_(std::shared_ptr<sd::message_impl>()) { - } - - bool operator==(const sd_message_identifier_t &_other) const { - return !(session_ != _other.session_ || - sender_ != _other.sender_ || - destination_ != _other.destination_ || - response_ != _other.response_); - } - - bool operator<(const sd_message_identifier_t &_other) const { - return (session_ < _other.session_ - || (session_ == _other.session_ && sender_ < _other.sender_) - || (session_ == _other.session_ && sender_ == _other.sender_ - && destination_ < _other.destination_) - || (session_ == _other.session_ && sender_ == _other.sender_ - && destination_ == _other.destination_ - && response_ < _other.response_)); - } - - session_t session_; - boost::asio::ip::address sender_; - boost::asio::ip::address destination_; - std::shared_ptr<sd::message_impl> response_; -}; +enum class remote_subscription_state_e : std::uint8_t { + SUBSCRIPTION_PENDING = 0x00, -struct pending_subscription_t { - pending_subscription_t( - std::shared_ptr<sd_message_identifier_t> _sd_message_identifier, - std::shared_ptr<endpoint_definition> _subscriber, - std::shared_ptr<endpoint_definition> _target, - ttl_t _ttl, - client_t _subscribing_client) : - sd_message_identifier_(_sd_message_identifier), - subscriber_(_subscriber), - target_(_target), - ttl_(_ttl), - subscribing_client_(_subscribing_client), - pending_subscription_id_(DEFAULT_SUBSCRIPTION) { - } - pending_subscription_t () : - sd_message_identifier_(std::shared_ptr<sd_message_identifier_t>()), - subscriber_(std::shared_ptr<endpoint_definition>()), - target_(std::shared_ptr<endpoint_definition>()), - ttl_(0), - subscribing_client_(VSOMEIP_ROUTING_CLIENT), - pending_subscription_id_(DEFAULT_SUBSCRIPTION) { - } - std::shared_ptr<sd_message_identifier_t> sd_message_identifier_; - std::shared_ptr<endpoint_definition> subscriber_; - std::shared_ptr<endpoint_definition> target_; - ttl_t ttl_; - client_t subscribing_client_; - pending_subscription_id_t pending_subscription_id_; -}; + SUBSCRIPTION_ACKED = 0x01, + SUBSCRIPTION_NACKED = 0x02, -enum remote_subscription_state_e : std::uint8_t { - SUBSCRIPTION_ACKED, - SUBSCRIPTION_NACKED, - SUBSCRIPTION_PENDING, - SUBSCRIPTION_ERROR + SUBSCRIPTION_ERROR = 0x03, + SUBSCRIPTION_UNKNOWN = 0xFF }; +typedef std::uint16_t remote_subscription_id_t; typedef std::uint32_t pending_remote_offer_id_t; } -// namespace vsomeip +// namespace vsomeip_v3 -#endif // VSOMEIP_ROUTING_TYPES_HPP +#endif // VSOMEIP_V3_ROUTING_TYPES_HPP_ diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp index ce78a65..7575733 100644 --- a/implementation/routing/src/event.cpp +++ b/implementation/routing/src/event.cpp @@ -4,25 +4,27 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include <iomanip> +#include <sstream> #include <vsomeip/constants.hpp> #include <vsomeip/defines.hpp> #include <vsomeip/message.hpp> #include <vsomeip/payload.hpp> #include <vsomeip/runtime.hpp> +#include <vsomeip/internal/logger.hpp> #include "../include/event.hpp" #include "../include/routing_manager.hpp" -#include "../../configuration/include/internal.hpp" -#include "../../logging/include/logger.hpp" #include "../../message/include/payload_impl.hpp" -namespace vsomeip { +#include "../../endpoints/include/endpoint_definition.hpp" + +namespace vsomeip_v3 { event::event(routing_manager *_routing, bool _is_shadow) : routing_(_routing), message_(runtime::get()->create_notification()), - is_field_(false), + type_(event_type_e::ET_EVENT), cycle_timer_(_routing->get_io()), cycle_(std::chrono::milliseconds::zero()), change_resets_cycle_(false), @@ -33,8 +35,7 @@ event::event(routing_manager *_routing, bool _is_shadow) : is_cache_placeholder_(false), epsilon_change_func_(std::bind(&event::compare, this, std::placeholders::_1, std::placeholders::_2)), - is_reliable_(false), - remote_notification_pending_(false) { + reliability_(reliability_type_e::RT_UNKNOWN) { } service_t event::get_service() const { @@ -69,12 +70,16 @@ void event::set_event(event_t _event) { message_->set_method(_event); // TODO: maybe we should check for the leading 0-bit } -bool event::is_field() const { - return (is_field_); +event_type_e event::get_type() const { + return (type_); } -void event::set_field(bool _is_field) { - is_field_ = _is_field; +void event::set_type(const event_type_e _type) { + type_ = _type; +} + +bool event::is_field() const { + return (type_ == event_type_e::ET_FIELD); } bool event::is_provided() const { @@ -109,8 +114,7 @@ bool event::set_payload_dont_notify(const std::shared_ptr<payload> &_payload) { return true; } -void event::set_payload(const std::shared_ptr<payload> &_payload, - bool _force, bool _flush) { +void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) { std::lock_guard<std::mutex> its_lock(mutex_); if (is_provided_) { if (set_payload_helper(_payload, _force)) { @@ -119,7 +123,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, if (change_resets_cycle_) stop_cycle(); - notify(_flush); + notify(); if (change_resets_cycle_) start_cycle(); @@ -132,13 +136,13 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, } void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _client, - bool _force, bool _flush) { + bool _force) { std::lock_guard<std::mutex> its_lock(mutex_); if (is_provided_) { if (set_payload_helper(_payload, _force)) { reset_payload(_payload); if (is_updating_on_change_) { - notify_one_unlocked(_client, _flush); + notify_one_unlocked(_client); } } } else { @@ -148,14 +152,15 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _clie } void event::set_payload(const std::shared_ptr<payload> &_payload, - const std::shared_ptr<endpoint_definition> _target, - bool _force, bool _flush) { + const client_t _client, + const std::shared_ptr<endpoint_definition>& _target, + bool _force) { std::lock_guard<std::mutex> its_lock(mutex_); if (is_provided_) { if (set_payload_helper(_payload, _force)) { reset_payload(_payload); if (is_updating_on_change_) { - notify_one_unlocked(_target, _flush); + notify_one_unlocked(_client, _target); } } } else { @@ -164,6 +169,25 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, } } +bool event::set_payload_notify_pending(const std::shared_ptr<payload> &_payload) { + std::lock_guard<std::mutex> its_lock(mutex_); + if (!is_set_ && is_provided_) { + reset_payload(_payload); + + // Send pending initial events. + for (const auto &its_target : pending_) { + message_->set_session(routing_->get_session()); + routing_->send_to(VSOMEIP_ROUTING_CLIENT, + its_target, message_); + } + pending_.clear(); + + return true; + } + + return false; +} + void event::unset_payload(bool _force) { std::lock_guard<std::mutex> its_lock(mutex_); if (_force) { @@ -209,7 +233,7 @@ const std::set<eventgroup_t> event::get_eventgroups() const { std::set<eventgroup_t> its_eventgroups; { std::lock_guard<std::mutex> its_lock(eventgroups_mutex_); - for (const auto e : eventgroups_) { + for (const auto& e : eventgroups_) { its_eventgroups.insert(e.first); } } @@ -243,7 +267,7 @@ void event::update_cbk(boost::system::error_code const &_error) { if (!_error) { std::lock_guard<std::mutex> its_lock(mutex_); cycle_timer_.expires_from_now(cycle_); - notify(true); + notify(); auto its_handler = std::bind(&event::update_cbk, shared_from_this(), std::placeholders::_1); @@ -251,47 +275,70 @@ void event::update_cbk(boost::system::error_code const &_error) { } } -void event::notify(bool _flush) { +void event::notify() { if (is_set_) { - routing_->send(VSOMEIP_ROUTING_CLIENT, message_, _flush); + message_->set_session(routing_->get_session()); + routing_->send(VSOMEIP_ROUTING_CLIENT, message_); } else { - VSOMEIP_INFO << "Notify event " << std::hex << message_->get_method() - << "failed. Event payload not set!"; + VSOMEIP_INFO << __func__ + << ": Notifying " << std::hex << get_event() + << " failed. Event payload not (yet) set!"; } } -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(client_t _client, + const std::shared_ptr<endpoint_definition> &_target) { + if (_target) { + std::lock_guard<std::mutex> its_lock(mutex_); + notify_one_unlocked(_client, _target); + } else { + VSOMEIP_WARNING << __func__ + << ": Notifying " << std::hex << get_event() + << " failed. Target undefined"; + } } -void event::notify_one_unlocked(const std::shared_ptr<endpoint_definition> &_target, bool _flush) { - if (is_set_) { - routing_->send_to(_target, message_, _flush); +void event::notify_one_unlocked(client_t _client, + const std::shared_ptr<endpoint_definition> &_target) { + if (_target) { + if (is_set_) { + message_->set_session(routing_->get_session()); + routing_->send_to(_client, _target, message_); + } else { + VSOMEIP_INFO << __func__ + << ": Notifying " << std::hex << get_event() + << " failed. Event payload not (yet) set!"; + pending_.insert(_target); + } } else { - VSOMEIP_INFO << "Notify one event " << std::hex << message_->get_method() - << "failed. Event payload not set!"; + VSOMEIP_WARNING << __func__ + << ": Notifying " << std::hex << get_event() + << " failed. Target undefined"; } } -void event::notify_one(client_t _client, bool _flush) { +void event::notify_one(client_t _client) { std::lock_guard<std::mutex> its_lock(mutex_); - notify_one_unlocked(_client, _flush); + notify_one_unlocked(_client); } -void event::notify_one_unlocked(client_t _client, bool _flush) { +void event::notify_one_unlocked(client_t _client) { if (is_set_) { - routing_->send(_client, message_, _flush); + message_->set_session(routing_->get_session()); + routing_->send(_client, message_); } else { - VSOMEIP_INFO << "Notify one event " << std::hex << message_->get_method() - << " to client " << _client << " failed. Event payload not set!"; + VSOMEIP_INFO << __func__ + << ": Notifying " + << std::hex << message_->get_method() + << " to client " << _client + << " failed. Event payload not set!"; } } bool event::set_payload_helper(const std::shared_ptr<payload> &_payload, bool _force) { std::shared_ptr<payload> its_payload = message_->get_payload(); - bool is_change(!is_field_); - if (is_field_) { + bool is_change(type_ != event_type_e::ET_FIELD); + if (!is_change) { is_change = _force || epsilon_change_func_(its_payload, _payload); } return is_change; @@ -357,7 +404,7 @@ bool event::add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _for } else { VSOMEIP_WARNING << __func__ << ": Didnt' insert client " << std::hex << std::setw(4) << std::setfill('0') << _client - << "to eventgroup 0x" + << " to eventgroup 0x" << std::hex << std::setw(4) << std::setfill('0') << _eventgroup; } return ret; @@ -480,20 +527,20 @@ bool event::is_subscribed(client_t _client) { return false; } -bool event::is_reliable() const { - return is_reliable_; +reliability_type_e +event::get_reliability() const { + return reliability_; } -void event::set_reliable(bool _is_reliable) { - is_reliable_ = _is_reliable; +void +event::set_reliability(const reliability_type_e _reliability) { + reliability_ = _reliability; } -bool event::get_remote_notification_pending() { - return remote_notification_pending_; -} - -void event::set_remote_notification_pending(bool _value) { - remote_notification_pending_ = _value; +void +event::remove_pending(const std::shared_ptr<endpoint_definition> &_target) { + std::lock_guard<std::mutex> its_lock(mutex_); + pending_.erase(_target); } -} // namespace vsomeip +} // namespace vsomeip_v3 diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp index 77bb228..52c6c1e 100644 --- a/implementation/routing/src/eventgroupinfo.cpp +++ b/implementation/routing/src/eventgroupinfo.cpp @@ -4,46 +4,77 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include <algorithm> +#include <iomanip> #include <vsomeip/constants.hpp> - +#include <vsomeip/internal/logger.hpp> #include "../include/eventgroupinfo.hpp" #include "../include/event.hpp" +#include "../include/remote_subscription.hpp" #include "../../endpoints/include/endpoint_definition.hpp" -#include "../../logging/include/logger.hpp" -#include "../../configuration/include/internal.hpp" - -namespace vsomeip { -eventgroupinfo::eventgroupinfo() : - major_(DEFAULT_MAJOR), - ttl_(DEFAULT_TTL), - port_(ILLEGAL_PORT), - threshold_(0), - has_reliable_(false), - has_unreliable_(false), - subscription_id_(DEFAULT_SUBSCRIPTION) { +namespace vsomeip_v3 { + +eventgroupinfo::eventgroupinfo() + : service_(0), + instance_(0), + eventgroup_(0), + major_(DEFAULT_MAJOR), + ttl_(DEFAULT_TTL), + port_(ILLEGAL_PORT), + threshold_(0), + id_(PENDING_SUBSCRIPTION_ID), + reliability_(reliability_type_e::RT_UNKNOWN) { } -eventgroupinfo::eventgroupinfo(major_version_t _major, ttl_t _ttl) : - major_(_major), - ttl_(_ttl), - port_(ILLEGAL_PORT), - threshold_(0), - has_reliable_(false), - has_unreliable_(false), - subscription_id_(DEFAULT_SUBSCRIPTION) { +eventgroupinfo::eventgroupinfo( + const service_t _service, const instance_t _instance, + const eventgroup_t _eventgroup, const major_version_t _major, + const ttl_t _ttl) + : service_(_service), + instance_(_instance), + eventgroup_(_eventgroup), + major_(_major), + ttl_(_ttl), + port_(ILLEGAL_PORT), + threshold_(0), + id_(PENDING_SUBSCRIPTION_ID), + reliability_(reliability_type_e::RT_UNKNOWN) { } eventgroupinfo::~eventgroupinfo() { } +service_t eventgroupinfo::get_service() const { + return service_; +} + +void eventgroupinfo::set_service(const service_t _service) { + service_ = _service; +} + +instance_t eventgroupinfo::get_instance() const { + return instance_; +} + +void eventgroupinfo::set_instance(const instance_t _instance) { + instance_ = _instance; +} + +eventgroup_t eventgroupinfo::get_eventgroup() const { + return eventgroup_; +} + +void eventgroupinfo::set_eventgroup(const eventgroup_t _eventgroup) { + eventgroup_ = _eventgroup; +} + major_version_t eventgroupinfo::get_major() const { return major_; } -void eventgroupinfo::set_major(major_version_t _major) { +void eventgroupinfo::set_major(const major_version_t _major) { major_ = _major; } @@ -51,7 +82,7 @@ ttl_t eventgroupinfo::get_ttl() const { return ttl_; } -void eventgroupinfo::set_ttl(ttl_t _ttl) { +void eventgroupinfo::set_ttl(const ttl_t _ttl) { ttl_ = _ttl; } @@ -89,264 +120,239 @@ const std::set<std::shared_ptr<event> > eventgroupinfo::get_events() const { return events_; } -void eventgroupinfo::add_event(std::shared_ptr<event> _event) { +void eventgroupinfo::add_event(const std::shared_ptr<event>& _event) { std::lock_guard<std::mutex> its_lock(events_mutex_); events_.insert(_event); - _event->is_reliable() ? has_reliable_ = true : has_unreliable_ = true; + + switch (_event->get_reliability()) { + case reliability_type_e::RT_RELIABLE: + if (reliability_ == reliability_type_e::RT_UNRELIABLE) { + reliability_ = reliability_type_e::RT_BOTH; + } else if (reliability_ != reliability_type_e::RT_BOTH) { + reliability_ = reliability_type_e::RT_RELIABLE; + } + break; + case reliability_type_e::RT_UNRELIABLE: + if (reliability_ == reliability_type_e::RT_RELIABLE) { + reliability_ = reliability_type_e::RT_BOTH; + } else if (reliability_ != reliability_type_e::RT_BOTH) { + reliability_ = reliability_type_e::RT_UNRELIABLE; + } + break; + case reliability_type_e::RT_BOTH: + reliability_ = reliability_type_e::RT_BOTH; + break; + default: + ; + } } -void eventgroupinfo::remove_event(std::shared_ptr<event> _event) { +void eventgroupinfo::remove_event(const std::shared_ptr<event>& _event) { std::lock_guard<std::mutex> its_lock(events_mutex_); events_.erase(_event); } -void eventgroupinfo::get_reliability(bool& _has_reliable, bool& _has_unreliable) const { - _has_reliable = has_reliable_; - _has_unreliable = has_unreliable_; +reliability_type_e eventgroupinfo::get_reliability() const { + return reliability_; } -const std::list<eventgroupinfo::target_t> eventgroupinfo::get_targets() const { - std::lock_guard<std::mutex> its_lock(targets_mutex_); - return targets_; -} +uint32_t +eventgroupinfo::get_unreliable_target_count() const { + uint32_t its_count(0); -uint32_t eventgroupinfo::get_unreliable_target_count() const { - uint32_t _count(0); - std::lock_guard<std::mutex> its_lock(targets_mutex_); - for (auto i = targets_.begin(); i != targets_.end(); i++) { - if (!i->endpoint_->is_reliable()) { - _count++; - } + std::lock_guard<std::mutex> its_lock(subscriptions_mutex_); + for (const auto &s : subscriptions_) { + auto its_subscription = s.second; + if (!its_subscription->get_parent() + && its_subscription->get_unreliable()) { + its_count++; + } } - return _count; + + return its_count; } -void eventgroupinfo::add_multicast_target(const eventgroupinfo::target_t &_multicast_target) { - std::lock_guard<std::mutex> its_lock(multicast_targets_mutex_); - if (std::find(multicast_targets_.begin(), multicast_targets_.end(), _multicast_target) - == multicast_targets_.end()) { - multicast_targets_.push_back(_multicast_target); - } +uint8_t eventgroupinfo::get_threshold() const { + return threshold_; } -void eventgroupinfo::clear_multicast_targets() { - std::lock_guard<std::mutex> its_lock(multicast_targets_mutex_); - multicast_targets_.clear(); +void eventgroupinfo::set_threshold(uint8_t _threshold) { + threshold_ = _threshold; } -const std::list<eventgroupinfo::target_t> eventgroupinfo::get_multicast_targets() const { - std::lock_guard<std::mutex> its_lock(multicast_targets_mutex_); - return multicast_targets_; +std::set<std::shared_ptr<remote_subscription> > +eventgroupinfo::get_remote_subscriptions() const { + std::set<std::shared_ptr<remote_subscription> > its_subscriptions; + + std::lock_guard<std::mutex> its_lock(subscriptions_mutex_); + for (const auto &i : subscriptions_) + its_subscriptions.insert(i.second); + + return its_subscriptions; } -bool eventgroupinfo::add_target(const eventgroupinfo::target_t &_target) { - std::lock_guard<std::mutex> its_lock(targets_mutex_); - std::size_t its_size = targets_.size(); - if (std::find(targets_.begin(), targets_.end(), _target) == targets_.end()) { - targets_.push_back(_target); - } - return (its_size != targets_.size()); -} - -bool eventgroupinfo::add_target(const eventgroupinfo::target_t &_target, - const eventgroupinfo::target_t &_subscriber) { - bool found(false); - bool add(false); - bool ret(false); - { - std::lock_guard<std::mutex> its_lock(targets_mutex_); - std::size_t its_size = targets_.size(); - - for (auto i = targets_.begin(); i != targets_.end(); i++) { - if (i->endpoint_->get_address() == _subscriber.endpoint_->get_address() && - i->endpoint_->get_port() == _subscriber.endpoint_->get_port() && - i->endpoint_->is_reliable() == _subscriber.endpoint_->is_reliable()) { - found = true; - break; +bool +eventgroupinfo::update_remote_subscription( + const std::shared_ptr<remote_subscription> &_subscription, + const std::chrono::steady_clock::time_point &_expiration, + std::set<client_t> &_changed, remote_subscription_id_t &_id, + const bool _is_subscribe) { + std::lock_guard<std::mutex> its_lock(subscriptions_mutex_); + + for (const auto& its_item : subscriptions_) { + if (its_item.second->equals(_subscription)) { + // update existing subscription + _changed = its_item.second->update( + _subscription->get_clients(), _expiration, _is_subscribe); + _id = its_item.second->get_id(); + + // Copy acknowledgment states from existing subscription + for (const auto its_client : _subscription->get_clients()) { + _subscription->set_client_state(its_client, + its_item.second->get_client_state(its_client)); } - } - if (!found) { - targets_.push_back(_subscriber); - add = true; - } - ret = (its_size != targets_.size()); - } - if (add) { - add_multicast_target(_target); - } - return ret; -} - -bool eventgroupinfo::update_target( - const std::shared_ptr<endpoint_definition> &_target, - const std::chrono::steady_clock::time_point &_expiration) { - std::lock_guard<std::mutex> its_lock(targets_mutex_); - bool updated_target(false); - - for (auto i = targets_.begin(); i != targets_.end(); i++) { - if (i->endpoint_->get_address() == _target->get_address() && - i->endpoint_->get_port() == _target->get_port() && - i->endpoint_->is_reliable() == _target->is_reliable() ) { - i->expiration_ = _expiration; - updated_target = true; - break; + if (_is_subscribe) { + if (!_changed.empty()) { + // New clients: + // Let this be a child subscription + _subscription->set_parent(its_item.second); + update_id(); + _subscription->set_id(id_); + subscriptions_[id_] = _subscription; + } else { + if (!_subscription->is_pending()) { + if (!_subscription->force_initial_events()) { + _subscription->set_initial(false); + } + } else { + its_item.second->set_answers( + its_item.second->get_answers() + 1); + } + } + } else { + if (its_item.second->is_pending()) { + for (const auto &its_event : events_) + its_event->remove_pending( + its_item.second->get_subscriber()); + } + } + + return true; } } - return updated_target; + + return false; } -bool eventgroupinfo::remove_target( - const std::shared_ptr<endpoint_definition> &_target) { - std::lock_guard<std::mutex> its_lock(targets_mutex_); - std::size_t its_size = targets_.size(); +remote_subscription_id_t +eventgroupinfo::add_remote_subscription( + const std::shared_ptr<remote_subscription> &_subscription) { + std::lock_guard<std::mutex> its_lock(subscriptions_mutex_); + update_id(); - for (auto i = targets_.begin(); i != targets_.end(); i++) { - if (i->endpoint_->get_address() == _target->get_address() && - i->endpoint_->get_port() == _target->get_port() && - i->endpoint_->is_reliable() == _target->is_reliable()) { - targets_.erase(i); - break; - } - } + _subscription->set_id(id_); + subscriptions_[id_] = _subscription; - return (its_size != targets_.size()); + return id_; } -void eventgroupinfo::clear_targets() { - std::lock_guard<std::mutex> its_lock(targets_mutex_); - targets_.clear(); +std::shared_ptr<remote_subscription> +eventgroupinfo::get_remote_subscription( + const remote_subscription_id_t _id) { + std::lock_guard<std::mutex> its_lock(subscriptions_mutex_); + + auto find_subscription = subscriptions_.find(_id); + if (find_subscription != subscriptions_.end()) + return find_subscription->second; + + return nullptr; } -uint8_t eventgroupinfo::get_threshold() const { - return threshold_; +void +eventgroupinfo::remove_remote_subscription( + const remote_subscription_id_t _id) { + std::lock_guard<std::mutex> its_lock(subscriptions_mutex_); + subscriptions_.erase(_id); } -void eventgroupinfo::set_threshold(uint8_t _threshold) { - threshold_ = _threshold; +std::set<std::shared_ptr<endpoint_definition> > +eventgroupinfo::get_unicast_targets() const { + std::set<std::shared_ptr<endpoint_definition>> its_targets; + + std::lock_guard<std::mutex> its_lock(subscriptions_mutex_); + for (const auto &s : subscriptions_) { + const auto its_reliable = s.second->get_reliable(); + if (its_reliable) + its_targets.insert(its_reliable); + const auto its_unreliable = s.second->get_unreliable(); + if (its_unreliable) + its_targets.insert(its_unreliable); + } + + return its_targets; } -std::unique_lock<std::mutex> eventgroupinfo::get_subscription_lock() { - return std::unique_lock<std::mutex>(subscription_mutex_); +std::set<std::shared_ptr<endpoint_definition> > +eventgroupinfo::get_multicast_targets() const { + std::set<std::shared_ptr<endpoint_definition>> its_targets; + return its_targets; } -pending_subscription_id_t eventgroupinfo::add_pending_subscription( - pending_subscription_t _pending_subscription) { - std::lock_guard<std::mutex> its_lock(pending_subscriptions_mutex_); - if (++subscription_id_ == DEFAULT_SUBSCRIPTION) { - subscription_id_++; - } - _pending_subscription.pending_subscription_id_ = subscription_id_; - pending_subscriptions_[subscription_id_] = _pending_subscription; - - const auto remote_address_port = std::make_tuple( - _pending_subscription.subscriber_->get_address(), - _pending_subscription.subscriber_->get_port(), - _pending_subscription.subscriber_->is_reliable()); - - auto found_address = pending_subscriptions_by_remote_.find(remote_address_port); - if (found_address != pending_subscriptions_by_remote_.end()) { - found_address->second.push_back(subscription_id_); - VSOMEIP_WARNING << __func__ << " num pending subscriptions: " - << std::dec << found_address->second.size(); - return DEFAULT_SUBSCRIPTION; - } else { - pending_subscriptions_by_remote_[remote_address_port].push_back(subscription_id_); - } - return subscription_id_; -} - -std::vector<pending_subscription_t> eventgroupinfo::remove_pending_subscription( - pending_subscription_id_t _subscription_id) { - std::vector<pending_subscription_t> its_pending_subscriptions; - std::lock_guard<std::mutex> its_lock(pending_subscriptions_mutex_); - const auto found_pending_subscription = pending_subscriptions_.find( - _subscription_id); - if (found_pending_subscription != pending_subscriptions_.end()) { - pending_subscription_t its_pending_sub = found_pending_subscription->second; - const auto remote_address_port = std::make_tuple( - its_pending_sub.subscriber_->get_address(), - its_pending_sub.subscriber_->get_port(), - its_pending_sub.subscriber_->is_reliable()); - const bool removed_is_subscribe = (found_pending_subscription->second.ttl_ > 0); - - // check if more (un)subscriptions to this eventgroup arrived from the - // same remote during the time the current pending subscription was processed - auto found_remote = pending_subscriptions_by_remote_.find(remote_address_port); - if (found_remote != pending_subscriptions_by_remote_.end()) { - if (found_remote->second.size() - && found_remote->second.front() == _subscription_id) { - pending_subscriptions_.erase(found_pending_subscription); - found_remote->second.erase(found_remote->second.begin()); - - // return removed (un)subscription as first element - its_pending_subscriptions.push_back(its_pending_sub); - - // retrieve all pending (un)subscriptions which arrived during - // the time the rm_proxy answered the currently processed subscription - for (auto iter = found_remote->second.begin(); - iter != found_remote->second.end();) { - const auto other_pen_sub = pending_subscriptions_.find(*iter); - if (other_pen_sub != pending_subscriptions_.end()) { - const bool queued_is_subscribe = (other_pen_sub->second.ttl_ > 0); - if (removed_is_subscribe) { - its_pending_subscriptions.push_back(other_pen_sub->second); - if (!queued_is_subscribe) { - // unsubscribe was queued and needs to be sent to - // rm_proxy first before continuing processing - // following queued (un)subscriptions - break; - } else { - iter = found_remote->second.erase(iter); - pending_subscriptions_.erase(other_pen_sub); - } - } else { - if (queued_is_subscribe) { - // subscribe was queued and needs to be sent to - // rm_proxy first before continuing processing - // following queued (un)subscriptions - its_pending_subscriptions.push_back(other_pen_sub->second); - break; - } else { - // further queued unsubscriptions can be ignored - iter = found_remote->second.erase(iter); - pending_subscriptions_.erase(other_pen_sub); - } - } - } else { - VSOMEIP_ERROR << __func__ << " didn't find queued subscription: " - << *iter; - ++iter; - } - } +bool eventgroupinfo::is_selective() const { + /* Selective eventgroups always contain a single event */ + std::lock_guard<std::mutex> its_lock(events_mutex_); + if (events_.size() != 1) + return false; - if (found_remote->second.empty()) { - pending_subscriptions_by_remote_.erase(found_remote); - } - } else { - boost::system::error_code ec; - VSOMEIP_WARNING << __func__ << " Subscriptions were answered in " - << " in wrong order by rm_proxy! [" - << " subscriber: " << std::get<0>(remote_address_port).to_string(ec) - << ":" << std::dec << std::get<1>(remote_address_port); - // found_pending_subscription isn't deleted from - // pending_subscriptions_ map in this case to ensure answer - // sequence of SD messages. - its_pending_subscriptions.clear(); - } - } - } else { - VSOMEIP_ERROR << __func__ << " didn't find pending_subscription: " - << _subscription_id; - } - return its_pending_subscriptions; + return ((*events_.begin())->get_type() + == event_type_e::ET_SELECTIVE_EVENT); } +void +eventgroupinfo::update_id() { + id_++; + if (id_ == PENDING_SUBSCRIPTION_ID) + id_ = 1; +} -void eventgroupinfo::clear_pending_subscriptions() { - std::lock_guard<std::mutex> its_lock(pending_subscriptions_mutex_); - pending_subscriptions_.clear(); - pending_subscriptions_by_remote_.clear(); +void +eventgroupinfo::send_initial_events( + const std::shared_ptr<endpoint_definition> &_reliable, + const std::shared_ptr<endpoint_definition> &_unreliable) const { + std::lock_guard<std::mutex> its_lock(events_mutex_); + for (const auto &its_event : events_) { + if (its_event && its_event->get_type() == event_type_e::ET_FIELD) { +#ifndef VSOMEIP_ENABLE_COMPAT + const auto its_reliability = its_event->get_reliability(); + switch (its_reliability) { + case reliability_type_e::RT_RELIABLE: + its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable); + break; + case reliability_type_e::RT_UNRELIABLE: + its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable); + break; + case reliability_type_e::RT_BOTH: + its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable); + its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable); + break; + default: + VSOMEIP_WARNING << __func__ << "Event reliability unknown: [" + << 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_event->get_event() << "]"; + } +#else + if (_reliable) { + its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable); + } + if (_unreliable) { + its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable); + } +#endif + } + } } -} // namespace vsomeip +} // namespace vsomeip_v3 diff --git a/implementation/routing/src/remote_subscription.cpp b/implementation/routing/src/remote_subscription.cpp new file mode 100644 index 0000000..a896b36 --- /dev/null +++ b/implementation/routing/src/remote_subscription.cpp @@ -0,0 +1,315 @@ +// Copyright (C) 2018 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/remote_subscription.hpp" + +#include <vsomeip/internal/logger.hpp> + +namespace vsomeip_v3 { + +remote_subscription::remote_subscription() + : id_(PENDING_SUBSCRIPTION_ID), + is_initial_(true), + force_initial_events_(false), + major_(DEFAULT_MAJOR), + ttl_(DEFAULT_TTL), + reserved_(0), + counter_(0), + answers_(1) { +} + +remote_subscription::~remote_subscription() { +} + +bool +remote_subscription::operator==( + const remote_subscription &_other) const { + auto own_egi = eventgroupinfo_.lock(); + auto other_egi = _other.eventgroupinfo_.lock(); + bool reliable_equal(true); + if (reliable_ && _other.reliable_) { + reliable_equal = (reliable_ == _other.reliable_); + } + bool unreliable_equal(true); + if (unreliable_ && _other.unreliable_) { + unreliable_equal = (unreliable_ == _other.unreliable_); + } + return (own_egi && other_egi && own_egi == other_egi && unreliable_equal + && reliable_equal); +} + +bool +remote_subscription::equals( + const std::shared_ptr<remote_subscription> &_other) const { + return operator ==(*_other); +} + +void +remote_subscription::reset(const std::set<client_t> &_clients) { + auto its_client_state = std::make_pair( + remote_subscription_state_e::SUBSCRIPTION_PENDING, + std::chrono::steady_clock::time_point()); + if (_clients.empty()) { + clients_[0] = its_client_state; + } else { + for (const auto &its_client : _clients) + clients_[its_client] = its_client_state; + } +} + +bool +remote_subscription::is_initial() const { + return is_initial_; +} + +void +remote_subscription::set_initial(const bool _is_initial) { + is_initial_ = _is_initial; +} + +bool +remote_subscription::force_initial_events() const { + return force_initial_events_; +} + +void +remote_subscription::set_force_initial_events( + const bool _force_initial_events) { + force_initial_events_ = _force_initial_events; +} + +remote_subscription_id_t +remote_subscription::get_id() const { + return id_; +} + +void +remote_subscription::set_id(const remote_subscription_id_t _id) { + id_ = _id; +} + +std::shared_ptr<eventgroupinfo> +remote_subscription::get_eventgroupinfo() const { + return eventgroupinfo_.lock(); +} + +void +remote_subscription::set_eventgroupinfo( + const std::shared_ptr<eventgroupinfo> &_info) { + eventgroupinfo_ = _info; +} + +ttl_t +remote_subscription::get_ttl() const { + return ttl_; +} + +void +remote_subscription::set_ttl(const ttl_t _ttl) { + ttl_ = _ttl; +} + +uint16_t +remote_subscription::get_reserved() const { + return reserved_; +} + +void +remote_subscription::set_reserved(const uint16_t _reserved) { + reserved_ = _reserved; +} + +uint8_t +remote_subscription::get_counter() const { + return counter_; +} + +void +remote_subscription::set_counter(uint8_t _counter) { + counter_ = _counter; +} + +std::set<client_t> +remote_subscription::get_clients() const { + std::lock_guard<std::mutex> its_lock(mutex_); + std::set<client_t> its_clients; + for (const auto its_item : clients_) + its_clients.insert(its_item.first); + return its_clients; +} + +bool +remote_subscription::has_client() const { + std::lock_guard<std::mutex> its_lock(mutex_); + return (clients_.size() > 0); +} + +bool +remote_subscription::has_client(const client_t _client) const { + std::lock_guard<std::mutex> its_lock(mutex_); + return (clients_.find(_client) != clients_.end()); +} + +void +remote_subscription::remove_client(const client_t _client) { + std::lock_guard<std::mutex> its_lock(mutex_); + clients_.erase(_client); +} + +remote_subscription_state_e +remote_subscription::get_client_state(const client_t _client) const { + std::lock_guard<std::mutex> its_lock(mutex_); + auto found_client = clients_.find(_client); + if (found_client != clients_.end()) { + return found_client->second.first; + } + return remote_subscription_state_e::SUBSCRIPTION_UNKNOWN; +} + +void +remote_subscription::set_client_state(const client_t _client, + remote_subscription_state_e _state) { + std::lock_guard<std::mutex> its_lock(mutex_); + auto found_item = clients_.find(_client); + if (found_item != clients_.end()) { + found_item->second.first = _state; + if (found_item->second.second == std::chrono::steady_clock::time_point() + && (_state == remote_subscription_state_e::SUBSCRIPTION_ACKED + || _state == remote_subscription_state_e::SUBSCRIPTION_NACKED)) { + found_item->second.second = std::chrono::steady_clock::now(); + } + } +} + +void +remote_subscription::set_all_client_states(remote_subscription_state_e _state) { + std::lock_guard<std::mutex> its_lock(mutex_); + for (auto &its_item : clients_) + its_item.second.first = _state; +} + +std::shared_ptr<endpoint_definition> +remote_subscription::get_subscriber() const { + return subscriber_; +} + +void +remote_subscription::set_subscriber( + const std::shared_ptr<endpoint_definition> &_subscriber) { + subscriber_ = _subscriber; +} + +std::shared_ptr<endpoint_definition> +remote_subscription::get_reliable() const { + return reliable_; +} + +void +remote_subscription::set_reliable( + const std::shared_ptr<endpoint_definition> &_reliable) { + reliable_ = _reliable; +} + +std::shared_ptr<endpoint_definition> +remote_subscription::get_unreliable() const { + return unreliable_; +} + +void +remote_subscription::set_unreliable( + const std::shared_ptr<endpoint_definition> &_unreliable) { + unreliable_ = _unreliable; +} + +bool +remote_subscription::is_pending() const { + std::lock_guard<std::mutex> its_lock(mutex_); + for (auto its_client : clients_) { + if (its_client.second.first + == remote_subscription_state_e::SUBSCRIPTION_PENDING) { + return true; + } + } + return false; +} + +bool +remote_subscription::is_acknowledged() const { + std::lock_guard<std::mutex> its_lock(mutex_); + for (auto its_client : clients_) { + if (its_client.second.first + != remote_subscription_state_e::SUBSCRIPTION_ACKED) { + return false; + } + } + return true; +} + +std::chrono::steady_clock::time_point +remote_subscription::get_expiration(const client_t _client) const { + std::lock_guard<std::mutex> its_lock(mutex_); + auto found_client = clients_.find(_client); + if (found_client != clients_.end()) { + return found_client->second.second; + } + return std::chrono::steady_clock::now(); +} + +std::set<client_t> +remote_subscription::update(const std::set<client_t> &_clients, + const std::chrono::steady_clock::time_point &_timepoint, + const bool _is_subscribe) { + std::set<client_t> its_changed; + + std::lock_guard<std::mutex> its_lock(mutex_); + for (const auto &its_client : _clients) { + auto found_client = clients_.find(its_client); + if (_is_subscribe) { + if (found_client != clients_.end()) { + found_client->second.second = _timepoint; + } else { + its_changed.insert(its_client); + } + } else { + if (found_client != clients_.end()) { + its_changed.insert(its_client); + } + } + } + + for (const auto &its_client : its_changed) { + if (_is_subscribe) { + clients_[its_client] = std::make_pair( + remote_subscription_state_e::SUBSCRIPTION_PENDING, _timepoint); + } else { + clients_.erase(its_client); + } + } + + return its_changed; +} + +std::shared_ptr<remote_subscription> +remote_subscription::get_parent() const { + return parent_.lock(); +} + +void +remote_subscription::set_parent( + const std::shared_ptr<remote_subscription> &_parent) { + parent_ = _parent; +} + +std::uint32_t +remote_subscription::get_answers() const { + return answers_; +} + +void +remote_subscription::set_answers(const std::uint32_t _answers) { + answers_ = _answers; +} + +} // namespace vsomeip_v3 diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp index 517ccdb..77e5b83 100644 --- a/implementation/routing/src/routing_manager_base.cpp +++ b/implementation/routing/src/routing_manager_base.cpp @@ -6,40 +6,47 @@ #include <iomanip> #include <vsomeip/runtime.hpp> +#include <vsomeip/internal/logger.hpp> -#include "../../utility/include/utility.hpp" -#include "../../utility/include/byteorder.hpp" #include "../include/routing_manager_base.hpp" -#include "../../logging/include/logger.hpp" #include "../../endpoints/include/local_client_endpoint_impl.hpp" #include "../../endpoints/include/local_server_endpoint_impl.hpp" +#include "../../security/include/security.hpp" #ifdef USE_DLT #include "../../tracing/include/connector_impl.hpp" #endif +#include "../../utility/include/byteorder.hpp" +#include "../../utility/include/utility.hpp" -namespace vsomeip { +namespace vsomeip_v3 { routing_manager_base::routing_manager_base(routing_manager_host *_host) : host_(_host), io_(host_->get_io()), client_(host_->get_client()), - configuration_(host_->get_configuration()), - serializer_( - std::make_shared<serializer>( - configuration_->get_buffer_shrink_threshold())) + configuration_(host_->get_configuration()) #ifdef USE_DLT , tc_(trace::connector_impl::get()) #endif { + const std::size_t its_max = configuration_->get_io_thread_count(host_->get_name()); const uint32_t its_buffer_shrink_threshold = configuration_->get_buffer_shrink_threshold(); - for (int i = 0; i < VSOMEIP_MAX_DESERIALIZER; ++i) { + + for (std::size_t i = 0; i < its_max; ++i) { + serializers_.push( + std::make_shared<serializer>(its_buffer_shrink_threshold)); deserializers_.push( - std::make_shared<deserializer>(its_buffer_shrink_threshold)); + std::make_shared<deserializer>(its_buffer_shrink_threshold)); } -} -routing_manager_base::~routing_manager_base() { + own_uid_ = ANY_UID; + own_gid_ = ANY_GID; +#ifndef _WIN32 + own_uid_ = getuid(); + own_gid_ = getgid(); +#endif + } boost::asio::io_service & routing_manager_base::get_io() { @@ -50,12 +57,21 @@ client_t routing_manager_base::get_client() const { return client_; } -void routing_manager_base::init() { +void routing_manager_base::set_client(const client_t &_client) { + client_ = _client; +} + +session_t routing_manager_base::get_session() { + return host_->get_session(); +} + +void routing_manager_base::init(const std::shared_ptr<endpoint_manager_base>& _endpoint_manager) { + ep_mgr_ = _endpoint_manager; } -bool routing_manager_base::offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor) { +bool routing_manager_base::offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) { (void)_client; // Remote route (incoming only) @@ -67,7 +83,6 @@ bool routing_manager_base::offer_service(client_t _client, service_t _service, && its_info->get_minor() == _minor) { its_info->set_ttl(DEFAULT_TTL); } else { - host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); VSOMEIP_ERROR << "rm_base::offer_service service property mismatch (" << std::hex << std::setw(4) << std::setfill('0') << _client <<"): [" << std::hex << std::setw(4) << std::setfill('0') << _service << "." @@ -98,11 +113,13 @@ bool routing_manager_base::offer_service(client_t _client, service_t _service, return true; } -void routing_manager_base::stop_offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor) { +void routing_manager_base::stop_offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) { (void)_client; (void)_major; (void)_minor; + std::map<event_t, std::shared_ptr<event> > events; { std::lock_guard<std::mutex> its_lock(events_mutex_); @@ -122,11 +139,9 @@ void routing_manager_base::stop_offer_service(client_t _client, service_t _servi } } -void routing_manager_base::request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor, bool _use_exclusive_proxy) { - (void)_use_exclusive_proxy; - +void routing_manager_base::request_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) { auto its_info = find_service(_service, _instance); if (its_info) { if ((_major == its_info->get_major() @@ -137,7 +152,6 @@ void routing_manager_base::request_service(client_t _client, service_t _service, || _minor == ANY_MINOR)) { its_info->add_client(_client); } else { - host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); VSOMEIP_ERROR << "rm_base::request_service service property mismatch (" << std::hex << std::setw(4) << std::setfill('0') << _client <<"): [" << std::hex << std::setw(4) << std::setfill('0') << _service << "." @@ -150,8 +164,8 @@ void routing_manager_base::request_service(client_t _client, service_t _service, } } -void routing_manager_base::release_service(client_t _client, service_t _service, - instance_t _instance) { +void routing_manager_base::release_service(client_t _client, + service_t _service, instance_t _instance) { auto its_info = find_service(_service, _instance); if (its_info) { its_info->remove_client(_client); @@ -168,38 +182,84 @@ void routing_manager_base::release_service(client_t _client, service_t _service, } } -void routing_manager_base::register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field, - 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); +void routing_manager_base::register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, + const event_type_e _type, + reliability_type_e _reliability, + std::chrono::milliseconds _cycle, bool _change_resets_cycle, + bool _update_on_change, + epsilon_change_func_t _epsilon_change_func, + bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) { + std::lock_guard<std::mutex> its_registration_lock(event_registration_mutex_); + + auto determine_event_reliability = [this, &_service, &_instance, + &_notifier, &_reliability]() { + reliability_type_e its_reliability = + configuration_->get_event_reliability(_service, _instance, _notifier); + if (its_reliability != reliability_type_e::RT_UNKNOWN) { + // event was explicitly configured -> overwrite value passed via API + return its_reliability; + } else if (_reliability != reliability_type_e::RT_UNKNOWN) { + // use value provided via API + return _reliability; + } else { // automatic mode, user service' reliability + return configuration_->get_service_reliability(_service, _instance); + } + }; + + std::shared_ptr<event> its_event = find_event(_service, _instance, _notifier); bool transfer_subscriptions_from_any_event(false); if (its_event) { - if(!its_event->is_cache_placeholder()) { - if (its_event->is_field() == _is_field) { + if (!its_event->is_cache_placeholder()) { + if (_type == its_event->get_type() + || its_event->get_type() == event_type_e::ET_UNKNOWN +#ifdef VSOMEIP_ENABLE_COMPAT + || (its_event->get_type() == event_type_e::ET_EVENT + && _type == event_type_e::ET_SELECTIVE_EVENT) + || (its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT + && _type == event_type_e::ET_EVENT && _is_provided) +#endif + ) { +#ifdef VSOMEIP_ENABLE_COMPAT + if (its_event->get_type() == event_type_e::ET_EVENT + && _type == event_type_e::ET_SELECTIVE_EVENT) { + its_event->set_type(_type); + VSOMEIP_INFO << "Event type changed to selective (" + << 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') << _notifier << "]"; + } +#endif if (_is_provided) { its_event->set_provided(true); + its_event->set_reliability(determine_event_reliability()); } if (_is_shadow && _is_provided) { its_event->set_shadow(_is_shadow); } if (_client == host_->get_client() && _is_provided) { its_event->set_shadow(false); + its_event->set_update_on_change(_update_on_change); } for (auto eg : _eventgroups) { its_event->add_eventgroup(eg); } transfer_subscriptions_from_any_event = true; } else { - VSOMEIP_ERROR << "Event registration update failed. " - "Specified arguments do not match existing registration."; +#ifdef VSOMEIP_ENABLE_COMPAT + if (!(its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT + && _type == event_type_e::ET_EVENT)) +#endif + VSOMEIP_ERROR << "Event registration update failed. " + "Specified arguments do not match existing registration."; } } else { // the found event was a placeholder for caching. // update it with the real values - if(!_is_field) { + if (_type != event_type_e::ET_FIELD) { // don't cache payload for non-fields its_event->unset_payload(true); } @@ -208,8 +268,10 @@ void routing_manager_base::register_event(client_t _client, service_t _service, } if (_client == host_->get_client() && _is_provided) { its_event->set_shadow(false); + its_event->set_update_on_change(_update_on_change); } - its_event->set_field(_is_field); + its_event->set_type(_type); + its_event->set_reliability(determine_event_reliability()); its_event->set_provided(_is_provided); its_event->set_cache_placeholder(false); std::shared_ptr<serviceinfo> its_service = find_service(_service, _instance); @@ -218,7 +280,7 @@ void routing_manager_base::register_event(client_t _client, service_t _service, } if (_eventgroups.size() == 0) { // No eventgroup specified std::set<eventgroup_t> its_eventgroups; - its_eventgroups.insert(_event); + its_eventgroups.insert(_notifier); its_event->set_eventgroups(its_eventgroups); } else { for (auto eg : _eventgroups) { @@ -232,11 +294,11 @@ void routing_manager_base::register_event(client_t _client, service_t _service, } } else { its_event = std::make_shared<event>(this, _is_shadow); - its_event->set_reliable(configuration_->is_event_reliable(_service, _instance, _event)); its_event->set_service(_service); its_event->set_instance(_instance); - its_event->set_event(_event); - its_event->set_field(_is_field); + its_event->set_event(_notifier); + its_event->set_type(_type); + its_event->set_reliability(determine_event_reliability()); its_event->set_provided(_is_provided); its_event->set_cache_placeholder(_is_cache_placeholder); std::shared_ptr<serviceinfo> its_service = find_service(_service, _instance); @@ -246,15 +308,15 @@ void routing_manager_base::register_event(client_t _client, service_t _service, if (_eventgroups.size() == 0) { // No eventgroup specified std::set<eventgroup_t> its_eventgroups; - its_eventgroups.insert(_event); + its_eventgroups.insert(_notifier); its_event->set_eventgroups(its_eventgroups); } else { its_event->set_eventgroups(_eventgroups); } if (_is_shadow && !_epsilon_change_func) { - std::shared_ptr<vsomeip::cfg::debounce> its_debounce - = configuration_->get_debounce(_service, _instance, _event); + std::shared_ptr<cfg::debounce> its_debounce + = configuration_->get_debounce(_service, _instance, _notifier); if (its_debounce) { VSOMEIP_WARNING << "Using debounce configuration for " << " SOME/IP event " @@ -263,7 +325,7 @@ void routing_manager_base::register_event(client_t _client, service_t _service, << std::hex << std::setw(4) << std::setfill('0') << _instance << "." << std::hex << std::setw(4) << std::setfill('0') - << _event << "."; + << _notifier << "."; std::stringstream its_debounce_parameters; its_debounce_parameters << "(on_change=" << (its_debounce->on_change_ ? "true" : "false") @@ -349,6 +411,7 @@ void routing_manager_base::register_event(client_t _client, service_t _service, its_event->set_epsilon_change_function(_epsilon_change_func); its_event->set_change_resets_cycle(_change_resets_cycle); its_event->set_update_cycle(_cycle); + its_event->set_update_on_change(_update_on_change); if (_is_provided) { transfer_subscriptions_from_any_event = true; @@ -381,18 +444,21 @@ void routing_manager_base::register_event(client_t _client, service_t _service, } for (auto eg : _eventgroups) { - std::shared_ptr<eventgroupinfo> its_eventgroup_info + std::shared_ptr<eventgroupinfo> its_eventgroupinfo = find_eventgroup(_service, _instance, eg); - if (!its_eventgroup_info) { - its_eventgroup_info = std::make_shared<eventgroupinfo>(); + if (!its_eventgroupinfo) { + its_eventgroupinfo = std::make_shared<eventgroupinfo>(); + its_eventgroupinfo->set_service(_service); + its_eventgroupinfo->set_instance(_instance); + its_eventgroupinfo->set_eventgroup(eg); std::lock_guard<std::mutex> its_lock(eventgroups_mutex_); - eventgroups_[_service][_instance][eg] = its_eventgroup_info; + eventgroups_[_service][_instance][eg] = its_eventgroupinfo; } - its_eventgroup_info->add_event(its_event); + its_eventgroupinfo->add_event(its_event); } std::lock_guard<std::mutex> its_lock(events_mutex_); - events_[_service][_instance][_event] = its_event; + events_[_service][_instance][_notifier] = its_event; } void routing_manager_base::unregister_event(client_t _client, service_t _service, instance_t _instance, @@ -470,7 +536,9 @@ std::vector<event_t> routing_manager_base::find_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()) { + + const auto its_security(security::get()); + if (!its_security->is_enabled()) { return true; } @@ -495,7 +563,7 @@ bool routing_manager_base::is_response_allowed(client_t _sender, service_t _serv // 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()) { + if (!its_security->is_audit()) { security_mode_text = ", but will be allowed due to audit mode is active!"; } @@ -506,16 +574,23 @@ bool routing_manager_base::is_response_allowed(client_t _sender, service_t _serv << _service << "/" << _instance << "/" << _method << security_mode_text; - return !configuration_->is_audit_mode_enabled(); + return !its_security->is_audit(); } -bool routing_manager_base::is_subscribe_to_any_event_allowed(client_t _client, +bool routing_manager_base::is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) { + + const auto its_security(security::get()); + const uid_t its_uid(std::get<0>(_credentials)); + const gid_t its_gid(std::get<1>(_credentials)); + 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())) { + for (const auto& e : its_eventgroup->get_events()) { + if (!its_security->is_client_allowed(its_uid, its_gid, + _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 " @@ -526,16 +601,17 @@ bool routing_manager_base::is_subscribe_to_any_event_allowed(client_t _client, } } } + 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, - subscription_type_e _subscription_type) { +void routing_manager_base::subscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + major_version_t _major, event_t _event) { (void) _major; - (void) _subscription_type; + (void)_uid; + (void)_gid; std::set<event_t> its_already_subscribed_events; bool inserted = insert_subscription(_service, _instance, _eventgroup, _event, _client, &its_already_subscribed_events); @@ -545,8 +621,10 @@ void routing_manager_base::subscribe(client_t _client, service_t _service, } } -void routing_manager_base::unsubscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, event_t _event) { +void routing_manager_base::unsubscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, eventgroup_t _eventgroup,event_t _event) { + (void)_uid; + (void)_gid; if (_event != ANY_EVENT) { auto its_event = find_event(_service, _instance, _event); if (its_event) { @@ -555,8 +633,9 @@ void routing_manager_base::unsubscribe(client_t _client, service_t _service, } else { auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - for (auto e : its_eventgroup->get_events()) { - e->remove_subscriber(_eventgroup, _client); + for (const auto &e : its_eventgroup->get_events()) { + if (e) + e->remove_subscriber(_eventgroup, _client); } } } @@ -564,10 +643,10 @@ void routing_manager_base::unsubscribe(client_t _client, service_t _service, void routing_manager_base::notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload, - bool _force, bool _flush) { + bool _force) { std::shared_ptr<event> its_event = find_event(_service, _instance, _event); if (its_event) { - its_event->set_payload(_payload, _force, _flush); + its_event->set_payload(_payload, _force); } else { VSOMEIP_WARNING << "Attempt to update the undefined event/field [" << std::hex << _service << "." << _instance << "." << _event @@ -577,14 +656,20 @@ 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, bool _remote_subscriber) { + client_t _client, bool _force +#ifdef VSOMEIP_ENABLE_COMPAT + , bool _remote_subscriber +#endif + ) { 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); +#ifdef VSOMEIP_ENABLE_COMPAT eventgroup_t valid_group = 0; subscription_state_e its_subscription_state(subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED); +#endif // 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()) { @@ -592,14 +677,21 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance, if (its_eventgroup) { // Eventgroup is valid for service/instance found_eventgroup = true; +#ifdef VSOMEIP_ENABLE_COMPAT valid_group = its_group; its_subscription_state = get_incoming_subscription_state(_client, _service, _instance, valid_group, _event); - if (find_local(_client)) { +#endif + if (ep_mgr_->find_local(_client)) { already_subscribed = its_event->has_subscriber(its_group, _client); +#ifdef VSOMEIP_ENABLE_COMPAT } 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 +#else + } else { + // Remotes always needs to be marked as subscribed here +#endif already_subscribed = true; } break; @@ -607,8 +699,10 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance, } if (found_eventgroup) { if (already_subscribed) { - its_event->set_payload(_payload, _client, _force, _flush); - } else { + its_event->set_payload(_payload, _client, _force); + } +#ifdef VSOMEIP_ENABLE_COMPAT + else { // cache notification if subscription is in progress if (subscription_state_e::IS_SUBSCRIBING == its_subscription_state) { VSOMEIP_INFO << "routing_manager_base::notify_one(" @@ -634,6 +728,7 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance, } } } +#endif } } else { VSOMEIP_WARNING << "Attempt to update the undefined event/field [" @@ -642,6 +737,7 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance, } } +#ifdef VSOMEIP_ENABLE_COMPAT void routing_manager_base::send_pending_notify_ones(service_t _service, instance_t _instance, eventgroup_t _eventgroup, client_t _client, bool _remote_subscriber) { std::lock_guard<std::recursive_mutex> its_lock(pending_notify_ones_mutex_); @@ -659,12 +755,13 @@ void routing_manager_base::send_pending_notify_ones(service_t _service, instance << 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, _remote_subscriber); + its_group->second->get_payload(), _client, false, _remote_subscriber); its_instance->second.erase(_eventgroup); } } } } +#endif void routing_manager_base::unset_all_eventpayloads(service_t _service, instance_t _instance) { @@ -719,16 +816,16 @@ void routing_manager_base::notify_one_current_value( if (_event != ANY_EVENT) { std::shared_ptr<event> its_event = find_event(_service, _instance, _event); if (its_event && its_event->is_field()) - its_event->notify_one(_client, true); + its_event->notify_one(_client); } else { auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { std::set<std::shared_ptr<event> > its_events = its_eventgroup->get_events(); - for (auto e : its_events) { + for (const auto &e : its_events) { if (e->is_field() && _events_to_exclude.find(e->get_event()) == _events_to_exclude.end()) { - e->notify_one(_client, true); // TODO: use _flush to send all events together! + e->notify_one(_client); } } } @@ -736,18 +833,19 @@ void routing_manager_base::notify_one_current_value( } bool routing_manager_base::send(client_t _client, - std::shared_ptr<message> _message, - bool _flush) { + std::shared_ptr<message> _message) { bool is_sent(false); if (utility::is_request(_message->get_message_type())) { _message->set_client(_client); } - std::lock_guard<std::mutex> its_lock(serialize_mutex_); - if (serializer_->serialize(_message.get())) { - is_sent = send(_client, serializer_->get_data(), - serializer_->get_size(), _message->get_instance(), - _flush, _message->is_reliable(), get_client(), true, false); - serializer_->reset(); + + std::shared_ptr<serializer> its_serializer(get_serializer()); + if (its_serializer->serialize(_message.get())) { + is_sent = send(_client, its_serializer->get_data(), + its_serializer->get_size(), _message->get_instance(), + _message->is_reliable(), get_client(), std::make_pair(ANY_UID, ANY_GID), 0, false); + its_serializer->reset(); + put_serializer(its_serializer); } else { VSOMEIP_ERROR << "Failed to serialize message. Check message size!"; } @@ -759,7 +857,8 @@ std::shared_ptr<serviceinfo> routing_manager_base::create_service_info( service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, ttl_t _ttl, bool _is_local_service) { std::shared_ptr<serviceinfo> its_info = - std::make_shared<serviceinfo>(_major, _minor, _ttl, _is_local_service); + std::make_shared<serviceinfo>(_service, _instance, + _major, _minor, _ttl, _is_local_service); { std::lock_guard<std::mutex> its_lock(services_mutex_); services_[_service][_instance] = its_info; @@ -873,7 +972,8 @@ std::set<client_t> routing_manager_base::find_local_clients(service_t _service, return its_clients; } -client_t routing_manager_base::find_local_client(service_t _service, instance_t _instance) { +client_t routing_manager_base::find_local_client(service_t _service, + instance_t _instance) const { std::lock_guard<std::mutex> its_lock(local_services_mutex_); client_t its_client(VSOMEIP_ROUTING_CLIENT); auto its_service = local_services_.find(_service); @@ -886,70 +986,6 @@ client_t routing_manager_base::find_local_client(service_t _service, instance_t return its_client; } -std::shared_ptr<endpoint> routing_manager_base::create_local_unlocked(client_t _client) { - std::stringstream its_path; - its_path << utility::get_base_path(configuration_) << std::hex << _client; - -#ifdef _WIN32 - boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1"); - int port = VSOMEIP_INTERNAL_BASE_PORT + _client; - VSOMEIP_INFO << "Connecting to [" - << std::hex << _client << "] at " << port; -#else - VSOMEIP_INFO << "Client [" << std::hex << get_client() << "] is connecting to [" - << std::hex << _client << "] at " << its_path.str(); -#endif - std::shared_ptr<local_client_endpoint_impl> its_endpoint = std::make_shared< - local_client_endpoint_impl>(shared_from_this(), -#ifdef _WIN32 - boost::asio::ip::tcp::endpoint(address, port) -#else - boost::asio::local::stream_protocol::endpoint(its_path.str()) -#endif - , io_, configuration_->get_max_message_size_local(), - configuration_->get_endpoint_queue_limit_local()); - - // Messages sent to the VSOMEIP_ROUTING_CLIENT are meant to be routed to - // external devices. Therefore, its local endpoint must not be found by - // a call to find_local. Thus it must not be inserted to the list of local - // clients. - if (_client != VSOMEIP_ROUTING_CLIENT) { - local_endpoints_[_client] = its_endpoint; - } - register_client_error_handler(_client, its_endpoint); - - return its_endpoint; -} - -std::shared_ptr<endpoint> routing_manager_base::create_local(client_t _client) { - std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); - return create_local_unlocked(_client); -} - -std::shared_ptr<endpoint> routing_manager_base::find_local_unlocked(client_t _client) { - std::shared_ptr<endpoint> its_endpoint; - auto found_endpoint = local_endpoints_.find(_client); - if (found_endpoint != local_endpoints_.end()) { - its_endpoint = found_endpoint->second; - } - return (its_endpoint); -} - -std::shared_ptr<endpoint> routing_manager_base::find_local(client_t _client) { - std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); - return find_local_unlocked(_client); -} - -std::shared_ptr<endpoint> routing_manager_base::find_or_create_local(client_t _client) { - std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); - std::shared_ptr<endpoint> its_endpoint(find_local_unlocked(_client)); - if (!its_endpoint) { - its_endpoint = create_local_unlocked(_client); - its_endpoint->start(); - } - return (its_endpoint); -} - void routing_manager_base::remove_local(client_t _client, bool _remove_uid) { remove_local(_client, get_subscriptions(_client), _remove_uid); } @@ -957,24 +993,20 @@ void routing_manager_base::remove_local(client_t _client, bool _remove_uid) { void routing_manager_base::remove_local(client_t _client, const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups, bool _remove_uid) { + + std::pair<uid_t, gid_t> its_uid_gid(ANY_UID, ANY_GID); + security::get()->get_client_to_uid_gid_mapping(_client, its_uid_gid); + if (_remove_uid) { - configuration_->remove_client_to_uid_gid_mapping(_client); + security::get()->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; }); - routing_manager_base::unsubscribe(_client, std::get<0>(its_subscription), + std::get<2>(its_subscription), _client, its_uid_gid.first, its_uid_gid.second, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; }); + routing_manager_base::unsubscribe(_client, its_uid_gid.first, its_uid_gid.second, std::get<0>(its_subscription), std::get<1>(its_subscription), std::get<2>(its_subscription), ANY_EVENT); } - std::shared_ptr<endpoint> its_endpoint(find_local(_client)); - if (its_endpoint) { - its_endpoint->register_error_handler(nullptr); - its_endpoint->stop(); - VSOMEIP_INFO << "Client [" << std::hex << get_client() << "] is closing connection to [" - << std::hex << _client << "]"; - std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); - local_endpoints_.erase(_client); - } + ep_mgr_->remove_local(_client); { std::lock_guard<std::mutex> its_lock(local_services_mutex_); // Finally remove all services that are implemented by the client. @@ -1016,24 +1048,10 @@ void routing_manager_base::remove_local(client_t _client, } } -std::shared_ptr<endpoint> routing_manager_base::find_local(service_t _service, - instance_t _instance) { - return find_local(find_local_client(_service, _instance)); -} - -std::unordered_set<client_t> routing_manager_base::get_connected_clients() { - std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); - std::unordered_set<client_t> clients; - for (auto its_client : local_endpoints_) { - clients.insert(its_client.first); - } - return clients; -} - std::shared_ptr<event> routing_manager_base::find_event(service_t _service, instance_t _instance, event_t _event) const { - std::shared_ptr<event> its_event; std::lock_guard<std::mutex> its_lock(events_mutex_); + std::shared_ptr<event> its_event; auto find_service = events_.find(_service); if (find_service != events_.end()) { auto find_instance = find_service->second.find(_instance); @@ -1082,6 +1100,8 @@ std::shared_ptr<eventgroupinfo> routing_manager_base::find_eventgroup( "multicast address is configured!"; } } + + // LB: THIS IS STRANGE. A "FIND" - METHOD SHOULD NOT ADD INFORMATION... its_info->set_major(its_service_info->get_major()); its_info->set_ttl(its_service_info->get_ttl()); its_info->set_threshold(configuration_->get_threshold( @@ -1107,7 +1127,7 @@ void routing_manager_base::remove_eventgroup_info(service_t _service, bool routing_manager_base::send_local_notification(client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, - bool _flush, bool _reliable, bool _is_valid_crc) { + bool _reliable, uint8_t _status_check) { #ifdef USE_DLT bool has_local(false); #endif @@ -1118,7 +1138,6 @@ bool routing_manager_base::send_local_notification(client_t _client, _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method); if (its_event && !its_event->is_shadow()) { - std::vector< byte_t > its_data; for (auto its_client : its_event->get_subscribers()) { // local @@ -1131,10 +1150,10 @@ bool routing_manager_base::send_local_notification(client_t _client, has_local = true; } #endif - std::shared_ptr<endpoint> its_local_target = find_local(its_client); + std::shared_ptr<endpoint> its_local_target = ep_mgr_->find_local(its_client); if (its_local_target) { send_local(its_local_target, _client, _data, _size, - _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc); + _instance, _reliable, VSOMEIP_SEND, _status_check); } } } @@ -1156,7 +1175,7 @@ bool routing_manager_base::send_local_notification(client_t _client, bool routing_manager_base::send_local( std::shared_ptr<endpoint>& _target, client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, - bool _flush, bool _reliable, uint8_t _command, bool _is_valid_crc) const { + bool _reliable, uint8_t _command, uint8_t _status_check) const { const std::size_t its_complete_size = VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE + _size; const client_t sender = get_client(); @@ -1169,12 +1188,10 @@ bool routing_manager_base::send_local( &its_complete_size, sizeof(_size)); std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN], &_instance, sizeof(instance_t)); - std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_FLUSH_POS], - &_flush, sizeof(bool)); std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_RELIABLE_POS], &_reliable, sizeof(bool)); - std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_VALID_CRC_POS], - &_is_valid_crc, sizeof(bool)); + std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS], + &_status_check, sizeof(uint8_t)); // Add target client, only relevant for selective notifications std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN], &_client, sizeof(client_t)); @@ -1244,7 +1261,33 @@ bool routing_manager_base::insert_subscription( return is_inserted; } +std::shared_ptr<serializer> routing_manager_base::get_serializer() { + + std::unique_lock<std::mutex> its_lock(serializer_mutex_); + while (serializers_.empty()) { + VSOMEIP_INFO << std::hex << "client " << get_client() << + "routing_manager_base::get_serializer ~> all in use!"; + serializer_condition_.wait(its_lock); + VSOMEIP_INFO << std::hex << "client " << get_client() << + "routing_manager_base::get_serializer ~> wait finished!"; + } + + auto its_serializer = serializers_.front(); + serializers_.pop(); + + return (its_serializer); +} + +void routing_manager_base::put_serializer( + const std::shared_ptr<serializer> &_serializer) { + + std::lock_guard<std::mutex> its_lock(serializer_mutex_); + serializers_.push(_serializer); + serializer_condition_.notify_one(); +} + std::shared_ptr<deserializer> routing_manager_base::get_deserializer() { + std::unique_lock<std::mutex> its_lock(deserializer_mutex_); while (deserializers_.empty()) { VSOMEIP_INFO << std::hex << "client " << get_client() << @@ -1253,30 +1296,28 @@ std::shared_ptr<deserializer> routing_manager_base::get_deserializer() { VSOMEIP_INFO << std::hex << "client " << get_client() << "routing_manager_base::get_deserializer ~> wait finished!"; } - auto deserializer = deserializers_.front(); + + auto its_deserializer = deserializers_.front(); deserializers_.pop(); - return deserializer; + + return (its_deserializer); } -void routing_manager_base::put_deserializer(std::shared_ptr<deserializer> _deserializer) { +void routing_manager_base::put_deserializer( + const std::shared_ptr<deserializer> &_deserializer) { + std::lock_guard<std::mutex> its_lock(deserializer_mutex_); deserializers_.push(_deserializer); deserializer_condition_.notify_one(); } -#ifndef _WIN32 -bool routing_manager_base::check_credentials(client_t _client, uid_t _uid, gid_t _gid) { - return configuration_->check_credentials(_client, _uid, _gid); -} -#endif - void routing_manager_base::send_pending_subscriptions(service_t _service, instance_t _instance, major_version_t _major) { for (auto &ps : pending_subscriptions_) { if (ps.service_ == _service && ps.instance_ == _instance && ps.major_ == _major) { send_subscribe(client_, ps.service_, ps.instance_, - ps.eventgroup_, ps.major_, ps.event_, ps.subscription_type_); + ps.eventgroup_, ps.major_, ps.event_); } } } @@ -1324,11 +1365,11 @@ std::set<std::tuple<service_t, instance_t, eventgroup_t>> routing_manager_base::get_subscriptions(const client_t _client) { std::set<std::tuple<service_t, instance_t, eventgroup_t>> result; std::lock_guard<std::mutex> its_lock(events_mutex_); - for (auto its_service : events_) { - for (auto its_instance : its_service.second) { - for (auto its_event : its_instance.second) { + for (const auto& its_service : events_) { + for (const auto& its_instance : its_service.second) { + for (const auto& its_event : its_instance.second) { auto its_eventgroups = its_event.second->get_eventgroups(_client); - for (auto e : its_eventgroups) { + for (const auto& e : its_eventgroups) { result.insert(std::make_tuple( its_service.first, its_instance.first, @@ -1340,27 +1381,7 @@ routing_manager_base::get_subscriptions(const client_t _client) { return result; } -void routing_manager_base::send_identify_request(service_t _service, - instance_t _instance, major_version_t _major, bool _reliable) { - auto message = runtime::get()->create_message(_reliable); - message->set_service(_service); - message->set_instance(_instance); - message->set_client(get_client()); - message->set_method(ANY_METHOD - 1); - message->set_interface_version(_major); - message->set_message_type(message_type_e::MT_REQUEST); - - // Initiate a request/response to the remote service - // Use host for sending to ensure correct session id is set - host_->send(message, true); -} - -std::map<client_t, std::shared_ptr<endpoint>> -routing_manager_base::get_local_endpoints() { - std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); - return local_endpoints_; -} - +#ifdef VSOMEIP_ENABLE_COMPAT 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_); @@ -1427,5 +1448,6 @@ void routing_manager_base::erase_incoming_subscription_state(client_t _client, s } } } +#endif -} // namespace vsomeip +} // namespace vsomeip_v3 diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp index f8dbd14..48e2cb5 100644 --- a/implementation/routing/src/routing_manager_impl.cpp +++ b/implementation/routing/src/routing_manager_impl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2018 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/. @@ -15,25 +15,23 @@ #include <time.h> #endif -#ifndef WITHOUT_SYSTEMD -#include <systemd/sd-daemon.h> -#endif - #include <boost/asio/steady_timer.hpp> #include <vsomeip/constants.hpp> -#include <vsomeip/message.hpp> #include <vsomeip/payload.hpp> #include <vsomeip/runtime.hpp> +#include <vsomeip/internal/logger.hpp> #include "../include/event.hpp" #include "../include/eventgroupinfo.hpp" +#include "../include/remote_subscription.hpp" #include "../include/routing_manager_host.hpp" #include "../include/routing_manager_impl.hpp" #include "../include/routing_manager_stub.hpp" #include "../include/serviceinfo.hpp" #include "../../configuration/include/configuration.hpp" -#include "../../configuration/include/internal.hpp" +#include "../../security/include/security.hpp" + #include "../../endpoints/include/endpoint_definition.hpp" #include "../../endpoints/include/local_client_endpoint_impl.hpp" #include "../../endpoints/include/tcp_client_endpoint_impl.hpp" @@ -41,32 +39,38 @@ #include "../../endpoints/include/udp_client_endpoint_impl.hpp" #include "../../endpoints/include/udp_server_endpoint_impl.hpp" #include "../../endpoints/include/virtual_server_endpoint_impl.hpp" -#include "../../logging/include/logger.hpp" #include "../../message/include/deserializer.hpp" +#include "../../message/include/message_impl.hpp" #include "../../message/include/serializer.hpp" #include "../../service_discovery/include/constants.hpp" #include "../../service_discovery/include/defines.hpp" #include "../../service_discovery/include/runtime.hpp" -#include "../../service_discovery/include/service_discovery_impl.hpp" +#include "../../service_discovery/include/service_discovery.hpp" #include "../../utility/include/byteorder.hpp" #include "../../utility/include/utility.hpp" -#include "../../plugin/include/plugin_manager.hpp" +#include "../../plugin/include/plugin_manager_impl.hpp" #ifdef USE_DLT #include "../../tracing/include/connector_impl.hpp" #endif +#ifndef ANDROID #include "../../e2e_protection/include/buffer/buffer.hpp" #include "../../e2e_protection/include/e2exf/config.hpp" -#include "../../e2e_protection/include/e2e/profile/profile01/profile_01.hpp" -#include "../../e2e_protection/include/e2e/profile/profile01/protector.hpp" -#include "../../e2e_protection/include/e2e/profile/profile01/checker.hpp" +#include "../../e2e_protection/include/e2e/profile/e2e_provider.hpp" +#endif -#include "../../e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp" -#include "../../e2e_protection/include/e2e/profile/profile_custom/protector.hpp" -#include "../../e2e_protection/include/e2e/profile/profile_custom/checker.hpp" +#ifdef USE_DLT +#include "../../tracing/include/connector_impl.hpp" +#endif -namespace vsomeip { +namespace vsomeip_v3 { + +#ifdef ANDROID +namespace sd { +runtime::~runtime() {} +} +#endif routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : routing_manager_base(_host), @@ -74,11 +78,9 @@ routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : if_state_running_(false), sd_route_set_(false), routing_running_(false), -#ifndef WITHOUT_SYSTEMD - watchdog_timer_(_host->get_io()), -#endif status_log_timer_(_host->get_io()), memory_log_timer_(_host->get_io()), + ep_mgr_impl_(std::make_shared<endpoint_manager_impl>(this, io_, configuration_)), pending_remote_offer_id_(0), last_resume_(std::chrono::steady_clock::now().min()), pending_security_update_id_(0) @@ -86,6 +88,8 @@ routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : } routing_manager_impl::~routing_manager_impl() { + utility::remove_lockfile(configuration_); + utility::reset_client_ids(); } boost::asio::io_service & routing_manager_impl::get_io() { @@ -100,22 +104,23 @@ std::set<client_t> routing_manager_impl::find_local_clients(service_t _service, return routing_manager_base::find_local_clients(_service, _instance); } -bool routing_manager_impl::is_subscribe_to_any_event_allowed(client_t _client, +client_t routing_manager_impl::find_local_client(service_t _service, instance_t _instance) { + return routing_manager_base::find_local_client(_service, _instance); +} + +bool routing_manager_impl::is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) { - return routing_manager_base::is_subscribe_to_any_event_allowed(_client, + return routing_manager_base::is_subscribe_to_any_event_allowed(_credentials, _client, _service, _instance, _eventgroup); } void routing_manager_impl::init() { - routing_manager_base::init(); + routing_manager_base::init(ep_mgr_impl_); // TODO: Only instantiate the stub if needed stub_ = std::make_shared<routing_manager_stub>(this, configuration_); stub_->init(); - // We need to be able to send messages to ourself (for delivering events) - (void)create_local(VSOMEIP_ROUTING_CLIENT); - if (configuration_->is_sd_enabled()) { VSOMEIP_INFO<< "Service Discovery enabled. Trying to load module."; auto its_plugin = plugin_manager::get()->get_plugin( @@ -130,34 +135,29 @@ void routing_manager_impl::init() { } } +#ifndef ANDROID if( configuration_->is_e2e_enabled()) { VSOMEIP_INFO << "E2E protection enabled."; + + const char *its_e2e_module = getenv(VSOMEIP_ENV_E2E_PROTECTION_MODULE); + std::string plugin_name = its_e2e_module != nullptr ? its_e2e_module : VSOMEIP_E2E_LIBRARY; + + auto its_plugin = plugin_manager::get()->get_plugin(plugin_type_e::APPLICATION_PLUGIN, plugin_name); + if (its_plugin) { + VSOMEIP_INFO << "E2E module loaded."; + e2e_provider_ = std::dynamic_pointer_cast<e2e::e2e_provider>(its_plugin); + } + } + + if(e2e_provider_) { 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_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")) { - custom_protectors[its_data_identifier] = std::make_shared<e2e::profile01::protector>(its_profile_config); - } - if ((its_cfg->variant == "checker") || (its_cfg->variant == "both")) { - 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_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")) { - custom_protectors[its_data_identifier] = std::make_shared<e2e::profile_custom::protector>(its_profile_config); - } - if ((its_cfg->variant == "checker") || (its_cfg->variant == "both")) { - custom_checkers[its_data_identifier] = std::make_shared<e2e::profile_custom::profile_custom_checker>(its_profile_config); - } + if(!e2e_provider_->add_configuration(identifier.second)) { + VSOMEIP_INFO << "Unknown E2E profile: " << identifier.second->profile << ", skipping ..."; } } } +#endif } void routing_manager_impl::start() { @@ -186,15 +186,6 @@ void routing_manager_impl::start() { version_log_timer_.async_wait(std::bind(&routing_manager_impl::log_version_timer_cbk, this, std::placeholders::_1)); } - -#ifndef WITHOUT_SYSTEMD - { - std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_); - watchdog_timer_.expires_from_now(std::chrono::seconds(0)); - watchdog_timer_.async_wait(std::bind(&routing_manager_impl::watchdog_cbk, - this, std::placeholders::_1)); - } -#endif #ifndef _WIN32 if (configuration_->log_memory()) { std::lock_guard<std::mutex> its_lock(memory_log_timer_mutex_); @@ -216,6 +207,26 @@ void routing_manager_impl::start() { } void routing_manager_impl::stop() { + // Ensure to StopOffer all services that are offered by the application hosting the rm + local_services_map_t its_services; + { + std::lock_guard<std::mutex> its_lock(local_services_mutex_); + for (const auto& s : local_services_) { + for (const auto& i : s.second) { + if (std::get<2>(i.second) == client_) { + its_services[s.first][i.first] = i.second; + } + } + } + + } + for (const auto& s : its_services) { + for (const auto& i : s.second) { + on_stop_offer_service(std::get<2>(i.second), s.first, i.first, + std::get<0>(i.second), std::get<1>(i.second)); + } + } + { std::lock_guard<std::mutex> its_lock(version_log_timer_mutex_); version_log_timer_.cancel(); @@ -236,37 +247,119 @@ void routing_manager_impl::stop() { boost::system::error_code ec; status_log_timer_.cancel(ec); } -#ifndef WITHOUT_SYSTEMD - { - std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_); - watchdog_timer_.cancel(); - } - sd_notify(0, "STOPPING=1"); - VSOMEIP_INFO << "Sent STOPPING to systemd watchdog"; -#endif - host_->on_state(state_type_e::ST_DEREGISTERED); if (discovery_) discovery_->stop(); stub_->stop(); - for (auto client: get_connected_clients()) { + for (auto client: ep_mgr_->get_connected_clients()) { if (client != VSOMEIP_ROUTING_CLIENT) { remove_local(client, true); } } } -bool routing_manager_impl::offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor) { +bool routing_manager_impl::insert_offer_command(service_t _service, instance_t _instance, uint8_t _command, + client_t _client, major_version_t _major, minor_version_t _minor) { + std::lock_guard<std::mutex> its_lock(offer_serialization_mutex_); + // flag to indicate whether caller of this function can start directly processing the command + bool must_process(false); + auto found_service_instance = offer_commands_.find(std::make_pair(_service, _instance)); + if (found_service_instance != offer_commands_.end()) { + // if nothing is queued + if (found_service_instance->second.empty()) { + must_process = true; + } + found_service_instance->second.push_back( + std::make_tuple(_command, _client, _major, _minor)); + } else { + // nothing is queued -> add command to queue and process command directly + offer_commands_[std::make_pair(_service, _instance)].push_back( + std::make_tuple(_command, _client, _major, _minor)); + must_process = true; + } + return must_process; +} + +bool routing_manager_impl::erase_offer_command(service_t _service, instance_t _instance) { + std::lock_guard<std::mutex> its_lock(offer_serialization_mutex_); + auto found_service_instance = offer_commands_.find(std::make_pair(_service, _instance)); + if (found_service_instance != offer_commands_.end()) { + // erase processed command + if (!found_service_instance->second.empty()) { + found_service_instance->second.pop_front(); + if (!found_service_instance->second.empty()) { + // check for other commands to be processed + auto its_command = found_service_instance->second.front(); + if (std::get<0>(its_command) == VSOMEIP_OFFER_SERVICE) { + io_.post([&, its_command, _service, _instance](){ + offer_service(std::get<1>(its_command), _service, _instance, + std::get<2>(its_command), std::get<3>(its_command), false); + }); + } else { + io_.post([&, its_command, _service, _instance](){ + stop_offer_service(std::get<1>(its_command), _service, _instance, + std::get<2>(its_command), std::get<3>(its_command), false); + }); + } + } + } + } + return true; +} + +bool routing_manager_impl::offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) { + + return offer_service(_client, _service, _instance, _major, _minor, true); +} + +bool routing_manager_impl::offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, + bool _must_queue) { + VSOMEIP_INFO << "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) << "." << std::dec << _minor << "]"; + << ":" << std::dec << int(_major) << "." << std::dec << _minor << "]" + << " (" << _must_queue << ")"; + + // only queue commands if method was NOT called via erase_offer_command() + if (_must_queue) { + if (!insert_offer_command(_service, _instance, VSOMEIP_OFFER_SERVICE, + _client, _major, _minor)) { + return false; + } + } + + // Check if the application hosted by routing manager is allowed to offer + // offer_service requests of local proxies are checked in rms::on:message + if (_client == get_client()) { +#ifdef _WIN32 + std::uint32_t its_routing_uid = ANY_UID; + std::uint32_t its_routing_gid = ANY_GID; +#else + std::uint32_t its_routing_uid = getuid(); + std::uint32_t its_routing_gid = getgid(); +#endif + if (!security::get()->is_offer_allowed(its_routing_uid, its_routing_gid, + _client, _service, _instance)) { + VSOMEIP_WARNING << "routing_manager_impl::offer_service: " + << std::hex << "Security: Client 0x" << _client + << " isn't allowed to offer the following service/instance " + << _service << "/" << _instance + << " ~> Skip offer!"; + erase_offer_command(_service, _instance); + return false; + } + } - if(!handle_local_offer_service(_client, _service, _instance, _major, _minor)) { + if (!handle_local_offer_service(_client, _service, _instance, _major, _minor)) { + erase_offer_command(_service, _instance); return false; } @@ -282,7 +375,7 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service, if (discovery_) { std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance); if (its_info) { - discovery_->offer_service(_service, _instance, its_info); + discovery_->offer_service(its_info); } } @@ -290,16 +383,23 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service, std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_); std::set<event_t> its_already_subscribed_events; for (auto &ps : pending_subscriptions_) { - if (ps.service_ == _service && - ps.instance_ == _instance && ps.major_ == _major) { + if (ps.service_ == _service + && ps.instance_ == _instance + && ps.major_ == _major) { insert_subscription(ps.service_, ps.instance_, ps.eventgroup_, ps.event_, client_, &its_already_subscribed_events); - } + VSOMEIP_ERROR << __func__ + << ": event=" + << std::hex << ps.service_ << "." + << std::hex << ps.instance_ << "." + << std::hex << ps.event_; } } + send_pending_subscriptions(_service, _instance, _major); } stub_->on_offer_service(_client, _service, _instance, _major, _minor); on_availability(_service, _instance, true, _major, _minor); + erase_offer_command(_service, _instance); return true; } @@ -307,11 +407,28 @@ void routing_manager_impl::stop_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { + stop_offer_service(_client, _service, _instance, _major, _minor, true); +} + +void routing_manager_impl::stop_offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, + bool _must_queue) { + VSOMEIP_INFO << "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 << "]"; + << ":" << std::dec << int(_major) << "." << _minor << "]" + << " (" << _must_queue << ")"; + + if (_must_queue) { + if (!insert_offer_command(_service, _instance, VSOMEIP_STOP_OFFER_SERVICE, + _client, _major, _minor)) { + return; + } + } + bool is_local(false); { std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance); @@ -340,12 +457,12 @@ void routing_manager_impl::stop_offer_service(client_t _client, << std::hex << std::setw(4) << std::setfill('0') << _instance << ":" << std::dec << int(_major) << "." << _minor << "] " << "for remote service --> ignore"; + erase_offer_command(_service, _instance); } } void routing_manager_impl::request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - bool _use_exclusive_proxy) { + instance_t _instance, major_version_t _major, minor_version_t _minor) { VSOMEIP_INFO << "REQUEST(" << std::hex << std::setw(4) << std::setfill('0') << _client << "): [" @@ -353,8 +470,8 @@ void routing_manager_impl::request_service(client_t _client, service_t _service, << std::hex << std::setw(4) << std::setfill('0') << _instance << ":" << std::dec << int(_major) << "." << std::dec << _minor << "]"; - routing_manager_base::request_service(_client, _service, _instance, _major, - _minor, _use_exclusive_proxy); + routing_manager_base::request_service(_client, + _service, _instance, _major, _minor); auto its_info = find_service(_service, _instance); if (!its_info) { @@ -381,27 +498,22 @@ void routing_manager_impl::request_service(client_t _client, service_t _service, || _minor == ANY_MINOR)) { if(!its_info->is_local()) { requested_service_add(_client, _service, _instance, _major, _minor); - its_info->add_client(_client); - find_or_create_remote_client(_service, _instance, true, VSOMEIP_ROUTING_CLIENT); - if (_use_exclusive_proxy) { - std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(true); - if(its_endpoint) { - find_or_create_remote_client(_service, _instance, true, _client); - } + if (discovery_) { + // Non local service instance ~> tell SD to find it! + discovery_->request_service(_service, _instance, _major, + _minor, DEFAULT_TTL); } + its_info->add_client(_client); + ep_mgr_impl_->find_or_create_remote_client( + _service, _instance, true, VSOMEIP_ROUTING_CLIENT); } } } - if (_use_exclusive_proxy) { - std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_); - specific_endpoint_clients_[_service][_instance].insert(_client); - } - if (_client == get_client()) { stub_->create_local_receiver(); - service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy }; + service_data_t request = { _service, _instance, _major, _minor }; std::set<service_data_t> requests; requests.insert(request); stub_->handle_requests(_client, requests); @@ -424,36 +536,28 @@ void routing_manager_impl::release_service(client_t _client, service_t _service, requested_service_remove(_client, _service, _instance); std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if(its_info && !its_info->is_local()) { - unsubscribe_specific_client_at_sd(_service, _instance, _client); - if(!its_info->get_requesters_size()) { - if(discovery_) { + if (its_info && !its_info->is_local()) { + if (!its_info->get_requesters_size()) { + if (discovery_) { discovery_->release_service(_service, _instance); - discovery_->unsubscribe_client(_service, _instance, VSOMEIP_ROUTING_CLIENT); + discovery_->unsubscribe_all(_service, _instance); } - clear_client_endpoints(_service, _instance, true); - clear_client_endpoints(_service, _instance, false); + ep_mgr_impl_->clear_client_endpoints(_service, _instance, true); + ep_mgr_impl_->clear_client_endpoints(_service, _instance, false); its_info->set_endpoint(nullptr, true); its_info->set_endpoint(nullptr, false); - clear_identified_clients(_service, _instance); - clear_identifying_clients( _service, _instance); unset_all_eventpayloads(_service, _instance); - } else { - remove_identified_client(_service, _instance, _client); - remove_identifying_client(_service, _instance, _client); - remove_specific_client_endpoint(_service, _instance, _client, true); - remove_specific_client_endpoint(_service, _instance, _client, false); } } else { - if(discovery_) { + if (discovery_) { discovery_->release_service(_service, _instance); } } } -void routing_manager_impl::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) { +void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + major_version_t _major, event_t _event) { VSOMEIP_INFO << "SUBSCRIBE(" << std::hex << std::setw(4) << std::setfill('0') << _client <<"): [" @@ -464,14 +568,16 @@ 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) { +#ifdef VSOMEIP_ENABLE_COMPAT routing_manager_base::set_incoming_subscription_state(_client, _service, _instance, _eventgroup, _event, subscription_state_e::IS_SUBSCRIBING); +#endif auto self = shared_from_this(); - host_->on_subscription(_service, _instance, _eventgroup, _client, true, - [this, self, _client, _service, _instance, _eventgroup, - _event, _major, _subscription_type] + host_->on_subscription(_service, _instance, _eventgroup, _client, _uid, _gid, true, + [this, self, _client, _uid, _gid, _service, _instance, _eventgroup, + _event, _major] (const bool _subscription_accepted) { - (void) find_or_create_local(_client); + (void) ep_mgr_->find_or_create_local(_client); if (!_subscription_accepted) { stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup, _event); VSOMEIP_INFO << "Subscription request from client: 0x" << std::hex @@ -481,58 +587,52 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service, } else { stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup, _event); } - routing_manager_base::subscribe(_client, _service, _instance, _eventgroup, _major, _event, _subscription_type); + routing_manager_base::subscribe(_client, _uid, _gid, _service, _instance, _eventgroup, _major, _event); +#ifdef VSOMEIP_ENABLE_COMPAT send_pending_notify_ones(_service, _instance, _eventgroup, _client); routing_manager_base::erase_incoming_subscription_state(_client, _service, _instance, _eventgroup, _event); +#endif }); } else { if (discovery_) { - client_t subscriber = VSOMEIP_ROUTING_CLIENT; - if (0 == its_local_client) { - subscriber = is_specific_endpoint_client(_client, _service, _instance); - if (subscriber != VSOMEIP_ROUTING_CLIENT) { - if (supports_selective(_service, _instance)) { - identify_for_subscribe(_client, _service, _instance, - _major, _subscription_type); - } else { - VSOMEIP_INFO << "Subcribe to legacy selective service: " << std::hex - << _service << ":" << _instance << "."; - } - } - } - std::unique_lock<std::mutex> eventgroup_lock; - auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); - if (its_eventgroup) { - eventgroup_lock = its_eventgroup->get_subscription_lock(); - } std::set<event_t> its_already_subscribed_events; + + // Note: The calls to insert_subscription & handle_subscription_state must not + // run concurrently to a call to on_subscribe_ack. Therefore the lock is acquired + // before calling insert_subscription and released after the call to + // handle_subscription_state. + std::unique_lock<std::mutex> its_critical(remote_subscription_state_mutex_); bool inserted = insert_subscription(_service, _instance, _eventgroup, _event, _client, &its_already_subscribed_events); if (inserted) { if (0 == its_local_client) { handle_subscription_state(_client, _service, _instance, _eventgroup, _event); - if (its_eventgroup) { - eventgroup_lock.unlock(); - } + its_critical.unlock(); static const ttl_t configured_ttl(configuration_->get_sd_ttl()); notify_one_current_value(_client, _service, _instance, _eventgroup, _event, its_already_subscribed_events); - discovery_->subscribe(_service, _instance, _eventgroup, - _major, configured_ttl, subscriber, _subscription_type); + + auto its_info = find_eventgroup(_service, _instance, _eventgroup); + if (its_info) { + discovery_->subscribe(_service, _instance, _eventgroup, + _major, configured_ttl, + its_info->is_selective() ? _client : VSOMEIP_ROUTING_CLIENT); + } } else { + its_critical.unlock(); if (is_available(_service, _instance, _major)) { - stub_->send_subscribe(find_local(_service, _instance), - _client, _service, _instance, _eventgroup, _major, _event, DEFAULT_SUBSCRIPTION); + stub_->send_subscribe(ep_mgr_->find_local(_service, _instance), + _client, _service, _instance, _eventgroup, _major, _event, + PENDING_SUBSCRIPTION_ID); } } - } else if (its_eventgroup) { - eventgroup_lock.unlock(); } if (get_client() == _client) { std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_); - subscription_data_t subscription = { _service, _instance, _eventgroup, _major, - _event, _subscription_type}; + subscription_data_t subscription = { + _service, _instance, _eventgroup, _major, _event, _uid, _gid + }; pending_subscriptions_.insert(subscription); } } else { @@ -541,8 +641,8 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service, } } -void routing_manager_impl::unsubscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, event_t _event) { +void routing_manager_impl::unsubscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) { VSOMEIP_INFO << "UNSUBSCRIBE(" << std::hex << std::setw(4) << std::setfill('0') << _client << "): [" @@ -552,14 +652,16 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service, << std::hex << std::setw(4) << std::setfill('0') << _event << "]"; bool last_subscriber_removed(true); + + auto its_event = find_event(_service, _instance, _event); std::shared_ptr<eventgroupinfo> its_info = find_eventgroup(_service, _instance, _eventgroup); if (its_info) { - for (auto e : its_info->get_events()) { + for (const auto& e : its_info->get_events()) { if (e->get_event() == _event || ANY_EVENT == _event) e->remove_subscriber(_eventgroup, _client); } - for (auto e : its_info->get_events()) { + for (const auto& e : its_info->get_events()) { if (e->has_subscriber(_eventgroup, ANY_CLIENT)) { last_subscriber_removed = false; break; @@ -568,40 +670,36 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service, } if (discovery_) { - host_->on_subscription(_service, _instance, _eventgroup, _client, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; }); + host_->on_subscription(_service, _instance, _eventgroup, _client, _uid, _gid, false, + [](const bool _subscription_accepted){ (void)_subscription_accepted; }); if (0 == find_local_client(_service, _instance)) { - client_t subscriber = is_specific_endpoint_client(_client, _service, _instance); if (last_subscriber_removed) { unset_all_eventpayloads(_service, _instance, _eventgroup); - } - if (subscriber == VSOMEIP_ROUTING_CLIENT && last_subscriber_removed) { { - auto tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber); + auto tuple = std::make_tuple(_service, _instance, _eventgroup, _client); std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); remote_subscription_state_.erase(tuple); } - // for normal subscribers only unsubscribe via SD if last - // subscriber was removed - discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber); - } else if (subscriber != VSOMEIP_ROUTING_CLIENT) { - { - auto tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber); - std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); - remote_subscription_state_.erase(tuple); + } + + if (last_subscriber_removed + || (its_event && its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT)) { + if (its_info) { + discovery_->unsubscribe(_service, _instance, _eventgroup, + its_info->is_selective() ? _client : VSOMEIP_ROUTING_CLIENT); } - // for selective subscribers always unsubscribe at the SD - discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber); } } else { if (get_client() == _client) { std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_); remove_pending_subscription(_service, _instance, _eventgroup, _event); - stub_->send_unsubscribe(find_local(_service, _instance), + stub_->send_unsubscribe( + ep_mgr_->find_local(_service, _instance), _client, _service, _instance, _eventgroup, _event, - DEFAULT_SUBSCRIPTION); + PENDING_SUBSCRIPTION_ID); } } - clear_multicast_endpoints(_service, _instance); + ep_mgr_impl_->clear_multicast_endpoints(_service, _instance); } else { VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!"; @@ -609,18 +707,21 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service, } bool routing_manager_impl::send(client_t _client, - std::shared_ptr<message> _message, bool _flush) { - return routing_manager_base::send(_client, _message, _flush); + std::shared_ptr<message> _message) { + return routing_manager_base::send(_client, _message); } bool routing_manager_impl::send(client_t _client, const byte_t *_data, - length_t _size, instance_t _instance, bool _flush, bool _reliable, - client_t _bound_client, bool _is_valid_crc, bool _sent_from_remote) { + length_t _size, instance_t _instance, bool _reliable, + client_t _bound_client, + credentials_t _credentials, + uint8_t _status_check, bool _sent_from_remote) { bool is_sent(false); if (_size > VSOMEIP_MESSAGE_TYPE_POS) { std::shared_ptr<endpoint> its_target; bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]); bool is_notification = utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]); + bool is_response = utility::is_response(_data[VSOMEIP_MESSAGE_TYPE_POS]); client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]); @@ -629,21 +730,14 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, method_t its_method = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); - bool is_service_discovery = (its_service == vsomeip::sd::service - && its_method == vsomeip::sd::method); - -#ifdef USE_DLT - bool is_response(false); -#endif + bool is_service_discovery + = (its_service == sd::service && its_method == sd::method); if (is_request) { - its_target = find_local(its_service, _instance); + its_target = ep_mgr_->find_local(its_service, _instance); } else if (!is_notification) { -#ifdef USE_DLT - is_response = true; -#endif its_target = find_local(its_client); - } else if (is_notification && _client) { // Selective notifications! + } else if (is_notification && _client && !is_service_discovery) { // Selective notifications! if (_client == get_client()) { #ifdef USE_DLT const uint16_t its_data_size @@ -654,7 +748,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data, its_data_size); #endif - deliver_message(_data, _size, _instance, _reliable, _bound_client, _is_valid_crc, _sent_from_remote); + deliver_message(_data, _size, _instance, _reliable, _bound_client, _credentials, _status_check, _sent_from_remote); return true; } its_target = find_local(_client); @@ -673,36 +767,39 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, _data, its_data_size); } #endif - is_sent = send_local(its_target, get_client(), _data, _size, _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc); + is_sent = send_local(its_target, get_client(), _data, _size, _instance, _reliable, VSOMEIP_SEND, _status_check); } else { // Check whether hosting application should get the message // If not, check routes to external - if ((its_client == host_->get_client() && !is_request) + if ((its_client == host_->get_client() && is_response) || (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, _bound_client, _is_valid_crc, _sent_from_remote); + // TODO: Find out how to handle session id here + is_sent = deliver_message(_data, _size, _instance, _reliable, VSOMEIP_ROUTING_CLIENT, _credentials, _status_check); } else { e2e_buffer outputBuffer; - if( configuration_->is_e2e_enabled()) { + if (e2e_provider_) { if ( !is_service_discovery) { service_t its_service = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); method_t its_method = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); - if( custom_protectors.count({its_service, its_method})) { +#ifndef ANDROID + if (e2e_provider_->is_protected({its_service, its_method})) { outputBuffer.assign(_data, _data + VSOMEIP_PAYLOAD_POS); e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data +_size); - custom_protectors[{its_service, its_method}]->protect( inputBuffer); + e2e_provider_->protect({its_service, its_method}, inputBuffer); outputBuffer.resize(inputBuffer.size() + VSOMEIP_PAYLOAD_POS); std::copy(inputBuffer.begin(), inputBuffer.end(), outputBuffer.begin() + VSOMEIP_PAYLOAD_POS); _data = outputBuffer.data(); } +#endif } } if (is_request) { - client_t client = is_specific_endpoint_client(its_client, its_service, _instance); - its_target = find_or_create_remote_client(its_service, _instance, _reliable, client); + client_t client = VSOMEIP_ROUTING_CLIENT; + its_target = ep_mgr_impl_->find_or_create_remote_client( + its_service, _instance, _reliable, client); if (its_target) { #ifdef USE_DLT const uint16_t its_data_size @@ -713,7 +810,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data, its_data_size); #endif - is_sent = its_target->send(_data, _size, _flush); + is_sent = its_target->send(_data, _size); } else { const session_t its_session = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_SESSION_POS_MIN], @@ -729,7 +826,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, std::shared_ptr<serviceinfo> its_info(find_service(its_service, _instance)); if (its_info || is_service_discovery) { if (is_notification && !is_service_discovery) { - send_local_notification(get_client(), _data, _size, _instance, _flush, _reliable, _is_valid_crc); + send_local_notification(get_client(), _data, _size, _instance, _reliable, _status_check); method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method); @@ -741,42 +838,49 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, // we need both endpoints as clients can subscribe to events via TCP and UDP std::shared_ptr<endpoint> its_udp_server_endpoint = its_info->get_endpoint(false); std::shared_ptr<endpoint> its_tcp_server_endpoint = its_info->get_endpoint(true); - bool is_offered_both(false); - if (its_udp_server_endpoint && its_tcp_server_endpoint) { - is_offered_both = true; - } + if (its_udp_server_endpoint || its_tcp_server_endpoint) { + const auto its_reliability = its_event->get_reliability(); for (auto its_group : its_event->get_eventgroups()) { auto its_eventgroup = find_eventgroup(its_service, _instance, its_group); if (its_eventgroup) { // Unicast targets - for (const auto &its_remote : its_eventgroup->get_targets()) { - if(its_remote.endpoint_->is_reliable() && its_tcp_server_endpoint) { - if (!is_offered_both || (is_offered_both && its_event->is_reliable())) { - its_targets.insert(its_remote.endpoint_); + for (const auto &its_remote : its_eventgroup->get_unicast_targets()) { + if (its_remote->is_reliable() && its_tcp_server_endpoint) { + if (its_reliability == reliability_type_e::RT_RELIABLE + || its_reliability == reliability_type_e::RT_BOTH) { + its_targets.insert(its_remote); } } else if (its_udp_server_endpoint && !its_eventgroup->is_sending_multicast()) { - if (!is_offered_both || (is_offered_both && !its_event->is_reliable())) { - its_targets.insert(its_remote.endpoint_); + if (its_reliability == reliability_type_e::RT_UNRELIABLE + || its_reliability == reliability_type_e::RT_BOTH) { + its_targets.insert(its_remote); } } } // Send to multicast targets if subscribers are still interested if (its_eventgroup->is_sending_multicast()) { - for (auto its_multicast_target : its_eventgroup->get_multicast_targets()) { - if (!is_offered_both || (is_offered_both && !its_event->is_reliable())) { - its_targets.insert(its_multicast_target.endpoint_); + if (its_reliability == reliability_type_e::RT_UNRELIABLE + || its_reliability == reliability_type_e::RT_BOTH) { + boost::asio::ip::address its_address; + uint16_t its_port; + if (its_eventgroup->get_multicast(its_address, its_port)) { + std::shared_ptr<endpoint_definition> its_multicast_target; + its_multicast_target = endpoint_definition::get(its_address, + its_port, false, its_service, _instance); + its_targets.insert(its_multicast_target); } } } } } } + for (auto const &target : its_targets) { if (target->is_reliable()) { - its_tcp_server_endpoint->send_to(target, _data, _size, _flush); + its_tcp_server_endpoint->send_to(target, _data, _size); } else { - its_udp_server_endpoint->send_to(target, _data, _size, _flush); + its_udp_server_endpoint->send_to(target, _data, _size); } #ifdef USE_DLT has_sent = true; @@ -798,7 +902,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, if ((utility::is_response(_data[VSOMEIP_MESSAGE_TYPE_POS]) || utility::is_error(_data[VSOMEIP_MESSAGE_TYPE_POS])) && !its_info->is_local()) { - // we received a response/error but neither the hosting application + // We received a response/error but neither the hosting application // nor another local client could be found --> drop const session_t its_session = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_SESSION_POS_MIN], @@ -824,7 +928,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data, its_data_size); #endif - is_sent = its_target->send(_data, _size, _flush); + is_sent = its_target->send(_data, _size); } else { const session_t its_session = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_SESSION_POS_MIN], @@ -860,30 +964,43 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, } bool routing_manager_impl::send_to( + const client_t _client, const std::shared_ptr<endpoint_definition> &_target, - std::shared_ptr<message> _message, bool _flush) { + std::shared_ptr<message> _message) { bool is_sent(false); - std::lock_guard<std::mutex> its_lock(serialize_mutex_); - if (serializer_->serialize(_message.get())) { - const byte_t *_data = serializer_->get_data(); - length_t _size = serializer_->get_size(); - e2e_buffer outputBuffer; - if( configuration_->is_e2e_enabled()) { + + std::shared_ptr<serializer> its_serializer(get_serializer()); + if (its_serializer->serialize(_message.get())) { + const byte_t *its_data = its_serializer->get_data(); + length_t its_size = its_serializer->get_size(); + e2e_buffer its_output_buffer; + if (e2e_provider_) { service_t its_service = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + its_data[VSOMEIP_SERVICE_POS_MIN], + its_data[VSOMEIP_SERVICE_POS_MAX]); method_t its_method = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); - if( custom_protectors.count({its_service, its_method})) { - outputBuffer.assign(_data, _data + VSOMEIP_PAYLOAD_POS); - e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data +_size); - custom_protectors[{its_service, its_method}]->protect( inputBuffer); - outputBuffer.resize(inputBuffer.size() + VSOMEIP_PAYLOAD_POS); - std::copy(inputBuffer.begin(), inputBuffer.end(), outputBuffer.begin() + VSOMEIP_PAYLOAD_POS); - _data = outputBuffer.data(); + its_data[VSOMEIP_METHOD_POS_MIN], + its_data[VSOMEIP_METHOD_POS_MAX]); +#ifndef ANDROID + if(e2e_provider_->is_protected({its_service, its_method})) { + its_output_buffer.assign(its_data, its_data + VSOMEIP_PAYLOAD_POS); + e2e_buffer its_input_buffer(its_data + VSOMEIP_PAYLOAD_POS, its_data + its_size); + e2e_provider_->protect({its_service, its_method}, its_input_buffer); + its_output_buffer.resize(its_input_buffer.size() + VSOMEIP_PAYLOAD_POS); + std::copy(its_input_buffer.begin(), its_input_buffer.end(), + its_output_buffer.begin() + VSOMEIP_PAYLOAD_POS); + its_data = its_output_buffer.data(); } +#endif } - is_sent = send_to(_target, _data, _size, _message->get_instance(), _flush); - serializer_->reset(); + + const_cast<byte_t*>(its_data)[VSOMEIP_CLIENT_POS_MIN] = VSOMEIP_WORD_BYTE1(_client); + const_cast<byte_t*>(its_data)[VSOMEIP_CLIENT_POS_MAX] = VSOMEIP_WORD_BYTE0(_client); + + is_sent = send_to(_target, its_data, its_size, _message->get_instance()); + + its_serializer->reset(); + put_serializer(its_serializer); } else { VSOMEIP_ERROR<< "routing_manager_impl::send_to: serialization failed."; } @@ -892,10 +1009,10 @@ bool routing_manager_impl::send_to( bool routing_manager_impl::send_to( const std::shared_ptr<endpoint_definition> &_target, - const byte_t *_data, uint32_t _size, instance_t _instance, - bool _flush) { - std::shared_ptr<endpoint> its_endpoint = find_server_endpoint( - _target->get_remote_port(), _target->is_reliable()); + const byte_t *_data, uint32_t _size, instance_t _instance) { + std::shared_ptr<endpoint> its_endpoint = + ep_mgr_impl_->find_server_endpoint( + _target->get_remote_port(), _target->is_reliable()); if (its_endpoint) { #ifdef USE_DLT @@ -909,26 +1026,30 @@ bool routing_manager_impl::send_to( #else (void) _instance; #endif - return its_endpoint->send_to(_target, _data, _size, _flush); + return its_endpoint->send_to(_target, _data, _size); } return false; } -bool routing_manager_impl::send_to( +bool routing_manager_impl::send_via_sd( const std::shared_ptr<endpoint_definition> &_target, const byte_t *_data, uint32_t _size, uint16_t _sd_port) { - std::shared_ptr<endpoint> its_endpoint = find_server_endpoint( - _sd_port, _target->is_reliable()); + std::shared_ptr<endpoint> its_endpoint = + ep_mgr_impl_->find_server_endpoint(_sd_port, + _target->is_reliable()); if (its_endpoint) { #ifdef USE_DLT - const uint16_t its_data_size - = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); + if (tc_->is_sd_enabled()) { + const uint16_t its_data_size + = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); - 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); + 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); + + } #endif return its_endpoint->send_to(_target, _data, _size); } @@ -936,13 +1057,16 @@ bool routing_manager_impl::send_to( return false; } -void routing_manager_impl::register_event( - client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::set<eventgroup_t> &_eventgroups, - bool _is_field, std::chrono::milliseconds _cycle, - bool _change_resets_cycle, epsilon_change_func_t _epsilon_change_func, +void routing_manager_impl::register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, const event_type_e _type, + reliability_type_e _reliability, + std::chrono::milliseconds _cycle, bool _change_resets_cycle, + bool _update_on_change, + epsilon_change_func_t _epsilon_change_func, bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) { - auto its_event = find_event(_service, _instance, _event); + auto its_event = find_event(_service, _instance, _notifier); bool is_first(false); if (its_event) { if (!its_event->has_ref(_client, _is_provided)) { @@ -952,8 +1076,11 @@ void routing_manager_impl::register_event( is_first = true; } if (is_first) { - routing_manager_base::register_event(_client, _service, _instance, - _event, _eventgroups, _is_field, _cycle, _change_resets_cycle, + routing_manager_base::register_event(_client, + _service, _instance, + _notifier, + _eventgroups, _type, _reliability, + _cycle, _change_resets_cycle, _update_on_change, _epsilon_change_func, _is_provided, _is_shadow, _is_cache_placeholder); } @@ -961,17 +1088,20 @@ void routing_manager_impl::register_event( << 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') << _event + << std::hex << std::setw(4) << std::setfill('0') << _notifier << ":is_provider=" << _is_provided << "]"; } void routing_manager_impl::register_shadow_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::set<eventgroup_t> &_eventgroups, - bool _is_field, bool _is_provided) { - routing_manager_base::register_event(_client, _service, _instance, - _event, _eventgroups, _is_field, - std::chrono::milliseconds::zero(), false, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, event_type_e _type, + reliability_type_e _reliability, bool _is_provided) { + routing_manager_base::register_event(_client, + _service, _instance, + _notifier, + _eventgroups, _type, _reliability, + std::chrono::milliseconds::zero(), false, true, nullptr, _is_provided, true); } @@ -985,56 +1115,49 @@ 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 _remote_subscriber) { + bool _force +#ifdef VSOMEIP_ENABLE_COMPAT + , bool _remote_subscriber +#endif + ) { if (find_local(_client)) { routing_manager_base::notify_one(_service, _instance, _event, _payload, - _client, _force, _flush, _remote_subscriber); + _client, _force +#ifdef VSOMEIP_ENABLE_COMPAT + , _remote_subscriber +#endif + ); } else { std::shared_ptr<event> its_event = find_event(_service, _instance, _event); if (its_event) { - // Event is valid for service/instance - bool found_eventgroup(false); - // 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()) { - auto its_eventgroup = find_eventgroup(_service, _instance, its_group); + std::set<std::shared_ptr<endpoint_definition> > its_targets; + const auto its_reliability = its_event->get_reliability(); + for (const auto g : its_event->get_eventgroups()) { + const auto its_eventgroup = find_eventgroup(_service, _instance, g); if (its_eventgroup) { - // Eventgroup is valid for service/instance - found_eventgroup = true; - break; - } - } - if (found_eventgroup) { - const bool is_offered_both = - (configuration_->get_reliable_port(_service, _instance) != ILLEGAL_PORT && - configuration_->get_unreliable_port(_service, _instance) != ILLEGAL_PORT); - - std::set<std::shared_ptr<endpoint_definition>> its_targets; - // Now set event's payload! - // Either with endpoint_definition (remote) or with client (local). - { - std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_); - auto its_service = remote_subscribers_.find(_service); - if (its_service != remote_subscribers_.end()) { - auto its_instance = its_service->second.find(_instance); - if (its_instance != its_service->second.end()) { - auto its_subscriber = its_instance->second.find(_client); - if (its_subscriber != its_instance->second.end()) { - its_targets = its_subscriber->second; + const auto its_subscriptions = its_eventgroup->get_remote_subscriptions(); + for (const auto &s : its_subscriptions) { + if (s->has_client(_client)) { + if (its_reliability == reliability_type_e::RT_RELIABLE + || its_reliability == reliability_type_e::RT_BOTH) { + const auto its_reliable = s->get_reliable(); + if (its_reliable) + its_targets.insert(its_reliable); + } + if (its_reliability == reliability_type_e::RT_UNRELIABLE + || its_reliability == reliability_type_e::RT_BOTH) { + const auto its_unreliable = s->get_unreliable(); + if (its_unreliable) + its_targets.insert(its_unreliable); } } } } + } + + if (its_targets.size() > 0) { for (const auto &its_target : its_targets) { - if (!is_offered_both) { - its_event->set_payload(_payload, its_target, _force, _flush); - } else { - if (its_event->is_reliable() && its_target->is_reliable()) { - its_event->set_payload(_payload, its_target, _force, _flush); - } else if (!its_event->is_reliable() && !its_target->is_reliable()) { - its_event->set_payload(_payload, its_target, _force, _flush); - } - } + its_event->set_payload(_payload, _client, its_target, _force); } } } else { @@ -1050,24 +1173,6 @@ void routing_manager_impl::on_availability(service_t _service, instance_t _insta host_->on_availability(_service, _instance, _is_available, _major, _minor); } -void routing_manager_impl::on_error( - const byte_t *_data, length_t _length, endpoint *_receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port) { - instance_t its_instance = 0; - if (_length >= VSOMEIP_SERVICE_POS_MAX) { - service_t its_service = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); - its_instance = find_instance(its_service, _receiver); - } - send_error(return_code_e::E_MALFORMED_MESSAGE, _data, _length, its_instance, - _receiver->is_reliable(), _receiver, _remote_address, _remote_port); -} - -void routing_manager_impl::release_port(uint16_t _port, bool _reliable) { - std::lock_guard<std::mutex> its_lock(used_client_ports_mutex_); - used_client_ports_[_reliable].erase(_port); -} bool routing_manager_impl::offer_service_remotely(service_t _service, instance_t _instance, @@ -1156,7 +1261,7 @@ bool routing_manager_impl::stop_offer_service_remotely(service_t _service, clear_remote_subscriber(_service, _instance); if (discovery_ && its_info) { - discovery_->stop_offer_service(_service, _instance, its_info); + discovery_->stop_offer_service(its_info); its_info->set_endpoint(std::shared_ptr<endpoint>(), _reliable); } } else { @@ -1168,7 +1273,7 @@ bool routing_manager_impl::stop_offer_service_remotely(service_t _service, // 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); + discovery_->stop_offer_service(its_copied_info); } } @@ -1178,7 +1283,7 @@ bool routing_manager_impl::stop_offer_service_remotely(service_t _service, 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, + client_t _bound_client, credentials_t _credentials, const boost::asio::ip::address &_remote_address, std::uint16_t _remote_port) { #if 0 @@ -1191,7 +1296,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, (void)_bound_client; service_t its_service; method_t its_method; - bool its_is_crc_valid(true); + uint8_t its_check_status = e2e::profile_interface::generic_check_status::E2E_OK; instance_t its_instance(0x0); #ifdef USE_DLT bool is_forwarded(true); @@ -1215,7 +1320,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, } } } else { - its_instance = find_instance(its_service, _receiver); + its_instance = ep_mgr_impl_->find_instance(its_service, _receiver); if (its_instance == 0xFFFF) { its_method = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_METHOD_POS_MIN], @@ -1256,7 +1361,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, } // Security checks if enabled! - if (configuration_->is_security_enabled()) { + if (security::get()->is_enabled()) { if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { client_t requester = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_CLIENT_POS_MIN], @@ -1276,7 +1381,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, << " which is already used locally ~> Skip message!"; return; } - if (!configuration_->is_remote_client_allowed()) { + if (!security::get()->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 @@ -1287,37 +1392,28 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, } } } - if( configuration_->is_e2e_enabled()) { + if (e2e_provider_) { its_method = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); - if( custom_checkers.count({its_service, its_method})) { +#ifndef ANDROID + if( e2e_provider_->is_checked({its_service, its_method})) { e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data + _size); - e2e::profile_interface::generic_check_status check_status; - custom_checkers[{its_service, its_method}]->check( inputBuffer, check_status); + e2e_provider_->check({its_service, its_method}, inputBuffer, its_check_status); - if ( check_status != e2e::profile_interface::generic_check_status::E2E_OK ) { + if ( its_check_status != e2e::profile_interface::generic_check_status::E2E_OK ) { VSOMEIP_INFO << std::hex << "E2E protection: CRC check failed for service: " << its_service << " method: " << its_method; - its_is_crc_valid = false; } } +#endif } - if (!deliver_specific_endpoint_message( - its_service, its_instance, _data, _size, _receiver)) { - // set client ID to zero for all messages - if( utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) { - byte_t *its_data = const_cast<byte_t *>(_data); - its_data[VSOMEIP_CLIENT_POS_MIN] = 0x0; - its_data[VSOMEIP_CLIENT_POS_MAX] = 0x0; - } - // Common way of message handling + + // Common way of message handling #ifdef USE_DLT - is_forwarded = + is_forwarded = #endif - on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(), - _bound_client, its_is_crc_valid, true); - - } + on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(), + _bound_client, _credentials, its_check_status, true); } } #ifdef USE_DLT @@ -1345,7 +1441,8 @@ bool routing_manager_impl::on_message( service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _reliable, client_t _bound_client, - bool _is_valid_crc, + credentials_t _credentials, + uint8_t _check_status, bool _is_from_remote) { #if 0 std::stringstream msg; @@ -1367,15 +1464,15 @@ bool routing_manager_impl::on_message( _data[VSOMEIP_CLIENT_POS_MAX]); } - if (its_client == VSOMEIP_ROUTING_CLIENT - && utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) { is_forwarded = deliver_notification(_service, _instance, _data, _size, - _reliable, _bound_client, _is_valid_crc, _is_from_remote); + _reliable, _bound_client, _credentials, _check_status, _is_from_remote); } else if (its_client == host_->get_client()) { deliver_message(_data, _size, _instance, - _reliable, _bound_client, _is_valid_crc, _is_from_remote); + _reliable, _bound_client, _credentials, _check_status, _is_from_remote); } else { - send(its_client, _data, _size, _instance, true, _reliable, _bound_client, _is_valid_crc, _is_from_remote); //send to proxy + send(its_client, _data, _size, _instance, _reliable, + _bound_client, _credentials, _check_status, _is_from_remote); //send to proxy } return is_forwarded; } @@ -1384,9 +1481,7 @@ void routing_manager_impl::on_notification(client_t _client, service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _notify_one) { event_t its_event_id = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_METHOD_POS_MIN], - _data[VSOMEIP_METHOD_POS_MAX]); - + _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); std::shared_ptr<event> its_event = find_event(_service, _instance, its_event_id); if (its_event) { uint32_t its_length = utility::get_payload_size(_data, _size); @@ -1396,197 +1491,37 @@ 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, false); + notify_one(_service, _instance, its_event->get_event(), + its_payload, _client, true +#ifdef VSOMEIP_ENABLE_COMPAT + , false +#endif + ); } else { if (its_event->is_field()) { - if (its_event->is_set()) { - its_event->set_payload(its_payload, false, true); - } else { - // new subscribers will be notified by SD via sent_initiale_events; - if (its_event->get_remote_notification_pending()) { - // Set payload first time ~> notify all remote subscriber per unicast (initial field) - std::vector<std::unique_lock<std::mutex>> its_locks; - std::vector<std::shared_ptr<eventgroupinfo>> its_eventgroupinfos; - for (auto its_group : its_event->get_eventgroups()) { - auto its_eventgroup = find_eventgroup(_service, _instance, its_group); - if (its_eventgroup) { - its_locks.push_back(its_eventgroup->get_subscription_lock()); - its_eventgroupinfos.push_back(its_eventgroup); - } - } - - bool is_offered_both(false); - if (configuration_->get_reliable_port(_service, _instance) != ILLEGAL_PORT && - configuration_->get_unreliable_port(_service, _instance) != ILLEGAL_PORT) { - is_offered_both = true; - } - for (const auto &its_eventgroup : its_eventgroupinfos) { - //Unicast targets - for (auto its_remote : its_eventgroup->get_targets()) { - if (!is_offered_both) { - its_event->set_payload(its_payload, its_remote.endpoint_, true, true); - } else { - bool was_set(false); - if (its_event->is_reliable() && its_remote.endpoint_->is_reliable()) { - its_event->set_payload(its_payload, its_remote.endpoint_, true, true); - was_set = true; - } - if (!its_event->is_reliable() && !its_remote.endpoint_->is_reliable()) { - its_event->set_payload(its_payload, its_remote.endpoint_, true, true); - was_set = true; - } - if (!was_set) { - its_event->set_payload_dont_notify(its_payload); - } - } - } - } - its_event->set_remote_notification_pending(false); - } else { - its_event->set_payload_dont_notify(its_payload); - } + if (!its_event->set_payload_notify_pending(its_payload)) { + its_event->set_payload(its_payload, false); } } else { - its_event->set_payload(its_payload, false, true); + its_event->set_payload(its_payload, false, true); } } } } -void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) { - // Is called when endpoint->connect succeeded! - struct service_info { - service_t service_id_; - instance_t instance_id_; - major_version_t major_; - minor_version_t minor_; - 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_); - for (auto &its_service : remote_services_) { - for (auto &its_instance : its_service.second) { - for (auto &its_client : its_instance.second) { - if (its_client.first == VSOMEIP_ROUTING_CLIENT || - its_client.first == get_client()) { - auto found_endpoint = its_client.second.find(false); - if (found_endpoint != its_client.second.end()) { - 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_established(true); - return; - } - services_to_report_.push_front( - { its_service.first, - its_instance.first, - its_info->get_major(), - its_info->get_minor(), - false, _endpoint }); - } - } - found_endpoint = its_client.second.find(true); - if (found_endpoint != its_client.second.end()) { - 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_established(true); - return; - } - services_to_report_.push_front( - { its_service.first, - its_instance.first, - its_info->get_major(), - its_info->get_minor(), - true, _endpoint }); - } - } - } - } - } +bool routing_manager_impl::is_last_stop_callback(const uint32_t _callback_id) { + bool last_callback(false); + auto found_id = callback_counts_.find(_callback_id); + if (found_id != callback_counts_.end()) { + found_id->second--; + if (found_id->second == 0) { + last_callback = true; } } - - for (const auto &s : services_to_report_) { - on_availability(s.service_id_, s.instance_id_, true, s.major_, s.minor_); - if (s.reliable_) { - stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, s.service_id_, - s.instance_id_, s.major_, s.minor_); - } - 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(3), ec); - if (!ec) { - its_timer->async_wait( - std::bind( - &routing_manager_impl::call_sd_endpoint_connected, - std::static_pointer_cast<routing_manager_impl>( - shared_from_this()), - std::placeholders::_1, s.service_id_, - s.instance_id_, s.endpoint_, its_timer)); - } else { - VSOMEIP_ERROR<< "routing_manager_impl::on_connect: " << ec.message(); - } - } - if (services_to_report_.empty()) { - _endpoint->set_established(true); - } -} - -void routing_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) { - // Is called when endpoint->connect fails! - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - for (auto &its_service : remote_services_) { - for (auto &its_instance : its_service.second) { - for (auto &its_client : its_instance.second) { - if (its_client.first == VSOMEIP_ROUTING_CLIENT || - its_client.first == get_client()) { - auto found_endpoint = its_client.second.find(false); - if (found_endpoint != its_client.second.end()) { - if (found_endpoint->second.get() == _endpoint.get()) { - - std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first)); - if(!its_info){ - return; - } - on_availability(its_service.first, its_instance.first, - false, its_info->get_major(), its_info->get_minor()); - } - } - found_endpoint = its_client.second.find(true); - if (found_endpoint != its_client.second.end()) { - if (found_endpoint->second.get() == _endpoint.get()) { - - std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first)); - if(!its_info){ - return; - } - on_availability(its_service.first, its_instance.first, - false, its_info->get_major(), its_info->get_minor()); - stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, - its_service.first, its_instance.first, - its_info->get_major(), - its_info->get_minor()); - VSOMEIP_WARNING << __func__ - << ": lost connection to remote service: " - << std::hex << std::setw(4) << std::setfill('0') << its_service.first << "." - << std::hex << std::setw(4) << std::setfill('0') << its_instance.first; - } - } - } - } - } + if (last_callback) { + callback_counts_.erase(_callback_id); } + return last_callback; } void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _service, @@ -1643,47 +1578,133 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se if (its_info) { its_reliable_endpoint = its_info->get_endpoint(true); its_unreliable_endpoint = its_info->get_endpoint(false); - } + static std::atomic<uint32_t> callback_id(0); + const uint32_t its_callback_id = ++callback_id; + + struct ready_to_stop_t { + ready_to_stop_t() : reliable_(false), unreliable_(false){} + std::atomic<bool> reliable_; + std::atomic<bool> unreliable_; + }; + auto ready_to_stop = std::make_shared<ready_to_stop_t>(); + auto ptr = shared_from_this(); + + auto callback = [&, its_callback_id, ptr, its_info, its_reliable_endpoint, its_unreliable_endpoint, + ready_to_stop, _service, _instance, _major, _minor] + (std::shared_ptr<endpoint> _endpoint, service_t _stopped_service) { + (void)_stopped_service; + if (its_reliable_endpoint && its_reliable_endpoint == _endpoint) { + ready_to_stop->reliable_ = true; + } + if (its_unreliable_endpoint && its_unreliable_endpoint == _endpoint) { + ready_to_stop->unreliable_ = true; + } + if ((its_unreliable_endpoint && !ready_to_stop->unreliable_) || + (its_reliable_endpoint && !ready_to_stop->reliable_)) { + { + std::lock_guard<std::mutex> its_lock(callback_counts_mutex_); + if (is_last_stop_callback(its_callback_id)) { + erase_offer_command(_service, _instance); + } + } + return; + } - if (discovery_) { - if (its_info) { - if (its_info->get_major() == _major && its_info->get_minor() == _minor) { - discovery_->stop_offer_service(_service, _instance, its_info); + if (discovery_) { + if (its_info->get_major() == _major && its_info->get_minor() == _minor) { + discovery_->stop_offer_service(its_info); + } } - } - } - del_routing_info(_service, _instance, (its_reliable_endpoint != nullptr), - (its_unreliable_endpoint != nullptr)); + del_routing_info(_service, _instance, (its_reliable_endpoint != nullptr), + (its_unreliable_endpoint != nullptr)); - // Cleanup reliable & unreliable server endpoints hold before - if (its_info) { - if (its_unreliable_endpoint) { - cleanup_server_endpoint(_service, its_unreliable_endpoint); - // Clear service info and service group - clear_service_info(_service, _instance, false); + for (const auto& ep: {its_reliable_endpoint, its_unreliable_endpoint}) { + if (ep) { + if (ep_mgr_impl_->remove_instance(_service, ep.get())) { + { + std::lock_guard<std::mutex> its_lock(callback_counts_mutex_); + callback_counts_[its_callback_id]++; + } + // last instance -> pass ANY_INSTANCE and shutdown completely + ep->prepare_stop( + [&, _service, _instance, its_callback_id, ptr, its_reliable_endpoint, its_unreliable_endpoint] + (std::shared_ptr<endpoint> _endpoint, + service_t _stopped_service) { + (void)_stopped_service; + if (ep_mgr_impl_->remove_server_endpoint( + _endpoint->get_local_port(), + _endpoint->is_reliable())) { + _endpoint->stop(); + } + { + std::lock_guard<std::mutex> its_lock(callback_counts_mutex_); + if (is_last_stop_callback(its_callback_id)) { + erase_offer_command(_service, _instance); + } + } + }, ANY_SERVICE); + } + // Clear service info and service group + clear_service_info(_service, _instance, ep->is_reliable()); + } + } + { + std::lock_guard<std::mutex> its_lock(callback_counts_mutex_); + if (is_last_stop_callback(its_callback_id)) { + erase_offer_command(_service, _instance); + } + } + }; + + // determine callback count + for (const auto& ep : {its_reliable_endpoint, its_unreliable_endpoint}) { + if (ep) { + std::lock_guard<std::mutex> its_lock(callback_counts_mutex_); + auto found_id = callback_counts_.find(its_callback_id); + if (found_id != callback_counts_.end()) { + found_id->second++; + } else { + callback_counts_[its_callback_id] = 1; + } + } } - if (its_reliable_endpoint) { - cleanup_server_endpoint(_service, its_reliable_endpoint); - // Clear service info and service group - clear_service_info(_service, _instance, true); + for (const auto& ep : {its_reliable_endpoint, its_unreliable_endpoint}) { + if (ep) { + ep->prepare_stop(callback, _service); + } + } + + if (!its_reliable_endpoint && !its_unreliable_endpoint) { + { + std::lock_guard<std::mutex> its_lock(callback_counts_mutex_); + callback_counts_.erase(its_callback_id); + } + erase_offer_command(_service, _instance); } + } else { + erase_offer_command(_service, _instance); } } bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, - instance_t _instance, bool _reliable, client_t _bound_client, bool _is_valid_crc, bool _is_from_remote) { + instance_t _instance, bool _reliable, client_t _bound_client, credentials_t _credentials, + uint8_t _status_check, bool _is_from_remote) { bool is_delivered(false); + std::uint32_t its_sender_uid = std::get<0>(_credentials); + std::uint32_t its_sender_gid = std::get<1>(_credentials); - auto a_deserializer = get_deserializer(); - a_deserializer->set_data(_data, _size); - std::shared_ptr<message> its_message(a_deserializer->deserialize_message()); - a_deserializer->reset(); - put_deserializer(a_deserializer); + auto its_deserializer = get_deserializer(); + its_deserializer->set_data(_data, _size); + std::shared_ptr<message_impl> its_message(its_deserializer->deserialize_message()); + its_deserializer->reset(); + put_deserializer(its_deserializer); if (its_message) { its_message->set_instance(_instance); its_message->set_reliable(_reliable); - its_message->set_is_valid_crc(_is_valid_crc); + its_message->set_check_result(_status_check); + its_message->set_uid(std::get<0>(_credentials)); + its_message->set_gid(std::get<1>(_credentials)); if (!_is_from_remote) { if (utility::is_notification(its_message->get_message_type())) { @@ -1698,7 +1719,8 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, << " ~> Skip message!"; return false; } else { - if (!configuration_->is_client_allowed(get_client(), its_message->get_service(), + if (!security::get()->is_client_allowed(own_uid_, own_gid_, + 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: " @@ -1711,7 +1733,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, } } } else if (utility::is_request(its_message->get_message_type())) { - if (configuration_->is_security_enabled() + if (security::get()->is_enabled() && its_message->get_client() != _bound_client) { VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client() << " : routing_manager_impl::deliver_message:" @@ -1720,12 +1742,13 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, << 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!"; + << " ~> 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())) { + if (!security::get()->is_client_allowed(its_sender_uid, its_sender_gid, + 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 " @@ -1746,8 +1769,9 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, << " ~> Skip message!"; return false; } else { - if (!configuration_->is_client_allowed(get_client(), its_message->get_service(), - its_message->get_instance(), its_message->get_method())) { + if (!security::get()->is_client_allowed(own_uid_, own_gid_, + 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 " @@ -1760,7 +1784,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, } } } else { - if (!configuration_->is_remote_client_allowed()) { + if (!security::get()->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() @@ -1773,7 +1797,8 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, << " ~> 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(), + if (!security::get()->is_client_allowed(own_uid_, own_gid_, + 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: " @@ -1800,11 +1825,14 @@ bool routing_manager_impl::deliver_notification( service_t _service, instance_t _instance, const byte_t *_data, length_t _length, 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]); + credentials_t _credentials, + uint8_t _status_check, bool _is_from_remote) { + event_t its_event_id = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); + client_t its_client_id = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]); - std::shared_ptr<event> its_event = find_event(_service, _instance, its_method); + std::shared_ptr<event> its_event = find_event(_service, _instance, its_event_id); if (its_event) { if (!its_event->is_provided()) { if (its_event->get_subscribers().size() == 0) { @@ -1843,17 +1871,46 @@ 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, _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) { - send_local(its_local_target, VSOMEIP_ROUTING_CLIENT, - _data, _length, _instance, true, _reliable, VSOMEIP_SEND, _is_valid_crc); + if (its_event->get_type() != event_type_e::ET_SELECTIVE_EVENT) { + for (const auto its_local_client : its_event->get_subscribers()) { + if (its_local_client == host_->get_client()) { + deliver_message(_data, _length, _instance, _reliable, + _bound_client, _credentials, _status_check, _is_from_remote); + } else { + std::shared_ptr<endpoint> its_local_target = find_local(its_local_client); + if (its_local_target) { + send_local(its_local_target, VSOMEIP_ROUTING_CLIENT, + _data, _length, _instance, _reliable, VSOMEIP_SEND, _status_check); + } + } + } + } else { + // TODO: Check whether it makes more sense to set the client id + // for internal selective events. This would create some extra + // effort but we could avoid this hack. + if (its_client_id == VSOMEIP_ROUTING_CLIENT) + its_client_id = get_client(); + + auto its_subscribers = its_event->get_subscribers(); + if (its_subscribers.find(its_client_id) != its_subscribers.end()) { + if (its_client_id == host_->get_client()) { + deliver_message(_data, _length, _instance, _reliable, + _bound_client, _credentials, _status_check, _is_from_remote); + } else { + std::shared_ptr<endpoint> its_local_target = find_local(its_client_id); + if (its_local_target) { + send_local(its_local_target, VSOMEIP_ROUTING_CLIENT, + _data, _length, _instance, _reliable, VSOMEIP_SEND, _status_check); + } } } } + } else { + VSOMEIP_WARNING << __func__ << ": Event [" + << 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') << its_event_id << "]" + << " is not registered. The message is dropped."; } return true; @@ -1865,34 +1922,40 @@ std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup( return routing_manager_base::find_eventgroup(_service, _instance, _eventgroup); } -const std::shared_ptr<configuration> routing_manager_impl::get_configuration() const { - return (host_->get_configuration()); -} - std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoint( const std::string &_address, uint16_t _port, bool _reliable) { - std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint(_port, - _reliable); + std::shared_ptr<endpoint> its_service_endpoint = + ep_mgr_impl_->find_server_endpoint(_port, _reliable); if (!its_service_endpoint) { try { - its_service_endpoint = create_server_endpoint(_port, _reliable, - true); + its_service_endpoint = + ep_mgr_impl_->create_server_endpoint(_port, + _reliable, true); if (its_service_endpoint) { - sd_info_ = std::make_shared<serviceinfo>(ANY_MAJOR, ANY_MINOR, - DEFAULT_TTL, false); // false, because we do _not_ want to announce it... + sd_info_ = std::make_shared<serviceinfo>( + VSOMEIP_SD_SERVICE, VSOMEIP_SD_INSTANCE, + ANY_MAJOR, ANY_MINOR, DEFAULT_TTL, + false); // false, because we do _not_ want to announce it... sd_info_->set_endpoint(its_service_endpoint, _reliable); its_service_endpoint->add_default_target(VSOMEIP_SD_SERVICE, _address, _port); - its_service_endpoint->join(_address); + if (!_reliable) { +#if defined(_WIN32) || defined(ANDROID) + dynamic_cast<udp_server_endpoint_impl*>( + its_service_endpoint.get())->join(_address); +#else + reinterpret_cast<udp_server_endpoint_impl*>( + its_service_endpoint.get())->join(_address); +#endif + } } else { VSOMEIP_ERROR<< "Service Discovery endpoint could not be created. " "Please check your network configuration."; } } catch (const std::exception &e) { - host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); - VSOMEIP_ERROR << "Service Discovery endpoint could not be created: " - << e.what(); + VSOMEIP_ERROR << "Server endpoint creation failed: Service " + "Discovery endpoint could not be created: " << e.what(); } } return its_service_endpoint; @@ -1900,8 +1963,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoin services_t routing_manager_impl::get_offered_services() const { services_t its_services; - for (auto s : get_services()) { - for (auto i : s.second) { + for (const auto& s : get_services()) { + for (const auto& i : s.second) { if (i.second->is_local()) { its_services[s.first][i.first] = i.second; } @@ -1926,7 +1989,7 @@ routing_manager_impl::get_offered_service_instances(service_t _service) const { const services_t its_services(get_services()); const auto found_service = its_services.find(_service); if (found_service != its_services.end()) { - for (const auto i : found_service->second) { + for (const auto& i : found_service->second) { if (i.second->is_local()) { its_instances[i.first] = i.second; } @@ -1935,25 +1998,6 @@ routing_manager_impl::get_offered_service_instances(service_t _service) const { return its_instances; } -std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client( - service_t _service, instance_t _instance, bool _reliable, client_t _client) { - std::shared_ptr<endpoint> its_endpoint; - bool start_endpoint(false); - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - its_endpoint = find_remote_client(_service, _instance, _reliable, _client); - if (!its_endpoint) { - its_endpoint = create_remote_client(_service, _instance, _reliable, _client); - start_endpoint = true; - } - } - if (start_endpoint && its_endpoint - && configuration_->is_someip(_service, _instance)) { - its_endpoint->start(); - } - return its_endpoint; -} - /////////////////////////////////////////////////////////////////////////////// // PRIVATE /////////////////////////////////////////////////////////////////////////////// @@ -1969,39 +2013,29 @@ void routing_manager_impl::init_service_info( return; } if (configuration_) { - std::shared_ptr<endpoint> its_reliable_endpoint; - std::shared_ptr<endpoint> its_unreliable_endpoint; - - uint16_t its_reliable_port = configuration_->get_reliable_port(_service, - _instance); - uint16_t its_unreliable_port = configuration_->get_unreliable_port( - _service, _instance); - - bool is_someip = configuration_->is_someip(_service, _instance); - // Create server endpoints for local services only if (_is_local_service) { + const bool is_someip = configuration_->is_someip(_service, _instance); + uint16_t its_reliable_port = configuration_->get_reliable_port( + _service, _instance); if (ILLEGAL_PORT != its_reliable_port) { - its_reliable_endpoint = find_or_create_server_endpoint( - its_reliable_port, true, is_someip); + std::shared_ptr<endpoint> its_reliable_endpoint = + ep_mgr_impl_->find_or_create_server_endpoint( + its_reliable_port, true, is_someip, _service, + _instance); if (its_reliable_endpoint) { its_info->set_endpoint(its_reliable_endpoint, true); - its_reliable_endpoint->increment_use_count(); - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - service_instances_[_service][its_reliable_endpoint.get()] = - _instance; } } - + uint16_t its_unreliable_port = configuration_->get_unreliable_port( + _service, _instance); if (ILLEGAL_PORT != its_unreliable_port) { - its_unreliable_endpoint = find_or_create_server_endpoint( - its_unreliable_port, false, is_someip); + std::shared_ptr<endpoint> its_unreliable_endpoint = + ep_mgr_impl_->find_or_create_server_endpoint( + its_unreliable_port, false, is_someip, _service, + _instance); if (its_unreliable_endpoint) { its_info->set_endpoint(its_unreliable_endpoint, false); - its_unreliable_endpoint->increment_use_count(); - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - service_instances_[_service][its_unreliable_endpoint.get()] = - _instance; } } @@ -2013,143 +2047,8 @@ void routing_manager_impl::init_service_info( } } } else { - host_->on_error(error_code_e::CONFIGURATION_MISSING); - } -} - -std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint( - const boost::asio::ip::address &_address, - uint16_t _local_port, uint16_t _remote_port, - bool _reliable, client_t _client) { - (void)_client; - - std::shared_ptr<endpoint> its_endpoint; - try { - if (_reliable) { - its_endpoint = std::make_shared<tcp_client_endpoint_impl>( - shared_from_this(), - boost::asio::ip::tcp::endpoint( - (_address.is_v4() ? - boost::asio::ip::tcp::v4() : - boost::asio::ip::tcp::v6()), - _local_port), - boost::asio::ip::tcp::endpoint(_address, _remote_port), - io_, - 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), - configuration_->get_max_tcp_restart_aborts(), - configuration_->get_max_tcp_connect_time()); - - if (configuration_->has_enabled_magic_cookies(_address.to_string(), - _remote_port)) { - its_endpoint->enable_magic_cookies(); - } - } else { - its_endpoint = std::make_shared<udp_client_endpoint_impl>( - shared_from_this(), - boost::asio::ip::udp::endpoint( - (_address.is_v4() ? - boost::asio::ip::udp::v4() : - boost::asio::ip::udp::v6()), - _local_port), - boost::asio::ip::udp::endpoint(_address, _remote_port), - io_, configuration_->get_endpoint_queue_limit( - _address.to_string(), _remote_port), - configuration_->get_udp_receive_buffer_size()); - } - } catch (...) { - host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED); + VSOMEIP_ERROR << "Missing vsomeip configuration."; } - - return (its_endpoint); -} - -std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( - uint16_t _port, bool _reliable, bool _start) { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - std::shared_ptr<endpoint> its_endpoint; - try { - boost::asio::ip::address its_unicast = configuration_->get_unicast_address(); - if (_start) { - if (_reliable) { - its_endpoint = std::make_shared<tcp_server_endpoint_impl>( - shared_from_this(), - boost::asio::ip::tcp::endpoint(its_unicast, _port), io_, - 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)); - if (configuration_->has_enabled_magic_cookies( - its_unicast.to_string(), _port) || - configuration_->has_enabled_magic_cookies( - "local", _port)) { - its_endpoint->enable_magic_cookies(); - } - } else { - configuration::endpoint_queue_limit_t its_limit = - configuration_->get_endpoint_queue_limit( - its_unicast.to_string(), _port); -#ifndef _WIN32 - if (its_unicast.is_v4()) { - its_unicast = boost::asio::ip::address_v4::any(); - } else if (its_unicast.is_v6()) { - its_unicast = boost::asio::ip::address_v6::any(); - } -#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, - configuration_->get_udp_receive_buffer_size()); - } - - } else { - its_endpoint = std::make_shared<virtual_server_endpoint_impl>( - its_unicast.to_string(), _port, _reliable); - } - - if (its_endpoint) { - server_endpoints_[_port][_reliable] = its_endpoint; - its_endpoint->start(); - } - } catch (const std::exception &e) { - host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); - VSOMEIP_ERROR << e.what(); - } - - return (its_endpoint); -} - -std::shared_ptr<endpoint> routing_manager_impl::find_server_endpoint( - uint16_t _port, bool _reliable) const { - std::shared_ptr<endpoint> its_endpoint; - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - auto found_port = server_endpoints_.find(_port); - if (found_port != server_endpoints_.end()) { - auto found_endpoint = found_port->second.find(_reliable); - if (found_endpoint != found_port->second.end()) { - its_endpoint = found_endpoint->second; - } - } - - return (its_endpoint); -} - -std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint( - uint16_t _port, bool _reliable, bool _start) { - std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port, - _reliable); - if (!its_endpoint) { - its_endpoint = create_server_endpoint(_port, _reliable, _start); - } - return (its_endpoint); } void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) { @@ -2167,8 +2066,8 @@ void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) { std::lock_guard<std::mutex> its_lock(requested_services_mutex_); auto its_client = requested_services_.find(_client); if (its_client != requested_services_.end()) { - for (auto its_service : its_client->second) { - for (auto its_instance : its_service.second) { + for (const auto& its_service : its_client->second) { + for (const auto& its_instance : its_service.second) { services_to_release_.push_front( { its_service.first, its_instance.first }); } @@ -2180,162 +2079,6 @@ void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) { } } -instance_t routing_manager_impl::find_instance(service_t _service, - endpoint * _endpoint) { - instance_t its_instance(0xFFFF); - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - auto found_service = service_instances_.find(_service); - if (found_service != service_instances_.end()) { - auto found_endpoint = found_service->second.find(_endpoint); - if (found_endpoint != found_service->second.end()) { - its_instance = found_endpoint->second; - } - } - } - return (its_instance); -} - -std::shared_ptr<endpoint> routing_manager_impl::create_remote_client( - service_t _service, instance_t _instance, bool _reliable, client_t _client) { - std::shared_ptr<endpoint> its_endpoint; - std::shared_ptr<endpoint_definition> its_endpoint_def; - uint16_t its_local_port; - uint16_t its_remote_port = ILLEGAL_PORT; - - auto found_service = remote_service_info_.find(_service); - if (found_service != remote_service_info_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_reliability = found_instance->second.find(_reliable); - if (found_reliability != found_instance->second.end()) { - its_endpoint_def = found_reliability->second; - its_remote_port = its_endpoint_def->get_port(); - } - } - } - - if( its_remote_port != ILLEGAL_PORT) { - // if client port range for remote service port range is configured - // and remote port is in range, determine unused client port - std::unique_lock<std::mutex> its_lock(used_client_ports_mutex_); - if (configuration_->get_client_port(_service, _instance, its_remote_port, _reliable, - used_client_ports_, its_local_port)) { - if(its_endpoint_def) { - its_endpoint = create_client_endpoint( - its_endpoint_def->get_address(), - its_local_port, - its_endpoint_def->get_port(), - _reliable, _client - ); - } - - if (its_endpoint) { - used_client_ports_[_reliable].insert(its_local_port); - its_lock.unlock(); - service_instances_[_service][its_endpoint.get()] = _instance; - remote_services_[_service][_instance][_client][_reliable] = its_endpoint; - if (_client == VSOMEIP_ROUTING_CLIENT) { - client_endpoints_by_ip_[its_endpoint_def->get_address()] - [its_endpoint_def->get_port()] - [_reliable] = its_endpoint; - // Set the basic route to the service in the service info - auto found_service_info = find_service(_service, _instance); - if (found_service_info) { - found_service_info->set_endpoint(its_endpoint, _reliable); - } - } - } - } - } - return its_endpoint; -} - - -std::shared_ptr<endpoint> routing_manager_impl::find_remote_client( - service_t _service, instance_t _instance, bool _reliable, client_t _client) { - std::shared_ptr<endpoint> its_endpoint; - auto found_service = remote_services_.find(_service); - if (found_service != remote_services_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_client = found_instance->second.find(_client); - if (found_client != found_instance->second.end()) { - auto found_reliability = found_client->second.find(_reliable); - if (found_reliability != found_client->second.end()) { - its_endpoint = found_reliability->second; - } - } - } - } - if (its_endpoint || _client != VSOMEIP_ROUTING_CLIENT) { - return its_endpoint; - } - - // If another service is hosted on the same server_endpoint - // reuse the existing client_endpoint. - auto found_service_info = remote_service_info_.find(_service); - if(found_service_info != remote_service_info_.end()) { - auto found_instance = found_service_info->second.find(_instance); - if(found_instance != found_service_info->second.end()) { - auto found_reliable = found_instance->second.find(_reliable); - if(found_reliable != found_instance->second.end()) { - std::shared_ptr<endpoint_definition> its_ep_def = - found_reliable->second; - auto found_address = client_endpoints_by_ip_.find( - its_ep_def->get_address()); - if(found_address != client_endpoints_by_ip_.end()) { - auto found_port = found_address->second.find( - its_ep_def->get_remote_port()); - if(found_port != found_address->second.end()) { - auto found_reliable2 = found_port->second.find( - _reliable); - if(found_reliable2 != found_port->second.end()) { - its_endpoint = found_reliable2->second; - // store the endpoint under this service/instance id - // as well - needed for later cleanup - remote_services_[_service][_instance][_client][_reliable] = - its_endpoint; - service_instances_[_service][its_endpoint.get()] = _instance; - // add endpoint to serviceinfo object - auto found_service_info = find_service(_service,_instance); - if (found_service_info) { - found_service_info->set_endpoint(its_endpoint, _reliable); - } - } - } - } - } - } - } - return its_endpoint; -} - -client_t routing_manager_impl::find_client( - service_t _service, instance_t _instance, - const std::shared_ptr<eventgroupinfo> &_eventgroup, - const std::shared_ptr<endpoint_definition> &_target) const { - client_t its_client = VSOMEIP_ROUTING_CLIENT; - if (!_eventgroup->is_multicast()) { - if (!_target->is_reliable()) { - uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance); - auto endpoint = find_server_endpoint(unreliable_port, false); - if (endpoint) { - its_client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)-> - get_client(_target); - } - } else { - uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance); - auto endpoint = find_server_endpoint(reliable_port, true); - if (endpoint) { - its_client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)-> - get_client(_target); - } - } - } - return its_client; -} - bool routing_manager_impl::is_field(service_t _service, instance_t _instance, event_t _event) const { std::lock_guard<std::mutex> its_lock(events_mutex_); @@ -2398,60 +2141,12 @@ void routing_manager_impl::add_routing_info( // Check whether remote services are unchanged bool is_reliable_known(false); bool is_unreliable_known(false); - - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - auto found_service = remote_service_info_.find(_service); - if (found_service != remote_service_info_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - std::shared_ptr<endpoint_definition> its_definition; - if (_reliable_port != ILLEGAL_PORT) { - auto found_reliable = found_instance->second.find(true); - if (found_reliable != found_instance->second.end()) { - its_definition = found_reliable->second; - if (its_definition->get_address() == _reliable_address - && its_definition->get_port() == _reliable_port) { - is_reliable_known = true; - } else { - VSOMEIP_WARNING << "Reliable service endpoint has changed: [" - << std::hex << std::setfill('0') << std::setw(4) << _service << "." - << std::hex << std::setfill('0') << std::setw(4) << _instance << "." - << std::dec << static_cast<std::uint32_t>(_major) << "." - << std::dec << _minor << "] old: " - << its_definition->get_address().to_string() << ":" - << its_definition->get_port() << " new: " - << _reliable_address.to_string() << ":" - << _reliable_port; - } - } - } - if (_unreliable_port != ILLEGAL_PORT) { - auto found_unreliable = found_instance->second.find(false); - if (found_unreliable != found_instance->second.end()) { - its_definition = found_unreliable->second; - if (its_definition->get_address() == _unreliable_address - && its_definition->get_port() == _unreliable_port) { - is_unreliable_known = true; - } else { - VSOMEIP_WARNING << "Unreliable service endpoint has changed: [" - << std::hex << std::setfill('0') << std::setw(4) << _service << "." - << std::hex << std::setfill('0') << std::setw(4) << _instance << "." - << std::dec << static_cast<std::uint32_t>(_major) << "." - << std::dec << _minor << "] old: " - << its_definition->get_address().to_string() << ":" - << its_definition->get_port() << " new: " - << _unreliable_address.to_string() << ":" - << _unreliable_port; - } - } - } - } - } - } + ep_mgr_impl_->is_remote_service_known(_service, _instance, _major, + _minor, _reliable_address, _reliable_port, &is_reliable_known, + _unreliable_address, _unreliable_port, &is_unreliable_known); bool udp_inserted(false); - + bool tcp_inserted(false); // Add endpoint(s) if necessary if (_reliable_port != ILLEGAL_PORT && !is_reliable_known) { std::shared_ptr<endpoint_definition> endpoint_def_tcp @@ -2459,15 +2154,14 @@ void routing_manager_impl::add_routing_info( if (_unreliable_port != ILLEGAL_PORT && !is_unreliable_known) { std::shared_ptr<endpoint_definition> endpoint_def_udp = endpoint_definition::get(_unreliable_address, _unreliable_port, false, _service, _instance); - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - remote_service_info_[_service][_instance][false] = endpoint_def_udp; - remote_service_info_[_service][_instance][true] = endpoint_def_tcp; - } + ep_mgr_impl_->add_remote_service_info(_service, _instance, + endpoint_def_tcp, endpoint_def_udp); udp_inserted = true; + tcp_inserted = true; } else { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - remote_service_info_[_service][_instance][true] = endpoint_def_tcp; + ep_mgr_impl_->add_remote_service_info(_service, _instance, + endpoint_def_tcp); + tcp_inserted = true; } // check if service was requested and establish TCP connection if necessary @@ -2489,11 +2183,13 @@ void routing_manager_impl::add_routing_info( // SWS_SD_00376 establish TCP connection to service // service is marked as available later in on_connect() if(!connected) { - find_or_create_remote_client(_service, _instance, - true, VSOMEIP_ROUTING_CLIENT); if (udp_inserted) { - find_or_create_remote_client(_service, _instance, - false, VSOMEIP_ROUTING_CLIENT); + // atomically create reliable and unreliable endpoint + ep_mgr_impl_->find_or_create_remote_client( + _service, _instance, VSOMEIP_ROUTING_CLIENT); + } else { + ep_mgr_impl_->find_or_create_remote_client( + _service, _instance, true, VSOMEIP_ROUTING_CLIENT); } connected = true; } @@ -2505,10 +2201,6 @@ void routing_manager_impl::add_routing_info( } } } - auto specific_endpoint_clients = get_specific_endpoint_clients(_service, _instance); - for (const client_t& c : specific_endpoint_clients) { - find_or_create_remote_client(_service, _instance, true, c); - } } else if (_reliable_port != ILLEGAL_PORT && is_reliable_known) { std::lock_guard<std::mutex> its_lock(requested_services_mutex_); for(const auto &client_id : requested_services_) { @@ -2523,7 +2215,9 @@ void routing_manager_impl::add_routing_info( && (major_minor_pair.second <= _minor || _minor == DEFAULT_MINOR || major_minor_pair.second == ANY_MINOR)) { - if (!stub_->contained_in_routing_info( + std::shared_ptr<endpoint> ep = its_info->get_endpoint(true); + if (ep && ep->is_established() && + !stub_->contained_in_routing_info( VSOMEIP_ROUTING_CLIENT, _service, _instance, its_info->get_major(), its_info->get_minor())) { @@ -2534,12 +2228,8 @@ void routing_manager_impl::add_routing_info( its_info->get_major(), its_info->get_minor()); if (discovery_) { - std::shared_ptr<endpoint> ep = its_info->get_endpoint(true); - if (ep && ep->is_established()) { - discovery_->on_endpoint_connected( - _service, _instance, - ep); - } + discovery_->on_endpoint_connected( + _service, _instance, ep); } } break; @@ -2554,10 +2244,7 @@ void routing_manager_impl::add_routing_info( if (!udp_inserted) { std::shared_ptr<endpoint_definition> endpoint_def = endpoint_definition::get(_unreliable_address, _unreliable_port, false, _service, _instance); - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - remote_service_info_[_service][_instance][false] = endpoint_def; - } + ep_mgr_impl_->add_remote_service_info(_service, _instance, endpoint_def); // check if service was requested and increase requester count if necessary { bool connected(false); @@ -2577,7 +2264,7 @@ void routing_manager_impl::add_routing_info( || major_minor_pair.second == ANY_MINOR)) { if(!connected) { - find_or_create_remote_client(_service, _instance, + ep_mgr_impl_->find_or_create_remote_client(_service, _instance, false, VSOMEIP_ROUTING_CLIENT); connected = true; } @@ -2590,7 +2277,8 @@ void routing_manager_impl::add_routing_info( } } } - if (!is_reliable_known) { + if (!is_reliable_known && !tcp_inserted) { + // UDP only service can be marked as available instantly on_availability(_service, _instance, true, _major, _minor); stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, _major, _minor); } @@ -2649,26 +2337,81 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst if(!its_info) return; - 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()); + 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 - clear_targets_and_pending_sub_from_eventgroups(_service, _instance); - clear_identified_clients( _service, _instance); - clear_identifying_clients( _service, _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 (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); + } + } + its_events.push_back(its_event); + remove_pending_subscription(_service, _instance, + its_eventgroup.first, its_event->get_event()); + } + + } + } + } + } + for (const auto& e : its_events) { + e->unset_payload(true); + } - clear_remote_subscriber(_service, _instance); + { + std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); + std::set<std::tuple< + service_t, instance_t, eventgroup_t, client_t> > its_invalid; + + for (const auto its_state : remote_subscription_state_) { + if (std::get<0>(its_state.first) == _service + && std::get<1>(its_state.first) == _instance) { + its_invalid.insert(its_state.first); + } + } + + for (const auto its_key : its_invalid) + remote_subscription_state_.erase(its_key); + } + + { + 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); + } + } + } if (_has_reliable) { - clear_client_endpoints(_service, _instance, true); - clear_remote_service_info(_service, _instance, true); + ep_mgr_impl_->clear_client_endpoints(_service, _instance, true); + ep_mgr_impl_->clear_remote_service_info(_service, _instance, true); } if (_has_unreliable) { - clear_client_endpoints(_service, _instance, false); - clear_remote_service_info(_service, _instance, false); + ep_mgr_impl_->clear_client_endpoints(_service, _instance, false); + ep_mgr_impl_->clear_remote_service_info(_service, _instance, false); } - clear_multicast_endpoints(_service, _instance); + ep_mgr_impl_->clear_multicast_endpoints(_service, _instance); if (_has_reliable) clear_service_info(_service, _instance, true); @@ -2677,8 +2420,8 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst // For expired services using only unreliable endpoints that have never been created before if (!_has_reliable && !_has_unreliable) { - clear_remote_service_info(_service, _instance, true); - clear_remote_service_info(_service, _instance, false); + ep_mgr_impl_->clear_remote_service_info(_service, _instance, true); + ep_mgr_impl_->clear_remote_service_info(_service, _instance, false); clear_service_info(_service, _instance, true); clear_service_info(_service, _instance, false); } @@ -2764,83 +2507,57 @@ void routing_manager_impl::expire_services(const boost::asio::ip::address &_addr } } -void routing_manager_impl::expire_subscriptions(const boost::asio::ip::address &_address) { - struct subscriptions_info { - service_t service_id_; - instance_t instance_id_; - eventgroup_t eventgroup_id_; - std::shared_ptr<endpoint_definition> invalid_endpoint_; - client_t client_; - std::set<std::shared_ptr<event>> events_; - std::shared_ptr<eventgroupinfo> eventgroupinfo_; - }; - std::vector<struct subscriptions_info> subscriptions_to_expire_; +void +routing_manager_impl::expire_subscriptions( + const boost::asio::ip::address &_address) { { std::lock_guard<std::mutex> its_lock(eventgroups_mutex_); - for (auto &its_service : eventgroups_) { - for (auto &its_instance : its_service.second) { - for (auto &its_eventgroup : its_instance.second) { - std::set<std::shared_ptr<endpoint_definition>> its_invalid_endpoints; - for (auto &its_target : its_eventgroup.second->get_targets()) { - if (its_target.endpoint_->get_address() == _address) - its_invalid_endpoints.insert(its_target.endpoint_); - } + for (const auto &its_service : eventgroups_) { + for (const auto &its_instance : its_service.second) { + for (const auto &its_eventgroup : its_instance.second) { + const auto its_info = its_eventgroup.second; + for (auto its_subscription + : its_info->get_remote_subscriptions()) { + // Note: get_remote_subscription delivers a copied + // set of subscriptions. Thus, its is possible to + // to remove them within the loop. + const auto its_reliable = its_subscription->get_reliable(); + const auto its_unreliable = its_subscription->get_unreliable(); + if ((its_reliable && its_reliable->get_address() == _address) + || (its_unreliable && its_unreliable->get_address() == _address)) { + + // TODO: Check whether subscriptions to different hosts are valid. + // IF yes, we probably need to simply reset the corresponding + // endpoint instead of removing the subscription... + + if (its_reliable) { + VSOMEIP_ERROR << __func__ + << ": removing subscription to " + << std::hex << its_info->get_service() << "." + << std::hex << its_info->get_instance() << "." + << std::hex << its_info->get_eventgroup() + << " from target " + << its_reliable->get_address().to_string() << ":" + << std::dec << its_reliable->get_port(); + } + if (its_unreliable) { + VSOMEIP_ERROR << __func__ + << ": removing subscription to " + << std::hex << its_info->get_service() << "." + << std::hex << its_info->get_instance() << "." + << std::hex << its_info->get_eventgroup() + << " from target " + << its_unreliable->get_address().to_string() << ":" + << std::dec << its_unreliable->get_port(); + } - for (auto &its_endpoint : its_invalid_endpoints) { - its_eventgroup.second->remove_target(its_endpoint); - client_t its_client = find_client(its_service.first, - its_instance.first, its_eventgroup.second, - its_endpoint); - clear_remote_subscriber(its_service.first, - its_instance.first, its_client, its_endpoint); - - std::set<std::shared_ptr<event> > its_events; - if (its_eventgroup.second->get_targets().size() == 0) { - its_events = its_eventgroup.second->get_events(); + on_remote_unsubscribe(its_subscription); } - subscriptions_to_expire_.push_back({its_service.first, - its_instance.first, - its_eventgroup.first, - its_endpoint, - its_client, - its_events, - its_eventgroup.second}); - } - if(its_eventgroup.second->is_multicast() && its_invalid_endpoints.size() && - 0 == its_eventgroup.second->get_unreliable_target_count() ) { - //clear multicast targets if no subscriber is left for multicast eventgroup - its_eventgroup.second->clear_multicast_targets(); } } } } } - - for (const auto &s : subscriptions_to_expire_) { - if (s.invalid_endpoint_) { - for (const auto e: s.events_) { - if (e->is_shadow()) { - e->unset_payload(); - } - } - const client_t its_hosting_client = find_local_client( - s.service_id_, s.instance_id_); - if (its_hosting_client != VSOMEIP_ROUTING_CLIENT) { - const pending_subscription_t its_pending_unsubscription( - std::shared_ptr<sd_message_identifier_t>(), - s.invalid_endpoint_, s.invalid_endpoint_, - 0, s.client_); - pending_subscription_id_t its_pending_unsubscription_id = - s.eventgroupinfo_->add_pending_subscription( - its_pending_unsubscription); - if (its_pending_unsubscription_id != DEFAULT_SUBSCRIPTION) { - send_unsubscription(its_hosting_client, s.client_, - s.service_id_, s.instance_id_, s.eventgroup_id_, - its_pending_unsubscription_id); - } - } - } - } } void routing_manager_impl::init_routing_info() { @@ -2863,200 +2580,194 @@ void routing_manager_impl::init_routing_info() { its_address, its_unreliable_port); if(its_reliable_port != ILLEGAL_PORT) { - find_or_create_remote_client(i.first, i.second, true, VSOMEIP_ROUTING_CLIENT); + ep_mgr_impl_->find_or_create_remote_client( + i.first, i.second, true, VSOMEIP_ROUTING_CLIENT); } if(its_unreliable_port != ILLEGAL_PORT) { - find_or_create_remote_client(i.first, i.second, false, VSOMEIP_ROUTING_CLIENT); + ep_mgr_impl_->find_or_create_remote_client( + i.first, i.second, false, VSOMEIP_ROUTING_CLIENT); } } } } -void routing_manager_impl::on_remote_subscription( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - const std::shared_ptr<endpoint_definition> &_subscriber, - const std::shared_ptr<endpoint_definition> &_target, ttl_t _ttl, - const std::shared_ptr<sd_message_identifier_t> &_sd_message_id, - const std::function<void(remote_subscription_state_e, client_t)>& _callback) { - std::shared_ptr<eventgroupinfo> its_eventgroup - = find_eventgroup(_service, _instance, _eventgroup); - client_t its_subscribing_client(ILLEGAL_CLIENT); - if (!its_eventgroup) { - VSOMEIP_ERROR << "REMOTE SUBSCRIBE: attempt to subscribe to unknown eventgroup [" - << 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 << "]" - << " from " << _subscriber->get_address().to_string() - << ":" << std::dec << _subscriber->get_port() - << (_subscriber->is_reliable() ? " reliable" : " unreliable"); - _callback(remote_subscription_state_e::SUBSCRIPTION_ERROR, its_subscribing_client); +void routing_manager_impl::on_remote_subscribe( + std::shared_ptr<remote_subscription> &_subscription, + const remote_subscription_callback_t &_callback) { + auto its_eventgroupinfo = _subscription->get_eventgroupinfo(); + if (!its_eventgroupinfo) { + VSOMEIP_ERROR << __func__ << " eventgroupinfo is invalid"; return; } - // find out client id for selective subscriber - if (!_subscriber->is_reliable()) { - uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance); - _subscriber->set_remote_port(unreliable_port); - if (!its_eventgroup->is_multicast()) { - auto endpoint = find_server_endpoint(unreliable_port, false); - if (endpoint) { - its_subscribing_client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)-> - get_client(_subscriber); - } - } - } else { - uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance); - _subscriber->set_remote_port(reliable_port); - auto endpoint = find_server_endpoint(reliable_port, true); - if (endpoint) { - its_subscribing_client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)-> - get_client(_subscriber); - } - } - std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock()); - const std::chrono::steady_clock::time_point its_expiration = - std::chrono::steady_clock::now() + std::chrono::seconds(_ttl); - if (its_eventgroup->update_target(_subscriber, its_expiration)) { - _callback(remote_subscription_state_e::SUBSCRIPTION_ACKED,its_subscribing_client); - return; - } else { - const pending_subscription_id_t its_subscription_id = - its_eventgroup->add_pending_subscription( - pending_subscription_t(_sd_message_id, _subscriber, - _target, _ttl, its_subscribing_client)); - if (its_subscription_id != DEFAULT_SUBSCRIPTION) { - // only sent subscription to rm_proxy / hosting application if there's - // no subscription for this eventgroup from the same remote subscriber - // already pending - const client_t its_offering_client = find_local_client(_service, _instance); - send_subscription(its_offering_client, its_subscribing_client, - _service, _instance, _eventgroup, - its_eventgroup->get_major(), its_subscription_id); - } else { - VSOMEIP_WARNING << __func__ << " a remote subscription is already pending [" - << 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 << "]" - << " from " << _subscriber->get_address().to_string() - << ":" << std::dec << _subscriber->get_port() - << (_subscriber->is_reliable() ? " reliable" : " unreliable"); - } - _callback(remote_subscription_state_e::SUBSCRIPTION_PENDING, its_subscribing_client); + const ttl_t its_ttl = _subscription->get_ttl(); + + const auto its_service = its_eventgroupinfo->get_service(); + const auto its_instance = its_eventgroupinfo->get_instance(); + const auto its_eventgroup = its_eventgroupinfo->get_eventgroup(); + const auto its_major = its_eventgroupinfo->get_major(); + + // Get remote port(s) + auto its_reliable = _subscription->get_reliable(); + if (its_reliable) { + uint16_t its_port + = configuration_->get_reliable_port(its_service, its_instance); + its_reliable->set_remote_port(its_port); + } + + auto its_unreliable = _subscription->get_unreliable(); + if (its_unreliable) { + uint16_t its_port + = configuration_->get_unreliable_port(its_service, its_instance); + its_unreliable->set_remote_port(its_port); + } + + // Calculate expiration time + const std::chrono::steady_clock::time_point its_expiration + = std::chrono::steady_clock::now() + std::chrono::seconds(its_ttl); + + // Try to update the subscription. This will fail, if the subscription does + // not exist or is still (partly) pending. + remote_subscription_id_t its_id; + std::set<client_t> its_added; + auto its_result = its_eventgroupinfo->update_remote_subscription( + _subscription, its_expiration, its_added, its_id, true); + if (its_result) { + if (!_subscription->is_pending()) { // resubscription without change + _callback(_subscription); + } else if (!its_added.empty()) { // new clients for a selective subscription + const client_t its_offering_client + = find_local_client(its_service, its_instance); + send_subscription(its_offering_client, + its_service, its_instance, its_eventgroup, its_major, + its_added, _subscription->get_id()); + } else { // identical subscription is not yet processed + std::stringstream its_warning; + its_warning << __func__ << " a remote subscription is already pending [" + << std::hex << std::setw(4) << std::setfill('0') << its_service << "." + << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." + << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "]" + << " from "; + if (its_reliable && its_unreliable) + its_warning << "["; + if (its_reliable) + its_warning << its_reliable->get_address().to_string() + << ":" << std::dec << its_reliable->get_port(); + if (its_reliable && its_unreliable) + its_warning << ", "; + if (its_unreliable) + its_warning << its_unreliable->get_address().to_string() + << ":" << std::dec << its_unreliable->get_port(); + if (its_reliable && its_unreliable) + its_warning << "]"; + VSOMEIP_WARNING << its_warning.str(); + } + } else { // new subscription + auto its_id + = its_eventgroupinfo->add_remote_subscription(_subscription); + + const client_t its_offering_client + = find_local_client(its_service, its_instance); + send_subscription(its_offering_client, + its_service, its_instance, its_eventgroup, its_major, + _subscription->get_clients(), its_id); + } +} + +void routing_manager_impl::on_remote_unsubscribe( + std::shared_ptr<remote_subscription> &_subscription) { + std::shared_ptr<eventgroupinfo> its_info + = _subscription->get_eventgroupinfo(); + if (!its_info) { + VSOMEIP_ERROR << __func__ + << ": Received Unsubscribe for unregistered eventgroup."; return; } - _callback(remote_subscription_state_e::SUBSCRIPTION_ERROR, its_subscribing_client); -} -void routing_manager_impl::on_unsubscribe(service_t _service, - instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<endpoint_definition> _target) { - std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service, - _instance, _eventgroup); - if (its_eventgroup) { - client_t its_client = find_client(_service, _instance, its_eventgroup, _target); - const pending_subscription_t its_pending_unsubscription( - std::shared_ptr<sd_message_identifier_t>(), _target, _target, - 0, its_client); - pending_subscription_id_t its_pending_unsubscription_id = - its_eventgroup->add_pending_subscription( - its_pending_unsubscription); - - its_eventgroup->remove_target(_target); - clear_remote_subscriber(_service, _instance, its_client, _target); - - if (its_pending_unsubscription_id != DEFAULT_SUBSCRIPTION) { - // there are no pending (un)subscriptions - const client_t its_offering_client = find_local_client(_service, _instance); - send_unsubscription(its_offering_client, its_client, _service, - _instance, _eventgroup, its_pending_unsubscription_id); - } + const auto its_service = its_info->get_service(); + const auto its_instance = its_info->get_instance(); + const auto its_eventgroup = its_info->get_eventgroup(); + const auto its_major = its_info->get_major(); - if (its_eventgroup->get_targets().size() == 0) { - std::set<std::shared_ptr<event> > its_events - = its_eventgroup->get_events(); - for (auto e : its_events) { - if (e->is_shadow()) { - e->unset_payload(); - } - } - } - VSOMEIP_INFO << "REMOTE UNSUBSCRIBE(" - << std::hex << std::setw(4) << std::setfill('0') << its_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 << "]" - << " from " << _target->get_address().to_string() - << ":" << std::dec <<_target->get_port() - << (_target->is_reliable() ? " reliable" : " unreliable"); + auto its_subscriber = _subscription->get_subscriber(); - } else { - VSOMEIP_ERROR << "REMOTE UNSUBSCRIBE: attempt to subscribe to unknown eventgroup [" - << 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 << "]" - << " from " << _target->get_address().to_string() - << ":" << std::dec <<_target->get_port() - << (_target->is_reliable() ? " reliable" : " unreliable"); + // Get remote port(s) + auto its_reliable = _subscription->get_reliable(); + if (its_reliable) { + uint16_t its_port + = configuration_->get_reliable_port(its_service, its_instance); + its_reliable->set_remote_port(its_port); } -} - -void routing_manager_impl::on_subscribe_ack(service_t _service, - instance_t _instance, const boost::asio::ip::address &_address, - uint16_t _port) { - bool multicast_known(false); - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - const auto found_service = multicast_info.find(_service); - if (found_service != multicast_info.end()) { - const auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - const auto& endpoint_def = found_instance->second; - if (endpoint_def->get_address() == _address && - endpoint_def->get_port() == _port) { - // Multicast info and endpoint already created before - // This can happen when more than one client subscribe on the same instance! - multicast_known = true; - } - } - } - if (!multicast_known) { - // Save multicast info to be able to delete the endpoint - // as soon as the instance stops offering its service - std::shared_ptr<endpoint_definition> endpoint_def = - endpoint_definition::get(_address, _port, false, _service, _instance); - multicast_info[_service][_instance] = endpoint_def; - } + auto its_unreliable = _subscription->get_unreliable(); + if (its_unreliable) { + uint16_t its_port + = configuration_->get_unreliable_port(its_service, its_instance); + its_unreliable->set_remote_port(its_port); } - const bool is_someip = configuration_->is_someip(_service, _instance); - // Create multicast endpoint & join multicase group - std::shared_ptr<endpoint> its_endpoint - = find_or_create_server_endpoint(_port, false, is_someip); - if (its_endpoint) { - if (!multicast_known) { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - service_instances_[_service][its_endpoint.get()] = _instance; - } - its_endpoint->join(_address.to_string()); - } else { - VSOMEIP_ERROR<<"Could not find/create multicast endpoint!"; + remote_subscription_id_t its_id(0); + std::set<client_t> its_removed; + auto its_result = its_info->update_remote_subscription( + _subscription, std::chrono::steady_clock::now(), + its_removed, its_id, false); + + if (its_result) { + const client_t its_offering_client + = find_local_client(its_service, its_instance); + send_unsubscription(its_offering_client, + its_service, its_instance, its_eventgroup, its_major, + its_removed, its_id); } } +void routing_manager_impl::on_subscribe_ack_with_multicast( + service_t _service, instance_t _instance, + const boost::asio::ip::address &_address, uint16_t _port) { + ep_mgr_impl_->find_or_create_multicast_endpoint(_service, + _instance, _address, _port); +} + void routing_manager_impl::on_subscribe_ack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - event_t _event, pending_subscription_id_t _subscription_id) { - client_t its_client = is_specific_endpoint_client(_client, _service, _instance); - bool specific_endpoint_client = its_client != VSOMEIP_ROUTING_CLIENT; + event_t _event, remote_subscription_id_t _id) { + std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock()); - if (_subscription_id == DEFAULT_SUBSCRIPTION) { - // ACK coming in via SD from remote or as answer to a subscription - // of the application hosting the rm_impl to a local service - auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, its_client); - std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); - auto its_state = remote_subscription_state_.find(its_tuple); + auto its_subscription = its_eventgroup->get_remote_subscription(_id); + if (its_subscription) { + its_subscription->set_client_state(_client, + remote_subscription_state_e::SUBSCRIPTION_ACKED); + + auto its_parent = its_subscription->get_parent(); + if (its_parent) { + its_parent->set_client_state(_client, + remote_subscription_state_e::SUBSCRIPTION_ACKED); + if (!its_subscription->is_pending()) { + its_eventgroup->remove_remote_subscription(_id); + } + } + + if (discovery_) { + std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_); + remote_subscribers_[_service][_instance][VSOMEIP_ROUTING_CLIENT].insert( + its_subscription->get_subscriber()); + discovery_->update_remote_subscription(its_subscription); + + VSOMEIP_INFO << "REMOTE SUBSCRIBE(" + << 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 << "]" + << " from " << its_subscription->get_subscriber()->get_address() + << ":" << std::dec << its_subscription->get_subscriber()->get_port() + << (its_subscription->get_subscriber()->is_reliable() ? " reliable" : " unreliable") + << " was accepted"; + + return; + } + } else { + const auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, _client); + const auto its_state = remote_subscription_state_.find(its_tuple); if (its_state != remote_subscription_state_.end()) { if (its_state->second == subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED) { // Already notified! @@ -3064,385 +2775,79 @@ void routing_manager_impl::on_subscribe_ack(client_t _client, } } remote_subscription_state_[its_tuple] = subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED; - } else { // ACK sent back from local client as answer to a remote subscription - const client_t its_offering_client = find_local_client(_service, _instance); - if (its_offering_client == VSOMEIP_ROUTING_CLIENT) { - // service was stopped while subscription was pending - // send subscribe_nack back instead - eventgroup_lock.unlock(); - on_subscribe_nack(_client, _service, _instance, _eventgroup, - _event, _subscription_id); - return; - } - if (discovery_) { - std::vector<pending_subscription_t> its_pending_subscriptions = - its_eventgroup->remove_pending_subscription(_subscription_id); - for (const pending_subscription_t& its_sd_message_id : its_pending_subscriptions) { - if (its_sd_message_id.ttl_ > 0) { - if (its_sd_message_id.sd_message_identifier_ - && its_sd_message_id.subscriber_ - && its_sd_message_id.target_) { - { - std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_); - remote_subscribers_[_service][_instance][_client].insert(its_sd_message_id.subscriber_); - } - const std::chrono::steady_clock::time_point its_expiration = - std::chrono::steady_clock::now() - + std::chrono::seconds( - its_sd_message_id.ttl_); - // IP address of target is a multicast address if the event is in a multicast eventgroup - if (its_eventgroup->is_multicast() - && !its_sd_message_id.subscriber_->is_reliable()) { - // Event is in multicast eventgroup and subscribe for UDP - its_eventgroup->add_target( - { its_sd_message_id.target_, its_expiration }, - { its_sd_message_id.subscriber_, its_expiration }); - } else { - // subscribe for TCP or UDP - its_eventgroup->add_target( - { its_sd_message_id.subscriber_, its_expiration }); - } - discovery_->remote_subscription_acknowledge(_service, - _instance, _eventgroup, _client, true, - its_sd_message_id.sd_message_identifier_); + } - VSOMEIP_INFO << "REMOTE SUBSCRIBE(" - << 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 << "]" - << " from " << its_sd_message_id.subscriber_->get_address().to_string() - << ":" << std::dec << its_sd_message_id.subscriber_->get_port() - << (its_sd_message_id.subscriber_->is_reliable() ? " reliable" : " unreliable") - << " was accepted"; - } - } else { // unsubscription was queued while subscription was pending -> send it to client - send_unsubscription(its_offering_client, - its_sd_message_id.subscribing_client_, - _service, _instance, _eventgroup, - its_sd_message_id.pending_subscription_id_); - } + std::set<client_t> subscribed_clients; + if (_client == VSOMEIP_ROUTING_CLIENT) { + for (const auto &its_event : its_eventgroup->get_events()) { + if (_event == ANY_EVENT || _event == its_event->get_event()) { + const auto &its_subscribers = its_event->get_subscribers(); + subscribed_clients.insert(its_subscribers.begin(), its_subscribers.end()); } } - return; + } else { + subscribed_clients.insert(_client); } - if (specific_endpoint_client) { - if (_client == get_client()) { - host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/); + for (const auto &its_subscriber : subscribed_clients) { + if (its_subscriber == get_client()) { 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); - } - } else { - std::set<client_t> subscribed_clients; - for (auto its_event : its_eventgroup->get_events()) { - for (auto its_client : its_event->get_subscribers()) { - subscribed_clients.insert(its_client); - } - } - for (auto its_subscriber : subscribed_clients) { - if (its_subscriber == get_client()) { - host_->on_subscription_error(_service, _instance, - _eventgroup, 0x0 /*OK*/); - for (auto its_event : its_eventgroup->get_events()) { + for (const auto &its_event : its_eventgroup->get_events()) { host_->on_subscription_status(_service, _instance, _eventgroup, its_event->get_event(), 0x0 /*OK*/); } } else { - stub_->send_subscribe_ack(its_subscriber, _service, - _instance, _eventgroup, _event); - } - } - } - } -} - -void routing_manager_impl::on_subscribe_nack(client_t _client, - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - event_t _event, pending_subscription_id_t _subscription_id) { - client_t its_client = is_specific_endpoint_client(_client, _service, _instance); - bool specific_endpoint_client = its_client != VSOMEIP_ROUTING_CLIENT; - auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); - if (its_eventgroup) { - std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock()); - if (_subscription_id == DEFAULT_SUBSCRIPTION) { - // NACK coming in via SD from remote or as answer to a subscription - // of the application hosting the rm_impl to a local service - auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, its_client); - std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); - auto its_state = remote_subscription_state_.find(its_tuple); - if (its_state != remote_subscription_state_.end()) { - if (its_state->second == subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED) { - // Already notified! - return; - } - } - remote_subscription_state_[its_tuple] = subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED; - } else { // NACK sent back from local client as answer to a remote subscription - if (discovery_) { - std::vector<pending_subscription_t> its_pending_subscriptions = - its_eventgroup->remove_pending_subscription(_subscription_id); - for (const pending_subscription_t& its_sd_message_id : its_pending_subscriptions) { - if (its_sd_message_id.ttl_ > 0) { - if (its_sd_message_id.sd_message_identifier_ && its_sd_message_id.subscriber_) { - discovery_->remote_subscription_acknowledge(_service, _instance, - _eventgroup, _client, false, its_sd_message_id.sd_message_identifier_); - VSOMEIP_INFO << "REMOTE SUBSCRIBE(" - << 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 << "]" - << " from " << its_sd_message_id.subscriber_->get_address().to_string() - << ":" << std::dec <<its_sd_message_id.subscriber_->get_port() - << (its_sd_message_id.subscriber_->is_reliable() ? " reliable" : " unreliable") - << " was not accepted"; - } - } else { // unsubscription was queued while subscription was pending -> send it to client - const client_t its_offering_client = find_local_client(_service, _instance); - send_unsubscription(its_offering_client, - its_sd_message_id.subscribing_client_, _service, - _instance, _eventgroup, - its_sd_message_id.pending_subscription_id_); - } + host_->on_subscription_status(_service, _instance, + _eventgroup, _event, 0x0 /*OK*/); } - } - return; - } - if (specific_endpoint_client) { - if (_client == get_client()) { - host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/); - host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/); } else { - stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup, - _event); - } - } else { - std::set<client_t> subscribed_clients; - for (auto its_event : its_eventgroup->get_events()) { - for (auto its_client : its_event->get_subscribers()) { - subscribed_clients.insert(its_client); - } - } - for (auto its_subscriber : subscribed_clients) { - if (its_subscriber == get_client()) { - host_->on_subscription_error(_service, _instance, - _eventgroup, 0x7 /*Rejected*/); - for (auto its_event : its_eventgroup->get_events()) { - host_->on_subscription_status(_service, _instance, - _eventgroup, its_event->get_event(), - 0x7 /*Rejected*/); - } - } else { - stub_->send_subscribe_nack(its_subscriber, _service, - _instance, _eventgroup, _event); - } + stub_->send_subscribe_ack(its_subscriber, _service, + _instance, _eventgroup, _event); } } - } + } } -bool routing_manager_impl::deliver_specific_endpoint_message(service_t _service, - instance_t _instance, const byte_t *_data, length_t _size, endpoint *_receiver) { - client_t its_client(0x0); - - // Try to deliver specific endpoint message (for selective subscribers) - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - auto found_servic = remote_services_.find(_service); - if (found_servic != remote_services_.end()) { - auto found_instance = found_servic->second.find(_instance); - if (found_instance != found_servic->second.end()) { - for (auto client_entry : found_instance->second) { - if (!client_entry.first) { - continue; - } - auto found_reliability = client_entry.second.find(_receiver->is_reliable()); - if (found_reliability != client_entry.second.end()) { - auto found_enpoint = found_reliability->second; - if (found_enpoint.get() == _receiver) { - its_client = client_entry.first; - break; - } - } - } - } - } - } - if (its_client) { - if (its_client != get_client()) { - auto local_endpoint = find_local(its_client); - if (local_endpoint) { - send_local(local_endpoint, its_client, _data, _size, _instance, true, - _receiver->is_reliable(), VSOMEIP_SEND); - } - } else { - deliver_message(_data, _size, _instance, _receiver->is_reliable(), VSOMEIP_ROUTING_CLIENT, true, true); - } - return true; - } - - return false; +std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client( + service_t _service, instance_t _instance, bool _reliable, + client_t _client) { + return ep_mgr_impl_->find_or_create_remote_client(_service, + _instance, _reliable, _client); } -void routing_manager_impl::clear_client_endpoints(service_t _service, instance_t _instance, - bool _reliable) { - auto its_specific_endpoint_clients = get_specific_endpoint_clients(_service, _instance); - std::shared_ptr<endpoint> endpoint_to_delete; - bool other_services_reachable_through_endpoint(false); - std::vector<std::shared_ptr<endpoint>> its_specific_endpoints; - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - // Clear client endpoints for remote services (generic and specific ones) - if (remote_services_.find(_service) != remote_services_.end()) { - if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { - auto endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT][_reliable]; - if (endpoint) { - service_instances_[_service].erase(endpoint.get()); - endpoint_to_delete = endpoint; - } - remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].erase(_reliable); - auto found_endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].find( - !_reliable); - if (found_endpoint == remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].end()) { - remote_services_[_service][_instance].erase(VSOMEIP_ROUTING_CLIENT); - } - // erase specific client endpoints - for (const client_t &client : its_specific_endpoint_clients) { - auto endpoint = remote_services_[_service][_instance][client][_reliable]; - if (endpoint) { - service_instances_[_service].erase(endpoint.get()); - its_specific_endpoints.push_back(endpoint); - } - remote_services_[_service][_instance][client].erase(_reliable); - auto found_endpoint = remote_services_[_service][_instance][client].find(!_reliable); - if (found_endpoint == remote_services_[_service][_instance][client].end()) { - remote_services_[_service][_instance].erase(client); - } - } - } - } - if (remote_services_.find(_service) != remote_services_.end()) { - if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { - if (!remote_services_[_service][_instance].size()) { - remote_services_[_service].erase(_instance); - if (0 >= remote_services_[_service].size()) { - remote_services_.erase(_service); - } - } - } - } - - if (!service_instances_[_service].size()) { - service_instances_.erase(_service); - } - - // Only stop and delete the endpoint if none of the services - // reachable through it is online anymore. - if (endpoint_to_delete) { - for (const auto& service : remote_services_) { - for (const auto& instance : service.second) { - const auto& client = instance.second.find(VSOMEIP_ROUTING_CLIENT); - if (client != instance.second.end()) { - for (const auto& reliable : client->second) { - if (reliable.second == endpoint_to_delete) { - other_services_reachable_through_endpoint = true; - break; - } - } - } - if (other_services_reachable_through_endpoint) { break; } - } - if (other_services_reachable_through_endpoint) { break; } - } +void routing_manager_impl::on_subscribe_nack(client_t _client, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + event_t _event, remote_subscription_id_t _id) { + (void)_event; // TODO: Remove completely? - if (!other_services_reachable_through_endpoint) { - std::uint16_t its_port(0); - boost::asio::ip::address its_address; - if (_reliable) { - std::shared_ptr<tcp_client_endpoint_impl> ep = - std::dynamic_pointer_cast<tcp_client_endpoint_impl>(endpoint_to_delete); - if (ep) { - its_port = ep->get_remote_port(); - ep->get_remote_address(its_address); - } - } else { - std::shared_ptr<udp_client_endpoint_impl> ep = - std::dynamic_pointer_cast<udp_client_endpoint_impl>(endpoint_to_delete); - if (ep) { - its_port = ep->get_remote_port(); - ep->get_remote_address(its_address); - } - } - const auto found_ip = client_endpoints_by_ip_.find(its_address); - if (found_ip != client_endpoints_by_ip_.end()) { - const auto found_port = found_ip->second.find(its_port); - if (found_port != found_ip->second.end()) { - const auto found_reliable = found_port->second.find(_reliable); - if (found_reliable != found_port->second.end()) { - if (found_reliable->second == endpoint_to_delete) { - found_port->second.erase(_reliable); - // delete if necessary - if (!found_port->second.size()) { - found_ip->second.erase(found_port); - if (!found_ip->second.size()) { - client_endpoints_by_ip_.erase(found_ip); - } - } - } - } - } + auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); + if (its_eventgroup) { + auto its_subscription = its_eventgroup->get_remote_subscription(_id); + if (its_subscription) { + its_subscription->set_client_state(_client, + remote_subscription_state_e::SUBSCRIPTION_NACKED); + + auto its_parent = its_subscription->get_parent(); + if (its_parent) { + its_parent->set_client_state(_client, + remote_subscription_state_e::SUBSCRIPTION_NACKED); + if (!its_subscription->is_pending()) { + its_eventgroup->remove_remote_subscription(_id); } } - } - } - if (!other_services_reachable_through_endpoint && endpoint_to_delete) { - endpoint_to_delete->stop(); - } - for (const auto &specific_endpoint : its_specific_endpoints) { - specific_endpoint->stop(); - } -} -void routing_manager_impl::clear_multicast_endpoints(service_t _service, instance_t _instance) { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - // Clear multicast info and endpoint and multicast instance (remote service) - if (multicast_info.find(_service) != multicast_info.end()) { - if (multicast_info[_service].find(_instance) != multicast_info[_service].end()) { - std::string address = multicast_info[_service][_instance]->get_address().to_string(); - uint16_t port = multicast_info[_service][_instance]->get_port(); - std::shared_ptr<endpoint> multicast_endpoint; - auto found_port = server_endpoints_.find(port); - if (found_port != server_endpoints_.end()) { - auto found_unreliable = found_port->second.find(false); - if (found_unreliable != found_port->second.end()) { - multicast_endpoint = found_unreliable->second; - multicast_endpoint->leave(address); - multicast_endpoint->stop(); - server_endpoints_[port].erase(false); - } - if (found_port->second.find(true) == found_port->second.end()) { - server_endpoints_.erase(port); - } - } - multicast_info[_service].erase(_instance); - if (0 >= multicast_info[_service].size()) { - multicast_info.erase(_service); - } - // Clear service_instances_ for multicase endpoint - if (1 >= service_instances_[_service].size()) { - service_instances_.erase(_service); - } else if (multicast_endpoint) { - service_instances_[_service].erase(multicast_endpoint.get()); + if (discovery_) { + discovery_->update_remote_subscription(its_subscription); + VSOMEIP_INFO << "REMOTE SUBSCRIBE(" + << 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 << "]" + << " from " << its_subscription->get_subscriber()->get_address() + << ":" << std::dec << its_subscription->get_subscriber()->get_port() + << (its_subscription->get_subscriber()->is_reliable() ? " reliable" : " unreliable") + << " was not accepted"; } } } @@ -3495,7 +2900,7 @@ return_code_e routing_manager_impl::check_error(const byte_t *_data, length_t _s void routing_manager_impl::send_error(return_code_e _return_code, const byte_t *_data, length_t _size, instance_t _instance, bool _reliable, - endpoint *_receiver, + endpoint* const _receiver, const boost::asio::ip::address &_remote_address, std::uint16_t _remote_port) { @@ -3535,150 +2940,39 @@ void routing_manager_impl::send_error(return_code_e _return_code, error_message->set_service(its_service); error_message->set_session(its_session); { - std::lock_guard<std::mutex> its_lock(serialize_mutex_); - if (serializer_->serialize(error_message.get())) { + std::shared_ptr<serializer> its_serializer(get_serializer()); + if (its_serializer->serialize(error_message.get())) { if (_receiver) { auto its_endpoint_def = std::make_shared<endpoint_definition>( _remote_address, _remote_port, _receiver->is_reliable()); its_endpoint_def->set_remote_port(_receiver->get_local_port()); - send_to(its_endpoint_def, serializer_->get_data(), - serializer_->get_size(), _instance, true); - } - serializer_->reset(); - } else { - VSOMEIP_ERROR<< "Failed to serialize error message."; - } - } -} - -void routing_manager_impl::on_identify_response(client_t _client, service_t _service, - instance_t _instance, bool _reliable) { - { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - auto its_service = identifying_clients_.find(_service); - if (its_service != identifying_clients_.end()) { - auto its_instance = its_service->second.find(_instance); - if (its_instance != its_service->second.end()) { - auto its_reliable = its_instance->second.find(_reliable); - if (its_reliable != its_instance->second.end()) { - its_reliable->second.erase(_client); - } - } - } - identified_clients_[_service][_instance][_reliable].insert(_client); - } - discovery_->send_subscriptions(_service, _instance, _client, _reliable); -} - -void routing_manager_impl::identify_for_subscribe(client_t _client, - service_t _service, instance_t _instance, major_version_t _major, - subscription_type_e _subscription_type) { - (void)_subscription_type; - if (!has_identified(_client, _service, _instance, false) - && !is_identifying(_client, _service, _instance, false)) { - send_identify_message(_client, _service, _instance, _major, false); - } - if (!has_identified(_client, _service, _instance, true) - && !is_identifying(_client, _service, _instance, true)) { - send_identify_message(_client, _service, _instance, _major, true); - } -} - -bool routing_manager_impl::send_identify_message(client_t _client, - service_t _service, - instance_t _instance, - major_version_t _major, - bool _reliable) { - auto its_endpoint = find_or_create_remote_client(_service, _instance, - _reliable, _client); - if (!its_endpoint) { - VSOMEIP_WARNING << "routing_manager_impl::send_identify_message: " - << "No " << (_reliable ? "reliable" : "unreliable") - << " route for identify message to service/instance " - << std::hex << _service << "/" << _instance << " for client " - << _client; - return false; - } - { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - identifying_clients_[_service][_instance][_reliable].insert(_client); - } - - if (_client == get_client()) { - send_identify_request(_service, _instance, _major, _reliable); - } else { - stub_->send_identify_request_command(find_local(_client), - _service, _instance, _major, _reliable); - } - - return true; -} - - -bool routing_manager_impl::supports_selective(service_t _service, instance_t _instance) { - bool supports_selective(false); - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - auto its_service = remote_service_info_.find(_service); - if (its_service != remote_service_info_.end()) { - auto its_instance = its_service->second.find(_instance); - if (its_instance != its_service->second.end()) { - for (auto its_reliable : its_instance->second) { - supports_selective |= configuration_-> - supports_selective_broadcasts( - its_reliable.second->get_address()); - } - } - } - return supports_selective; -} - -bool routing_manager_impl::is_identifying(client_t _client, service_t _service, - instance_t _instance, bool _reliable) { - if (!supports_selective(_service, _instance)) { - // For legacy selective services clients can't be identified! - return false; - } - bool is_identifieing(false); - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - auto its_service = identifying_clients_.find(_service); - if (its_service != identifying_clients_.end()) { - auto its_instance = its_service->second.find(_instance); - if (its_instance != its_service->second.end()) { - auto its_reliable = its_instance->second.find(_reliable); - if (its_reliable != its_instance->second.end()) { - auto its_client = its_reliable->second.find(_client); - if (its_client != its_reliable->second.end()) { - is_identifieing = true; - } - } - } - } - return is_identifieing; -} + std::shared_ptr<endpoint> its_endpoint = + ep_mgr_impl_->find_server_endpoint( + its_endpoint_def->get_remote_port(), + its_endpoint_def->is_reliable()); + if (its_endpoint) { + #ifdef USE_DLT + const uint16_t its_data_size + = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); -bool routing_manager_impl::has_identified(client_t _client, service_t _service, - instance_t _instance, bool _reliable) { - if (!supports_selective(_service, _instance)) { - // For legacy selective services clients can't be identified! - return true; - } - bool has_identified(false); - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - auto its_service = identified_clients_.find(_service); - if (its_service != identified_clients_.end()) { - auto its_instance = its_service->second.find(_instance); - if (its_instance != its_service->second.end()) { - auto its_reliable = its_instance->second.find(_reliable); - if (its_reliable != its_instance->second.end()) { - auto its_client = its_reliable->second.find(_client); - if (its_client != its_reliable->second.end()) { - has_identified = true; + 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); + #else + (void) _instance; + #endif + its_endpoint->send_error(its_endpoint_def, + its_serializer->get_data(), its_serializer->get_size()); } } + its_serializer->reset(); + put_serializer(its_serializer); + } else { + VSOMEIP_ERROR<< "Failed to serialize error message."; } } - return has_identified; } void routing_manager_impl::clear_remote_subscriber( @@ -3703,19 +2997,12 @@ void routing_manager_impl::clear_remote_subscriber( std::chrono::steady_clock::time_point routing_manager_impl::expire_subscriptions(bool _force) { - struct subscriptions_info { - service_t service_id_; - instance_t instance_id_; - eventgroup_t eventgroup_id_; - std::shared_ptr<endpoint_definition> invalid_endpoint_; - client_t client_; - std::set<std::shared_ptr<event>> events_; - std::shared_ptr<eventgroupinfo> eventgroupinfo_; - }; - std::vector<struct subscriptions_info> subscriptions_to_expire_; + std::map<std::shared_ptr<remote_subscription>, + std::set<client_t> > its_expired_subscriptions; + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - std::chrono::steady_clock::time_point next_expiration + std::chrono::steady_clock::time_point its_next_expiration = std::chrono::steady_clock::now() + std::chrono::hours(24); { std::lock_guard<std::mutex> its_lock(eventgroups_mutex_); @@ -3723,86 +3010,70 @@ routing_manager_impl::expire_subscriptions(bool _force) { for (auto &its_service : eventgroups_) { for (auto &its_instance : its_service.second) { 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 (_force) { - its_expired_endpoints.insert(its_target.endpoint_); - } 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_; + auto its_subscriptions + = its_eventgroup.second->get_remote_subscriptions(); + for (auto &s : its_subscriptions) { + for (auto its_client : s->get_clients()) { + if (_force) { + its_expired_subscriptions[s].insert(its_client); + } else { + auto its_expiration = s->get_expiration(its_client); + if (its_expiration != std::chrono::steady_clock::time_point()) { + if (its_expiration < now) { + its_expired_subscriptions[s].insert(its_client); + } else if (its_expiration < its_next_expiration) { + its_next_expiration = its_expiration; + } + } } } } - - for (auto its_endpoint : its_expired_endpoints) { - its_eventgroup.second->remove_target(its_endpoint); - - client_t its_client - = find_client(its_service.first, its_instance.first, - its_eventgroup.second, its_endpoint); - clear_remote_subscriber(its_service.first, its_instance.first, - its_client, its_endpoint); - - std::set<std::shared_ptr<event> > its_events; - if (its_eventgroup.second->get_targets().size() == 0) { - its_events = its_eventgroup.second->get_events(); - } - subscriptions_to_expire_.push_back({its_service.first, - its_instance.first, - its_eventgroup.first, - its_endpoint, - its_client, - its_events, - its_eventgroup.second}); - } - if(its_eventgroup.second->is_multicast() && its_expired_endpoints.size() && - 0 == its_eventgroup.second->get_unreliable_target_count() ) { - //clear multicast targets if no unreliable subscriber is left for multicast eventgroup - its_eventgroup.second->clear_multicast_targets(); - } } } } } - for (const auto &s : subscriptions_to_expire_) { - if (s.invalid_endpoint_) { - for (const auto e: s.events_) { - if (e->is_shadow()) { - e->unset_payload(); - } + for (auto &s : its_expired_subscriptions) { + auto its_info = s.first->get_eventgroupinfo(); + if (its_info) { + auto its_service = its_info->get_service(); + auto its_instance = its_info->get_instance(); + auto its_eventgroup = its_info->get_eventgroup(); + auto its_major = its_info->get_major(); + + remote_subscription_id_t its_id; + auto its_result = its_info->update_remote_subscription( + s.first, std::chrono::steady_clock::now(), + s.second, its_id, false); + if (its_result) { + const client_t its_offering_client + = find_local_client(its_service, its_instance); + send_unsubscription(its_offering_client, + its_service, its_instance, its_eventgroup, its_major, + s.second, s.first->get_id()); } - const client_t its_hosting_client = find_local_client(s.service_id_, - s.instance_id_); - - if (its_hosting_client != VSOMEIP_ROUTING_CLIENT) { - const pending_subscription_t its_pending_unsubscription( - std::shared_ptr<sd_message_identifier_t>(), - s.invalid_endpoint_, s.invalid_endpoint_, - 0, s.client_); - pending_subscription_id_t its_pending_unsubscription_id = - s.eventgroupinfo_->add_pending_subscription( - its_pending_unsubscription); - if (its_pending_unsubscription_id != DEFAULT_SUBSCRIPTION) { - send_unsubscription(its_hosting_client, s.client_, s.service_id_, - s.instance_id_, s.eventgroup_id_, - its_pending_unsubscription_id); - } + + if (s.first->get_unreliable()) { + VSOMEIP_INFO << "Expired subscription [" + << std::hex << std::setfill('0') << std::setw(4) << its_service << "." + << std::hex << std::setfill('0') << std::setw(4) << its_instance << "." + << std::hex << std::setfill('0') << std::setw(4) << its_eventgroup << "] unreliable from " + << s.first->get_unreliable()->get_address() << ":" + << std::dec << s.first->get_unreliable()->get_port(); } - VSOMEIP_INFO << "Expired subscription [" - << std::hex << std::setfill('0') << std::setw(4) << s.service_id_ << "." - << std::hex << std::setfill('0') << std::setw(4) << s.instance_id_ << "." - << 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_ << ") " - << _force; + if (s.first->get_reliable()) { + VSOMEIP_INFO << "Expired subscription [" + << std::hex << std::setfill('0') << std::setw(4) << its_service << "." + << std::hex << std::setfill('0') << std::setw(4) << its_instance << "." + << std::hex << std::setfill('0') << std::setw(4) << its_eventgroup << "] reliable from " + << s.first->get_reliable()->get_address() << ":" + << std::dec << s.first->get_reliable()->get_port(); + } } } - return next_expiration; + + return its_next_expiration; } void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const & _error) { @@ -3811,6 +3082,9 @@ void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const #ifndef VSOMEIP_VERSION #define VSOMEIP_VERSION "unknown version" #endif + static int counter(0); + static uint32_t its_interval = configuration_->get_log_version_interval(); + bool is_diag_mode(false); if (discovery_) { @@ -3825,62 +3099,24 @@ void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const std::chrono::steady_clock::now() - last_resume_).count() << "s"; } } + VSOMEIP_INFO << "vSomeIP " << VSOMEIP_VERSION << " | (" << ((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( - std::chrono::seconds(configuration_->get_log_version_interval())); - version_log_timer_.async_wait(std::bind(&routing_manager_impl::log_version_timer_cbk, - this, std::placeholders::_1)); - } - } -} - -#ifndef WITHOUT_SYSTEMD -void routing_manager_impl::watchdog_cbk(boost::system::error_code const &_error) { - if (!_error) { - static bool is_ready(false); - static bool has_interval(false); - static uint64_t its_interval(0); - - if (is_ready) { - sd_notify(0, "WATCHDOG=1"); - VSOMEIP_INFO << "Triggered systemd watchdog"; - } else { - is_ready = true; - sd_notify(0, "READY=1"); - VSOMEIP_INFO << "Sent READY to systemd watchdog"; - if (0 < sd_watchdog_enabled(0, &its_interval)) { - has_interval = true; - VSOMEIP_INFO << "systemd watchdog is enabled"; - } - } - if (has_interval) { - std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_); - watchdog_timer_.expires_from_now(std::chrono::microseconds(its_interval / 2)); - watchdog_timer_.async_wait(std::bind(&routing_manager_impl::watchdog_cbk, - this, std::placeholders::_1)); + counter++; + if (counter == 6) { + ep_mgr_->log_client_states(); + ep_mgr_impl_->log_client_states(); + counter = 0; } - } -} -#endif -void routing_manager_impl::clear_remote_service_info(service_t _service, instance_t _instance, bool _reliable) { - // Clear remote_service_info_ - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - if (remote_service_info_.find(_service) != remote_service_info_.end()) { - if (remote_service_info_[_service].find(_instance) != remote_service_info_[_service].end()) { - remote_service_info_[_service][_instance].erase(_reliable); - auto found_endpoint_def = remote_service_info_[_service][_instance].find(!_reliable); - if (found_endpoint_def == remote_service_info_[_service][_instance].end()) { - remote_service_info_[_service].erase(_instance); - if (0 >= remote_service_info_[_service].size()) { - remote_service_info_.erase(_service); - } - } + { + std::lock_guard<std::mutex> its_lock(version_log_timer_mutex_); + version_log_timer_.expires_from_now(std::chrono::seconds(its_interval)); + version_log_timer_.async_wait( + std::bind(&routing_manager_impl::log_version_timer_cbk, + this, std::placeholders::_1)); } } } @@ -4123,135 +3359,28 @@ void routing_manager_impl::handle_client_error(client_t _client) { } for (const auto &offer : its_offers) { offer_service(std::get<0>(offer), std::get<1>(offer), std::get<2>(offer), - std::get<3>(offer), std::get<4>(offer)); + std::get<3>(offer), std::get<4>(offer), true); } } -void routing_manager_impl::remove_specific_client_endpoint(client_t _client, service_t _service, - instance_t _instance, bool _reliable) { - client_t its_client = is_specific_endpoint_client(_client, _service, _instance); - if (its_client != VSOMEIP_ROUTING_CLIENT) { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - if (remote_services_.find(_service) != remote_services_.end()) { - if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { - auto endpoint = remote_services_[_service][_instance][_client][_reliable]; - if (endpoint) { - service_instances_[_service].erase(endpoint.get()); - endpoint->stop(); - } - remote_services_[_service][_instance][_client].erase(_reliable); - auto found_endpoint = remote_services_[_service][_instance][_client].find(!_reliable); - if (found_endpoint == remote_services_[_service][_instance][_client].end()) { - remote_services_[_service][_instance].erase(_client); - } - } - } - } -} - -void routing_manager_impl::clear_identified_clients( service_t _service, instance_t _instance) { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - auto its_service = identified_clients_.find(_service); - if (its_service != identified_clients_.end()) { - auto found_instance = its_service->second.find(_instance); - if (found_instance != its_service->second.end()) { - auto found_reliable = found_instance->second.find(true); - if (found_reliable != found_instance->second.end()) { - found_reliable->second.clear(); - } - auto found_unreliable = found_instance->second.find(false); - if (found_unreliable != found_instance->second.end()) { - found_unreliable->second.clear(); - } - } - } -} - -void routing_manager_impl::clear_identifying_clients( service_t _service, instance_t _instance) { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - auto its_service = identifying_clients_.find(_service); - if (its_service != identifying_clients_.end()) { - auto found_instance = its_service->second.find(_instance); - if (found_instance != its_service->second.end()) { - auto found_reliable = found_instance->second.find(true); - if (found_reliable != found_instance->second.end()) { - found_reliable->second.clear(); - } - auto found_unreliable = found_instance->second.find(false); - if (found_unreliable != found_instance->second.end()) { - found_unreliable->second.clear(); - } - } - } -} - -void routing_manager_impl::remove_identified_client(service_t _service, instance_t _instance, client_t _client) { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - auto its_service = identified_clients_.find(_service); - if (its_service != identified_clients_.end()) { - auto found_instance = its_service->second.find(_instance); - if (found_instance != its_service->second.end()) { - auto found_reliable = found_instance->second.find(true); - if (found_reliable != found_instance->second.end()) { - auto found_client = found_reliable->second.find(_client); - if(found_client != found_reliable->second.end()) - found_reliable->second.erase(_client); - } - auto found_unreliable = found_instance->second.find(false); - if (found_unreliable != found_instance->second.end()) { - auto found_client = found_unreliable->second.find(_client); - if(found_client != found_unreliable->second.end()) - found_unreliable->second.erase(_client); - } - } - } -} - -void routing_manager_impl::remove_identifying_client(service_t _service, instance_t _instance, client_t _client) { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - auto its_service = identifying_clients_.find(_service); - if (its_service != identifying_clients_.end()) { - auto found_instance = its_service->second.find(_instance); - if (found_instance != its_service->second.end()) { - auto found_reliable = found_instance->second.find(true); - if (found_reliable != found_instance->second.end()) { - auto found_client = found_reliable->second.find(_client); - if(found_client != found_reliable->second.end()) - found_reliable->second.erase(_client); - } - auto found_unreliable = found_instance->second.find(false); - if (found_unreliable != found_instance->second.end()) { - auto found_client = found_unreliable->second.find(_client); - if(found_client != found_unreliable->second.end()) - found_unreliable->second.erase(_client); - } - } - } -} - -void routing_manager_impl::unsubscribe_specific_client_at_sd( - service_t _service, instance_t _instance, client_t _client) { - client_t subscriber = is_specific_endpoint_client(_client, _service, _instance); - if (subscriber != VSOMEIP_ROUTING_CLIENT && discovery_) { - discovery_->unsubscribe_client(_service, _instance, _client); - } +std::shared_ptr<endpoint_manager_impl> routing_manager_impl::get_endpoint_manager() const { + return ep_mgr_impl_; } void routing_manager_impl::send_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) { - (void)_subscription_type; - auto endpoint = find_local(_service, _instance); + event_t _event) { + auto endpoint = ep_mgr_->find_local(_service, _instance); if (endpoint) { stub_->send_subscribe(endpoint, _client, - _service, _instance, _eventgroup, _major, _event, DEFAULT_SUBSCRIPTION); + _service, _instance, _eventgroup, _major, _event, PENDING_SUBSCRIPTION_ID); } } void routing_manager_impl::set_routing_state(routing_state_e _routing_state) { if(discovery_) { switch (_routing_state) { - case vsomeip::routing_state_e::RS_SUSPENDED: + case routing_state_e::RS_SUSPENDED: { VSOMEIP_INFO << "Set routing to suspend mode, diagnosis mode is " << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive."); @@ -4271,7 +3400,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) { << 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); + discovery_->stop_offer_service(its_instance.second); } } { @@ -4289,13 +3418,6 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) { // determine existing subscriptions to remote service and send StopSubscribe for (auto its_eventgroup : get_subscribed_eventgroups(s.first, i.first)) { discovery_->unsubscribe(s.first, i.first, its_eventgroup, VSOMEIP_ROUTING_CLIENT); - auto specific_endpoint_clients = get_specific_endpoint_clients(s.first, i.first); - for (auto its_client : specific_endpoint_clients) { - discovery_->unsubscribe(s.first, i.first, its_eventgroup, its_client); - } - for (const auto &e : find_events(s.first, i.first, its_eventgroup)) { - e->clear_subscribers(); - } } const bool has_reliable(i.second->get_endpoint(true)); @@ -4308,7 +3430,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) { } break; } - case vsomeip::routing_state_e::RS_RESUMED: + case routing_state_e::RS_RESUMED: { VSOMEIP_INFO << "Set routing to resume mode, diagnosis mode was " << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive."); @@ -4337,8 +3459,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) { // Trigger initial offer phase for relevant services for (const auto &its_service : get_offered_services()) { for (const auto &its_instance : its_service.second) { - discovery_->offer_service(its_service.first, - its_instance.first, its_instance.second); + discovery_->offer_service(its_instance.second); } } break; @@ -4353,8 +3474,7 @@ 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)) { - discovery_->stop_offer_service( - its_service.first, its_instance.first, its_instance.second); + discovery_->stop_offer_service(its_instance.second); } } } @@ -4382,8 +3502,7 @@ 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)) { - discovery_->offer_service(its_service.first, - its_instance.first, its_instance.second); + discovery_->offer_service(its_instance.second); } } } @@ -4446,6 +3565,10 @@ void routing_manager_impl::on_net_interface_or_route_state_changed( } void routing_manager_impl::start_ip_routing() { +#ifdef _WIN32 + if_state_running_ = true; +#endif + if (routing_ready_handler_) { routing_ready_handler_(); } @@ -4506,8 +3629,8 @@ routing_manager_impl::get_subscribed_eventgroups( if (found_service != eventgroups_.end()) { auto found_instance = found_service->second.find(_instance); if (found_instance != found_service->second.end()) { - for (auto its_group : found_instance->second) { - for (auto its_event : its_group.second->get_events()) { + for (const auto& its_group : found_instance->second) { + for (const auto& its_event : its_group.second->get_events()) { if (its_event->has_subscriber(its_group.first, ANY_CLIENT)) { its_eventgroups.insert(its_group.first); } @@ -4540,7 +3663,7 @@ void routing_manager_impl::clear_targets_and_pending_sub_from_eventgroups( its_eventgroup.first, its_subscriber); } - client_t its_client = is_specific_endpoint_client(its_subscriber, _service, _instance); + client_t its_client = VSOMEIP_ROUTING_CLIENT; //is_specific_endpoint_client(its_subscriber, _service, _instance); { std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); const auto its_tuple = @@ -4551,8 +3674,9 @@ void routing_manager_impl::clear_targets_and_pending_sub_from_eventgroups( } its_events.push_back(its_event); } - its_eventgroup.second->clear_targets(); - its_eventgroup.second->clear_pending_subscriptions(); + // TODO dn: find out why this was commented out + //its_eventgroup.second->clear_targets(); + //its_eventgroup.second->clear_pending_subscriptions(); } } } @@ -4578,7 +3702,7 @@ void routing_manager_impl::clear_remote_subscriber(service_t _service, void routing_manager_impl::call_sd_endpoint_connected( const boost::system::error_code& _error, service_t _service, instance_t _instance, - std::shared_ptr<endpoint> _endpoint, + const std::shared_ptr<endpoint>& _endpoint, std::shared_ptr<boost::asio::steady_timer> _timer) { (void)_timer; if (_error) { @@ -4604,14 +3728,20 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe( if (its_local_client == host_->get_client()) { // received subscription for event of a service instance hosted by // application acting as rm_impl register with own client id and shadow = false - register_event(host_->get_client(), _service, _instance, _event, - its_eventgroups, true, std::chrono::milliseconds::zero(), false, + register_event(host_->get_client(), + _service, _instance, + _event, + its_eventgroups, event_type_e::ET_UNKNOWN, reliability_type_e::RT_UNKNOWN, + std::chrono::milliseconds::zero(), false, true, nullptr, false, false, true); } else if (its_local_client != VSOMEIP_ROUTING_CLIENT) { // received subscription for event of a service instance hosted on // this node register with client id of local_client and set shadow to true - register_event(its_local_client, _service, _instance, _event, - its_eventgroups, true, std::chrono::milliseconds::zero(), false, + register_event(its_local_client, + _service, _instance, + _event, its_eventgroups, event_type_e::ET_UNKNOWN, + reliability_type_e::RT_UNKNOWN, + std::chrono::milliseconds::zero(), false, true, nullptr, false, true, true); } else { // received subscription for event of a unknown or remote service instance @@ -4620,9 +3750,12 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe( if (its_info && !its_info->is_local()) { // remote service, register shadow event with client ID of subscriber // which should have called register_event - register_event(_client, _service, _instance, _event, - its_eventgroups, true, std::chrono::milliseconds::zero(), - false, nullptr, false, true, true); + register_event(_client, + _service, _instance, + _event, its_eventgroups, event_type_e::ET_UNKNOWN, + reliability_type_e::RT_UNKNOWN, + std::chrono::milliseconds::zero(), + false, true, nullptr, false, true, true); } else { VSOMEIP_WARNING << "routing_manager_impl::create_placeholder_event_and_subscribe(" @@ -4642,126 +3775,84 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe( return is_inserted; } -void routing_manager_impl::handle_subscription_state(client_t _client, service_t _service, instance_t _instance, +void routing_manager_impl::handle_subscription_state( + client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) { +#if 0 + VSOMEIP_ERROR << "routing_manager_impl::" << __func__ + << "(" << std::hex << _client << "): " + << "event=" + << std::hex << _service << "." + << std::hex << _instance << "." + << std::hex << _eventgroup << "." + << std::hex << _event + << " me=" + << std::hex << get_client(); +#endif + // Note: remote_subscription_state_mutex_ is already locked as this + // method builds a critical section together with insert_subscription + // from routing_manager_base. + // Todo: Improve this situation... + auto its_event = find_event(_service, _instance, _event); + client_t its_client(VSOMEIP_ROUTING_CLIENT); + if (its_event && + its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT) { + its_client = _client; + } - client_t subscriber = is_specific_endpoint_client(_client, _service, _instance); - auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber); - - std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_); + auto its_tuple + = std::make_tuple(_service, _instance, _eventgroup, its_client); auto its_state = remote_subscription_state_.find(its_tuple); if (its_state != remote_subscription_state_.end()) { +#if 0 + VSOMEIP_ERROR << "routing_manager_impl::" << __func__ + << "(" << std::hex << _client << "): " + << "event=" + << std::hex << _service << "." + << std::hex << _instance << "." + << std::hex << _eventgroup << "." + << std::hex << _event + << " state=" << std::hex << (int)its_state->second + << " me=" + << std::hex << get_client(); +#endif if (its_state->second == subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED) { // Subscription already acknowledged! if (_client == get_client()) { - host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/); host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/); } else { stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup, _event); } } - } else { - remote_subscription_state_[its_tuple] = subscription_state_e::IS_SUBSCRIBING; } } -client_t routing_manager_impl::is_specific_endpoint_client(client_t _client, - service_t _service, instance_t _instance) { - client_t result = VSOMEIP_ROUTING_CLIENT; - { - std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_); - auto found_service = specific_endpoint_clients_.find(_service); - if (found_service != specific_endpoint_clients_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_client = found_instance->second.find(_client); - if(found_client != found_instance->second.end()) { - result = _client; - } - } - } - } - // A client_t != VSOMEIP_ROUTING_CLIENT implies true - return result; -} - -std::unordered_set<client_t> routing_manager_impl::get_specific_endpoint_clients( - service_t _service, instance_t _instance) { - std::unordered_set<client_t> result; - { - std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_); - auto found_service = specific_endpoint_clients_.find(_service); - if (found_service != specific_endpoint_clients_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - result = found_instance->second; - } - } - } - return result; -} - -void routing_manager_impl::send_initial_events( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - const std::shared_ptr<endpoint_definition> &_subscriber) { - std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service, - _instance, _eventgroup); - if (!its_eventgroup) { - return; - } - bool is_offered_both(false); - if (configuration_->get_reliable_port(_service, _instance) != ILLEGAL_PORT && - configuration_->get_unreliable_port(_service, _instance) != ILLEGAL_PORT) { - is_offered_both = true; - } - // send initial events if we already have a cached field (is_set) - for (const auto &its_event : its_eventgroup->get_events()) { - if (its_event->is_field()) { - if (its_event->is_set()) { - if (!is_offered_both) { - its_event->notify_one(_subscriber, true); - } else { - if (its_event->is_reliable() && _subscriber->is_reliable()) { - its_event->notify_one(_subscriber, true); - } - if (!its_event->is_reliable() && !_subscriber->is_reliable()) { - its_event->notify_one(_subscriber, true); - } - } - } else { - // received a subscription but can't notify due to missing payload - its_event->set_remote_notification_pending(true); - } - } - } -} - -void routing_manager_impl::register_offer_acceptance_handler( - vsomeip::offer_acceptance_handler_t _handler) const { +void routing_manager_impl::register_sd_acceptance_handler( + const sd_acceptance_handler_t& _handler) const { if (discovery_) { - discovery_->register_offer_acceptance_handler(_handler); + discovery_->register_sd_acceptance_handler(_handler); } } void routing_manager_impl::register_reboot_notification_handler( - vsomeip::reboot_notification_handler_t _handler) const { + const 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) { + const routing_ready_handler_t& _handler) { routing_ready_handler_ = _handler; } void routing_manager_impl::register_routing_state_handler( - routing_state_handler_t _handler) { + const routing_state_handler_t& _handler) { routing_state_handler_ = _handler; } -void routing_manager_impl::offer_acceptance_enabled( - boost::asio::ip::address _address) { +void routing_manager_impl::sd_acceptance_enabled( + const boost::asio::ip::address& _address) { boost::system::error_code ec; VSOMEIP_INFO << "ipsec-plugin-mgu: expire subscriptions and services: " << _address.to_string(ec); @@ -4775,7 +3866,7 @@ void routing_manager_impl::memory_log_timer_cbk( return; } #ifndef _WIN32 - static const std::uint32_t its_pagesize = getpagesize() / 1024; + static const std::uint32_t its_pagesize = static_cast<std::uint32_t>(getpagesize() / 1024); #else static const std::uint32_t its_pagesize = 4096 / 1024; #endif @@ -4836,75 +3927,7 @@ void routing_manager_impl::status_log_timer_cbk( return; } - // local client endpoints - { - std::map<client_t, std::shared_ptr<endpoint>> lces = get_local_endpoints(); - VSOMEIP_INFO << "status local client endpoints: " << std::dec << lces.size(); - for (const auto lce : lces) { - lce.second->print_status(); - } - } - - // udp and tcp client endpoints - { - client_endpoints_by_ip_t client_endpoints_by_ip; - remote_services_t remote_services; - server_endpoints_t server_endpoints; - { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - client_endpoints_by_ip = client_endpoints_by_ip_; - remote_services = remote_services_; - server_endpoints = server_endpoints_; - } - VSOMEIP_INFO << "status start remote client endpoints:"; - std::uint32_t num_remote_client_endpoints(0); - // normal endpoints - for (const auto &a : client_endpoints_by_ip) { - for (const auto p : a.second) { - for (const auto ru : p.second) { - ru.second->print_status(); - num_remote_client_endpoints++; - } - } - } - VSOMEIP_INFO << "status end remote client endpoints: " << std::dec - << num_remote_client_endpoints; - - // selective client endpoints - VSOMEIP_INFO << "status start selective remote client endpoints:"; - std::uint32_t num_remote_selectiv_client_endpoints(0); - for (const auto s : remote_services) { - for (const auto i : s.second) { - for (const auto c : i.second) { - if (c.first != VSOMEIP_ROUTING_CLIENT) { - for (const auto ur : c.second) { - ur.second->print_status(); - num_remote_selectiv_client_endpoints++; - } - } - } - } - } - VSOMEIP_INFO << "status end selective remote client endpoints: " - << std::dec << num_remote_selectiv_client_endpoints; - - VSOMEIP_INFO << "status start server endpoints:"; - std::uint32_t num_server_endpoints(1); - // local server endpoints - stub_->print_endpoint_status(); - - // server endpoints - for (const auto p : server_endpoints) { - for (const auto ru : p.second ) { - ru.second->print_status(); - num_server_endpoints++; - } - } - VSOMEIP_INFO << "status end server endpoints:" - << std::dec << num_server_endpoints; - } - - + ep_mgr_impl_->print_status(); { std::lock_guard<std::mutex> its_lock(status_log_timer_mutex_); boost::system::error_code ec; @@ -4916,138 +3939,107 @@ void routing_manager_impl::status_log_timer_cbk( } } -void routing_manager_impl::on_unsubscribe_ack(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, - pending_subscription_id_t _unsubscription_id) { - std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service, - _instance, _eventgroup); - if (!its_eventgroup) { - VSOMEIP_ERROR << __func__ << ": Received UNSUBSCRIBE_ACK for unknown " - << "eventgroup: (" - << 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 << "]"; - return; - } - // there will only be one or zero subscriptions returned here - std::vector<pending_subscription_t> its_pending_subscriptions = - its_eventgroup->remove_pending_subscription(_unsubscription_id); - for (const pending_subscription_t& its_sd_message_id : its_pending_subscriptions) { - if (its_sd_message_id.pending_subscription_id_ == _unsubscription_id) { - its_eventgroup->remove_target(its_sd_message_id.target_); - clear_remote_subscriber(_service, _instance, - its_sd_message_id.subscribing_client_, - its_sd_message_id.target_); - if (its_eventgroup->get_targets().size() == 0) { - for (auto e : its_eventgroup->get_events()) { - if (e->is_shadow()) { - e->unset_payload(); +void +routing_manager_impl::on_unsubscribe_ack(client_t _client, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + remote_subscription_id_t _id) { + std::shared_ptr<eventgroupinfo> its_info + = find_eventgroup(_service, _instance, _eventgroup); + if (its_info) { + const auto its_subscription = its_info->get_remote_subscription(_id); + if (its_subscription) { + its_info->remove_remote_subscription(_id); + + std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_); + remote_subscribers_[_service][_instance].erase(_client); + + if (its_info->get_remote_subscriptions().size() == 0) { + for (const auto &its_event : its_info->get_events()) { + bool has_remote_subscriber(false); + for (const auto &its_eventgroup : its_event->get_eventgroups()) { + const auto its_eventgroup_info + = find_eventgroup(_service, _instance, its_eventgroup); + if (its_eventgroup_info + && its_eventgroup_info->get_remote_subscriptions().size() > 0) { + has_remote_subscriber = true; + } + } + + if (!has_remote_subscriber && its_event->is_shadow()) { + its_event->unset_payload(); } } } } else { - const pending_subscription_id_t its_subscription_id = - its_sd_message_id.pending_subscription_id_; - const client_t its_subscribing_client = its_sd_message_id.subscribing_client_; - const client_t its_offering_client = find_local_client(_service, _instance); - send_subscription(its_offering_client, its_subscribing_client, _service, - _instance, _eventgroup, its_eventgroup->get_major(), - its_subscription_id); + VSOMEIP_ERROR << __func__ + << ": Unknown StopSubscribe " << std::dec << _id << " for eventgroup [" + << 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 << "]"; } + } else { + VSOMEIP_ERROR << __func__ + << ": Received StopSubscribe for unknown eventgroup: (" + << 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 << "]"; } } -void routing_manager_impl::send_unsubscription( - client_t _offering_client, client_t _subscribing_client, - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - pending_subscription_id_t _pending_unsubscription_id) { +void routing_manager_impl::on_connect(const std::shared_ptr<endpoint>& _endpoint) { + (void)_endpoint; +} +void routing_manager_impl::on_disconnect(const std::shared_ptr<endpoint>& _endpoint) { + (void)_endpoint; +} +void routing_manager_impl::send_subscription( + const client_t _offering_client, + const service_t _service, const instance_t _instance, + const eventgroup_t _eventgroup, const major_version_t _major, + const std::set<client_t> &_clients, + const remote_subscription_id_t _id) { if (host_->get_client() == _offering_client) { auto self = shared_from_this(); - host_->on_subscription(_service, _instance, _eventgroup, - _subscribing_client, false, - [this, self, _service, _instance, _eventgroup, - _subscribing_client, _pending_unsubscription_id, _offering_client] - (const bool _subscription_accepted) { - (void)_subscription_accepted; + for (const auto its_client : _clients) { + host_->on_subscription(_service, _instance, _eventgroup, its_client, own_uid_, own_gid_, true, + [this, self, _service, _instance, _eventgroup, its_client, _id] + (const bool _is_accepted) { try { - const auto its_callback = std::bind( - &routing_manager_stub_host::on_unsubscribe_ack, - std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), - _offering_client, _service, _instance, - _eventgroup, _pending_unsubscription_id); - io_.post(its_callback); + if (!_is_accepted) { + const auto its_callback = std::bind( + &routing_manager_stub_host::on_subscribe_nack, + std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), + its_client, _service, _instance, + _eventgroup, ANY_EVENT, _id); + io_.post(its_callback); + } else { + const auto its_callback = std::bind( + &routing_manager_stub_host::on_subscribe_ack, + std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), + its_client, _service, _instance, + _eventgroup, ANY_EVENT, _id); + io_.post(its_callback); + } } catch (const std::exception &e) { VSOMEIP_ERROR << __func__ << e.what(); } - } - ); - } else { - if (!stub_->send_unsubscribe(find_local(_offering_client), - _subscribing_client, - _service, _instance, _eventgroup, ANY_EVENT, - _pending_unsubscription_id)) { - try { - const auto its_callback = std::bind( - &routing_manager_stub_host::on_unsubscribe_ack, - std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), - _offering_client, _service, _instance, - _eventgroup, _pending_unsubscription_id); - io_.post(its_callback); - } catch (const std::exception &e) { - VSOMEIP_ERROR << __func__ << e.what(); - } + }); } - } -} - -void routing_manager_impl::send_subscription( - client_t _offering_client, client_t _subscribing_client, - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, - pending_subscription_id_t _pending_subscription_id) { - if (host_->get_client() == _offering_client) { - auto self = shared_from_this(); - host_->on_subscription(_service, _instance, _eventgroup, - _subscribing_client, true, - [this, self, _service, _instance, - _eventgroup, _subscribing_client, _pending_subscription_id] - (const bool _subscription_accepted) { - try { - if (!_subscription_accepted) { + } else { // service hosted by local client + for (const auto its_client : _clients) { + if (!stub_->send_subscribe(find_local(_offering_client), its_client, + _service, _instance, _eventgroup, _major, ANY_EVENT, _id)) { + try { const auto its_callback = std::bind( &routing_manager_stub_host::on_subscribe_nack, std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), - _subscribing_client, _service, _instance, - _eventgroup, ANY_EVENT, _pending_subscription_id); - io_.post(its_callback); - } else { - const auto its_callback = std::bind( - &routing_manager_stub_host::on_subscribe_ack, - std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), - _subscribing_client, _service, _instance, - _eventgroup, ANY_EVENT, _pending_subscription_id); + its_client, _service, _instance, _eventgroup, + ANY_EVENT, _id); io_.post(its_callback); + } catch (const std::exception &e) { + VSOMEIP_ERROR << __func__ << e.what(); } - } catch (const std::exception &e) { - VSOMEIP_ERROR << __func__ << e.what(); - } - }); - } else { // service hosted by local client - if (!stub_->send_subscribe(find_local(_offering_client), - _subscribing_client, - _service, _instance, _eventgroup, - _major, ANY_EVENT, - _pending_subscription_id)) { - try { - const auto its_callback = std::bind( - &routing_manager_stub_host::on_subscribe_nack, - std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), - _subscribing_client, _service, _instance, - _eventgroup, ANY_EVENT, _pending_subscription_id); - io_.post(its_callback); - } catch (const std::exception &e) { - VSOMEIP_ERROR << __func__ << e.what(); } } } @@ -5056,31 +4048,15 @@ 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); - } + // Clear service_instances_, check whether any service still + // uses this endpoint and clear server endpoint if no service + // remains using it + if (ep_mgr_impl_->remove_instance(_service, _endpoint.get())) { + if (ep_mgr_impl_->remove_server_endpoint( + _endpoint->get_local_port(), _endpoint->is_reliable())) { + // Stop endpoint (close socket) to release its async_handlers! + _endpoint->stop(); } - - // Stop endpoint (close socket) to release its async_handlers! - _endpoint->stop(); } } } @@ -5182,16 +4158,18 @@ void routing_manager_impl::on_security_update_timeout( 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) { + const std::shared_ptr<policy>& _policy, + const std::shared_ptr<payload>& _payload, + const 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); + security::get()->update_security_policy(_uid, _gid, _policy); // determine currently connected clients - std::unordered_set<client_t> its_clients_to_inform = get_connected_clients(); + std::unordered_set<client_t> its_clients_to_inform = ep_mgr_impl_->get_connected_clients(); // add handler pending_security_update_id_t its_id; @@ -5254,13 +4232,13 @@ bool routing_manager_impl::update_security_policy_configuration( } bool routing_manager_impl::remove_security_policy_configuration( - uint32_t _uid, uint32_t _gid, security_update_handler_t _handler) { + uint32_t _uid, uint32_t _gid, const 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); + if (!security::get()->remove_security_policy(_uid, _gid)) { + _handler(security_update_state_e::SU_UNKNOWN_USER_ID); ret = false; } else { // remove policy from cache to prevent sending it to registering clients @@ -5270,7 +4248,7 @@ bool routing_manager_impl::remove_security_policy_configuration( pending_security_update_id_t its_id; // determine currently connected clients - std::unordered_set<client_t> its_clients_to_inform = get_connected_clients(); + std::unordered_set<client_t> its_clients_to_inform = ep_mgr_impl_->get_connected_clients(); if (!its_clients_to_inform.empty()) { its_id = pending_security_update_add(its_clients_to_inform); @@ -5330,14 +4308,14 @@ bool routing_manager_impl::remove_security_policy_configuration( } } else { - _handler(vsomeip::security_update_state_e::SU_UNKNOWN_USER_ID); + _handler(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) { + const 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_++; @@ -5423,4 +4401,96 @@ void routing_manager_impl::on_security_update_response( } } -} // namespace vsomeip +void routing_manager_impl::print_stub_status() const { + stub_->print_endpoint_status(); +} + +void routing_manager_impl::service_endpoint_connected( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, const std::shared_ptr<endpoint>& _endpoint, + bool _unreliable_only) { + + if (!_unreliable_only) { + // Mark only TCP-only and TCP+UDP services available here + // UDP-only services are already marked as available in add_routing_info + on_availability(_service, _instance, true, _major, _minor); + stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, + _major, _minor); + } + + 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(3), ec); + if (!ec) { + its_timer->async_wait( + std::bind(&routing_manager_impl::call_sd_endpoint_connected, + std::static_pointer_cast<routing_manager_impl>( + shared_from_this()), std::placeholders::_1, + _service, _instance, _endpoint, its_timer)); + } else { + VSOMEIP_ERROR << __func__ << " " << ec.message(); + } +} + +void routing_manager_impl::service_endpoint_disconnected( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, const std::shared_ptr<endpoint>& _endpoint) { + (void)_endpoint; + on_availability(_service, _instance, false, _major, _minor); + stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, + _major, _minor); + VSOMEIP_WARNING << __func__ << ": lost connection to remote service: [" + << std::hex << std::setw(4) << std::setfill('0') << _service << "." + << std::hex << std::setw(4) << std::setfill('0') << _instance << "]"; +} + +void +routing_manager_impl::send_unsubscription(client_t _offering_client, + service_t _service, instance_t _instance, + eventgroup_t _eventgroup, major_version_t _major, + const std::set<client_t> &_removed, + remote_subscription_id_t _id) { + + (void)_major; // TODO: Remove completely? + + if (host_->get_client() == _offering_client) { + auto self = shared_from_this(); + for (const auto its_client : _removed) { + host_->on_subscription(_service, _instance, + _eventgroup, its_client, own_uid_, own_gid_, false, + [this, self, _service, _instance, _eventgroup, + its_client, _id, _offering_client] + (const bool _is_accepted) { + (void)_is_accepted; + try { + const auto its_callback = std::bind( + &routing_manager_stub_host::on_unsubscribe_ack, + std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), + its_client, _service, _instance, _eventgroup, _id); + io_.post(its_callback); + } catch (const std::exception &e) { + VSOMEIP_ERROR << __func__ << e.what(); + } + } + ); + } + } else { + for (const auto its_client : _removed) { + if (!stub_->send_unsubscribe(find_local(_offering_client), its_client, + _service, _instance, _eventgroup, ANY_EVENT, _id)) { + try { + const auto its_callback = std::bind( + &routing_manager_stub_host::on_unsubscribe_ack, + std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()), + its_client, _service, _instance, _eventgroup, _id); + io_.post(its_callback); + } catch (const std::exception &e) { + VSOMEIP_ERROR << __func__ << e.what(); + } + } + } + } +} + +} // namespace vsomeip_v3 diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp index d439654..8135c3f 100644 --- a/implementation/routing/src/routing_manager_proxy.cpp +++ b/implementation/routing/src/routing_manager_proxy.cpp @@ -12,26 +12,28 @@ #include <vsomeip/constants.hpp> #include <vsomeip/runtime.hpp> +#include <vsomeip/internal/logger.hpp> #include "../include/event.hpp" #include "../include/routing_manager_host.hpp" #include "../include/routing_manager_proxy.hpp" #include "../../configuration/include/configuration.hpp" -#include "../../configuration/include/internal.hpp" +#include "../../security/include/policy.hpp" +#include "../../security/include/security_impl.hpp" + #include "../../endpoints/include/local_client_endpoint_impl.hpp" #include "../../endpoints/include/local_server_endpoint_impl.hpp" -#include "../../logging/include/logger.hpp" #include "../../message/include/deserializer.hpp" +#include "../../message/include/message_impl.hpp" #include "../../message/include/serializer.hpp" #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 { +namespace vsomeip_v3 { routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host, bool _client_side_logging, @@ -40,8 +42,8 @@ routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host, is_connected_(false), is_started_(false), state_(inner_state_type_e::ST_DEREGISTERED), - sender_(0), - receiver_(0), + sender_(nullptr), + receiver_(nullptr), register_application_timer_(io_), logger_(logger::get()), request_debounce_timer_ (io_), @@ -55,31 +57,20 @@ routing_manager_proxy::~routing_manager_proxy() { } void routing_manager_proxy::init() { - routing_manager_base::init(); + routing_manager_base::init(std::make_shared<endpoint_manager_base>(this, io_, configuration_)); { std::lock_guard<std::mutex> its_lock(sender_mutex_); - sender_ = create_local(VSOMEIP_ROUTING_CLIENT); + sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT); } - - init_receiver(); } void routing_manager_proxy::start() { is_started_ = true; - - if (!receiver_) { - // application has been stopped and started again - init_receiver(); - } - if (receiver_) { - receiver_->start(); - } - { std::lock_guard<std::mutex> its_lock(sender_mutex_); if (!sender_) { // application has been stopped and started again - sender_ = create_local(VSOMEIP_ROUTING_CLIENT); + sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT); } if (sender_) { sender_->start(); @@ -135,7 +126,7 @@ void routing_manager_proxy::stop() { sender_ = nullptr; } - for (auto client: get_connected_clients()) { + for (auto client: ep_mgr_->get_connected_clients()) { if (client != VSOMEIP_ROUTING_CLIENT) { remove_local(client, true); } @@ -153,12 +144,14 @@ void routing_manager_proxy::stop() { #endif } -const std::shared_ptr<configuration> routing_manager_proxy::get_configuration() const { +std::shared_ptr<configuration> routing_manager_proxy::get_configuration() const { return host_->get_configuration(); } -bool routing_manager_proxy::offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor) { +bool routing_manager_proxy::offer_service(client_t _client, + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) { + if(!routing_manager_base::offer_service(_client, _service, _instance, _major, _minor)) { VSOMEIP_WARNING << "routing_manager_proxy::offer_service," << "routing_manager_base::offer_service returned false"; @@ -168,15 +161,15 @@ bool routing_manager_proxy::offer_service(client_t _client, service_t _service, if (state_ == inner_state_type_e::ST_REGISTERED) { send_offer_service(_client, _service, _instance, _major, _minor); } - service_data_t offer = { _service, _instance, _major, _minor, false }; + service_data_t offer = { _service, _instance, _major, _minor }; pending_offers_.insert(offer); } return true; } void routing_manager_proxy::send_offer_service(client_t _client, - service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor) { + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) { (void)_client; byte_t its_command[VSOMEIP_OFFER_SERVICE_COMMAND_SIZE]; @@ -207,6 +200,7 @@ void routing_manager_proxy::send_offer_service(client_t _client, void routing_manager_proxy::stop_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { + (void)_client; routing_manager_base::stop_offer_service(_client, _service, _instance, _major, _minor); @@ -256,14 +250,14 @@ void routing_manager_proxy::stop_offer_service(client_t _client, } void routing_manager_proxy::request_service(client_t _client, - service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, bool _use_exclusive_proxy) { - routing_manager_base::request_service(_client, _service, _instance, _major, - _minor, _use_exclusive_proxy); + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor) { + routing_manager_base::request_service(_client, + _service, _instance, _major, _minor); { std::lock_guard<std::mutex> its_lock(state_mutex_); size_t request_debouncing_time = configuration_->get_request_debouncing(host_->get_name()); - service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy }; + service_data_t request = { _service, _instance, _major, _minor }; if (!request_debouncing_time) { if (state_ == inner_state_type_e::ST_REGISTERED) { std::set<service_data_t> requests; @@ -325,10 +319,11 @@ void routing_manager_proxy::release_service(client_t _client, void routing_manager_proxy::register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::set<eventgroup_t> &_eventgroups, - bool _is_field, + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, const event_type_e _type, + reliability_type_e _reliability, std::chrono::milliseconds _cycle, bool _change_resets_cycle, - epsilon_change_func_t _epsilon_change_func, + bool _update_on_change, epsilon_change_func_t _epsilon_change_func, bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) { (void)_is_shadow; (void)_is_cache_placeholder; @@ -336,8 +331,9 @@ void routing_manager_proxy::register_event(client_t _client, const event_data_t registration = { _service, _instance, - _event, - _is_field, + _notifier, + _type, + _reliability, _is_provided, _eventgroups }; @@ -351,36 +347,29 @@ void routing_manager_proxy::register_event(client_t _client, } } if (is_first || _is_provided) { - routing_manager_base::register_event(_client, _service, _instance, - _event,_eventgroups, _is_field, - _cycle, _change_resets_cycle, - _epsilon_change_func, - _is_provided); + routing_manager_base::register_event(_client, + _service, _instance, + _notifier, + _eventgroups, _type, _reliability, + _cycle, _change_resets_cycle, _update_on_change, + _epsilon_change_func, + _is_provided); } { std::lock_guard<std::mutex> its_lock(state_mutex_); if (state_ == inner_state_type_e::ST_REGISTERED && is_first) { send_register_event(client_, _service, _instance, - _event, _eventgroups, _is_field, _is_provided); + _notifier, _eventgroups, _type, _reliability, _is_provided); } } - - if(_is_provided) { - VSOMEIP_INFO << "REGISTER EVENT(" - << 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') << _event - << ":is_provider=" << _is_provided << "]"; - } } void routing_manager_proxy::unregister_event(client_t _client, - service_t _service, instance_t _instance, event_t _event, + service_t _service, instance_t _instance, event_t _notifier, bool _is_provided) { routing_manager_base::unregister_event(_client, _service, _instance, - _event, _is_provided); + _notifier, _is_provided); { std::lock_guard<std::mutex> its_lock(state_mutex_); @@ -398,8 +387,8 @@ void routing_manager_proxy::unregister_event(client_t _client, sizeof(_service)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, sizeof(_instance)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_event, - sizeof(_event)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_notifier, + sizeof(_notifier)); its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = static_cast<byte_t>(_is_provided); @@ -414,7 +403,7 @@ void routing_manager_proxy::unregister_event(client_t _client, while (it != pending_event_registrations_.end()) { if (it->service_ == _service && it->instance_ == _instance - && it->event_ == _event) { + && it->notifier_ == _notifier) { break; } it++; @@ -433,12 +422,15 @@ bool routing_manager_proxy::is_field(service_t _service, instance_t _instance, return false; } -void routing_manager_proxy::subscribe(client_t _client, service_t _service, +void routing_manager_proxy::subscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, - event_t _event, subscription_type_e _subscription_type) { + event_t _event) { + (void)_uid; + (void)_gid; { + credentials_t its_credentials = std::make_pair(own_uid_, own_gid_); if (_event == ANY_EVENT) { - if (!is_subscribe_to_any_event_allowed(_client, _service, _instance, _eventgroup)) { + if (!is_subscribe_to_any_event_allowed(its_credentials, _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 " @@ -447,8 +439,11 @@ void routing_manager_proxy::subscribe(client_t _client, service_t _service, return; } } else { - if (!configuration_->is_client_allowed(_client, _service, - _instance, _event)) { + auto its_security = security_impl::get(); + if (!its_security) + return; + if (!its_security->is_client_allowed(own_uid_, own_gid_, + _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 " @@ -460,18 +455,16 @@ void routing_manager_proxy::subscribe(client_t _client, service_t _service, 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, - _event, _subscription_type); + send_subscribe(_client, _service, _instance, _eventgroup, _major, _event ); } - subscription_data_t subscription = { _service, _instance, _eventgroup, _major, - _event, _subscription_type}; + subscription_data_t subscription = { _service, _instance, _eventgroup, _major, _event, _uid, _gid}; pending_subscriptions_.insert(subscription); } } void routing_manager_proxy::send_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) { + event_t _event) { (void)_client; byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; @@ -492,14 +485,12 @@ void routing_manager_proxy::send_subscribe(client_t _client, service_t _service, its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major; std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_event, sizeof(_event)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_subscription_type, - sizeof(_subscription_type)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &DEFAULT_SUBSCRIPTION, - sizeof(DEFAULT_SUBSCRIPTION)); // local subscription + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], + &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID)); client_t target_client = find_local_client(_service, _instance); if (target_client != VSOMEIP_ROUTING_CLIENT) { - auto its_target = find_or_create_local(target_client); + auto its_target = ep_mgr_->find_or_create_local(target_client); its_target->send(its_command, sizeof(its_command)); } else { std::lock_guard<std::mutex> its_lock(sender_mutex_); @@ -511,7 +502,7 @@ void routing_manager_proxy::send_subscribe(client_t _client, service_t _service, void routing_manager_proxy::send_subscribe_nack(client_t _subscriber, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - event_t _event, pending_subscription_id_t _subscription_id) { + event_t _event, remote_subscription_id_t _id) { byte_t its_command[VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE; @@ -532,12 +523,12 @@ void routing_manager_proxy::send_subscribe_nack(client_t _subscriber, sizeof(_subscriber)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event, sizeof(_event)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], - &_subscription_id, sizeof(_subscription_id)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &_id, + sizeof(_id)); if (_subscriber != VSOMEIP_ROUTING_CLIENT - && _subscription_id == DEFAULT_SUBSCRIPTION) { - auto its_target = find_local(_subscriber); + && _id == PENDING_SUBSCRIPTION_ID) { + auto its_target = ep_mgr_->find_local(_subscriber); if (its_target) { its_target->send(its_command, sizeof(its_command)); return; @@ -553,7 +544,7 @@ void routing_manager_proxy::send_subscribe_nack(client_t _subscriber, void routing_manager_proxy::send_subscribe_ack(client_t _subscriber, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - event_t _event, pending_subscription_id_t _subscription_id) { + event_t _event, remote_subscription_id_t _id) { byte_t its_command[VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE; @@ -574,12 +565,12 @@ void routing_manager_proxy::send_subscribe_ack(client_t _subscriber, sizeof(_subscriber)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event, sizeof(_event)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], - &_subscription_id, sizeof(_subscription_id)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &_id, + sizeof(_id)); if (_subscriber != VSOMEIP_ROUTING_CLIENT - && _subscription_id == DEFAULT_SUBSCRIPTION) { - auto its_target = find_local(_subscriber); + && _id == PENDING_SUBSCRIPTION_ID) { + auto its_target = ep_mgr_->find_local(_subscriber); if (its_target) { its_target->send(its_command, sizeof(its_command)); return; @@ -593,9 +584,11 @@ void routing_manager_proxy::send_subscribe_ack(client_t _subscriber, } } -void routing_manager_proxy::unsubscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, event_t _event) { +void routing_manager_proxy::unsubscribe(client_t _client, uid_t _uid, gid_t _gid, + service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) { (void)_client; + (void)_uid; + (void)_gid; { std::lock_guard<std::mutex> its_lock(state_mutex_); remove_pending_subscription(_service, _instance, _eventgroup, _event); @@ -618,10 +611,10 @@ void routing_manager_proxy::unsubscribe(client_t _client, service_t _service, sizeof(_eventgroup)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event, sizeof(_event)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &DEFAULT_SUBSCRIPTION, - sizeof(DEFAULT_SUBSCRIPTION)); // is_local + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], + &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID)); - auto its_target = find_local(_service, _instance); + auto its_target = ep_mgr_->find_local(_service, _instance); if (its_target) { its_target->send(its_command, sizeof(its_command)); } else { @@ -636,13 +629,14 @@ void routing_manager_proxy::unsubscribe(client_t _client, service_t _service, bool routing_manager_proxy::send(client_t _client, const byte_t *_data, length_t _size, instance_t _instance, - bool _flush, bool _reliable, client_t _bound_client, - bool _is_valid_crc, + credentials_t _credentials, + uint8_t _status_check, bool _sent_from_remote) { (void)_client; (void)_bound_client; + (void)_credentials; (void)_sent_from_remote; bool is_sent(false); bool has_remote_subscribers(false); @@ -695,7 +689,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, client_t its_client = find_local_client(its_service, _instance); if (its_client != VSOMEIP_ROUTING_CLIENT) { if (is_client_known(its_client)) { - its_target = find_or_create_local(its_client); + its_target = ep_mgr_->find_or_create_local(its_client); } } } else if (!utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) { @@ -705,18 +699,18 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, _data[VSOMEIP_CLIENT_POS_MAX]); if (its_client != VSOMEIP_ROUTING_CLIENT) { if (is_client_known(its_client)) { - its_target = find_or_create_local(its_client); + its_target = ep_mgr_->find_or_create_local(its_client); } } } else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) && _client == VSOMEIP_ROUTING_CLIENT) { // notify has_remote_subscribers = send_local_notification(get_client(), _data, _size, - _instance, _flush, _reliable, _is_valid_crc); + _instance, _reliable, _status_check); } else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) && _client != VSOMEIP_ROUTING_CLIENT) { // notify_one - its_target = find_local(_client); + its_target = ep_mgr_->find_local(_client); if (its_target) { #ifdef USE_DLT const uint16_t its_data_size @@ -728,7 +722,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, _data, its_data_size); #endif return send_local(its_target, get_client(), _data, _size, - _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc); + _instance, _reliable, VSOMEIP_SEND, _status_check); } } // If no direct endpoint could be found @@ -775,35 +769,32 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, if (send) { is_sent = send_local(its_target, (command == VSOMEIP_NOTIFY_ONE ? _client : get_client()), - _data, _size, _instance, _flush, _reliable, command, _is_valid_crc); + _data, _size, _instance, _reliable, command, _status_check); } } return (is_sent); } -bool routing_manager_proxy::send_to( +bool routing_manager_proxy::send_to(const client_t _client, const std::shared_ptr<endpoint_definition> &_target, - std::shared_ptr<message> _message, - bool _flush) { + std::shared_ptr<message> _message) { + (void)_client; (void)_target; (void)_message; - (void)_flush; return (false); } bool routing_manager_proxy::send_to( const std::shared_ptr<endpoint_definition> &_target, - const byte_t *_data, uint32_t _size, instance_t _instance, - bool _flush) { + const byte_t *_data, uint32_t _size, instance_t _instance) { (void)_target; (void)_data; (void)_size; (void)_instance; - (void)_flush; return (false); } -void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) { +void routing_manager_proxy::on_connect(const std::shared_ptr<endpoint>& _endpoint) { _endpoint->set_connected(true); _endpoint->set_established(true); { @@ -813,14 +804,10 @@ void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) { } } is_connected_ = true; - if (is_connected_ && is_started_) { - VSOMEIP_INFO << std::hex << "Client " << client_ - << " successfully connected to routing ~> registering.."; - register_application(); - } + assign_client(); } -void routing_manager_proxy::on_disconnect(std::shared_ptr<endpoint> _endpoint) { +void routing_manager_proxy::on_disconnect(const std::shared_ptr<endpoint>& _endpoint) { { std::lock_guard<std::mutex> its_lock(sender_mutex_); is_connected_ = !(_endpoint == sender_); @@ -833,29 +820,10 @@ void routing_manager_proxy::on_disconnect(std::shared_ptr<endpoint> _endpoint) { } } -void routing_manager_proxy::on_error( - const byte_t *_data, length_t _length, endpoint *_receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port) { - - // Implement me when needed - - (void)(_data); - (void)(_length); - (void)(_receiver); - (void)(_remote_address); - (void)(_remote_port); -} - -void routing_manager_proxy::release_port(uint16_t _port, bool _reliable) { - (void)_port; - (void)_reliable; - // intentionally empty -} - void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, endpoint *_receiver, const boost::asio::ip::address &_destination, client_t _bound_client, + credentials_t _credentials, const boost::asio::ip::address &_remote_address, std::uint16_t _remote_port) { (void)_receiver; @@ -879,10 +847,16 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, major_version_t its_major; client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host()); client_t its_subscriber; - bool its_reliable; - pending_subscription_id_t its_subscription_id(DEFAULT_SUBSCRIPTION); + remote_subscription_id_t its_subscription_id(PENDING_SUBSCRIPTION_ID); std::uint32_t its_remote_subscriber_count(0); + std::uint32_t its_sender_uid = std::get<0>(_credentials); + std::uint32_t its_sender_gid = std::get<1>(_credentials); + + auto its_security = security_impl::get(); + if (!its_security) + return; + if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) { its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], @@ -891,7 +865,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, sizeof(its_length)); bool message_from_routing(false); - if (configuration_->is_security_enabled()) { + if (its_security->is_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); @@ -899,7 +873,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, message_from_routing = (its_client == routing_host_id); } - if (configuration_->is_security_enabled() && !message_from_routing && + if (its_security->is_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 @@ -918,13 +892,13 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, } instance_t its_instance; bool its_reliable; - bool its_is_valid_crc; + uint8_t its_check_status; 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_valid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS], - sizeof(its_is_valid_crc)); + std::memcpy(&its_check_status, &_data[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS], + sizeof(its_check_status)); // reduce by size of instance, flush, reliable, client and is_valid_crc flag const std::uint32_t its_message_size = its_length - @@ -943,14 +917,17 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, auto a_deserializer = get_deserializer(); a_deserializer->set_data(&_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS], its_message_size); - std::shared_ptr<message> its_message(a_deserializer->deserialize_message()); + std::shared_ptr<message_impl> its_message(a_deserializer->deserialize_message()); a_deserializer->reset(); put_deserializer(a_deserializer); if (its_message) { its_message->set_instance(its_instance); its_message->set_reliable(its_reliable); - its_message->set_is_valid_crc(its_is_valid_crc); + its_message->set_check_result(its_check_status); + its_message->set_uid(std::get<0>(_credentials)); + its_message->set_gid(std::get<1>(_credentials)); + if (!message_from_routing) { if (utility::is_notification(its_message->get_message_type())) { if (!is_response_allowed(_bound_client, its_message->get_service(), @@ -964,7 +941,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, << " ~> Skip message!"; return; } else { - if (!configuration_->is_client_allowed(get_client(), its_message->get_service(), + if (!its_security->is_client_allowed(own_uid_, own_gid_, + 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: " @@ -978,7 +956,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, cache_event_payload(its_message); } } else if (utility::is_request(its_message->get_message_type())) { - if (configuration_->is_security_enabled() + if (its_security->is_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') @@ -990,8 +968,9 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, return; } - if (!configuration_->is_client_allowed(its_message->get_client(), - its_message->get_service(), its_message->get_instance(), its_message->get_method())) { + if (!its_security->is_client_allowed(its_sender_uid, its_sender_gid, + 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 " @@ -1012,7 +991,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, << " ~> Skip message!"; return; } else { - if (!configuration_->is_client_allowed(get_client(), its_message->get_service(), + if (!its_security->is_client_allowed(own_uid_, own_gid_, + 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: " @@ -1026,7 +1006,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, } } } else { - if (!configuration_->is_remote_client_allowed()) { + if (!its_security->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() @@ -1042,7 +1022,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, // 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(), + if (!its_security->is_client_allowed(own_uid_, own_gid_, + 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: " @@ -1068,6 +1049,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, static_cast<std::uint16_t>(its_message_size)); } #endif + host_->on_message(std::move(its_message)); } else { VSOMEIP_ERROR << "Routing proxy: on_message: " @@ -1076,12 +1058,23 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, break; } + case VSOMEIP_ASSIGN_CLIENT_ACK: { + if (_size != VSOMEIP_ASSIGN_CLIENT_ACK_COMMAND_SIZE) { + VSOMEIP_WARNING << "Received a VSOMEIP_ASSIGN_CLIENT_ACK command with wrong size ~> skip!"; + break; + } + client_t its_assigned_client(VSOMEIP_CLIENT_UNSET); + std::memcpy(&its_assigned_client, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(client_)); + on_client_assign_ack(its_assigned_client); + break; + } case VSOMEIP_ROUTING_INFO: 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) { + if (!its_security->is_enabled() || message_from_routing) { on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length); } else { VSOMEIP_WARNING << "routing_manager_proxy::on_message: " @@ -1116,18 +1109,20 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, sizeof(its_major)); std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], sizeof(its_event)); - std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10], + std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9], sizeof(its_subscription_id)); { std::unique_lock<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_); - if (its_subscription_id != DEFAULT_SUBSCRIPTION) { + if (its_subscription_id != PENDING_SUBSCRIPTION_ID) { its_lock.unlock(); +#ifdef VSOMEIP_ENABLE_COMPAT routing_manager_base::set_incoming_subscription_state(its_client, its_service, its_instance, its_eventgroup, its_event, subscription_state_e::IS_SUBSCRIBING); +#endif // Remote subscriber: Notify routing manager initially + count subscribes auto self = shared_from_this(); host_->on_subscription(its_service, its_instance, its_eventgroup, - its_client, true, + its_client, its_sender_uid, its_sender_gid, true, [this, self, its_client, its_service, its_instance, its_eventgroup, its_event, its_subscription_id, its_major] (const bool _subscription_accepted){ @@ -1145,8 +1140,9 @@ 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); } +#ifdef VSOMEIP_ENABLE_COMPAT send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client, true); - +#endif std::uint32_t its_count = get_remote_subscriber_count( its_service, its_instance, its_eventgroup, true); VSOMEIP_INFO << "SUBSCRIBE(" @@ -1156,17 +1152,18 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << ":" << std::hex << std::setw(4) << std::setfill('0') << its_event << ":" << std::dec << (uint16_t)its_major << "]" - << (bool)(its_subscription_id != DEFAULT_SUBSCRIPTION) << " " + << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " " << std::dec << its_count; - +#ifdef VSOMEIP_ENABLE_COMPAT routing_manager_base::erase_incoming_subscription_state(its_client, its_service, its_instance, its_eventgroup, its_event); +#endif }); } else if (is_client_known(its_client)) { its_lock.unlock(); if (!message_from_routing) { if (its_event == ANY_EVENT) { - if (!is_subscribe_to_any_event_allowed(its_client, its_service, its_instance, its_eventgroup)) { + if (!is_subscribe_to_any_event_allowed(_credentials, 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 " @@ -1175,8 +1172,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, return; } } else { - if (!configuration_->is_client_allowed(its_client, - its_service, its_instance, its_event)) { + if (!its_security->is_client_allowed(its_sender_uid, its_sender_gid, + 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 " @@ -1186,7 +1183,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, } } } else { - if (!configuration_->is_remote_client_allowed()) { + if (!its_security->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" @@ -1201,38 +1198,42 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, } // Local & already known subscriber: create endpoint + send (N)ACK + insert subscription +#ifdef VSOMEIP_ENABLE_COMPAT 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); +#endif + (void) ep_mgr_->find_or_create_local(its_client); auto self = shared_from_this(); host_->on_subscription(its_service, its_instance, - its_eventgroup, its_client, true, - [this, self, its_client, its_service, its_instance, its_eventgroup, - its_event, its_major] + its_eventgroup, its_client, its_sender_uid, its_sender_gid, true, + [this, self, its_client, its_sender_uid, its_sender_gid, its_service, + its_instance, its_eventgroup, its_event, its_major] (const bool _subscription_accepted) { if (!_subscription_accepted) { - send_subscribe_nack(its_client, its_service, - its_instance, its_eventgroup, its_event, DEFAULT_SUBSCRIPTION); + send_subscribe_nack(its_client, its_service, its_instance, + its_eventgroup, its_event, PENDING_SUBSCRIPTION_ID); } else { send_subscribe_ack(its_client, its_service, its_instance, - its_eventgroup, its_event, DEFAULT_SUBSCRIPTION); - routing_manager_base::subscribe(its_client, its_service, its_instance, - its_eventgroup, its_major, its_event, - subscription_type_e::SU_RELIABLE_AND_UNRELIABLE); + its_eventgroup, its_event, PENDING_SUBSCRIPTION_ID); + routing_manager_base::subscribe(its_client, its_sender_uid, its_sender_gid, + its_service, its_instance, its_eventgroup, its_major, its_event); +#ifdef VSOMEIP_ENABLE_COMPAT send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client); +#endif } +#ifdef VSOMEIP_ENABLE_COMPAT routing_manager_base::erase_incoming_subscription_state(its_client, its_service, its_instance, its_eventgroup, its_event); +#endif }); } else { // Local & not yet known subscriber ~> set pending until subscriber gets known! subscription_data_t subscription = { its_service, its_instance, - its_eventgroup, its_major, its_event, - subscription_type_e::SU_RELIABLE_AND_UNRELIABLE}; + its_eventgroup, its_major, its_event, its_sender_uid, its_sender_gid }; pending_incoming_subscripitons_[its_client].insert(subscription); } } - if (its_subscription_id == DEFAULT_SUBSCRIPTION) { // local subscription + if (its_subscription_id == PENDING_SUBSCRIPTION_ID) { // local subscription VSOMEIP_INFO << "SUBSCRIBE(" << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): [" << std::hex << std::setw(4) << std::setfill('0') << its_service << "." @@ -1258,16 +1259,16 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, sizeof(its_event)); std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8], sizeof(its_subscription_id)); - host_->on_subscription(its_service, its_instance, its_eventgroup, its_client, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; }); - if (its_subscription_id == DEFAULT_SUBSCRIPTION) { + host_->on_subscription(its_service, its_instance, its_eventgroup, its_client, its_sender_uid, its_sender_gid, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; }); + if (its_subscription_id == PENDING_SUBSCRIPTION_ID) { // Local subscriber: withdraw subscription - routing_manager_base::unsubscribe(its_client, its_service, its_instance, its_eventgroup, its_event); + routing_manager_base::unsubscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance, its_eventgroup, its_event); } else { // Remote subscriber: withdraw subscription only if no more remote subscriber exists its_remote_subscriber_count = get_remote_subscriber_count(its_service, its_instance, its_eventgroup, false); if (!its_remote_subscriber_count) { - routing_manager_base::unsubscribe(VSOMEIP_ROUTING_CLIENT, its_service, + routing_manager_base::unsubscribe(VSOMEIP_ROUTING_CLIENT, ANY_UID, ANY_GID, its_service, its_instance, its_eventgroup, its_event); } send_unsubscribe_ack(its_service, its_instance, its_eventgroup, @@ -1279,7 +1280,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "." << std::hex << std::setw(4) << std::setfill('0') << its_event << "] " - << (bool)(its_subscription_id != DEFAULT_SUBSCRIPTION) << " " + << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " " << std::dec << its_remote_subscriber_count; break; @@ -1333,30 +1334,12 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, << std::hex << std::setw(4) << std::setfill('0') << its_event << "]"; break; - case VSOMEIP_ID_REQUEST: - if (_size < VSOMEIP_ID_REQUEST_COMMAND_SIZE) { - VSOMEIP_WARNING << "Received a VSOMEIP_ID_REQUEST command with wrong size ~> skip!"; - break; - } - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_major)); - std::memcpy(&its_reliable, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], - sizeof(its_reliable)); - - send_identify_request(its_service, its_instance, its_major, its_reliable); - - break; - case VSOMEIP_OFFERED_SERVICES_RESPONSE: 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) { + if (!its_security->is_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() @@ -1385,7 +1368,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY command with wrong size -> skip!"; break; } - if (!configuration_->is_security_enabled() || message_from_routing) { + if (!its_security->is_enabled() || message_from_routing) { pending_security_update_id_t its_update_id(0); uint32_t its_uid(0); uint32_t its_gid(0); @@ -1399,10 +1382,10 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, 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); + its_security->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); + if (its_security->is_policy_update_allowed(its_uid, its_policy)) { + its_security->update_security_policy(its_uid, its_gid, its_policy); send_update_security_policy_response(its_update_id); } } else { @@ -1418,10 +1401,10 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _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) { + if (!its_security->is_enabled() || message_from_routing) { pending_security_update_id_t its_update_id(0); - uint32_t its_uid(0xffffffff); - uint32_t its_gid(0xffffffff); + uint32_t its_uid(ANY_UID); + uint32_t its_gid(ANY_GID); std::memcpy(&its_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(pending_security_update_id_t)); @@ -1429,8 +1412,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, 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); + if (its_security->is_policy_removal_allowed(its_uid)) { + its_security->remove_security_policy(its_uid, its_gid); send_remove_security_policy_response(its_update_id); } } else { @@ -1447,7 +1430,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_DISTRIBUTE_SECURITY_POLICIES command with wrong size -> skip!"; break; } - if (!configuration_->is_security_enabled() || message_from_routing) { + if (!its_security->is_enabled() || message_from_routing) { uint32_t its_policy_count(0); uint32_t its_policy_size(0); const byte_t* buffer_ptr = 0; @@ -1471,9 +1454,9 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, 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); + if (its_security->parse_policy(buffer_ptr, its_policy_size, its_uid, its_gid, its_policy)) { + if (its_security->is_policy_update_allowed(its_uid, its_policy)) { + its_security->update_security_policy(its_uid, its_gid, its_policy); } } else { VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client() << " could not parse policy!"; @@ -1496,7 +1479,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_CREDENTIALS command with wrong size -> skip!"; break; } - if (!configuration_->is_security_enabled() || message_from_routing) { + if (!its_security->is_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() @@ -1521,6 +1504,9 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; VSOMEIP_INFO << msg.str(); #endif + auto its_security = security_impl::get(); + if (!its_security) + return; uint32_t i = 0; while (i + sizeof(uint32_t) + sizeof(routing_info_entry_e) <= _size) { @@ -1550,10 +1536,10 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, } if (its_client == get_client()) { VSOMEIP_INFO << std::hex << "Application/Client " << get_client() - << " is registered."; + << " (" << host_->get_name() << ") is registered."; #ifndef _WIN32 - if (!check_credentials(get_client(), getuid(), getgid())) { + if (!its_security->check_credentials(get_client(), own_uid_, own_gid_)) { 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!"; @@ -1583,9 +1569,9 @@ 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); + its_security->remove_client_to_uid_gid_mapping(its_client); VSOMEIP_INFO << std::hex << "Application/Client " << get_client() - << " is deregistered."; + << " (" << host_->get_name() << ") is deregistered."; // inform host about its own registration state changes host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED)); @@ -1684,6 +1670,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, client_t client_id_; major_version_t major_; event_t event_; + uid_t uid_; + gid_t gid_; }; std::lock_guard<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_); std::forward_list<struct subscription_info> subscription_actions; @@ -1697,35 +1685,41 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, subscription_actions.push_front( { subscription.service_, subscription.instance_, subscription.eventgroup_, client, - subscription.major_, subscription.event_ }); + subscription.major_, subscription.event_, + subscription.uid_, subscription.gid_ }); } } } } for (const subscription_info &si : subscription_actions) { +#ifdef VSOMEIP_ENABLE_COMPAT 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_); +#endif + (void) ep_mgr_->find_or_create_local(si.client_id_); auto self = shared_from_this(); host_->on_subscription( si.service_id_, si.instance_id_, si.eventgroup_id_, - si.client_id_, true, + si.client_id_, si.uid_, si.gid_, true, [this, self, si](const bool _subscription_accepted) { if (!_subscription_accepted) { send_subscribe_nack(si.client_id_, si.service_id_, - si.instance_id_, si.eventgroup_id_, si.event_, DEFAULT_SUBSCRIPTION); + si.instance_id_, si.eventgroup_id_, si.event_, PENDING_SUBSCRIPTION_ID); } else { - routing_manager_base::subscribe(si.client_id_, + routing_manager_base::subscribe(si.client_id_, si.uid_, si.gid_, si.service_id_, si.instance_id_, si.eventgroup_id_, - si.major_, si.event_, - subscription_type_e::SU_RELIABLE_AND_UNRELIABLE); + si.major_, si.event_); send_subscribe_ack(si.client_id_, si.service_id_, - si.instance_id_, si.eventgroup_id_, si.event_, DEFAULT_SUBSCRIPTION); + si.instance_id_, si.eventgroup_id_, si.event_, PENDING_SUBSCRIPTION_ID); +#ifdef VSOMEIP_ENABLE_COMPAT send_pending_notify_ones(si.service_id_, si.instance_id_, si.eventgroup_id_, si.client_id_); +#endif } +#ifdef VSOMEIP_ENABLE_COMPAT routing_manager_base::erase_incoming_subscription_state(si.client_id_, si.service_id_, si.instance_id_, si.eventgroup_id_, si.event_); +#endif { std::lock_guard<std::recursive_mutex> its_lock2(incoming_subscriptions_mutex_); pending_incoming_subscripitons_.erase(si.client_id_); @@ -1788,6 +1782,10 @@ void routing_manager_proxy::on_offered_services_info(const byte_t *_data, } void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clients) { + auto its_security = security_impl::get(); + if (!its_security) + return; + // inform host about its own registration state changes host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED)); @@ -1810,7 +1808,7 @@ void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clien <<": Reconnecting to routing manager."; #ifndef _WIN32 - if (!check_credentials(get_client(), getuid(), getgid())) { + if (!its_security->check_credentials(get_client(), own_uid_, own_gid_)) { 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!"; @@ -1828,6 +1826,44 @@ void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clien } } +void routing_manager_proxy::assign_client() { + std::vector<byte_t> its_command; + + std::string its_name(host_->get_name()); + uint32_t its_size(static_cast<uint32_t>(its_name.size())); + its_command.resize(7 + its_name.size()); + + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ASSIGN_CLIENT; + 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 (0 < its_name.size()) + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], its_name.c_str(), + its_name.size()); + + std::lock_guard<std::mutex> its_state_lock(state_mutex_); + if (is_connected_) { + std::lock_guard<std::mutex> its_lock(sender_mutex_); + if (sender_) { + if (state_ != inner_state_type_e::ST_DEREGISTERED) + return; + state_ = inner_state_type_e::ST_ASSIGNING; + + sender_->send(&its_command[0], static_cast<uint32_t>(its_command.size())); + + boost::system::error_code ec; + register_application_timer_.cancel(ec); + register_application_timer_.expires_from_now(std::chrono::milliseconds(10000)); + register_application_timer_.async_wait( + std::bind( + &routing_manager_proxy::assign_client_timeout_cbk, + std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()), + std::placeholders::_1)); + } + } +} + void routing_manager_proxy::register_application() { byte_t its_command[] = { VSOMEIP_REGISTER_APPLICATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -1836,12 +1872,9 @@ void routing_manager_proxy::register_application() { sizeof(client_)); if (is_connected_) { - std::lock_guard<std::mutex> its_state_lock(state_mutex_); std::lock_guard<std::mutex> its_lock(sender_mutex_); if (sender_) { - { - state_ = inner_state_type_e::ST_REGISTERING; - } + state_ = inner_state_type_e::ST_REGISTERING; sender_->send(its_command, sizeof(its_command)); register_application_timer_.cancel(); @@ -1898,32 +1931,31 @@ void routing_manager_proxy::send_request_services(std::set<service_data_t>& _req std::vector<byte_t> its_command(its_size + VSOMEIP_COMMAND_HEADER_SIZE); its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(std::uint32_t)); + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], + &client_, sizeof(client_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], + &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)); + uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + + sizeof(major_version_t) + sizeof(minor_version_t)); - int i = 0; + unsigned int i = 0; for (auto its_service : _requests) { - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)], &its_service.service_, - sizeof(its_service.service_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)], &its_service.instance_, - sizeof(its_service.instance_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)], + &its_service.service_, sizeof(its_service.service_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)], + &its_service.instance_, sizeof(its_service.instance_)); its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4 + (i * entry_size)] = its_service.major_; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)], &its_service.minor_, - sizeof(its_service.minor_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9 + (i * entry_size)], &its_service.use_exclusive_proxy_, - sizeof(its_service.use_exclusive_proxy_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)], + &its_service.minor_, sizeof(its_service.minor_)); ++i; } { std::lock_guard<std::mutex> its_lock(sender_mutex_); if (sender_) { - sender_->send(&its_command[0], static_cast<std::uint32_t>(its_size + VSOMEIP_COMMAND_HEADER_SIZE)); + sender_->send(&its_command[0], + static_cast<std::uint32_t>(its_size + VSOMEIP_COMMAND_HEADER_SIZE)); } } } @@ -1955,8 +1987,10 @@ void routing_manager_proxy::send_release_service(client_t _client, service_t _se void routing_manager_proxy::send_register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::set<eventgroup_t> &_eventgroups, - bool _is_field, bool _is_provided) { + event_t _notifier, + const std::set<eventgroup_t> &_eventgroups, const event_type_e _type, + reliability_type_e _reliability, + bool _is_provided) { std::size_t its_eventgroups_size = (_eventgroups.size() * sizeof(eventgroup_t)) + VSOMEIP_REGISTER_EVENT_COMMAND_SIZE; @@ -1978,14 +2012,16 @@ void routing_manager_proxy::send_register_event(client_t _client, sizeof(_service)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, sizeof(_instance)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_event, - sizeof(_event)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_notifier, + sizeof(_notifier)); its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] - = static_cast<byte_t>(_is_field); + = static_cast<byte_t>(_type); its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7] = static_cast<byte_t>(_is_provided); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8] + = static_cast<byte_t>(_reliability); - std::size_t i = 8; + std::size_t i = 9; for (auto eg : _eventgroups) { std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + i], &eg, sizeof(eventgroup_t)); @@ -1999,22 +2035,38 @@ void routing_manager_proxy::send_register_event(client_t _client, } } + if (_is_provided) { + VSOMEIP_INFO << "REGISTER EVENT(" + << 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') << _notifier + << ":is_provider=" << _is_provided << "]"; + } + delete[] its_command; } void routing_manager_proxy::on_subscribe_ack(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) { (void)_client; +#if 0 + VSOMEIP_ERROR << "routing_manager_proxy::" << __func__ + << "(" << std::hex << host_->get_client() << "):" + << "event=" + << std::hex << _service << "." + << std::hex << _instance << "." + << std::hex << _eventgroup << "." + << std::hex << _event; +#endif if (_event == ANY_EVENT) { auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - for (auto its_event : its_eventgroup->get_events()) { - host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/); + 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_error(_service, _instance, _eventgroup, 0x0 /*OK*/); host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/); } } @@ -2025,41 +2077,15 @@ void routing_manager_proxy::on_subscribe_nack(client_t _client, if (_event == ANY_EVENT) { auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - for (auto its_event : its_eventgroup->get_events()) { - host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/); + for (const auto& its_event : its_eventgroup->get_events()) { host_->on_subscription_status(_service, _instance, _eventgroup, its_event->get_event(), 0x7 /*Rejected*/); } } } else { - host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/); host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/); } } -void routing_manager_proxy::on_identify_response(client_t _client, service_t _service, - instance_t _instance, bool _reliable) { - static const uint32_t size = VSOMEIP_ID_RESPONSE_COMMAND_SIZE; - byte_t its_command[size]; - uint32_t its_size = size - VSOMEIP_COMMAND_HEADER_SIZE; - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ID_RESPONSE; - 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)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, - sizeof(_service)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, - sizeof(_instance)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_reliable, - sizeof(_reliable)); - { - std::lock_guard<std::mutex> its_lock(sender_mutex_); - if (sender_) { - sender_->send(its_command, size); - } - } -} - void routing_manager_proxy::cache_event_payload( const std::shared_ptr<message> &_message) { const service_t its_service(_message->get_service()); @@ -2075,9 +2101,12 @@ void routing_manager_proxy::cache_event_payload( std::set<eventgroup_t> its_eventgroups; // create a placeholder field until someone requests this event with // full information like eventgroup, field or not etc. - routing_manager_base::register_event(host_->get_client(), its_service, - its_instance, its_method, its_eventgroups, true, - std::chrono::milliseconds::zero(), false, + routing_manager_base::register_event(host_->get_client(), + its_service, its_instance, + its_method, + its_eventgroups, event_type_e::ET_UNKNOWN, + reliability_type_e::RT_UNKNOWN, + std::chrono::milliseconds::zero(), false, true, nullptr, false, false, true); std::shared_ptr<event> its_event = find_event(its_service, its_instance, its_method); @@ -2113,52 +2142,30 @@ void routing_manager_proxy::on_stop_offer_service(service_t _service, void routing_manager_proxy::send_pending_commands() { for (auto &po : pending_offers_) - send_offer_service(client_, po.service_, po.instance_, + send_offer_service(client_, + po.service_, po.instance_, po.major_, po.minor_); for (auto &per : pending_event_registrations_) - send_register_event(client_, per.service_, per.instance_, - per.event_, per.eventgroups_, - per.is_field_, per.is_provided_); + send_register_event(client_, + per.service_, per.instance_, + per.notifier_, + per.eventgroups_, per.type_, per.reliability_, + per.is_provided_); send_request_services(requests_); } void routing_manager_proxy::init_receiver() { - std::stringstream its_client; - its_client << utility::get_base_path(configuration_) << std::hex << client_; -#ifdef _WIN32 - ::_unlink(its_client.str().c_str()); - int port = VSOMEIP_INTERNAL_BASE_PORT + client_; -#else - configuration_->store_client_to_uid_gid_mapping(get_client(), getuid(), getgid()); - configuration_->store_uid_gid_to_client_mapping(getuid(), getgid(), get_client()); +#ifndef _WIN32 + auto its_security = security_impl::get(); + if (!its_security) + return; - 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); - } -#endif - try { - receiver_ = std::make_shared<local_server_endpoint_impl>(shared_from_this(), -#ifdef _WIN32 - boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), -#else - boost::asio::local::stream_protocol::endpoint(its_client.str()), -#endif - io_, configuration_->get_max_message_size_local(), - configuration_->get_buffer_shrink_threshold(), - configuration_->get_endpoint_queue_limit_local(), - configuration_->get_permissions_uds()); -#ifdef _WIN32 - VSOMEIP_INFO << "Listening at " << port; -#else - VSOMEIP_INFO << "Listening at " << its_client.str(); + its_security->store_client_to_uid_gid_mapping(get_client(), own_uid_, own_gid_); + its_security->store_uid_gid_to_client_mapping(own_uid_, own_gid_, get_client()); #endif - } catch (const std::exception &e) { - host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); - VSOMEIP_ERROR << "Client ID: " << std::hex << client_ << ": " << e.what(); - } + receiver_ = ep_mgr_->create_local_server(shared_from_this()); } void routing_manager_proxy::notify_remote_initially(service_t _service, instance_t _instance, @@ -2179,16 +2186,18 @@ void routing_manager_proxy::notify_remote_initially(service_t _service, instance if (service_info) { its_notification->set_interface_version(service_info->get_major()); } - std::lock_guard<std::mutex> its_lock(serialize_mutex_); - if (serializer_->serialize(its_notification.get())) { + + std::shared_ptr<serializer> its_serializer(get_serializer()); + if (its_serializer->serialize(its_notification.get())) { { std::lock_guard<std::mutex> its_lock(sender_mutex_); if (sender_) { - send_local(sender_, VSOMEIP_ROUTING_CLIENT, serializer_->get_data(), - serializer_->get_size(), _instance, true, false, VSOMEIP_NOTIFY); + send_local(sender_, VSOMEIP_ROUTING_CLIENT, its_serializer->get_data(), + its_serializer->get_size(), _instance, false, VSOMEIP_NOTIFY); } } - serializer_->reset(); + its_serializer->reset(); + put_serializer(its_serializer); } else { VSOMEIP_ERROR << "Failed to serialize message. Check message size!"; } @@ -2243,6 +2252,30 @@ void routing_manager_proxy::clear_remote_subscriber_count( } } +void +routing_manager_proxy::assign_client_timeout_cbk( + boost::system::error_code const &_error) { + if (!_error) { + bool register_again(false); + { + std::lock_guard<std::mutex> its_lock(state_mutex_); + if (state_ != inner_state_type_e::ST_REGISTERED) { + state_ = inner_state_type_e::ST_DEREGISTERED; + register_again = true; + } + } + if (register_again) { + std::lock_guard<std::mutex> its_lock(sender_mutex_); + VSOMEIP_WARNING << std::hex << "Client 0x" << get_client() + << " request client timeout! Trying again..."; + + if (sender_) { + sender_->restart(); + } + } + } +} + void routing_manager_proxy::register_application_timeout_cbk( boost::system::error_code const &_error) { if (!_error) { @@ -2256,8 +2289,9 @@ void routing_manager_proxy::register_application_timeout_cbk( } if (register_again) { std::lock_guard<std::mutex> its_lock(sender_mutex_); - VSOMEIP_WARNING << std::hex << "Client 0x" << get_client() << " register timeout!" - << " : Restart route to stub!"; + VSOMEIP_WARNING << std::hex << "Client 0x" << get_client() + << " register timeout! Trying again..."; + if (sender_) { sender_->restart(); } @@ -2285,19 +2319,21 @@ bool routing_manager_proxy::is_client_known(client_t _client) { } bool routing_manager_proxy::create_placeholder_event_and_subscribe( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - event_t _event, client_t _client) { + service_t _service, instance_t _instance, + eventgroup_t _eventgroup, event_t _notifier, client_t _client) { + bool is_inserted(false); // we received a event which was not yet requested/offered // create a placeholder field until someone requests/offers this event with // full information like eventgroup, field or not etc. std::set<eventgroup_t> its_eventgroups({ _eventgroup }); // routing_manager_proxy: Always register with own client id and shadow = false - routing_manager_base::register_event(host_->get_client(), _service, - _instance, _event, its_eventgroups, true, - std::chrono::milliseconds::zero(), false, nullptr, false, false, + routing_manager_base::register_event(host_->get_client(), + _service, _instance, _notifier, + its_eventgroups, event_type_e::ET_UNKNOWN, reliability_type_e::RT_UNKNOWN, + std::chrono::milliseconds::zero(), false, true, nullptr, false, false, true); - std::shared_ptr<event> its_event = find_event(_service, _instance, _event); + std::shared_ptr<event> its_event = find_event(_service, _instance, _notifier); if (its_event) { is_inserted = its_event->add_subscriber(_eventgroup, _client, false); } @@ -2318,7 +2354,8 @@ void routing_manager_proxy::request_debounce_timeout_cbk( { std::lock_guard<std::mutex> its_lock(request_timer_mutex_); request_debounce_timer_running_ = true; - request_debounce_timer_.expires_from_now(std::chrono::milliseconds(configuration_->get_request_debouncing(host_->get_name()))); + request_debounce_timer_.expires_from_now(std::chrono::milliseconds( + configuration_->get_request_debouncing(host_->get_name()))); request_debounce_timer_.async_wait( std::bind( &routing_manager_proxy::request_debounce_timeout_cbk, @@ -2358,7 +2395,7 @@ void routing_manager_proxy::handle_client_error(client_t _client) { std::lock_guard<std::mutex> its_lock(known_clients_mutex_); its_known_clients = known_clients_; } - reconnect(its_known_clients); + reconnect(its_known_clients); } } } @@ -2386,7 +2423,7 @@ void routing_manager_proxy::send_get_offered_services_info(client_t _client, off void routing_manager_proxy::send_unsubscribe_ack( service_t _service, instance_t _instance, eventgroup_t _eventgroup, - pending_subscription_id_t _subscription_id) { + remote_subscription_id_t _id) { byte_t its_command[VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE]; const std::uint32_t its_size = VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE; @@ -2403,8 +2440,8 @@ void routing_manager_proxy::send_unsubscribe_ack( sizeof(_instance)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, sizeof(_eventgroup)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], - &_subscription_id, sizeof(_subscription_id)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_id, + sizeof(_id)); { std::lock_guard<std::mutex> its_lock(sender_mutex_); @@ -2419,8 +2456,8 @@ void routing_manager_proxy::resend_provided_event_registrations() { 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_); + ed.notifier_, ed.eventgroups_, ed.type_, ed.reliability_, + ed.is_provided_); } } } @@ -2489,6 +2526,10 @@ void routing_manager_proxy::send_remove_security_policy_response(pending_securit } void routing_manager_proxy::on_update_security_credentials(const byte_t *_data, uint32_t _size) { + auto its_security = security_impl::get(); + if (!its_security) + return; + uint32_t i = 0; while ( (i + sizeof(uint32_t) + sizeof(uint32_t)) <= _size) { std::shared_ptr<policy> its_policy(std::make_shared<policy>()); @@ -2505,8 +2546,49 @@ void routing_manager_proxy::on_update_security_credentials(const byte_t *_data, 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()); + its_security->add_security_credentials(its_uid, its_gid, its_policy, get_client()); + } +} + +void routing_manager_proxy::on_client_assign_ack(const client_t &_client) { + std::lock_guard<std::mutex> its_lock(state_mutex_); + if (state_ == inner_state_type_e::ST_ASSIGNING) { + if (_client != VSOMEIP_CLIENT_UNSET) { + state_ = inner_state_type_e::ST_ASSIGNED; + + boost::system::error_code ec; + register_application_timer_.cancel(ec); + host_->set_client(_client); + client_ = _client; + + if (is_started_) { + init_receiver(); + if (receiver_) { + receiver_->start(); + + VSOMEIP_INFO << std::hex << "Client " << client_ + << " (" << host_->get_name() + << ") successfully connected to routing ~> registering.."; + register_application(); + } else { + state_ = inner_state_type_e::ST_DEREGISTERED; + + host_->set_client(VSOMEIP_CLIENT_UNSET); + client_ = VSOMEIP_CLIENT_UNSET; + + sender_->restart(); + } + } + } else { + VSOMEIP_ERROR << "Didn't receive valid clientID! Won't register application."; + } + } else { + VSOMEIP_WARNING << "Client " << std::hex << client_ + << " received another client identifier (" + << std::hex << _client + << "). Ignoring it. (" + << (int)state_ << ")"; } } -} // namespace vsomeip +} // namespace vsomeip_v3 diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp index 5c19af9..65945f7 100644 --- a/implementation/routing/src/routing_manager_stub.cpp +++ b/implementation/routing/src/routing_manager_stub.cpp @@ -14,30 +14,28 @@ #include <vsomeip/primitive_types.hpp> #include <vsomeip/runtime.hpp> #include <vsomeip/error.hpp> - -#ifndef WITHOUT_SYSTEMD -#include <systemd/sd-daemon.h> -#endif -#define SD_LISTEN_FDS_START 3 +#include <vsomeip/internal/logger.hpp> #include "../include/routing_manager_stub.hpp" #include "../include/routing_manager_stub_host.hpp" +#include "../include/remote_subscription.hpp" #include "../../configuration/include/configuration.hpp" -#include "../../configuration/include/internal.hpp" +#include "../../security/include/security.hpp" + #include "../../endpoints/include/local_server_endpoint_impl.hpp" -#include "../../logging/include/logger.hpp" +#include "../../endpoints/include/endpoint_manager_impl.hpp" #include "../../utility/include/byteorder.hpp" #include "../../utility/include/utility.hpp" #include "../implementation/message/include/payload_impl.hpp" -namespace vsomeip { +namespace vsomeip_v3 { const std::vector<byte_t> routing_manager_stub::its_ping_( { VSOMEIP_PING, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); routing_manager_stub::routing_manager_stub( routing_manager_stub_host *_host, - std::shared_ptr<configuration> _configuration) : + const std::shared_ptr<configuration>& _configuration) : host_(_host), io_(_host->get_io()), watchdog_timer_(_host->get_io()), @@ -45,7 +43,6 @@ routing_manager_stub::routing_manager_stub( endpoint_(nullptr), local_receiver_(nullptr), configuration_(_configuration), - routingCommandSize_(VSOMEIP_ROUTING_INFO_SIZE_INIT), is_socket_activated_(false), client_registration_running_(false), max_local_message_size_(configuration_->get_max_message_size_local()), @@ -75,11 +72,11 @@ void routing_manager_stub::start() { std::placeholders::_1)); } - if(!endpoint_) { + if (!endpoint_) { // application has been stopped and started again init_routing_endpoint(); } - if(endpoint_) { + if (endpoint_) { endpoint_->start(); } @@ -127,12 +124,15 @@ void routing_manager_stub::stop() { if( !is_socket_activated_) { endpoint_->stop(); endpoint_ = nullptr; + std::stringstream its_endpoint_path; + its_endpoint_path << utility::get_base_path(configuration_) << std::hex + << VSOMEIP_ROUTING_CLIENT; #ifdef _WIN32 - ::_unlink(endpoint_path_.c_str()); + ::_unlink(its_endpoint_path.str().c_str()); #else - if (-1 == ::unlink(endpoint_path_.c_str())) { + if (-1 == ::unlink(its_endpoint_path.str().c_str())) { VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed (" - << endpoint_path_ << "): "<< std::strerror(errno); + << its_endpoint_path.str() << "): "<< std::strerror(errno); } #endif } @@ -140,53 +140,24 @@ void routing_manager_stub::stop() { if(local_receiver_) { local_receiver_->stop(); local_receiver_ = nullptr; + std::stringstream its_local_receiver_path; + its_local_receiver_path << utility::get_base_path(configuration_) + << std::hex << host_->get_client(); #ifdef _WIN32 - ::_unlink(local_receiver_path_.c_str()); + ::_unlink(its_local_receiver_path.str().c_str()); #else - if (-1 == ::unlink(local_receiver_path_.c_str())) { + if (-1 == ::unlink(its_local_receiver_path.str().c_str())) { VSOMEIP_ERROR << "routing_manager_stub::stop() unlink (local receiver) failed (" - << local_receiver_path_ << "): "<< std::strerror(errno); + << its_local_receiver_path.str() << "): "<< std::strerror(errno); } #endif } } -const std::shared_ptr<configuration> routing_manager_stub::get_configuration() const { - return configuration_; -} - -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) { - (void)_endpoint; -} - -void routing_manager_stub::on_error( - const byte_t *_data, length_t _length, endpoint *_receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port) { - - // Implement me when needed - - (void)(_data); - (void)(_length); - (void)(_receiver); - (void)(_remote_address); - (void)(_remote_port); -} - -void routing_manager_stub::release_port(uint16_t _port, bool _reliable) { - (void)_port; - (void)_reliable; - // intentionally empty -} - void routing_manager_stub::on_message(const byte_t *_data, length_t _size, endpoint *_receiver, const boost::asio::ip::address &_destination, client_t _bound_client, + credentials_t _credentials, const boost::asio::ip::address &_remote_address, std::uint16_t _remote_port) { (void)_receiver; @@ -201,6 +172,9 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, VSOMEIP_INFO << msg.str(); #endif + std::uint32_t its_sender_uid = std::get<0>(_credentials); + std::uint32_t its_sender_gid = std::get<1>(_credentials); + if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) { byte_t its_command; client_t its_client; @@ -209,9 +183,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, instance_t its_instance; method_t its_method; eventgroup_t its_eventgroup; - std::set<eventgroup_t> its_eventgroups; - event_t its_event; - bool is_field(false); + event_t its_notifier; + event_type_e its_event_type; bool is_provided(false); major_version_t its_major; minor_version_t its_minor; @@ -219,19 +192,18 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, const byte_t *its_data; uint32_t its_size; bool its_reliable(false); - subscription_type_e its_subscription_type; client_t its_client_from_header; client_t its_target_client; client_t its_subscriber; - bool its_is_valid_crc(true); - std::uint16_t its_subscription_id(DEFAULT_SUBSCRIPTION); + uint8_t its_check_status(0); + std::uint16_t its_subscription_id(PENDING_SUBSCRIPTION_ID); offer_type_e its_offer_type; its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], sizeof(its_client)); - if (configuration_->is_security_enabled() && _bound_client != its_client) { + if (security::get()->is_enabled() && _bound_client != its_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') @@ -278,6 +250,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, VSOMEIP_WARNING << "Received a OFFER_SERVICE command with wrong size ~> skip!"; break; } + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(its_service)); std::memcpy(&its_instance, @@ -288,7 +261,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], sizeof(its_minor)); - if (configuration_->is_offer_allowed(its_client, its_service, its_instance)) { + if (security::get()->is_offer_allowed(its_sender_uid, its_sender_gid, + its_client, its_service, its_instance)) { host_->offer_service(its_client, its_service, its_instance, its_major, its_minor); } else { @@ -331,15 +305,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_eventgroup)); std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], sizeof(its_major)); - std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], - sizeof(its_event)); - std::memcpy(&its_subscription_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9], - sizeof(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); + std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], + sizeof(its_notifier)); + + if (its_notifier == ANY_EVENT) { + if (host_->is_subscribe_to_any_event_allowed(_credentials, its_client, its_service, + its_instance, its_eventgroup)) { + host_->subscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance, + its_eventgroup, its_major, its_notifier); } else { VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client << " : routing_manager_stub::on_message: " @@ -348,15 +321,15 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, << " which violates the security policy ~> Skip subscribe!"; } } else { - 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); + if (security::get()->is_client_allowed(its_sender_uid, its_sender_gid, + its_client, its_service, its_instance, its_notifier)) { + host_->subscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance, + its_eventgroup, its_major, its_notifier); } 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 + << its_service << "/" << its_instance << "/" << its_notifier << " which violates the security policy ~> Skip subscribe!"; } } @@ -373,11 +346,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_instance)); std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], sizeof(its_eventgroup)); - std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], - sizeof(its_event)); + std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], + sizeof(its_notifier)); - host_->unsubscribe(its_client, its_service, - its_instance, its_eventgroup, its_event); + host_->unsubscribe(its_client, its_sender_uid, its_sender_gid, its_service, + its_instance, its_eventgroup, its_notifier); break; case VSOMEIP_SUBSCRIBE_ACK: @@ -393,18 +366,18 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_eventgroup)); std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], sizeof(its_subscriber)); - std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8], - sizeof(its_event)); + std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8], + sizeof(its_notifier)); std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10], sizeof(its_subscription_id)); host_->on_subscribe_ack(its_subscriber, its_service, - its_instance, its_eventgroup, its_event, its_subscription_id); + its_instance, its_eventgroup, its_notifier, its_subscription_id); VSOMEIP_INFO << "SUBSCRIBE ACK(" << std::hex << std::setw(4) << std::setfill('0') << its_client << "): [" << std::hex << std::setw(4) << std::setfill('0') << its_service << "." << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "." - << std::hex << std::setw(4) << std::setfill('0') << its_event << "]"; + << std::hex << std::setw(4) << std::setfill('0') << its_notifier << "]"; break; case VSOMEIP_SUBSCRIBE_NACK: @@ -420,18 +393,18 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_eventgroup)); std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], sizeof(its_subscriber)); - std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8], - sizeof(its_event)); + std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8], + sizeof(its_notifier)); std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10], sizeof(its_subscription_id)); host_->on_subscribe_nack(its_subscriber, its_service, - its_instance, its_eventgroup, its_event, its_subscription_id); + its_instance, its_eventgroup, its_notifier, its_subscription_id); VSOMEIP_INFO << "SUBSCRIBE NACK(" << std::hex << std::setw(4) << std::setfill('0') << its_client << "): [" << std::hex << std::setw(4) << std::setfill('0') << its_service << "." << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "." - << std::hex << std::setw(4) << std::setfill('0') << its_event << "]"; + << std::hex << std::setw(4) << std::setfill('0') << its_notifier << "]"; break; case VSOMEIP_UNSUBSCRIBE_ACK: if (_size != VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE) { @@ -473,14 +446,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_instance)); std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS], sizeof(its_reliable)); - std::memcpy(&its_is_valid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS], - sizeof(its_is_valid_crc)); + std::memcpy(&its_check_status, &_data[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS], + sizeof(its_check_status)); // 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, its_method)) { + if (!security::get()->is_client_allowed(its_sender_uid, its_sender_gid, + its_client_from_header, 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 " @@ -502,7 +475,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, break; } host_->on_message(its_service, its_instance, its_data, its_message_size, - its_reliable, _bound_client, its_is_valid_crc, false); + its_reliable, _bound_client, _credentials, its_check_status, false); break; } case VSOMEIP_NOTIFY: { @@ -562,8 +535,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, } case VSOMEIP_REQUEST_SERVICE: { - uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t) - + sizeof(minor_version_t) + sizeof(bool)); + uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + + sizeof(major_version_t) + sizeof(minor_version_t)); if (its_size % entry_size > 0) { VSOMEIP_WARNING << "Received a REQUEST_SERVICE command with invalid size -> skip!"; break; @@ -575,7 +548,6 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, instance_t its_instance; major_version_t its_major; minor_version_t its_minor; - bool use_exclusive_proxy; std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)], sizeof(its_service)); std::memcpy(&its_instance, @@ -585,13 +557,14 @@ 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 + (i * entry_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, 0x00, true)) { + if (security::get()->is_client_allowed(its_sender_uid, its_sender_gid, + 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 }; + its_major, its_minor ); + service_data_t request = { + its_service, its_instance, + its_major, its_minor + }; requests.insert(request); } else { VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex @@ -601,7 +574,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, << " which violates the security policy ~> Skip request!"; } } - if (configuration_->is_security_enabled()) { + if (security::get()->is_enabled()) { handle_credentials(its_client, requests); } handle_requests(its_client, requests); @@ -622,48 +595,58 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, host_->release_service(its_client, its_service, its_instance); break; - case VSOMEIP_REGISTER_EVENT: + case VSOMEIP_REGISTER_EVENT: { if (_size < VSOMEIP_REGISTER_EVENT_COMMAND_SIZE) { VSOMEIP_WARNING << "Received a REGISTER_EVENT command with wrong size ~> skip!"; break; } + + std::set<eventgroup_t> its_eventgroups; + reliability_type_e its_reliability = reliability_type_e::RT_UNKNOWN; + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(its_service)); std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], sizeof(its_instance)); - std::memcpy(&its_event, + std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_event)); - std::memcpy(&is_field, + sizeof(its_notifier)); + std::memcpy(&its_event_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], - sizeof(is_field)); + sizeof(its_event_type)); std::memcpy(&is_provided, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], sizeof(is_provided)); + std::memcpy(&its_reliability, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8], + sizeof(its_reliability)); if (is_provided && !configuration_->is_offered_remote(its_service, its_instance)) { break; } - for (std::size_t i = 8; i+1 < its_size; i++) { + for (std::size_t i = 9; i+1 < its_size; i++) { std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + i], sizeof(its_eventgroup)); its_eventgroups.insert(its_eventgroup); } - host_->register_shadow_event(its_client, its_service, - its_instance, its_event, its_eventgroups, - is_field, is_provided); + host_->register_shadow_event(its_client, + its_service, its_instance, + its_notifier, its_eventgroups, its_event_type, + its_reliability, + is_provided); VSOMEIP_INFO << "REGISTER EVENT(" << std::hex << std::setw(4) << std::setfill('0') << its_client << "): [" << std::hex << std::setw(4) << std::setfill('0') << its_service << "." << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." - << std::hex << std::setw(4) << std::setfill('0') << its_event - << ":is_provider=" << is_provided << "]"; + << std::hex << std::setw(4) << std::setfill('0') << its_notifier + << ":is_provider=" << is_provided << ":reliability=" + << (std::uint32_t)(its_reliability) << "]"; break; - + } case VSOMEIP_UNREGISTER_EVENT: if (_size != VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE) { VSOMEIP_WARNING << "Received a UNREGISTER_EVENT command with wrong size ~> skip!"; @@ -674,8 +657,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], sizeof(its_instance)); - std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_event)); + std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_notifier)); std::memcpy(&is_provided, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], sizeof(is_provided)); @@ -685,36 +668,15 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, break; } host_->unregister_shadow_event(its_client, its_service, its_instance, - its_event, is_provided); + its_notifier, is_provided); VSOMEIP_INFO << "UNREGISTER EVENT(" << std::hex << std::setw(4) << std::setfill('0') << its_client << "): [" << std::hex << std::setw(4) << std::setfill('0') << its_service << "." << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." - << std::hex << std::setw(4) << std::setfill('0') << its_event + << std::hex << std::setw(4) << std::setfill('0') << its_notifier << ":is_provider=" << is_provided << "]"; break; - case VSOMEIP_ID_RESPONSE: - if (_size != VSOMEIP_ID_RESPONSE_COMMAND_SIZE) { - VSOMEIP_WARNING << "Received a ID_RESPONSE command with wrong size ~> skip!"; - break; - } - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, - &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_reliable, - &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_reliable)); - host_->on_identify_response(its_client, its_service, its_instance, its_reliable); - VSOMEIP_INFO << "ID RESPONSE(" - << std::hex << std::setw(4) << std::setfill('0') << its_client << "): [" - << std::hex << std::setw(4) << std::setfill('0') << its_service << "." - << std::hex << std::setw(4) << std::setfill('0') << its_instance - << ":is_reliable=" << its_reliable << "]"; - break; - case VSOMEIP_REGISTERED_ACK: if (_size != VSOMEIP_REGISTERED_ACK_COMMAND_SIZE) { VSOMEIP_WARNING << "Received a REGISTERED_ACK command with wrong size ~> skip!"; @@ -735,7 +697,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, std::lock_guard<std::mutex> its_guard(routing_info_mutex_); create_offered_services_info(its_client); - for (auto found_client : routing_info_) { + for (const auto& found_client : routing_info_) { // skip services which are offered on remote hosts if (found_client.first != VSOMEIP_ROUTING_CLIENT) { for (const auto &its_service : found_client.second.second) { @@ -879,7 +841,7 @@ void routing_manager_stub::client_registration_func(void) { pending_client_registrations_.clear(); its_lock.unlock(); - for (auto r : its_registrations) { + for (const auto& r : its_registrations) { for (auto b : r.second) { if (b == registration_type_e::REGISTER) { on_register_application(r.first); @@ -921,7 +883,7 @@ void routing_manager_stub::client_registration_func(void) { } connection_matrix_.erase(r.first); } - for (auto its_client : connection_matrix_) { + for (const auto& its_client : connection_matrix_) { connection_matrix_[its_client.first].erase(r.first); } service_requests_.erase(r.first); @@ -929,9 +891,7 @@ void routing_manager_stub::client_registration_func(void) { // 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); - } + utility::release_client_id(r.first); } } } @@ -940,76 +900,8 @@ void routing_manager_stub::client_registration_func(void) { } void routing_manager_stub::init_routing_endpoint() { - std::stringstream its_endpoint_path; - its_endpoint_path << utility::get_base_path(configuration_) << VSOMEIP_ROUTING_CLIENT; - 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 << __func__ << std::hex << " Client " << get_client() << " isn't allowed" - << " to create the routing endpoint due to its not configured as the routing master!"; - return; - } - uint32_t native_socket_fd, num_fd = 0; -#ifndef WITHOUT_SYSTEMD - num_fd = sd_listen_fds(0); -#endif - if (num_fd > 1) { - VSOMEIP_ERROR << "Too many file descriptors received by systemd socket activation! num_fd: " << num_fd; - } else if (num_fd == 1) { - native_socket_fd = SD_LISTEN_FDS_START + 0; - VSOMEIP_INFO << "Using native socket created by systemd socket activation! fd: " << native_socket_fd; - #ifndef _WIN32 - try { - endpoint_ = - std::make_shared < local_server_endpoint_impl - > (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_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(); - } - #endif - is_socket_activated_ = true; - } else { - #if _WIN32 - ::_unlink(endpoint_path_.c_str()); - int port = VSOMEIP_INTERNAL_BASE_PORT; - VSOMEIP_INFO << "Routing endpoint at " << port; - #else - if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) { - VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed (" - << endpoint_path_ << "): "<< std::strerror(errno); - } - VSOMEIP_INFO << "init_routing_endpoint Routing endpoint at " << endpoint_path_; - #endif - - try { - endpoint_ = - std::make_shared < local_server_endpoint_impl - > (shared_from_this(), - #ifdef _WIN32 - boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), - #else - boost::asio::local::stream_protocol::endpoint(endpoint_path_), - #endif - io_, configuration_->get_max_message_size_local(), - 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) << ")"; - VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint Client ID: " - << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what(); - } - is_socket_activated_ = false; - } + endpoint_ = host_->get_endpoint_manager()->create_local_server( + &is_socket_activated_, shared_from_this()); } void routing_manager_stub::on_offer_service(client_t _client, @@ -1018,22 +910,13 @@ void routing_manager_stub::on_offer_service(client_t _client, create_local_receiver(); } - if (_client == VSOMEIP_ROUTING_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 << "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!"; + std::lock_guard<std::mutex> its_guard(routing_info_mutex_); + routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor); + if (security::get()->is_enabled()) { + distribute_credentials(_client, _service, _instance); } + inform_requesters(_client, _service, _instance, _major, _minor, + routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, true); } void routing_manager_stub::on_stop_offer_service(client_t _client, @@ -1155,7 +1038,7 @@ void routing_manager_stub::send_client_credentials_info(const client_t _target) // 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); + its_endpoint->send(&its_command[0], uint32_t(its_size)); } else { VSOMEIP_ERROR << "Credentials info exceeds maximum message size: Can't send!"; } @@ -1212,7 +1095,7 @@ void routing_manager_stub::send_client_routing_info(const client_t _target) { // 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); + its_endpoint->send(&its_command[0], uint32_t(its_size)); } else { VSOMEIP_ERROR << "Routing info exceeds maximum message size: Can't send!"; } @@ -1249,7 +1132,7 @@ void routing_manager_stub::send_offered_services_info(const client_t _target) { // 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); + its_endpoint->send(&its_command[0], uint32_t(its_size)); } else { VSOMEIP_ERROR << "Offered services info exceeds maximum message size: Can't send!"; } @@ -1406,10 +1289,10 @@ void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _s // 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)) { + if (security::get()->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 (security::get()->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); @@ -1465,21 +1348,21 @@ bool routing_manager_stub::is_already_connected(client_t _source, client_t _sink void routing_manager_stub::broadcast(const std::vector<byte_t> &_command) const { std::lock_guard<std::mutex> its_guard(routing_info_mutex_); - for (auto a : routing_info_) { + for (const auto& a : routing_info_) { if (a.first != VSOMEIP_ROUTING_CLIENT && a.first != host_->get_client()) { std::shared_ptr<endpoint> its_endpoint = host_->find_local(a.first); if (its_endpoint) { - its_endpoint->send(&_command[0], uint32_t(_command.size()), true); + its_endpoint->send(&_command[0], uint32_t(_command.size())); } } } } -bool routing_manager_stub::send_subscribe(std::shared_ptr<vsomeip::endpoint> _target, +bool routing_manager_stub::send_subscribe(const std::shared_ptr<endpoint>& _target, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, - event_t _event, pending_subscription_id_t _subscription_id) { + event_t _event, remote_subscription_id_t _id) { if (_target) { byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE @@ -1498,11 +1381,8 @@ bool routing_manager_stub::send_subscribe(std::shared_ptr<vsomeip::endpoint> _ta its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major; std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_event, sizeof(_event)); - // set byte for subscription_type to zero. It's only used - // in subscribe messages sent from rm_proxies to rm_stub. - its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9] = 0x0; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], - &_subscription_id, sizeof(_subscription_id)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_id, + sizeof(_id)); return _target->send(its_command, sizeof(its_command)); } else { @@ -1517,10 +1397,11 @@ bool routing_manager_stub::send_subscribe(std::shared_ptr<vsomeip::endpoint> _ta } } -bool routing_manager_stub::send_unsubscribe(std::shared_ptr<vsomeip::endpoint> _target, +bool routing_manager_stub::send_unsubscribe( + const std::shared_ptr<endpoint>& _target, client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, - pending_subscription_id_t _unsubscription_id) { + remote_subscription_id_t _id) { if (_target) { byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE @@ -1538,8 +1419,8 @@ bool routing_manager_stub::send_unsubscribe(std::shared_ptr<vsomeip::endpoint> _ sizeof(_eventgroup)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event, sizeof(_event)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_unsubscription_id, - sizeof(_unsubscription_id)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_id, + sizeof(_id)); return _target->send(its_command, sizeof(its_command)); } else { @@ -1580,9 +1461,9 @@ void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _servi std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event, sizeof(_event)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], - &DEFAULT_SUBSCRIPTION, sizeof(DEFAULT_SUBSCRIPTION)); + &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID)); - its_endpoint->send(&its_command[0], sizeof(its_command), true); + its_endpoint->send(&its_command[0], sizeof(its_command)); } } @@ -1612,9 +1493,9 @@ void routing_manager_stub::send_subscribe_nack(client_t _client, service_t _serv std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event, sizeof(_event)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], - &DEFAULT_SUBSCRIPTION, sizeof(DEFAULT_SUBSCRIPTION)); + &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID)); - its_endpoint->send(&its_command[0], sizeof(its_command), true); + its_endpoint->send(&its_command[0], sizeof(its_command)); } } @@ -1691,7 +1572,7 @@ void routing_manager_stub::check_watchdog() { std::list< client_t > lost; { std::lock_guard<std::mutex> its_lock(routing_info_mutex_); - for (auto i : routing_info_) { + for (const auto& i : routing_info_) { if (i.first > 0 && i.first != host_->get_client()) { if (i.second.first > configuration_->get_allowed_missing_pongs()) { VSOMEIP_WARNING << "Lost contact to application " << std::hex << (int)i.first; @@ -1720,43 +1601,16 @@ void routing_manager_stub::create_local_receiver() { if (local_receiver_) { return; } - std::stringstream its_local_receiver_path; - its_local_receiver_path << utility::get_base_path(configuration_) << std::hex << host_->get_client(); - local_receiver_path_ = its_local_receiver_path.str(); -#if _WIN32 - ::_unlink(local_receiver_path_.c_str()); - int port = VSOMEIP_INTERNAL_BASE_PORT; -#else - if (!check_credentials(get_client(), getuid(), getgid())) { +#ifndef _WIN32 + else if (!security::get()->check_credentials(get_client(), getuid(), getgid())) { 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; } - if (-1 == ::unlink(local_receiver_path_.c_str()) && errno != ENOENT) { - VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver unlink (local receiver) failed (" - << local_receiver_path_ << "): "<< std::strerror(errno); - } #endif - try { - local_receiver_ = - std::make_shared < local_server_endpoint_impl - > (shared_from_this(), - #ifdef _WIN32 - boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port + host_->get_client()), - #else - boost::asio::local::stream_protocol::endpoint(local_receiver_path_), - #endif - io_, configuration_->get_max_message_size_local(), - 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) << ")"; - VSOMEIP_ERROR << "routing_manager_stub::_local_receiver Client ID: " - << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what(); - } + local_receiver_ = std::static_pointer_cast<endpoint_manager_base>( + host_->get_endpoint_manager())->create_local_server(shared_from_this()); local_receiver_->start(); } @@ -1805,8 +1659,7 @@ bool routing_manager_stub::send_ping(client_t _client) { pinged_clients_timer_.async_wait( std::bind(&routing_manager_stub::on_ping_timer_expired, this, std::placeholders::_1)); - return its_endpoint->send(&its_ping_[0], uint32_t(its_ping_.size()), - true); + return its_endpoint->send(&its_ping_[0], uint32_t(its_ping_.size())); } } @@ -1904,7 +1757,7 @@ void routing_manager_stub::remove_from_pinged_clients(client_t _client) { } pinged_clients_timer_.async_wait( std::bind(&routing_manager_stub::on_ping_timer_expired, this, - std::placeholders::_1)); + std::placeholders::_1)); } bool routing_manager_stub::is_registered(client_t _client) const { @@ -1922,7 +1775,7 @@ void routing_manager_stub::update_registration(client_t _client, "registering." : "deregistering."); if (_type != registration_type_e::REGISTER) { - configuration_->remove_client_to_uid_gid_mapping(_client); + security::get()->remove_client_to_uid_gid_mapping(_client); } if (_type == registration_type_e::DEREGISTER) { @@ -1968,7 +1821,7 @@ void routing_manager_stub::handle_credentials(const client_t _client, std::set<s 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)) { + if (security::get()->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; @@ -1984,7 +1837,7 @@ void routing_manager_stub::handle_credentials(const client_t _client, std::set<s // 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 (security::get()->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))); } @@ -2010,51 +1863,63 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv for (auto request : _requests) { service_requests_[_client][request.service_][request.instance_] = std::make_pair(request.major_, request.minor_); - for (auto found_client : routing_info_) { - auto found_service = found_client.second.second.find(request.service_); - if (found_service != found_client.second.second.end()) { - if (request.instance_ == ANY_INSTANCE) { - if (found_client.first != VSOMEIP_ROUTING_CLIENT && - found_client.first != host_->get_client()) { - if (!is_already_connected(found_client.first, _client)) { - if (_client == found_client.first) { - service_available = true; - insert_client_routing_info(found_client.first, + if (request.instance_ == ANY_INSTANCE) { + std::set<client_t> its_clients = host_->find_local_clients(request.service_, request.instance_); + // insert VSOMEIP_ROUTING_CLIENT to check wether service is remotely offered + its_clients.insert(VSOMEIP_ROUTING_CLIENT); + for (const client_t c : its_clients) { + if (c != VSOMEIP_ROUTING_CLIENT && + c != host_->get_client()) { + if (!is_already_connected(c, _client)) { + if (_client == c) { + service_available = true; + insert_client_routing_info(c, + routing_info_entry_e::RIE_ADD_CLIENT, _client); + } else { + create_client_routing_info(c); + insert_client_routing_info(c, routing_info_entry_e::RIE_ADD_CLIENT, _client); - } else { - create_client_routing_info(found_client.first); - insert_client_routing_info(found_client.first, - routing_info_entry_e::RIE_ADD_CLIENT, _client); - send_client_routing_info(found_client.first); - } + send_client_routing_info(c); } } - if (_client != VSOMEIP_ROUTING_CLIENT && - _client != host_->get_client()) { - for (auto instance : found_service->second) { - service_available = true; - insert_client_routing_info(_client, - routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, - found_client.first, request.service_, instance.first, - instance.second.first, instance.second.second); + } + if (_client != VSOMEIP_ROUTING_CLIENT && + _client != host_->get_client()) { + const auto found_client = routing_info_.find(c); + if (found_client != routing_info_.end()) { + const auto found_service = found_client->second.second.find(request.service_); + if (found_service != found_client->second.second.end()) { + for (auto instance : found_service->second) { + service_available = true; + insert_client_routing_info(_client, + routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, + c, request.service_, instance.first, + instance.second.first, instance.second.second); + } } } - break; - } else { - auto found_instance = found_service->second.find(request.instance_); + } + } + } else { + const client_t c = host_->find_local_client(request.service_, request.instance_); + const auto found_client = routing_info_.find(c); + if (found_client != routing_info_.end()) { + const auto found_service = found_client->second.second.find(request.service_); + if (found_service != found_client->second.second.end()) { + const auto found_instance = found_service->second.find(request.instance_); if (found_instance != found_service->second.end()) { - if (found_client.first != VSOMEIP_ROUTING_CLIENT && - found_client.first != host_->get_client()) { - if (!is_already_connected(found_client.first, _client)) { - if (_client == found_client.first) { + if (c != VSOMEIP_ROUTING_CLIENT && + c != host_->get_client()) { + if (!is_already_connected(c, _client)) { + if (_client == c) { service_available = true; - insert_client_routing_info(found_client.first, - routing_info_entry_e::RIE_ADD_CLIENT, _client); + insert_client_routing_info(c, + routing_info_entry_e::RIE_ADD_CLIENT, _client); } else { - create_client_routing_info(found_client.first); - insert_client_routing_info(found_client.first, + create_client_routing_info(c); + insert_client_routing_info(c, routing_info_entry_e::RIE_ADD_CLIENT, _client); - send_client_routing_info(found_client.first); + send_client_routing_info(c); } } } @@ -2063,11 +1928,10 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv service_available = true; insert_client_routing_info(_client, routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, - found_client.first, request.service_, request.instance_, + c, request.service_, request.instance_, found_instance->second.first, found_instance->second.second); } - break; } } } @@ -2078,37 +1942,6 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv } } -#ifndef _WIN32 -bool routing_manager_stub::check_credentials(client_t _client, uid_t _uid, gid_t _gid) { - return configuration_->check_credentials(_client, _uid, _gid); -} -#endif - -void routing_manager_stub::send_identify_request_command(std::shared_ptr<vsomeip::endpoint> _target, - service_t _service, instance_t _instance, major_version_t _major, bool _reliable) { - if (_target) { - byte_t its_command[VSOMEIP_ID_REQUEST_COMMAND_SIZE]; - uint32_t its_size = VSOMEIP_ID_REQUEST_COMMAND_SIZE - - VSOMEIP_COMMAND_HEADER_SIZE; - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ID_REQUEST; - client_t client = get_client(); - 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)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, - sizeof(_service)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, - sizeof(_instance)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_major, - sizeof(_major)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_reliable, - sizeof(_reliable)); - - _target->send(its_command, sizeof(its_command)); - } -} - void routing_manager_stub::on_client_id_timer_expired(boost::system::error_code const &_error) { std::set<client_t> used_client_ids; { @@ -2152,8 +1985,9 @@ bool routing_manager_stub::send_provided_event_resend_request(client_t _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)); + const client_t routing_client(VSOMEIP_ROUTING_CLIENT); + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &routing_client, + sizeof(routing_client)); 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)); @@ -2182,7 +2016,7 @@ bool routing_manager_stub::is_policy_cached(uint32_t _uid) { } } -void routing_manager_stub::policy_cache_add(uint32_t _uid, std::shared_ptr<payload> _payload) { +void routing_manager_stub::policy_cache_add(uint32_t _uid, const 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_); @@ -2198,7 +2032,8 @@ void routing_manager_stub::policy_cache_remove(uint32_t _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) { + uint32_t _uid, const std::shared_ptr<payload>& _payload) { + (void)_uid; std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client); if (its_endpoint) { std::vector<byte_t> its_command; @@ -2269,7 +2104,7 @@ bool routing_manager_stub::send_cached_security_policies(client_t _client) { reinterpret_cast<const byte_t*>(&its_policy_count)[i]); } - for (auto its_uid_gid : updated_security_policies_) { + for (const 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) { @@ -2318,4 +2153,4 @@ bool routing_manager_stub::send_remove_security_policy_request( client_t _client } } -} // namespace vsomeip +} // namespace vsomeip_v3 diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp index 42db53b..324fcd7 100644 --- a/implementation/routing/src/serviceinfo.cpp +++ b/implementation/routing/src/serviceinfo.cpp @@ -5,11 +5,14 @@ #include "../include/serviceinfo.hpp" -namespace vsomeip { +namespace vsomeip_v3 { -serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor, - ttl_t _ttl, bool _is_local) +serviceinfo::serviceinfo(service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, + ttl_t _ttl, bool _is_local) : group_(0), + service_(_service), + instance_(_instance), major_(_major), minor_(_minor), ttl_(0), @@ -24,6 +27,8 @@ serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor, serviceinfo::serviceinfo(const serviceinfo& _other) : group_(_other.group_), + service_(_other.service_), + instance_(_other.instance_), major_(_other.major_), minor_(_other.minor_), ttl_(_other.ttl_), @@ -45,6 +50,14 @@ void serviceinfo::set_group(servicegroup *_group) { group_ = _group; } +service_t serviceinfo::get_service() const { + return service_; +} + +instance_t serviceinfo::get_instance() const { + return instance_; +} + major_version_t serviceinfo::get_major() const { return major_; } @@ -80,7 +93,7 @@ std::shared_ptr<endpoint> serviceinfo::get_endpoint(bool _reliable) const { return (_reliable ? reliable_ : unreliable_); } -void serviceinfo::set_endpoint(std::shared_ptr<endpoint> _endpoint, +void serviceinfo::set_endpoint(const std::shared_ptr<endpoint>& _endpoint, bool _reliable) { std::lock_guard<std::mutex> its_lock(endpoint_mutex_); if (_reliable) { @@ -117,5 +130,4 @@ void serviceinfo::set_is_in_mainphase(bool _in_mainphase) { is_in_mainphase_ = _in_mainphase; } -} // namespace vsomeip - +} // namespace vsomeip_v3 |