summaryrefslogtreecommitdiff
path: root/implementation/routing
diff options
context:
space:
mode:
Diffstat (limited to 'implementation/routing')
-rw-r--r--implementation/routing/include/event.hpp50
-rw-r--r--implementation/routing/include/eventgroupinfo.hpp4
-rw-r--r--implementation/routing/include/function_types.hpp7
-rw-r--r--implementation/routing/include/remote_subscription.hpp3
-rw-r--r--implementation/routing/include/routing_host.hpp13
-rw-r--r--implementation/routing/include/routing_manager.hpp43
-rw-r--r--implementation/routing/include/routing_manager_adapter.hpp2
-rw-r--r--implementation/routing/include/routing_manager_base.hpp126
-rw-r--r--implementation/routing/include/routing_manager_client.hpp (renamed from implementation/routing/include/routing_manager_proxy.hpp)107
-rw-r--r--implementation/routing/include/routing_manager_host.hpp30
-rw-r--r--implementation/routing/include/routing_manager_impl.hpp155
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp136
-rw-r--r--implementation/routing/include/routing_manager_stub_host.hpp96
-rw-r--r--implementation/routing/include/serviceinfo.hpp8
-rw-r--r--implementation/routing/include/types.hpp18
-rw-r--r--implementation/routing/src/event.cpp615
-rw-r--r--implementation/routing/src/eventgroupinfo.cpp72
-rw-r--r--implementation/routing/src/remote_subscription.cpp3
-rw-r--r--implementation/routing/src/routing_manager_base.cpp346
-rw-r--r--implementation/routing/src/routing_manager_client.cpp2890
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp1160
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp2734
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp2550
-rw-r--r--implementation/routing/src/serviceinfo.cpp14
24 files changed, 6125 insertions, 5057 deletions
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp
index b22b6ed..97adb89 100644
--- a/implementation/routing/include/event.hpp
+++ b/implementation/routing/include/event.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -13,7 +13,6 @@
#include <set>
#include <atomic>
-#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/steady_timer.hpp>
@@ -35,6 +34,8 @@ class message;
class payload;
class routing_manager;
+struct debounce_filter_t;
+
class event
: public std::enable_shared_from_this<event> {
public:
@@ -52,16 +53,19 @@ public:
event_t get_event() const;
void set_event(event_t _event);
- const std::shared_ptr<payload> get_payload() const;
+ std::shared_ptr<payload> get_payload() const;
void set_payload(const std::shared_ptr<payload> &_payload,
const client_t _client, bool _force);
void set_payload(const std::shared_ptr<payload> &_payload,
const client_t _client,
- const std::shared_ptr<endpoint_definition>& _target, bool _force);
+ const std::shared_ptr<endpoint_definition>& _target);
+
+ bool prepare_update_payload(const std::shared_ptr<payload> &_payload,
+ bool _force);
+ void update_payload();
- 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);
@@ -90,20 +94,25 @@ public:
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() 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(client_t _client,
const std::shared_ptr<endpoint_definition> &_target);
- void notify_one(client_t _client);
+ void notify_one(client_t _client, bool _force);
- bool add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _force);
+ bool add_subscriber(eventgroup_t _eventgroup,
+ const std::shared_ptr<debounce_filter_t> &_filter,
+ 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_filtered_subscribers(bool _force);
+ std::set<client_t> update_and_get_filtered_subscribers(
+ const std::shared_ptr<payload> &_payload, bool _force);
VSOMEIP_EXPORT std::set<client_t> get_subscribers(eventgroup_t _eventgroup);
void clear_subscribers();
@@ -122,30 +131,34 @@ public:
void remove_pending(const std::shared_ptr<endpoint_definition> &_target);
+ void set_session();
+
private:
void update_cbk(boost::system::error_code const &_error);
- void notify();
+ void notify(bool _force);
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,
+ bool has_changed(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);
- void reset_payload(const std::shared_ptr<payload> &_payload);
-
- void notify_one_unlocked(client_t _client);
+ void notify_one_unlocked(client_t _client, bool _force);
void notify_one_unlocked(client_t _client,
const std::shared_ptr<endpoint_definition> &_target);
+ bool prepare_update_payload_unlocked(
+ const std::shared_ptr<payload> &_payload, bool _force);
+ void update_payload_unlocked();
+
private:
routing_manager *routing_;
mutable std::mutex mutex_;
- std::shared_ptr<message> message_;
+
+ std::shared_ptr<message> current_;
+ std::shared_ptr<message> update_;
std::atomic<event_type_e> type_;
@@ -172,6 +185,11 @@ private:
std::atomic<reliability_type_e> reliability_;
std::set<std::shared_ptr<endpoint_definition> > pending_;
+
+ std::mutex filters_mutex_;
+ std::map<client_t, epsilon_change_func_t> filters_;
+ std::mutex last_forwarded_mutex_;
+ std::map<client_t, std::chrono::steady_clock::time_point> last_forwarded_;
};
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp
index 8ec1ac6..1a5a1b9 100644
--- a/implementation/routing/include/eventgroupinfo.hpp
+++ b/implementation/routing/include/eventgroupinfo.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -67,7 +67,7 @@ public:
uint16_t _port);
VSOMEIP_EXPORT bool is_sending_multicast() const;
- VSOMEIP_EXPORT const std::set<std::shared_ptr<event> > get_events() const;
+ VSOMEIP_EXPORT std::set<std::shared_ptr<event> > get_events() 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;
diff --git a/implementation/routing/include/function_types.hpp b/implementation/routing/include/function_types.hpp
index 3f89c08..f74ff37 100644
--- a/implementation/routing/include/function_types.hpp
+++ b/implementation/routing/include/function_types.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2018-2021 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/.
@@ -10,9 +10,8 @@ namespace vsomeip_v3 {
class remote_subscription;
-typedef std::function<
- void (const std::shared_ptr<remote_subscription> &_subscription)
-> remote_subscription_callback_t;
+using remote_subscription_callback_t =
+ std::function<void (const std::shared_ptr<remote_subscription> &_subscription)>;
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/remote_subscription.hpp b/implementation/routing/include/remote_subscription.hpp
index ff94d5b..f5bf2a2 100644
--- a/implementation/routing/include/remote_subscription.hpp
+++ b/implementation/routing/include/remote_subscription.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2018-2021 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/.
@@ -100,7 +100,6 @@ private:
std::weak_ptr<eventgroupinfo> eventgroupinfo_;
- major_version_t major_;
ttl_t ttl_;
std::uint16_t reserved_;
std::uint8_t counter_;
diff --git a/implementation/routing/include/routing_host.hpp b/implementation/routing/include/routing_host.hpp
index 337e4a7..1decea3 100644
--- a/implementation/routing/include/routing_host.hpp
+++ b/implementation/routing/include/routing_host.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -11,6 +11,7 @@
#include <boost/asio/ip/address.hpp>
#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/vsomeip_sec.h>
#ifdef ANDROID
#include "../../configuration/include/internal_android.hpp"
@@ -28,15 +29,19 @@ public:
virtual void on_message(const byte_t *_data, length_t _length,
endpoint *_receiver,
- const boost::asio::ip::address &_destination =
- boost::asio::ip::address(),
+ bool _is_multicast = false,
client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- credentials_t _credentials = {ANY_UID, ANY_GID},
+ const vsomeip_sec_client_t *_sec_client = nullptr,
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;
+ virtual void add_known_client(client_t _client, const std::string &_client_host) = 0;
+
+ virtual void remove_subscriptions(port_t _local_port,
+ const boost::asio::ip::address &_remote_address,
+ port_t _remote_port) = 0;
};
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp
index fa0e675..6fa7693 100644
--- a/implementation/routing/include/routing_manager.hpp
+++ b/implementation/routing/include/routing_manager.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -10,11 +10,19 @@
#include <set>
#include <vector>
-#include <boost/asio/io_service.hpp>
+#if VSOMEIP_BOOST_VERSION < 106600
+# include <boost/asio/io_service.hpp>
+# define io_context io_service
+#else
+# include <boost/asio/io_context.hpp>
+#endif
#include <vsomeip/function_types.hpp>
+#include <vsomeip/structured_types.hpp>
#include <vsomeip/message.hpp>
#include <vsomeip/handler.hpp>
+#include <vsomeip/vsomeip_sec.h>
+
#include "types.hpp"
namespace vsomeip_v3 {
@@ -30,10 +38,12 @@ public:
virtual ~routing_manager() {
}
- virtual boost::asio::io_service & get_io() = 0;
+ virtual boost::asio::io_context &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 set_client(const client_t &_client) = 0;
+ virtual session_t get_session(bool _is_request) = 0;
+
+ virtual const vsomeip_sec_client_t *get_sec_client() const = 0;
virtual void init() = 0;
virtual void start() = 0;
@@ -54,24 +64,29 @@ public:
virtual void release_service(client_t _client, service_t _service,
instance_t _instance) = 0;
- 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) = 0;
+ virtual void subscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter) = 0;
- 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 unsubscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event) = 0;
- virtual bool send(client_t _client, std::shared_ptr<message> _message) = 0;
+ virtual bool send(client_t _client, std::shared_ptr<message> _message,
+ bool _force) = 0;
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
instance_t _instance, bool _reliable,
client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- credentials_t _credentials = {ANY_UID, ANY_GID},
- uint8_t _status_check = 0, bool _sent_from_remote = false) = 0;
+ const vsomeip_sec_client_t *_sec_client = nullptr,
+ uint8_t _status_check = 0,
+ bool _sent_from_remote = false,
+ bool _force = true) = 0;
virtual bool send_to(const client_t _client,
const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message>) = 0;
+ std::shared_ptr<message> _message) = 0;
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, instance_t _instance) = 0;
diff --git a/implementation/routing/include/routing_manager_adapter.hpp b/implementation/routing/include/routing_manager_adapter.hpp
index a2195ee..26154b0 100644
--- a/implementation/routing/include/routing_manager_adapter.hpp
+++ b/implementation/routing/include/routing_manager_adapter.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp
index 270f4c4..e4f9073 100644
--- a/implementation/routing/include/routing_manager_base.hpp
+++ b/implementation/routing/include/routing_manager_base.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -12,16 +12,19 @@
#include <condition_variable>
#include <vsomeip/constants.hpp>
+#include <vsomeip/vsomeip_sec.h>
-#include "routing_host.hpp"
-#include "routing_manager.hpp"
-#include "routing_manager_host.hpp"
#include "types.hpp"
-#include "serviceinfo.hpp"
#include "event.hpp"
+#include "serviceinfo.hpp"
+#include "routing_host.hpp"
#include "eventgroupinfo.hpp"
+#include "routing_manager.hpp"
+#include "routing_manager_host.hpp"
+
#include "../../message/include/serializer.hpp"
#include "../../message/include/deserializer.hpp"
+#include "../../protocol/include/protocol.hpp"
#include "../../configuration/include/configuration.hpp"
#include "../../endpoints/include/endpoint_manager_base.hpp"
@@ -43,10 +46,19 @@ public:
routing_manager_base(routing_manager_host *_host);
virtual ~routing_manager_base() = default;
- virtual boost::asio::io_service & get_io();
+ virtual boost::asio::io_context &get_io();
virtual client_t get_client() const;
+
+ virtual std::string get_client_host() const;
+ virtual void set_client_host(const std::string &_client_host);
virtual void set_client(const client_t &_client);
- virtual session_t get_session();
+ virtual session_t get_session(bool _is_request);
+
+ virtual const vsomeip_sec_client_t *get_sec_client() const;
+
+ virtual std::string get_env(client_t _client) const = 0;
+
+ virtual bool is_routing_manager() const;
virtual void init() = 0;
void init(const std::shared_ptr<endpoint_manager_base>& _endpoint_manager);
@@ -83,11 +95,14 @@ public:
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, uid_t _uid, gid_t _gid,
+ virtual void subscribe(client_t _client,
+ const vsomeip_sec_client_t *_sec_client,
service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major, event_t _event);
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter);
- virtual void unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ virtual void unsubscribe(client_t _client,
+ const vsomeip_sec_client_t *_sec_client,
service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
@@ -102,23 +117,22 @@ public:
#endif
);
- virtual bool send(client_t _client, std::shared_ptr<message> _message);
+ virtual bool send(client_t _client, std::shared_ptr<message> _message,
+ bool _force);
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
instance_t _instance, bool _reliable,
- client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- credentials_t _credentials = {ANY_UID, ANY_GID},
- uint8_t _status_check = 0, bool _sent_from_remote = false) = 0;
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ uint8_t _status_check, bool _sent_from_remote,
+ bool _force) = 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(),
+ endpoint *_receiver, bool _is_multicast,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port = 0) = 0;
-
virtual void set_routing_state(routing_state_e _routing_state) = 0;
virtual routing_state_e get_routing_state();
@@ -138,6 +152,17 @@ public:
std::shared_ptr<event> find_event(service_t _service, instance_t _instance,
event_t _event) const;
+ // address data for vsomeip routing via TCP
+ bool get_guest(client_t _client, boost::asio::ip::address &_address,
+ port_t &_port) const;
+ void add_guest(client_t _client, const boost::asio::ip::address &_address,
+ port_t _port);
+ void remove_guest(client_t _client);
+
+ void remove_subscriptions(port_t _local_port,
+ const boost::asio::ip::address &_remote_address,
+ port_t _remote_port);
+
virtual void on_connect(const std::shared_ptr<endpoint>& _endpoint) = 0;
virtual void on_disconnect(const std::shared_ptr<endpoint>& _endpoint) = 0;
protected:
@@ -150,10 +175,12 @@ protected:
services_t get_services_remote() const;
bool is_available(service_t _service, instance_t _instance, major_version_t _major);
- void remove_local(client_t _client, bool _remove_uid);
+ void remove_local(client_t _client, bool _remove_sec_client);
void remove_local(client_t _client,
- const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups,
- bool _remove_uid);
+ const std::set<
+ std::tuple<service_t, instance_t, eventgroup_t>
+ > &_subscribed_eventgroups,
+ bool _remove_sec_client);
std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) const;
@@ -163,15 +190,16 @@ protected:
bool send_local_notification(client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _reliable = false, uint8_t _status_check = 0);
+ bool _reliable, uint8_t _status_check, bool _force);
bool send_local(
std::shared_ptr<endpoint> &_target, client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _reliable, uint8_t _command, uint8_t _status_check = 0) const;
+ bool _reliable, protocol::id_e _command, uint8_t _status_check) const;
bool insert_subscription(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, event_t _event, client_t _client,
+ eventgroup_t _eventgroup, event_t _event,
+ const std::shared_ptr<debounce_filter_t> &_filter, client_t _client,
std::set<event_t> *_already_subscribed_events);
std::shared_ptr<serializer> get_serializer();
@@ -182,9 +210,10 @@ protected:
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) = 0;
+ virtual void send_subscribe(client_t _client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter) = 0;
void remove_pending_subscription(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
@@ -209,9 +238,11 @@ protected:
bool is_response_allowed(client_t _sender, service_t _service,
instance_t _instance, method_t _method);
- bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
+ bool is_subscribe_to_any_event_allowed(
+ const vsomeip_sec_client_t *_sec_client, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup);
- void unsubscribe_all(service_t _service, instance_t _instance);
+
+ void add_known_client(client_t _client, const std::string &_client_host);
#ifdef VSOMEIP_ENABLE_COMPAT
void set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
@@ -227,12 +258,12 @@ protected:
private:
virtual bool create_placeholder_event_and_subscribe(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, client_t _client) = 0;
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter,
+ client_t _client) = 0;
protected:
routing_manager_host *host_;
- boost::asio::io_service &io_;
- std::atomic<client_t> client_;
+ boost::asio::io_context &io_;
std::shared_ptr<configuration> configuration_;
@@ -245,8 +276,9 @@ protected:
std::condition_variable deserializer_condition_;
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;
+ using local_services_map_t =
+ std::map<service_t, std::map<instance_t,
+ std::tuple<major_version_t, minor_version_t, client_t>>>;
local_services_map_t local_services_;
std::map<service_t, std::map<instance_t, std::set<client_t> > > local_services_history_;
@@ -264,9 +296,6 @@ protected:
std::mutex event_registration_mutex_;
- std::mutex routing_state_mutex_;
- routing_state_e routing_state_;
-
#ifdef USE_DLT
std::shared_ptr<trace::connector_impl> tc_;
#endif
@@ -277,8 +306,8 @@ protected:
eventgroup_t eventgroup_;
major_version_t major_;
event_t event_;
- uid_t uid_;
- gid_t gid_;
+ std::shared_ptr<debounce_filter_t> filter_;
+ vsomeip_sec_client_t sec_client_;
bool operator<(const subscription_data_t &_other) const {
return (service_ < _other.service_
@@ -300,13 +329,26 @@ protected:
std::shared_ptr<endpoint_manager_base> ep_mgr_;
- std::uint32_t own_uid_;
- std::uint32_t own_gid_;
+ mutable std::mutex known_clients_mutex_;
+ std::map<client_t, std::string> known_clients_;
+
+ mutable std::mutex env_mutex_;
+ std::string env_;
+
+ std::mutex routing_state_mutex_;
+ routing_state_e routing_state_;
private:
services_t services_;
mutable std::mutex services_mutex_;
+ mutable std::mutex guests_mutex_;
+ std::map<client_t,
+ std::pair<boost::asio::ip::address, port_t>
+ > guests_;
+
+ std::mutex add_known_client_mutex_;
+
#ifdef VSOMEIP_ENABLE_COMPAT
std::map<service_t,
std::map<instance_t,
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_client.hpp
index 2b5335a..fb56ec7 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_client.hpp
@@ -1,41 +1,53 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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_MANAGER_PROXY_HPP
-#define VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_CLIENT_HPP
+#define VSOMEIP_V3_ROUTING_MANAGER_CLIENT_HPP
#include <map>
#include <mutex>
#include <atomic>
#include <tuple>
-#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
-#include "routing_manager_base.hpp"
-#include "types.hpp"
#include <vsomeip/enumeration_types.hpp>
#include <vsomeip/handler.hpp>
+#include "routing_manager_base.hpp"
+#include "types.hpp"
+#include "../../protocol/include/protocol.hpp"
+
namespace vsomeip_v3 {
class configuration;
class event;
+#ifdef __linux__
+class netlink_connector;
+#endif
class routing_manager_host;
-class routing_manager_proxy: public routing_manager_base {
+namespace protocol {
+ class offered_services_response_command;
+ class update_security_credentials_command;
+}
+
+class routing_manager_client
+ : public routing_manager_base {
public:
- routing_manager_proxy(routing_manager_host *_host, bool _client_side_logging,
+ routing_manager_client(routing_manager_host *_host, bool _client_side_logging,
const std::set<std::tuple<service_t, instance_t> > & _client_side_logging_filter);
- virtual ~routing_manager_proxy();
+ virtual ~routing_manager_client();
void init();
void start();
void stop();
std::shared_ptr<configuration> get_configuration() const;
+ std::string get_env(client_t _client) const;
+ std::string get_env_unlocked(client_t _client) const;
bool offer_service(client_t _client,
service_t _service, instance_t _instance,
@@ -52,20 +64,20 @@ public:
void release_service(client_t _client,
service_t _service, instance_t _instance);
- void subscribe(client_t _client, uid_t _uid, gid_t _gid,
+ void subscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
service_t _service, instance_t _instance,
eventgroup_t _eventgroup, major_version_t _major,
- event_t _event);
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter);
- void unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ void unsubscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
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 _reliable,
- client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- credentials_t _credentials = {ANY_UID, ANY_GID},
- uint8_t _status_check = 0, bool _sent_from_remote = false);
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ uint8_t _status_check, bool _sent_from_remote,
+ bool _force);
bool send_to(const client_t _client,
const std::shared_ptr<endpoint_definition> &_target,
@@ -91,9 +103,8 @@ public:
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,
+ bool _is_multicast,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
@@ -103,7 +114,7 @@ public:
const std::shared_ptr<endpoint> &_endpoint);
void handle_client_error(client_t _client);
- void on_offered_services_info(const byte_t *_data, uint32_t _size);
+ void on_offered_services_info(protocol::offered_services_response_command &_command);
void send_get_offered_services_info(client_t _client, offer_type_e _offer_type);
@@ -112,23 +123,30 @@ private:
void register_application();
void deregister_application();
- void reconnect(const std::unordered_set<client_t> &_clients);
+ void reconnect(const std::map<client_t, std::string> &_clients);
void send_pong() const;
+
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_pending_event_registrations(client_t _client);
+
void send_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,
- 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);
+ bool _is_provided, bool _is_cyclic);
+
+ void send_subscribe(client_t _client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter);
void send_subscribe_nack(client_t _subscriber, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
@@ -176,12 +194,13 @@ 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 _notifier, client_t _client);
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ event_t _notifier, const std::shared_ptr<debounce_filter_t> &_filter,
+ 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_request_services(const std::set<protocol::service> &_requests);
void send_unsubscribe_ack(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, remote_subscription_id_t _id);
@@ -189,14 +208,23 @@ private:
void resend_provided_event_registrations();
void send_resend_provided_event_response(pending_remote_offer_id_t _id);
+#ifndef VSOMEIP_DISABLE_SECURITY
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_update_security_credentials(const protocol::update_security_credentials_command &_command);
+#endif
void on_client_assign_ack(const client_t &_client);
+ port_t get_routing_port();
+
void on_suspend();
+#if defined(__linux__) || defined(ANDROID)
+ void on_net_state_change(bool _is_interface, const std::string &_name, bool _is_available);
+#endif
+
private:
+
enum class inner_state_type_e : std::uint8_t {
ST_REGISTERED = 0x0,
ST_DEREGISTERED = 0x1,
@@ -212,12 +240,9 @@ private:
std::shared_ptr<endpoint> sender_; // --> stub
std::shared_ptr<endpoint> receiver_; // --> from everybody
- std::mutex known_clients_mutex_;
- std::unordered_set<client_t> known_clients_;
-
- std::set<service_data_t> pending_offers_;
- std::set<service_data_t> requests_;
- std::set<service_data_t> requests_to_debounce_;
+ std::set<protocol::service> pending_offers_;
+ std::set<protocol::service> requests_;
+ std::set<protocol::service> requests_to_debounce_;
struct event_data_t {
service_t service_;
@@ -226,19 +251,20 @@ private:
event_type_e type_;
reliability_type_e reliability_;
bool is_provided_;
+ bool is_cyclic_;
std::set<eventgroup_t> eventgroups_;
bool operator<(const event_data_t &_other) const {
return std::tie(service_, instance_, notifier_,
- type_, reliability_, is_provided_, eventgroups_)
+ type_, reliability_, is_provided_, is_cyclic_, eventgroups_)
< std::tie(_other.service_, _other.instance_,
_other.notifier_, _other.type_, _other.reliability_,
- _other.is_provided_, _other.eventgroups_);
+ _other.is_provided_, _other.is_cyclic_, _other.eventgroups_);
}
};
std::set<event_data_t> pending_event_registrations_;
- std::map<client_t, std::set<subscription_data_t>> pending_incoming_subscripitons_;
+ std::map<client_t, std::set<subscription_data_t>> pending_incoming_subscriptions_;
std::recursive_mutex incoming_subscriptions_mutex_;
std::mutex state_mutex_;
@@ -260,8 +286,13 @@ private:
const std::set<std::tuple<service_t, instance_t> > client_side_logging_filter_;
std::mutex stop_mutex_;
+
+#if defined(__linux__) || defined(ANDROID)
+ std::shared_ptr<netlink_connector> local_link_connector_;
+ bool is_local_link_available_;
+#endif
};
} // namespace vsomeip_v3
-#endif // VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP_
+#endif // VSOMEIP_V3_ROUTING_MANAGER_CLIENT_HPP_
diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp
index 69133e2..18a74af 100644
--- a/implementation/routing/include/routing_manager_host.hpp
+++ b/implementation/routing/include/routing_manager_host.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -8,9 +8,15 @@
#include <memory>
-#include <boost/asio/io_service.hpp>
+#if VSOMEIP_BOOST_VERSION < 106600
+# include <boost/asio/io_service.hpp>
+# define io_context io_service
+#else
+# include <boost/asio/io_context.hpp>
+#endif
#include <vsomeip/error.hpp>
+#include <vsomeip/vsomeip_sec.h>
namespace vsomeip_v3 {
@@ -24,22 +30,30 @@ public:
virtual client_t get_client() const = 0;
virtual void set_client(const client_t &_client) = 0;
- virtual session_t get_session() = 0;
+ virtual session_t get_session(bool _is_request) = 0;
+
+ virtual const vsomeip_sec_client_t *get_sec_client() const = 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;
+ virtual boost::asio::io_context &get_io() = 0;
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;
+ availability_state_e _state,
+ 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(std::shared_ptr<message> &&_message) = 0;
virtual void on_subscription(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, client_t _client, uid_t _uid, gid_t _gid, bool _subscribed,
- std::function<void(bool)> _accepted_cb) = 0;
+ eventgroup_t _eventgroup,
+ client_t _client, const vsomeip_sec_client_t *_sec_client,
+ const std::string &_env, bool _subscribed,
+ const 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) = 0;
- virtual void on_offered_services_info(std::vector<std::pair<service_t, instance_t>> &_services) = 0;
+ virtual void on_offered_services_info(
+ std::vector<std::pair<service_t, instance_t>> &_services) = 0;
virtual bool is_routing() const = 0;
};
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index 3fd6eed..3c105c2 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -14,7 +14,6 @@
#include <unordered_set>
#include <boost/asio/ip/address.hpp>
-#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
#include <vsomeip/primitive_types.hpp>
@@ -36,7 +35,6 @@ class deserializer;
class eventgroupinfo;
class routing_manager_host;
class routing_manager_stub;
-class servicegroup;
class serializer;
class service_endpoint;
@@ -55,8 +53,13 @@ public:
routing_manager_impl(routing_manager_host *_host);
~routing_manager_impl();
- boost::asio::io_service & get_io();
+ boost::asio::io_context &get_io();
client_t get_client() const;
+ const vsomeip_sec_client_t *get_sec_client() const;
+ std::string get_client_host() const;
+ void set_client_host(const std::string &_client_host);
+
+ bool is_routing_manager() const;
void init();
void start();
@@ -77,21 +80,23 @@ public:
void release_service(client_t _client,
service_t _service, instance_t _instance);
- void subscribe(client_t _client, uid_t _uid, gid_t _gid,
+ void subscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major, event_t _event);
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter);
- void unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ void unsubscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
- bool send(client_t _client, std::shared_ptr<message> _message);
+ bool send(client_t _client, std::shared_ptr<message> _message,
+ bool _force);
bool send(client_t _client, const byte_t *_data, uint32_t _size,
instance_t _instance, bool _reliable,
- client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- credentials_t _credentials = {ANY_UID, ANY_GID},
- uint8_t _status_check = 0, bool _sent_from_remote = false);
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ uint8_t _status_check, bool _sent_from_remote,
+ bool _force);
bool send_to(const client_t _client,
const std::shared_ptr<endpoint_definition> &_target,
@@ -120,7 +125,7 @@ public:
event_t _notifier,
const std::set<eventgroup_t> &_eventgroups,
event_type_e _type, reliability_type_e _reliability,
- bool _is_provided);
+ bool _is_provided, bool _is_cyclic);
void unregister_shadow_event(client_t _client, service_t _service,
instance_t _instance, event_t _event,
@@ -140,7 +145,7 @@ public:
void on_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- remote_subscription_id_t _id, bool _simulated);
+ remote_subscription_id_t _id);
// interface to stub
@@ -161,7 +166,7 @@ public:
major_version_t _major, minor_version_t _minor);
void on_availability(service_t _service, instance_t _instance,
- bool _is_available,
+ availability_state_e _state,
major_version_t _major, minor_version_t _minor);
void on_pong(client_t _client);
@@ -178,13 +183,13 @@ public:
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);
+ bool _is_multicast,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ const boost::asio::ip::address &_remote_address,
+ std::uint16_t _remote_port);
bool on_message(service_t _service, instance_t _instance,
const byte_t *_data, length_t _size, bool _reliable,
- client_t _bound_client, credentials_t _credentials,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
uint8_t _check_status = 0,
bool _is_from_remote = false);
void on_notification(client_t _client, service_t _service,
@@ -199,8 +204,6 @@ public:
bool _magic_cookies_enabled);
// interface "service_discovery_host"
- typedef std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_t;
- const servicegroups_t & get_servicegroups() const;
std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) const;
services_t get_offered_services() const;
@@ -285,15 +288,27 @@ public:
void on_resend_provided_events_response(pending_remote_offer_id_t _id);
client_t find_local_client(service_t _service, instance_t _instance);
std::set<client_t> find_local_clients(service_t _service, instance_t _instance);
- bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
+ bool is_subscribe_to_any_event_allowed(
+ const vsomeip_sec_client_t *_sec_client, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup);
+#ifndef VSOMEIP_DISABLE_SECURITY
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);
+#endif
+
+ void add_known_client(client_t _client, const std::string &_client_host);
+
+ void register_message_acceptance_handler(
+ const message_acceptance_handler_t &_handler);
+
+ void remove_subscriptions(port_t _local_port,
+ const boost::asio::ip::address &_remote_address,
+ port_t _remote_port);
private:
bool offer_service(client_t _client,
@@ -307,12 +322,12 @@ private:
bool _must_queue);
bool deliver_message(const byte_t *_data, length_t _size,
- instance_t _instance, bool _reliable, client_t _bound_client,
- credentials_t _credentials,
+ instance_t _instance, bool _reliable,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
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,
- credentials_t _credentials,
+ const byte_t *_data, length_t _length, bool _reliable,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
uint8_t _status_check = 0, bool _is_from_remote = false);
@@ -351,38 +366,49 @@ private:
bool handle_local_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,minor_version_t _minor);
- void send_subscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event);
+ void send_subscribe(client_t _client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter);
void on_net_interface_or_route_state_changed(bool _is_interface,
- std::string _if,
+ const std::string &_if,
bool _available);
void start_ip_routing();
- void requested_service_add(client_t _client, service_t _service,
+ void add_requested_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor);
- void requested_service_remove(client_t _client, service_t _service,
- instance_t _instance);
-
- void call_sd_endpoint_connected(const boost::system::error_code& _error,
- service_t _service, instance_t _instance,
- const std::shared_ptr<endpoint>& _endpoint,
- std::shared_ptr<boost::asio::steady_timer> _timer);
+ void remove_requested_service(client_t _client, service_t _service,
+ instance_t _instance, major_version_t _major,
+ minor_version_t _minor);
+ std::vector<std::pair<service_t, instance_t>> get_requested_services(client_t _client);
+ std::set<client_t> get_requesters(service_t _service,
+ instance_t _instance, major_version_t _major,
+ minor_version_t _minor);
+ std::set<client_t> get_requesters_unlocked(service_t _service,
+ instance_t _instance, major_version_t _major,
+ minor_version_t _minor);
+ bool has_requester_unlocked(service_t _service,
+ instance_t _instance, major_version_t _major,
+ minor_version_t _minor);
+
+ void call_sd_endpoint_connected(const boost::system::error_code &_error,
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<endpoint> &_endpoint,
+ std::shared_ptr<boost::asio::steady_timer> _timer);
- 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 _event, const std::shared_ptr<debounce_filter_t> &_filter,
+ client_t _client);
void handle_subscription_state(client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
- void memory_log_timer_cbk(boost::system::error_code const & _error);
- void status_log_timer_cbk(boost::system::error_code const & _error);
+ 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(const client_t _offering_client,
const service_t _service, const instance_t _instance,
@@ -416,25 +442,48 @@ private:
bool is_last_stop_callback(const uint32_t _callback_id);
+ std::string get_env(client_t _client) const;
+ std::string get_env_unlocked(client_t _client) const;
+
bool insert_event_statistics(service_t _service, instance_t _instance,
method_t _method, length_t _length);
void statistics_log_timer_cbk(boost::system::error_code const & _error);
+ bool get_guest(client_t _client, boost::asio::ip::address &_address,
+ port_t &_port) const;
+ void add_guest(client_t _client, const boost::asio::ip::address &_address,
+ port_t _port);
+ void remove_guest(client_t _client);
+
void send_suspend() const;
+ void clear_local_services();
+
+ bool is_acl_message_allowed(endpoint *_receiver,
+ service_t _service, instance_t _instance,
+ const boost::asio::ip::address &_remote_address) const;
+
private:
std::shared_ptr<routing_manager_stub> stub_;
std::shared_ptr<sd::service_discovery> discovery_;
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_;
+ std::map<service_t,
+ std::map<instance_t,
+ std::map<major_version_t,
+ std::map<minor_version_t, std::set<client_t> >
+ >
+ >
+ > requested_services_;
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::map<service_t,
+ std::map<instance_t,
+ std::map<client_t,
+ std::set<std::shared_ptr<endpoint_definition> >
+ >
+ >
+ > remote_subscribers_;
std::shared_ptr<serviceinfo> sd_info_;
@@ -446,7 +495,7 @@ private:
bool routing_running_;
std::mutex pending_sd_offers_mutex_;
std::vector<std::pair<service_t, instance_t>> pending_sd_offers_;
-#ifndef _WIN32
+#if defined(__linux__) || defined(ANDROID)
std::shared_ptr<netlink_connector> netlink_connector_;
#endif
@@ -503,6 +552,8 @@ private:
// synchronize update_remote_subscription() and send_(un)subscription()
std::mutex update_remote_subscription_mutex_;
+
+ message_acceptance_handler_t message_acceptance_handler_;
};
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index aa5796e..4209eec 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -16,22 +16,34 @@
#include <atomic>
#include <unordered_set>
-#include <boost/asio/io_service.hpp>
+#if VSOMEIP_BOOST_VERSION < 106600
+# include <boost/asio/io_service.hpp>
+# define io_context io_service
+#else
+# include <boost/asio/io_context.hpp>
+#endif
#include <boost/asio/steady_timer.hpp>
#include <vsomeip/handler.hpp>
-
-#include "../../endpoints/include/endpoint_host.hpp"
-#include "../include/routing_host.hpp"
+#include <vsomeip/vsomeip_sec.h>
#include "types.hpp"
+#include "../include/routing_host.hpp"
+#include "../../endpoints/include/endpoint_host.hpp"
+#include "../../protocol/include/protocol.hpp"
+#include "../../protocol/include/routing_info_entry.hpp"
namespace vsomeip_v3 {
class configuration;
-struct policy;
+#if defined(__linux__) || defined(ANDROID)
+class netlink_connector;
+#endif // __linux__ || ANDROID
class routing_manager_stub_host;
+struct debounce_filter_t;
+struct policy;
+
class routing_manager_stub: public routing_host,
public std::enable_shared_from_this<routing_manager_stub> {
public:
@@ -44,10 +56,9 @@ public:
void start();
void stop();
- 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,
+ void on_message(const byte_t *_data, length_t _size,
+ endpoint *_receiver, bool _is_multicast,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
@@ -56,9 +67,11 @@ public:
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(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,
+ 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, const std::shared_ptr<debounce_filter_t> &_filter,
remote_subscription_id_t _id);
bool send_unsubscribe(const std::shared_ptr<endpoint>& _target,
@@ -85,16 +98,18 @@ public:
bool send_ping(client_t _client);
bool is_registered(client_t _client) const;
client_t get_client() const;
- void handle_credentials(const client_t _client, std::set<service_data_t>& _requests);
- void handle_requests(const client_t _client, std::set<service_data_t>& _requests);
+ void handle_credentials(const client_t _client, std::set<protocol::service> &_requests);
+ void handle_requests(const client_t _client, std::set<protocol::service> &_requests);
- void update_registration(client_t _client, registration_type_e _type);
+ void update_registration(client_t _client, registration_type_e _type,
+ const boost::asio::ip::address &_address, port_t _port);
void print_endpoint_status() const;
bool send_provided_event_resend_request(client_t _client,
pending_remote_offer_id_t _id);
+#ifndef VSOMEIP_DISABLE_SECURITY
bool update_security_policy_configuration(uint32_t _uid, uint32_t _gid,
const std::shared_ptr<policy> &_policy,
const std::shared_ptr<payload> &_payload,
@@ -119,23 +134,29 @@ public:
bool add_requester_policies(uid_t _uid, gid_t _gid,
const std::set<std::shared_ptr<policy> > &_policies);
void remove_requester_policies(uid_t _uid, gid_t _gid);
+#endif // !VSOMEIP_DISABLE_SECURITY
+
+ void add_known_client(client_t _client, const std::string &_client_host);
void send_suspend() const;
+ void remove_subscriptions(port_t _local_port,
+ const boost::asio::ip::address &_remote_address,
+ port_t _remote_port);
+
private:
void broadcast(const std::vector<byte_t> &_command) const;
void on_register_application(client_t _client);
void on_deregister_application(client_t _client);
+ void on_offered_service_request(client_t _client, offer_type_e _offer_type);
+
void distribute_credentials(client_t _hoster, service_t _service, instance_t _instance);
- void inform_provider(client_t _hoster, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor,
- routing_info_entry_e _entry);
void inform_requesters(client_t _hoster, service_t _service,
instance_t _instance, major_version_t _major,
- minor_version_t _minor, routing_info_entry_e _entry,
+ minor_version_t _minor, protocol::routing_info_entry_type_e _entry,
bool _inform_service);
void broadcast_ping() const;
@@ -151,27 +172,35 @@ private:
(void)_routing_state;
};
- bool is_already_connected(client_t _source, client_t _sink);
- void create_client_routing_info(const client_t _target);
- void insert_client_routing_info(client_t _target, routing_info_entry_e _entry,
- client_t _client, service_t _service = ANY_SERVICE,
- instance_t _instance = ANY_INSTANCE,
- major_version_t _major = ANY_MAJOR,
- minor_version_t _minor = ANY_MINOR);
- void send_client_routing_info(const client_t _target);
-
- void create_offered_services_info(const client_t _target);
- void insert_offered_services_info(client_t _target,
- routing_info_entry_e _entry,
- service_t _service,
- instance_t _instance,
- major_version_t _major,
- minor_version_t _minor);
- void send_offered_services_info(const client_t _target);
-
- void create_client_credentials_info(const client_t _target);
- void insert_client_credentials_info(client_t _target, std::set<std::pair<uint32_t, uint32_t>> _credentials);
- void send_client_credentials_info(const client_t _target);
+ inline bool is_connected(client_t _source, client_t _sink) const {
+
+ auto find_source = connection_matrix_.find(_source);
+ if (find_source != connection_matrix_.end())
+ return (find_source->second.find(_sink)
+ != find_source->second.end());
+
+ return (false);
+ }
+ inline void add_connection(client_t _source, client_t _sink) {
+
+ connection_matrix_[_source].insert(_sink);
+ }
+ inline void remove_connection(client_t _source, client_t _sink) {
+
+ auto find_source = connection_matrix_.find(_source);
+ if (find_source != connection_matrix_.end())
+ find_source->second.erase(_sink);
+ }
+ inline void remove_source(client_t _source) {
+
+ connection_matrix_.erase(_source);
+ }
+
+ void send_client_routing_info(const client_t _target,
+ protocol::routing_info_entry &_entry);
+ void send_client_routing_info(const client_t _target,
+ std::vector<protocol::routing_info_entry> &&_entries);
+ void send_client_credentials(client_t _target, std::set<std::pair<uint32_t, uint32_t>> &_credentials);
void on_client_id_timer_expired(boost::system::error_code const &_error);
@@ -199,13 +228,17 @@ private:
void add_pending_security_update_handler(
pending_security_update_id_t _id,
- security_update_handler_t _handler);
+ const security_update_handler_t &_handler);
void add_pending_security_update_timer(
pending_security_update_id_t _id);
+#if defined(__linux__) || defined(ANDROID)
+ void on_net_state_change(bool _is_interface, const std::string &_name, bool _is_available);
+#endif
+
private:
routing_manager_stub_host *host_;
- boost::asio::io_service &io_;
+ boost::asio::io_context &io_;
std::mutex watchdog_timer_mutex_;
boost::asio::steady_timer watchdog_timer_;
@@ -213,7 +246,8 @@ private:
std::set<client_t> used_client_ids_;
std::mutex used_client_ids_mutex_;
- std::shared_ptr<endpoint> endpoint_;
+ std::shared_ptr<endpoint> root_; // Routing manager endpoint
+
std::shared_ptr<endpoint> local_receiver_;
std::mutex local_receiver_mutex_;
@@ -229,8 +263,8 @@ private:
std::condition_variable client_registration_condition_;
std::map<client_t, std::vector<registration_type_e>> pending_client_registrations_;
+ std::map<client_t, std::pair<boost::asio::ip::address, port_t> > internal_client_ports_;
const std::uint32_t max_local_message_size_;
- static const std::vector<byte_t> its_ping_;
const std::chrono::milliseconds configured_watchdog_timeout_;
boost::asio::steady_timer pinged_clients_timer_;
std::mutex pinged_clients_mutex_;
@@ -239,10 +273,6 @@ private:
std::map<client_t, std::map<service_t, std::map<instance_t, std::pair<major_version_t, minor_version_t> > > > service_requests_;
std::map<client_t, std::set<client_t>> connection_matrix_;
- std::map<client_t, std::vector<byte_t>> client_routing_info_;
- std::map<client_t, std::vector<byte_t>> offered_services_info_;
- std::map<client_t, std::vector<byte_t>> client_credentials_info_;
-
std::mutex pending_security_updates_mutex_;
pending_security_update_id_t pending_security_update_id_;
std::map<pending_security_update_id_t, std::unordered_set<client_t>> pending_security_updates_;
@@ -262,6 +292,14 @@ private:
std::set<std::shared_ptr<policy> >
>
> requester_policies_;
+
+
+#if defined(__linux__) || defined(ANDROID)
+ // netlink connector for internal network
+ // (replacement for Unix Domain Sockets if configured)
+ std::shared_ptr<netlink_connector> local_link_connector_;
+ bool is_local_link_available_;
+#endif
};
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp
index 6ad0ab1..c55dd86 100644
--- a/implementation/routing/include/routing_manager_stub_host.hpp
+++ b/implementation/routing/include/routing_manager_stub_host.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -6,9 +6,16 @@
#ifndef VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_
#define VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_
-#include <boost/asio/io_service.hpp>
+#if VSOMEIP_BOOST_VERSION < 106600
+# include <boost/asio/io_service.hpp>
+# define io_context io_service
+#else
+# include <boost/asio/io_context.hpp>
+#endif
#include <vsomeip/handler.hpp>
+#include <vsomeip/vsomeip_sec.h>
+
#include "types.hpp"
namespace vsomeip_v3 {
@@ -28,57 +35,59 @@ public:
instance_t _instance, major_version_t _major,
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 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 _notifier,
- const std::set<eventgroup_t> &_eventgroups,
- event_type_e _type, reliability_type_e _reliability,
- bool _is_provided) = 0;
+ virtual void register_shadow_event(client_t _client, service_t _service,
+ instance_t _instance, event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups, event_type_e _type,
+ reliability_type_e _reliability, bool _is_provided,
+ bool _is_cyclic) = 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, uid_t _uid, gid_t _gid, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event) = 0;
+ virtual void subscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ major_version_t _major, event_t _event,
+ const std::shared_ptr<debounce_filter_t> &_filter) = 0;
virtual void on_subscribe_nack(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- remote_subscription_id_t _subscription_id, bool _simulated) = 0;
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ 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,
- remote_subscription_id_t _subscription_id) = 0;
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ remote_subscription_id_t _subscription_id) = 0;
- 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 unsubscribe(client_t _client, const vsomeip_sec_client_t *_sec_client,
+ 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,
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,
- credentials_t _credentials,
+ const byte_t *_data, length_t _size, bool _reliable,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
uint8_t _status_check = 0, bool _is_from_remote = false) = 0;
- virtual void on_notification(client_t _client,
- service_t _service, instance_t _instance,
- const byte_t *_data, length_t _size, bool _notify_one = false) = 0;
+ virtual void on_notification(client_t _client, service_t _service,
+ instance_t _instance, const byte_t *_data, length_t _size,
+ bool _notify_one = false) = 0;
virtual void on_stop_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor) = 0;
virtual void on_availability(service_t _service, instance_t _instance,
- bool _is_available, major_version_t _major, minor_version_t _minor) = 0;
+ availability_state_e _state, major_version_t _major,
+ minor_version_t _minor) = 0;
virtual std::shared_ptr<endpoint> find_local(client_t _client) = 0;
@@ -86,8 +95,9 @@ public:
client_t _client) = 0;
virtual void remove_local(client_t _client, bool _remove_local) = 0;
- virtual boost::asio::io_service & get_io() = 0;
+ virtual boost::asio::io_context& get_io() = 0;
virtual client_t get_client() const = 0;
+ virtual const vsomeip_sec_client_t *get_sec_client() const = 0;
virtual void on_pong(client_t _client) = 0;
@@ -95,14 +105,32 @@ public:
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_resend_provided_events_response(
+ pending_remote_offer_id_t _id) = 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(
+ const vsomeip_sec_client_t *_sec_client,
+ client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup) = 0;
+
+ virtual void add_known_client(client_t _client,
+ const std::string &_client_host) = 0;
- virtual client_t find_local_client(service_t _service, instance_t _instance) = 0;
+ virtual void set_client_host(const std::string &_client_host) = 0;
- virtual std::set<client_t> find_local_clients(service_t _service, instance_t _instance) = 0;
+ virtual bool get_guest(client_t _client,
+ boost::asio::ip::address &_address, port_t &_port) const = 0;
+ virtual void add_guest(client_t _client,
+ const boost::asio::ip::address &_address, port_t _port) = 0;
+ virtual void remove_guest(client_t _client) = 0;
- virtual bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0;
+ virtual void clear_local_services() = 0;
};
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp
index a405cf0..5ea4c18 100644
--- a/implementation/routing/include/serviceinfo.hpp
+++ b/implementation/routing/include/serviceinfo.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -18,7 +18,6 @@
namespace vsomeip_v3 {
class endpoint;
-class servicegroup;
class serviceinfo {
public:
@@ -28,9 +27,6 @@ public:
VSOMEIP_EXPORT serviceinfo(const serviceinfo& _other);
VSOMEIP_EXPORT ~serviceinfo();
- 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;
@@ -57,8 +53,6 @@ public:
VSOMEIP_EXPORT void set_is_in_mainphase(bool _in_mainphase);
private:
- servicegroup *group_;
-
service_t service_;
instance_t instance_;
diff --git a/implementation/routing/include/types.hpp b/implementation/routing/include/types.hpp
index c301b33..d59015c 100644
--- a/implementation/routing/include/types.hpp
+++ b/implementation/routing/include/types.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -18,18 +18,13 @@ namespace vsomeip_v3 {
class serviceinfo;
class endpoint_definition;
-
-typedef std::map<service_t,
- std::map<instance_t,
- std::shared_ptr<serviceinfo> > > services_t;
+using services_t = std::map<service_t, std::map<instance_t, std::shared_ptr<serviceinfo>>>;
class eventgroupinfo;
-typedef std::map<service_t,
- std::map<instance_t,
- std::map<eventgroup_t,
- std::shared_ptr<
- eventgroupinfo> > > > eventgroups_t;
+using eventgroups_t =
+ std::map<service_t,
+ std::map<instance_t, std::map<eventgroup_t, std::shared_ptr<eventgroupinfo>>>>;
enum class registration_type_e : std::uint8_t {
REGISTER = 0x1,
@@ -47,8 +42,7 @@ enum class remote_subscription_state_e : std::uint8_t {
SUBSCRIPTION_UNKNOWN = 0xFF
};
-typedef std::uint16_t remote_subscription_id_t;
-typedef std::uint32_t pending_remote_offer_id_t;
+using remote_subscription_id_t = std::uint16_t;
struct msg_statistic_t {
uint32_t counter_;
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
index b63022c..e4eed17 100644
--- a/implementation/routing/src/event.cpp
+++ b/implementation/routing/src/event.cpp
@@ -1,10 +1,12 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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 <chrono>
#include <iomanip>
#include <sstream>
+#include <thread>
#include <vsomeip/constants.hpp>
#include <vsomeip/defines.hpp>
@@ -21,72 +23,104 @@
namespace vsomeip_v3 {
-event::event(routing_manager *_routing, bool _is_shadow) :
- routing_(_routing),
- message_(runtime::get()->create_notification()),
- type_(event_type_e::ET_EVENT),
- cycle_timer_(_routing->get_io()),
- cycle_(std::chrono::milliseconds::zero()),
- change_resets_cycle_(false),
- is_updating_on_change_(true),
- is_set_(false),
- is_provided_(false),
- is_shadow_(_is_shadow),
- is_cache_placeholder_(false),
- epsilon_change_func_(std::bind(&event::compare, this,
+event::event(routing_manager *_routing, bool _is_shadow)
+ : routing_(_routing),
+ current_(runtime::get()->create_notification()),
+ update_(runtime::get()->create_notification()),
+ type_(event_type_e::ET_EVENT),
+ cycle_timer_(_routing->get_io()),
+ cycle_(std::chrono::milliseconds::zero()),
+ change_resets_cycle_(false),
+ is_updating_on_change_(true),
+ is_set_(false),
+ is_provided_(false),
+ is_shadow_(_is_shadow),
+ is_cache_placeholder_(false),
+ epsilon_change_func_(std::bind(&event::has_changed, this,
std::placeholders::_1, std::placeholders::_2)),
- reliability_(reliability_type_e::RT_UNKNOWN) {
+ reliability_(reliability_type_e::RT_UNKNOWN) {
+
}
-service_t event::get_service() const {
- return (message_->get_service());
+service_t
+event::get_service() const {
+
+ return (current_->get_service());
}
-void event::set_service(service_t _service) {
- message_->set_service(_service);
+void
+event::set_service(service_t _service) {
+
+ current_->set_service(_service);
+ update_->set_service(_service);
}
-instance_t event::get_instance() const {
- return (message_->get_instance());
+instance_t
+event::get_instance() const {
+
+ return (current_->get_instance());
}
-void event::set_instance(instance_t _instance) {
- message_->set_instance(_instance);
+void
+event::set_instance(instance_t _instance) {
+
+ current_->set_instance(_instance);
+ update_->set_instance(_instance);
}
-major_version_t event::get_version() const {
- return message_->get_interface_version();
+major_version_t
+event::get_version() const {
+
+ return current_->get_interface_version();
}
-void event::set_version(major_version_t _major) {
- message_->set_interface_version(_major);
+void
+event::set_version(major_version_t _major) {
+
+ current_->set_interface_version(_major);
+ update_->set_interface_version(_major);
}
-event_t event::get_event() const {
- return (message_->get_method());
+event_t
+event::get_event() const {
+
+ return (current_->get_method());
}
-void event::set_event(event_t _event) {
- message_->set_method(_event);
+void
+event::set_event(event_t _event) {
+
+ current_->set_method(_event);
+ update_->set_method(_event);
}
-event_type_e event::get_type() const {
+event_type_e
+event::get_type() const {
+
return (type_);
}
-void event::set_type(const event_type_e _type) {
+void
+event::set_type(const event_type_e _type) {
+
type_ = _type;
}
-bool event::is_field() const {
+bool
+event::is_field() const {
+
return (type_ == event_type_e::ET_FIELD);
}
-bool event::is_provided() const {
+bool
+event::is_provided() const {
+
return (is_provided_);
}
-void event::set_provided(bool _is_provided) {
+void
+event::set_provided(bool _is_provided) {
+
is_provided_ = _is_provided;
}
@@ -94,122 +128,138 @@ bool event::is_set() const {
return is_set_;
}
-const std::shared_ptr<payload> event::get_payload() const {
+std::shared_ptr<payload>
+event::get_payload() const {
+
std::lock_guard<std::mutex> its_lock(mutex_);
- return (message_->get_payload());
+ return (current_->get_payload());
}
-bool event::set_payload_dont_notify(const std::shared_ptr<payload> &_payload) {
+void
+event::update_payload() {
+
std::lock_guard<std::mutex> its_lock(mutex_);
- if (is_cache_placeholder_) {
- reset_payload(_payload);
- is_set_ = true;
- } else {
- if (set_payload_helper(_payload, false)) {
- reset_payload(_payload);
- } else {
- return false;
- }
- }
- return true;
+ update_payload_unlocked();
+}
+
+void
+event::update_payload_unlocked() {
+
+ current_->set_payload(update_->get_payload());
}
-void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
+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)) {
- reset_payload(_payload);
- if (is_updating_on_change_) {
- if (change_resets_cycle_)
- stop_cycle();
+ if (is_provided_ && prepare_update_payload_unlocked(_payload, _force)) {
+ if (is_updating_on_change_) {
+ if (change_resets_cycle_)
+ stop_cycle();
- notify();
+ notify(_force);
- if (change_resets_cycle_)
- start_cycle();
- }
+ if (change_resets_cycle_)
+ start_cycle();
+
+ update_payload_unlocked();
}
} else {
- VSOMEIP_INFO << "Can't set payload for event "
+ VSOMEIP_INFO << "Cannot set payload for event ["
<< std::hex << std::setw(4) << std::setfill('0')
- << get_service() << "." << get_instance() << "." << get_event()
- << " as it isn't provided";
+ << current_->get_service() << "."
+ << current_->get_instance() << "."
+ << current_->get_method()
+ << "]. It isn't provided";
}
}
-void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _client,
+void
+event::set_payload(const std::shared_ptr<payload> &_payload, client_t _client,
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);
- }
+ if (is_provided_ && prepare_update_payload_unlocked(_payload, _force)) {
+ if (is_updating_on_change_) {
+ notify_one_unlocked(_client, _force);
+ update_payload_unlocked();
}
} else {
- VSOMEIP_INFO << "Can't set payload for event "
+ VSOMEIP_INFO << "Cannot set payload for event ["
<< std::hex << std::setw(4) << std::setfill('0')
- << get_service() << "." << get_instance() << "." << get_event()
- << ". It isn't provided";
+ << current_->get_service() << "."
+ << current_->get_instance() << "."
+ << current_->get_method()
+ << "]. It isn't provided";
}
}
-void event::set_payload(const std::shared_ptr<payload> &_payload,
+void
+event::set_payload(const std::shared_ptr<payload> &_payload,
const client_t _client,
- const std::shared_ptr<endpoint_definition>& _target,
- bool _force) {
+ const std::shared_ptr<endpoint_definition> &_target) {
+
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, _target);
- }
+ if (is_provided_ && prepare_update_payload_unlocked(_payload, false)) {
+ if (is_updating_on_change_) {
+ notify_one_unlocked(_client, _target);
+ update_payload_unlocked();
}
} else {
- VSOMEIP_INFO << "Can't set payload for event "
+ VSOMEIP_INFO << "Cannot set payload for event ["
<< std::hex << std::setw(4) << std::setfill('0')
- << get_service() << "." << get_instance() << "." << get_event()
- << ". It isn't provided";
+ << current_->get_service() << "."
+ << current_->get_instance() << "."
+ << current_->get_method()
+ << "]. It isn't provided";
}
}
-bool event::set_payload_notify_pending(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);
+ if (is_provided_ && !is_set_) {
+
+ update_->set_payload(_payload);
+ is_set_ = true;
// Send pending initial events.
for (const auto &its_target : pending_) {
- message_->set_session(routing_->get_session());
+ set_session();
routing_->send_to(VSOMEIP_ROUTING_CLIENT,
- its_target, message_);
+ its_target, update_);
}
pending_.clear();
- return true;
+ update_payload_unlocked();
+
+ return (true);
}
- return false;
+ return (false);
}
-void event::unset_payload(bool _force) {
+void
+event::unset_payload(bool _force) {
+
std::lock_guard<std::mutex> its_lock(mutex_);
if (_force) {
is_set_ = false;
stop_cycle();
- message_->set_payload(std::make_shared<payload_impl>());
+ current_->set_payload(std::make_shared<payload_impl>());
} else {
if (is_provided_) {
is_set_ = false;
stop_cycle();
- message_->set_payload(std::make_shared<payload_impl>());
+ current_->set_payload(std::make_shared<payload_impl>());
}
}
}
-void event::set_update_cycle(std::chrono::milliseconds &_cycle) {
+void
+event::set_update_cycle(std::chrono::milliseconds &_cycle) {
+
if (is_provided_) {
std::lock_guard<std::mutex> its_lock(mutex_);
stop_cycle();
@@ -218,24 +268,33 @@ void event::set_update_cycle(std::chrono::milliseconds &_cycle) {
}
}
-void event::set_change_resets_cycle(bool _change_resets_cycle) {
+void
+event::set_change_resets_cycle(bool _change_resets_cycle) {
+
change_resets_cycle_ = _change_resets_cycle;
}
-void event::set_update_on_change(bool _is_active) {
+void
+event::set_update_on_change(bool _is_active) {
+
if (is_provided_) {
is_updating_on_change_ = _is_active;
}
}
-void event::set_epsilon_change_function(const epsilon_change_func_t &_epsilon_change_func) {
+void
+event::set_epsilon_change_function(
+ const epsilon_change_func_t &_epsilon_change_func) {
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
if (_epsilon_change_func) {
- std::lock_guard<std::mutex> its_lock(mutex_);
epsilon_change_func_ = _epsilon_change_func;
}
}
-const std::set<eventgroup_t> event::get_eventgroups() const {
+std::set<eventgroup_t>
+event::get_eventgroups() const {
+
std::set<eventgroup_t> its_eventgroups;
{
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
@@ -246,7 +305,9 @@ const std::set<eventgroup_t> event::get_eventgroups() const {
return its_eventgroups;
}
-std::set<eventgroup_t> event::get_eventgroups(client_t _client) const {
+std::set<eventgroup_t>
+event::get_eventgroups(client_t _client) const {
+
std::set<eventgroup_t> its_eventgroups;
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
@@ -257,23 +318,29 @@ std::set<eventgroup_t> event::get_eventgroups(client_t _client) const {
return its_eventgroups;
}
-void event::add_eventgroup(eventgroup_t _eventgroup) {
+void
+event::add_eventgroup(eventgroup_t _eventgroup) {
+
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
if (eventgroups_.find(_eventgroup) == eventgroups_.end())
eventgroups_[_eventgroup] = std::set<client_t>();
}
-void event::set_eventgroups(const std::set<eventgroup_t> &_eventgroups) {
+void
+event::set_eventgroups(const std::set<eventgroup_t> &_eventgroups) {
+
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
for (auto e : _eventgroups)
eventgroups_[e] = std::set<client_t>();
}
-void event::update_cbk(boost::system::error_code const &_error) {
+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();
+ notify(true);
auto its_handler =
std::bind(&event::update_cbk, shared_from_this(),
std::placeholders::_1);
@@ -281,10 +348,12 @@ void event::update_cbk(boost::system::error_code const &_error) {
}
}
-void event::notify() {
+void
+event::notify(bool _force) {
+
if (is_set_) {
- message_->set_session(routing_->get_session());
- routing_->send(VSOMEIP_ROUTING_CLIENT, message_);
+ set_session();
+ routing_->send(VSOMEIP_ROUTING_CLIENT, update_, _force);
} else {
VSOMEIP_INFO << __func__
<< ": Notifying "
@@ -294,8 +363,10 @@ void event::notify() {
}
}
-void event::notify_one(client_t _client,
+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);
@@ -308,12 +379,14 @@ void event::notify_one(client_t _client,
}
}
-void event::notify_one_unlocked(client_t _client,
+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_);
+ set_session();
+ routing_->send_to(_client, _target, update_);
} else {
VSOMEIP_INFO << __func__
<< ": Notifying "
@@ -331,15 +404,23 @@ void event::notify_one_unlocked(client_t _client,
}
}
-void event::notify_one(client_t _client) {
+void
+event::notify_one(client_t _client, bool _force) {
+
std::lock_guard<std::mutex> its_lock(mutex_);
- notify_one_unlocked(_client);
+ notify_one_unlocked(_client, _force);
}
-void event::notify_one_unlocked(client_t _client) {
+void
+event::notify_one_unlocked(client_t _client, bool _force) {
+
if (is_set_) {
- message_->set_session(routing_->get_session());
- routing_->send(_client, message_);
+ set_session();
+ {
+ std::lock_guard<std::mutex> its_last_forwarded_guard(last_forwarded_mutex_);
+ last_forwarded_[_client] = std::chrono::steady_clock::now();
+ }
+ routing_->send(_client, update_, _force);
} else {
VSOMEIP_INFO << __func__
<< ": Notifying "
@@ -350,28 +431,46 @@ void event::notify_one_unlocked(client_t _client) {
}
}
-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(type_ != event_type_e::ET_FIELD);
- if (!is_change) {
- is_change = _force || epsilon_change_func_(its_payload, _payload);
- }
- return is_change;
+bool
+event::prepare_update_payload(const std::shared_ptr<payload> &_payload,
+ bool _force) {
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ return (prepare_update_payload_unlocked(_payload, _force));
}
-void event::reset_payload(const std::shared_ptr<payload> &_payload) {
- std::shared_ptr<payload> its_new_payload
+bool
+event::prepare_update_payload_unlocked(
+ const std::shared_ptr<payload> &_payload, bool _force) {
+
+ // Copy payload to avoid manipulation from the outside
+ std::shared_ptr<payload> its_payload
= runtime::get()->create_payload(
- _payload->get_data(), _payload->get_length());
- message_->set_payload(its_new_payload);
+ _payload->get_data(), _payload->get_length());
+
+ bool is_change = has_changed(current_->get_payload(), its_payload);
+ if (!_force
+ && type_ == event_type_e::ET_FIELD
+ && cycle_ == std::chrono::milliseconds::zero()
+ && !is_change) {
+
+ return (false);
+ }
+
+ if (is_change)
+ update_->set_payload(its_payload);
if (!is_set_)
start_cycle();
is_set_ = true;
+
+ return (true);
}
-void event::add_ref(client_t _client, bool _is_provided) {
+void
+event::add_ref(client_t _client, bool _is_provided) {
+
std::lock_guard<std::mutex> its_lock(refs_mutex_);
auto its_client = refs_.find(_client);
if (its_client == refs_.end()) {
@@ -386,7 +485,9 @@ void event::add_ref(client_t _client, bool _is_provided) {
}
}
-void event::remove_ref(client_t _client, bool _is_provided) {
+void
+event::remove_ref(client_t _client, bool _is_provided) {
+
std::lock_guard<std::mutex> its_lock(refs_mutex_);
auto its_client = refs_.find(_client);
if (its_client != refs_.end()) {
@@ -403,24 +504,126 @@ void event::remove_ref(client_t _client, bool _is_provided) {
}
}
-bool event::has_ref() {
+bool
+event::has_ref() {
+
std::lock_guard<std::mutex> its_lock(refs_mutex_);
return refs_.size() != 0;
}
-bool event::add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _force) {
+bool
+event::add_subscriber(eventgroup_t _eventgroup,
+ const std::shared_ptr<debounce_filter_t> &_filter,
+ client_t _client, bool _force) {
+
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
bool ret = false;
if (_force // remote events managed by rm_impl
|| is_provided_ // events provided by rm_proxies
|| is_shadow_ // local events managed by rm_impl
|| is_cache_placeholder_) {
+
+ if (_filter) {
+ VSOMEIP_WARNING << "Using client ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _client
+ << "] specific filter configuration for SOME/IP event "
+ << get_service() << "." << get_instance() << "." << get_event() << ".";
+ std::stringstream its_filter_parameters;
+ its_filter_parameters << "(on_change="
+ << std::boolalpha << _filter->on_change_
+ << ", interval=" << std::dec << _filter->interval_
+ << ", on_change_resets_interval="
+ << std::boolalpha << _filter->on_change_resets_interval_
+ << ", ignore=[ ";
+ for (auto i : _filter->ignore_)
+ its_filter_parameters << "(" << std::dec << i.first << ", "
+ << std::hex << std::setw(2) << std::setfill('0')
+ << (int)i.second << ") ";
+ its_filter_parameters << "])";
+ VSOMEIP_INFO << "Filter parameters: "
+ << its_filter_parameters.str();
+
+ filters_[_client] = [_filter, _client, this](
+ const std::shared_ptr<payload> &_old,
+ const std::shared_ptr<payload> &_new) {
+
+ bool is_changed(false), is_elapsed(false);
+
+ // Check whether we should forward because of changed data
+ if (_filter->on_change_) {
+ length_t its_min_length, its_max_length;
+
+ if (_old->get_length() < _new->get_length()) {
+ its_min_length = _old->get_length();
+ its_max_length = _new->get_length();
+ } else {
+ its_min_length = _new->get_length();
+ its_max_length = _old->get_length();
+ }
+
+ // Check whether all additional bytes (if any) are excluded
+ for (length_t i = its_min_length; i < its_max_length; i++) {
+ auto j = _filter->ignore_.find(i);
+ // A change is detected when an additional byte is not
+ // excluded at all or if its exclusion does not cover all
+ // bits
+ if (j == _filter->ignore_.end() || j->second != 0xFF) {
+ is_changed = true;
+ break;
+ }
+ }
+
+ if (!is_changed) {
+ const byte_t *its_old = _old->get_data();
+ const byte_t *its_new = _new->get_data();
+ for (length_t i = 0; i < its_min_length; i++) {
+ auto j = _filter->ignore_.find(i);
+ if (j == _filter->ignore_.end()) {
+ if (its_old[i] != its_new[i]) {
+ is_changed = true;
+ break;
+ }
+ } else if (j->second != 0xFF) {
+ if ((its_old[i] & ~(j->second)) != (its_new[i] & ~(j->second))) {
+ is_changed = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (_filter->interval_ > -1) {
+ // Check whether we should forward because of the elapsed time since
+ // we did last time
+ std::chrono::steady_clock::time_point its_current
+ = std::chrono::steady_clock::now();
+
+ std::lock_guard<std::mutex> its_last_forwarded_guard(last_forwarded_mutex_);
+ is_elapsed = (last_forwarded_.find(_client) == last_forwarded_.end());
+ if (!is_elapsed) {
+ std::int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
+ its_current - last_forwarded_[_client]).count();
+ is_elapsed = (elapsed >= _filter->interval_);
+ }
+
+ if (is_elapsed || (is_changed && _filter->on_change_resets_interval_))
+ last_forwarded_[_client] = its_current;
+ }
+
+ return (is_changed || is_elapsed);
+ };
+ } else {
+ filters_.erase(_client);
+ }
+
ret = eventgroups_[_eventgroup].insert(_client).second;
+
} else {
VSOMEIP_WARNING << __func__ << ": Didnt' insert client "
- << std::hex << std::setw(4) << std::setfill('0')
- << _client
- << " to eventgroup "
+ << std::hex << std::setw(4) << std::setfill('0') << _client
+ << " to eventgroup 0x"
<< std::hex << std::setw(4) << std::setfill('0')
<< get_service() << "." << get_instance() << "."
<< _eventgroup;
@@ -428,14 +631,21 @@ bool event::add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _for
return ret;
}
-void event::remove_subscriber(eventgroup_t _eventgroup, client_t _client) {
+void
+event::remove_subscriber(eventgroup_t _eventgroup, client_t _client) {
+
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
auto find_eventgroup = eventgroups_.find(_eventgroup);
if (find_eventgroup != eventgroups_.end())
find_eventgroup->second.erase(_client);
+
+ std::lock_guard<std::mutex> its_last_forwarded_guard(last_forwarded_mutex_);
+ last_forwarded_.erase(_client);
}
-bool event::has_subscriber(eventgroup_t _eventgroup, client_t _client) {
+bool
+event::has_subscriber(eventgroup_t _eventgroup, client_t _client) {
+
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
auto find_eventgroup = eventgroups_.find(_eventgroup);
if (find_eventgroup != eventgroups_.end()) {
@@ -449,7 +659,9 @@ bool event::has_subscriber(eventgroup_t _eventgroup, client_t _client) {
return false;
}
-std::set<client_t> event::get_subscribers() {
+std::set<client_t>
+event::get_subscribers() {
+
std::set<client_t> its_subscribers;
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
for (const auto &e : eventgroups_)
@@ -457,13 +669,79 @@ std::set<client_t> event::get_subscribers() {
return its_subscribers;
}
-void event::clear_subscribers() {
+std::set<client_t>
+event::get_filtered_subscribers(bool _force) {
+
+ std::set<client_t> its_subscribers(get_subscribers());
+ std::set<client_t> its_filtered_subscribers;
+
+ std::shared_ptr<payload> its_payload, its_payload_update;
+ {
+ its_payload = current_->get_payload();
+ its_payload_update = update_->get_payload();
+ }
+
+ if (filters_.empty()) {
+
+ bool must_forward = (type_ != event_type_e::ET_FIELD
+ || _force
+ || epsilon_change_func_(its_payload, its_payload_update));
+
+ if (must_forward)
+ return (its_subscribers);
+
+ } else {
+ byte_t is_allowed(0xff);
+
+ std::lock_guard<std::mutex> its_lock(filters_mutex_);
+ for (const auto s : its_subscribers) {
+
+ auto its_specific = filters_.find(s);
+ if (its_specific != filters_.end()) {
+ if (its_specific->second(its_payload, its_payload_update))
+ its_filtered_subscribers.insert(s);
+ } else {
+ if (is_allowed == 0xff) {
+ is_allowed = (type_ != event_type_e::ET_FIELD
+ || _force
+ || epsilon_change_func_(its_payload, its_payload_update)
+ ? 0x01 : 0x00);
+ }
+
+ if (is_allowed == 0x01)
+ its_filtered_subscribers.insert(s);
+ }
+ }
+ }
+
+ return (its_filtered_subscribers);
+}
+
+std::set<client_t>
+event::update_and_get_filtered_subscribers(
+ const std::shared_ptr<payload> &_payload, bool _is_from_remote) {
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+
+ (void)prepare_update_payload_unlocked(_payload, true);
+ auto its_subscribers = get_filtered_subscribers(!_is_from_remote);
+ if (_is_from_remote)
+ update_payload_unlocked();
+
+ return (its_subscribers);
+}
+
+void
+event::clear_subscribers() {
+
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
for (auto &e : eventgroups_)
e.second.clear();
}
-bool event::has_ref(client_t _client, bool _is_provided) {
+bool
+event::has_ref(client_t _client, bool _is_provided) {
+
std::lock_guard<std::mutex> its_lock(refs_mutex_);
auto its_client = refs_.find(_client);
if (its_client != refs_.end()) {
@@ -477,24 +755,35 @@ bool event::has_ref(client_t _client, bool _is_provided) {
return false;
}
-bool event::is_shadow() const {
+bool
+event::is_shadow() const {
+
return is_shadow_;
}
-void event::set_shadow(bool _shadow) {
+void
+event::set_shadow(bool _shadow) {
+
is_shadow_ = _shadow;
}
-bool event::is_cache_placeholder() const {
+bool
+event::is_cache_placeholder() const {
+
return is_cache_placeholder_;
}
-void event::set_cache_placeholder(bool _is_cache_place_holder) {
+void
+event::set_cache_placeholder(bool _is_cache_place_holder) {
+
is_cache_placeholder_ = _is_cache_place_holder;
}
-void event::start_cycle() {
- if (std::chrono::milliseconds::zero() != cycle_) {
+void
+event::start_cycle() {
+
+ if (!is_shadow_
+ && std::chrono::milliseconds::zero() != cycle_) {
cycle_timer_.expires_from_now(cycle_);
auto its_handler =
std::bind(&event::update_cbk, shared_from_this(),
@@ -503,15 +792,20 @@ void event::start_cycle() {
}
}
-void event::stop_cycle() {
- if (std::chrono::milliseconds::zero() != cycle_) {
+void
+event::stop_cycle() {
+
+ if (!is_shadow_
+ && std::chrono::milliseconds::zero() != cycle_) {
boost::system::error_code ec;
cycle_timer_.cancel(ec);
}
}
-bool event::compare(const std::shared_ptr<payload> &_lhs,
+bool
+event::has_changed(const std::shared_ptr<payload> &_lhs,
const std::shared_ptr<payload> &_rhs) const {
+
bool is_change = (_lhs->get_length() != _rhs->get_length());
if (!is_change) {
std::size_t its_pos = 0;
@@ -522,10 +816,12 @@ bool event::compare(const std::shared_ptr<payload> &_lhs,
its_pos++;
}
}
- return is_change;
+ return (is_change);
}
-std::set<client_t> event::get_subscribers(eventgroup_t _eventgroup) {
+std::set<client_t>
+event::get_subscribers(eventgroup_t _eventgroup) {
+
std::set<client_t> its_subscribers;
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
auto found_eventgroup = eventgroups_.find(_eventgroup);
@@ -535,7 +831,9 @@ std::set<client_t> event::get_subscribers(eventgroup_t _eventgroup) {
return its_subscribers;
}
-bool event::is_subscribed(client_t _client) {
+bool
+event::is_subscribed(client_t _client) {
+
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
for (const auto &egp : eventgroups_) {
if (egp.second.find(_client) != egp.second.end()) {
@@ -547,18 +845,27 @@ bool event::is_subscribed(client_t _client) {
reliability_type_e
event::get_reliability() const {
+
return reliability_;
}
void
event::set_reliability(const reliability_type_e _reliability) {
+
reliability_ = _reliability;
}
void
event::remove_pending(const std::shared_ptr<endpoint_definition> &_target) {
+
std::lock_guard<std::mutex> its_lock(mutex_);
pending_.erase(_target);
}
+void
+event::set_session() {
+
+ update_->set_session(routing_->get_session(false));
+}
+
} // namespace vsomeip_v3
diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp
index 50bbdb6..c41f55b 100644
--- a/implementation/routing/src/eventgroupinfo.cpp
+++ b/implementation/routing/src/eventgroupinfo.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -119,12 +119,18 @@ void eventgroupinfo::set_multicast(const boost::asio::ip::address &_address,
port_ = _port;
}
-const std::set<std::shared_ptr<event> > eventgroupinfo::get_events() const {
+std::set<std::shared_ptr<event> > eventgroupinfo::get_events() const {
std::lock_guard<std::mutex> its_lock(events_mutex_);
return events_;
}
void eventgroupinfo::add_event(const std::shared_ptr<event>& _event) {
+
+ if (_event == nullptr) {
+ VSOMEIP_ERROR << __func__ << ": Received ptr is null";
+ return;
+ }
+
std::lock_guard<std::mutex> its_lock(events_mutex_);
events_.insert(_event);
@@ -158,6 +164,12 @@ void eventgroupinfo::add_event(const std::shared_ptr<event>& _event) {
}
void eventgroupinfo::remove_event(const std::shared_ptr<event>& _event) {
+
+ if (_event == nullptr) {
+ VSOMEIP_ERROR << __func__ << ": Received ptr is null";
+ return;
+ }
+
std::lock_guard<std::mutex> its_lock(events_mutex_);
events_.erase(_event);
}
@@ -217,13 +229,19 @@ eventgroupinfo::update_remote_subscription(
const bool _is_subscribe) {
bool its_result(false);
+
+ if (_subscription == nullptr) {
+ VSOMEIP_ERROR << __func__ << ": Received ptr is null";
+ return (its_result);
+ }
+
std::shared_ptr<endpoint_definition> its_subscriber;
std::set<std::shared_ptr<event> > its_events;
{
std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
- for (const auto& its_item : subscriptions_) {
+ for (const auto &its_item : subscriptions_) {
if (its_item.second->equals(_subscription)) {
// update existing subscription
_changed = its_item.second->update(
@@ -231,16 +249,17 @@ eventgroupinfo::update_remote_subscription(
_id = its_item.second->get_id();
// Copy acknowledgment states from existing subscription
- for (const auto& its_client : _subscription->get_clients()) {
- const auto its_state = its_item.second->get_client_state(its_client);
- if (_is_subscribe &&
- its_state == remote_subscription_state_e::SUBSCRIPTION_UNKNOWN) {
- _subscription->set_client_state(its_client,
- remote_subscription_state_e::SUBSCRIPTION_PENDING);
+ for (const auto its_client : _subscription->get_clients()) {
+ auto its_state = its_item.second->get_client_state(its_client);
+ if (_is_subscribe
+ && its_state == remote_subscription_state_e::SUBSCRIPTION_UNKNOWN) {
+ // We met the current subscription object during its
+ // unsubscribe process. Therefore, trigger a resubscription.
+ its_state = remote_subscription_state_e::SUBSCRIPTION_PENDING;
_changed.insert(its_client);
- } else {
- _subscription->set_client_state(its_client, its_state);
}
+
+ _subscription->set_client_state(its_client, its_state);
}
if (_is_subscribe) {
@@ -295,6 +314,11 @@ eventgroupinfo::is_remote_subscription_limit_reached(
const std::shared_ptr<remote_subscription> &_subscription) {
bool limit_reached(false);
+ if (_subscription == nullptr) {
+ VSOMEIP_ERROR << __func__ << ": Received ptr is null";
+ return (limit_reached);
+ }
+
if (subscriptions_.size() <= max_remote_subscribers_) {
return false;
}
@@ -321,6 +345,11 @@ eventgroupinfo::is_remote_subscription_limit_reached(
remote_subscription_id_t
eventgroupinfo::add_remote_subscription(
const std::shared_ptr<remote_subscription> &_subscription) {
+
+ if (_subscription == nullptr) {
+ VSOMEIP_ERROR << __func__ << ": Received ptr is null";
+ return id_;
+ }
std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
update_id();
@@ -419,7 +448,6 @@ void
eventgroupinfo::send_initial_events(
const std::shared_ptr<endpoint_definition> &_reliable,
const std::shared_ptr<endpoint_definition> &_unreliable) const {
-
std::set<std::shared_ptr<event> > its_reliable_events, its_unreliable_events;
// Build sets of reliable/unreliable events first to avoid having to
@@ -465,11 +493,23 @@ eventgroupinfo::send_initial_events(
}
// Send events
- for (const auto &its_event : its_reliable_events)
- its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable);
+ if (!its_reliable_events.empty()) {
+ if (_reliable != nullptr) {
+ for (const auto &its_event : its_reliable_events)
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable);
+ } else {
+ VSOMEIP_ERROR << __func__ << ": Received ptr (_reliable) is null";
+ }
+ }
- for (const auto &its_event : its_unreliable_events)
- its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable);
+ if (!its_unreliable_events.empty()) {
+ if (_unreliable != nullptr) {
+ for (const auto &its_event : its_unreliable_events)
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable);
+ } else {
+ VSOMEIP_ERROR << __func__ << ": Received ptr (_unreliable) is null";
+ }
+ }
}
uint8_t eventgroupinfo::get_max_remote_subscribers() const {
diff --git a/implementation/routing/src/remote_subscription.cpp b/implementation/routing/src/remote_subscription.cpp
index cb04d93..3c95108 100644
--- a/implementation/routing/src/remote_subscription.cpp
+++ b/implementation/routing/src/remote_subscription.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2018-2021 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/.
@@ -13,7 +13,6 @@ 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),
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index c787a9e..49dcffb 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -9,8 +9,8 @@
#include <vsomeip/internal/logger.hpp>
#include "../include/routing_manager_base.hpp"
-#include "../../endpoints/include/local_client_endpoint_impl.hpp"
-#include "../../endpoints/include/local_server_endpoint_impl.hpp"
+#include "../../protocol/include/send_command.hpp"
+#include "../../security/include/policy_manager_impl.hpp"
#include "../../security/include/security.hpp"
#ifdef USE_DLT
#include "../../tracing/include/connector_impl.hpp"
@@ -23,9 +23,7 @@ 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()),
- routing_state_(routing_state_e::RS_UNKNOWN)
+ configuration_(host_->get_configuration())
#ifdef USE_DLT
, tc_(trace::connector_impl::get())
#endif
@@ -41,29 +39,52 @@ routing_manager_base::routing_manager_base(routing_manager_host *_host) :
std::make_shared<deserializer>(its_buffer_shrink_threshold));
}
- own_uid_ = ANY_UID;
- own_gid_ = ANY_GID;
-#ifndef _WIN32
- own_uid_ = getuid();
- own_gid_ = getgid();
-#endif
-
+ if (!configuration_->is_local_routing()) {
+ auto its_routing_address = configuration_->get_routing_host_address();
+ auto its_routing_port = configuration_->get_routing_host_port();
+ if (!its_routing_address.is_unspecified() && !its_routing_address.is_multicast()) {
+ add_guest(VSOMEIP_ROUTING_CLIENT, its_routing_address, its_routing_port);
+ }
+ }
}
-boost::asio::io_service & routing_manager_base::get_io() {
+boost::asio::io_context &routing_manager_base::get_io() {
+
return (io_);
}
client_t routing_manager_base::get_client() const {
- return client_;
+
+ return (host_->get_client());
}
void routing_manager_base::set_client(const client_t &_client) {
- client_ = _client;
+
+ host_->set_client(_client);
}
-session_t routing_manager_base::get_session() {
- return host_->get_session();
+session_t routing_manager_base::get_session(bool _is_request) {
+ return host_->get_session(_is_request);
+}
+
+const vsomeip_sec_client_t *routing_manager_base::get_sec_client() const {
+
+ return (host_->get_sec_client());
+}
+
+std::string routing_manager_base::get_client_host() const {
+ std::lock_guard<std::mutex> its_env_lock(env_mutex_);
+ return env_;
+}
+
+void routing_manager_base::set_client_host(const std::string &_client_host) {
+
+ std::lock_guard<std::mutex> its_env_lock(env_mutex_);
+ env_ = _client_host;
+}
+
+bool routing_manager_base::is_routing_manager() const {
+ return false;
}
void routing_manager_base::init(const std::shared_ptr<endpoint_manager_base>& _endpoint_manager) {
@@ -218,25 +239,7 @@ void routing_manager_base::register_event(client_t _client,
if (its_event) {
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
+ || its_event->get_type() == event_type_e::ET_UNKNOWN) {
if (_is_provided) {
its_event->set_provided(true);
its_event->set_reliability(determine_event_reliability());
@@ -319,8 +322,8 @@ void routing_manager_base::register_event(client_t _client,
}
if (_is_shadow && !_epsilon_change_func) {
- std::shared_ptr<cfg::debounce> its_debounce
- = configuration_->get_debounce(_service, _instance, _notifier);
+ std::shared_ptr<debounce_filter_t> its_debounce
+ = configuration_->get_debounce(host_->get_name(), _service, _instance, _notifier);
if (its_debounce) {
VSOMEIP_WARNING << "Using debounce configuration for "
<< " SOME/IP event "
@@ -344,6 +347,9 @@ void routing_manager_base::register_event(client_t _client,
_epsilon_change_func = [its_debounce](
const std::shared_ptr<payload> &_old,
const std::shared_ptr<payload> &_new) {
+
+ static std::chrono::steady_clock::time_point its_last_forwarded
+ = std::chrono::steady_clock::time_point::max();
bool is_changed(false), is_elapsed(false);
// Check whether we should forward because of changed data
@@ -362,8 +368,8 @@ void routing_manager_base::register_event(client_t _client,
for (length_t i = its_min_length; i < its_max_length; i++) {
auto j = its_debounce->ignore_.find(i);
// A change is detected when an additional byte is not
- // excluded at all or if its exclusion does not cover
- // all its bits.
+ // excluded at all or if its exclusion does not cover all
+ // bits
if (j == its_debounce->ignore_.end() || j->second != 0xFF) {
is_changed = true;
break;
@@ -396,12 +402,12 @@ void routing_manager_base::register_event(client_t _client,
std::chrono::steady_clock::time_point its_current
= std::chrono::steady_clock::now();
- long elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
- its_current - its_debounce->last_forwarded_).count();
- is_elapsed = (its_debounce->last_forwarded_ == (std::chrono::steady_clock::time_point::max)()
+ std::int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
+ its_current - its_last_forwarded).count();
+ is_elapsed = (its_last_forwarded == std::chrono::steady_clock::time_point::max()
|| elapsed >= its_debounce->interval_);
if (is_elapsed || (is_changed && its_debounce->on_change_resets_interval_))
- its_debounce->last_forwarded_ = its_current;
+ its_last_forwarded = its_current;
}
return (is_changed || is_elapsed);
};
@@ -440,14 +446,13 @@ void routing_manager_base::register_event(client_t _client,
std::set<client_t> its_any_event_subscribers =
its_any_event->get_subscribers(eventgroup);
for (const client_t subscriber : its_any_event_subscribers) {
- its_event->add_subscriber(eventgroup, subscriber, true);
+ its_event->add_subscriber(eventgroup, nullptr, subscriber, true);
}
}
}
}
}
-
- if (!its_event->is_cache_placeholder()) {
+ if(!_is_cache_placeholder) {
its_event->add_ref(_client, _is_provided);
}
@@ -547,8 +552,8 @@ 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) {
- const auto its_security(security::get());
- if (!its_security->is_enabled()) {
+ if (!configuration_->is_security_enabled()
+ || !configuration_->is_local_routing()) {
return true;
}
@@ -575,7 +580,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 (!its_security->is_audit()) {
+ if (!configuration_->is_security_audit()) {
security_mode_text = ", but will be allowed due to audit mode is active!";
}
@@ -586,23 +591,20 @@ bool routing_manager_base::is_response_allowed(client_t _sender, service_t _serv
<< _service << "/" << _instance << "/" << _method
<< security_mode_text;
- return !its_security->is_audit();
+ return !configuration_->is_security_audit();
}
-bool routing_manager_base::is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
+bool routing_manager_base::is_subscribe_to_any_event_allowed(
+ const vsomeip_sec_client_t *_sec_client, 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 (const auto& e : its_eventgroup->get_events()) {
- if (!its_security->is_client_allowed(its_uid, its_gid,
- _client, _service, _instance, e->get_event())) {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(
+ _sec_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 "
@@ -617,26 +619,64 @@ bool routing_manager_base::is_subscribe_to_any_event_allowed(credentials_t _cred
return is_allowed;
}
-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 routing_manager_base::add_known_client(client_t _client, const std::string &_client_host) {
+#if !defined(VSOMEIP_DISABLE_SECURITY) && (defined(__linux__) || defined(ANDROID))
+ std::lock_guard<std::mutex> lazy_lock(add_known_client_mutex_);
+ if (configuration_->is_security_enabled()) {
+ //Ignore if we have already loaded the policy extension
+ policy_manager_impl::policy_loaded_e policy_loaded
+ = policy_manager_impl::get()->is_policy_extension_loaded(_client_host);
+
+ if (policy_loaded == policy_manager_impl::policy_loaded_e::POLICY_PATH_FOUND_AND_NOT_LOADED)
+ {
+ if (configuration_->lazy_load_security(_client_host)) {
+ VSOMEIP_INFO << __func__ << " vSomeIP Security: Loaded security policies for host: "
+ << _client_host
+ << " at UID/GID: " << std::dec << getuid() << "/" << getgid();
+ }
+ } else if (policy_loaded == policy_manager_impl::policy_loaded_e::POLICY_PATH_INEXISTENT) {
+ if (configuration_->lazy_load_security(_client_host))
+ {
+ VSOMEIP_INFO << __func__ << " vSomeIP Security: Loaded security policies for host: "
+ << _client_host
+ << " at UID/GID: " << std::dec << getuid() << "/" << getgid();
+ } else if (configuration_->lazy_load_security(get_client_host())) { //necessary for lazy loading from inside android container
+ VSOMEIP_INFO << __func__ << " vSomeIP Security: Loaded security policies for host: "
+ << get_client_host()
+ << " at UID/GID: " << std::dec << getuid() << "/" << getgid();
+ }
+ }
+ }
+#endif
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ known_clients_[_client] = _client_host;
+}
+
+void routing_manager_base::subscribe(client_t _client,
+ const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter) {
+
+ (void)_major;
+ (void)_sec_client;
- (void) _major;
- (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);
+ _event, _filter, _client, &its_already_subscribed_events);
if (inserted) {
notify_one_current_value(_client, _service, _instance, _eventgroup,
_event, its_already_subscribed_events);
}
}
-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;
+void routing_manager_base::unsubscribe(client_t _client,
+ const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ event_t _event) {
+
+ (void)_sec_client;
+
if (_event != ANY_EVENT) {
auto its_event = find_event(_service, _instance, _event);
if (its_event) {
@@ -653,24 +693,10 @@ void routing_manager_base::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
}
}
-void
-routing_manager_base::unsubscribe_all(
- service_t _service, instance_t _instance) {
-
- std::lock_guard<std::mutex> its_guard(events_mutex_);
- auto find_service = events_.find(_service);
- if (find_service != events_.end()) {
- auto find_instance = find_service->second.find(_instance);
- if (find_instance != find_service->second.end()) {
- for (auto &e : find_instance->second)
- e.second->clear_subscribers();
- }
- }
-}
-
void routing_manager_base::notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
bool _force) {
+
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
its_event->set_payload(_payload, _force);
@@ -843,7 +869,7 @@ 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);
+ its_event->notify_one(_client, false);
} else {
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
@@ -852,7 +878,7 @@ void routing_manager_base::notify_one_current_value(
if (e->is_field()
&& _events_to_exclude.find(e->get_event())
== _events_to_exclude.end()) {
- e->notify_one(_client);
+ e->notify_one(_client, false);
}
}
}
@@ -860,7 +886,8 @@ void routing_manager_base::notify_one_current_value(
}
bool routing_manager_base::send(client_t _client,
- std::shared_ptr<message> _message) {
+ std::shared_ptr<message> _message, bool _force) {
+
bool is_sent(false);
if (utility::is_request(_message->get_message_type())) {
_message->set_client(_client);
@@ -870,7 +897,8 @@ bool routing_manager_base::send(client_t _client,
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);
+ _message->is_reliable(), get_client(), get_sec_client(),
+ 0, false, _force);
its_serializer->reset();
put_serializer(its_serializer);
} else {
@@ -1024,18 +1052,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) {
+ bool _remove_sec_client) {
- 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);
+ vsomeip_sec_client_t its_sec_client;
+ policy_manager_impl::get()->get_client_to_sec_client_mapping(_client, its_sec_client);
- if (_remove_uid) {
- security::get()->remove_client_to_uid_gid_mapping(_client);
+ if (_remove_sec_client) {
+ policy_manager_impl::get()->remove_client_to_sec_client_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, 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<2>(its_subscription), _client,
+ &its_sec_client, get_env(_client),
+ false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
+ routing_manager_base::unsubscribe(_client, &its_sec_client, std::get<0>(its_subscription),
std::get<1>(its_subscription), std::get<2>(its_subscription), ANY_EVENT);
}
ep_mgr_->remove_local(_client);
@@ -1047,7 +1077,7 @@ void routing_manager_base::remove_local(client_t _client,
for (auto& i : s.second) {
if (std::get<2>(i.second) == _client) {
its_services.insert({ s.first, i.first });
- host_->on_availability(s.first, i.first, false,
+ host_->on_availability(s.first, i.first, availability_state_e::AS_UNAVAILABLE,
std::get<0>(i.second), std::get<1>(i.second));
}
}
@@ -1074,9 +1104,7 @@ void routing_manager_base::remove_local(client_t _client,
for (auto& sic : its_clients) {
local_services_history_[std::get<0>(sic)][std::get<1>(sic)].erase(std::get<2>(sic));
if (local_services_history_[std::get<0>(sic)][std::get<1>(sic)].size() == 0) {
- local_services_history_[std::get<0>(sic)].erase(std::get<1>(sic));
- if (local_services_history_[std::get<0>(sic)].size() == 0)
- local_services_history_.erase(std::get<0>(sic));
+ local_services_history_.erase(std::get<0>(sic));
}
}
}
@@ -1161,7 +1189,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 _reliable, uint8_t _status_check) {
+ bool _reliable, uint8_t _status_check, bool _force) {
#ifdef USE_DLT
bool has_local(false);
#endif
@@ -1173,7 +1201,7 @@ bool routing_manager_base::send_local_notification(client_t _client,
std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method);
if (its_event && !its_event->is_shadow()) {
- for (auto its_client : its_event->get_subscribers()) {
+ for (auto its_client : its_event->get_filtered_subscribers(_force)) {
// local
if (its_client == VSOMEIP_ROUTING_CLIENT) {
@@ -1189,60 +1217,57 @@ bool routing_manager_base::send_local_notification(client_t _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, _reliable, VSOMEIP_SEND, _status_check);
+ _instance, _reliable, protocol::id_e::SEND_ID, _status_check);
}
}
}
#ifdef USE_DLT
// Trace the message if a local client but will _not_ be forwarded to the routing manager
if (has_local && !has_remote) {
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ _data, _size);
}
#endif
return has_remote;
}
bool routing_manager_base::send_local(
- std::shared_ptr<endpoint>& _target, client_t _client,
+ std::shared_ptr<endpoint> &_target, client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- 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();
-
- std::vector<byte_t> its_command_header(VSOMEIP_SEND_COMMAND_SIZE);
- its_command_header[VSOMEIP_COMMAND_TYPE_POS] = _command;
- std::memcpy(&its_command_header[VSOMEIP_COMMAND_CLIENT_POS],
- &sender, sizeof(client_t));
- std::memcpy(&its_command_header[VSOMEIP_COMMAND_SIZE_POS_MIN],
- &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_RELIABLE_POS],
- &_reliable, 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));
-
- return _target->send(its_command_header, _data, _size);
+ bool _reliable, protocol::id_e _command, uint8_t _status_check) const {
+
+ bool has_sent(false);
+
+ protocol::send_command its_command(_command);
+ its_command.set_client(get_client());
+ its_command.set_instance(_instance);
+ its_command.set_reliable(_reliable);
+ its_command.set_status(_status_check);
+ its_command.set_target(_client);
+ its_command.set_message(std::vector<byte_t>(_data, _data + _size));
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ has_sent = _target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+
+ return (has_sent);
}
bool routing_manager_base::insert_subscription(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, client_t _client, std::set<event_t> *_already_subscribed_events) {
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter,
+ client_t _client, std::set<event_t> *_already_subscribed_events) {
+
bool is_inserted(false);
if (_event != ANY_EVENT) { // subscribe to specific event
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- is_inserted = its_event->add_subscriber(_eventgroup, _client,
+ is_inserted = its_event->add_subscriber(_eventgroup, _filter, _client,
host_->is_routing());
} else {
VSOMEIP_WARNING << "routing_manager_base::insert_subscription("
@@ -1255,7 +1280,7 @@ bool routing_manager_base::insert_subscription(
<< "unoffered) event. Creating placeholder event holding "
<< "subscription until event is requested/offered.";
is_inserted = create_placeholder_event_and_subscribe(_service,
- _instance, _eventgroup, _event, _client);
+ _instance, _eventgroup, _event, _filter, _client);
}
} else { // subscribe to all events of the eventgroup
std::shared_ptr<eventgroupinfo> its_eventgroup
@@ -1273,7 +1298,7 @@ bool routing_manager_base::insert_subscription(
// eventgroups
_already_subscribed_events->insert(e->get_event());
}
- is_inserted = e->add_subscriber(_eventgroup, _client,
+ is_inserted = e->add_subscriber(_eventgroup, _filter, _client,
host_->is_routing()) || is_inserted;
}
}
@@ -1291,7 +1316,7 @@ bool routing_manager_base::insert_subscription(
<< "unoffered) eventgroup. Creating placeholder event holding "
<< "subscription until event is requested/offered.";
is_inserted = create_placeholder_event_and_subscribe(_service,
- _instance, _eventgroup, _event, _client);
+ _instance, _eventgroup, _event, _filter, _client);
}
}
return is_inserted;
@@ -1305,7 +1330,8 @@ std::shared_ptr<serializer> routing_manager_base::get_serializer() {
<< std::hex << std::setw(4) << std::setfill('0')
<< get_client()
<< " has no available serializer. Waiting...";
- serializer_condition_.wait(its_lock);
+
+ serializer_condition_.wait(its_lock, [this] { return !serializers_.empty(); });
VSOMEIP_INFO << __func__ << ": Client "
<< std::hex << std::setw(4) << std::setfill('0')
<< get_client()
@@ -1332,7 +1358,8 @@ std::shared_ptr<deserializer> routing_manager_base::get_deserializer() {
while (deserializers_.empty()) {
VSOMEIP_INFO << std::hex << "client " << get_client() <<
"routing_manager_base::get_deserializer ~> all in use!";
- deserializer_condition_.wait(its_lock);
+
+ deserializer_condition_.wait(its_lock, [this] { return !deserializers_.empty(); });
VSOMEIP_INFO << std::hex << "client " << get_client() <<
"routing_manager_base::get_deserializer ~> wait finished!";
}
@@ -1356,8 +1383,8 @@ void routing_manager_base::send_pending_subscriptions(service_t _service,
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_);
+ send_subscribe(get_client(), ps.service_, ps.instance_,
+ ps.eventgroup_, ps.major_, ps.event_, ps.filter_);
}
}
}
@@ -1421,6 +1448,47 @@ routing_manager_base::get_subscriptions(const client_t _client) {
return result;
}
+bool
+routing_manager_base::get_guest(client_t _client,
+ boost::asio::ip::address &_address, port_t &_port) const {
+
+ std::lock_guard<std::mutex> its_lock(guests_mutex_);
+ auto find_guest = guests_.find(_client);
+ if (find_guest == guests_.end())
+ return (false);
+
+ _address = find_guest->second.first;
+ _port = find_guest->second.second;
+
+ return (true);
+}
+
+void
+routing_manager_base::add_guest(client_t _client,
+ const boost::asio::ip::address &_address, port_t _port) {
+
+ std::lock_guard<std::mutex> its_lock(guests_mutex_);
+ guests_[_client] = std::make_pair(_address, _port);
+}
+
+void
+routing_manager_base::remove_guest(client_t _client) {
+
+ std::lock_guard<std::mutex> its_lock(guests_mutex_);
+ guests_.erase(_client);
+}
+
+void
+routing_manager_base::remove_subscriptions(port_t _local_port,
+ const boost::asio::ip::address &_remote_address,
+ port_t _remote_port) {
+
+ (void)_local_port;
+ (void)_remote_address;
+ (void)_remote_port;
+ // dummy method to implement routing_host interface
+}
+
routing_state_e
routing_manager_base::get_routing_state() {
return routing_state_;
diff --git a/implementation/routing/src/routing_manager_client.cpp b/implementation/routing/src/routing_manager_client.cpp
new file mode 100644
index 0000000..378ab5d
--- /dev/null
+++ b/implementation/routing/src/routing_manager_client.cpp
@@ -0,0 +1,2890 @@
+// Copyright (C) 2014-2021 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/.
+
+#if defined(__linux__) || defined(ANDROID)
+#include <unistd.h>
+#endif
+
+#include <climits>
+#include <forward_list>
+#include <future>
+#include <iomanip>
+#include <mutex>
+#include <thread>
+#include <unordered_set>
+
+#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_client.hpp"
+#include "../../configuration/include/configuration.hpp"
+#include "../../endpoints/include/netlink_connector.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/message_impl.hpp"
+#include "../../message/include/serializer.hpp"
+#include "../../protocol/include/assign_client_command.hpp"
+#include "../../protocol/include/assign_client_ack_command.hpp"
+#include "../../protocol/include/deregister_application_command.hpp"
+#include "../../protocol/include/distribute_security_policies_command.hpp"
+#include "../../protocol/include/dummy_command.hpp"
+#include "../../protocol/include/expire_command.hpp"
+#include "../../protocol/include/offer_service_command.hpp"
+#include "../../protocol/include/offered_services_request_command.hpp"
+#include "../../protocol/include/offered_services_response_command.hpp"
+#include "../../protocol/include/ping_command.hpp"
+#include "../../protocol/include/pong_command.hpp"
+#include "../../protocol/include/register_application_command.hpp"
+#include "../../protocol/include/register_events_command.hpp"
+#include "../../protocol/include/registered_ack_command.hpp"
+#include "../../protocol/include/release_service_command.hpp"
+#include "../../protocol/include/remove_security_policy_command.hpp"
+#include "../../protocol/include/remove_security_policy_response_command.hpp"
+#include "../../protocol/include/request_service_command.hpp"
+#include "../../protocol/include/resend_provided_events_command.hpp"
+#include "../../protocol/include/routing_info_command.hpp"
+#include "../../protocol/include/send_command.hpp"
+#include "../../protocol/include/stop_offer_service_command.hpp"
+#include "../../protocol/include/subscribe_ack_command.hpp"
+#include "../../protocol/include/subscribe_command.hpp"
+#include "../../protocol/include/subscribe_nack_command.hpp"
+#include "../../protocol/include/unregister_event_command.hpp"
+#include "../../protocol/include/unsubscribe_ack_command.hpp"
+#include "../../protocol/include/unsubscribe_command.hpp"
+#include "../../protocol/include/update_security_credentials_command.hpp"
+#include "../../protocol/include/update_security_policy_command.hpp"
+#include "../../protocol/include/update_security_policy_response_command.hpp"
+#include "../../service_discovery/include/runtime.hpp"
+#include "../../security/include/policy.hpp"
+#include "../../security/include/policy_manager_impl.hpp"
+#include "../../security/include/security.hpp"
+#include "../../utility/include/byteorder.hpp"
+#include "../../utility/include/utility.hpp"
+#ifdef USE_DLT
+#include "../../tracing/include/connector_impl.hpp"
+#endif
+
+namespace vsomeip_v3 {
+
+routing_manager_client::routing_manager_client(routing_manager_host *_host,
+ bool _client_side_logging,
+ const std::set<std::tuple<service_t, instance_t> > & _client_side_logging_filter) :
+ routing_manager_base(_host),
+ is_connected_(false),
+ is_started_(false),
+ state_(inner_state_type_e::ST_DEREGISTERED),
+ sender_(nullptr),
+ receiver_(nullptr),
+ register_application_timer_(io_),
+ request_debounce_timer_ (io_),
+ request_debounce_timer_running_(false),
+ client_side_logging_(_client_side_logging),
+ client_side_logging_filter_(_client_side_logging_filter)
+#if defined(__linux__) || defined(ANDROID)
+ , is_local_link_available_(false)
+#endif // defined(__linux__) || defined(ANDROID)
+{
+
+ char its_hostname[1024];
+ if (gethostname(its_hostname, sizeof(its_hostname)) == 0) {
+ set_client_host(its_hostname);
+ }
+}
+
+routing_manager_client::~routing_manager_client() {
+}
+
+void routing_manager_client::init() {
+ routing_manager_base::init(std::make_shared<endpoint_manager_base>(this, io_, configuration_));
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (configuration_->is_local_routing()) {
+ sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
+ } else {
+#if defined(__linux__) || defined(ANDROID)
+ auto its_guest_address = configuration_->get_routing_guest_address();
+ auto its_host_address = configuration_->get_routing_host_address();
+ local_link_connector_ = std::make_shared<netlink_connector>(
+ io_, its_guest_address, boost::asio::ip::address(),
+ (its_guest_address != its_host_address));
+ // if the guest is in the same node as the routing manager
+ // it should not require LINK to be UP to communicate
+
+ if (local_link_connector_) {
+ local_link_connector_->register_net_if_changes_handler(
+ std::bind(&routing_manager_client::on_net_state_change,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ }
+#else
+ receiver_ = ep_mgr_->create_local_server(shared_from_this());
+ sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
+#endif
+ }
+ }
+}
+
+void routing_manager_client::start() {
+
+#if defined(__linux__) || defined(ANDROID)
+ if (configuration_->is_local_routing()) {
+#else
+ {
+#endif // __linux__ || ANDROID
+ is_started_ = true;
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (!sender_) {
+ // application has been stopped and started again
+ sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
+ }
+ if (sender_) {
+ sender_->start();
+ }
+ }
+#if defined(__linux__) || defined(ANDROID)
+ } else {
+ if (local_link_connector_)
+ local_link_connector_->start();
+#endif // __linux__ || ANDROID
+ }
+}
+
+void routing_manager_client::stop() {
+ std::unique_lock<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERING) {
+ register_application_timer_.cancel();
+ }
+
+ const std::chrono::milliseconds its_timeout(configuration_->get_shutdown_timeout());
+ while (state_ == inner_state_type_e::ST_REGISTERING) {
+ std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
+ if (status == std::cv_status::timeout) {
+ VSOMEIP_WARNING << std::hex << get_client() << " registering timeout on stop";
+ break;
+ }
+ }
+
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ deregister_application();
+ // Waiting de-register acknowledge to synchronize shutdown
+ while (state_ == inner_state_type_e::ST_REGISTERED) {
+ std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
+ if (status == std::cv_status::timeout) {
+ VSOMEIP_WARNING << std::hex << get_client() << " couldn't deregister application - timeout";
+ break;
+ }
+ }
+ }
+ is_started_ = false;
+ its_lock.unlock();
+
+#if defined(__linux__) || defined(ANDROID)
+ if (local_link_connector_)
+ local_link_connector_->stop();
+#endif
+
+ {
+ std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
+ request_debounce_timer_.cancel();
+ }
+
+ if (receiver_) {
+ receiver_->stop();
+ }
+ receiver_ = nullptr;
+
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->stop();
+ }
+ // delete the sender
+ sender_ = nullptr;
+ }
+
+ for (const auto client : ep_mgr_->get_connected_clients()) {
+ if (client != VSOMEIP_ROUTING_CLIENT) {
+ remove_local(client, true);
+ }
+ }
+
+ if (configuration_->is_local_routing()) {
+ std::stringstream its_client;
+ its_client << utility::get_base_path(configuration_->get_network())
+ << std::hex << get_client();
+ #ifdef _WIN32
+ ::_unlink(its_client.str().c_str());
+ #else
+
+ if (-1 == ::unlink(its_client.str().c_str())) {
+ VSOMEIP_ERROR<< "routing_manager_proxy::stop unlink failed ("
+ << its_client.str() << "): "<< std::strerror(errno);
+ }
+ #endif
+ }
+}
+
+#if defined(__linux__) || defined(ANDROID)
+void
+routing_manager_client::on_net_state_change(
+ bool _is_interface, const std::string &_name, bool _is_available) {
+
+ VSOMEIP_INFO << __func__
+ << ": " << std::boolalpha << _is_interface << " "
+ << _name << " "
+ << std::boolalpha << _is_available;
+
+ if (_is_interface) {
+ if (_is_available) {
+ if (!is_local_link_available_) {
+
+ is_local_link_available_ = true;
+
+ if (!receiver_)
+ receiver_ = ep_mgr_->create_local_server(shared_from_this());
+ receiver_->start();
+ is_started_ = true;
+
+ if (!sender_)
+ sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
+ sender_->start();
+ }
+ } else {
+ if (is_local_link_available_) {
+ is_started_ = false;
+
+ state_ = inner_state_type_e::ST_DEREGISTERED;
+ on_disconnect(sender_);
+
+ sender_->stop();
+
+ receiver_->stop();
+
+ {
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ local_services_.clear();
+ }
+
+ is_local_link_available_ = false;
+ }
+ }
+ }
+}
+#endif // __linux__ || ANDROID
+
+std::shared_ptr<configuration> routing_manager_client::get_configuration() const {
+ return host_->get_configuration();
+}
+
+std::string routing_manager_client::get_env(client_t _client) const {
+
+ std::lock_guard<std::mutex> its_known_clients_lock(known_clients_mutex_);
+ return get_env_unlocked(_client);
+}
+
+std::string routing_manager_client::get_env_unlocked(client_t _client) const {
+
+ auto find_client = known_clients_.find(_client);
+ if (find_client != known_clients_.end()) {
+ return (find_client->second);
+ }
+ return "";
+}
+
+bool routing_manager_client::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_client::offer_service,"
+ << "routing_manager_base::offer_service returned false";
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ send_offer_service(_client, _service, _instance, _major, _minor);
+ }
+ protocol::service offer(_service, _instance, _major, _minor );
+ pending_offers_.insert(offer);
+ }
+ return true;
+}
+
+void routing_manager_client::send_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ (void)_client;
+
+ protocol::offer_service_command its_offer;
+ its_offer.set_client(get_client());
+ its_offer.set_service(_service);
+ its_offer.set_instance(_instance);
+ its_offer.set_major(_major);
+ its_offer.set_minor(_minor);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_offer.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else {
+ VSOMEIP_ERROR << __func__ << ": offer_service serialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+
+}
+
+void routing_manager_client::stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ (void)_client;
+
+ {
+ // Hold the mutex to ensure no placeholder event is created inbetween.
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
+
+ routing_manager_base::stop_offer_service(_client, _service, _instance, _major, _minor);
+ clear_remote_subscriber_count(_service, _instance);
+
+ // Note: The last argument does not matter here as a proxy
+ // does not manage endpoints to the external network.
+ clear_service_info(_service, _instance, false);
+ }
+
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+
+ protocol::stop_offer_service_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_major(_major);
+ its_command.set_minor(_minor);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else {
+ VSOMEIP_ERROR << __func__ << ": stop offer serialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+ }
+ auto it = pending_offers_.begin();
+ while (it != pending_offers_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance) {
+ break;
+ }
+ it++;
+ }
+ if (it != pending_offers_.end()) pending_offers_.erase(it);
+ }
+}
+
+void routing_manager_client::request_service(client_t _client,
+ 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());
+ protocol::service request = { _service, _instance, _major, _minor };
+ if (!request_debouncing_time) {
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ std::set<protocol::service> requests;
+ requests.insert(request);
+ send_request_services(requests);
+ }
+ requests_.insert(request);
+ } else {
+ requests_to_debounce_.insert(request);
+ std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
+ if (!request_debounce_timer_running_) {
+ request_debounce_timer_running_ = true;
+ request_debounce_timer_.expires_from_now(std::chrono::milliseconds(request_debouncing_time));
+ request_debounce_timer_.async_wait(
+ std::bind(
+ &routing_manager_client::request_debounce_timeout_cbk,
+ std::dynamic_pointer_cast<routing_manager_client>(shared_from_this()),
+ std::placeholders::_1));
+ }
+ }
+ }
+}
+
+void routing_manager_client::release_service(client_t _client,
+ service_t _service, instance_t _instance) {
+ routing_manager_base::release_service(_client, _service, _instance);
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ remove_pending_subscription(_service, _instance, 0xFFFF, ANY_EVENT);
+
+ bool pending(false);
+ auto it = requests_to_debounce_.begin();
+ while (it != requests_to_debounce_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance) {
+ pending = true;
+ }
+ it++;
+ }
+ if (it != requests_to_debounce_.end()) requests_to_debounce_.erase(it);
+
+ if (!pending && state_ == inner_state_type_e::ST_REGISTERED) {
+ send_release_service(_client, _service, _instance);
+ }
+
+ {
+ auto it = requests_.begin();
+ while (it != requests_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance) {
+ break;
+ }
+ it++;
+ }
+ if (it != requests_.end()) requests_.erase(it);
+ }
+ }
+}
+
+
+void routing_manager_client::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)_is_shadow;
+ (void)_is_cache_placeholder;
+
+ bool is_cyclic(_cycle != std::chrono::milliseconds::zero());
+
+ const event_data_t registration = {
+ _service,
+ _instance,
+ _notifier,
+ _type,
+ _reliability,
+ _is_provided,
+ is_cyclic,
+ _eventgroups
+ };
+ bool is_first(false);
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ is_first = pending_event_registrations_.find(registration)
+ == pending_event_registrations_.end();
+#ifndef VSOMEIP_ENABLE_COMPAT
+ if (is_first) {
+ pending_event_registrations_.insert(registration);
+ }
+#else
+ bool insert = true;
+ if (is_first) {
+ for (auto iter = pending_event_registrations_.begin();
+ iter != pending_event_registrations_.end();) {
+ if (iter->service_ == _service
+ && iter->instance_ == _instance
+ && iter->notifier_ == _notifier
+ && iter->is_provided_ == _is_provided
+ && iter->type_ == event_type_e::ET_EVENT
+ && _type == event_type_e::ET_SELECTIVE_EVENT) {
+ iter = pending_event_registrations_.erase(iter);
+ iter = pending_event_registrations_.insert(registration).first;
+ is_first = true;
+ insert = false;
+ break;
+ } else {
+ iter++;
+ }
+ }
+ if (insert) {
+ pending_event_registrations_.insert(registration);
+ }
+ }
+#endif
+ }
+ if (is_first || _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(get_client(), _service, _instance,
+ _notifier, _eventgroups, _type, _reliability,
+ _is_provided, is_cyclic);
+ }
+ }
+}
+
+void routing_manager_client::unregister_event(client_t _client,
+ service_t _service, instance_t _instance, event_t _notifier,
+ bool _is_provided) {
+
+ routing_manager_base::unregister_event(_client, _service, _instance,
+ _notifier, _is_provided);
+
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+
+ protocol::unregister_event_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_event(_notifier);
+ its_command.set_provided(_is_provided);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+ }
+
+ for (auto iter = pending_event_registrations_.begin();
+ iter != pending_event_registrations_.end(); ) {
+ if (iter->service_ == _service
+ && iter->instance_ == _instance
+ && iter->notifier_ == _notifier
+ && iter->is_provided_ == _is_provided) {
+ pending_event_registrations_.erase(iter);
+ break;
+ } else {
+ iter++;
+ }
+ }
+ }
+}
+
+bool routing_manager_client::is_field(service_t _service, instance_t _instance,
+ event_t _event) const {
+ auto event = find_event(_service, _instance, _event);
+ if (event && event->is_field()) {
+ return true;
+ }
+ return false;
+}
+
+void routing_manager_client::subscribe(
+ client_t _client, const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter) {
+
+ (void)_client;
+
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERED && is_available(_service, _instance, _major)) {
+ send_subscribe(get_client(), _service, _instance, _eventgroup, _major, _event, _filter );
+ }
+ subscription_data_t subscription = {
+ _service, _instance,
+ _eventgroup, _major,
+ _event, _filter,
+ *_sec_client
+ };
+ pending_subscriptions_.insert(subscription);
+}
+
+void routing_manager_client::send_subscribe(client_t _client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter) {
+
+ if (_event == ANY_EVENT) {
+ if (!is_subscribe_to_any_event_allowed(get_sec_client(), _client, _service, _instance, _eventgroup)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : routing_manager_proxy::subscribe: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << _service << "/" << _instance << "/ANY_EVENT"
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ } else {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(
+ get_sec_client(), _service, _instance, _event)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : routing_manager_proxy::subscribe: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << _service << "/" << _instance
+ << "/" << _event;
+ return;
+ }
+ }
+
+ protocol::subscribe_command its_command;
+ its_command.set_client(_client);
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_major(_major);
+ its_command.set_event(_event);
+ its_command.set_pending_id(PENDING_SUBSCRIPTION_ID);
+ its_command.set_filter(_filter);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ client_t its_target_client = find_local_client(_service, _instance);
+ if (its_target_client != VSOMEIP_ROUTING_CLIENT) {
+ auto its_target = ep_mgr_->find_or_create_local(its_target_client);
+ its_target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+ } else {
+ VSOMEIP_ERROR << __func__ << ": subscribe command serialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+}
+
+void routing_manager_client::send_subscribe_nack(client_t _subscriber,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ event_t _event, remote_subscription_id_t _id) {
+
+ protocol::subscribe_nack_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_subscriber(_subscriber);
+ its_command.set_event(_event);
+ its_command.set_pending_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ if (_subscriber != VSOMEIP_ROUTING_CLIENT
+ && _id == PENDING_SUBSCRIPTION_ID) {
+ auto its_target = ep_mgr_->find_local(_subscriber);
+ if (its_target) {
+ its_target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ return;
+ }
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+ } else {
+ VSOMEIP_ERROR << __func__ << ": subscribe nack serialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+}
+
+void routing_manager_client::send_subscribe_ack(client_t _subscriber,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ event_t _event, remote_subscription_id_t _id) {
+
+ protocol::subscribe_ack_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_subscriber(_subscriber);
+ its_command.set_event(_event);
+ its_command.set_pending_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ if (_subscriber != VSOMEIP_ROUTING_CLIENT
+ && _id == PENDING_SUBSCRIPTION_ID) {
+ auto its_target = ep_mgr_->find_local(_subscriber);
+ if (its_target) {
+ its_target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ return;
+ }
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+ } else {
+ VSOMEIP_ERROR << __func__ << ": subscribe ack serialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+}
+
+void routing_manager_client::unsubscribe(client_t _client,
+ const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
+
+ (void)_client;
+ (void)_sec_client;
+
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ remove_pending_subscription(_service, _instance, _eventgroup, _event);
+
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+
+ protocol::unsubscribe_command its_command;
+ its_command.set_client(_client);
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_major(ANY_MAJOR);
+ its_command.set_event(_event);
+ its_command.set_pending_id(PENDING_SUBSCRIPTION_ID);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ auto its_target = ep_mgr_->find_local(_service, _instance);
+ if (its_target) {
+ its_target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+ } else {
+
+ VSOMEIP_ERROR << __func__
+ << ": unsubscribe serialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+ }
+ }
+}
+
+bool routing_manager_client::send(client_t _client, const byte_t *_data,
+ length_t _size, instance_t _instance, bool _reliable,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ uint8_t _status_check, bool _sent_from_remote, bool _force) {
+
+ (void)_client;
+ (void)_bound_client;
+ (void)_sec_client;
+ (void)_sent_from_remote;
+ bool is_sent(false);
+ bool has_remote_subscribers(false);
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ != inner_state_type_e::ST_REGISTERED) {
+ return false;
+ }
+ }
+ if (client_side_logging_) {
+ if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
+ service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+ if (client_side_logging_filter_.empty()
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, ANY_INSTANCE)))
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, _instance)))) {
+ method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SESSION_POS_MIN],
+ _data[VSOMEIP_SESSION_POS_MAX]);
+ client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ VSOMEIP_INFO << "routing_manager_client::send: ("
+ << std::hex << std::setw(4) << std::setfill('0') << get_client() <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << ":"
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << ":"
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << "] "
+ << "type=" << std::hex << static_cast<std::uint32_t>(_data[VSOMEIP_MESSAGE_TYPE_POS])
+ << " thread=" << std::hex << std::this_thread::get_id();
+ }
+ } else {
+ VSOMEIP_ERROR << "routing_manager_client::send: ("
+ << std::hex << std::setw(4) << std::setfill('0') << get_client()
+ <<"): message too short to log: " << std::dec << _size;
+ }
+ }
+ if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
+ std::shared_ptr<endpoint> its_target;
+ if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ // Request
+ service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+ client_t its_client = find_local_client(its_service, _instance);
+ if (its_client != VSOMEIP_ROUTING_CLIENT) {
+ if (is_client_known(its_client)) {
+ its_target = ep_mgr_->find_or_create_local(its_client);
+ }
+ }
+ } else if (!utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ // Response
+ client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ if (its_client != VSOMEIP_ROUTING_CLIENT) {
+ if (is_client_known(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, _reliable, _status_check, _force);
+ } else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) &&
+ _client != VSOMEIP_ROUTING_CLIENT) {
+ // notify_one
+ its_target = ep_mgr_->find_local(_client);
+ if (its_target) {
+#ifdef USE_DLT
+ trace::header its_header;
+ if (its_header.prepare(nullptr, true, _instance))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, _size);
+#endif
+ return send_local(its_target, get_client(), _data, _size,
+ _instance, _reliable, protocol::id_e::SEND_ID, _status_check);
+ }
+ }
+ // If no direct endpoint could be found
+ // or for notifications ~> route to routing_manager_stub
+#ifdef USE_DLT
+ bool message_to_stub(false);
+#endif
+ if (!its_target) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ its_target = sender_;
+#ifdef USE_DLT
+ message_to_stub = true;
+#endif
+ } else {
+ return false;
+ }
+ }
+
+ bool send(true);
+ protocol::id_e its_command(protocol::id_e::SEND_ID);
+
+ if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
+ its_command = protocol::id_e::NOTIFY_ONE_ID;
+ } else {
+ its_command = protocol::id_e::NOTIFY_ID;
+ // Do we need to deliver a notification to the routing manager?
+ // Only for services which already have remote clients subscribed to
+ send = has_remote_subscribers;
+ }
+ }
+#ifdef USE_DLT
+ else if (!message_to_stub) {
+ trace::header its_header;
+ if (its_header.prepare(nullptr, true, _instance))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, _size);
+ }
+#endif
+ if (send) {
+ is_sent = send_local(its_target,
+ (its_command == protocol::id_e::NOTIFY_ONE_ID ? _client : get_client()),
+ _data, _size, _instance, _reliable, its_command, _status_check);
+ }
+ }
+ return (is_sent);
+}
+
+bool routing_manager_client::send_to(const client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target,
+ std::shared_ptr<message> _message) {
+
+ (void)_client;
+ (void)_target;
+ (void)_message;
+
+ return (false);
+}
+
+bool routing_manager_client::send_to(
+ const std::shared_ptr<endpoint_definition> &_target,
+ const byte_t *_data, uint32_t _size, instance_t _instance) {
+
+ (void)_target;
+ (void)_data;
+ (void)_size;
+ (void)_instance;
+
+ return (false);
+}
+
+void routing_manager_client::on_connect(const std::shared_ptr<endpoint>& _endpoint) {
+
+ _endpoint->set_connected(true);
+ _endpoint->set_established(true);
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (_endpoint != sender_) {
+ return;
+ }
+ }
+ is_connected_ = true;
+ assign_client();
+}
+
+void routing_manager_client::on_disconnect(const std::shared_ptr<endpoint>& _endpoint) {
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ is_connected_ = !(_endpoint == sender_);
+ }
+ if (!is_connected_) {
+ VSOMEIP_INFO << "routing_manager_client::on_disconnect: Client 0x" << std::hex
+ << get_client() << " calling host_->on_state "
+ << "with DEREGISTERED";
+ host_->on_state(state_type_e::ST_DEREGISTERED);
+ }
+}
+
+void routing_manager_client::on_message(
+ const byte_t *_data, length_t _size,
+ endpoint *_receiver, bool _is_multicast,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ const boost::asio::ip::address &_remote_address,
+ std::uint16_t _remote_port) {
+
+ (void)_receiver;
+ (void)_is_multicast;
+ (void)_remote_address;
+ (void)_remote_port;
+
+#if 0
+ std::stringstream msg;
+ msg << "rmp::on_message<" << std::hex << get_client() << ">: ";
+ for (length_t i = 0; i < _size; ++i)
+ msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ protocol::id_e its_id;
+ client_t its_client;
+ service_t its_service;
+ instance_t its_instance;
+ eventgroup_t its_eventgroup;
+ event_t its_event;
+ major_version_t its_major;
+ client_t routing_host_id = configuration_->get_id(
+ configuration_->get_routing_host_name());
+ client_t its_subscriber;
+ remote_subscription_id_t its_pending_id(PENDING_SUBSCRIPTION_ID);
+ std::uint32_t its_remote_subscriber_count(0);
+#ifndef VSOMEIP_DISABLE_SECURITY
+ bool is_internal_policy_update(false);
+#endif // !VSOMEIP_DISABLE_SECURITY
+ std::vector<byte_t> its_buffer(_data, _data + _size);
+ protocol::error_e its_error;
+
+ auto its_security = policy_manager_impl::get();
+ if (!its_security)
+ return;
+
+ protocol::dummy_command its_dummy_command;
+ its_dummy_command.deserialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ its_id = its_dummy_command.get_id();
+ its_client = its_dummy_command.get_client();
+
+ bool is_from_routing(false);
+ if (configuration_->is_security_enabled()) {
+ if (configuration_->is_local_routing()) {
+ // if security is enabled, client ID of routing must be configured
+ // and credential passing is active. Otherwise bound client is zero by default
+ is_from_routing = (_bound_client == routing_host_id);
+ } else {
+ is_from_routing = (_remote_address == configuration_->get_routing_host_address()
+ && _remote_port == configuration_->get_routing_host_port() + 1);
+ }
+ } else {
+ is_from_routing = (its_client == routing_host_id);
+ }
+
+ if (configuration_->is_security_enabled()
+ && configuration_->is_local_routing()
+ && !is_from_routing && _bound_client != its_client) {
+ VSOMEIP_WARNING << std::hex << "Client "
+ << std::setw(4) << std::setfill('0') << get_client()
+ << " received a message with command " << int(its_id)
+ << " from " << std::setw(4) << std::setfill('0')
+ << its_client << " which doesn't match the bound client "
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return;
+ }
+
+ switch (its_id) {
+ case protocol::id_e::SEND_ID:
+ {
+ protocol::send_command its_send_command(protocol::id_e::SEND_ID);
+ its_send_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ auto a_deserializer = get_deserializer();
+ a_deserializer->set_data(its_send_command.get_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_send_command.get_instance());
+ its_message->set_reliable(its_send_command.is_reliable());
+ its_message->set_check_result(its_send_command.get_status());
+ if (_sec_client)
+ its_message->set_sec_client(*_sec_client);
+ its_message->set_env(get_env(_bound_client));
+
+ if (!is_from_routing) {
+ if (utility::is_notification(its_message->get_message_type())) {
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_message: "
+ << " received a notification from client 0x" << _bound_client
+ << " which does not offer service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ } else {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(get_sec_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_client::on_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return;
+ }
+ cache_event_payload(its_message);
+ }
+ } else if (utility::is_request(its_message->get_message_type())) {
+ if (configuration_->is_security_enabled()
+ && configuration_->is_local_routing()
+ && its_message->get_client() != _bound_client) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Client 0x" << std::setw(4) << std::setfill('0') << get_client()
+ << " received a request from client 0x" << std::setw(4) << std::setfill('0')
+ << its_message->get_client() << " to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method() << " which doesn't match the bound client 0x"
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return;
+ }
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(_sec_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_client::on_message: "
+ << "isn't allowed to send a request to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ }
+ } else { // response
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_message: "
+ << " received a response from client 0x" << _bound_client
+ << " which does not offer service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ } else {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(get_sec_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_client::on_message: "
+ << " isn't allowed to receive a response from service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return;
+ }
+ }
+ }
+ } else {
+ if (!configuration_->is_remote_access_allowed()) {
+ // if the message is from routing manager, check if
+ // policy allows remote requests.
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_message: "
+ << std::hex << "Security: Remote clients via routing manager with client ID 0x" << its_client
+ << " are not allowed to communicate with service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively with client 0x" << get_client()
+ << " ~> Skip message!";
+ return;
+ } else if (utility::is_notification(its_message->get_message_type())) {
+ // As subscription is sent on eventgroup level, incoming remote event ID's
+ // need to be checked as well if remote clients are allowed
+ // and the local policy only allows specific events in the eventgroup to be received.
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(get_sec_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_client::on_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from remote clients via routing manager with client ID 0x"
+ << routing_host_id
+ << " ~> Skip message!";
+ return;
+ }
+ cache_event_payload(its_message);
+ }
+ }
+ #ifdef USE_DLT
+ if (client_side_logging_
+ && (client_side_logging_filter_.empty()
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), ANY_INSTANCE)))
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), its_message->get_instance()))))) {
+ trace::header its_header;
+ if (its_header.prepare(nullptr, false, its_send_command.get_instance())) {
+ uint32_t its_message_size = its_send_command.get_size();
+ if (its_message_size >= uint32_t{vsomeip_v3::protocol::SEND_COMMAND_HEADER_SIZE})
+ its_message_size -= uint32_t{vsomeip_v3::protocol::SEND_COMMAND_HEADER_SIZE};
+ else
+ its_message_size = 0;
+
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ &_data[vsomeip_v3::protocol::SEND_COMMAND_HEADER_SIZE], its_message_size);
+ }
+ }
+ #endif
+
+ host_->on_message(std::move(its_message));
+ } else
+ VSOMEIP_ERROR << "Routing proxy: on_message: "
+ << "SomeIP-Header deserialization failed!";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": send command deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::ASSIGN_CLIENT_ACK_ID:
+ {
+ client_t its_assigned_client(VSOMEIP_CLIENT_UNSET);
+ protocol::assign_client_ack_command its_ack_command;
+ its_ack_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK)
+ its_assigned_client = its_ack_command.get_assigned();
+
+ on_client_assign_ack(its_assigned_client);
+ break;
+ }
+
+ case protocol::id_e::ROUTING_INFO_ID:
+ if (!configuration_->is_security_enabled() || is_from_routing) {
+ on_routing_info(_data, _size);
+ } else {
+ VSOMEIP_WARNING << "routing_manager_client::on_message: "
+ << std::hex << "Security: Client 0x" << get_client()
+ << " received an routing info from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+
+ case protocol::id_e::PING_ID:
+ {
+ protocol::ping_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ send_pong();
+ VSOMEIP_TRACE << "PING("
+ << std::hex << std::setw(4) << std::setfill('0') << get_client() << ")";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": ping command deserialization failed ("
+ << std::dec << int(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::SUBSCRIBE_ID:
+ {
+ protocol::subscribe_command its_subscribe_command;
+ its_subscribe_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_service = its_subscribe_command.get_service();
+ its_instance = its_subscribe_command.get_instance();
+ its_eventgroup = its_subscribe_command.get_eventgroup();
+ its_major = its_subscribe_command.get_major();
+ its_event = its_subscribe_command.get_event();
+ its_pending_id = its_subscribe_command.get_pending_id();
+ auto its_filter = its_subscribe_command.get_filter();
+
+ std::unique_lock<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_);
+ if (its_pending_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, _sec_client, get_env(its_client), true,
+ [this, self, its_client, its_service, its_instance,
+ its_eventgroup, its_event, its_filter, its_pending_id, its_major]
+ (const bool _subscription_accepted) {
+
+ std::uint32_t its_count(0);
+ if (_subscription_accepted) {
+ send_subscribe_ack(its_client, its_service, its_instance,
+ its_eventgroup, its_event, its_pending_id);
+ std::set<event_t> its_already_subscribed_events;
+ bool inserted = insert_subscription(its_service, its_instance, its_eventgroup,
+ its_event, its_filter, VSOMEIP_ROUTING_CLIENT, &its_already_subscribed_events);
+ if (inserted) {
+ 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
+ its_count = get_remote_subscriber_count(
+ its_service, its_instance, its_eventgroup, true);
+ } else {
+ send_subscribe_nack(its_client, its_service, its_instance,
+ its_eventgroup, its_event, its_pending_id);
+ }
+ VSOMEIP_INFO << "SUBSCRIBE("
+ << 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::dec << (uint16_t)its_major << "] "
+ << std::boolalpha << (its_pending_id != PENDING_SUBSCRIPTION_ID)
+ << " "
+ << (_subscription_accepted ?
+ std::to_string(its_count) + " accepted." : "not accepted.");
+
+#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 (!is_from_routing) {
+ if (its_event == ANY_EVENT) {
+ if (!is_subscribe_to_any_event_allowed(_sec_client, its_client, its_service, its_instance, its_eventgroup)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_client::on_message: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << its_service << "/" << its_instance << "/ANY_EVENT"
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ } else {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(
+ _sec_client, its_service, its_instance, its_event)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_client::on_message: "
+ << " subscribes to service/instance/event "
+ << its_service << "/" << its_instance << "/" << its_event
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ }
+ } else {
+ if (!configuration_->is_remote_access_allowed()) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_client::on_message: "
+ << std::hex << "Routing manager with client ID 0x"
+ << its_client
+ << " isn't allowed to subscribe to service/instance/event "
+ << its_service << "/" << its_instance
+ << "/" << its_event
+ << " respectively to client 0x" << get_client()
+ << " ~> Skip Subscribe!";
+ return;
+ }
+ }
+
+ // Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
+#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
+ (void) ep_mgr_->find_or_create_local(its_client);
+ auto self = shared_from_this();
+ auto its_env = get_env(its_client);
+ host_->on_subscription(its_service, its_instance,
+ its_eventgroup, its_client, _sec_client, its_env, true,
+ [this, self, its_client, its_filter, _sec_client, its_env, 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, PENDING_SUBSCRIPTION_ID);
+ } else {
+ send_subscribe_ack(its_client, its_service, its_instance,
+ its_eventgroup, its_event, PENDING_SUBSCRIPTION_ID);
+ routing_manager_base::subscribe(its_client, _sec_client,
+ its_service, its_instance, its_eventgroup, its_major, its_event, its_filter);
+#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 {
+ if (_sec_client) {
+ // 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, its_filter,
+ *_sec_client
+ };
+ pending_incoming_subscriptions_[its_client].insert(subscription);
+ } else {
+ VSOMEIP_WARNING << __func__
+ << ": Local subscription without security info.";
+ }
+ }
+
+ if (its_pending_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 << "."
+ << 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::dec << (uint16_t)its_major << "]";
+ }
+ } else {
+ VSOMEIP_ERROR << __func__
+ << ": subscribe command deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+ break;
+ }
+
+ case protocol::id_e::UNSUBSCRIBE_ID:
+ {
+ protocol::unsubscribe_command its_unsubscribe;
+ its_unsubscribe.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_unsubscribe.get_client();
+ its_service = its_unsubscribe.get_service();
+ its_instance = its_unsubscribe.get_instance();
+ its_eventgroup = its_unsubscribe.get_eventgroup();
+ its_event = its_unsubscribe.get_event();
+ its_pending_id = its_unsubscribe.get_pending_id();
+
+ host_->on_subscription(its_service, its_instance, its_eventgroup,
+ its_client, _sec_client, get_env(its_client), false,
+ [](const bool _subscription_accepted){
+ (void)_subscription_accepted;
+ }
+ );
+ if (its_pending_id == PENDING_SUBSCRIPTION_ID) {
+ // Local subscriber: withdraw subscription
+ routing_manager_base::unsubscribe(its_client, _sec_client, 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, nullptr, its_service,
+ its_instance, its_eventgroup, its_event);
+ }
+ send_unsubscribe_ack(its_service, its_instance, its_eventgroup, its_pending_id);
+ }
+ VSOMEIP_INFO << "UNSUBSCRIBE("
+ << 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 << "] "
+ << (bool)(its_pending_id != PENDING_SUBSCRIPTION_ID) << " "
+ << std::dec << its_remote_subscriber_count;
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": unsubscribe command deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::EXPIRE_ID:
+ {
+ protocol::expire_command its_expire;
+ its_expire.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_expire.get_client();
+ its_service = its_expire.get_service();
+ its_instance = its_expire.get_instance();
+ its_eventgroup = its_expire.get_eventgroup();
+ its_event = its_expire.get_event();
+ its_pending_id = its_expire.get_pending_id();
+
+ host_->on_subscription(its_service, its_instance, its_eventgroup, its_client,
+ _sec_client, get_env(its_client), false,
+ [](const bool _subscription_accepted){ (void)_subscription_accepted; });
+ if (its_pending_id == PENDING_SUBSCRIPTION_ID) {
+ // Local subscriber: withdraw subscription
+ routing_manager_base::unsubscribe(its_client, _sec_client,
+ 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, nullptr,
+ its_service, its_instance, its_eventgroup, its_event);
+ }
+ }
+ VSOMEIP_INFO << "EXPIRED SUBSCRIPTION("
+ << 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 << "] "
+ << (bool)(its_pending_id != PENDING_SUBSCRIPTION_ID) << " "
+ << std::dec << its_remote_subscriber_count;
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": expire deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::SUBSCRIBE_NACK_ID:
+ {
+ protocol::subscribe_nack_command its_subscribe_nack;
+ its_subscribe_nack.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_service = its_subscribe_nack.get_service();
+ its_instance = its_subscribe_nack.get_instance();
+ its_eventgroup = its_subscribe_nack.get_eventgroup();
+ its_subscriber = its_subscribe_nack.get_subscriber();
+ its_event = its_subscribe_nack.get_event();
+
+ on_subscribe_nack(its_subscriber, its_service, its_instance, its_eventgroup, its_event);
+ 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 << "]";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": subscribe nack command deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::SUBSCRIBE_ACK_ID:
+ {
+ protocol::subscribe_ack_command its_subscribe_ack;
+ its_subscribe_ack.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_service = its_subscribe_ack.get_service();
+ its_instance = its_subscribe_ack.get_instance();
+ its_eventgroup = its_subscribe_ack.get_eventgroup();
+ its_subscriber = its_subscribe_ack.get_subscriber();
+ its_event = its_subscribe_ack.get_event();
+
+ on_subscribe_ack(its_subscriber, its_service, its_instance, its_eventgroup, its_event);
+ 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 << "]";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": subscribe ack command deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::OFFERED_SERVICES_RESPONSE_ID:
+ {
+ protocol::offered_services_response_command its_response;
+ its_response.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ if (!configuration_->is_security_enabled() || is_from_routing) {
+ on_offered_services_info(its_response);
+ } else {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ << " received an offered services info from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": offered services response command deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+ case protocol::id_e::RESEND_PROVIDED_EVENTS_ID:
+ {
+ protocol::resend_provided_events_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ resend_provided_event_registrations();
+ send_resend_provided_event_response(its_command.get_remote_offer_id());
+
+ VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_command.get_client() << ")";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": resend provided events command deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+ case protocol::id_e::SUSPEND_ID:
+ {
+ on_suspend(); // cleanup remote subscribers
+ break;
+ }
+#ifndef VSOMEIP_DISABLE_SECURITY
+ case protocol::id_e::UPDATE_SECURITY_POLICY_INT_ID:
+ is_internal_policy_update = true;
+ [[gnu::fallthrough]];
+ case protocol::id_e::UPDATE_SECURITY_POLICY_ID:
+ {
+ if (!configuration_->is_security_enabled() || is_from_routing) {
+ protocol::update_security_policy_command its_command(is_internal_policy_update);
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ auto its_policy = its_command.get_policy();
+ uint32_t its_uid;
+ uint32_t its_gid;
+ if (its_policy->get_uid_gid(its_uid, its_gid)) {
+ if (is_internal_policy_update
+ || 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_command.get_update_id());
+ }
+ } else {
+ VSOMEIP_ERROR << "vSomeIP Security: Policy has no valid uid/gid!";
+ }
+ } else {
+ VSOMEIP_ERROR << "vSomeIP Security: Policy deserialization failed!";
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_message: "
+ << " received a security policy update from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
+
+ case protocol::id_e::REMOVE_SECURITY_POLICY_ID:
+ {
+ if (!configuration_->is_security_enabled() || is_from_routing) {
+ protocol::remove_security_policy_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ uid_t its_uid(its_command.get_uid());
+ gid_t its_gid(its_command.get_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_command.get_update_id());
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": remove security policy command deserialization failed ("
+ << static_cast<int>(its_error)
+ << ")";
+ } else
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_message: "
+ << "received a security policy removal from a client which isn't the routing manager"
+ << " : Skip message!";
+ break;
+ }
+
+ case protocol::id_e::DISTRIBUTE_SECURITY_POLICIES_ID:
+ {
+ if (!configuration_->is_security_enabled() || is_from_routing) {
+ protocol::distribute_security_policies_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ for (auto p : its_command.get_policies()) {
+ uid_t its_uid;
+ gid_t its_gid;
+ p->get_uid_gid(its_uid, its_gid);
+ if (its_security->is_policy_update_allowed(its_uid, p))
+ its_security->update_security_policy(its_uid, its_gid, p);
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": distribute security policies command deserialization failed ("
+ << static_cast<int>(its_error)
+ << ")";
+ } else
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_message: "
+ << " received a security policy distribution command from a client which isn't the routing manager"
+ << " : Skip message!";
+ break;
+ }
+
+ case protocol::id_e::UPDATE_SECURITY_CREDENTIALS_ID:
+ {
+ if (!configuration_->is_security_enabled() || is_from_routing) {
+ protocol::update_security_credentials_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ on_update_security_credentials(its_command);
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": update security credentials command deserialization failed ("
+ << static_cast<int>(its_error)
+ << ")";
+ } else
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_message: "
+ << "received a security credential update from a client which isn't the routing manager"
+ << " : Skip message!";
+
+ break;
+ }
+#endif // !VSOMEIP_DISABLE_SECURITY
+ default:
+ break;
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": dummy command deserialization failed ("
+ << std::dec << static_cast<int>(its_error)
+ << ")";
+}
+
+void routing_manager_client::on_routing_info(
+ const byte_t *_data, uint32_t _size) {
+#if 0
+ std::stringstream msg;
+ msg << "rmp::on_routing_info(" << std::hex << get_client() << "): ";
+ for (uint32_t i = 0; i < _size; ++i)
+ msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ auto its_security = policy_manager_impl::get();
+ if (!its_security)
+ return;
+
+ std::vector<byte_t> its_buffer(_data, _data + _size);
+ protocol::error_e its_error;
+
+ protocol::routing_info_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error != protocol::error_e::ERROR_OK) {
+ VSOMEIP_ERROR << __func__
+ << ": deserializing routing info command failed ("
+ << static_cast<int>(its_error)
+ << ")";
+ return;
+ }
+
+ for (const auto &e : its_command.get_entries()) {
+ auto its_client = e.get_client();
+ switch (e.get_type()) {
+ case protocol::routing_info_entry_type_e::RIE_ADD_CLIENT:
+ {
+ auto its_address = e.get_address();
+ if (!its_address.is_unspecified()) {
+ add_guest(its_client, its_address, e.get_port());
+ add_known_client(its_client, "");
+ }
+
+ if (its_client == get_client()) {
+ VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
+ << " (" << host_->get_name() << ") is registered.";
+#if defined(__linux__) || defined(ANDROID)
+ if (!its_security->check_credentials(get_client(), get_sec_client())) {
+ VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::on_routing_info: RIE_ADD_CLIENT: isn't allowed"
+ << " to use the server endpoint due to credential check failed!";
+ deregister_application();
+ host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
+ return;
+ }
+#endif
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERING) {
+ boost::system::error_code ec;
+ register_application_timer_.cancel(ec);
+ send_registered_ack();
+ send_pending_commands();
+ state_ = inner_state_type_e::ST_REGISTERED;
+ // Notify stop() call about clean deregistration
+ state_condition_.notify_one();
+ }
+ }
+
+ // inform host about its own registration state changes
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_REGISTERED));
+ }
+ }
+ break;
+ }
+
+ case protocol::routing_info_entry_type_e::RIE_DELETE_CLIENT:
+ {
+ {
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ known_clients_.erase(its_client);
+ }
+ if (its_client == get_client()) {
+ its_security->remove_client_to_sec_client_mapping(its_client);
+ VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
+ << " (" << 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));
+
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ state_ = inner_state_type_e::ST_DEREGISTERED;
+ // Notify stop() call about clean deregistration
+ state_condition_.notify_one();
+ }
+ } else if (its_client != VSOMEIP_ROUTING_CLIENT) {
+ remove_local(its_client, true);
+ }
+ break;
+ }
+
+ case protocol::routing_info_entry_type_e::RIE_ADD_SERVICE_INSTANCE:
+ {
+ auto its_address = e.get_address();
+ if (!its_address.is_unspecified()) {
+ add_guest(its_client, its_address, e.get_port());
+ add_known_client(its_client, "");
+ }
+ {
+ // Add yet unknown clients that offer services. Otherwise,
+ // the service cannot be used. The entry will be overwritten,
+ // when the offering clients connects.
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ if (known_clients_.find(its_client) == known_clients_.end()) {
+ known_clients_[its_client] = "";
+ }
+ }
+
+ for (const auto &s : e.get_services()) {
+
+ const auto its_service(s.service_);
+ const auto its_instance(s.instance_);
+ const auto its_major(s.major_);
+ const auto its_minor(s.minor_);
+
+ {
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+
+ // Check whether the service instance is already known. If yes,
+ // continue with the next service within the routing info.
+ auto found_service = local_services_.find(its_service);
+ if (found_service != local_services_.end()) {
+ if (found_service->second.find(its_instance) != found_service->second.end())
+ continue;
+ }
+
+ local_services_[its_service][its_instance]
+ = std::make_tuple(its_major, its_minor, its_client);
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ send_pending_subscriptions(its_service, its_instance, its_major);
+ }
+ host_->on_availability(its_service, its_instance,
+ availability_state_e::AS_AVAILABLE, its_major, its_minor);
+ VSOMEIP_INFO << "ON_AVAILABLE("
+ << std::hex << std::setw(4) << std::setfill('0') << get_client() <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance
+ << ":" << std::dec << int(its_major) << "." << std::dec << its_minor << "]";
+ }
+ break;
+ }
+
+ case protocol::routing_info_entry_type_e::RIE_DELETE_SERVICE_INSTANCE:
+ {
+ for (const auto &s : e.get_services()) {
+ const auto its_service(s.service_);
+ const auto its_instance(s.instance_);
+ const auto its_major(s.major_);
+ const auto its_minor(s.minor_);
+
+ {
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ auto found_service = local_services_.find(its_service);
+ if (found_service != local_services_.end()) {
+ found_service->second.erase(its_instance);
+ // move previously offering client to history
+ local_services_history_[its_service][its_instance].insert(its_client);
+ if (found_service->second.size() == 0) {
+ local_services_.erase(its_service);
+ }
+ }
+ }
+ on_stop_offer_service(its_service, its_instance, its_major, its_minor);
+ host_->on_availability(its_service, its_instance,
+ availability_state_e::AS_UNAVAILABLE, its_major, its_minor);
+ VSOMEIP_INFO << "ON_UNAVAILABLE("
+ << std::hex << std::setw(4) << std::setfill('0') << get_client() <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance
+ << ":" << std::dec << int(its_major) << "." << std::dec << its_minor << "]";
+ }
+ break;
+ }
+
+ default:
+ VSOMEIP_ERROR << __func__
+ << ": Unknown routing info entry type ("
+ << static_cast<int>(e.get_type())
+ << ")";
+ break;
+ }
+ }
+
+ {
+ struct subscription_info {
+ service_t service_id_;
+ instance_t instance_id_;
+ eventgroup_t eventgroup_id_;
+ client_t client_id_;
+ major_version_t major_;
+ event_t event_;
+ std::shared_ptr<debounce_filter_t> filter_;
+ vsomeip_sec_client_t sec_client_;
+ std::string env_;
+ };
+ std::lock_guard<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_);
+ std::forward_list<struct subscription_info> subscription_actions;
+ if (pending_incoming_subscriptions_.size()) {
+ {
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ for (const auto &k : known_clients_) {
+ auto its_client = pending_incoming_subscriptions_.find(k.first);
+ if (its_client != pending_incoming_subscriptions_.end()) {
+ for (const auto &subscription : its_client->second) {
+ subscription_actions.push_front(
+ { subscription.service_, subscription.instance_,
+ subscription.eventgroup_, k.first,
+ subscription.major_, subscription.event_,
+ subscription.filter_,
+ subscription.sec_client_,
+ get_env_unlocked(k.first)});
+ }
+ }
+ }
+ }
+ 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);
+#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_, &si.sec_client_, si.env_, 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_, PENDING_SUBSCRIPTION_ID);
+ } else {
+ send_subscribe_ack(si.client_id_, si.service_id_,
+ si.instance_id_, si.eventgroup_id_, si.event_, PENDING_SUBSCRIPTION_ID);
+ routing_manager_base::subscribe(si.client_id_, &si.sec_client_,
+ si.service_id_, si.instance_id_, si.eventgroup_id_,
+ si.major_, si.event_, si.filter_);
+#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_subscriptions_.erase(si.client_id_);
+ }
+ });
+ }
+ }
+ }
+}
+
+void routing_manager_client::on_offered_services_info(
+ protocol::offered_services_response_command &_command) {
+
+ std::vector<std::pair<service_t, instance_t>> its_offered_services_info;
+
+ for (const auto &s : _command.get_services())
+ its_offered_services_info.push_back(std::make_pair(s.service_, s.instance_));
+
+ host_->on_offered_services_info(its_offered_services_info);
+}
+
+void routing_manager_client::reconnect(const std::map<client_t, std::string> &_clients) {
+ auto its_security = policy_manager_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));
+
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ state_ = inner_state_type_e::ST_DEREGISTERED;
+ // Notify stop() call about clean deregistration
+ state_condition_.notify_one();
+ }
+
+
+ // Remove all local connections/endpoints
+ for (const auto &c : _clients) {
+ if (c.first != VSOMEIP_ROUTING_CLIENT) {
+ remove_local(c.first, true);
+ }
+ }
+
+ VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
+ <<": Reconnecting to routing manager.";
+
+#if defined(__linux__) || defined(ANDROID)
+ if (!its_security->check_credentials(get_client(), get_sec_client())) {
+ VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_client::reconnect: isn't allowed"
+ << " to use the server endpoint due to credential check failed!";
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->stop();
+ }
+ return;
+ }
+#endif
+
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->restart();
+ }
+}
+
+void routing_manager_client::assign_client() {
+
+ protocol::assign_client_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_name(host_->get_name());
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error != protocol::error_e::ERROR_OK) {
+
+ VSOMEIP_ERROR << __func__ << ": command creation failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ return;
+ }
+
+ 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_buffer[0], static_cast<uint32_t>(its_buffer.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_client::assign_client_timeout_cbk,
+ std::dynamic_pointer_cast<routing_manager_client>(shared_from_this()),
+ std::placeholders::_1));
+ }
+ }
+}
+
+void routing_manager_client::register_application() {
+
+ if (!receiver_) {
+ VSOMEIP_ERROR << __func__
+ << "Cannot register. Local server endpoint does not exist.";
+ return;
+ }
+
+ auto its_configuration(get_configuration());
+ if (its_configuration->is_local_routing()) {
+ VSOMEIP_INFO << "Registering to routing manager @ "
+ << its_configuration->get_network() << "-0";
+ } else {
+ auto its_routing_address(its_configuration->get_routing_host_address());
+ auto its_routing_port(its_configuration->get_routing_host_port());
+ VSOMEIP_INFO << "Registering to routing manager @ "
+ << its_routing_address.to_string() << ":" << its_routing_port;
+ }
+
+ protocol::register_application_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_port(receiver_->get_local_port());
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ if (is_connected_) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ state_ = inner_state_type_e::ST_REGISTERING;
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+
+ register_application_timer_.cancel();
+ register_application_timer_.expires_from_now(std::chrono::milliseconds(1000));
+ register_application_timer_.async_wait(
+ std::bind(
+ &routing_manager_client::register_application_timeout_cbk,
+ std::dynamic_pointer_cast<routing_manager_client>(shared_from_this()),
+ std::placeholders::_1));
+ }
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": register application command serialization failed("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::deregister_application() {
+
+ protocol::deregister_application_command its_command;
+ its_command.set_client(get_client());
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ if (is_connected_)
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deregister application command serialization failed("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::send_pong() const {
+
+ protocol::pong_command its_command;
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ if (is_connected_) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": pong command serialization failed("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::send_request_services(const std::set<protocol::service> &_requests) {
+
+ if (!_requests.size()) {
+ return;
+ }
+
+ protocol::request_service_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_services(_requests);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else {
+ VSOMEIP_ERROR << __func__ << ": request service serialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ }
+}
+
+void routing_manager_client::send_release_service(client_t _client, service_t _service,
+ instance_t _instance) {
+
+ (void)_client;
+
+ protocol::release_service_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ }
+}
+
+void routing_manager_client::send_pending_event_registrations(client_t _client) {
+
+ protocol::register_events_command its_command;
+ its_command.set_client(_client);
+ std::set<vsomeip_v3::routing_manager_client::event_data_t>::iterator it = pending_event_registrations_.begin();
+
+ while(it != pending_event_registrations_.end())
+ {
+ for(; it!=pending_event_registrations_.end(); it++) {
+ protocol::register_event reg(it->service_, it->instance_, it->notifier_, it->type_,
+ it->is_provided_, it->reliability_, it->is_cyclic_
+ , (uint16_t)it->eventgroups_.size(), it->eventgroups_);
+ if(!its_command.add_registration(reg)) {break;}
+ }
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": register event command serialization failed ("
+ << std::dec << int(its_error) << ")";
+ }
+}
+
+void routing_manager_client::send_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,
+ bool _is_provided, bool _is_cyclic) {
+
+ (void)_client;
+
+ protocol::register_events_command its_command;
+ its_command.set_client(get_client());
+
+ protocol::register_event reg(_service, _instance, _notifier, _type,
+ _is_provided, _reliability, _is_cyclic,
+ (uint16_t)_eventgroups.size(), _eventgroups);
+
+ if(!its_command.add_registration(reg)) {
+ VSOMEIP_ERROR << __func__ << ": register event command is too long.";
+ }
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+
+ if (_is_provided) {
+ VSOMEIP_INFO << "REGISTER EVENT("
+ << std::hex << std::setw(4) << std::setfill('0') << get_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=" << std::boolalpha << _is_provided << "]";
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": register event command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::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_client::" << __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 (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*/);
+ }
+}
+
+void routing_manager_client::on_subscribe_nack(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
+ (void)_client;
+ if (_event == ANY_EVENT) {
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ 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_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/);
+ }
+}
+
+void routing_manager_client::cache_event_payload(
+ const std::shared_ptr<message> &_message) {
+ const service_t its_service(_message->get_service());
+ const instance_t its_instance(_message->get_instance());
+ const method_t its_method(_message->get_method());
+ std::shared_ptr<event> its_event = find_event(its_service, its_instance, its_method);
+ if (its_event) {
+ if (its_event->is_field()) {
+ its_event->prepare_update_payload(_message->get_payload(), true);
+ its_event->update_payload();
+ }
+ } else {
+ // we received a event which was not yet requested
+ 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, 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);
+ if (its_event) {
+ its_event->prepare_update_payload(_message->get_payload(), true);
+ its_event->update_payload();
+ }
+ }
+}
+
+void routing_manager_client::on_stop_offer_service(service_t _service,
+ instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor) {
+ (void) _major;
+ (void) _minor;
+ std::map<event_t, std::shared_ptr<event> > events;
+ {
+ std::lock_guard<std::mutex> its_lock(events_mutex_);
+ auto its_events_service = events_.find(_service);
+ if (its_events_service != events_.end()) {
+ auto its_events_instance = its_events_service->second.find(_instance);
+ if (its_events_instance != its_events_service->second.end()) {
+ for (auto &e : its_events_instance->second)
+ events[e.first] = e.second;
+ }
+ }
+ }
+ for (auto &e : events) {
+ e.second->unset_payload();
+ }
+}
+
+void routing_manager_client::send_pending_commands() {
+ for (auto &po : pending_offers_)
+ send_offer_service(get_client(),
+ po.service_, po.instance_,
+ po.major_, po.minor_);
+
+ send_pending_event_registrations(get_client());
+
+ send_request_services(requests_);
+}
+
+void routing_manager_client::init_receiver() {
+#if defined(__linux__) || defined(ANDROID)
+ auto its_security = policy_manager_impl::get();
+ if (!its_security)
+ return;
+
+ its_security->store_client_to_sec_client_mapping(get_client(), get_sec_client());
+ its_security->store_sec_client_to_client_mapping(get_sec_client(), get_client());
+#endif
+ if (!receiver_) {
+ receiver_ = ep_mgr_->create_local_server(shared_from_this());
+ } else {
+ std::uint16_t its_port = receiver_->get_local_port();
+ if (its_port != ILLEGAL_PORT)
+ VSOMEIP_INFO << "Reusing local server endpoint@" << its_port;
+ }
+}
+
+void routing_manager_client::notify_remote_initially(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, const std::set<event_t> &_events_to_exclude) {
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ auto service_info = find_service(_service, _instance);
+ for (const auto &e : its_eventgroup->get_events()) {
+ if (e->is_field() && e->is_set()
+ && _events_to_exclude.find(e->get_event())
+ == _events_to_exclude.end()) {
+ std::shared_ptr<message> its_notification
+ = runtime::get()->create_notification();
+ its_notification->set_service(_service);
+ its_notification->set_instance(_instance);
+ its_notification->set_method(e->get_event());
+ its_notification->set_payload(e->get_payload());
+ if (service_info) {
+ its_notification->set_interface_version(service_info->get_major());
+ }
+
+ 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,
+ its_serializer->get_data(), its_serializer->get_size(),
+ _instance, false, protocol::id_e::NOTIFY_ID, 0);
+ }
+ }
+ its_serializer->reset();
+ put_serializer(its_serializer);
+ } else {
+ VSOMEIP_ERROR << "Failed to serialize message. Check message size!";
+ }
+ }
+ }
+ }
+
+}
+
+uint32_t routing_manager_client::get_remote_subscriber_count(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, bool _increment) {
+ std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
+ uint32_t count (0);
+ bool found(false);
+ auto found_service = remote_subscriber_count_.find(_service);
+ if (found_service != remote_subscriber_count_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_group = found_instance->second.find(_eventgroup);
+ if (found_group != found_instance->second.end()) {
+ found = true;
+ if (_increment) {
+ found_group->second = found_group->second + 1;
+ } else {
+ if (found_group->second > 0) {
+ found_group->second = found_group->second - 1;
+ }
+ }
+ count = found_group->second;
+ }
+ }
+ }
+ if (!found) {
+ if (_increment) {
+ remote_subscriber_count_[_service][_instance][_eventgroup] = 1;
+ count = 1;
+ }
+ }
+ return count;
+}
+
+void routing_manager_client::clear_remote_subscriber_count(
+ service_t _service, instance_t _instance) {
+ std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
+ auto found_service = remote_subscriber_count_.find(_service);
+ if (found_service != remote_subscriber_count_.end()) {
+ if (found_service->second.erase(_instance)) {
+ if (!found_service->second.size()) {
+ remote_subscriber_count_.erase(found_service);
+ }
+ }
+ }
+}
+
+void
+routing_manager_client::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_client::register_application_timeout_cbk(
+ boost::system::error_code const &_error) {
+
+ bool register_again(false);
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (!_error && 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()
+ << " register timeout! Trying again...";
+
+ if (sender_)
+ sender_->restart();
+ }
+}
+
+void routing_manager_client::send_registered_ack() {
+
+ protocol::registered_ack_command its_command;
+ its_command.set_client(get_client());
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": registered ack command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+bool routing_manager_client::is_client_known(client_t _client) {
+
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ return (known_clients_.find(_client) != known_clients_.end());
+}
+
+bool routing_manager_client::create_placeholder_event_and_subscribe(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ event_t _notifier, const std::shared_ptr<debounce_filter_t> &_filter,
+ client_t _client) {
+
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
+
+ bool is_inserted(false);
+
+ if (find_service(_service, _instance)) {
+ // We received an event for an existing service which was not yet
+ // requested/offered. Create a placeholder field until someone
+ // requests/offers this event with full information like eventgroup,
+ // field/event, etc.
+ std::set<eventgroup_t> its_eventgroups({ _eventgroup });
+ // routing_manager_client: Always register with own client id and shadow = 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, _notifier);
+ if (its_event) {
+ is_inserted = its_event->add_subscriber(_eventgroup, _filter, _client, false);
+ }
+ }
+
+ return is_inserted;
+}
+
+void routing_manager_client::request_debounce_timeout_cbk(
+ boost::system::error_code const &_error) {
+
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (!_error) {
+ if (requests_to_debounce_.size()) {
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ send_request_services(requests_to_debounce_);
+ requests_.insert(requests_to_debounce_.begin(),
+ requests_to_debounce_.end());
+ requests_to_debounce_.clear();
+ } else {
+ {
+ 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_.async_wait(
+ std::bind(
+ &routing_manager_client::request_debounce_timeout_cbk,
+ std::dynamic_pointer_cast<routing_manager_client>(shared_from_this()),
+ std::placeholders::_1));
+ return;
+ }
+ }
+ }
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
+ request_debounce_timer_running_ = false;
+ }
+}
+
+void routing_manager_client::register_client_error_handler(client_t _client,
+ const std::shared_ptr<endpoint> &_endpoint) {
+
+ _endpoint->register_error_handler(
+ std::bind(&routing_manager_client::handle_client_error, this, _client));
+}
+
+void routing_manager_client::handle_client_error(client_t _client) {
+
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
+ VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
+ << " handles a client error(" << std::hex << _client << ")";
+ remove_local(_client, true);
+ } else {
+ bool should_reconnect(true);
+ {
+ std::unique_lock<std::mutex> its_lock(state_mutex_);
+ should_reconnect = is_started_;
+ }
+ if (should_reconnect) {
+ std::map<client_t, std::string> its_known_clients;
+ {
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ its_known_clients = known_clients_;
+ }
+ reconnect(its_known_clients);
+ }
+ }
+}
+
+void routing_manager_client::send_get_offered_services_info(client_t _client, offer_type_e _offer_type) {
+
+ protocol::offered_services_request_command its_command;
+ its_command.set_client(_client);
+ its_command.set_offer_type(_offer_type);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": offered service request command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::send_unsubscribe_ack(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ remote_subscription_id_t _id) {
+
+ protocol::unsubscribe_ack_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_pending_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": unsubscribe ack command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::resend_provided_event_registrations() {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ for (const event_data_t& ed : pending_event_registrations_) {
+ if (ed.is_provided_) {
+ send_register_event(get_client(), ed.service_, ed.instance_,
+ ed.notifier_, ed.eventgroups_, ed.type_, ed.reliability_,
+ ed.is_provided_, ed.is_cyclic_);
+ }
+ }
+}
+
+void routing_manager_client::send_resend_provided_event_response(pending_remote_offer_id_t _id) {
+
+ protocol::resend_provided_events_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_remote_offer_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": resend provided event command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+#ifndef VSOMEIP_DISABLE_SECURITY
+void routing_manager_client::send_update_security_policy_response(
+ pending_security_update_id_t _update_id) {
+
+ protocol::update_security_policy_response_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_update_id(_update_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": update security policy response command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::send_remove_security_policy_response(
+ pending_security_update_id_t _update_id) {
+
+ protocol::remove_security_policy_response_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_update_id(_update_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": update security policy response command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+void routing_manager_client::on_update_security_credentials(
+ const protocol::update_security_credentials_command &_command) {
+
+ auto its_security = policy_manager_impl::get();
+ if (!its_security)
+ return;
+
+ for (const auto &c : _command.get_credentials()) {
+ std::shared_ptr<policy> its_policy(std::make_shared<policy>());
+ boost::icl::interval_set<uint32_t> its_gid_set;
+ uid_t its_uid(c.first);
+ gid_t its_gid(c.second);
+
+ its_gid_set.insert(its_gid);
+
+ its_policy->credentials_ += std::make_pair(
+ boost::icl::interval<uid_t>::closed(its_uid, its_uid), its_gid_set);
+ its_policy->allow_who_ = true;
+ its_policy->allow_what_ = true;
+
+ its_security->add_security_credentials(its_uid, its_gid, its_policy, get_client());
+ }
+}
+#endif
+
+void routing_manager_client::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);
+
+ if (is_started_) {
+ init_receiver();
+ if (receiver_) {
+ receiver_->start();
+
+ VSOMEIP_INFO << std::hex << "Client " << get_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);
+
+ sender_->restart();
+ }
+ }
+ } else {
+ VSOMEIP_ERROR << "Didn't receive valid clientID! Won't register application.";
+ }
+ } else {
+ VSOMEIP_WARNING << "Client " << std::hex << get_client()
+ << " received another client identifier ("
+ << std::hex << _client
+ << "). Ignoring it. ("
+ << (int)state_ << ")";
+ }
+}
+
+void routing_manager_client::on_suspend() {
+
+ VSOMEIP_INFO << __func__ << ": Application "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << host_->get_client();
+
+ std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
+
+ // Unsubscribe everything that is left over.
+ for (const auto &s : remote_subscriber_count_) {
+ for (const auto &i : s.second) {
+ for (const auto &e : i.second)
+ routing_manager_base::unsubscribe(
+ VSOMEIP_ROUTING_CLIENT, nullptr,
+ s.first, i.first, e.first, ANY_EVENT);
+ }
+ }
+
+ // Remove all entries.
+ remote_subscriber_count_.clear();
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 07c0740..4ebca55 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -8,8 +8,9 @@
#include <memory>
#include <sstream>
#include <forward_list>
+#include <thread>
-#ifndef _WIN32
+#if defined(__linux__) || defined(ANDROID)
#include <unistd.h>
#include <cstdio>
#include <time.h>
@@ -30,10 +31,7 @@
#include "../include/routing_manager_stub.hpp"
#include "../include/serviceinfo.hpp"
#include "../../configuration/include/configuration.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"
#include "../../endpoints/include/tcp_server_endpoint_impl.hpp"
#include "../../endpoints/include/udp_client_endpoint_impl.hpp"
@@ -42,13 +40,15 @@
#include "../../message/include/deserializer.hpp"
#include "../../message/include/message_impl.hpp"
#include "../../message/include/serializer.hpp"
+#include "../../plugin/include/plugin_manager_impl.hpp"
+#include "../../protocol/include/protocol.hpp"
+#include "../../security/include/security.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.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
-#include "../../plugin/include/plugin_manager_impl.hpp"
#ifdef USE_DLT
#include "../../tracing/include/connector_impl.hpp"
#endif
@@ -89,11 +89,11 @@ routing_manager_impl::routing_manager_impl(routing_manager_host *_host) :
}
routing_manager_impl::~routing_manager_impl() {
- utility::remove_lockfile(configuration_);
- utility::reset_client_ids();
+ utility::remove_lockfile(configuration_->get_network());
+ utility::reset_client_ids(configuration_->get_network());
}
-boost::asio::io_service & routing_manager_impl::get_io() {
+boost::asio::io_context &routing_manager_impl::get_io() {
return routing_manager_base::get_io();
}
@@ -101,6 +101,34 @@ client_t routing_manager_impl::get_client() const {
return routing_manager_base::get_client();
}
+const vsomeip_sec_client_t *routing_manager_impl::get_sec_client() const {
+
+ return (routing_manager_base::get_sec_client());
+}
+
+std::string routing_manager_impl::get_client_host() const {
+ return routing_manager_base::get_client_host();
+}
+
+void routing_manager_impl::set_client_host(const std::string &_client_host) {
+ routing_manager_base::set_client_host(_client_host);
+}
+
+std::string routing_manager_impl::get_env(client_t _client) const {
+
+ std::lock_guard<std::mutex> its_known_clients_lock(known_clients_mutex_);
+ return get_env_unlocked(_client);
+}
+
+std::string routing_manager_impl::get_env_unlocked(client_t _client) const {
+
+ auto find_client = known_clients_.find(_client);
+ if (find_client != known_clients_.end()) {
+ return (find_client->second);
+ }
+ return "";
+}
+
std::set<client_t> routing_manager_impl::find_local_clients(service_t _service, instance_t _instance) {
return routing_manager_base::find_local_clients(_service, _instance);
}
@@ -109,18 +137,31 @@ client_t routing_manager_impl::find_local_client(service_t _service, instance_t
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,
+bool routing_manager_impl::is_subscribe_to_any_event_allowed(
+ const vsomeip_sec_client_t *_sec_client, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
- return routing_manager_base::is_subscribe_to_any_event_allowed(_credentials, _client,
+
+ return routing_manager_base::is_subscribe_to_any_event_allowed(_sec_client, _client,
_service, _instance, _eventgroup);
}
+void routing_manager_impl::add_known_client(client_t _client, const std::string &_client_host) {
+ routing_manager_base::add_known_client(_client, _client_host);
+}
+
+bool routing_manager_impl::is_routing_manager() const {
+ return true;
+}
+
void routing_manager_impl::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();
+ if (configuration_->is_routing_enabled()) {
+ stub_ = std::make_shared<routing_manager_stub>(this, configuration_);
+ stub_->init();
+ } else {
+ VSOMEIP_INFO << "Internal message routing disabled!";
+ }
if (configuration_->is_sd_enabled()) {
VSOMEIP_INFO<< "Service Discovery enabled. Trying to load module.";
@@ -162,7 +203,7 @@ void routing_manager_impl::init() {
}
void routing_manager_impl::start() {
-#ifndef _WIN32
+#if defined(__linux__) || defined(ANDROID)
boost::asio::ip::address its_multicast;
try {
its_multicast = boost::asio::ip::address::from_string(configuration_->get_sd_multicast());
@@ -172,6 +213,20 @@ void routing_manager_impl::start() {
<< "\". Please check your configuration.";
}
+ std::stringstream its_netmask_or_prefix;
+ auto its_unicast = configuration_->get_unicast_address();
+ if (its_unicast.is_v4())
+ its_netmask_or_prefix << "netmask:" << configuration_->get_netmask().to_string();
+ else
+ its_netmask_or_prefix << "prefix:" << configuration_->get_prefix();
+
+ VSOMEIP_INFO << "Client ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_client()
+ << "] routes unicast:" << its_unicast.to_string()
+ << ", "
+ << its_netmask_or_prefix.str();
+
netlink_connector_ = std::make_shared<netlink_connector>(
host_->get_io(), configuration_->get_unicast_address(), its_multicast);
netlink_connector_->register_net_if_changes_handler(
@@ -185,7 +240,8 @@ void routing_manager_impl::start() {
}
#endif
- stub_->start();
+ if (stub_)
+ stub_->start();
host_->on_state(state_type_e::ST_REGISTERED);
if (configuration_->log_version()) {
@@ -195,7 +251,7 @@ void routing_manager_impl::start() {
version_log_timer_.async_wait(std::bind(&routing_manager_impl::log_version_timer_cbk,
this, std::placeholders::_1));
}
-#ifndef _WIN32
+#if defined(__linux__) || defined(ANDROID)
if (configuration_->log_memory()) {
std::lock_guard<std::mutex> its_lock(memory_log_timer_mutex_);
boost::system::error_code ec;
@@ -231,7 +287,7 @@ void routing_manager_impl::stop() {
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_) {
+ if (std::get<2>(i.second) == get_client()) {
its_services[s.first][i.first] = i.second;
}
}
@@ -249,7 +305,7 @@ void routing_manager_impl::stop() {
std::lock_guard<std::mutex> its_lock(version_log_timer_mutex_);
version_log_timer_.cancel();
}
-#ifndef _WIN32
+#if defined(__linux__) || defined(ANDROID)
{
boost::system::error_code ec;
std::lock_guard<std::mutex> its_lock(memory_log_timer_mutex_);
@@ -276,9 +332,10 @@ void routing_manager_impl::stop() {
if (discovery_)
discovery_->stop();
- stub_->stop();
+ if (stub_)
+ stub_->stop();
- for (const auto& client : ep_mgr_->get_connected_clients()) {
+ for (const auto client : ep_mgr_->get_connected_clients()) {
if (client != VSOMEIP_ROUTING_CLIENT) {
remove_local(client, true);
}
@@ -317,7 +374,7 @@ bool routing_manager_impl::erase_offer_command(service_t _service, instance_t _i
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) {
+ if (std::get<0>(its_command) == uint8_t(protocol::id_e::OFFER_SERVICE_ID)) {
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);
@@ -355,7 +412,8 @@ bool routing_manager_impl::offer_service(client_t _client,
// only queue commands if method was NOT called via erase_offer_command()
if (_must_queue) {
- if (!insert_offer_command(_service, _instance, VSOMEIP_OFFER_SERVICE,
+ if (!insert_offer_command(_service, _instance,
+ uint8_t(protocol::id_e::OFFER_SERVICE_ID),
_client, _major, _minor)) {
return false;
}
@@ -364,15 +422,8 @@ bool routing_manager_impl::offer_service(client_t _client,
// 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)) {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_offer(
+ get_sec_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 "
@@ -412,7 +463,8 @@ bool routing_manager_impl::offer_service(client_t _client,
&& ps.instance_ == _instance
&& ps.major_ == _major) {
insert_subscription(ps.service_, ps.instance_,
- ps.eventgroup_, ps.event_, client_, &its_already_subscribed_events);
+ ps.eventgroup_, ps.event_, nullptr,
+ get_client(), &its_already_subscribed_events);
#if 0
VSOMEIP_ERROR << __func__
<< ": event="
@@ -425,8 +477,9 @@ bool routing_manager_impl::offer_service(client_t _client,
send_pending_subscriptions(_service, _instance, _major);
}
- stub_->on_offer_service(_client, _service, _instance, _major, _minor);
- on_availability(_service, _instance, true, _major, _minor);
+ if (stub_)
+ stub_->on_offer_service(_client, _service, _instance, _major, _minor);
+ on_availability(_service, _instance, availability_state_e::AS_AVAILABLE, _major, _minor);
erase_offer_command(_service, _instance);
return true;
}
@@ -451,7 +504,8 @@ void routing_manager_impl::stop_offer_service(client_t _client,
<< " (" << std::boolalpha << _must_queue << ")";
if (_must_queue) {
- if (!insert_offer_command(_service, _instance, VSOMEIP_STOP_OFFER_SERVICE,
+ if (!insert_offer_command(_service, _instance,
+ uint8_t(protocol::id_e::STOP_OFFER_SERVICE_ID),
_client, _major, _minor)) {
return;
}
@@ -476,8 +530,9 @@ void routing_manager_impl::stop_offer_service(client_t _client,
}
on_stop_offer_service(_client, _service, _instance, _major, _minor);
- stub_->on_stop_offer_service(_client, _service, _instance, _major, _minor);
- on_availability(_service, _instance, false, _major, _minor);
+ if (stub_)
+ stub_->on_stop_offer_service(_client, _service, _instance, _major, _minor);
+ on_availability(_service, _instance, availability_state_e::AS_UNAVAILABLE, _major, _minor);
} else {
VSOMEIP_WARNING << __func__ << " received STOP_OFFER("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
@@ -503,7 +558,7 @@ void routing_manager_impl::request_service(client_t _client, service_t _service,
auto its_info = find_service(_service, _instance);
if (!its_info) {
- requested_service_add(_client, _service, _instance, _major, _minor);
+ add_requested_service(_client, _service, _instance, _major, _minor);
if (discovery_) {
if (!configuration_->is_local_service(_service, _instance)) {
// Non local service instance ~> tell SD to find it!
@@ -525,7 +580,7 @@ void routing_manager_impl::request_service(client_t _client, service_t _service,
|| DEFAULT_MINOR == its_info->get_minor()
|| _minor == ANY_MINOR)) {
if(!its_info->is_local()) {
- requested_service_add(_client, _service, _instance, _major, _minor);
+ add_requested_service(_client, _service, _instance, _major, _minor);
if (discovery_) {
// Non local service instance ~> tell SD to find it!
discovery_->request_service(_service, _instance, _major,
@@ -538,12 +593,15 @@ void routing_manager_impl::request_service(client_t _client, service_t _service,
}
if (_client == get_client()) {
- stub_->create_local_receiver();
+ if (stub_)
+ stub_->create_local_receiver();
+
+ protocol::service its_request(_service, _instance, _major, _minor);
+ std::set<protocol::service> requests;
+ requests.insert(its_request);
- service_data_t request = { _service, _instance, _major, _minor };
- std::set<service_data_t> requests;
- requests.insert(request);
- stub_->handle_requests(_client, requests);
+ if (stub_)
+ stub_->handle_requests(_client, requests);
}
}
@@ -560,7 +618,7 @@ void routing_manager_impl::release_service(client_t _client, service_t _service,
remove_pending_subscription(_service, _instance, 0xFFFF, ANY_EVENT);
}
routing_manager_base::release_service(_client, _service, _instance);
- requested_service_remove(_client, _service, _instance);
+ remove_requested_service(_client, _service, _instance, ANY_MAJOR, ANY_MINOR);
std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
if (its_info && !its_info->is_local()) {
@@ -582,9 +640,11 @@ void routing_manager_impl::release_service(client_t _client, service_t _service,
}
}
-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) {
+void routing_manager_impl::subscribe(
+ client_t _client, const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter) {
VSOMEIP_INFO << "SUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
@@ -600,21 +660,25 @@ void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
_eventgroup, _event, subscription_state_e::IS_SUBSCRIBING);
#endif
auto self = shared_from_this();
- host_->on_subscription(_service, _instance, _eventgroup, _client, _uid, _gid, true,
- [this, self, _client, _uid, _gid, _service, _instance, _eventgroup,
- _event, _major]
+ host_->on_subscription(_service, _instance, _eventgroup, _client,
+ _sec_client, get_env(_client), true,
+ [this, self, _client, _sec_client, _service, _instance, _eventgroup,
+ _major, _event, _filter]
(const bool _subscription_accepted) {
(void) ep_mgr_->find_or_create_local(_client);
if (!_subscription_accepted) {
- stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup, _event);
+ if (stub_)
+ stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup, _event);
VSOMEIP_INFO << "Subscription request from client: 0x" << std::hex
<< _client << std::dec << " for eventgroup: 0x" << _eventgroup
<< " rejected from application handler.";
return;
- } else {
+ } else if (stub_) {
stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup, _event);
}
- routing_manager_base::subscribe(_client, _uid, _gid, _service, _instance, _eventgroup, _major, _event);
+ routing_manager_base::subscribe(_client, _sec_client,
+ _service, _instance, _eventgroup, _major,
+ _event, _filter);
#ifdef VSOMEIP_ENABLE_COMPAT
send_pending_notify_ones(_service, _instance, _eventgroup, _client);
routing_manager_base::erase_incoming_subscription_state(_client, _service, _instance,
@@ -631,7 +695,7 @@ void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
// 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);
+ _event, _filter, _client, &its_already_subscribed_events);
const bool subscriber_is_rm_host = (get_client() == _client);
if (inserted) {
if (0 == its_local_client) {
@@ -654,17 +718,20 @@ void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
}
} else {
its_critical.unlock();
- if (is_available(_service, _instance, _major)) {
+ if (is_available(_service, _instance, _major) && stub_) {
stub_->send_subscribe(ep_mgr_->find_local(_service, _instance),
- _client, _service, _instance, _eventgroup, _major, _event,
- PENDING_SUBSCRIPTION_ID);
+ _client, _service, _instance, _eventgroup, _major,
+ _event, _filter, PENDING_SUBSCRIPTION_ID);
}
}
}
if (subscriber_is_rm_host) {
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
subscription_data_t subscription = {
- _service, _instance, _eventgroup, _major, _event, _uid, _gid
+ _service, _instance,
+ _eventgroup, _major,
+ _event, _filter,
+ *_sec_client
};
pending_subscriptions_.insert(subscription);
}
@@ -674,8 +741,10 @@ void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
}
}
-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) {
+void routing_manager_impl::unsubscribe(
+ client_t _client, const vsomeip_sec_client_t *_sec_client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ event_t _event) {
VSOMEIP_INFO << "UNSUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
@@ -702,7 +771,8 @@ void routing_manager_impl::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
}
if (discovery_) {
- host_->on_subscription(_service, _instance, _eventgroup, _client, _uid, _gid, false,
+ host_->on_subscription(_service, _instance, _eventgroup, _client,
+ _sec_client, get_env(_client), false,
[](const bool _subscription_accepted){ (void)_subscription_accepted; });
if (0 == find_local_client(_service, _instance)) {
if (get_client() == _client) {
@@ -728,10 +798,11 @@ void routing_manager_impl::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
if (get_client() == _client) {
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
remove_pending_subscription(_service, _instance, _eventgroup, _event);
- stub_->send_unsubscribe(
- ep_mgr_->find_local(_service, _instance),
- _client, _service, _instance, _eventgroup, _event,
- PENDING_SUBSCRIPTION_ID);
+ if (stub_)
+ stub_->send_unsubscribe(
+ ep_mgr_->find_local(_service, _instance),
+ _client, _service, _instance, _eventgroup, _event,
+ PENDING_SUBSCRIPTION_ID);
}
}
ep_mgr_impl_->clear_multicast_endpoints(_service, _instance);
@@ -742,15 +813,16 @@ void routing_manager_impl::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
}
bool routing_manager_impl::send(client_t _client,
- std::shared_ptr<message> _message) {
- return routing_manager_base::send(_client, _message);
+ std::shared_ptr<message> _message, bool _force) {
+
+ return routing_manager_base::send(_client, _message, _force);
}
bool routing_manager_impl::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance, bool _reliable,
- client_t _bound_client,
- credentials_t _credentials,
- uint8_t _status_check, bool _sent_from_remote) {
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
+ uint8_t _status_check, bool _sent_from_remote, bool _force) {
+
bool is_sent(false);
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
std::shared_ptr<endpoint> its_target;
@@ -775,15 +847,14 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
} else if (is_notification && _client && !is_service_discovery) { // Selective notifications!
if (_client == get_client()) {
#ifdef USE_DLT
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ _data, _size);
#endif
- deliver_message(_data, _size, _instance, _reliable, _bound_client, _credentials, _status_check, _sent_from_remote);
+ deliver_message(_data, _size, _instance, _reliable,
+ _bound_client, _sec_client,
+ _status_check, _sent_from_remote);
return true;
}
its_target = find_local(_client);
@@ -794,16 +865,15 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
if ((is_request && its_client == get_client()) ||
(is_response && find_local_client(its_service, _instance) == get_client()) ||
(is_notification && find_local_client(its_service, _instance) == VSOMEIP_ROUTING_CLIENT)) {
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ _data, _size);
}
#endif
- is_sent = send_local(its_target, get_client(), _data, _size, _instance, _reliable, VSOMEIP_SEND, _status_check);
+ is_sent = send_local(its_target, get_client(), _data, _size, _instance,
+ _reliable, protocol::id_e::SEND_ID, _status_check);
} else {
// Check whether hosting application should get the message
// If not, check routes to external
@@ -811,7 +881,8 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
|| (find_local_client(its_service, _instance)
== host_->get_client() && is_request)) {
// TODO: Find out how to handle session id here
- is_sent = deliver_message(_data, _size, _instance, _reliable, VSOMEIP_ROUTING_CLIENT, _credentials, _status_check);
+ is_sent = deliver_message(_data, _size, _instance, _reliable,
+ VSOMEIP_ROUTING_CLIENT, _sec_client, _status_check);
} else {
e2e_buffer its_buffer;
@@ -844,13 +915,10 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
its_service, _instance, _reliable);
if (its_target) {
#ifdef USE_DLT
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ _data, _size);
#endif
is_sent = its_target->send(_data, _size);
} else {
@@ -868,7 +936,8 @@ 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, _reliable, _status_check);
+ (void)send_local_notification(get_client(), _data, _size, _instance,
+ _reliable, _status_check, _force);
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);
@@ -930,13 +999,10 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
}
#ifdef USE_DLT
if (has_sent) {
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ _data, _size);
}
#endif
}
@@ -962,13 +1028,10 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
(sd_info_ ? sd_info_->get_endpoint(false) : nullptr) : its_info->get_endpoint(_reliable);
if (its_target) {
#ifdef USE_DLT
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
trace::header its_header;
if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ _data, _size);
#endif
is_sent = its_target->send(_data, _size);
} else {
@@ -1009,6 +1072,7 @@ bool routing_manager_impl::send_to(
const client_t _client,
const std::shared_ptr<endpoint_definition> &_target,
std::shared_ptr<message> _message) {
+
bool is_sent(false);
std::shared_ptr<serializer> its_serializer(get_serializer());
@@ -1050,19 +1114,17 @@ 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) {
+
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
- 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, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ _data, _size);
#else
(void) _instance;
#endif
@@ -1081,13 +1143,10 @@ bool routing_manager_impl::send_via_sd(
if (its_endpoint) {
#ifdef USE_DLT
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);
+ _data, _size);
}
#endif
@@ -1136,13 +1195,15 @@ void routing_manager_impl::register_shadow_event(client_t _client,
service_t _service, instance_t _instance,
event_t _notifier,
const std::set<eventgroup_t> &_eventgroups, event_type_e _type,
- reliability_type_e _reliability, bool _is_provided) {
+ reliability_type_e _reliability, bool _is_provided, bool _is_cyclic) {
+
routing_manager_base::register_event(_client,
_service, _instance,
_notifier,
_eventgroups, _type, _reliability,
- std::chrono::milliseconds::zero(), false, true,
- nullptr,
+ (_is_cyclic ? std::chrono::milliseconds(1)
+ : std::chrono::milliseconds::zero()),
+ false, true, nullptr,
_is_provided, true);
}
@@ -1172,7 +1233,7 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
if (its_event) {
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()) {
+ for (const auto g : its_event->get_eventgroups()) {
const auto its_eventgroup = find_eventgroup(_service, _instance, g);
if (its_eventgroup) {
const auto its_subscriptions = its_eventgroup->get_remote_subscriptions();
@@ -1197,7 +1258,7 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
if (its_targets.size() > 0) {
for (const auto &its_target : its_targets) {
- its_event->set_payload(_payload, _client, its_target, _force);
+ its_event->set_payload(_payload, _client, its_target);
}
}
} else {
@@ -1209,11 +1270,11 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
}
void routing_manager_impl::on_availability(service_t _service, instance_t _instance,
- bool _is_available, major_version_t _major, minor_version_t _minor) {
+ availability_state_e _state, major_version_t _major, minor_version_t _minor) {
// insert subscriptions of routing manager into service discovery
// to send SubscribeEventgroup after StopOffer / Offer was received
- if (_is_available) {
+ if (_state == availability_state_e::AS_AVAILABLE) {
if (discovery_) {
const client_t its_local_client = find_local_client(_service, _instance);
// remote service
@@ -1241,7 +1302,7 @@ void routing_manager_impl::on_availability(service_t _service, instance_t _insta
}
}
}
- host_->on_availability(_service, _instance, _is_available, _major, _minor);
+ host_->on_availability(_service, _instance, _state, _major, _minor);
}
@@ -1273,7 +1334,7 @@ bool routing_manager_impl::offer_service_remotely(service_t _service,
<< "]";
ret = false;
} else {
- if (!stub_->send_provided_event_resend_request(its_offering_client,
+ if (stub_ && !stub_->send_provided_event_resend_request(its_offering_client,
pending_remote_offer_add(_service, _instance))) {
VSOMEIP_ERROR << __func__ << ": Couldn't send event resend"
<< "request to client 0x" << std::hex << std::setw(4)
@@ -1332,7 +1393,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(its_info);
+ discovery_->stop_offer_service(its_info, true);
its_info->set_endpoint(std::shared_ptr<endpoint>(), _reliable);
}
} else {
@@ -1344,7 +1405,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(its_copied_info);
+ discovery_->stop_offer_service(its_copied_info, true);
}
}
@@ -1353,8 +1414,8 @@ 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, credentials_t _credentials,
+ endpoint *_receiver, bool _is_multicast,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) {
#if 0
@@ -1369,10 +1430,12 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
method_t its_method;
uint8_t its_check_status = e2e::profile_interface::generic_check_status::E2E_OK;
instance_t its_instance(0x0);
+ message_type_e its_message_type;
#ifdef USE_DLT
bool is_forwarded(true);
#endif
if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) {
+ its_message_type = static_cast<message_type_e>(_data[VSOMEIP_MESSAGE_TYPE_POS]);
its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
_data[VSOMEIP_SERVICE_POS_MAX]);
if (its_service == VSOMEIP_SD_SERVICE) {
@@ -1381,7 +1444,11 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
if (discovery_ && its_method == sd::method) {
if (configuration_->get_sd_port() == _remote_port) {
if (!_remote_address.is_unspecified()) {
- discovery_->on_message(_data, _size, _remote_address, _destination);
+ // ACL check SD message
+ if(!is_acl_message_allowed(_receiver, its_service, ANY_INSTANCE, _remote_address)) {
+ return;
+ }
+ discovery_->on_message(_data, _size, _remote_address, _is_multicast);
} else {
VSOMEIP_ERROR << "Ignored SD message from unknown address.";
}
@@ -1391,7 +1458,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
}
} else {
- if(_destination.is_multicast()) {
+ if (_is_multicast) {
its_instance = ep_mgr_impl_->find_instance_multicast(its_service, _remote_address);
} else {
its_instance = ep_mgr_impl_->find_instance(its_service, _receiver);
@@ -1417,7 +1484,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
//Ignore messages with invalid message type
if(_size >= VSOMEIP_MESSAGE_TYPE_POS) {
- if(!utility::is_valid_message_type(static_cast<message_type_e>(_data[VSOMEIP_MESSAGE_TYPE_POS]))) {
+ if(!utility::is_valid_message_type(its_message_type)) {
VSOMEIP_ERROR << "Ignored SomeIP message with invalid message type.";
return;
}
@@ -1436,7 +1503,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
// Security checks if enabled!
- if (security::get()->is_enabled()) {
+ if (configuration_->is_security_enabled()) {
if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
client_t requester = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_CLIENT_POS_MIN],
@@ -1456,7 +1523,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
<< " which is already used locally ~> Skip message!";
return;
}
- if (!security::get()->is_remote_client_allowed()) {
+ if (!configuration_->is_remote_access_allowed()) {
// check if policy allows remote requests.
VSOMEIP_WARNING << "routing_manager_impl::on_message: "
<< std::hex << "Security: Remote client with client ID 0x" << requester
@@ -1485,19 +1552,22 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
#endif
}
+
+ // ACL check message
+ if(!is_acl_message_allowed(_receiver, its_service, its_instance, _remote_address)) {
+ return;
+ }
+
// Common way of message handling
#ifdef USE_DLT
is_forwarded =
#endif
on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(),
- _bound_client, _credentials, its_check_status, true);
+ _bound_client, _sec_client, its_check_status, true);
}
}
#ifdef USE_DLT
if (is_forwarded) {
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
trace::header its_header;
const boost::asio::ip::address_v4 its_remote_address =
_remote_address.is_v4() ? _remote_address.to_v4() :
@@ -1508,19 +1578,16 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
trace::protocol_e::udp;
its_header.prepare(its_remote_address, _remote_port, its_protocol, false,
its_instance);
- tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data,
- its_data_size);
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, _size);
}
#endif
}
-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,
- credentials_t _credentials,
- uint8_t _check_status,
- bool _is_from_remote) {
+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, const vsomeip_sec_client_t *_sec_client,
+ uint8_t _check_status, bool _is_from_remote) {
#if 0
std::stringstream msg;
msg << "rmi::on_message("
@@ -1541,15 +1608,29 @@ bool routing_manager_impl::on_message(
_data[VSOMEIP_CLIENT_POS_MAX]);
}
+#if 0
+ // ACL message check for local test purpouse
+ std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
+ if (its_info) {
+ std::shared_ptr<endpoint> _receiver = its_info->get_endpoint(_reliable);
+ if (_receiver && _receiver.get()) {
+ if(!is_acl_message_allowed(_receiver.get(), _service, _instance,
+ boost::asio::ip::address_v4::from_string("127.0.0.1"))) {
+ return false;
+ }
+ }
+ }
+#endif
+
if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
is_forwarded = deliver_notification(_service, _instance, _data, _size,
- _reliable, _bound_client, _credentials, _check_status, _is_from_remote);
+ _reliable, _bound_client, _sec_client, _check_status, _is_from_remote);
} else if (its_client == host_->get_client()) {
deliver_message(_data, _size, _instance,
- _reliable, _bound_client, _credentials, _check_status, _is_from_remote);
+ _reliable, _bound_client, _sec_client, _check_status, _is_from_remote);
} else {
send(its_client, _data, _size, _instance, _reliable,
- _bound_client, _credentials, _check_status, _is_from_remote); //send to proxy
+ _bound_client, _sec_client, _check_status, _is_from_remote, false); //send to proxy
}
return is_forwarded;
}
@@ -1689,7 +1770,7 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
if (discovery_) {
if (its_info->get_major() == _major && its_info->get_minor() == _minor) {
- discovery_->stop_offer_service(its_info);
+ discovery_->stop_offer_service(its_info, true);
}
}
del_routing_info(_service, _instance, (its_reliable_endpoint != nullptr),
@@ -1782,11 +1863,11 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
}
bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
- instance_t _instance, bool _reliable, client_t _bound_client, credentials_t _credentials,
+ instance_t _instance, bool _reliable,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
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 its_deserializer = get_deserializer();
its_deserializer->set_data(_data, _size);
@@ -1798,8 +1879,9 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
its_message->set_instance(_instance);
its_message->set_reliable(_reliable);
its_message->set_check_result(_status_check);
- its_message->set_uid(std::get<0>(_credentials));
- its_message->set_gid(std::get<1>(_credentials));
+ if (_sec_client)
+ its_message->set_sec_client(*_sec_client);
+ its_message->set_env(get_env(_bound_client));
if (!_is_from_remote) {
if (utility::is_notification(its_message->get_message_type())) {
@@ -1814,9 +1896,9 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return false;
} else {
- if (!security::get()->is_client_allowed(own_uid_, own_gid_,
- get_client(), its_message->get_service(),
- its_message->get_instance(), its_message->get_method())) {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(get_sec_client(),
+ its_message->get_service(), its_message->get_instance(),
+ its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message: "
<< " isn't allowed to receive a notification from service/instance/event "
@@ -1828,7 +1910,8 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
}
}
} else if (utility::is_request(its_message->get_message_type())) {
- if (security::get()->is_enabled()
+ if (configuration_->is_security_enabled()
+ && configuration_->is_local_routing()
&& its_message->get_client() != _bound_client) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message:"
@@ -1841,9 +1924,9 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
return false;
}
- 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())) {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(_sec_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 "
@@ -1864,9 +1947,9 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return false;
} else {
- if (!security::get()->is_client_allowed(own_uid_, own_gid_,
- get_client(), its_message->get_service(),
- its_message->get_instance(), its_message->get_method())) {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(get_sec_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 "
@@ -1879,7 +1962,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
}
}
} else {
- if (!security::get()->is_remote_client_allowed()) {
+ if (!configuration_->is_remote_access_allowed()) {
// if the message is from remote, check if
// policy allows remote requests.
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
@@ -1892,9 +1975,9 @@ 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 (!security::get()->is_client_allowed(own_uid_, own_gid_,
- get_client(), its_message->get_service(),
- its_message->get_instance(), its_message->get_method())) {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(get_sec_client(),
+ its_message->get_service(), its_message->get_instance(),
+ its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message: "
<< " isn't allowed to receive a notification from service/instance/event "
@@ -1918,10 +2001,10 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
bool routing_manager_impl::deliver_notification(
service_t _service, instance_t _instance,
- const byte_t *_data, length_t _length,
- bool _reliable, client_t _bound_client,
- credentials_t _credentials,
+ const byte_t *_data, length_t _length, bool _reliable,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
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(
@@ -1934,7 +2017,7 @@ bool routing_manager_impl::deliver_notification(
// no subscribers for this specific event / check subscriptions
// to other events of the event's eventgroups
bool cache_event = false;
- for (const auto& eg : its_event->get_eventgroups()) {
+ for (const auto eg : its_event->get_eventgroups()) {
std::shared_ptr<eventgroupinfo> egi = find_eventgroup(_service, _instance, eg);
if (egi) {
for (const auto &e : egi->get_events()) {
@@ -1957,37 +2040,30 @@ bool routing_manager_impl::deliver_notification(
return true; // as there is nothing to do
}
}
- const uint32_t its_length(utility::get_payload_size(_data, _length));
- if (its_length != _length - VSOMEIP_FULL_HEADER_SIZE) {
- VSOMEIP_ERROR << "Message length mismatch, dropping message!";
- return false;
- }
- std::shared_ptr<payload> its_payload
- = runtime::get()->create_payload(&_data[VSOMEIP_PAYLOAD_POS],
- its_length);
- if (!its_event->set_payload_dont_notify(its_payload)) {
- // do not forward the notification as it was filtered
- return false;
- }
}
+ auto its_length = utility::get_payload_size(_data, _length);
+ auto its_payload = runtime::get()->create_payload(
+ &_data[VSOMEIP_PAYLOAD_POS], its_length);
+
// incoming events statistics
(void) insert_event_statistics(
- _service,
- _instance,
- its_event_id,
- utility::get_payload_size(_data, _length));
+ _service, _instance, its_event_id, its_length);
+ // Ignore the filter for messages coming from other local clients
+ // as the filter was already applied there.
+ auto its_subscribers
+ = its_event->update_and_get_filtered_subscribers(its_payload, _is_from_remote);
if (its_event->get_type() != event_type_e::ET_SELECTIVE_EVENT) {
- for (const auto& its_local_client : its_event->get_subscribers()) {
+ for (const auto its_local_client : its_subscribers) {
if (its_local_client == host_->get_client()) {
deliver_message(_data, _length, _instance, _reliable,
- _bound_client, _credentials, _status_check, _is_from_remote);
+ _bound_client, _sec_client, _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);
+ _data, _length, _instance, _reliable, protocol::id_e::SEND_ID, _status_check);
}
}
}
@@ -1998,20 +2074,20 @@ bool routing_manager_impl::deliver_notification(
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);
+ _bound_client, _sec_client, _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);
+ _data, _length, _instance, _reliable, protocol::id_e::SEND_ID, _status_check);
}
}
}
}
+
} else {
VSOMEIP_WARNING << __func__ << ": Event ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
@@ -2048,10 +2124,10 @@ std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoin
its_service_endpoint->add_default_target(VSOMEIP_SD_SERVICE,
_address, _port);
if (!_reliable) {
- auto its_udp_server_endpoint_impl = std::dynamic_pointer_cast<
+ auto its_server_endpoint = std::dynamic_pointer_cast<
udp_server_endpoint_impl>(its_service_endpoint);
- if (its_udp_server_endpoint_impl)
- its_udp_server_endpoint_impl->join(_address);
+ if (its_server_endpoint)
+ its_server_endpoint->join(_address);
}
} else {
VSOMEIP_ERROR<< "Service Discovery endpoint could not be created. "
@@ -2102,6 +2178,37 @@ routing_manager_impl::get_offered_service_instances(service_t _service) const {
return its_instances;
}
+bool routing_manager_impl::is_acl_message_allowed(endpoint *_receiver,
+ service_t _service, instance_t _instance,
+ const boost::asio::ip::address &_remote_address) const {
+ if (message_acceptance_handler_ && _receiver) {
+ // Check the ACL whitelist rules if shall accepts the message
+
+ message_acceptance_t message_acceptance {
+#if VSOMEIP_BOOST_VERSION < 106600
+ static_cast<uint32_t>(_remote_address.to_v4().to_ulong()), _receiver->get_local_port(),
+#else
+ _remote_address.to_v4().to_uint(), _receiver->get_local_port(),
+#endif
+ _receiver->is_local(), _service, _instance
+ };
+ if (!message_acceptance_handler_(message_acceptance)) {
+ VSOMEIP_WARNING << "Message from " << _remote_address.to_string()
+ << std::hex << " with service/instance " << _instance << "/"
+ << _instance << " was rejected by the ACL check.";
+ return false;
+ }
+#if 0
+ else {
+ VSOMEIP_INFO << "Message from " << _remote_address.to_string()
+ << std::hex << " with service/instance " << _instance << "/"
+ << _instance << " was accepted by the ACL check.";
+ }
+#endif
+ }
+ return true;
+}
+
///////////////////////////////////////////////////////////////////////////////
// PRIVATE
///////////////////////////////////////////////////////////////////////////////
@@ -2166,20 +2273,7 @@ void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) {
}
routing_manager_base::remove_local(_client, clients_subscriptions, _remove_uid);
- std::forward_list<std::pair<service_t, instance_t>> services_to_release_;
- {
- std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
- auto its_client = requested_services_.find(_client);
- if (its_client != requested_services_.end()) {
- 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 });
- }
- }
- }
- }
- for (const auto &s : services_to_release_) {
+ for (const auto &s : get_requested_services(_client)) {
release_service(_client, s.first, s.second);
}
}
@@ -2210,7 +2304,7 @@ void routing_manager_impl::add_routing_info(
std::lock_guard<std::mutex> its_lock(routing_state_mutex_);
if (routing_state_ == routing_state_e::RS_SUSPENDED) {
- VSOMEIP_INFO << "rmi::" << __func__ << " We are suspened --> do nothing.";
+ VSOMEIP_INFO << "rmi::" << __func__ << " We are suspended --> do nothing.";
return;
}
@@ -2280,89 +2374,63 @@ void routing_manager_impl::add_routing_info(
{
bool connected(false);
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
- for(const auto &client_id : requested_services_) {
- auto found_service = client_id.second.find(_service);
- if (found_service != client_id.second.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- for (const auto &major_minor_pair : found_instance->second) {
- if ((major_minor_pair.first == _major
- || _major == DEFAULT_MAJOR
- || major_minor_pair.first == ANY_MAJOR)
- && (major_minor_pair.second <= _minor
- || _minor == DEFAULT_MINOR
- || major_minor_pair.second == ANY_MINOR)) {
- // SWS_SD_00376 establish TCP connection to service
- // service is marked as available later in on_connect()
- if(!connected) {
- if (udp_inserted) {
- // atomically create reliable and unreliable endpoint
- ep_mgr_impl_->find_or_create_remote_client(
- _service, _instance);
- } else {
- ep_mgr_impl_->find_or_create_remote_client(
- _service, _instance, true);
- }
- connected = true;
- }
- its_info->add_client(client_id.first);
- break;
- }
- }
+ for (const client_t its_client : get_requesters_unlocked(
+ _service, _instance, _major, _minor)) {
+ // SWS_SD_00376 establish TCP connection to service
+ // service is marked as available later in on_connect()
+ if (!connected) {
+ if (udp_inserted) {
+ // atomically create reliable and unreliable endpoint
+ ep_mgr_impl_->find_or_create_remote_client(
+ _service, _instance);
+ } else {
+ ep_mgr_impl_->find_or_create_remote_client(
+ _service, _instance, true);
}
+ connected = true;
}
+ its_info->add_client(its_client);
}
}
} else if (_reliable_port != ILLEGAL_PORT && is_reliable_known) {
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
- bool connected(false);
- for(const auto &client_id : requested_services_) {
- auto found_service = client_id.second.find(_service);
- if (found_service != client_id.second.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- for (const auto &major_minor_pair : found_instance->second) {
- if ((major_minor_pair.first == _major
- || _major == DEFAULT_MAJOR
- || major_minor_pair.first == ANY_MAJOR)
- && (major_minor_pair.second <= _minor
- || _minor == DEFAULT_MINOR
- || major_minor_pair.second == ANY_MINOR)) {
- std::shared_ptr<endpoint> ep = its_info->get_endpoint(true);
- if (ep) {
- if (ep->is_established() &&
- !stub_->contained_in_routing_info(
- VSOMEIP_ROUTING_CLIENT, _service, _instance,
- its_info->get_major(),
- its_info->get_minor())) {
- on_availability(_service, _instance,
- true, its_info->get_major(), its_info->get_minor());
- stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT,
- _service, _instance,
- its_info->get_major(),
- its_info->get_minor());
- if (discovery_) {
- discovery_->on_endpoint_connected(
- _service, _instance, ep);
- }
- }
- } else {
- // no endpoint yet, but requested -> create one
-
- // SWS_SD_00376 establish TCP connection to service
- // service is marked as available later in on_connect()
- if (!connected) {
- ep_mgr_impl_->find_or_create_remote_client(
- _service, _instance, true);
- connected = true;
- }
- its_info->add_client(client_id.first);
- }
- break;
- }
+ if (has_requester_unlocked(_service, _instance, _major, _minor)) {
+ std::shared_ptr<endpoint> ep = its_info->get_endpoint(true);
+ if (ep) {
+ if (ep->is_established() &&
+ stub_ &&
+ !stub_->contained_in_routing_info(
+ VSOMEIP_ROUTING_CLIENT, _service, _instance,
+ its_info->get_major(),
+ its_info->get_minor())) {
+ on_availability(_service, _instance,
+ availability_state_e::AS_AVAILABLE,
+ its_info->get_major(), its_info->get_minor());
+ stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT,
+ _service, _instance,
+ its_info->get_major(),
+ its_info->get_minor());
+ if (discovery_) {
+ discovery_->on_endpoint_connected(
+ _service, _instance, ep);
}
}
+ } else {
+ // no endpoint yet, but requested -> create one
+
+ // SWS_SD_00376 establish TCP connection to service
+ // service is marked as available later in on_connect()
+ ep_mgr_impl_->find_or_create_remote_client(
+ _service, _instance, true);
+ for (const client_t its_client : get_requesters_unlocked(
+ _service, _instance, _major, _minor)) {
+ its_info->add_client(its_client);
+ }
}
+ } else {
+ on_availability(_service, _instance,
+ availability_state_e::AS_OFFERED,
+ its_info->get_major(), its_info->get_minor());
}
}
@@ -2375,38 +2443,28 @@ void routing_manager_impl::add_routing_info(
{
bool connected(false);
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
- for (const auto &client_id : requested_services_) {
- const auto found_service = client_id.second.find(_service);
- if (found_service != client_id.second.end()) {
- const auto found_instance = found_service->second.find(
- _instance);
- if (found_instance != found_service->second.end()) {
- for (const auto &major_minor_pair : found_instance->second) {
- if ((major_minor_pair.first == _major
- || _major == DEFAULT_MAJOR
- || major_minor_pair.first == ANY_MAJOR)
- && (major_minor_pair.second <= _minor
- || _minor == DEFAULT_MINOR
- || major_minor_pair.second
- == ANY_MINOR)) {
- if(!connected) {
- ep_mgr_impl_->find_or_create_remote_client(_service, _instance,
- false);
- connected = true;
- }
- its_info->add_client(client_id.first);
- break;
- }
- }
- }
+ for (const client_t its_client : get_requesters_unlocked(
+ _service, _instance, _major, _minor)) {
+ if (!connected) {
+ ep_mgr_impl_->find_or_create_remote_client(_service, _instance,
+ false);
+ connected = true;
}
+ its_info->add_client(its_client);
}
}
}
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);
+ if (has_requester_unlocked(_service, _instance, _major, _minor)) {
+ on_availability(_service, _instance,
+ availability_state_e::AS_AVAILABLE, _major, _minor);
+ if (stub_)
+ stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, _major, _minor);
+ } else {
+ on_availability(_service, _instance,
+ availability_state_e::AS_OFFERED, _major, _minor);
+ }
}
if (discovery_) {
std::shared_ptr<endpoint> ep = its_info->get_endpoint(false);
@@ -2416,43 +2474,32 @@ void routing_manager_impl::add_routing_info(
}
} else if (_unreliable_port != ILLEGAL_PORT && is_unreliable_known) {
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
- for(const auto &client_id : requested_services_) {
- auto found_service = client_id.second.find(_service);
- if (found_service != client_id.second.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- for (const auto &major_minor_pair : found_instance->second) {
- if ((major_minor_pair.first == _major
- || _major == DEFAULT_MAJOR
- || major_minor_pair.first == ANY_MAJOR)
- && (major_minor_pair.second <= _minor
- || _minor == DEFAULT_MINOR
- || major_minor_pair.second == ANY_MINOR)) {
- if (_reliable_port == ILLEGAL_PORT && !is_reliable_known &&
- !stub_->contained_in_routing_info(
- VSOMEIP_ROUTING_CLIENT, _service, _instance,
- its_info->get_major(),
- its_info->get_minor())) {
- on_availability(_service, _instance,
- true, its_info->get_major(), its_info->get_minor());
- stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT,
- _service, _instance,
- its_info->get_major(),
- its_info->get_minor());
- if (discovery_) {
- std::shared_ptr<endpoint> ep = its_info->get_endpoint(false);
- if (ep && ep->is_established()) {
- discovery_->on_endpoint_connected(
- _service, _instance,
- ep);
- }
- }
- }
- break;
- }
+ if (has_requester_unlocked(_service, _instance, _major, _minor)) {
+ if (_reliable_port == ILLEGAL_PORT && !is_reliable_known &&
+ stub_ &&
+ !stub_->contained_in_routing_info(
+ VSOMEIP_ROUTING_CLIENT, _service, _instance,
+ its_info->get_major(),
+ its_info->get_minor())) {
+ on_availability(_service, _instance,
+ availability_state_e::AS_AVAILABLE,
+ its_info->get_major(), its_info->get_minor());
+ stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT,
+ _service, _instance,
+ its_info->get_major(),
+ its_info->get_minor());
+ if (discovery_) {
+ std::shared_ptr<endpoint> ep = its_info->get_endpoint(false);
+ if (ep && ep->is_established()) {
+ discovery_->on_endpoint_connected(
+ _service, _instance,
+ ep);
}
}
}
+ } else {
+ on_availability(_service, _instance,
+ availability_state_e::AS_OFFERED, _major, _minor);
}
}
}
@@ -2464,10 +2511,12 @@ 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,
+ on_availability(_service, _instance,
+ availability_state_e::AS_UNAVAILABLE,
its_info->get_major(), its_info->get_minor());
+ if (stub_)
+ stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance,
+ its_info->get_major(), its_info->get_minor());
// Implicit unsubscribe
std::vector<std::shared_ptr<event>> its_events;
@@ -2482,7 +2531,7 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst
// 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();
+ const auto its_subscribers = its_event->get_subscribers();
for (const auto its_subscriber : its_subscribers) {
if (its_subscriber != get_client()) {
its_event->remove_subscriber(
@@ -2747,24 +2796,12 @@ void routing_manager_impl::init_routing_info() {
= configuration_->get_reliable_port(i.first, i.second);
uint16_t its_unreliable_port
= configuration_->get_unreliable_port(i.first, i.second);
- major_version_t its_major
- = configuration_->get_major_version(i.first, i.second);
- minor_version_t its_minor
- = configuration_->get_minor_version(i.first, i.second);
- ttl_t its_ttl
- = configuration_->get_ttl(i.first, i.second);
if (its_reliable_port != ILLEGAL_PORT
|| its_unreliable_port != ILLEGAL_PORT) {
- VSOMEIP_INFO << "Adding static remote service ["
- << std::hex << std::setw(4) << std::setfill('0')
- << i.first << "." << i.second
- << std::dec << ":" << +its_major << "." << its_minor
- << "]";
-
add_routing_info(i.first, i.second,
- its_major, its_minor, its_ttl,
+ DEFAULT_MAJOR, DEFAULT_MINOR, DEFAULT_TTL,
its_address, its_reliable_port,
its_address, its_unreliable_port);
@@ -3009,7 +3046,7 @@ void routing_manager_impl::on_subscribe_ack(client_t _client,
host_->on_subscription_status(_service, _instance,
_eventgroup, _event, 0x0 /*OK*/);
}
- } else {
+ } else if (stub_) {
stub_->send_subscribe_ack(its_subscriber, _service,
_instance, _eventgroup, _event);
}
@@ -3025,20 +3062,13 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client(
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, bool _simulated) {
+ event_t _event, remote_subscription_id_t _id) {
(void)_event; // TODO: Remove completely?
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
auto its_subscription = its_eventgroup->get_remote_subscription(_id);
if (its_subscription) {
- if (_simulated) {
- // method was called because a subscription for unoffered
- // service was received. Therefore, remove the remote_subscription
- // from the eventgroupinfo to ensure subsequent similar
- // subscriptions are handled like a new/unknown subscription
- its_eventgroup->remove_remote_subscription(_id);
- }
its_subscription->set_client_state(_client,
remote_subscription_state_e::SUBSCRIPTION_NACKED);
@@ -3167,13 +3197,10 @@ void routing_manager_impl::send_error(return_code_e _return_code,
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);
-
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);
+ _data, _size);
#else
(void) _instance;
#endif
@@ -3233,6 +3260,14 @@ routing_manager_impl::expire_subscriptions(bool _force) {
auto its_subscriptions
= its_eventgroup.second->get_remote_subscriptions();
for (auto &s : its_subscriptions) {
+ if(!s) {
+ VSOMEIP_ERROR << __func__
+ << ": Remote subscription is NULL for eventgroup ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service.first << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance.first << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup.first << "]";
+ continue;
+ }
for (auto its_client : s->get_clients()) {
if (_force) {
its_expired_subscriptions[s].insert(its_client);
@@ -3429,13 +3464,10 @@ bool routing_manager_impl::handle_local_offer_service(client_t _client, service_
}
if (!already_pinged) {
// find out endpoint of previously offering application
- std::shared_ptr<local_client_endpoint_base_impl>
- its_old_endpoint
- = std::dynamic_pointer_cast<local_client_endpoint_base_impl>(
- find_local(its_stored_client));
+ auto its_old_endpoint = find_local(its_stored_client);
if (its_old_endpoint) {
std::lock_guard<std::mutex> its_lock(pending_offers_mutex_);
- if(stub_->send_ping(its_stored_client)) {
+ if (stub_ && stub_->send_ping(its_stored_client)) {
pending_offers_[_service][_instance] =
std::make_tuple(_major, _minor, _client,
its_stored_client);
@@ -3557,10 +3589,11 @@ void routing_manager_impl::register_client_error_handler(client_t _client,
}
void routing_manager_impl::handle_client_error(client_t _client) {
- VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
+ VSOMEIP_INFO << "routing_manager_impl::" << __func__ << " Client 0x" << std::hex << get_client()
<< " handles a client error(" << std::hex << _client << ")";
if (stub_)
- stub_->update_registration(_client, registration_type_e::DEREGISTER_ON_ERROR);
+ stub_->update_registration(_client, registration_type_e::DEREGISTER_ON_ERROR,
+ boost::asio::ip::address(), 0);
std::forward_list<std::tuple<client_t, service_t, instance_t, major_version_t,
minor_version_t>> its_offers;
@@ -3619,17 +3652,18 @@ std::shared_ptr<endpoint_manager_impl> routing_manager_impl::get_endpoint_manage
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) {
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter) {
auto endpoint = ep_mgr_->find_local(_service, _instance);
- if (endpoint) {
+ if (endpoint && stub_) {
stub_->send_subscribe(endpoint, _client,
- _service, _instance, _eventgroup, _major, _event, PENDING_SUBSCRIPTION_ID);
+ _service, _instance,
+ _eventgroup, _major,
+ _event, _filter,
+ PENDING_SUBSCRIPTION_ID);
}
}
void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
-
- // Ignore setting to the current routing state
{
std::lock_guard<std::mutex> its_lock(routing_state_mutex_);
if (routing_state_ == _routing_state) {
@@ -3640,7 +3674,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
routing_state_ = _routing_state;
}
- if(discovery_) {
+ if (discovery_) {
switch (_routing_state) {
case routing_state_e::RS_SUSPENDED:
{
@@ -3656,6 +3690,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
// remove all remote subscriptions to remotely offered services on this node
expire_subscriptions(true);
+ std::vector<std::shared_ptr<serviceinfo>> _service_infos;
// send StopOffer messages for remotely offered services on this node
for (const auto &its_service : get_offered_services()) {
for (const auto &its_instance : its_service.second) {
@@ -3666,9 +3701,16 @@ 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_instance.second);
+ // collect stop offers to be sent out
+ if (discovery_->stop_offer_service(its_instance.second, false)) {
+ _service_infos.push_back(its_instance.second);
+ }
}
}
+ // send collected stop offers packed together in one ore multiple SD messages
+ discovery_->send_collected_stop_offers(_service_infos);
+ _service_infos.clear();
+
{
std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
remote_subscription_state_.clear();
@@ -3746,7 +3788,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_instance.second);
+ discovery_->stop_offer_service(its_instance.second, true);
}
}
}
@@ -3791,7 +3833,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
}
void routing_manager_impl::on_net_interface_or_route_state_changed(
- bool _is_interface, std::string _if, bool _available) {
+ bool _is_interface, const std::string &_if, bool _available) {
std::lock_guard<std::mutex> its_lock(pending_sd_offers_mutex_);
auto log_change_message = [&_if, _available, _is_interface](bool _warning) {
std::stringstream ss;
@@ -3864,36 +3906,184 @@ void routing_manager_impl::start_ip_routing() {
VSOMEIP_INFO << VSOMEIP_ROUTING_READY_MESSAGE;
}
-void routing_manager_impl::requested_service_add(client_t _client,
- service_t _service,
- instance_t _instance,
- major_version_t _major,
- minor_version_t _minor) {
+void
+routing_manager_impl::add_requested_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
std::lock_guard<std::mutex> ist_lock(requested_services_mutex_);
- requested_services_[_client][_service][_instance].insert({ _major, _minor });
+ requested_services_[_service][_instance][_major][_minor].insert(_client);
}
-void routing_manager_impl::requested_service_remove(client_t _client,
- service_t _service,
- instance_t _instance) {
+void
+routing_manager_impl::remove_requested_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
std::lock_guard<std::mutex> ist_lock(requested_services_mutex_);
- auto found_client = requested_services_.find(_client);
- if (found_client != requested_services_.end()) {
- auto found_service = found_client->second.find(_service);
- if (found_service != found_client->second.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- // delete all requested major/minor versions
- found_service->second.erase(_instance);
- if (!found_service->second.size()) {
- found_client->second.erase(_service);
- if (!found_client->second.size()) {
- requested_services_.erase(_client);
+
+ using minor_map_t = std::map<minor_version_t, std::set<client_t> >;
+ using major_map_t = std::map<major_version_t, minor_map_t>;
+ using instance_map_t = std::map<instance_t, major_map_t>;
+
+ auto delete_client = [&_client](
+ minor_map_t::iterator& _minor_iter,
+ const major_map_t::iterator& _parent_major_iter) {
+ if (_minor_iter->second.erase(_client)) { // client was requester
+ if (_minor_iter->second.empty()) {
+ // client was last requester of this minor version
+ _minor_iter = _parent_major_iter->second.erase(_minor_iter);
+ } else { // there are still other requesters of this minor version
+ ++_minor_iter;
+ }
+ } else { // client wasn't requester
+ ++_minor_iter;
+ }
+ };
+
+ auto handle_minor = [&_minor, &delete_client](
+ major_map_t::iterator& _major_iter,
+ const instance_map_t::iterator& _parent_instance_iter) {
+ if (_minor == ANY_MINOR) {
+ for (auto minor_iter = _major_iter->second.begin();
+ minor_iter != _major_iter->second.end(); ) {
+ delete_client(minor_iter, _major_iter);
+ }
+ } else {
+ auto found_minor = _major_iter->second.find(_minor);
+ if (found_minor != _major_iter->second.end()) {
+ delete_client(found_minor, _major_iter);
+ }
+ }
+ if (_major_iter->second.empty()) {
+ // client was last requester of this major version
+ _major_iter = _parent_instance_iter->second.erase(_major_iter);
+ } else {
+ ++_major_iter;
+ }
+ };
+
+ auto found_service = requested_services_.find(_service);
+ if (found_service != requested_services_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ if (_major == ANY_MAJOR) {
+ for (auto major_iter = found_instance->second.begin();
+ major_iter != found_instance->second.end();) {
+ handle_minor(major_iter, found_instance);
+ }
+ } else {
+ auto found_major = found_instance->second.find(_major);
+ if (found_major != found_instance->second.end()) {
+ handle_minor(found_major, found_instance);
+ }
+ }
+ if (found_instance->second.empty()) {
+ // client was last requester of this instance
+ found_service->second.erase(found_instance);
+ if (found_service->second.empty()) {
+ // client was last requester of this service
+ requested_services_.erase(found_service);
+ }
+ }
+ }
+ }
+}
+
+std::vector<std::pair<service_t, instance_t> >
+routing_manager_impl::get_requested_services(client_t _client) {
+ std::lock_guard<std::mutex> ist_lock(requested_services_mutex_);
+ std::vector<std::pair<service_t, instance_t>> its_requests;
+ for (const auto& service : requested_services_) {
+ for (const auto& instance : service.second) {
+ bool requested = false;
+ for (const auto& major : instance.second) {
+ for (const auto& minor : major.second) {
+ if (minor.second.find(_client) != minor.second.end()) {
+ requested = true;
+ break;
+ }
+ }
+ if (requested) {
+ break;
+ }
+ }
+ if (requested) {
+ its_requests.push_back(
+ std::make_pair(service.first, instance.first));
+ break;
+ }
+ }
+ }
+ return (its_requests);
+}
+
+std::set<client_t>
+routing_manager_impl::get_requesters(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ std::lock_guard<std::mutex> ist_lock(requested_services_mutex_);
+ return (get_requesters_unlocked(_service, _instance, _major, _minor));
+}
+
+std::set<client_t>
+routing_manager_impl::get_requesters_unlocked(
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ std::set<client_t> its_requesters;
+
+ auto found_service = requested_services_.find(_service);
+ if (found_service != requested_services_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (const auto& its_major : found_instance->second) {
+ if (its_major.first == _major || _major == DEFAULT_MAJOR
+ || its_major.first == ANY_MAJOR) {
+ for (const auto &its_minor : its_major.second) {
+ if (its_minor.first <= _minor
+ || _minor == DEFAULT_MINOR
+ || its_minor.first == ANY_MINOR) {
+ if (its_requesters.empty()) {
+ its_requesters = its_minor.second;
+ } else {
+ its_requesters.insert(its_minor.second.cbegin(),
+ its_minor.second.cend());
+ }
+ }
}
}
}
}
}
+ return (its_requesters);
+}
+
+bool
+routing_manager_impl::has_requester_unlocked(
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ auto found_service = requested_services_.find(_service);
+ if (found_service != requested_services_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (const auto& its_major : found_instance->second) {
+ if (its_major.first == _major || _major == DEFAULT_MAJOR
+ || its_major.first == ANY_MAJOR) {
+ for (const auto &its_minor : its_major.second) {
+ if (its_minor.first <= _minor
+ || _minor == DEFAULT_MINOR
+ || its_minor.first == ANY_MINOR) {
+
+ return (true);
+ }
+ }
+ }
+ }
+ }
+ }
+ return (false);
}
std::set<eventgroup_t>
@@ -3934,7 +4124,7 @@ void routing_manager_impl::clear_targets_and_pending_sub_from_eventgroups(
// 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) {
+ for (const auto its_subscriber : its_subscribers) {
if (its_subscriber != get_client()) {
its_event->remove_subscriber(
its_eventgroup.first, its_subscriber);
@@ -3994,7 +4184,9 @@ void routing_manager_impl::call_sd_endpoint_connected(
bool routing_manager_impl::create_placeholder_event_and_subscribe(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, client_t _client) {
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter,
+ 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
@@ -4047,7 +4239,8 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe(
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- is_inserted = its_event->add_subscriber(_eventgroup, _client, false);
+ is_inserted = its_event->add_subscriber(
+ _eventgroup, _filter, _client, false);
}
return is_inserted;
}
@@ -4097,7 +4290,7 @@ void routing_manager_impl::handle_subscription_state(
// Subscription already acknowledged!
if (_client == get_client()) {
host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
- } else {
+ } else if (stub_) {
stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup, _event);
}
}
@@ -4140,11 +4333,10 @@ void routing_manager_impl::memory_log_timer_cbk(
if (_error) {
return;
}
-#ifndef _WIN32
+
+#if defined(__linux__) || defined(ANDROID)
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
+
std::FILE *its_file = std::fopen("/proc/self/statm", "r");
if (!its_file) {
VSOMEIP_ERROR << "memory_log_timer_cbk: couldn't open:"
@@ -4166,11 +4358,10 @@ void routing_manager_impl::memory_log_timer_cbk(
<< std::string(std::strerror(errno));
}
std::fclose(its_file);
-#ifndef _WIN32
+
struct timespec cputs, monots;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cputs);
clock_gettime(CLOCK_MONOTONIC, &monots);
-#endif
VSOMEIP_INFO << "memory usage: "
<< "VmSize " << std::dec << its_size * its_pagesize << " kB, "
@@ -4178,12 +4369,11 @@ void routing_manager_impl::memory_log_timer_cbk(
<< "shared pages " << std::dec << its_sharedpages * its_pagesize << " kB, "
<< "text " << std::dec << its_text * its_pagesize << " kB, "
<< "data " << std::dec << its_data * its_pagesize << " kB "
-#ifndef _WIN32
<< "| monotonic time: " << std::dec << monots.tv_sec << "."
<< std::dec << monots.tv_nsec << " cpu time: "
<< std::dec << cputs.tv_sec << "." << std::dec << cputs.tv_nsec
-#endif
;
+#endif
{
std::lock_guard<std::mutex> its_lock(memory_log_timer_mutex_);
@@ -4278,8 +4468,9 @@ void routing_manager_impl::send_subscription(
const remote_subscription_id_t _id) {
if (host_->get_client() == _offering_client) {
auto self = shared_from_this();
- for (const auto& its_client : _clients) {
- host_->on_subscription(_service, _instance, _eventgroup, its_client, own_uid_, own_gid_, true,
+ for (const auto its_client : _clients) {
+ host_->on_subscription(_service, _instance, _eventgroup, its_client,
+ get_sec_client(), get_env(its_client), true,
[this, self, _service, _instance, _eventgroup, its_client, _id]
(const bool _is_accepted) {
try {
@@ -4288,7 +4479,7 @@ void routing_manager_impl::send_subscription(
&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, false);
+ _eventgroup, ANY_EVENT, _id);
io_.post(its_callback);
} else {
const auto its_callback = std::bind(
@@ -4304,15 +4495,15 @@ void routing_manager_impl::send_subscription(
});
}
} 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)) {
+ for (const auto its_client : _clients) {
+ if (stub_ && !stub_->send_subscribe(find_local(_offering_client), its_client,
+ _service, _instance, _eventgroup, _major, ANY_EVENT, nullptr, _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()),
its_client, _service, _instance, _eventgroup,
- ANY_EVENT, _id, true);
+ ANY_EVENT, _id);
io_.post(its_callback);
} catch (const std::exception &e) {
VSOMEIP_ERROR << __func__ << e.what();
@@ -4378,7 +4569,8 @@ void routing_manager_impl::on_resend_provided_events_response(
}
void routing_manager_impl::print_stub_status() const {
- stub_->print_endpoint_status();
+ if (stub_)
+ stub_->print_endpoint_status();
}
void routing_manager_impl::service_endpoint_connected(
@@ -4389,9 +4581,12 @@ void routing_manager_impl::service_endpoint_connected(
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,
+ on_availability(_service, _instance,
+ availability_state_e::AS_AVAILABLE,
_major, _minor);
+ if (stub_)
+ stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance,
+ _major, _minor);
}
std::shared_ptr<boost::asio::steady_timer> its_timer =
@@ -4413,9 +4608,12 @@ 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,
+ on_availability(_service, _instance,
+ availability_state_e::AS_UNAVAILABLE,
_major, _minor);
+ if (stub_)
+ 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 << "]";
@@ -4432,9 +4630,9 @@ routing_manager_impl::send_unsubscription(client_t _offering_client,
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,
+ for (const auto its_client : _removed) {
+ host_->on_subscription(_service, _instance, _eventgroup,
+ its_client, get_sec_client(), get_env(its_client),false,
[this, self, _service, _instance, _eventgroup,
its_client, _id]
(const bool _is_accepted) {
@@ -4452,8 +4650,8 @@ routing_manager_impl::send_unsubscription(client_t _offering_client,
);
}
} else {
- for (const auto& its_client : _removed) {
- if (!stub_->send_unsubscribe(find_local(_offering_client), its_client,
+ for (const auto its_client : _removed) {
+ if (stub_ && !stub_->send_unsubscribe(find_local(_offering_client), its_client,
_service, _instance, _eventgroup, ANY_EVENT, _id)) {
try {
const auto its_callback = std::bind(
@@ -4480,19 +4678,21 @@ routing_manager_impl::send_expired_subscription(client_t _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,
+ _eventgroup, its_client, get_sec_client(), get_env(its_client), false,
[] (const bool _subscription_accepted){
(void)_subscription_accepted;
});
}
} else {
for (const auto its_client : _removed) {
- stub_->send_expired_subscription(find_local(_offering_client), its_client,
- _service, _instance, _eventgroup, ANY_EVENT, _id);
+ if (stub_)
+ stub_->send_expired_subscription(find_local(_offering_client), its_client,
+ _service, _instance, _eventgroup, ANY_EVENT, _id);
}
}
}
+#ifndef VSOMEIP_DISABLE_SECURITY
bool
routing_manager_impl::update_security_policy_configuration(
uint32_t _uid, uint32_t _gid,
@@ -4518,6 +4718,7 @@ routing_manager_impl::remove_security_policy_configuration(
return (false);
}
+#endif // !VSOMEIP_DISABLE_SECURITY
bool routing_manager_impl::insert_event_statistics(service_t _service, instance_t _instance,
method_t _method, length_t _length) {
@@ -4527,7 +4728,7 @@ bool routing_manager_impl::insert_event_statistics(service_t _service, instance_
const auto its_tuple = std::make_tuple(_service, _instance, _method);
const auto its_main_s = message_statistics_.find(its_tuple);
if (its_main_s != message_statistics_.end()) {
- // increase counter and calculate moving avergae for payload length
+ // increase counter and calculate moving average for payload length
its_main_s->second.avg_length_ =
(its_main_s->second.avg_length_ * its_main_s->second.counter_ + _length) /
(its_main_s->second.counter_ + 1);
@@ -4537,10 +4738,10 @@ bool routing_manager_impl::insert_event_statistics(service_t _service, instance_
// check list for entry with least counter value
uint32_t its_min_count(0xFFFFFFFF);
auto its_tuple_to_discard = std::make_tuple(0xFFFF, 0xFFFF, 0xFFFF);
- for (const auto &it : message_statistics_) {
- if (it.second.counter_ < its_min_count) {
- its_min_count = it.second.counter_;
- its_tuple_to_discard = it.first;
+ for (const auto &s : message_statistics_) {
+ if (s.second.counter_ < its_min_count) {
+ its_min_count = s.second.counter_;
+ its_tuple_to_discard = s.first;
}
}
if (its_min_count != 0xFFFF
@@ -4580,7 +4781,7 @@ void routing_manager_impl::statistics_log_timer_cbk(boost::system::error_code co
{
std::lock_guard<std::mutex> its_lock(message_statistics_mutex_);
for (const auto &s : message_statistics_) {
- if (s.second.counter_ / (its_interval / 1000) >= its_min_freq) {
+ if (s.second.counter_ / (its_interval / 1000) > its_min_freq) {
uint16_t its_subscribed(0);
std::shared_ptr<event> its_event = find_event(std::get<0>(s.first), std::get<1>(s.first), std::get<2>(s.first));
if (its_event) {
@@ -4621,9 +4822,86 @@ void routing_manager_impl::statistics_log_timer_cbk(boost::system::error_code co
}
}
+bool
+routing_manager_impl::get_guest(client_t _client,
+ boost::asio::ip::address &_address, port_t &_port) const {
+
+ return (routing_manager_base::get_guest(_client, _address, _port));
+}
+
+void
+routing_manager_impl::add_guest(client_t _client,
+ const boost::asio::ip::address &_address, port_t _port) {
+
+ routing_manager_base::add_guest(_client, _address, _port);
+}
+
+void
+routing_manager_impl::remove_guest(client_t _client) {
+
+ routing_manager_base::remove_guest(_client);
+}
+
void routing_manager_impl::send_suspend() const {
+ if (stub_)
+ stub_->send_suspend();
+}
+
+void routing_manager_impl::clear_local_services() {
+
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ local_services_.clear();
+}
+
+void routing_manager_impl::register_message_acceptance_handler(
+ const message_acceptance_handler_t& _handler) {
+ message_acceptance_handler_ = _handler;
+}
+
+void
+routing_manager_impl::remove_subscriptions(port_t _local_port,
+ const boost::asio::ip::address &_remote_address,
+ port_t _remote_port) {
+
+ std::map<service_t,
+ std::map<instance_t,
+ std::map<eventgroup_t,
+ std::shared_ptr<eventgroupinfo> > > >its_eventgroups;
+ {
+ std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
+ its_eventgroups = eventgroups_;
+ }
+ for (const auto &its_service : its_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()) {
+ auto its_definition = its_subscription->get_reliable();
+ if (its_definition
+ && its_definition->get_address() == _remote_address
+ && its_definition->get_port() == _remote_port
+ && its_definition->get_remote_port() == _local_port) {
+
+ VSOMEIP_INFO << __func__
+ << ": Removing subscription to ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_info->get_service() << "."
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_info->get_instance() << "."
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_info->get_eventgroup()
+ << "] from target "
+ << its_definition->get_address() << ":"
+ << std::dec << its_definition->get_port()
+ << " reliable=true";
- stub_->send_suspend();
+ on_remote_unsubscribe(its_subscription);
+ }
+ }
+ }
+ }
+ }
}
} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
deleted file mode 100644
index 06573a5..0000000
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ /dev/null
@@ -1,2734 +0,0 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <climits>
-#include <iomanip>
-#include <mutex>
-#include <unordered_set>
-#include <future>
-#include <forward_list>
-
-#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 "../../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 "../../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"
-#ifdef USE_DLT
-#include "../../tracing/include/connector_impl.hpp"
-#endif
-
-namespace vsomeip_v3 {
-
-routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host,
- bool _client_side_logging,
- const std::set<std::tuple<service_t, instance_t> > & _client_side_logging_filter) :
- routing_manager_base(_host),
- is_connected_(false),
- is_started_(false),
- state_(inner_state_type_e::ST_DEREGISTERED),
- sender_(nullptr),
- receiver_(nullptr),
- register_application_timer_(io_),
- request_debounce_timer_ (io_),
- request_debounce_timer_running_(false),
- client_side_logging_(_client_side_logging),
- client_side_logging_filter_(_client_side_logging_filter)
-{
-}
-
-routing_manager_proxy::~routing_manager_proxy() {
-}
-
-void routing_manager_proxy::init() {
- routing_manager_base::init(std::make_shared<endpoint_manager_base>(this, io_, configuration_));
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
- }
-}
-
-void routing_manager_proxy::start() {
- is_started_ = true;
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (!sender_) {
- // application has been stopped and started again
- sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
- }
- if (sender_) {
- sender_->start();
- }
- }
-}
-
-void routing_manager_proxy::stop() {
- std::unique_lock<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERING) {
- register_application_timer_.cancel();
- }
-
- const std::chrono::milliseconds its_timeout(configuration_->get_shutdown_timeout());
- while (state_ == inner_state_type_e::ST_REGISTERING) {
- std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
- if (status == std::cv_status::timeout) {
- VSOMEIP_WARNING << std::hex << client_ << " registering timeout on stop";
- break;
- }
- }
-
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- deregister_application();
- // Waiting de-register acknowledge to synchronize shutdown
- while (state_ == inner_state_type_e::ST_REGISTERED) {
- std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
- if (status == std::cv_status::timeout) {
- VSOMEIP_WARNING << std::hex << client_ << " couldn't deregister application - timeout";
- break;
- }
- }
- }
- is_started_ = false;
- its_lock.unlock();
-
- {
- std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
- request_debounce_timer_.cancel();
- }
-
- if (receiver_) {
- receiver_->stop();
- }
- receiver_ = nullptr;
-
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->stop();
- }
- // delete the sender
- sender_ = nullptr;
- }
-
- for (const auto& client : ep_mgr_->get_connected_clients()) {
- if (client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(client, true);
- }
- }
-
- std::stringstream its_client;
- its_client << utility::get_base_path(configuration_) << std::hex << client_;
-#ifdef _WIN32
- ::_unlink(its_client.str().c_str());
-#else
- if (-1 == ::unlink(its_client.str().c_str())) {
- VSOMEIP_ERROR<< "routing_manager_proxy::stop unlink failed ("
- << its_client.str() << "): "<< std::strerror(errno);
- }
-#endif
-}
-
-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) {
-
- 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";
- return false;
- }
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- send_offer_service(_client, _service, _instance, _major, _minor);
- }
- 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) {
- (void)_client;
-
- byte_t its_command[VSOMEIP_OFFER_SERVICE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_OFFER_SERVICE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_OFFER_SERVICE;
- 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));
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major;
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor,
- sizeof(_minor));
-
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-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;
-
- {
- // Hold the mutex to ensure no placeholder event is created inbetween.
- std::lock_guard<std::mutex> its_lock(stop_mutex_);
-
- routing_manager_base::stop_offer_service(_client, _service, _instance, _major, _minor);
- clear_remote_subscriber_count(_service, _instance);
-
- // Note: The last argument does not matter here as a proxy
- // does not manage endpoints to the external network.
- clear_service_info(_service, _instance, false);
- }
-
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- byte_t its_command[VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_STOP_OFFER_SERVICE;
- 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));
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major;
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor,
- sizeof(_minor));
-
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
- }
- auto it = pending_offers_.begin();
- while (it != pending_offers_.end()) {
- if (it->service_ == _service
- && it->instance_ == _instance) {
- break;
- }
- it++;
- }
- if (it != pending_offers_.end()) pending_offers_.erase(it);
- }
-}
-
-void routing_manager_proxy::request_service(client_t _client,
- 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 };
- if (!request_debouncing_time) {
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- std::set<service_data_t> requests;
- requests.insert(request);
- send_request_services(requests);
- }
- requests_.insert(request);
- } else {
- requests_to_debounce_.insert(request);
- std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
- if (!request_debounce_timer_running_) {
- request_debounce_timer_running_ = true;
- request_debounce_timer_.expires_from_now(std::chrono::milliseconds(request_debouncing_time));
- request_debounce_timer_.async_wait(
- std::bind(
- &routing_manager_proxy::request_debounce_timeout_cbk,
- std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()),
- std::placeholders::_1));
- }
- }
- }
-}
-
-void routing_manager_proxy::release_service(client_t _client,
- service_t _service, instance_t _instance) {
- routing_manager_base::release_service(_client, _service, _instance);
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- remove_pending_subscription(_service, _instance, 0xFFFF, ANY_EVENT);
-
- auto it = requests_to_debounce_.begin();
- while (it != requests_to_debounce_.end()) {
- if (it->service_ == _service
- && it->instance_ == _instance) {
- break;
- }
- it++;
- }
- if (it != requests_to_debounce_.end()) {
- requests_to_debounce_.erase(it);
- } else if (state_ == inner_state_type_e::ST_REGISTERED) {
- send_release_service(_client, _service, _instance);
- }
-
- {
- auto it = requests_.begin();
- while (it != requests_.end()) {
- if (it->service_ == _service
- && it->instance_ == _instance) {
- break;
- }
- it++;
- }
- if (it != requests_.end()) requests_.erase(it);
- }
- }
-}
-
-void routing_manager_proxy::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)_is_shadow;
- (void)_is_cache_placeholder;
-
- const event_data_t registration = {
- _service,
- _instance,
- _notifier,
- _type,
- _reliability,
- _is_provided,
- _eventgroups
- };
- bool is_first(false);
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- is_first = pending_event_registrations_.find(registration)
- == pending_event_registrations_.end();
-#ifndef VSOMEIP_ENABLE_COMPAT
- if (is_first) {
- pending_event_registrations_.insert(registration);
- }
-#else
- bool insert = true;
- if (is_first) {
- for (auto iter = pending_event_registrations_.begin();
- iter != pending_event_registrations_.end();) {
- if (iter->service_ == _service
- && iter->instance_ == _instance
- && iter->notifier_ == _notifier
- && iter->is_provided_ == _is_provided
- && iter->type_ == event_type_e::ET_EVENT
- && _type == event_type_e::ET_SELECTIVE_EVENT) {
- iter = pending_event_registrations_.erase(iter);
- iter = pending_event_registrations_.insert(registration).first;
- is_first = true;
- insert = false;
- break;
- } else {
- iter++;
- }
- }
- if (insert) {
- pending_event_registrations_.insert(registration);
- }
- }
-#endif
- }
- if (is_first || _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,
- _notifier, _eventgroups, _type, _reliability, _is_provided);
- }
- }
-}
-
-void routing_manager_proxy::unregister_event(client_t _client,
- service_t _service, instance_t _instance, event_t _notifier,
- bool _is_provided) {
-
- routing_manager_base::unregister_event(_client, _service, _instance,
- _notifier, _is_provided);
-
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- byte_t its_command[VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNREGISTER_EVENT;
- 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], &_notifier,
- sizeof(_notifier));
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
- = static_cast<byte_t>(_is_provided);
-
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
- }
-
- for (auto iter = pending_event_registrations_.begin();
- iter != pending_event_registrations_.end(); ) {
- if (iter->service_ == _service
- && iter->instance_ == _instance
- && iter->notifier_ == _notifier
- && iter->is_provided_ == _is_provided) {
- pending_event_registrations_.erase(iter);
- break;
- } else {
- iter++;
- }
- }
- }
-}
-
-bool routing_manager_proxy::is_field(service_t _service, instance_t _instance,
- event_t _event) const {
- auto event = find_event(_service, _instance, _event);
- if (event && event->is_field()) {
- return true;
- }
- return false;
-}
-
-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) {
- (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(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 "
- << _service << "/" << _instance << "/ANY_EVENT"
- << " which violates the security policy ~> Skip subscribe!";
- return;
- }
- } else {
- 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 "
- << _service << "/" << _instance
- << "/" << _event;
- return;
- }
- }
-
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED && is_available(_service, _instance, _major)) {
- send_subscribe(client_, _service, _instance, _eventgroup, _major, _event );
- }
- 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) {
- (void)_client;
-
- byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE;
- 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], &_eventgroup,
- sizeof(_eventgroup));
- 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],
- &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 = 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_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-void routing_manager_proxy::send_subscribe_nack(client_t _subscriber,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- 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;
-
- client_t its_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_NACK;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
- sizeof(its_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
- sizeof(_service));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
- sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_subscriber,
- sizeof(_subscriber));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
- sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &_id,
- sizeof(_id));
-
- if (_subscriber != VSOMEIP_ROUTING_CLIENT
- && _id == PENDING_SUBSCRIPTION_ID) {
- auto its_target = ep_mgr_->find_local(_subscriber);
- if (its_target) {
- its_target->send(its_command, sizeof(its_command));
- return;
- }
- }
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-void routing_manager_proxy::send_subscribe_ack(client_t _subscriber,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- 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;
-
- client_t its_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_ACK;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
- sizeof(its_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
- sizeof(_service));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
- sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_subscriber,
- sizeof(_subscriber));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
- sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &_id,
- sizeof(_id));
-
- if (_subscriber != VSOMEIP_ROUTING_CLIENT
- && _id == PENDING_SUBSCRIPTION_ID) {
- auto its_target = ep_mgr_->find_local(_subscriber);
- if (its_target) {
- its_target->send(its_command, sizeof(its_command));
- return;
- }
- }
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-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);
-
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNSUBSCRIBE;
- 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], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
- sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
- &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
-
- auto its_target = ep_mgr_->find_local(_service, _instance);
- if (its_target) {
- its_target->send(its_command, sizeof(its_command));
- } else {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
- }
- }
-}
-
-bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
- length_t _size, instance_t _instance,
- bool _reliable,
- client_t _bound_client,
- 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);
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ != inner_state_type_e::ST_REGISTERED) {
- return false;
- }
- }
- if (client_side_logging_) {
- if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
- service_t its_service = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SERVICE_POS_MIN],
- _data[VSOMEIP_SERVICE_POS_MAX]);
- if (client_side_logging_filter_.empty()
- || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, ANY_INSTANCE)))
- || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, _instance)))) {
- method_t its_method = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
- session_t its_session = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SESSION_POS_MIN],
- _data[VSOMEIP_SESSION_POS_MAX]);
- client_t its_client = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_CLIENT_POS_MIN],
- _data[VSOMEIP_CLIENT_POS_MAX]);
- VSOMEIP_INFO << "routing_manager_proxy::send: ("
- << std::hex << std::setw(4) << std::setfill('0') << client_ <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << ":"
- << std::hex << std::setw(4) << std::setfill('0') << its_session << ":"
- << std::hex << std::setw(4) << std::setfill('0') << its_client << "] "
- << "type=" << std::hex << static_cast<std::uint32_t>(_data[VSOMEIP_MESSAGE_TYPE_POS])
- << " thread=" << std::hex << std::this_thread::get_id();
- }
- } else {
- VSOMEIP_ERROR << "routing_manager_proxy::send: ("
- << std::hex << std::setw(4) << std::setfill('0') << client_
- <<"): message too short to log: " << std::dec << _size;
- }
- }
- if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
- std::shared_ptr<endpoint> its_target;
- if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- // Request
- service_t its_service = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SERVICE_POS_MIN],
- _data[VSOMEIP_SERVICE_POS_MAX]);
- client_t its_client = find_local_client(its_service, _instance);
- if (its_client != VSOMEIP_ROUTING_CLIENT) {
- if (is_client_known(its_client)) {
- its_target = ep_mgr_->find_or_create_local(its_client);
- }
- }
- } else if (!utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- // Response
- client_t its_client = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_CLIENT_POS_MIN],
- _data[VSOMEIP_CLIENT_POS_MAX]);
- if (its_client != VSOMEIP_ROUTING_CLIENT) {
- if (is_client_known(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, _reliable, _status_check);
- } else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) &&
- _client != VSOMEIP_ROUTING_CLIENT) {
- // notify_one
- its_target = ep_mgr_->find_local(_client);
- if (its_target) {
-#ifdef USE_DLT
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
- trace::header its_header;
- if (its_header.prepare(nullptr, true, _instance))
- tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
-#endif
- return send_local(its_target, get_client(), _data, _size,
- _instance, _reliable, VSOMEIP_SEND, _status_check);
- }
- }
- // If no direct endpoint could be found
- // or for notifications ~> route to routing_manager_stub
-#ifdef USE_DLT
- bool message_to_stub(false);
-#endif
- if (!its_target) {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- its_target = sender_;
-#ifdef USE_DLT
- message_to_stub = true;
-#endif
- } else {
- return false;
- }
- }
-
- bool send(true);
- uint8_t command = VSOMEIP_SEND;
-
- if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- if (_client != VSOMEIP_ROUTING_CLIENT) {
- command = VSOMEIP_NOTIFY_ONE;
- } else {
- command = VSOMEIP_NOTIFY;
- // Do we need to deliver a notification to the routing manager?
- // Only for services which already have remote clients subscribed to
- send = has_remote_subscribers;
- }
- }
-#ifdef USE_DLT
- else if (!message_to_stub) {
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
- trace::header its_header;
- if (its_header.prepare(nullptr, true, _instance))
- tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
- }
-#endif
- if (send) {
- is_sent = send_local(its_target,
- (command == VSOMEIP_NOTIFY_ONE ? _client : get_client()),
- _data, _size, _instance, _reliable, command, _status_check);
- }
- }
- return (is_sent);
-}
-
-bool routing_manager_proxy::send_to(const client_t _client,
- const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message) {
- (void)_client;
- (void)_target;
- (void)_message;
- 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) {
- (void)_target;
- (void)_data;
- (void)_size;
- (void)_instance;
- return (false);
-}
-
-void routing_manager_proxy::on_connect(const std::shared_ptr<endpoint>& _endpoint) {
- _endpoint->set_connected(true);
- _endpoint->set_established(true);
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (_endpoint != sender_) {
- return;
- }
- }
- is_connected_ = true;
- assign_client();
-}
-
-void routing_manager_proxy::on_disconnect(const std::shared_ptr<endpoint>& _endpoint) {
-
- bool is_disconnected((_endpoint == sender_));
- if (is_disconnected) {
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- is_connected_ = false;
- }
-
- VSOMEIP_INFO << "routing_manager_proxy::on_disconnect: Client 0x" << std::hex
- << get_client() << " calling host_->on_state "
- << "with DEREGISTERED";
- host_->on_state(state_type_e::ST_DEREGISTERED);
- }
-}
-
-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;
- (void)_destination;
- (void)_remote_address;
- (void)_remote_port;
-#if 0
- std::stringstream msg;
- msg << "rmp::on_message: ";
- for (length_t i = 0; i < _size; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- byte_t its_command;
- client_t its_client;
- length_t its_length;
- service_t its_service;
- instance_t its_instance;
- eventgroup_t its_eventgroup;
- event_t its_event;
- major_version_t its_major;
- client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
- client_t its_subscriber;
- remote_subscription_id_t its_subscription_id(PENDING_SUBSCRIPTION_ID);
- std::uint32_t its_remote_subscriber_count(0);
- bool is_internal_policy_update(false);
-
- 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],
- sizeof(its_client));
- std::memcpy(&its_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
- sizeof(its_length));
-
- bool message_from_routing(false);
- 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);
- } else {
- message_from_routing = (its_client == routing_host_id);
- }
-
- 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
- << " from " << std::setw(4) << std::setfill('0')
- << its_client << " which doesn't match the bound client "
- << std::setw(4) << std::setfill('0') << _bound_client
- << " ~> skip message!";
- return;
- }
-
- switch (its_command) {
- case VSOMEIP_SEND: {
- if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a SEND command with too small size -> skip!";
- break;
- }
- instance_t its_instance;
- bool its_reliable;
- 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_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 -
- (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
-
- if (its_message_size !=
- VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
- + VSOMEIP_SOMEIP_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a SEND command containing message with invalid size -> skip!";
- break;
- }
-
- auto a_deserializer = get_deserializer();
- a_deserializer->set_data(&_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS],
- its_message_size);
- 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_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(),
- its_message->get_instance(), its_message->get_method())) {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
- << " : routing_manager_proxy::on_message: "
- << " received a notification from client 0x" << _bound_client
- << " which does not offer service/instance/event "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method()
- << " ~> Skip message!";
- return;
- } else {
- if (!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: "
- << " isn't allowed to receive a notification from service/instance/event "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method()
- << " respectively from client 0x" << _bound_client
- << " ~> Skip message!";
- return;
- }
- cache_event_payload(its_message);
- }
- } else if (utility::is_request(its_message->get_message_type())) {
- if (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')
- << its_message->get_client() << " to service/instance/method "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method() << " which doesn't match the bound client 0x"
- << std::setw(4) << std::setfill('0') << _bound_client
- << " ~> skip message!";
- return;
- }
-
- if (!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 "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method()
- << " ~> Skip message!";
- return;
- }
- } else { // response
- if (!is_response_allowed(_bound_client, its_message->get_service(),
- its_message->get_instance(), its_message->get_method())) {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
- << " : routing_manager_proxy::on_message: "
- << " received a response from client 0x" << _bound_client
- << " which does not offer service/instance/method "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method()
- << " ~> Skip message!";
- return;
- } else {
- if (!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: "
- << " isn't allowed to receive a response from service/instance/method "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method()
- << " respectively from client 0x" << _bound_client
- << " ~> Skip message!";
- return;
- }
- }
- }
- } else {
- 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()
- << " : routing_manager_proxy::on_message: "
- << std::hex << "Security: Remote clients via routing manager with client ID 0x" << its_client
- << " are not allowed to communicate with service/instance/method "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method()
- << " respectively with client 0x" << get_client()
- << " ~> Skip message!";
- return;
- } else if (utility::is_notification(its_message->get_message_type())) {
- // As subscription is sent on eventgroup level, incoming remote event ID's
- // need to be checked as well if remote clients are allowed
- // and the local policy only allows specific events in the eventgroup to be received.
- if (!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: "
- << " isn't allowed to receive a notification from service/instance/event "
- << its_message->get_service() << "/" << its_message->get_instance()
- << "/" << its_message->get_method()
- << " respectively from remote clients via routing manager with client ID 0x"
- << routing_host_id
- << " ~> Skip message!";
- return;
- }
- cache_event_payload(its_message);
- }
- }
-#ifdef USE_DLT
- if (client_side_logging_
- && (client_side_logging_filter_.empty()
- || (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), ANY_INSTANCE)))
- || (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), its_message->get_instance()))))) {
- trace::header its_header;
- if (its_header.prepare(nullptr, false, its_instance))
- tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS],
- static_cast<std::uint16_t>(its_message_size));
- }
-#endif
-
- host_->on_message(std::move(its_message));
- } else {
- VSOMEIP_ERROR << "Routing proxy: on_message: "
- << "SomeIP-Header deserialization failed!";
- }
- 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 (!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: "
- << std::hex << "Security: Client 0x" << get_client()
- << " received an routing info from a client which isn't the routing manager"
- << " : Skip message!";
- }
- break;
-
- case VSOMEIP_PING:
- if (_size != VSOMEIP_PING_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a PING command with wrong size ~> skip!";
- break;
- }
- send_pong();
- VSOMEIP_TRACE << "PING("
- << std::hex << std::setw(4) << std::setfill('0') << client_ << ")";
- break;
-
- case VSOMEIP_SUBSCRIBE:
- if (_size != VSOMEIP_SUBSCRIBE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a SUBSCRIBE 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- 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_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 != 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, 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){
- std::uint32_t its_count = 0;
- if(_subscription_accepted) {
- send_subscribe_ack(its_client, its_service, its_instance,
- its_eventgroup, its_event, its_subscription_id);
- std::set<event_t> its_already_subscribed_events;
- bool inserted = insert_subscription(its_service, its_instance, its_eventgroup,
- its_event, VSOMEIP_ROUTING_CLIENT, &its_already_subscribed_events);
- if (inserted) {
- 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
- its_count = get_remote_subscriber_count(its_service, its_instance, its_eventgroup, true);
- } else {
- send_subscribe_nack(its_client, its_service, its_instance,
- its_eventgroup, its_event, its_subscription_id);
- }
- VSOMEIP_INFO << "SUBSCRIBE("
- << 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::dec << (uint16_t)its_major << "] "
- << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " "
- << (_subscription_accepted ? std::to_string(its_count) : "-")
- << (_subscription_accepted ? " ACCEPTED" : " NOT ACCEPTED");
-#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(_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 "
- << its_service << "/" << its_instance << "/ANY_EVENT"
- << " which violates the security policy ~> Skip subscribe!";
- return;
- }
- } else {
- 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 "
- << its_service << "/" << its_instance << "/" << its_event
- << " which violates the security policy ~> Skip subscribe!";
- return;
- }
- }
- } else {
- 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"
- << its_client
- << " isn't allowed to subscribe to service/instance/event "
- << its_service << "/" << its_instance
- << "/" << its_event
- << " respectively to client 0x" << get_client()
- << " ~> Skip Subscribe!";
- return;
- }
- }
-
- // Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
-#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
- (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, 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, PENDING_SUBSCRIPTION_ID);
- } else {
- send_subscribe_ack(its_client, its_service, its_instance,
- 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, its_sender_uid, its_sender_gid };
- pending_incoming_subscripitons_[its_client].insert(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 << "."
- << 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::dec << (uint16_t)its_major << "]";
- }
- break;
-
- case VSOMEIP_UNSUBSCRIBE:
- if (_size != VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received an UNSUBSCRIBE 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_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_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
- sizeof(its_subscription_id));
- 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_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, ANY_UID, ANY_GID, its_service,
- its_instance, its_eventgroup, its_event);
- }
- send_unsubscribe_ack(its_service, its_instance, its_eventgroup,
- its_subscription_id);
- }
- VSOMEIP_INFO << "UNSUBSCRIBE("
- << 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 << "] "
- << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " "
- << std::dec << its_remote_subscriber_count;
- break;
-
- case VSOMEIP_EXPIRED_SUBSCRIPTION:
- if (_size != VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received an VSOMEIP_EXPIRED_SUBSCRIPTION 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_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_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
- sizeof(its_subscription_id));
- 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_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, ANY_UID, ANY_GID, its_service,
- its_instance, its_eventgroup, its_event);
- }
- }
- VSOMEIP_INFO << "UNSUBSCRIBE EXPIRED SUBSCRIPTION("
- << 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 << "] "
- << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " "
- << std::dec << its_remote_subscriber_count;
- break;
-
- case VSOMEIP_SUBSCRIBE_NACK:
- if (_size != VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a VSOMEIP_SUBSCRIBE_NACK 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- 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));
-
- on_subscribe_nack(its_subscriber, its_service, its_instance, its_eventgroup, its_event);
- 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 << "]";
- break;
-
- case VSOMEIP_SUBSCRIBE_ACK:
- if (_size != VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a VSOMEIP_SUBSCRIBE_ACK 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- 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));
-
- on_subscribe_ack(its_subscriber, its_service, its_instance, its_eventgroup, its_event);
- 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 << "]";
- 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 (!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()
- << " received an offered services info from a client which isn't the routing manager"
- << " : Skip message!";
- }
- break;
- case VSOMEIP_RESEND_PROVIDED_EVENTS: {
- if (_size != VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a RESEND_PROVIDED_EVENTS command with wrong size ~> skip!";
- break;
- }
- pending_remote_offer_id_t its_pending_remote_offer_id(0);
- std::memcpy(&its_pending_remote_offer_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(pending_remote_offer_id_t));
- resend_provided_event_registrations();
- send_resend_provided_event_response(its_pending_remote_offer_id);
- VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
- << std::hex << std::setw(4) << std::setfill('0')
- << its_client << ")";
- break;
- }
- case VSOMEIP_UPDATE_SECURITY_POLICY_INT:
- is_internal_policy_update = true;
- /* Fallthrough */
- case VSOMEIP_UPDATE_SECURITY_POLICY: {
- if (_size < VSOMEIP_COMMAND_HEADER_SIZE + sizeof(pending_security_update_id_t) ||
- _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
- VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY command with wrong size -> skip!";
- break;
- }
- if (!its_security->is_enabled() || message_from_routing) {
- pending_security_update_id_t its_update_id(0);
-
- std::memcpy(&its_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(pending_security_update_id_t));
-
- std::shared_ptr<policy> its_policy(std::make_shared<policy>());
- const byte_t *its_policy_data = _data + (VSOMEIP_COMMAND_PAYLOAD_POS +
- sizeof(pending_security_update_id_t));
-
- uint32_t its_policy_size = uint32_t(_size - (VSOMEIP_COMMAND_PAYLOAD_POS
- + sizeof(pending_security_update_id_t)));
-
- bool is_valid = its_policy->deserialize(its_policy_data, its_policy_size);
- if (is_valid) {
- uint32_t its_uid;
- uint32_t its_gid;
- is_valid = its_policy->get_uid_gid(its_uid, its_gid);
- if (is_valid) {
- if (is_internal_policy_update
- || 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 {
- VSOMEIP_ERROR << "vSomeIP Security: Policy has no valid uid/gid!";
- }
- } else {
- VSOMEIP_ERROR << "vSomeIP Security: Policy deserialization failed!";
- }
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
- << " : routing_manager_proxy::on_message: "
- << " received a security policy update from a client which isn't the routing manager"
- << " : Skip message!";
- }
- break;
- }
- case VSOMEIP_REMOVE_SECURITY_POLICY: {
- if (_size != VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE) {
- VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_REMOVE_SECURITY_POLICY command with wrong size ~> skip!";
- break;
- }
- if (!its_security->is_enabled() || message_from_routing) {
- pending_security_update_id_t its_update_id(0);
- 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));
- std::memcpy(&its_uid, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(uint32_t));
- std::memcpy(&its_gid, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
- sizeof(uint32_t));
- if (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 {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
- << " : routing_manager_proxy::on_message: "
- << "received a security policy removal from a client which isn't the routing manager"
- << " : Skip message!";
- }
- break;
- }
- case VSOMEIP_DISTRIBUTE_SECURITY_POLICIES: {
- if (_size < VSOMEIP_COMMAND_HEADER_SIZE ||
- _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
- VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_DISTRIBUTE_SECURITY_POLICIES command with wrong size -> skip!";
- break;
- }
- if (!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;
-
- if (VSOMEIP_COMMAND_PAYLOAD_POS + sizeof(uint32_t) * 2 <= _size) {
- std::memcpy(&its_policy_count, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(uint32_t));
-
- // skip policy count field
- buffer_ptr = _data + (VSOMEIP_COMMAND_PAYLOAD_POS +
- sizeof(uint32_t));
-
- for (uint32_t i = 0; i < its_policy_count; i++) {
- uint32_t its_uid(0);
- uint32_t its_gid(0);
- std::shared_ptr<policy> its_policy(std::make_shared<policy>());
- // length field of next (UID/GID + policy)
- if (buffer_ptr + sizeof(uint32_t) <= _data + _size) {
- std::memcpy(&its_policy_size, buffer_ptr,
- sizeof(uint32_t));
- buffer_ptr += sizeof(uint32_t);
-
- if (buffer_ptr + its_policy_size <= _data + _size) {
- if (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!";
- }
- }
- }
- }
- }
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
- << " : routing_manager_proxy::on_message: "
- << " received a security policy distribution command from a client which isn't the routing manager"
- << " : Skip message!";
- }
- break;
- }
- case VSOMEIP_UPDATE_SECURITY_CREDENTIALS: {
- if (_size < VSOMEIP_COMMAND_HEADER_SIZE ||
- _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
- VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_CREDENTIALS command with wrong size -> skip!";
- break;
- }
- if (!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()
- << " : routing_manager_proxy::on_message: "
- << "received a security credential update from a client which isn't the routing manager"
- << " : Skip message!";
- }
- break;
- }
-
- case VSOMEIP_SUSPEND:
- on_suspend(); // cleanup remote subscribers
- break;
-
- default:
- break;
- }
- }
-}
-
-void routing_manager_proxy::on_routing_info(const byte_t *_data,
- uint32_t _size) {
-#if 0
- std::stringstream msg;
- msg << "rmp::on_routing_info(" << std::hex << client_ << "): ";
- for (uint32_t i = 0; i < _size; ++i)
- 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) {
- routing_info_entry_e routing_info_entry;
- std::memcpy(&routing_info_entry, &_data[i], sizeof(routing_info_entry_e));
- i += uint32_t(sizeof(routing_info_entry_e));
-
- uint32_t its_client_size;
- std::memcpy(&its_client_size, &_data[i], sizeof(uint32_t));
- i += uint32_t(sizeof(uint32_t));
-
- if (its_client_size + i > _size) {
- VSOMEIP_WARNING << "Client 0x" << std::hex << get_client() << " : "
- << "Processing of routing info failed due to bad length fields!";
- return;
- }
-
- if (i + sizeof(client_t) <= _size) {
- client_t its_client;
- std::memcpy(&its_client, &_data[i], sizeof(client_t));
- i += uint32_t(sizeof(client_t));
-
- if (routing_info_entry == routing_info_entry_e::RIE_ADD_CLIENT) {
- {
- std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
- known_clients_.insert(its_client);
- }
- if (its_client == get_client()) {
- VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
- << " (" << host_->get_name() << ") is registered.";
-
-#ifndef _WIN32
- 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!";
- deregister_application();
- host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
- return;
- }
-#endif
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERING) {
- boost::system::error_code ec;
- register_application_timer_.cancel(ec);
- send_registered_ack();
- send_pending_commands();
- state_ = inner_state_type_e::ST_REGISTERED;
- // Notify stop() call about clean deregistration
- state_condition_.notify_one();
- }
- }
-
- // inform host about its own registration state changes
- if (state_ == inner_state_type_e::ST_REGISTERED)
- host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_REGISTERED));
-
- }
- } else if (routing_info_entry == routing_info_entry_e::RIE_DEL_CLIENT) {
- {
- std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
- known_clients_.erase(its_client);
- }
- if (its_client == get_client()) {
- its_security->remove_client_to_uid_gid_mapping(its_client);
- VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
- << " (" << 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));
-
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- state_ = inner_state_type_e::ST_DEREGISTERED;
- // Notify stop() call about clean deregistration
- state_condition_.notify_one();
- }
- } else if (its_client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(its_client, true);
- }
- }
-
- uint32_t j = 0;
- while (j + sizeof(uint32_t) <= its_client_size) {
- uint32_t its_services_size;
- std::memcpy(&its_services_size, &_data[i + j], sizeof(uint32_t));
- j += uint32_t(sizeof(uint32_t));
-
- if (its_services_size >= sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t)) {
- its_services_size -= uint32_t(sizeof(service_t));
-
- service_t its_service;
- std::memcpy(&its_service, &_data[i + j], sizeof(service_t));
- j += uint32_t(sizeof(service_t));
-
- while (its_services_size >= sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t)) {
- instance_t its_instance;
- std::memcpy(&its_instance, &_data[i + j], sizeof(instance_t));
- j += uint32_t(sizeof(instance_t));
-
- major_version_t its_major;
- std::memcpy(&its_major, &_data[i + j], sizeof(major_version_t));
- j += uint32_t(sizeof(major_version_t));
-
- minor_version_t its_minor;
- std::memcpy(&its_minor, &_data[i + j], sizeof(minor_version_t));
- j += uint32_t(sizeof(minor_version_t));
-
- if (routing_info_entry == routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE) {
- if (get_routing_state() == routing_state_e::RS_SUSPENDED) {
- VSOMEIP_INFO << "rmp::" <<__func__ << " We are in suspended mode, the service will not be added!";
- return;
- }
- {
- std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
- known_clients_.insert(its_client);
- }
- {
- std::lock_guard<std::mutex> its_lock(local_services_mutex_);
- local_services_[its_service][its_instance] = std::make_tuple(its_major, its_minor, its_client);
- }
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- send_pending_subscriptions(its_service, its_instance, its_major);
- }
- host_->on_availability(its_service, its_instance, true, its_major, its_minor);
- VSOMEIP_INFO << "ON_AVAILABLE("
- << std::hex << std::setw(4) << std::setfill('0') << get_client() <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_instance
- << ":" << std::dec << int(its_major) << "." << std::dec << its_minor << "]";
- } else if (routing_info_entry == routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE) {
- {
- std::lock_guard<std::mutex> its_lock(local_services_mutex_);
- auto found_service = local_services_.find(its_service);
- if (found_service != local_services_.end()) {
- found_service->second.erase(its_instance);
- // move previously offering client to history
- local_services_history_[its_service][its_instance].insert(its_client);
- if (found_service->second.size() == 0) {
- local_services_.erase(its_service);
- }
- }
- }
- on_stop_offer_service(its_service, its_instance, its_major, its_minor);
- host_->on_availability(its_service, its_instance, false, its_major, its_minor);
- VSOMEIP_INFO << "ON_UNAVAILABLE("
- << std::hex << std::setw(4) << std::setfill('0') << get_client() <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_instance
- << ":" << std::dec << int(its_major) << "." << std::dec << its_minor << "]";
-
- if (its_client == get_client()) {
- VSOMEIP_INFO << __func__
- << ": Clearing subscriptions for service ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_instance << "]";
- unsubscribe_all(its_service, its_instance);
- }
- }
-
- its_services_size -= uint32_t(sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t) );
- }
- }
- }
-
- i += j;
- }
- }
- {
- struct subscription_info {
- service_t service_id_;
- instance_t instance_id_;
- eventgroup_t eventgroup_id_;
- 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;
- if (pending_incoming_subscripitons_.size()) {
- {
- std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
- for (const client_t client : known_clients_) {
- auto its_client = pending_incoming_subscripitons_.find(client);
- if (its_client != pending_incoming_subscripitons_.end()) {
- for (const auto& subscription : its_client->second) {
- subscription_actions.push_front(
- { subscription.service_, subscription.instance_,
- subscription.eventgroup_, client,
- 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);
-#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_, 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_, PENDING_SUBSCRIPTION_ID);
- } else {
- send_subscribe_ack(si.client_id_, si.service_id_,
- si.instance_id_, si.eventgroup_id_, si.event_, PENDING_SUBSCRIPTION_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_);
-#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_);
- }
- });
- }
- }
- }
-}
-
-void routing_manager_proxy::on_offered_services_info(const byte_t *_data,
- uint32_t _size) {
-#if 0
- std::stringstream msg;
- msg << "rmp::on_offered_services_info(" << std::hex << client_ << "): ";
- for (uint32_t i = 0; i < _size; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
-
- std::vector<std::pair<service_t, instance_t>> its_offered_services_info;
-
- uint32_t i = 0;
- while (i + sizeof(uint32_t) + sizeof(routing_info_entry_e) <= _size) {
- routing_info_entry_e routing_info_entry;
- std::memcpy(&routing_info_entry, &_data[i], sizeof(routing_info_entry_e));
- i += uint32_t(sizeof(routing_info_entry_e));
-
- uint32_t its_service_entry_size;
- std::memcpy(&its_service_entry_size, &_data[i], sizeof(uint32_t));
- i += uint32_t(sizeof(uint32_t));
-
- if (its_service_entry_size + i > _size) {
- VSOMEIP_WARNING << "Client 0x" << std::hex << get_client() << " : "
- << "Processing of offered services info failed due to bad length fields!";
- return;
- }
-
- if (its_service_entry_size >= sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t)) {
- service_t its_service;
- std::memcpy(&its_service, &_data[i], sizeof(service_t));
- i += uint32_t(sizeof(service_t));
-
- instance_t its_instance;
- std::memcpy(&its_instance, &_data[i], sizeof(instance_t));
- i += uint32_t(sizeof(instance_t));
-
- major_version_t its_major;
- std::memcpy(&its_major, &_data[i], sizeof(major_version_t));
- i += uint32_t(sizeof(major_version_t));
-
- minor_version_t its_minor;
- std::memcpy(&its_minor, &_data[i], sizeof(minor_version_t));
- i += uint32_t(sizeof(minor_version_t));
-
- its_offered_services_info.push_back(std::make_pair(its_service, its_instance));
- }
- }
- host_->on_offered_services_info(its_offered_services_info);
-}
-
-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));
-
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- state_ = inner_state_type_e::ST_DEREGISTERED;
- // Notify stop() call about clean deregistration
- state_condition_.notify_one();
- }
-
-
- // Remove all local connections/endpoints
- for (const auto& its_client : _clients) {
- if (its_client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(its_client, true);
- }
- }
-
- VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
- <<": Reconnecting to routing manager.";
-
-#ifndef _WIN32
- 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!";
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->stop();
- }
- return;
- }
-#endif
-
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->restart();
- }
-}
-
-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 };
-
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
- sizeof(client_));
-
- if (is_connected_) {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- state_ = inner_state_type_e::ST_REGISTERING;
- sender_->send(its_command, sizeof(its_command));
-
- register_application_timer_.cancel();
- register_application_timer_.expires_from_now(std::chrono::milliseconds(1000));
- register_application_timer_.async_wait(
- std::bind(
- &routing_manager_proxy::register_application_timeout_cbk,
- std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()),
- std::placeholders::_1));
- }
- }
-}
-
-void routing_manager_proxy::deregister_application() {
- std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE, 0);
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_DEREGISTER_APPLICATION;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
- sizeof(client_));
- if (is_connected_)
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(&its_command[0], uint32_t(its_command.size()));
- }
- }
-}
-
-void routing_manager_proxy::send_pong() const {
- byte_t its_pong[] = {
- VSOMEIP_PONG, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
-
- std::memcpy(&its_pong[VSOMEIP_COMMAND_CLIENT_POS], &client_,
- sizeof(client_t));
-
- if (is_connected_) {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_pong, sizeof(its_pong));
- }
- }
-}
-
-void routing_manager_proxy::send_request_services(std::set<service_data_t>& _requests) {
- if (!_requests.size()) {
- return;
- }
- size_t its_size = (VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE) * _requests.size();
- if (its_size > (std::numeric_limits<std::uint32_t>::max)()) {
- VSOMEIP_ERROR<< "routing_manager_proxy::send_request_services too many"
- << " requests (" << std::dec << its_size << "), returning.";
- return;
- }
-
- 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));
-
- uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t)
- + sizeof(major_version_t) + sizeof(minor_version_t));
-
- 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_));
- 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_));
- ++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));
- }
- }
-}
-
-void routing_manager_proxy::send_release_service(client_t _client, service_t _service,
- instance_t _instance) {
- (void)_client;
- byte_t its_command[VSOMEIP_RELEASE_SERVICE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_RELEASE_SERVICE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RELEASE_SERVICE;
- 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::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-void routing_manager_proxy::send_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,
- bool _is_provided) {
-
- std::size_t its_eventgroups_size = (_eventgroups.size() * sizeof(eventgroup_t)) +
- VSOMEIP_REGISTER_EVENT_COMMAND_SIZE;
- if (its_eventgroups_size > (std::numeric_limits<std::uint32_t>::max)()) {
- VSOMEIP_ERROR<< "routing_manager_proxy::send_register_event too many"
- << " eventgroups (" << std::dec << its_eventgroups_size << "), returning.";
- return;
- }
- byte_t *its_command = new byte_t[its_eventgroups_size];
- uint32_t its_size = static_cast<std::uint32_t>(its_eventgroups_size)
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REGISTER_EVENT;
- 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], &_notifier,
- sizeof(_notifier));
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
- = 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 = 9;
- for (auto eg : _eventgroups) {
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + i], &eg,
- sizeof(eventgroup_t));
- i += sizeof(eventgroup_t);
- }
-
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, static_cast<std::uint32_t>(its_eventgroups_size));
- }
- }
-
- 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 (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*/);
- }
-}
-
-void routing_manager_proxy::on_subscribe_nack(client_t _client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
- (void)_client;
- if (_event == ANY_EVENT) {
- auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
- if (its_eventgroup) {
- 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_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/);
- }
-}
-
-void routing_manager_proxy::cache_event_payload(
- const std::shared_ptr<message> &_message) {
- const service_t its_service(_message->get_service());
- const instance_t its_instance(_message->get_instance());
- const method_t its_method(_message->get_method());
- std::shared_ptr<event> its_event = find_event(its_service, its_instance, its_method);
- if (its_event) {
- if (its_event->is_field()) {
- its_event->set_payload_dont_notify(_message->get_payload());
- }
- } else {
- // we received a event which was not yet requested
- 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, 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);
- if (its_event) {
- its_event->set_payload_dont_notify(_message->get_payload());
- }
- }
-
-}
-
-void routing_manager_proxy::on_stop_offer_service(service_t _service,
- instance_t _instance,
- major_version_t _major,
- minor_version_t _minor) {
- (void) _major;
- (void) _minor;
- std::map<event_t, std::shared_ptr<event> > events;
- {
- std::lock_guard<std::mutex> its_lock(events_mutex_);
- auto its_events_service = events_.find(_service);
- if (its_events_service != events_.end()) {
- auto its_events_instance = its_events_service->second.find(_instance);
- if (its_events_instance != its_events_service->second.end()) {
- for (auto &e : its_events_instance->second)
- events[e.first] = e.second;
- }
- }
- }
- for (auto &e : events) {
- e.second->unset_payload();
- }
-}
-
-void routing_manager_proxy::send_pending_commands() {
- for (auto &po : pending_offers_)
- 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.notifier_,
- per.eventgroups_, per.type_, per.reliability_,
- per.is_provided_);
-
- send_request_services(requests_);
-}
-
-void routing_manager_proxy::init_receiver() {
-#ifndef _WIN32
- auto its_security = security_impl::get();
- if (!its_security)
- return;
-
- 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
- receiver_ = ep_mgr_->create_local_server(shared_from_this());
-}
-
-void routing_manager_proxy::notify_remote_initially(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, const std::set<event_t> &_events_to_exclude) {
- auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
- if (its_eventgroup) {
- auto service_info = find_service(_service, _instance);
- for (const auto &e : its_eventgroup->get_events()) {
- if (e->is_field() && e->is_set()
- && _events_to_exclude.find(e->get_event())
- == _events_to_exclude.end()) {
- std::shared_ptr<message> its_notification
- = runtime::get()->create_notification();
- its_notification->set_service(_service);
- its_notification->set_instance(_instance);
- its_notification->set_method(e->get_event());
- its_notification->set_payload(e->get_payload());
- if (service_info) {
- its_notification->set_interface_version(service_info->get_major());
- }
-
- 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, its_serializer->get_data(),
- its_serializer->get_size(), _instance, false, VSOMEIP_NOTIFY);
- }
- }
- its_serializer->reset();
- put_serializer(its_serializer);
- } else {
- VSOMEIP_ERROR << "Failed to serialize message. Check message size!";
- }
- }
- }
- }
-
-}
-
-uint32_t routing_manager_proxy::get_remote_subscriber_count(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, bool _increment) {
- std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
- uint32_t count (0);
- bool found(false);
- auto found_service = remote_subscriber_count_.find(_service);
- if (found_service != remote_subscriber_count_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_group = found_instance->second.find(_eventgroup);
- if (found_group != found_instance->second.end()) {
- found = true;
- if (_increment) {
- found_group->second = found_group->second + 1;
- } else {
- if (found_group->second > 0) {
- found_group->second = found_group->second - 1;
- }
- }
- count = found_group->second;
- }
- }
- }
- if (!found) {
- if (_increment) {
- remote_subscriber_count_[_service][_instance][_eventgroup] = 1;
- count = 1;
- }
- }
- return count;
-}
-
-void routing_manager_proxy::clear_remote_subscriber_count(
- service_t _service, instance_t _instance) {
- std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
- auto found_service = remote_subscriber_count_.find(_service);
- if (found_service != remote_subscriber_count_.end()) {
- if (found_service->second.erase(_instance)) {
- if (!found_service->second.size()) {
- remote_subscriber_count_.erase(found_service);
- }
- }
- }
-}
-
-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) {
-
- bool register_again(false);
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (!_error && 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()
- << " register timeout! Trying again...";
-
- if (sender_)
- sender_->restart();
- }
-}
-
-void routing_manager_proxy::send_registered_ack() {
- byte_t its_command[VSOMEIP_COMMAND_HEADER_SIZE] = {
- VSOMEIP_REGISTERED_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- client_t client = get_client();
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client,
- sizeof(client));
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, VSOMEIP_COMMAND_HEADER_SIZE);
- }
- }
-}
-
-bool routing_manager_proxy::is_client_known(client_t _client) {
- std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
- return (known_clients_.find(_client) != known_clients_.end());
-}
-
-bool routing_manager_proxy::create_placeholder_event_and_subscribe(
- service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, event_t _notifier, client_t _client) {
-
- std::lock_guard<std::mutex> its_lock(stop_mutex_);
-
- bool is_inserted(false);
-
- if (find_service(_service, _instance)) {
- // We received an event for an existing service which was not yet
- // requested/offered. Create a placeholder field until someone
- // requests/offers this event with full information like eventgroup,
- // field/event, 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, _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, _notifier);
- if (its_event) {
- is_inserted = its_event->add_subscriber(_eventgroup, _client, false);
- }
- }
-
- return is_inserted;
-}
-
-void routing_manager_proxy::request_debounce_timeout_cbk(
- boost::system::error_code const &_error) {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (!_error) {
- if (requests_to_debounce_.size()) {
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- send_request_services(requests_to_debounce_);
- requests_.insert(requests_to_debounce_.begin(),
- requests_to_debounce_.end());
- requests_to_debounce_.clear();
- } else {
- {
- 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_.async_wait(
- std::bind(
- &routing_manager_proxy::request_debounce_timeout_cbk,
- std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()),
- std::placeholders::_1));
- return;
- }
- }
- }
- }
- {
- std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
- request_debounce_timer_running_ = false;
- }
-}
-
-void routing_manager_proxy::register_client_error_handler(client_t _client,
- const std::shared_ptr<endpoint> &_endpoint) {
- _endpoint->register_error_handler(
- std::bind(&routing_manager_proxy::handle_client_error, this, _client));
-}
-
-void routing_manager_proxy::handle_client_error(client_t _client) {
- if (_client != VSOMEIP_ROUTING_CLIENT) {
- VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
- << " handles a client error(" << std::hex << _client << ")";
- remove_local(_client, true);
- } else {
- bool should_reconnect(true);
- {
- std::unique_lock<std::mutex> its_lock(state_mutex_);
- should_reconnect = is_started_;
- }
- if (should_reconnect) {
- std::unordered_set<client_t> its_known_clients;
- {
- std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
- its_known_clients = known_clients_;
- }
- reconnect(its_known_clients);
- }
- }
-}
-
-void routing_manager_proxy::send_get_offered_services_info(client_t _client, offer_type_e _offer_type) {
- (void)_client;
-
- byte_t its_command[VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_OFFERED_SERVICES_REQUEST;
- 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], &_offer_type,
- sizeof(_offer_type));
-
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
-}
-
-void routing_manager_proxy::send_unsubscribe_ack(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- 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;
-
- const client_t its_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNSUBSCRIBE_ACK;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
- sizeof(its_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
- sizeof(_service));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
- sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_id,
- sizeof(_id));
-
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-void routing_manager_proxy::resend_provided_event_registrations() {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- for (const event_data_t& ed : pending_event_registrations_) {
- if (ed.is_provided_) {
- send_register_event(client_, ed.service_, ed.instance_,
- ed.notifier_, ed.eventgroups_, ed.type_, ed.reliability_,
- ed.is_provided_);
- }
- }
-}
-
-void routing_manager_proxy::send_resend_provided_event_response(pending_remote_offer_id_t _id) {
- byte_t its_command[VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE];
- const std::uint32_t its_size = VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- const client_t its_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RESEND_PROVIDED_EVENTS;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
- sizeof(its_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_id,
- sizeof(pending_remote_offer_id_t));
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-void routing_manager_proxy::send_update_security_policy_response(pending_security_update_id_t _update_id) {
- byte_t its_command[VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE];
- const std::uint32_t its_size = VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- const client_t its_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
- sizeof(its_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
- sizeof(pending_security_update_id_t));
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-void routing_manager_proxy::send_remove_security_policy_response(pending_security_update_id_t _update_id) {
- byte_t its_command[VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE];
- const std::uint32_t its_size = VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- const client_t its_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
- sizeof(its_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
- sizeof(pending_security_update_id_t));
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
- }
-}
-
-void routing_manager_proxy::on_update_security_credentials(const byte_t *_data, uint32_t _size) {
- 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>());
-
- boost::icl::interval_set<uint32_t> its_gid_set;
- uint32_t its_uid, its_gid;
-
- std::memcpy(&its_uid, &_data[i], sizeof(uint32_t));
- i += uint32_t(sizeof(uint32_t));
- std::memcpy(&its_gid, &_data[i], sizeof(uint32_t));
- i += uint32_t(sizeof(uint32_t));
-
- its_gid_set.insert(its_gid);
-
- its_policy->credentials_ += std::make_pair(
- boost::icl::interval<uid_t>::closed(its_uid, its_uid), its_gid_set);
- its_policy->allow_who_ = true;
- its_policy->allow_what_ = true;
-
- 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_ << ")";
- }
-}
-
-void routing_manager_proxy::on_suspend() {
-
- VSOMEIP_INFO << __func__ << ": Application "
- << std::hex << std::setw(4) << std::setfill('0')
- << host_->get_client();
-
- std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
-
- // Unsubscribe everything that is left over.
- for (const auto &s : remote_subscriber_count_) {
- for (const auto &i : s.second) {
- for (const auto e : i.second)
- routing_manager_base::unsubscribe(
- VSOMEIP_ROUTING_CLIENT, ANY_UID, ANY_GID,
- s.first, i.first, e.first, ANY_EVENT);
- }
- }
-
- // Remove all entries.
- remote_subscriber_count_.clear();
-}
-
-} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 406b0d9..16ad36d 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -11,28 +11,56 @@
#include <boost/system/error_code.hpp>
#include <vsomeip/constants.hpp>
+#include <vsomeip/error.hpp>
+#include <vsomeip/payload.hpp>
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/runtime.hpp>
-#include <vsomeip/error.hpp>
+#include <vsomeip/structured_types.hpp>
#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 "../../security/include/security.hpp"
-
-#include "../../endpoints/include/local_server_endpoint_impl.hpp"
#include "../../endpoints/include/endpoint_manager_impl.hpp"
+#include "../../endpoints/include/netlink_connector.hpp"
+#include "../../protocol/include/deregister_application_command.hpp"
+#include "../../protocol/include/distribute_security_policies_command.hpp"
+#include "../../protocol/include/dummy_command.hpp"
+#include "../../protocol/include/expire_command.hpp"
+#include "../../protocol/include/offer_service_command.hpp"
+#include "../../protocol/include/offered_services_request_command.hpp"
+#include "../../protocol/include/offered_services_response_command.hpp"
+#include "../../protocol/include/ping_command.hpp"
+#include "../../protocol/include/pong_command.hpp"
+#include "../../protocol/include/register_application_command.hpp"
+#include "../../protocol/include/register_events_command.hpp"
+#include "../../protocol/include/registered_ack_command.hpp"
+#include "../../protocol/include/release_service_command.hpp"
+#include "../../protocol/include/remove_security_policy_command.hpp"
+#include "../../protocol/include/remove_security_policy_response_command.hpp"
+#include "../../protocol/include/request_service_command.hpp"
+#include "../../protocol/include/resend_provided_events_command.hpp"
+#include "../../protocol/include/routing_info_command.hpp"
+#include "../../protocol/include/send_command.hpp"
+#include "../../protocol/include/stop_offer_service_command.hpp"
+#include "../../protocol/include/subscribe_ack_command.hpp"
+#include "../../protocol/include/subscribe_command.hpp"
+#include "../../protocol/include/subscribe_nack_command.hpp"
+#include "../../protocol/include/suspend_command.hpp"
+#include "../../protocol/include/unregister_event_command.hpp"
+#include "../../protocol/include/unsubscribe_ack_command.hpp"
+#include "../../protocol/include/unsubscribe_command.hpp"
+#include "../../protocol/include/update_security_credentials_command.hpp"
+#include "../../protocol/include/update_security_policy_command.hpp"
+#include "../../protocol/include/update_security_policy_response_command.hpp"
+#include "../../security/include/policy_manager_impl.hpp"
+#include "../../security/include/security.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
-#include "../implementation/message/include/payload_impl.hpp"
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,
const std::shared_ptr<configuration>& _configuration) :
@@ -40,7 +68,7 @@ routing_manager_stub::routing_manager_stub(
io_(_host->get_io()),
watchdog_timer_(_host->get_io()),
client_id_timer_(_host->get_io()),
- endpoint_(nullptr),
+ root_(nullptr),
local_receiver_(nullptr),
configuration_(_configuration),
is_socket_activated_(false),
@@ -48,20 +76,31 @@ routing_manager_stub::routing_manager_stub(
max_local_message_size_(configuration_->get_max_message_size_local()),
configured_watchdog_timeout_(configuration_->get_watchdog_timeout()),
pinged_clients_timer_(io_),
- pending_security_update_id_(0) {
+ pending_security_update_id_(0)
+#if defined(__linux__) || defined(ANDROID)
+ , is_local_link_available_(false)
+#endif
+{
}
routing_manager_stub::~routing_manager_stub() {
}
void routing_manager_stub::init() {
+
init_routing_endpoint();
+
+ std::string its_env;
+ char its_hostname[1024];
+ if (gethostname(its_hostname, sizeof(its_hostname)) == 0)
+ its_env = its_hostname;
+ host_->set_client_host(its_env);
}
void routing_manager_stub::start() {
{
std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
- used_client_ids_ = utility::get_used_client_ids();
+ used_client_ids_ = utility::get_used_client_ids(configuration_->get_network());
// Wait VSOMEIP_MAX_CONNECT_TIMEOUT * 2 and expect after that time
// that all client_ids are used have to be connected to the routing.
// Otherwise they can be marked as "erroneous client".
@@ -73,12 +112,23 @@ void routing_manager_stub::start() {
std::placeholders::_1));
}
- if (!endpoint_) {
- // application has been stopped and started again
- init_routing_endpoint();
- }
- if (endpoint_) {
- endpoint_->start();
+#if defined(__linux__) || defined(ANDROID)
+ if (configuration_->is_local_routing()) {
+#else
+ {
+#endif // __linux__ || ANDROID
+ if (!root_) {
+ // application has been stopped and started again
+ init_routing_endpoint();
+ }
+ if (root_) {
+ root_->start();
+ }
+#if defined(__linux__) || defined(ANDROID)
+ } else {
+ if (local_link_connector_)
+ local_link_connector_->start();
+#endif
}
client_registration_running_ = true;
@@ -122,47 +172,60 @@ void routing_manager_stub::stop() {
client_id_timer_.cancel();
}
- 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(its_endpoint_path.str().c_str());
-#else
- if (-1 == ::unlink(its_endpoint_path.str().c_str())) {
- VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
- << its_endpoint_path.str() << "): "<< std::strerror(errno);
+ bool is_local_routing(configuration_->is_local_routing());
+
+#if defined(__linux__) || defined(ANDROID)
+ if (local_link_connector_)
+ local_link_connector_->stop();
+#endif // __linux__ || ANDROID
+
+ if (!is_socket_activated_) {
+ root_->stop();
+ root_ = nullptr;
+
+ if (is_local_routing) {
+ std::stringstream its_endpoint_path;
+ its_endpoint_path << utility::get_base_path(configuration_->get_network())
+ << std::hex << VSOMEIP_ROUTING_CLIENT;
+ #ifdef _WIN32
+ ::_unlink(its_endpoint_path.str().c_str());
+ #else
+ if (-1 == ::unlink(its_endpoint_path.str().c_str())) {
+ VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
+ << its_endpoint_path.str() << "): "<< std::strerror(errno);
+ }
+ #endif
}
-#endif
}
- if(local_receiver_) {
+ 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();
+
+ if (is_local_routing) {
+ std::stringstream its_local_receiver_path;
+ its_local_receiver_path << utility::get_base_path(configuration_->get_network())
+ << std::hex << host_->get_client();
#ifdef _WIN32
- ::_unlink(its_local_receiver_path.str().c_str());
+ ::_unlink(its_local_receiver_path.str().c_str());
#else
- if (-1 == ::unlink(its_local_receiver_path.str().c_str())) {
- VSOMEIP_ERROR << "routing_manager_stub::stop() unlink (local receiver) failed ("
- << its_local_receiver_path.str() << "): "<< std::strerror(errno);
- }
+ if (-1 == ::unlink(its_local_receiver_path.str().c_str())) {
+ VSOMEIP_ERROR << "routing_manager_stub::stop() unlink (local receiver) failed ("
+ << its_local_receiver_path.str() << "): "<< std::strerror(errno);
+ }
#endif
+ }
}
}
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,
+ endpoint *_receiver, bool _is_multicast,
+ client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) {
+
(void)_receiver;
- (void)_destination;
+ (void)_is_multicast;
(void)_remote_address;
(void) _remote_port;
#if 0
@@ -173,97 +236,118 @@ 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;
- std::string its_client_endpoint;
- service_t its_service;
- instance_t its_instance;
- method_t its_method;
- eventgroup_t its_eventgroup;
- event_t its_notifier;
- event_type_e its_event_type;
- bool is_provided(false);
- major_version_t its_major;
- minor_version_t its_minor;
- std::shared_ptr<payload> its_payload;
- const byte_t *its_data;
- uint32_t its_size;
- bool its_reliable(false);
- client_t its_client_from_header;
- client_t its_target_client;
- client_t its_subscriber;
- 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 (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')
- << its_client << " with command " << (uint32_t)its_command
- << " which doesn't match the bound client "
- << std::setw(4) << std::setfill('0') << _bound_client
- << " ~> skip message!";
- return;
- }
+ client_t its_client;
+ protocol::id_e its_id;
+ std::string its_client_endpoint;
+ service_t its_service;
+ instance_t its_instance;
+ method_t its_method;
+ eventgroup_t its_eventgroup;
+ event_t its_notifier;
+ major_version_t its_major;
+ minor_version_t its_minor;
+ std::shared_ptr<payload> its_payload;
+ bool is_reliable(false);
+ client_t its_subscriber;
+ uint8_t its_check_status(0);
+ std::uint16_t its_subscription_id(PENDING_SUBSCRIPTION_ID);
+ port_t its_port(ILLEGAL_PORT);
+
+ std::vector<byte_t> its_buffer(_data, _data + _size);
+ protocol::error_e its_error;
+
+ // Use dummy command to deserialize id and client.
+ protocol::dummy_command its_base_command;
+ its_base_command.deserialize(its_buffer, its_error);
+ if (its_error != protocol::error_e::ERROR_OK) {
- std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
- sizeof(its_size));
+ VSOMEIP_ERROR << __func__
+ << ": deserialization of command and client identifier failed ("
+ << std::dec << static_cast<int>(its_error)
+ << ")";
+ return;
+ }
- if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) {
- switch (its_command) {
- case VSOMEIP_REGISTER_APPLICATION:
- if (_size != VSOMEIP_REGISTER_APPLICATION_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a REGISTER_APPLICATION command with wrong size ~> skip!";
- break;
- }
- update_registration(its_client, registration_type_e::REGISTER);
- break;
+ its_client = its_base_command.get_client();
+ its_id = its_base_command.get_id();
- case VSOMEIP_DEREGISTER_APPLICATION:
- if (_size != VSOMEIP_DEREGISTER_APPLICATION_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a DEREGISTER_APPLICATION command with wrong size ~> skip!";
- break;
- }
- update_registration(its_client, registration_type_e::DEREGISTER);
- break;
+ if (configuration_->is_security_enabled()
+ && configuration_->is_local_routing()
+ && _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')
+ << its_client << " with command " << (uint32_t)its_id
+ << " which doesn't match the bound client "
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return;
+ }
- case VSOMEIP_PONG:
- if (_size != VSOMEIP_PONG_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a PONG command with wrong size ~> skip!";
- break;
- }
+ switch (its_id) {
+
+ case protocol::id_e::REGISTER_APPLICATION_ID:
+ {
+ protocol::register_application_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK)
+ update_registration(its_command.get_client(),
+ registration_type_e::REGISTER,
+ _remote_address, its_command.get_port());
+ else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing register application failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+
+ break;
+ }
+
+ case protocol::id_e::DEREGISTER_APPLICATION_ID:
+ {
+ protocol::deregister_application_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK)
+ update_registration(its_command.get_client(),
+ registration_type_e::DEREGISTER,
+ _remote_address, its_port);
+ else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing register application failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+
+ break;
+ }
+
+ case protocol::id_e::PONG_ID:
+ {
+ protocol::pong_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
on_pong(its_client);
VSOMEIP_TRACE << "PONG("
- << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
- break;
-
- case VSOMEIP_OFFER_SERVICE:
- if (_size != VSOMEIP_OFFER_SERVICE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a OFFER_SERVICE command with wrong size ~> skip!";
- break;
- }
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_client << ")";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing pong failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ 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_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
- sizeof(its_minor));
-
- if (security::get()->is_offer_allowed(its_sender_uid, its_sender_gid,
- its_client, its_service, its_instance)) {
+ case protocol::id_e::OFFER_SERVICE_ID:
+ {
+ protocol::offer_service_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ its_service = its_command.get_service();
+ its_instance = its_command.get_instance();
+ its_major = its_command.get_major();
+ its_minor = its_command.get_minor();
+
+ if (VSOMEIP_SEC_OK == security::is_client_allowed_to_offer(
+ _sec_client, its_service, its_instance)) {
host_->offer_service(its_client, its_service, its_instance,
its_major, its_minor);
} else {
@@ -272,48 +356,54 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< "the following service/instance " << its_service << "/" << its_instance
<< " ~> Skip offer!";
}
- break;
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing offer service failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
- case VSOMEIP_STOP_OFFER_SERVICE:
- if (_size != VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a STOP_OFFER_SERVICE 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_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
- sizeof(its_minor));
-
- host_->stop_offer_service(its_client, its_service, its_instance, its_major, its_minor);
- break;
-
- case VSOMEIP_SUBSCRIBE:
- if (_size != VSOMEIP_SUBSCRIBE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a SUBSCRIBE 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_eventgroup));
- std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(its_major));
- std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
- sizeof(its_notifier));
+ case protocol::id_e::STOP_OFFER_SERVICE_ID:
+ {
+ protocol::stop_offer_service_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ its_service = its_command.get_service();
+ its_instance = its_command.get_instance();
+ its_major = its_command.get_major();
+ its_minor = its_command.get_minor();
+
+ host_->stop_offer_service(its_client,
+ its_service, its_instance,
+ its_major, its_minor);
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing stop offer service failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::SUBSCRIBE_ID:
+ {
+ protocol::subscribe_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ its_service = its_command.get_service();
+ its_instance = its_command.get_instance();
+ its_eventgroup = its_command.get_eventgroup();
+ its_major = its_command.get_major();
+ its_notifier = its_command.get_event();
+ auto its_filter = its_command.get_filter();
if (its_notifier == ANY_EVENT) {
- if (host_->is_subscribe_to_any_event_allowed(_credentials, its_client, its_service,
+ if (host_->is_subscribe_to_any_event_allowed(_sec_client, 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);
+ host_->subscribe(its_client, _sec_client, its_service, its_instance,
+ its_eventgroup, its_major, its_notifier, its_filter);
} else {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
<< " : routing_manager_stub::on_message: "
@@ -322,10 +412,10 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< " which violates the security policy ~> Skip subscribe!";
}
} else {
- 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);
+ if (VSOMEIP_SEC_OK == security::is_client_allowed_to_access_member(
+ _sec_client, its_service, its_instance, its_notifier)) {
+ host_->subscribe(its_client, _sec_client, its_service, its_instance,
+ its_eventgroup, its_major, its_notifier, its_filter);
} else {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
<< " : routing_manager_stub::on_message: "
@@ -334,456 +424,397 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< " which violates the security policy ~> Skip subscribe!";
}
}
- break;
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing subscribe failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::UNSUBSCRIBE_ID:
+ {
+ protocol::unsubscribe_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ its_service = its_command.get_service();
+ its_instance = its_command.get_instance();
+ its_eventgroup = its_command.get_eventgroup();
+ its_notifier = its_command.get_event();
+
+ host_->unsubscribe(its_client, _sec_client,
+ its_service, its_instance, its_eventgroup, its_notifier);
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing unsubscribe failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::SUBSCRIBE_ACK_ID:
+ {
+ protocol::subscribe_ack_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ its_service = its_command.get_service();
+ its_instance = its_command.get_instance();
+ its_eventgroup = its_command.get_eventgroup();
+ its_subscriber = its_command.get_subscriber();
+ its_notifier = its_command.get_event();
+ its_subscription_id = its_command.get_pending_id();
- case VSOMEIP_UNSUBSCRIBE:
- if (_size != VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a UNSUBSCRIBE 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_eventgroup));
- std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(its_notifier));
-
- host_->unsubscribe(its_client, its_sender_uid, its_sender_gid, its_service,
- its_instance, its_eventgroup, its_notifier);
- break;
-
- case VSOMEIP_SUBSCRIBE_ACK:
- if (_size != VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a SUBSCRIBE_ACK 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_eventgroup));
- std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(its_subscriber));
- 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_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_notifier << "]";
- break;
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing subscribe ack failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+
+ break;
+ }
+
+ case protocol::id_e::SUBSCRIBE_NACK_ID:
+ {
+ protocol::subscribe_nack_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ its_service = its_command.get_service();
+ its_instance = its_command.get_instance();
+ its_eventgroup = its_command.get_eventgroup();
+ its_subscriber = its_command.get_subscriber();
+ its_notifier = its_command.get_event();
+ its_subscription_id = its_command.get_pending_id();
- case VSOMEIP_SUBSCRIBE_NACK:
- if (_size != VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a SUBSCRIBE_NACK 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_eventgroup));
- std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(its_subscriber));
- 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_notifier,
- its_subscription_id, false);
+ 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_notifier << "]";
- break;
- case VSOMEIP_UNSUBSCRIBE_ACK:
- if (_size != VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a VSOMEIP_UNSUBSCRIBE_ACK 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_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_eventgroup));
- std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(its_subscription_id));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing subscribe nack failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+
+ break;
+ }
+
+ case protocol::id_e::UNSUBSCRIBE_ACK_ID:
+ {
+ protocol::unsubscribe_ack_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ its_service = its_command.get_service();
+ its_instance = its_command.get_instance();
+ its_eventgroup = its_command.get_eventgroup();
+ its_subscription_id = its_command.get_pending_id();
+
host_->on_unsubscribe_ack(its_client, its_service,
its_instance, its_eventgroup, its_subscription_id);
+
VSOMEIP_INFO << "UNSUBSCRIBE 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 << "]";
- break;
- case VSOMEIP_SEND: {
- if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a SEND command with too small size ~> skip!";
- break;
- }
- its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
- its_service = VSOMEIP_BYTES_TO_WORD(
- its_data[VSOMEIP_SERVICE_POS_MIN],
- its_data[VSOMEIP_SERVICE_POS_MAX]);
- its_client_from_header = VSOMEIP_BYTES_TO_WORD(
- its_data[VSOMEIP_CLIENT_POS_MIN],
- its_data[VSOMEIP_CLIENT_POS_MAX]);
- its_method = VSOMEIP_BYTES_TO_WORD(
- its_data[VSOMEIP_METHOD_POS_MIN],
- its_data[VSOMEIP_METHOD_POS_MAX]);
- std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
- sizeof(its_instance));
- std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
- sizeof(its_reliable));
- 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 (!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 "
- << its_service << "/" << its_instance << "/" << its_method
- << " ~> Skip message!";
- return;
- }
- }
- // reduce by size of instance, flush, reliable, client and is_valid_crc flag
- const std::uint32_t its_message_size = its_size -
- (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
- if (its_message_size !=
- VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
- + VSOMEIP_SOMEIP_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a SEND command containing message with invalid size -> skip!";
- break;
- }
- host_->on_message(its_service, its_instance, its_data, its_message_size,
- its_reliable, _bound_client, _credentials, its_check_status, false);
- break;
- }
- case VSOMEIP_NOTIFY: {
- if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a NOTIFY command with too small size ~> skip!";
- break;
- }
- its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
- its_service = VSOMEIP_BYTES_TO_WORD(
- its_data[VSOMEIP_SERVICE_POS_MIN],
- its_data[VSOMEIP_SERVICE_POS_MAX]);
- std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
- sizeof(its_instance));
- // reduce by size of instance, flush, reliable, is_valid_crc flag and target client
- const std::uint32_t its_message_size = its_size -
- (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
- if (its_message_size !=
- VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
- + VSOMEIP_SOMEIP_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a NOTIFY command containing message with invalid size -> skip!";
- break;
- }
- host_->on_notification(VSOMEIP_ROUTING_CLIENT, its_service, its_instance, its_data, its_message_size);
- break;
- }
- case VSOMEIP_NOTIFY_ONE: {
- if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a NOTIFY_ONE command with too small size ~> skip!";
- break;
- }
- its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
- its_service = VSOMEIP_BYTES_TO_WORD(
- its_data[VSOMEIP_SERVICE_POS_MIN],
- its_data[VSOMEIP_SERVICE_POS_MAX]);
- std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
- sizeof(its_instance));
- std::memcpy(&its_target_client, &_data[VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN],
- sizeof(client_t));
- // reduce by size of instance, flush, reliable flag, is_valid_crc and target client
- const std::uint32_t its_message_size = its_size -
- (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
- if (its_message_size !=
- VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
- _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
- + VSOMEIP_SOMEIP_HEADER_SIZE) {
- VSOMEIP_WARNING << "Received a NOTIFY_ONE command containing message with invalid size -> skip!";
- break;
- }
- host_->on_notification(its_target_client, its_service, its_instance,
- its_data, its_message_size, true);
- break;
- }
- case VSOMEIP_REQUEST_SERVICE:
- {
- 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;
- }
- uint32_t request_count(its_size / entry_size);
- std::set<service_data_t> requests;
- for (uint32_t i = 0; i < request_count; ++i) {
- service_t its_service;
- instance_t its_instance;
- major_version_t its_major;
- minor_version_t its_minor;
- std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)],
- sizeof(its_service));
- std::memcpy(&its_instance,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)],
- sizeof(its_instance));
- std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4 + (i * entry_size)],
- sizeof(its_major));
- std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)],
- sizeof(its_minor));
- 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 );
- service_data_t request = {
- its_service, its_instance,
- its_major, its_minor
- };
- requests.insert(request);
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
- << its_client << " : routing_manager_stub::on_message: "
- << "requests service/instance "
- << its_service << "/" << its_instance
- << " which violates the security policy ~> Skip request!";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": deserializing unsubscribe ack failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::SEND_ID:
+ {
+ protocol::send_command its_command(its_id);
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ auto its_message_data(its_command.get_message());
+ if (its_message_data.size() > VSOMEIP_MESSAGE_TYPE_POS) {
+
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ its_message_data[VSOMEIP_SERVICE_POS_MIN],
+ its_message_data[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ its_message_data[VSOMEIP_METHOD_POS_MIN],
+ its_message_data[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(
+ its_message_data[VSOMEIP_CLIENT_POS_MIN],
+ its_message_data[VSOMEIP_CLIENT_POS_MAX]);
+
+ its_instance = its_command.get_instance();
+ is_reliable = its_command.is_reliable();
+ its_check_status = its_command.get_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_message_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ if (VSOMEIP_SEC_OK != security::is_client_allowed_to_access_member(
+ _sec_client, its_service, its_instance, its_method)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_stub::on_message: "
+ << " isn't allowed to send a request to service/instance/method "
+ << its_service << "/" << its_instance << "/" << its_method
+ << " ~> Skip message!";
+ return;
}
}
- if (security::get()->is_enabled()) {
- handle_credentials(its_client, requests);
+ // reduce by size of instance, flush, reliable, client and is_valid_crc flag
+ auto its_contained_size = VSOMEIP_BYTES_TO_LONG(
+ its_message_data[VSOMEIP_LENGTH_POS_MIN],
+ its_message_data[VSOMEIP_LENGTH_POS_MIN+1],
+ its_message_data[VSOMEIP_LENGTH_POS_MIN+2],
+ its_message_data[VSOMEIP_LENGTH_POS_MIN+3]);
+ if (its_message_data.size() != its_contained_size + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a SEND command containing message with invalid size -> skip!";
+ break;
}
- handle_requests(its_client, requests);
- break;
+ host_->on_message(its_service, its_instance,
+ &its_message_data[0], length_t(its_message_data.size()),
+ is_reliable, _bound_client, _sec_client, its_check_status, false);
}
+ }
+ break;
+ }
- case VSOMEIP_RELEASE_SERVICE:
- if (_size != VSOMEIP_RELEASE_SERVICE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a RELEASE_SERVICE command with wrong size ~> skip!";
+ case protocol::id_e::NOTIFY_ID:
+ case protocol::id_e::NOTIFY_ONE_ID:
+ {
+ protocol::send_command its_command(its_id);
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ auto its_message_data(its_command.get_message());
+ if (its_message_data.size() > VSOMEIP_MESSAGE_TYPE_POS) {
+
+ its_client = its_command.get_target();
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ its_message_data[VSOMEIP_SERVICE_POS_MIN],
+ its_message_data[VSOMEIP_SERVICE_POS_MAX]);
+ its_instance = its_command.get_instance();
+
+ auto its_contained_size = VSOMEIP_BYTES_TO_LONG(
+ its_message_data[VSOMEIP_LENGTH_POS_MIN],
+ its_message_data[VSOMEIP_LENGTH_POS_MIN+1],
+ its_message_data[VSOMEIP_LENGTH_POS_MIN+2],
+ its_message_data[VSOMEIP_LENGTH_POS_MIN+3]);
+ if (its_message_data.size() != its_contained_size + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a NOTIFY command containing message with invalid 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));
- host_->release_service(its_client, its_service, its_instance);
+ host_->on_notification(its_client, its_service, its_instance,
+ &its_message_data[0], length_t(its_message_data.size()),
+ its_id == protocol::id_e::NOTIFY_ONE_ID);
break;
+ }
+ }
+ break;
+ }
- case VSOMEIP_REGISTER_EVENT: {
- if (_size < VSOMEIP_REGISTER_EVENT_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a REGISTER_EVENT command with wrong size ~> skip!";
- break;
+ case protocol::id_e::REQUEST_SERVICE_ID:
+ {
+ protocol::request_service_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ its_client = its_command.get_client();
+ auto its_requests = its_command.get_services();
+
+ std::set<protocol::service> its_allowed_requests;
+ for (const auto &r : its_requests) {
+ if (VSOMEIP_SEC_OK == security::is_client_allowed_to_request(
+ _sec_client, r.service_, r.instance_)) {
+ host_->request_service(its_client,
+ r.service_, r.instance_, r.major_, r.minor_);
+ its_allowed_requests.insert(r);
}
+ }
+ if (configuration_->is_security_enabled()) {
+ handle_credentials(its_client, its_allowed_requests);
+ }
+ handle_requests(its_client, its_allowed_requests);
+ } else
+ VSOMEIP_ERROR << __func__ << ": request service deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
- 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_notifier,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_notifier));
- std::memcpy(&its_event_type,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- 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;
+ break;
+ }
+
+ case protocol::id_e::RELEASE_SERVICE_ID:
+ {
+ protocol::release_service_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ host_->release_service(its_command.get_client(),
+ its_command.get_service(), its_command.get_instance());
+ } else
+ VSOMEIP_ERROR << __func__ << ": release service deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::REGISTER_EVENT_ID:
+ {
+ protocol::register_events_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ its_client = its_command.get_client();
+ for(std::size_t i = 0; i < its_command.get_num_registrations(); i++) {
+ protocol::register_event register_event;
+ if (!its_command.get_registration_at(i, register_event)) {
+ continue;
}
- 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);
+
+ its_service = register_event.get_service();
+ its_instance = register_event.get_instance();
+
+ if (register_event.is_provided()
+ && !configuration_->is_offered_remote(its_service, its_instance)) {
+ continue;
}
+
host_->register_shadow_event(its_client,
its_service, its_instance,
- its_notifier, its_eventgroups, its_event_type,
- its_reliability,
- is_provided);
+ register_event.get_event(), register_event.get_eventgroups(),
+ register_event.get_event_type(), register_event.get_reliability(),
+ register_event.is_provided(), register_event.is_cyclic());
+
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_notifier
- << ":is_provider=" << is_provided << ":reliability="
- << (std::uint32_t)(its_reliability) << "]";
- break;
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance
+ << ":eventtype=" << std::dec << (int)register_event.get_event_type()
+ << ":is_provided=" << std::boolalpha << register_event.is_provided()
+ << ":reliable=" << std::dec << (int)register_event.get_reliability() << "]";
}
- case VSOMEIP_UNREGISTER_EVENT:
- if (_size != VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a UNREGISTER_EVENT 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_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_notifier));
- std::memcpy(&is_provided,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(is_provided));
- if (is_provided
- && !configuration_->is_offered_remote(its_service,
- its_instance)) {
- break;
- }
- host_->unregister_shadow_event(its_client, its_service, its_instance,
- 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_notifier
- << ":is_provider=" << is_provided << "]";
- break;
- case VSOMEIP_REGISTERED_ACK:
- if (_size != VSOMEIP_REGISTERED_ACK_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a REGISTERED_ACK command with wrong size ~> skip!";
- break;
- }
- VSOMEIP_INFO << "REGISTERED_ACK("
- << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
- break;
- case VSOMEIP_OFFERED_SERVICES_REQUEST: {
- if (_size != VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a VSOMEIP_OFFERED_SERVICES_REQUEST command with wrong size ~> skip!";
- break;
- }
- std::memcpy(&its_offer_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(its_offer_type));
+ } else
+ VSOMEIP_ERROR << __func__ << ": register event deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
- std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- create_offered_services_info(its_client);
-
- 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) {
- for (const auto &its_instance : its_service.second) {
- uint16_t its_reliable_port = configuration_->get_reliable_port(its_service.first,
- its_instance.first);
- uint16_t its_unreliable_port = configuration_->get_unreliable_port(
- its_service.first, its_instance.first);
-
- if (its_offer_type == offer_type_e::OT_LOCAL) {
- if (its_reliable_port == ILLEGAL_PORT
- && its_unreliable_port == ILLEGAL_PORT) {
- insert_offered_services_info(its_client,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- its_service.first, its_instance.first,
- its_instance.second.first, its_instance.second.second);
- }
- }
- else if (its_offer_type == offer_type_e::OT_REMOTE) {
- if (its_reliable_port != ILLEGAL_PORT
- || its_unreliable_port != ILLEGAL_PORT) {
- insert_offered_services_info(its_client,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- its_service.first, its_instance.first,
- its_instance.second.first, its_instance.second.second);
- }
- } else if (its_offer_type == offer_type_e::OT_ALL) {
- insert_offered_services_info(its_client,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- its_service.first, its_instance.first,
- its_instance.second.first, its_instance.second.second);
- }
- }
- }
- }
- }
- send_offered_services_info(its_client);
- break;
- }
- case VSOMEIP_RESEND_PROVIDED_EVENTS: {
- if (_size != VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a RESEND_PROVIDED_EVENTS command with wrong size ~> skip!";
- break;
- }
- pending_remote_offer_id_t its_pending_remote_offer_id(0);
- std::memcpy(&its_pending_remote_offer_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(pending_remote_offer_id_t));
- host_->on_resend_provided_events_response(its_pending_remote_offer_id);
- VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
- << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
- break;
- }
- case VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE: {
- if (_size != VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE "
- << "command with wrong size ~> skip!";
- break;
- }
- pending_security_update_id_t its_pending_security_update_id(0);
- std::memcpy(&its_pending_security_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(pending_security_update_id_t));
+ case protocol::id_e::UNREGISTER_EVENT_ID:
+ {
+ protocol::unregister_event_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ host_->unregister_shadow_event(its_command.get_client(),
+ its_command.get_service(), its_command.get_instance(),
+ its_command.get_event(), its_command.is_provided());
+
+ VSOMEIP_INFO << "UNREGISTER EVENT("
+ << std::hex << std::setw(4) << std::setfill('0') << its_command.get_client() << "): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_command.get_service() << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_command.get_instance() << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_command.get_event()
+ << ":is_provider=" << std::boolalpha << its_command.is_provided() << "]";
+ } else
+ VSOMEIP_ERROR << __func__ << ": unregister event deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
- on_security_update_response(its_pending_security_update_id ,its_client);
- break;
- }
- case VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE: {
- if (_size != VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE "
- << "command with wrong size ~> skip!";
- break;
- }
- pending_security_update_id_t its_pending_security_update_id(0);
- std::memcpy(&its_pending_security_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(pending_security_update_id_t));
+ case protocol::id_e::REGISTERED_ACK_ID:
+ {
+ protocol::registered_ack_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ VSOMEIP_INFO << "REGISTERED_ACK("
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_command.get_client() << ")";
+ } else
+ VSOMEIP_ERROR << __func__ << ": registered ack deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
- on_security_update_response(its_pending_security_update_id ,its_client);
- break;
- }
- }
+ case protocol::id_e::OFFERED_SERVICES_REQUEST_ID:
+ {
+ protocol::offered_services_request_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+
+ on_offered_service_request(its_command.get_client(), its_command.get_offer_type());
+ } else
+ VSOMEIP_ERROR << __func__ << ": offer service request deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::RESEND_PROVIDED_EVENTS_ID:
+ {
+ protocol::resend_provided_events_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ host_->on_resend_provided_events_response(its_command.get_remote_offer_id());
+ VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
+ } else
+ VSOMEIP_ERROR << __func__ << ": resend provided events deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+#ifndef VSOMEIP_DISABLE_SECURITY
+ case protocol::id_e::UPDATE_SECURITY_POLICY_RESPONSE_ID:
+ {
+ protocol::update_security_policy_response_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ on_security_update_response(its_command.get_update_id(), its_client);
+ } else
+ VSOMEIP_ERROR << __func__ << ": update security policy deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
+ }
+
+ case protocol::id_e::REMOVE_SECURITY_POLICY_RESPONSE_ID:
+ {
+ protocol::remove_security_policy_response_command its_command;
+ its_command.deserialize(its_buffer, its_error);
+ if (its_error == protocol::error_e::ERROR_OK) {
+ on_security_update_response(its_command.get_update_id(), its_client);
+ } else
+ VSOMEIP_ERROR << __func__ << ": update security policy deserialization failed ("
+ << std::dec << static_cast<int>(its_error) << ")";
+ break;
}
+#endif // !VSOMEIP_DISABLE_SECURITY
+ default:
+ VSOMEIP_WARNING << __func__ << ": Received an unhandled command ("
+ << std::dec << static_cast<int>(its_id) << ")";
}
}
+void routing_manager_stub::add_known_client(client_t _client, const std::string &_client_host) {
+ host_->add_known_client(_client, _client_host);
+}
+
void routing_manager_stub::on_register_application(client_t _client) {
+
auto endpoint = host_->find_local(_client);
if (endpoint) {
VSOMEIP_WARNING << "Reregistering application: " << std::hex << _client
@@ -794,15 +825,21 @@ void routing_manager_stub::on_register_application(client_t _client) {
std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
routing_info_[_client].first = 0;
}
+#ifndef VSOMEIP_DISABLE_SECURITY
+ if (configuration_->is_local_routing()) {
+ vsomeip_sec_client_t its_sec_client;
+ std::set<std::shared_ptr<policy> > its_policies;
+
+ policy_manager_impl::get()->get_client_to_sec_client_mapping(_client, its_sec_client);
+ if (its_sec_client.client_type == VSOMEIP_CLIENT_UDS) {
+ get_requester_policies(its_sec_client.client.uds_client.user,
+ its_sec_client.client.uds_client.group, its_policies);
+ }
- std::pair<uid_t, gid_t> its_uid_gid;
- std::set<std::shared_ptr<policy> > its_policies;
-
- security::get()->get_client_to_uid_gid_mapping(_client, its_uid_gid);
- get_requester_policies(its_uid_gid.first, its_uid_gid.second, its_policies);
-
- if (!its_policies.empty())
- send_requester_policies({ _client }, its_policies);
+ if (!its_policies.empty())
+ send_requester_policies({ _client }, its_policies);
+ }
+#endif // !VSOMEIP_DISABLE_SECURITY
}
}
@@ -827,15 +864,59 @@ void routing_manager_stub::on_deregister_application(client_t _client) {
routing_info_.erase(_client);
}
for (const auto &s : services_to_report) {
- host_->on_availability(std::get<0>(s), std::get<1>(s), false,
+ host_->on_availability(std::get<0>(s), std::get<1>(s),
+ availability_state_e::AS_UNAVAILABLE,
std::get<2>(s), std::get<3>(s));
host_->on_stop_offer_service(_client, std::get<0>(s), std::get<1>(s),
std::get<2>(s), std::get<3>(s));
}
}
+void
+routing_manager_stub::on_offered_service_request(client_t _client,
+ offer_type_e _offer_type) {
+
+ protocol::offered_services_response_command its_command;
+ its_command.set_client(_client);
+
+ 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 &s : found_client.second.second) {
+ for (const auto &i : s.second) {
+ uint16_t its_reliable_port
+ = configuration_->get_reliable_port(s.first, i.first);
+ uint16_t its_unreliable_port
+ = configuration_->get_unreliable_port(s.first, i.first);
+ bool has_port = (its_reliable_port != ILLEGAL_PORT
+ || its_unreliable_port != ILLEGAL_PORT);
+
+ if (_offer_type == offer_type_e::OT_ALL
+ || (_offer_type == offer_type_e::OT_LOCAL && !has_port)
+ || (_offer_type == offer_type_e::OT_REMOTE && has_port)) {
+
+ protocol::service its_service(s.first, i.first,
+ i.second.first, i.second.second);
+ its_command.add_service(its_service);
+ }
+ }
+ }
+ }
+ }
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint)
+ its_endpoint->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ }
+}
+
void routing_manager_stub::client_registration_func(void) {
-#ifndef _WIN32
+#if defined(__linux__) || defined(ANDROID)
{
std::stringstream s;
s << std::hex << std::setw(4) << std::setfill('0')
@@ -845,9 +926,9 @@ void routing_manager_stub::client_registration_func(void) {
#endif
std::unique_lock<std::mutex> its_lock(client_registration_mutex_);
while (client_registration_running_) {
- while (!pending_client_registrations_.size() && client_registration_running_) {
- client_registration_condition_.wait(its_lock);
- }
+ client_registration_condition_.wait(its_lock, [this] {
+ return pending_client_registrations_.size() || !client_registration_running_;
+ });
std::map<client_t, std::vector<registration_type_e>> its_registrations(
pending_client_registrations_);
@@ -867,44 +948,53 @@ void routing_manager_stub::client_registration_func(void) {
// endpoint error to avoid writing in an already closed socket
if (b != registration_type_e::DEREGISTER_ON_ERROR) {
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- create_client_routing_info(r.first);
- insert_client_routing_info(r.first,
- b == registration_type_e::REGISTER ?
- routing_info_entry_e::RIE_ADD_CLIENT :
- routing_info_entry_e::RIE_DEL_CLIENT,
- r.first);
- // distribute updated security config to new clients
+ add_connection(r.first, r.first);
+ protocol::routing_info_entry its_entry;
+ its_entry.set_client(r.first);
if (b == registration_type_e::REGISTER) {
+ boost::asio::ip::address its_address;
+ port_t its_port;
+
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_ADD_CLIENT);
+ if (host_->get_guest(r.first, its_address, its_port)) {
+ its_entry.set_address(its_address);
+ its_entry.set_port(its_port);
+ }
+#ifndef VSOMEIP_DISABLE_SECURITY
+ // distribute updated security config to new clients
send_cached_security_policies(r.first);
+#endif // !VSOMEIP_DISABLE_SECURITY
+ } else {
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_DELETE_CLIENT);
}
- send_client_routing_info(r.first);
+ send_client_routing_info(r.first, its_entry);
}
if (b != registration_type_e::REGISTER) {
{
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- auto its_connection = connection_matrix_.find(r.first);
- if (its_connection != connection_matrix_.end()) {
- for (auto its_client : its_connection->second) {
+ auto find_connections = connection_matrix_.find(r.first);
+ if (find_connections != connection_matrix_.end()) {
+ for (auto its_client : find_connections->second) {
if (its_client != r.first &&
its_client != VSOMEIP_ROUTING_CLIENT &&
its_client != get_client()) {
- create_client_routing_info(its_client);
- insert_client_routing_info(its_client,
- routing_info_entry_e::RIE_DEL_CLIENT, r.first);
- send_client_routing_info(its_client);
+ protocol::routing_info_entry its_entry;
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_DELETE_CLIENT);
+ its_entry.set_client(r.first);
+ send_client_routing_info(its_client, its_entry);
}
}
- connection_matrix_.erase(r.first);
+ remove_source(r.first);
}
- for (const auto& its_client : connection_matrix_) {
- connection_matrix_[its_client.first].erase(r.first);
+ for (const auto &its_connections : connection_matrix_) {
+ remove_connection(its_connections.first, r.first);
}
service_requests_.erase(r.first);
}
// Don't remove client ID to UID maping as same client
// could have passed its credentials again
host_->remove_local(r.first, false);
- utility::release_client_id(r.first);
+ utility::release_client_id(configuration_->get_network(), r.first);
}
}
}
@@ -913,9 +1003,75 @@ void routing_manager_stub::client_registration_func(void) {
}
void routing_manager_stub::init_routing_endpoint() {
- endpoint_ = host_->get_endpoint_manager()->create_local_server(
- &is_socket_activated_, shared_from_this());
+
+#if defined(__linux__) || defined(ANDROID)
+ if (configuration_->is_local_routing()) {
+#else
+ {
+#endif // __linux__ || ANDROID
+ bool is_successful = host_->get_endpoint_manager()->create_routing_root(
+ root_, is_socket_activated_, shared_from_this());
+
+ if (!is_successful) {
+ VSOMEIP_WARNING << "Routing root creating (partially) failed. Please check your configuration.";
+ }
+#if defined(__linux__) || defined(ANDROID)
+ } else {
+ auto its_host_address = configuration_->get_routing_host_address();
+ local_link_connector_ = std::make_shared<netlink_connector>(
+ io_, its_host_address, boost::asio::ip::address(), false); // routing host doesn't need link up
+ if (local_link_connector_) {
+ local_link_connector_->register_net_if_changes_handler(
+ std::bind(&routing_manager_stub::on_net_state_change,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ }
+#endif // __linux__ || ANDROID
+ }
+}
+
+#if defined(__linux__) || defined(ANDROID)
+void
+routing_manager_stub::on_net_state_change(
+ bool _is_interface, const std::string &_name, bool _is_available) {
+
+ VSOMEIP_INFO << __func__
+ << "("<< std::hex << std::this_thread::get_id() << "): "
+ << std::boolalpha << _is_interface << " "
+ << _name << " "
+ << std::boolalpha << _is_available;
+
+ if (_is_interface) {
+ if (_is_available) {
+ if (!is_local_link_available_) {
+ is_local_link_available_ = true;
+ if (!root_)
+ (void)host_->get_endpoint_manager()->create_routing_root(
+ root_, is_socket_activated_, shared_from_this());
+ if (root_) {
+ VSOMEIP_INFO << __func__
+ << ": Starting routing root.";
+ root_->start();
+ } else
+ VSOMEIP_WARNING << "Routing root creating (partially) failed. "
+ "Please check your configuration.";
+ }
+ } else {
+ if (is_local_link_available_) {
+
+ VSOMEIP_INFO << __func__
+ << ": Stopping routing root.";
+ root_->stop();
+
+ routing_info_.clear();
+ host_->clear_local_services();
+
+ is_local_link_available_ = false;
+ }
+ }
+ }
}
+#endif // __linux__ || ANDROID
void routing_manager_stub::on_offer_service(client_t _client,
service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) {
@@ -925,11 +1081,11 @@ void routing_manager_stub::on_offer_service(client_t _client,
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()) {
+ 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);
+ protocol::routing_info_entry_type_e::RIE_ADD_SERVICE_INSTANCE, true);
}
void routing_manager_stub::on_stop_offer_service(client_t _client,
@@ -947,102 +1103,29 @@ void routing_manager_stub::on_stop_offer_service(client_t _client,
if (0 == found_service->second.size()) {
found_client->second.second.erase(_service);
}
- inform_provider(_client, _service, _instance, _major, _minor,
- routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE);
inform_requesters(_client, _service, _instance, _major, _minor,
- routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE, false);
+ protocol::routing_info_entry_type_e::RIE_DELETE_SERVICE_INSTANCE, false);
} else if( _major == DEFAULT_MAJOR && _minor == DEFAULT_MINOR) {
found_service->second.erase(_instance);
if (0 == found_service->second.size()) {
found_client->second.second.erase(_service);
}
- inform_provider(_client, _service, _instance, _major, _minor,
- routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE);
inform_requesters(_client, _service, _instance, _major, _minor,
- routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE, false);
+ protocol::routing_info_entry_type_e::RIE_DELETE_SERVICE_INSTANCE, false);
}
}
}
}
}
-void routing_manager_stub::create_client_routing_info(const client_t _target) {
- std::vector<byte_t> its_command;
- its_command.push_back(VSOMEIP_ROUTING_INFO);
-
- // Sender client
- client_t client = get_client();
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&client)[i]);
- }
-
- // Overall size placeholder
- byte_t size_placeholder = 0x0;
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(size_placeholder);
- }
-
- client_routing_info_[_target] = its_command;
-}
-
-void routing_manager_stub::create_client_credentials_info(const client_t _target) {
- std::vector<byte_t> its_command;
- its_command.push_back(VSOMEIP_UPDATE_SECURITY_CREDENTIALS);
-
- // Sender client
- client_t client = get_client();
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&client)[i]);
- }
-
- // Overall size placeholder
- byte_t size_placeholder = 0x0;
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(size_placeholder);
- }
-
- client_credentials_info_[_target] = its_command;
-}
-
-void routing_manager_stub::insert_client_credentials_info(client_t _target, std::set<std::pair<uint32_t, uint32_t>> _credentials) {
- if (client_credentials_info_.find(_target) == client_credentials_info_.end()) {
- return;
- }
-
- auto its_command = client_credentials_info_[_target];
-
- // insert uid / gid credential pairs
- for (auto its_credentials : _credentials) {
- //uid
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&std::get<0>(its_credentials))[i]);
- }
- //gid
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&std::get<1>(its_credentials))[i]);
- }
- }
-
- client_credentials_info_[_target] = its_command;
-}
-
-void routing_manager_stub::send_client_credentials_info(const client_t _target) {
- if (client_credentials_info_.find(_target) == client_credentials_info_.end()) {
- return;
- }
+void routing_manager_stub::send_client_credentials(const client_t _target,
+ std::set<std::pair<uint32_t, uint32_t>> &_credentials) {
std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
if (its_endpoint) {
- auto its_command = client_credentials_info_[_target];
-
- // File overall size
- std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
- its_size += VSOMEIP_COMMAND_PAYLOAD_POS;
+ protocol::update_security_credentials_command its_command;
+ its_command.set_client(_target);
+ its_command.set_credentials(_credentials);
#if 0
std::stringstream msg;
@@ -1052,235 +1135,66 @@ void routing_manager_stub::send_client_credentials_info(const client_t _target)
VSOMEIP_INFO << msg.str();
#endif
- // Send routing info or error!
- if(its_command.size() <= max_local_message_size_
- || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
- its_endpoint->send(&its_command[0], uint32_t(its_size));
- } else {
- VSOMEIP_ERROR << "Credentials info exceeds maximum message size: Can't send!";
- }
-
- client_credentials_info_.erase(_target);
- } else {
- VSOMEIP_ERROR << "Send credentials info to client 0x" << std::hex << _target
- << " failed: No valid endpoint!";
- }
-}
-
-void routing_manager_stub::create_offered_services_info(const client_t _target) {
- std::vector<byte_t> its_command;
- its_command.push_back(VSOMEIP_OFFERED_SERVICES_RESPONSE);
-
- // Sender client
- client_t client = get_client();
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&client)[i]);
- }
-
- // Overall size placeholder
- byte_t size_placeholder = 0x0;
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(size_placeholder);
- }
-
- offered_services_info_[_target] = its_command;
-}
-
-
-void routing_manager_stub::send_client_routing_info(const client_t _target) {
- if (client_routing_info_.find(_target) == client_routing_info_.end()) {
- return;
- }
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
- if (its_endpoint) {
- auto its_command = client_routing_info_[_target];
-
- // File overall size
- std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
- its_size += VSOMEIP_COMMAND_PAYLOAD_POS;
-
-#if 0
- std::stringstream msg;
- msg << "rms::send_routing_info to (" << std::hex << _target << "): ";
- for (uint32_t i = 0; i < its_size; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
-
- // Send routing info or error!
- if(its_command.size() <= max_local_message_size_
- || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
- its_endpoint->send(&its_command[0], uint32_t(its_size));
- } else {
- VSOMEIP_ERROR << "Routing info exceeds maximum message size: Can't send!";
- }
-
- client_routing_info_.erase(_target);
- } else {
- VSOMEIP_ERROR << "Send routing info to client 0x" << std::hex << _target
- << " failed: No valid endpoint!";
- }
-}
-
-
-void routing_manager_stub::send_offered_services_info(const client_t _target) {
- if (offered_services_info_.find(_target) == offered_services_info_.end()) {
- return;
- }
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
- if (its_endpoint) {
- auto its_command = offered_services_info_[_target];
-
- // File overall size
- std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
- its_size += VSOMEIP_COMMAND_PAYLOAD_POS;
-
-#if 0
- std::stringstream msg;
- msg << "rms::send_offered_services_info to (" << std::hex << _target << "): ";
- for (uint32_t i = 0; i < its_size; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
-
- // Send routing info or error!
- if(its_command.size() <= max_local_message_size_
- || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
- its_endpoint->send(&its_command[0], uint32_t(its_size));
- } else {
- VSOMEIP_ERROR << "Offered services info exceeds maximum message size: Can't send!";
- }
-
- offered_services_info_.erase(_target);
- } else {
- VSOMEIP_ERROR << "Send offered services info to client 0x" << std::hex << _target
- << " failed: No valid endpoint!";
- }
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ if(its_buffer.size() <= max_local_message_size_
+ || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
+ its_endpoint->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": Credentials info exceeds maximum message size: Can't send!";
+
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": update security credentials command serialization failed ("
+ << static_cast<int>(its_error)
+ << ")";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": Sending credentials to client ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _target
+ << "] failed";
}
-void routing_manager_stub::insert_client_routing_info(client_t _target,
- routing_info_entry_e _entry,
- client_t _client, service_t _service,
- instance_t _instance,
- major_version_t _major,
- minor_version_t _minor) {
-
- if (client_routing_info_.find(_target) == client_routing_info_.end()) {
- return;
- }
-
- connection_matrix_[_target].insert(_client);
-
- auto its_command = client_routing_info_[_target];
-
- // Routing Info State Change
- for (uint32_t i = 0; i < sizeof(routing_info_entry_e); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_entry)[i]);
- }
-
- std::size_t its_size_pos = its_command.size();
- std::size_t its_entry_size = its_command.size();
-
- // Client size placeholder
- byte_t placeholder = 0x0;
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(placeholder);
- }
- // Client
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_client)[i]);
- }
-
- if (_entry == routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE ||
- _entry == routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE) {
- //Service
- uint32_t its_service_entry_size = uint32_t(sizeof(service_t)
- + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t));
- for (uint32_t i = 0; i < sizeof(its_service_entry_size); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&its_service_entry_size)[i]);
- }
- for (uint32_t i = 0; i < sizeof(service_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_service)[i]);
- }
- // Instance
- for (uint32_t i = 0; i < sizeof(instance_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_instance)[i]);
- }
- // Major version
- for (uint32_t i = 0; i < sizeof(major_version_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_major)[i]);
- }
- // Minor version
- for (uint32_t i = 0; i < sizeof(minor_version_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_minor)[i]);
- }
- }
-
- // File client size
- its_entry_size = its_command.size() - its_entry_size - uint32_t(sizeof(uint32_t));
- std::memcpy(&its_command[its_size_pos], &its_entry_size, sizeof(uint32_t));
+void routing_manager_stub::send_client_routing_info(const client_t _target,
+ protocol::routing_info_entry &_entry) {
- client_routing_info_[_target] = its_command;
+ std::vector<protocol::routing_info_entry> its_entries;
+ its_entries.emplace_back(_entry);
+ send_client_routing_info(_target, std::move(its_entries));
}
-void routing_manager_stub::insert_offered_services_info(client_t _target,
- routing_info_entry_e _entry,
- service_t _service,
- instance_t _instance,
- major_version_t _major,
- minor_version_t _minor) {
+void routing_manager_stub::send_client_routing_info(const client_t _target,
+ std::vector<protocol::routing_info_entry> &&_entries) {
- if (offered_services_info_.find(_target) == offered_services_info_.end()) {
- return;
- }
+ auto its_target_endpoint = host_->find_local(_target);
+ if (its_target_endpoint) {
- auto its_command = offered_services_info_[_target];
+ protocol::routing_info_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_entries(std::move(_entries));
- // Routing Info State Change
- for (uint32_t i = 0; i < sizeof(routing_info_entry_e); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_entry)[i]);
- }
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
- // entry size
- uint32_t its_service_entry_size = uint32_t(sizeof(service_t)
- + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t));
- for (uint32_t i = 0; i < sizeof(its_service_entry_size); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&its_service_entry_size)[i]);
- }
- //Service
- for (uint32_t i = 0; i < sizeof(service_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_service)[i]);
- }
- // Instance
- for (uint32_t i = 0; i < sizeof(instance_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_instance)[i]);
- }
- // Major version
- for (uint32_t i = 0; i < sizeof(major_version_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_major)[i]);
- }
- // Minor version
- for (uint32_t i = 0; i < sizeof(minor_version_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_minor)[i]);
- }
-
- offered_services_info_[_target] = its_command;
+ if (its_error == protocol::error_e::ERROR_OK) {
+ its_target_endpoint->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": routing info command serialization failed ("
+ << static_cast<int>(its_error)
+ << ")";
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": Sending routing info to client ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _target
+ << "] failed";
}
void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _service, instance_t _instance) {
@@ -1298,38 +1212,30 @@ 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 (security::get()->get_client_to_uid_gid_mapping(_hoster, its_uid_gid)) {
+ vsomeip_sec_client_t its_sec_client;
+ if (policy_manager_impl::get()->get_client_to_sec_client_mapping(_hoster, its_sec_client)) {
+ std::pair<uint32_t, uint32_t> its_uid_gid;
+ its_uid_gid.first = its_sec_client.client.uds_client.user;
+ its_uid_gid.second = its_sec_client.client.uds_client.group;
its_credentials.insert(its_uid_gid);
for (auto its_requesting_client : its_requesting_clients) {
- std::pair<uint32_t, uint32_t> 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) {
- create_client_credentials_info(its_requesting_client);
- insert_client_credentials_info(its_requesting_client, its_credentials);
- send_client_credentials_info(its_requesting_client);
- }
+ vsomeip_sec_client_t its_requester_sec_client;
+ if (policy_manager_impl::get()->get_client_to_sec_client_mapping(
+ its_requesting_client, its_requester_sec_client)) {
+ if (!utility::compare(its_sec_client, its_requester_sec_client))
+ send_client_credentials(its_requesting_client, its_credentials);
}
}
}
}
-void routing_manager_stub::inform_provider(client_t _hoster, service_t _service,
+void routing_manager_stub::inform_requesters(client_t _hoster, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor,
- routing_info_entry_e _entry) {
+ protocol::routing_info_entry_type_e _type, bool _inform_service) {
- if (_hoster != VSOMEIP_ROUTING_CLIENT
- && _hoster != host_->get_client()) {
- create_client_routing_info(_hoster);
- insert_client_routing_info(_hoster, _entry, _hoster,
- _service, _instance, _major, _minor);
- send_client_routing_info(_hoster);
- }
-};
+ boost::asio::ip::address its_address;
+ port_t its_port;
-void routing_manager_stub::inform_requesters(client_t _hoster, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor,
- routing_info_entry_e _entry, bool _inform_service) {
for (auto its_client : service_requests_) {
auto its_service = its_client.second.find(_service);
if (its_service != its_client.second.end()) {
@@ -1338,31 +1244,39 @@ void routing_manager_stub::inform_requesters(client_t _hoster, service_t _servic
if (_inform_service) {
if (_hoster != VSOMEIP_ROUTING_CLIENT &&
_hoster != host_->get_client()) {
- if (!is_already_connected(_hoster, its_client.first)) {
- create_client_routing_info(_hoster);
- insert_client_routing_info(_hoster,
- routing_info_entry_e::RIE_ADD_CLIENT,
- its_client.first);
- send_client_routing_info(_hoster);
+ if (!is_connected(_hoster, its_client.first)) {
+ add_connection(_hoster, its_client.first);
+ protocol::routing_info_entry its_entry;
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_ADD_CLIENT);
+ its_entry.set_client(its_client.first);
+ if (host_->get_guest(its_client.first, its_address, its_port)) {
+ its_entry.set_address(its_address);
+ its_entry.set_port(its_port);
+ }
+ send_client_routing_info(_hoster, its_entry);
}
}
}
if (its_client.first != VSOMEIP_ROUTING_CLIENT &&
its_client.first != get_client()) {
- create_client_routing_info(its_client.first);
- insert_client_routing_info(its_client.first, _entry, _hoster,
- _service, _instance, _major, _minor);
- send_client_routing_info(its_client.first);
+ add_connection(its_client.first, _hoster);
+ protocol::routing_info_entry its_entry;
+ its_entry.set_type(_type);
+ its_entry.set_client(_hoster);
+ if ((_type == protocol::routing_info_entry_type_e::RIE_ADD_CLIENT
+ || _type == protocol::routing_info_entry_type_e::RIE_ADD_SERVICE_INSTANCE)
+ && host_->get_guest(_hoster, its_address, its_port)) {
+ its_entry.set_address(its_address);
+ its_entry.set_port(its_port);
+ }
+ its_entry.add_service({ _service, _instance, _major, _minor} );
+ send_client_routing_info(its_client.first, its_entry);
}
}
}
}
}
-bool routing_manager_stub::is_already_connected(client_t _source, client_t _sink) {
- return connection_matrix_[_source].find(_sink) != connection_matrix_[_source].end();
-}
-
void routing_manager_stub::broadcast(const std::vector<byte_t> &_command) const {
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
for (const auto& a : routing_info_) {
@@ -1376,42 +1290,50 @@ void routing_manager_stub::broadcast(const std::vector<byte_t> &_command) const
}
}
-bool routing_manager_stub::send_subscribe(const std::shared_ptr<endpoint>& _target,
- client_t _client, service_t _service, instance_t _instance,
+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, remote_subscription_id_t _id) {
+ event_t _event, const std::shared_ptr<debounce_filter_t> &_filter,
+ remote_subscription_id_t _id) {
+
+ bool has_sent(false);
+
if (_target) {
- byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE;
- 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], &_eventgroup,
- sizeof(_eventgroup));
- 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], &_id,
- sizeof(_id));
-
- return _target->send(its_command, sizeof(its_command));
+
+ protocol::subscribe_command its_command;
+ its_command.set_client(_client);
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_major(_major);
+ its_command.set_event(_event);
+ its_command.set_filter(_filter);
+ its_command.set_pending_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ has_sent = _target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": subscribe command serialization failed ("
+ << std::dec << int(its_error) << ")";
+
} else {
- VSOMEIP_WARNING << __func__ << " Couldn't send subscription to local client ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
- << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
- << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
- << _client;
- return false;
+ VSOMEIP_WARNING << __func__
+ << " Couldn't send subscription to local client ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
+ << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
+ << _client;
}
+
+ return (has_sent);
}
bool routing_manager_stub::send_unsubscribe(
@@ -1419,37 +1341,41 @@ bool routing_manager_stub::send_unsubscribe(
client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event,
remote_subscription_id_t _id) {
+
+ bool has_sent(false);
+
if (_target) {
- byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNSUBSCRIBE;
- 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], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
- sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_id,
- sizeof(_id));
-
- return _target->send(its_command, sizeof(its_command));
+
+ protocol::unsubscribe_command its_command;
+ its_command.set_client(_client);
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_event(_event);
+ its_command.set_pending_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ has_sent = _target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": unsubscribe command serialization failed ("
+ << std::dec << int(its_error) << ")";
} else {
- VSOMEIP_WARNING << __func__ << " Couldn't send unsubscription to local client ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
- << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
- << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
- << _client;
- return false;
+ VSOMEIP_WARNING << __func__
+ << " Couldn't send unsubscription to local client ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
+ << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
+ << _client;
}
+
+ return (has_sent);
}
bool routing_manager_stub::send_expired_subscription(
@@ -1457,100 +1383,94 @@ bool routing_manager_stub::send_expired_subscription(
client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event,
remote_subscription_id_t _id) {
+
+ bool has_sent(false);
+
if (_target) {
- byte_t its_command[VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_EXPIRED_SUBSCRIPTION;
- 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], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
- sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_id,
- sizeof(_id));
-
- return _target->send(its_command, sizeof(its_command));
+
+ protocol::expire_command its_command;
+ its_command.set_client(_client);
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_event(_event);
+ its_command.set_pending_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ has_sent = _target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": unsubscribe command serialization failed ("
+ << std::dec << int(its_error) << ")";
} else {
- VSOMEIP_WARNING << __func__ << " Couldn't send expired subscription to local client ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
- << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
- << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
- << _client;
- return false;
+ VSOMEIP_WARNING << __func__
+ << " Couldn't send expired subscription to local client ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
+ << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
+ << _client;
}
+
+ return (has_sent);
}
void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
- if (its_endpoint) {
- byte_t its_command[VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- client_t this_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_ACK;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
- sizeof(this_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], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_client,
- sizeof(_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
- sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
- &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
-
- its_endpoint->send(&its_command[0], sizeof(its_command));
+ std::shared_ptr<endpoint> its_target = host_->find_local(_client);
+ if (its_target) {
+
+ protocol::subscribe_ack_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_subscriber(_client);
+ its_command.set_event(_event);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ (void)its_target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": subscribe ack command serialization failed ("
+ << std::dec << int(its_error) << ")";
}
}
void routing_manager_stub::send_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
- if (its_endpoint) {
- byte_t its_command[VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
-
- client_t this_client = get_client();
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_NACK;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
- sizeof(this_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], &_eventgroup,
- sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_client,
- sizeof(_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
- sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
- &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
-
- its_endpoint->send(&its_command[0], sizeof(its_command));
+ std::shared_ptr<endpoint> its_target = host_->find_local(_client);
+ if (its_target) {
+
+ protocol::subscribe_nack_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_service(_service);
+ its_command.set_instance(_instance);
+ its_command.set_eventgroup(_eventgroup);
+ its_command.set_subscriber(_client);
+ its_command.set_event(_event);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ (void)its_target->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": subscribe ack command serialization failed ("
+ << std::dec << int(its_error) << ")";
}
}
@@ -1576,7 +1496,19 @@ bool routing_manager_stub::contained_in_routing_info(
// Watchdog
void routing_manager_stub::broadcast_ping() const {
- broadcast(its_ping_);
+
+ protocol::ping_command its_command;
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK)
+ broadcast(its_buffer);
+ else
+ VSOMEIP_ERROR << __func__
+ << ": ping command serialization failed ("
+ << std::dec << int(its_error) << ")";
}
void routing_manager_stub::on_pong(client_t _client) {
@@ -1656,8 +1588,8 @@ void routing_manager_stub::create_local_receiver() {
if (local_receiver_) {
return;
}
-#ifndef _WIN32
- else if (!security::get()->check_credentials(get_client(), getuid(), getgid())) {
+#if defined(__linux__) || defined(ANDROID)
+ else if (!policy_manager_impl::get()->check_credentials(get_client(), host_->get_sec_client())) {
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!";
@@ -1666,56 +1598,71 @@ void routing_manager_stub::create_local_receiver() {
#endif
local_receiver_ = std::static_pointer_cast<endpoint_manager_base>(
host_->get_endpoint_manager())->create_local_server(shared_from_this());
- local_receiver_->start();
+
+ if (local_receiver_)
+ local_receiver_->start();
}
bool routing_manager_stub::send_ping(client_t _client) {
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
- if (!its_endpoint) {
- return false;
- }
- {
+ bool has_sent(false);
+
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint) {
std::lock_guard<std::mutex> its_lock(pinged_clients_mutex_);
if (pinged_clients_.find(_client) != pinged_clients_.end()) {
// client was already pinged: don't ping again and wait for answer
// or timeout of previous ping.
- return true;
- }
-
- boost::system::error_code ec;
- pinged_clients_timer_.cancel(ec);
- if (ec) {
- VSOMEIP_ERROR << "routing_manager_stub::send_ping cancellation of "
- "timer failed: " << ec.message();
- }
- const std::chrono::steady_clock::time_point now(
- std::chrono::steady_clock::now());
+ has_sent = true;
+ } else {
+ boost::system::error_code ec;
+ pinged_clients_timer_.cancel(ec);
+ if (ec) {
+ VSOMEIP_ERROR << "routing_manager_stub::send_ping cancellation of "
+ "timer failed: " << ec.message();
+ }
+ const std::chrono::steady_clock::time_point now(
+ std::chrono::steady_clock::now());
- std::chrono::milliseconds next_timeout(configured_watchdog_timeout_);
- for (const auto &tp : pinged_clients_) {
- const std::chrono::milliseconds its_clients_timeout =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- now - tp.second);
- if (next_timeout > its_clients_timeout) {
- next_timeout = its_clients_timeout;
+ std::chrono::milliseconds next_timeout(configured_watchdog_timeout_);
+ for (const auto &tp : pinged_clients_) {
+ const std::chrono::milliseconds its_clients_timeout =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - tp.second);
+ if (next_timeout > its_clients_timeout) {
+ next_timeout = its_clients_timeout;
+ }
}
- }
- pinged_clients_[_client] = now;
+ pinged_clients_[_client] = now;
- ec.clear();
- pinged_clients_timer_.expires_from_now(next_timeout, ec);
- if (ec) {
- VSOMEIP_ERROR<< "routing_manager_stub::send_ping setting "
- "expiry time of timer failed: " << ec.message();
+ ec.clear();
+ pinged_clients_timer_.expires_from_now(next_timeout, ec);
+ if (ec) {
+ VSOMEIP_ERROR << "routing_manager_stub::send_ping setting "
+ "expiry time of timer failed: " << ec.message();
+ }
+ pinged_clients_timer_.async_wait(
+ std::bind(&routing_manager_stub::on_ping_timer_expired, this,
+ std::placeholders::_1));
+
+ protocol::ping_command its_command;
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK)
+ has_sent = its_endpoint->send(&its_buffer[0], uint32_t(its_buffer.size()));
+ else
+ VSOMEIP_ERROR << __func__
+ << ": ping command serialization failed ("
+ << std::dec << int(its_error) << ")";
}
- 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()));
}
+
+ return (has_sent);
}
void routing_manager_stub::on_ping_timer_expired(
@@ -1821,19 +1768,33 @@ bool routing_manager_stub::is_registered(client_t _client) const {
}
void routing_manager_stub::update_registration(client_t _client,
- registration_type_e _type) {
+ registration_type_e _type,
+ const boost::asio::ip::address &_address, port_t _port) {
+
+ std::stringstream its_client;
+ its_client << std::hex << std::setw(4) << std::setfill('0')
+ << _client;
+
+ if (_port > 0 && _port < ILLEGAL_PORT) {
+ its_client << " @ " << _address.to_string() << ":" << std::dec << _port;
+ }
VSOMEIP_INFO << "Application/Client "
- << std::hex << std::setw(4) << std::setfill('0') << _client
+ << its_client.str()
<< " is "
<< (_type == registration_type_e::REGISTER ?
"registering." : "deregistering.");
if (_type != registration_type_e::REGISTER) {
- security::get()->remove_client_to_uid_gid_mapping(_client);
+ policy_manager_impl::get()->remove_client_to_sec_client_mapping(_client);
+ } else {
+ if (_port > 0 && _port < ILLEGAL_PORT)
+ host_->add_guest(_client, _address, _port);
}
if (_type == registration_type_e::DEREGISTER) {
+ host_->remove_guest(_client);
+
// If we receive a DEREGISTER client command
// the endpoint error handler is not longer needed
// as the client is going down anyways.
@@ -1868,15 +1829,15 @@ client_t routing_manager_stub::get_client() const {
return host_->get_client();
}
-void routing_manager_stub::handle_credentials(const client_t _client, std::set<service_data_t>& _requests) {
+void routing_manager_stub::handle_credentials(const client_t _client, std::set<protocol::service> &_requests) {
if (!_requests.size()) {
return;
}
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
std::set<std::pair<uint32_t, uint32_t>> its_credentials;
- std::pair<uint32_t, uint32_t> its_requester_uid_gid;
- if (security::get()->get_client_to_uid_gid_mapping(_client, its_requester_uid_gid)) {
+ vsomeip_sec_client_t its_requester_sec_client;
+ if (policy_manager_impl::get()->get_client_to_sec_client_mapping(_client, its_requester_sec_client)) {
// determine credentials of offering clients using current routing info
std::set<client_t> its_offering_clients;
@@ -1891,65 +1852,79 @@ 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 (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)));
+ vsomeip_sec_client_t its_sec_client;
+ if (policy_manager_impl::get()->get_client_to_sec_client_mapping(its_offering_client, its_sec_client)) {
+ if (its_sec_client.client_type == VSOMEIP_CLIENT_UDS
+ && !utility::compare(its_sec_client, its_requester_sec_client)) {
+
+ its_credentials.insert(std::make_pair(
+ its_sec_client.client.uds_client.user, its_sec_client.client.uds_client.group));
}
}
}
// send credentials to clients
- if (!its_credentials.empty()) {
- create_client_credentials_info(_client);
- insert_client_credentials_info(_client, its_credentials);
- send_client_credentials_info(_client);
- }
+ if (!its_credentials.empty())
+ send_client_credentials(_client, its_credentials);
}
}
-void routing_manager_stub::handle_requests(const client_t _client, std::set<service_data_t>& _requests) {
- if (!_requests.size()) {
+void routing_manager_stub::handle_requests(const client_t _client, std::set<protocol::service> &_requests) {
+
+ if (_requests.empty())
return;
- }
- bool service_available(false);
+
+ boost::asio::ip::address its_address;
+ port_t its_port;
+
+ std::vector<protocol::routing_info_entry> its_entries;
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- create_client_routing_info(_client);
+
for (auto request : _requests) {
service_requests_[_client][request.service_][request.instance_]
- = std::make_pair(request.major_, request.minor_);
+ = std::make_pair(request.major_, request.minor_);
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
+ // insert VSOMEIP_ROUTING_CLIENT to check whether 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 (!is_connected(c, _client)) {
+ add_connection(c, _client);
+
+ protocol::routing_info_entry its_entry;
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_ADD_CLIENT);
+ its_entry.set_client(_client);
+ if (host_->get_guest(_client, its_address, its_port)) {
+ its_entry.set_address(its_address);
+ its_entry.set_port(its_port);
+ }
if (_client == c) {
- service_available = true;
- insert_client_routing_info(c,
- routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ its_entries.emplace_back(its_entry);
} else {
- create_client_routing_info(c);
- insert_client_routing_info(c,
- routing_info_entry_e::RIE_ADD_CLIENT, _client);
- send_client_routing_info(c);
+ send_client_routing_info(c, its_entry);
}
}
}
- if (_client != VSOMEIP_ROUTING_CLIENT &&
- _client != host_->get_client()) {
+ 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);
+ add_connection(_client, c);
+
+ protocol::routing_info_entry its_entry;
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_ADD_SERVICE_INSTANCE);
+ its_entry.set_client(c);
+ if (host_->get_guest(c, its_address, its_port)) {
+ its_entry.set_address(its_address);
+ its_entry.set_port(its_port);
+ }
+ its_entry.add_service({ request.service_, instance.first,
+ instance.second.first, instance.second.second });
+ its_entries.emplace_back(its_entry);
}
}
}
@@ -1963,38 +1938,46 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
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 (c != VSOMEIP_ROUTING_CLIENT &&
- c != host_->get_client()) {
- if (!is_already_connected(c, _client)) {
+ if (c != VSOMEIP_ROUTING_CLIENT && c != host_->get_client()) {
+ if (!is_connected(c, _client)) {
+ add_connection(c, _client);
+
+ protocol::routing_info_entry its_entry;
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_ADD_CLIENT);
+ its_entry.set_client(_client);
+ if (host_->get_guest(_client, its_address, its_port)) {
+ its_entry.set_address(its_address);
+ its_entry.set_port(its_port);
+ }
if (_client == c) {
- service_available = true;
- insert_client_routing_info(c,
- routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ its_entries.emplace_back(its_entry);
} else {
- create_client_routing_info(c);
- insert_client_routing_info(c,
- routing_info_entry_e::RIE_ADD_CLIENT, _client);
- send_client_routing_info(c);
+ send_client_routing_info(c, its_entry);
}
}
}
- if (_client != VSOMEIP_ROUTING_CLIENT &&
- _client != host_->get_client()) {
- service_available = true;
- insert_client_routing_info(_client,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- c, request.service_, request.instance_,
- found_instance->second.first,
- found_instance->second.second);
+ if (_client != VSOMEIP_ROUTING_CLIENT && _client != host_->get_client()) {
+ add_connection(_client, c);
+
+ protocol::routing_info_entry its_entry;
+ its_entry.set_type(protocol::routing_info_entry_type_e::RIE_ADD_SERVICE_INSTANCE);
+ its_entry.set_client(c);
+ if (host_->get_guest(c, its_address, its_port)) {
+ its_entry.set_address(its_address);
+ its_entry.set_port(its_port);
+ }
+ its_entry.add_service({ request.service_, request.instance_,
+ found_instance->second.first, found_instance->second.second });
+ its_entries.emplace_back(its_entry);
}
}
}
}
}
}
- if (service_available) {
- send_client_routing_info(_client);
- }
+
+ if (!its_entries.empty())
+ send_client_routing_info(_client, std::move(its_entries));
}
void routing_manager_stub::on_client_id_timer_expired(boost::system::error_code const &_error) {
@@ -2029,34 +2012,37 @@ void routing_manager_stub::print_endpoint_status() const {
if (local_receiver_) {
local_receiver_->print_status();
}
- if (endpoint_) {
- endpoint_->print_status();
+ if (root_) {
+ root_->print_status();
}
}
-bool routing_manager_stub::send_provided_event_resend_request(client_t _client,
- pending_remote_offer_id_t _id) {
+bool routing_manager_stub::send_provided_event_resend_request(
+ client_t _client, pending_remote_offer_id_t _id) {
+
std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
if (its_endpoint) {
- byte_t its_command[VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE];
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RESEND_PROVIDED_EVENTS;
- 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));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_id,
- sizeof(pending_remote_offer_id_t));
- return its_endpoint->send(its_command, sizeof(its_command));
+
+ protocol::resend_provided_events_command its_command;
+ its_command.set_client(VSOMEIP_ROUTING_CLIENT);
+ its_command.set_remote_offer_id(_id);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK)
+ return (its_endpoint->send(&its_buffer[0], uint32_t(its_buffer.size())));
} else {
VSOMEIP_WARNING << __func__ << " Couldn't send provided event resend "
"request to local client: 0x"
<< std::hex << std::setw(4) << std::setfill('0') << _client;
- return false;
}
+
+ return (false);
}
+#ifndef VSOMEIP_DISABLE_SECURITY
bool routing_manager_stub::is_policy_cached(uint32_t _uid) {
{
std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
@@ -2089,11 +2075,16 @@ 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, 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;
// command
- its_command.push_back(VSOMEIP_UPDATE_SECURITY_POLICY);
+ its_command.push_back(byte_t(protocol::id_e::UPDATE_SECURITY_POLICY_ID));
+
+ // version
+ its_command.push_back(0x00);
+ its_command.push_back(0x00);
// client ID
for (uint32_t i = 0; i < sizeof(client_t); ++i) {
@@ -2123,89 +2114,74 @@ bool routing_manager_stub::send_update_security_policy_request(client_t _client,
}
bool routing_manager_stub::send_cached_security_policies(client_t _client) {
- std::vector<byte_t> its_command;
- std::size_t its_size(0);
- std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
- uint32_t its_policy_count = uint32_t(updated_security_policies_.size());
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint) {
- if (!its_policy_count) {
- return true;
- }
- VSOMEIP_INFO << __func__ << " Distributing ["
- << std::dec << its_policy_count
- << "] security policy updates to registering client: "
- << std::hex << _client;
+ std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
+ if (!updated_security_policies_.empty()) {
- // command
- its_command.push_back(VSOMEIP_DISTRIBUTE_SECURITY_POLICIES);
+ VSOMEIP_INFO << __func__ << " Distributing ["
+ << std::dec << updated_security_policies_.size()
+ << "] security policy updates to registering client: "
+ << std::hex << _client;
- // client ID
- client_t its_client = get_client();
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&its_client)[i]);
- }
+ protocol::distribute_security_policies_command its_command;
+ its_command.set_client(get_client());
+ its_command.set_payloads(updated_security_policies_);
- //overall size (placeholder
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(0x00);
- }
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
- // number of policies contained in message
- for (uint32_t i = 0; i < sizeof(its_policy_count); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&its_policy_count)[i]);
- }
+ if (its_error == protocol::error_e::ERROR_OK)
+ return its_endpoint->send(its_buffer.data(), uint32_t(its_buffer.size()));
- 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) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&its_length)[i]);
+ VSOMEIP_ERROR << __func__
+ << ": serializing distribute security policies ("
+ << static_cast<int>(its_error)
+ << ")";
}
- // payload
- its_command.insert(its_command.end(), its_uid_gid.second->get_data(),
- its_uid_gid.second->get_data() + its_uid_gid.second->get_length());
- }
- // File overall size
- its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(uint32_t));
+ } else
+ VSOMEIP_WARNING << __func__
+ << ": could not send cached security policies to registering client: 0x"
+ << std::hex << std::setw(4) << std::setfill('0') << _client;
+
+ return (false);
+}
+
+bool routing_manager_stub::send_remove_security_policy_request(
+ client_t _client, pending_security_update_id_t _update_id,
+ uint32_t _uid, uint32_t _gid) {
+
+ protocol::remove_security_policy_command its_command;
+ its_command.set_client(_client);
+ its_command.set_update_id(_update_id);
+ its_command.set_uid(_uid);
+ its_command.set_gid(_gid);
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
+
+ if (its_error == protocol::error_e::ERROR_OK) {
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
+ if (its_endpoint)
+ return (its_endpoint->send(&its_buffer[0], uint32_t(its_buffer.size())));
+ else
+ VSOMEIP_ERROR << __func__
+ << ": cannot find local client endpoint for client "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _client;
+ } else
+ VSOMEIP_ERROR << __func__
+ << ": remove security policy command serialization failed ("
+ << std::dec << static_cast<int>(its_error)
+ << ")";
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
- if (its_endpoint) {
- return its_endpoint->send(its_command.data(), uint32_t(its_command.size()));
- } else {
- VSOMEIP_WARNING << __func__ << " Couldn't send cached security policies "
- " to registering client: 0x"
- << std::hex << std::setw(4) << std::setfill('0') << _client;
- return false;
- }
-}
+ return (false);
-bool routing_manager_stub::send_remove_security_policy_request( client_t _client, pending_security_update_id_t _update_id,
- uint32_t _uid, uint32_t _gid) {
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
- if (its_endpoint) {
- byte_t its_command[VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE];
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REMOVE_SECURITY_POLICY;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
- sizeof(client_t));
- std::uint32_t its_size = sizeof(_update_id) + sizeof(_uid) + sizeof(_gid);
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
- sizeof(uint32_t));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_uid,
- sizeof(uint32_t));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_gid,
- sizeof(uint32_t));
- return its_endpoint->send(its_command, sizeof(its_command));
- } else {
- return false;
- }
}
bool
@@ -2219,7 +2195,7 @@ routing_manager_stub::add_requester_policies(uid_t _uid, gid_t _gid,
if (found_gid != found_uid->second.end()) {
found_gid->second.insert(_policies.begin(), _policies.end());
} else {
- found_uid->second.insert(std::make_pair(_gid, _policies));
+ found_uid->second[_gid] = _policies;
}
} else {
requester_policies_[_uid][_gid] = _policies;
@@ -2228,7 +2204,7 @@ routing_manager_stub::add_requester_policies(uid_t _uid, gid_t _gid,
// Check whether clients with uid/gid are already registered.
// If yes, update their policy
std::unordered_set<client_t> its_clients;
- security::get()->get_clients(_uid, _gid, its_clients);
+ policy_manager_impl::get()->get_clients(_uid, _gid, its_clients);
if (!its_clients.empty())
return send_requester_policies(its_clients, _policies);
@@ -2263,7 +2239,7 @@ routing_manager_stub::get_requester_policies(uid_t _uid, gid_t _gid,
void
routing_manager_stub::add_pending_security_update_handler(
- pending_security_update_id_t _id, security_update_handler_t _handler) {
+ pending_security_update_id_t _id, const security_update_handler_t &_handler) {
std::lock_guard<std::recursive_mutex> its_lock(security_update_handlers_mutex_);
security_update_handlers_[_id] = _handler;
@@ -2304,7 +2280,13 @@ routing_manager_stub::send_requester_policies(const std::unordered_set<client_t>
std::vector<byte_t> its_policy_data;
if (p->serialize(its_policy_data)) {
std::vector<byte_t> its_message;
- its_message.push_back(VSOMEIP_UPDATE_SECURITY_POLICY_INT);
+ its_message.push_back(byte_t(protocol::id_e::UPDATE_SECURITY_POLICY_INT_ID));
+
+ // version
+ its_message.push_back(0);
+ its_message.push_back(0);
+
+ // client identifier
its_message.push_back(0);
its_message.push_back(0);
@@ -2322,7 +2304,7 @@ routing_manager_stub::send_requester_policies(const std::unordered_set<client_t>
its_message.insert(its_message.end(), its_policy_data.begin(), its_policy_data.end());
- for (const auto& c : _clients) {
+ for (const auto c : _clients) {
std::shared_ptr<endpoint> its_endpoint = host_->find_local(c);
if (its_endpoint)
its_endpoint->send(&its_message[0], static_cast<uint32_t>(its_message.size()));
@@ -2401,11 +2383,11 @@ bool routing_manager_stub::update_security_policy_configuration(
policy_cache_add(_uid, _payload);
// update security policy from configuration
- security::get()->update_security_policy(_uid, _gid, _policy);
+ policy_manager_impl::get()->update_security_policy(_uid, _gid, _policy);
// Build requester policies for the services offered by the new policy
std::set<std::shared_ptr<policy> > its_requesters;
- security::get()->get_requester_policies(_policy, its_requesters);
+ policy_manager_impl::get()->get_requester_policies(_policy, its_requesters);
// and add them to the requester policy cache
add_requester_policies(_uid, _gid, its_requesters);
@@ -2464,7 +2446,7 @@ bool routing_manager_stub::remove_security_policy_configuration(
// remove security policy from configuration (only if there was a updateACL call before)
if (is_policy_cached(_uid)) {
- if (!security::get()->remove_security_policy(_uid, _gid)) {
+ if (!policy_manager_impl::get()->remove_security_policy(_uid, _gid)) {
_handler(security_update_state_e::SU_UNKNOWN_USER_ID);
ret = false;
} else {
@@ -2611,13 +2593,33 @@ void routing_manager_stub::on_security_update_response(
}
}
}
+#endif // !VSOMEIP_DISABLE_SECURITY
void routing_manager_stub::send_suspend() const {
- static const std::vector<byte_t> its_suspend(
- { VSOMEIP_SUSPEND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
+ protocol::suspend_command its_command;
+
+ std::vector<byte_t> its_buffer;
+ protocol::error_e its_error;
+ its_command.serialize(its_buffer, its_error);
- broadcast(its_suspend);
+ if (its_error == protocol::error_e::ERROR_OK)
+ broadcast(its_buffer);
+ else
+ VSOMEIP_ERROR << __func__
+ << ": suspend command serialization failed ("
+ << std::dec << int(its_error) << ")";
+}
+
+void
+routing_manager_stub::remove_subscriptions(port_t _local_port,
+ const boost::asio::ip::address &_remote_address,
+ port_t _remote_port) {
+
+ (void)_local_port;
+ (void)_remote_address;
+ (void)_remote_port;
+ // dummy method to implement routing_host interface
}
} // namespace vsomeip_v3
diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp
index 324fcd7..fcdcbd8 100644
--- a/implementation/routing/src/serviceinfo.cpp
+++ b/implementation/routing/src/serviceinfo.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2021 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/.
@@ -10,8 +10,7 @@ namespace vsomeip_v3 {
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),
+ : service_(_service),
instance_(_instance),
major_(_major),
minor_(_minor),
@@ -26,7 +25,6 @@ serviceinfo::serviceinfo(service_t _service, instance_t _instance,
}
serviceinfo::serviceinfo(const serviceinfo& _other) :
- group_(_other.group_),
service_(_other.service_),
instance_(_other.instance_),
major_(_other.major_),
@@ -42,14 +40,6 @@ serviceinfo::serviceinfo(const serviceinfo& _other) :
serviceinfo::~serviceinfo() {
}
-servicegroup * serviceinfo::get_group() const {
- return group_;
-}
-
-void serviceinfo::set_group(servicegroup *_group) {
- group_ = _group;
-}
-
service_t serviceinfo::get_service() const {
return service_;
}