summaryrefslogtreecommitdiff
path: root/implementation/routing/src
diff options
context:
space:
mode:
Diffstat (limited to 'implementation/routing/src')
-rw-r--r--implementation/routing/src/event.cpp33
-rw-r--r--implementation/routing/src/routing_manager_base.cpp84
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp301
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp358
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp275
-rw-r--r--implementation/routing/src/serviceinfo.cpp11
6 files changed, 785 insertions, 277 deletions
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
index c077844..653f262 100644
--- a/implementation/routing/src/event.cpp
+++ b/implementation/routing/src/event.cpp
@@ -85,10 +85,12 @@ bool event::is_set() const {
}
const std::shared_ptr<payload> event::get_payload() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
return (message_->get_payload());
}
void event::set_payload_dont_notify(const std::shared_ptr<payload> &_payload) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if(is_cache_placeholder_) {
reset_payload(_payload);
is_set_ = true;
@@ -99,7 +101,9 @@ void event::set_payload_dont_notify(const std::shared_ptr<payload> &_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, bool _flush) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if (is_provided_) {
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
@@ -107,7 +111,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
if (change_resets_cycle_)
stop_cycle();
- notify();
+ notify(_flush);
if (change_resets_cycle_)
start_cycle();
@@ -120,12 +124,13 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
}
void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _client,
- bool _force) {
+ bool _force, bool _flush) {
+ 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(_client);
+ notify_one(_client, _flush);
}
}
} else {
@@ -136,12 +141,13 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _clie
void event::set_payload(const std::shared_ptr<payload> &_payload,
const std::shared_ptr<endpoint_definition> _target,
- bool _force) {
+ bool _force, bool _flush) {
+ 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(_target);
+ notify_one(_target, _flush);
}
}
} else {
@@ -151,6 +157,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload,
}
void event::unset_payload(bool _force) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if (_force) {
is_set_ = false;
stop_cycle();
@@ -202,7 +209,7 @@ void event::set_eventgroups(const std::set<eventgroup_t> &_eventgroups) {
void event::update_cbk(boost::system::error_code const &_error) {
if (!_error) {
cycle_timer_.expires_from_now(cycle_);
- notify();
+ notify(true);
std::function<void(boost::system::error_code const &)> its_handler =
std::bind(&event::update_cbk, shared_from_this(),
std::placeholders::_1);
@@ -210,27 +217,27 @@ void event::update_cbk(boost::system::error_code const &_error) {
}
}
-void event::notify() {
+void event::notify(bool _flush) {
if (is_set_) {
- routing_->send(VSOMEIP_ROUTING_CLIENT, message_, true);
+ routing_->send(VSOMEIP_ROUTING_CLIENT, message_, _flush);
} else {
VSOMEIP_DEBUG << "Notify event " << std::hex << message_->get_method()
<< "failed. Event payload not set!";
}
}
-void event::notify_one(const std::shared_ptr<endpoint_definition> &_target) {
+void event::notify_one(const std::shared_ptr<endpoint_definition> &_target, bool _flush) {
if (is_set_) {
- routing_->send_to(_target, message_);
+ routing_->send_to(_target, message_, _flush);
} else {
VSOMEIP_DEBUG << "Notify one event " << std::hex << message_->get_method()
<< "failed. Event payload not set!";
}
}
-void event::notify_one(client_t _client) {
+void event::notify_one(client_t _client, bool _flush) {
if (is_set_) {
- routing_->send(_client, message_, true);
+ routing_->send(_client, message_, _flush);
} else {
VSOMEIP_DEBUG << "Notify one event " << std::hex << message_->get_method()
<< " to client " << _client << " failed. Event payload not set!";
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index e146d65..89a5843 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -20,12 +20,14 @@ routing_manager_base::routing_manager_base(routing_manager_host *_host) :
io_(host_->get_io()),
client_(host_->get_client()),
configuration_(host_->get_configuration()),
- serializer_(std::make_shared<serializer>()),
- deserializer_(std::make_shared<deserializer>())
+ serializer_(std::make_shared<serializer>())
#ifdef USE_DLT
, tc_(tc::trace_connector::get())
#endif
{
+ for (int i = 0; i < VSOMEIP_MAX_DESERIALIZER; ++i) {
+ deserializers_.push(std::make_shared<deserializer>());
+ }
}
routing_manager_base::~routing_manager_base() {
@@ -303,7 +305,7 @@ void routing_manager_base::subscribe(client_t _client, service_t _service,
= its_eventgroup->get_events();
for (auto e : its_events) {
if (e->is_field())
- e->notify_one(_client);
+ e->notify_one(_client, true); // TODO: use _flush to send all events together!
}
}
}
@@ -325,10 +327,11 @@ void routing_manager_base::unsubscribe(client_t _client, service_t _service,
}
void routing_manager_base::notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload, bool _force) {
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- its_event->set_payload(_payload, _force);
+ its_event->set_payload(_payload, _force, _flush);
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
<< std::hex << _service << "." << _instance << "." << _event
@@ -338,7 +341,7 @@ void routing_manager_base::notify(service_t _service, instance_t _instance,
void routing_manager_base::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force) {
+ client_t _client, bool _force, bool _flush) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
// Event is valid for service/instance
@@ -354,7 +357,7 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
}
}
if (found_eventgroup) {
- its_event->set_payload(_payload, _client, _force);
+ its_event->set_payload(_payload, _client, _force, _flush);
}
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
@@ -757,11 +760,16 @@ bool routing_manager_base::send_local(
const byte_t *_data, uint32_t _size, instance_t _instance,
bool _flush, bool _reliable, uint8_t _command) const {
+ client_t sender = get_client();
+ size_t additional_size = 0;
+ if (_command == VSOMEIP_NOTIFY_ONE) {
+ additional_size +=sizeof(client_t);
+ }
std::vector<byte_t> its_command(
VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t)
- + sizeof(bool) + sizeof(bool));
+ + sizeof(bool) + sizeof(bool) + additional_size);
its_command[VSOMEIP_COMMAND_TYPE_POS] = _command;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &sender,
sizeof(client_t));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size,
sizeof(_size));
@@ -773,6 +781,11 @@ bool routing_manager_base::send_local(
+ sizeof(instance_t)], &_flush, sizeof(bool));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size
+ sizeof(instance_t) + sizeof(bool)], &_reliable, sizeof(bool));
+ if (_command == VSOMEIP_NOTIFY_ONE) {
+ // Add target client
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size
+ + sizeof(instance_t) + sizeof(bool) + sizeof(bool)], &_client, sizeof(client_t));
+ }
return _target->send(&its_command[0], uint32_t(its_command.size()));
}
@@ -804,4 +817,57 @@ void routing_manager_base::on_clientendpoint_error(client_t _client) {
remove_local(_client);
}
+std::shared_ptr<deserializer> routing_manager_base::get_deserializer() {
+ std::unique_lock<std::mutex> its_lock(deserializer_mutex_);
+ while (deserializers_.empty()) {
+ VSOMEIP_INFO << std::hex << "client " << get_client() <<
+ "routing_manager_base::get_deserializer ~> all in use!";
+ deserializer_condition_.wait(its_lock);
+ VSOMEIP_INFO << std::hex << "client " << get_client() <<
+ "routing_manager_base::get_deserializer ~> wait finished!";
+ }
+ auto deserializer = deserializers_.front();
+ deserializers_.pop();
+ return deserializer;
+}
+
+void routing_manager_base::put_deserializer(std::shared_ptr<deserializer> _deserializer) {
+ {
+ std::lock_guard<std::mutex> its_lock(deserializer_mutex_);
+ deserializers_.push(_deserializer);
+ }
+ deserializer_condition_.notify_one();
+}
+
+#ifndef WIN32
+bool routing_manager_base::check_credentials(client_t _client, uid_t _uid, gid_t _gid) {
+ return configuration_->check_credentials(_client, _uid, _gid);
+}
+#endif
+
+void routing_manager_base::send_pending_subscriptions(service_t _service,
+ instance_t _instance, major_version_t _major) {
+ for (auto &ps : pending_subscriptions_) {
+ if (ps.service_ == _service &&
+ ps.instance_ == _instance && ps.major_ == _major) {
+ send_subscribe(client_, ps.service_, ps.instance_,
+ ps.eventgroup_, ps.major_, ps.subscription_type_);
+ }
+ }
+}
+
+void routing_manager_base::remove_pending_subscription(service_t _service,
+ instance_t _instance) {
+ auto it = pending_subscriptions_.begin();
+ while (it != pending_subscriptions_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance) {
+ break;
+ }
+ it++;
+ }
+ if (it != pending_subscriptions_.end()) pending_subscriptions_.erase(it);
+}
+
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 99c8c7d..7a27e4e 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -136,8 +136,6 @@ void routing_manager_impl::stop() {
bool routing_manager_impl::offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor) {
- std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
-
VSOMEIP_DEBUG << "OFFER("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
@@ -165,9 +163,23 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service,
}
if (discovery_) {
- discovery_->on_offer_change();
+ std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
+ if (its_info) {
+ discovery_->offer_service(_service, _instance, its_info);
+ }
}
+ {
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ for (auto &ps : pending_subscriptions_) {
+ if (ps.service_ == _service &&
+ ps.instance_ == _instance && ps.major_ == _major) {
+ insert_subscription(ps.service_, ps.instance_,
+ ps.eventgroup_, client_);
+ }
+ }
+ send_pending_subscriptions(_service, _instance, _major);
+ }
stub_->on_offer_service(_client, _service, _instance, _major, _minor);
host_->on_availability(_service, _instance, true, _major, _minor);
return true;
@@ -368,14 +380,21 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
= its_eventgroup->get_events();
for (auto e : its_events) {
if (e->is_field())
- e->notify_one(_client);
+ e->notify_one(_client, true); // TODO: use _flush to send all initial events together
}
}
} else {
- stub_->send_subscribe(routing_manager_base::find_local(_service, _instance),
- _client, _service, _instance, _eventgroup, _major, false);
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ if (is_available(_service, _instance, _major)) {
+ stub_->send_subscribe(find_local(_service, _instance),
+ _client, _service, _instance, _eventgroup, _major, false);
+ }
}
}
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major,
+ _subscription_type};
+ pending_subscriptions_.insert(subscription);
} else {
VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!";
}
@@ -431,10 +450,13 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
if( last_subscriber_removed )
discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber);
} else {
- stub_->send_unsubscribe(routing_manager_base::find_local(_service, _instance),
+ stub_->send_unsubscribe(find_local(_service, _instance),
_client, _service, _instance, _eventgroup, false);
}
clear_multicast_endpoints(_service, _instance);
+
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ remove_pending_subscription(_service, _instance);
} else {
VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!";
}
@@ -449,7 +471,6 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
bool _flush, bool _reliable) {
bool is_sent(false);
-
std::shared_ptr<endpoint> its_target;
bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]);
bool is_notification = utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]);
@@ -466,12 +487,20 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
if (is_request) {
- its_target = routing_manager_base::find_local(its_service, _instance);
+ its_target = find_local(its_service, _instance);
} else if (!is_notification) {
its_target = find_local(its_client);
- } else if (is_notification && _client) {
- // Selective notifications!
+ } else if (is_notification && _client) { // Selective notifications!
if (_client == get_client()) {
+#ifdef USE_DLT
+ uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+
+ tc::trace_header its_header;
+ if (its_header.prepare(its_target, true))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, its_data_size);
+#endif
deliver_message(_data, _size, _instance, _reliable);
return true;
}
@@ -479,7 +508,16 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
}
if (its_target) {
- is_sent = send_local(its_target, _client, _data, _size, _instance, _flush, _reliable, VSOMEIP_SEND);
+#ifdef USE_DLT
+ uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+
+ tc::trace_header its_header;
+ if (its_header.prepare(its_target, true))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, its_data_size);
+#endif
+ is_sent = send_local(its_target, get_client(), _data, _size, _instance, _flush, _reliable, VSOMEIP_SEND);
} else {
// Check whether hosting application should get the message
// If not, check routes to external
@@ -543,9 +581,9 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
// Unicast targets
for (auto its_remote : its_eventgroup->get_targets()) {
if(its_remote.endpoint_->is_reliable() && its_reliable_target) {
- its_reliable_target->send_to(its_remote.endpoint_, _data, _size);
+ its_reliable_target->send_to(its_remote.endpoint_, _data, _size, _flush);
} else if (its_unreliable_target && !its_eventgroup->is_sending_multicast()) {
- its_unreliable_target->send_to(its_remote.endpoint_, _data, _size);
+ its_unreliable_target->send_to(its_remote.endpoint_, _data, _size, _flush);
}
#ifdef USE_DLT
has_sent = true;
@@ -554,7 +592,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
// Send to multicast targets if subscribers are still interested
if (its_eventgroup->is_sending_multicast()) {
for (auto its_multicast_target : its_eventgroup->get_multicast_targets()) {
- its_unreliable_target->send_to(its_multicast_target.endpoint_, _data, _size);
+ its_unreliable_target->send_to(its_multicast_target.endpoint_, _data, _size, _flush);
#ifdef USE_DLT
has_sent = true;
#endif
@@ -612,12 +650,12 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
bool routing_manager_impl::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message) {
+ std::shared_ptr<message> _message, bool _flush) {
bool is_sent(false);
std::lock_guard<std::mutex> its_lock(serialize_mutex_);
if (serializer_->serialize(_message.get())) {
is_sent = send_to(_target,
- serializer_->get_data(), serializer_->get_size());
+ serializer_->get_data(), serializer_->get_size(), _flush);
serializer_->reset();
} else {
VSOMEIP_ERROR<< "routing_manager_impl::send_to: serialization failed.";
@@ -627,7 +665,7 @@ 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) {
+ const byte_t *_data, uint32_t _size, bool _flush) {
std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(
_target->get_remote_port(), _target->is_reliable());
@@ -641,7 +679,7 @@ bool routing_manager_impl::send_to(
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- return its_endpoint->send_to(_target, _data, _size);
+ return its_endpoint->send_to(_target, _data, _size, _flush);
}
return false;
}
@@ -687,10 +725,10 @@ void routing_manager_impl::unregister_shadow_event(client_t _client,
void routing_manager_impl::notify(
service_t _service, instance_t _instance, event_t _event,
- std::shared_ptr<payload> _payload, bool _force) {
+ std::shared_ptr<payload> _payload, bool _force, bool _flush) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- its_event->set_payload(_payload, _force);
+ its_event->set_payload(_payload, _force, _flush);
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
<< std::hex << _service << "." << _instance << "." << _event
@@ -700,10 +738,10 @@ void routing_manager_impl::notify(
void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, client_t _client,
- bool _force) {
+ bool _force, bool _flush) {
if (find_local(_client)) {
routing_manager_base::notify_one(_service, _instance, _event, _payload,
- _client, _force);
+ _client, _force, _flush);
} else {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
@@ -730,7 +768,7 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
auto its_subscriber = its_instance->second.find(_client);
if (its_subscriber != its_instance->second.end()) {
for (auto its_target : its_subscriber->second) {
- its_event->set_payload(_payload, its_target, _force);
+ its_event->set_payload(_payload, its_target, _force, _flush);
}
}
}
@@ -756,11 +794,13 @@ void routing_manager_impl::on_error(const byte_t *_data, length_t _length, endpo
}
void routing_manager_impl::release_port(uint16_t _port, bool _reliable) {
+ std::lock_guard<std::mutex> its_lock(used_client_ports_mutex_);
used_client_ports_[_reliable].erase(_port);
}
void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
- endpoint *_receiver, const boost::asio::ip::address &_destination) {
+ endpoint *_receiver, const boost::asio::ip::address &_destination,
+ client_t _bound_client) {
#if 0
std::stringstream msg;
msg << "rmi::on_message: ";
@@ -768,6 +808,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
VSOMEIP_DEBUG << msg.str();
#endif
+ (void)_bound_client;
service_t its_service;
method_t its_method;
if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) {
@@ -810,6 +851,34 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
return;
}
+ // Security checks if 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],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ if (!configuration_->is_offered_remote(its_service, its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
+ << "for service/instance " << its_service << "/" << its_instance
+ << " which isn't offered remote ~> Skip message!";
+ return;
+ }
+ if (find_local(requester)) {
+ VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
+ << "from client identifier 0x" << requester
+ << " which is already used locally ~> Skip message!";
+ return;
+ }
+ if (!configuration_->is_client_allowed(requester, its_service, its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
+ << "from client 0x" << requester << " for service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip message!";
+ return;
+ }
+ }
+ }
+
if (!deliver_specific_endpoint_message(
its_service, its_instance, _data, _size, _receiver)) {
// set client ID to zero for all messages
@@ -883,11 +952,11 @@ void routing_manager_impl::on_notification(client_t _client,
its_length);
if (_notify_one) {
- notify_one(_service, _instance, its_event->get_event(), its_payload, _client, true);
+ notify_one(_service, _instance, its_event->get_event(), its_payload, _client, true, true);
} else {
if (its_event->is_field()) {
if (its_event->is_set()) {
- its_event->set_payload(its_payload);
+ its_event->set_payload(its_payload, false, true);
} else {
// Set payload first time ~> notify all remote subscriber per unicast (inital field)
for (auto its_group : its_event->get_eventgroups()) {
@@ -895,13 +964,13 @@ void routing_manager_impl::on_notification(client_t _client,
if (its_eventgroup) {
//Unicast targets
for (auto its_remote : its_eventgroup->get_targets()) {
- its_event->set_payload(its_payload, its_remote.endpoint_, true);
+ its_event->set_payload(its_payload, its_remote.endpoint_, true, true);
}
}
}
}
} else {
- its_event->set_payload(its_payload);
+ its_event->set_payload(its_payload, false, true);
}
}
@@ -1089,11 +1158,10 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
// Trigger "del_routing_info" either over SD or static
if (discovery_) {
- auto its_info = find_service(_service, _instance);
if (its_info) {
if (its_info->get_major() == _major && its_info->get_minor() == _minor) {
its_info->set_ttl(0);
- discovery_->on_offer_change();
+ discovery_->stop_offer_service(_service, _instance, its_info);
}
}
} else {
@@ -1158,8 +1226,13 @@ 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) {
bool is_delivered(false);
- deserializer_->set_data(_data, _size);
- std::shared_ptr<message> its_message(deserializer_->deserialize_message());
+
+ auto a_deserializer = get_deserializer();
+ a_deserializer->set_data(_data, _size);
+ std::shared_ptr<message> its_message(a_deserializer->deserialize_message());
+ a_deserializer->reset();
+ put_deserializer(a_deserializer);
+
if (its_message) {
its_message->set_instance(_instance);
its_message->set_reliable(_reliable);
@@ -1223,7 +1296,7 @@ std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup(
return routing_manager_base::find_eventgroup(_service, _instance, _eventgroup);
}
-std::shared_ptr<configuration> routing_manager_impl::get_configuration() const {
+const std::shared_ptr<configuration> routing_manager_impl::get_configuration() const {
return (host_->get_configuration());
}
@@ -1278,6 +1351,14 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client(
void routing_manager_impl::init_service_info(
service_t _service, instance_t _instance, bool _is_local_service) {
std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
+ if (!its_info) {
+ VSOMEIP_ERROR << "routing_manager_impl::init_service_info: couldn't "
+ "find serviceinfo for service: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "]"
+ << " is_local_service=" << _is_local_service;
+ return;
+ }
if (configuration_) {
std::shared_ptr<endpoint> its_reliable_endpoint;
std::shared_ptr<endpoint> its_unreliable_endpoint;
@@ -1392,11 +1473,13 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint(
its_endpoint->enable_magic_cookies();
}
} else {
+#ifndef WIN32
if (its_unicast.is_v4()) {
its_unicast = boost::asio::ip::address_v4::any();
} else if (its_unicast.is_v6()) {
its_unicast = boost::asio::ip::address_v6::any();
}
+#endif
boost::asio::ip::udp::endpoint ep(its_unicast, _port);
its_endpoint = std::make_shared<udp_server_endpoint_impl>(
shared_from_this(),
@@ -1445,15 +1528,6 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint(
return (its_endpoint);
}
-std::shared_ptr<endpoint> routing_manager_impl::find_local(client_t _client) {
- return routing_manager_base::find_local(_client);
-}
-
-std::shared_ptr<endpoint> routing_manager_impl::find_or_create_local(
- client_t _client) {
- return routing_manager_base::find_or_create_local(_client);
-}
-
void routing_manager_impl::remove_local(client_t _client) {
routing_manager_base::remove_local(_client);
std::forward_list<std::pair<service_t, instance_t>> services_to_release_;
@@ -1922,7 +1996,7 @@ std::chrono::milliseconds routing_manager_impl::update_routing_info(std::chrono:
for (auto &s : get_services()) {
for (auto &i : s.second) {
- if (routing_manager_base::find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
+ if (find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
continue; //don't expire local services
}
ttl_t its_ttl = i.second->get_ttl();
@@ -1964,7 +2038,7 @@ void routing_manager_impl::expire_services(const boost::asio::ip::address &_addr
for (auto &s : get_services()) {
for (auto &i : s.second) {
- if (routing_manager_base::find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
+ if (find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
continue; //don't expire local services
}
bool is_gone(false);
@@ -2016,7 +2090,7 @@ void routing_manager_impl::expire_subscriptions(const boost::asio::ip::address &
for (auto &its_endpoint : its_invalid_endpoints) {
its_eventgroup.second->remove_target(its_endpoint);
- auto target = routing_manager_base::find_local(its_service.first, its_instance.first);
+ auto target = find_local(its_service.first, its_instance.first);
if (target) {
stub_->send_unsubscribe(target, VSOMEIP_ROUTING_CLIENT, its_service.first,
its_instance.first, its_eventgroup.first, true);
@@ -2114,8 +2188,6 @@ bool routing_manager_impl::on_subscribe_accepted(service_t _service, instance_t
<< " from unknown client.";
}
- stub_->send_subscribe(routing_manager_base::find_local(_service, _instance),
- client, _service, _instance, _eventgroup, its_eventgroup->get_major(), true);
{
std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
remote_subscribers_[_service][_instance][client].insert(_target);
@@ -2156,10 +2228,30 @@ void routing_manager_impl::on_subscribe(
}
if (target_added) { // unicast or multicast
+ client_t client = VSOMEIP_ROUTING_CLIENT;
+ if (!_subscriber->is_reliable()) {
+ if (!its_eventgroup->is_multicast()) {
+ uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance);
+ auto endpoint = find_server_endpoint(unreliable_port, false);
+ if (endpoint) {
+ client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)->
+ get_client(_subscriber);
+ }
+ }
+ } else {
+ uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance);
+ auto endpoint = find_server_endpoint(reliable_port, true);
+ if (endpoint) {
+ client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)->
+ get_client(_subscriber);
+ }
+ }
+ stub_->send_subscribe(find_local(_service, _instance),
+ client, _service, _instance, _eventgroup, its_eventgroup->get_major(), true);
// send initial events if we already have a cached field (is_set)
for (auto its_event : its_eventgroup->get_events()) {
if (its_event->is_field() && its_event->is_set()) {
- its_event->notify_one(_subscriber); // unicast
+ its_event->notify_one(_subscriber, true); // TODO: use _flush parameter to send all event at once
}
}
}
@@ -2188,7 +2280,7 @@ void routing_manager_impl::on_unsubscribe(service_t _service,
its_eventgroup->remove_target(_target);
clear_remote_subscriber(_service, _instance, its_client, _target);
- stub_->send_unsubscribe(routing_manager_base::find_local(_service, _instance),
+ stub_->send_unsubscribe(find_local(_service, _instance),
its_client, _service, _instance, _eventgroup, true);
host_->on_subscription(_service, _instance, _eventgroup, its_client, false);
@@ -2565,22 +2657,38 @@ void routing_manager_impl::send_error(return_code_e _return_code,
if(!endpoint) {
return;
}
- auto remote = endpoint->get_remote();
- adr = remote.address();
- port = remote.port();
+ if (!endpoint->get_remote_address(adr)) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote address (reliable)";
+ return;
+ }
+ port = endpoint->get_remote_port();
+ if (!port) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote port (reliable)";
+ return;
+ }
} else {
auto endpoint = dynamic_cast<udp_server_endpoint_impl*>(_receiver);
if (!endpoint) {
return;
}
- auto remote = endpoint->get_remote();
- adr = remote.address();
- port = remote.port();
+ if (!endpoint->get_remote_address(adr)) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote address (unreliable)";
+ return;
+ }
+ port = endpoint->get_remote_port();
+ if (!port) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote port (unreliable)";
+ return;
+ }
}
auto its_endpoint_def =
std::make_shared<endpoint_definition>(adr, port, _receiver->is_reliable());
its_endpoint_def->set_remote_port(_receiver->get_local_port());
- send_to(its_endpoint_def, serializer_->get_data(), serializer_->get_size());
+ send_to(its_endpoint_def, serializer_->get_data(), serializer_->get_size(), true);
}
serializer_->reset();
} else {
@@ -2770,7 +2878,7 @@ routing_manager_impl::expire_subscriptions() {
clear_remote_subscriber(its_service.first, its_instance.first,
its_client, its_endpoint);
- auto target = routing_manager_base::find_local(its_service.first, its_instance.first);
+ auto target = find_local(its_service.first, its_instance.first);
if (target) {
stub_->send_unsubscribe(target, VSOMEIP_ROUTING_CLIENT, its_service.first,
its_instance.first, its_eventgroup.first, true);
@@ -2855,7 +2963,6 @@ void routing_manager_impl::clear_remote_service_info(service_t _service, instanc
bool routing_manager_impl::handle_local_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,minor_version_t _minor) {
- bool previously_offered(false);
{
std::lock_guard<std::mutex> its_lock(local_services_mutex_);
auto found_service = local_services_.find(_service);
@@ -2875,7 +2982,7 @@ bool routing_manager_impl::handle_local_offer_service(client_t _client, service_
<< std::hex << std::setfill('0') << std::setw(4) << _instance << "."
<< std::dec << static_cast<std::uint32_t>(_major) << "."
<< _minor << "] offered previously by itself.";
- previously_offered = true;
+ return false;
} else if ( its_stored_major == _major
&& its_stored_minor == _minor
&& its_stored_client != _client) {
@@ -2975,7 +3082,7 @@ bool routing_manager_impl::handle_local_offer_service(client_t _client, service_
// check if the same service instance is already offered remotely
if (routing_manager_base::offer_service(_client, _service, _instance,
- _major, _minor) || previously_offered) {
+ _major, _minor)) {
local_services_[_service][_instance] = std::make_tuple(_major,
_minor, _client);
} else {
@@ -3199,4 +3306,76 @@ void routing_manager_impl::remove_identifying_client(service_t _service, instanc
}
}
}
+
+void routing_manager_impl::send_subscribe(client_t _client, service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
+ subscription_type_e _subscription_type) {
+ (void)_subscription_type;
+ auto endpoint = find_local(_service, _instance);
+ if (endpoint) {
+ stub_->send_subscribe(endpoint, _client,
+ _service, _instance, _eventgroup, _major, false);
+ }
+}
+
+void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
+ if(discovery_) {
+ switch (_routing_state) {
+ case vsomeip::routing_state_e::RS_SUSPENDED:
+ {
+ // stop cycling offers for services and processing of incoming SD messages
+ discovery_->stop();
+
+ // send StopOffer messages for remotely offered services on this node
+ services_t offered_services = get_offered_services();
+ for (const auto its_service : offered_services) {
+ for (const auto its_instance : its_service.second) {
+ its_instance.second->set_ttl(0);
+ discovery_->stop_offer_service(its_service.first, its_instance.first, its_instance.second);
+ }
+ }
+
+ // determine existing subscriptions to remote services and send StopSubscribe
+ for (auto &s : get_services()) {
+ for (auto &i : s.second) {
+ if (find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
+ continue; //don't expire local services
+ }
+ std::lock_guard<std::mutex> its_lock(eventgroup_clients_mutex_);
+
+ auto found_service = eventgroup_clients_.find(s.first);
+ if (found_service != eventgroup_clients_.end()) {
+ auto found_instance = found_service->second.find(i.first);
+ if (found_instance != found_service->second.end()) {
+ for (auto its_eventgroup : found_instance->second) {
+ discovery_->unsubscribe(s.first, i.first, its_eventgroup.first, VSOMEIP_ROUTING_CLIENT);
+ std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
+ auto its_specific_service = specific_endpoint_clients_.find(s.first);
+ if (its_specific_service != specific_endpoint_clients_.end()) {
+ auto its_specific_instance = its_specific_service->second.find(i.first);
+ if (its_specific_instance != its_specific_service->second.end()) {
+ for (auto its_client : its_specific_instance->second) {
+ discovery_->unsubscribe(s.first, i.first, its_eventgroup.first, its_client);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ case vsomeip::routing_state_e::RS_RESUMED:
+ {
+ discovery_->start();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 9491544..b762a17 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -42,7 +42,8 @@ routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host) :
state_(inner_state_type_e::ST_DEREGISTERED),
sender_(0),
receiver_(0),
- register_application_timer_(io_)
+ register_application_timer_(io_),
+ logger_(logger::get())
{
}
@@ -142,6 +143,10 @@ void routing_manager_proxy::stop() {
#endif
}
+const std::shared_ptr<configuration> routing_manager_proxy::get_configuration() const {
+ return host_->get_configuration();
+}
+
bool routing_manager_proxy::offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor) {
if(!routing_manager_base::offer_service(_client, _service, _instance, _major, _minor)) {
@@ -292,24 +297,21 @@ void routing_manager_proxy::register_event(client_t _client,
_epsilon_change_func,
_is_provided);
- if (!_is_provided ||
- configuration_->is_offered_remote(_service, _instance)) {
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- send_register_event(client_, _service, _instance,
- _event, _eventgroups, _is_field, _is_provided);
- }
- event_data_t registration = {
- _service,
- _instance,
- _event,
- _is_field,
- _is_provided,
- _eventgroups
- };
- pending_event_registrations_.insert(registration);
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ send_register_event(client_, _service, _instance,
+ _event, _eventgroups, _is_field, _is_provided);
}
+ event_data_t registration = {
+ _service,
+ _instance,
+ _event,
+ _is_field,
+ _is_provided,
+ _eventgroups
+ };
+ pending_event_registrations_.insert(registration);
}
}
@@ -320,48 +322,45 @@ void routing_manager_proxy::unregister_event(client_t _client,
routing_manager_base::unregister_event(_client, _service, _instance,
_event, _is_provided);
- if (!_is_provided ||
- configuration_->is_offered_remote(_service, _instance)) {
- {
- 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;
+ {
+ 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], &_event,
- sizeof(_event));
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
- = static_cast<byte_t>(_is_provided);
+ 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], &_event,
+ sizeof(_event));
+ its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
+ = static_cast<byte_t>(_is_provided);
- {
- std::lock_guard<std::recursive_mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
}
}
- auto it = pending_event_registrations_.begin();
- while (it != pending_event_registrations_.end()) {
- if (it->service_ == _service
- && it->instance_ == _instance
- && it->event_ == _event) {
- break;
- }
- it++;
+ }
+ auto it = pending_event_registrations_.begin();
+ while (it != pending_event_registrations_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance
+ && it->event_ == _event) {
+ break;
}
- if (it != pending_event_registrations_.end())
- pending_event_registrations_.erase(it);
+ it++;
}
+ if (it != pending_event_registrations_.end())
+ pending_event_registrations_.erase(it);
}
}
@@ -529,15 +528,7 @@ void routing_manager_proxy::unsubscribe(client_t _client, service_t _service,
};
}
}
- auto it = pending_subscriptions_.begin();
- while (it != pending_subscriptions_.end()) {
- if (it->service_ == _service
- && it->instance_ == _instance) {
- break;
- }
- it++;
- }
- if (it != pending_subscriptions_.end()) pending_subscriptions_.erase(it);
+ remove_pending_subscription(_service, _instance);
}
}
@@ -545,6 +536,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
bool _flush,
bool _reliable) {
+ (void)_client;
bool is_sent(false);
bool has_remote_subscribers(false);
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
@@ -554,10 +546,9 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
service_t its_service = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SERVICE_POS_MIN],
_data[VSOMEIP_SERVICE_POS_MAX]);
- std::lock_guard<std::mutex> its_lock(send_mutex_);
client_t its_client = find_local_client(its_service, _instance);
if (its_client != VSOMEIP_ROUTING_CLIENT) {
- if (known_clients_.find(its_client) != known_clients_.end()) {
+ if (is_client_known(its_client)) {
its_target = find_or_create_local(its_client);
}
}
@@ -566,9 +557,8 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
client_t its_client = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_CLIENT_POS_MIN],
_data[VSOMEIP_CLIENT_POS_MAX]);
- std::lock_guard<std::mutex> its_lock(send_mutex_);
if (its_client != VSOMEIP_ROUTING_CLIENT) {
- if (known_clients_.find(its_client) != known_clients_.end()) {
+ if (is_client_known(its_client)) {
its_target = find_or_create_local(its_client);
}
}
@@ -582,6 +572,15 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
// notify_one
its_target = find_local(_client);
if (its_target) {
+#ifdef USE_DLT
+ uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+
+ tc::trace_header its_header;
+ if (its_header.prepare(its_target, true))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, its_data_size);
+#endif
return send_local(its_target, get_client(), _data, _size,
_instance, _flush, _reliable, VSOMEIP_SEND);
}
@@ -600,17 +599,13 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
uint8_t command = VSOMEIP_SEND;
if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- if (_client) {
+ 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 offered remote which already have remote clients subscribed to
- service_t its_service = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SERVICE_POS_MIN],
- _data[VSOMEIP_SERVICE_POS_MAX]);
- send = configuration_->is_offered_remote(its_service, _instance)
- && has_remote_subscribers;
+ // Only for services which already have remote clients subscribed to
+ send = has_remote_subscribers;
}
}
#ifdef USE_DLT
@@ -625,8 +620,9 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
}
#endif
if (send) {
- is_sent = send_local(its_target, _client, _data, _size,
- _instance, _flush, _reliable, command);
+ is_sent = send_local(its_target,
+ (command == VSOMEIP_NOTIFY_ONE ? _client : get_client()),
+ _data, _size, _instance, _flush, _reliable, command);
}
}
return (is_sent);
@@ -634,28 +630,32 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
bool routing_manager_proxy::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message) {
+ std::shared_ptr<message> _message,
+ bool _flush) {
(void)_target;
(void)_message;
+ (void)_flush;
return (false);
}
bool routing_manager_proxy::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size) {
+ const byte_t *_data, uint32_t _size,
+ bool _flush) {
(void)_target;
(void)_data;
(void)_size;
+ (void)_flush;
return (false);
}
void routing_manager_proxy::notify(
service_t _service, instance_t _instance, event_t _event,
- std::shared_ptr<payload> _payload, bool _force) {
+ std::shared_ptr<payload> _payload, bool _force, bool _flush) {
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (state_ == inner_state_type_e::ST_REGISTERED) {
- routing_manager_base::notify(_service, _instance, _event, _payload, _force);
+ routing_manager_base::notify(_service, _instance, _event, _payload, _force, _flush);
}
if (is_field(_service, _instance, _event)){
@@ -710,7 +710,8 @@ void routing_manager_proxy::release_port(uint16_t _port, bool _reliable) {
}
void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
- endpoint *_receiver, const boost::asio::ip::address &_destination) {
+ endpoint *_receiver, const boost::asio::ip::address &_destination,
+ client_t _bound_client) {
(void)_receiver;
(void)_destination;
#if 0
@@ -728,6 +729,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
eventgroup_t its_eventgroup;
major_version_t its_major;
bool is_remote_subscriber;
+ client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) {
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
@@ -736,6 +738,17 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
sizeof(its_length));
+ if (configuration_->is_security_enabled() && _bound_client != routing_host_id &&
+ _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: {
instance_t its_instance;
@@ -745,27 +758,64 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
bool its_reliable;
std::memcpy(&its_reliable, &_data[_size - sizeof(bool)],
sizeof(its_reliable));
- deserializer_->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+
+ auto a_deserializer = get_deserializer();
+ a_deserializer->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS],
its_length);
- std::shared_ptr<message> its_message(
- deserializer_->deserialize_message());
+ std::shared_ptr<message> 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);
- if(its_message->get_message_type() == message_type_e::MT_NOTIFICATION) {
+ if (utility::is_notification(its_message->get_message_type())) {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance())) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ << " isn't allow receive a notification from to service/instance "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << " respectively from client 0x" << its_client
+ << " : Skip message!";
+ return;
+ }
cache_event_payload(its_message);
+ } else if (utility::is_request(its_message->get_message_type())) {
+ if (!configuration_->is_client_allowed(its_message->get_client(),
+ its_message->get_service(), its_message->get_instance())) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << its_message->get_client()
+ << " isn't allow to send a request to service/instance "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << " : Skip message!";
+ return;
+ }
+ } else { // response
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance())) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ << " isn't allow receive a response from to service/instance "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << " respectively from client 0x" << its_client
+ << " : Skip message!";
+ return;
+ }
}
host_->on_message(its_message);
} else {
VSOMEIP_ERROR << "Routing proxy: on_message: "
<< "SomeIP-Header deserialization failed!";
}
- deserializer_->reset();
}
break;
case VSOMEIP_ROUTING_INFO:
- on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
+ if (!configuration_->is_security_enabled() ||_bound_client == routing_host_id) {
+ on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
+ } else {
+ VSOMEIP_WARNING << 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:
@@ -796,11 +846,20 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
notify_remote_initally(its_service, its_instance, its_eventgroup);
}
(void)get_remote_subscriber_count(its_service, its_instance, its_eventgroup, true);
- } else if (known_clients_.find(its_client) != known_clients_.end()) {
+ } else if (is_client_known(its_client)) {
+ if (!configuration_->is_client_allowed(its_client,
+ its_service, its_instance)) {
+ VSOMEIP_WARNING << "Security: Client " << std::hex
+ << its_client << " subscribes to service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+
// Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
+ (void) find_or_create_local(its_client);
bool subscription_accepted = host_->on_subscription(its_service, its_instance,
its_eventgroup, its_client, true);
- (void) find_or_create_local(its_client);
if (!subscription_accepted) {
send_subscribe_nack(its_client, its_service, its_instance, its_eventgroup);
} else {
@@ -813,8 +872,9 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
eventgroup_data_t subscription = { its_service, its_instance,
its_eventgroup, its_major,
subscription_type_e::SU_RELIABLE_AND_UNRELIABLE};
+ std::lock_guard<std::mutex> its_lock(pending_ingoing_subscripitons_mutex_);
pending_ingoing_subscripitons_[its_client].insert(subscription);
- }
+ }
VSOMEIP_DEBUG << "SUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
@@ -973,7 +1033,10 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
clients_to_delete.insert(client);
}
}
- known_clients_ = known_clients;
+ {
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ known_clients_ = known_clients;
+ }
// Check for services that are no longer available
for (const auto &i : old_local_services) {
@@ -1022,51 +1085,82 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<< (its_state == inner_state_type_e::ST_REGISTERED ?
" is registered." : " is deregistered.");
+
+ // inform host about its own registration state changes
+ host_->on_state(static_cast<state_type_e>(its_state));
+
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (its_state == inner_state_type_e::ST_REGISTERED) {
boost::system::error_code ec;
register_application_timer_.cancel(ec);
+ send_registered_ack();
send_pending_commands();
}
state_ = its_state;
}
- // inform host about its own registration state changes
- host_->on_state(static_cast<state_type_e>(its_state));
-
// Notify stop() call about clean deregistration
state_condition_.notify_one();
}
// Report services that are no longer available
- for (const struct service_info &sr : services_to_remove) {
+ for (const service_info &sr : services_to_remove) {
on_stop_offer_service(sr.service_id_, sr.instance_id_, sr.major_, sr.minor_);
host_->on_availability(sr.service_id_, sr.instance_id_, false, sr.major_, sr.minor_);
}
// Report services that are newly available
- for (const struct service_info &sa : services_to_add) {
- send_pending_subscriptions(sa.service_id_, sa.instance_id_, sa.major_);
+ for (const service_info &sa : services_to_add) {
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ send_pending_subscriptions(sa.service_id_, sa.instance_id_, sa.major_);
+ }
host_->on_availability(sa.service_id_, sa.instance_id_, true, sa.major_, sa.minor_);
}
- if (pending_ingoing_subscripitons_.size()) {
- for (const client_t client : known_clients_) {
- auto its_client = pending_ingoing_subscripitons_.find(client);
- if (its_client != pending_ingoing_subscripitons_.end()) {
- for (const auto subscription : its_client->second) {
- bool subscription_accepted = host_->on_subscription(subscription.service_, subscription.instance_, subscription.eventgroup_, client, true);
- (void) find_or_create_local(client);
- if (!subscription_accepted) {
- send_subscribe_nack(client, subscription.service_, subscription.instance_, subscription.eventgroup_);
- } else {
- routing_manager_base::subscribe(client, subscription.service_, subscription.instance_, subscription.eventgroup_,
- subscription.major_, subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
- send_subscribe_ack(client, subscription.service_, subscription.instance_, subscription.eventgroup_);
+ {
+ struct subscription_info {
+ service_t service_id_;
+ instance_t instance_id_;
+ eventgroup_t eventgroup_id_;
+ client_t client_id_;
+ major_version_t major_;
+ };
+ std::lock_guard<std::mutex> its_lock(pending_ingoing_subscripitons_mutex_);
+ std::forward_list<struct subscription_info> subscription_actions;
+ if (pending_ingoing_subscripitons_.size()) {
+ {
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ for (const client_t client : known_clients_) {
+ auto its_client = pending_ingoing_subscripitons_.find(client);
+ if (its_client != pending_ingoing_subscripitons_.end()) {
+ for (const auto subscription : its_client->second) {
+ subscription_actions.push_front(
+ { subscription.service_, subscription.instance_,
+ subscription.eventgroup_, client,
+ subscription.major_ });
+ }
}
}
}
- pending_ingoing_subscripitons_.erase(client);
+ for (const subscription_info &si : subscription_actions) {
+ bool subscription_accepted = host_->on_subscription(
+ si.service_id_, si.instance_id_, si.eventgroup_id_,
+ si.client_id_, true);
+ (void) find_or_create_local(si.client_id_);
+ if (!subscription_accepted) {
+ send_subscribe_nack(si.client_id_, si.service_id_,
+ si.instance_id_, si.eventgroup_id_);
+ } else {
+ routing_manager_base::subscribe(si.client_id_,
+ si.service_id_, si.instance_id_, si.eventgroup_id_,
+ si.major_,
+ subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
+ send_subscribe_ack(si.client_id_, si.service_id_,
+ si.instance_id_, si.eventgroup_id_);
+ }
+ pending_ingoing_subscripitons_.erase(si.client_id_);
+ }
}
}
@@ -1100,10 +1194,10 @@ void routing_manager_proxy::register_application() {
sizeof(uint32_t));
if (is_connected_) {
+ std::lock_guard<std::mutex> its_state_lock(state_mutex_);
std::lock_guard<std::recursive_mutex> its_lock(sender_mutex_);
if (sender_) {
{
- std::lock_guard<std::mutex> its_state_lock(state_mutex_);
state_ = inner_state_type_e::ST_REGISTERING;
}
sender_->send(its_command, sizeof(its_command));
@@ -1322,18 +1416,6 @@ void routing_manager_proxy::cache_event_payload(
}
-void routing_manager_proxy::send_pending_subscriptions(service_t _service,
- instance_t _instance, major_version_t _major) {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- 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.subscription_type_);
- }
- }
-}
-
void routing_manager_proxy::on_stop_offer_service(service_t _service,
instance_t _instance,
major_version_t _major,
@@ -1367,7 +1449,7 @@ void routing_manager_proxy::send_pending_commands() {
for (auto &i : s.second) {
for (auto &pn : i.second) {
routing_manager_base::notify(s.first, i.first,
- pn.first, pn.second->get_payload(), false);
+ pn.first, pn.second->get_payload(), false, true); // TODO: Use _flush argument to send all events at once
}
}
}
@@ -1385,6 +1467,12 @@ void routing_manager_proxy::init_receiver() {
::_unlink(its_client.str().c_str());
int port = VSOMEIP_INTERNAL_BASE_PORT + client_;
#else
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "routing_manager_proxy::init_receiver: "
+ << std::hex << "Client " << get_client() << " isn't allow"
+ << " to create a server endpoint due to credential check failed!";
+ return;
+ }
if (-1 == ::unlink(its_client.str().c_str()) && errno != ENOENT) {
VSOMEIP_ERROR << "routing_manager_proxy::init_receiver unlink failed ("
<< its_client.str() << "): "<< std::strerror(errno);
@@ -1503,4 +1591,24 @@ void routing_manager_proxy::register_application_timeout_cbk(
}
}
+void routing_manager_proxy::send_registered_ack() {
+ byte_t its_command[VSOMEIP_COMMAND_HEADER_SIZE];
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REGISTERED_ACK;
+ client_t client = get_client();
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client,
+ sizeof(client));
+ std::memset(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], 0,
+ sizeof(uint32_t));
+ {
+ std::lock_guard<std::recursive_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());
+}
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 900f266..3874a07 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -21,6 +21,11 @@
#include <vsomeip/runtime.hpp>
#include <vsomeip/error.hpp>
+#ifndef WITHOUT_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+#define SD_LISTEN_FDS_START 3
+
#include "../include/routing_manager_stub.hpp"
#include "../include/routing_manager_stub_host.hpp"
#include "../../configuration/include/configuration.hpp"
@@ -94,16 +99,18 @@ void routing_manager_stub::stop() {
watchdog_timer_.cancel();
- endpoint_->stop();
- endpoint_ = nullptr;
+ if( !is_socket_activated_) {
+ endpoint_->stop();
+ endpoint_ = nullptr;
#ifdef WIN32
- ::_unlink(endpoint_path_.c_str());
+ ::_unlink(endpoint_path_.c_str());
#else
- if (-1 == ::unlink(endpoint_path_.c_str())) {
- VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
- << endpoint_path_ << "): "<< std::strerror(errno);
- }
+ if (-1 == ::unlink(endpoint_path_.c_str())) {
+ VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
+ << endpoint_path_ << "): "<< std::strerror(errno);
+ }
#endif
+ }
if(local_receiver_) {
local_receiver_->stop();
@@ -121,6 +128,10 @@ void routing_manager_stub::stop() {
broadcast_routing_info(true);
}
+const std::shared_ptr<configuration> routing_manager_stub::get_configuration() const {
+ return configuration_;
+}
+
void routing_manager_stub::on_connect(std::shared_ptr<endpoint> _endpoint) {
(void)_endpoint;
}
@@ -146,7 +157,8 @@ void routing_manager_stub::release_port(uint16_t _port, bool _reliable) {
}
void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
- endpoint *_receiver, const boost::asio::ip::address &_destination) {
+ endpoint *_receiver, const boost::asio::ip::address &_destination,
+ client_t _bound_client) {
(void)_receiver;
(void)_destination;
#if 0
@@ -177,11 +189,23 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
bool use_exclusive_proxy(false);
subscription_type_e its_subscription_type;
bool is_remote_subscriber(false);
+ client_t its_client_from_header;
+ client_t its_target_client;
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS],
sizeof(its_client));
+ if (configuration_->is_security_enabled() && _bound_client != its_client) {
+ VSOMEIP_WARNING << "Security: 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;
+ }
+
std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
sizeof(its_size));
@@ -257,8 +281,16 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(is_remote_subscriber));
std::memcpy(&its_subscription_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
sizeof(its_subscription_type));
- host_->subscribe(its_client, its_service,
- its_instance, its_eventgroup, its_major, its_subscription_type);
+ if (configuration_->is_client_allowed(its_client,
+ its_service, its_instance)) {
+ host_->subscribe(its_client, its_service,
+ its_instance, its_eventgroup, its_major, its_subscription_type);
+ } else {
+ VSOMEIP_WARNING << "Security: Client " << std::hex
+ << its_client << " subscribes to service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip subscribe!";
+ }
break;
case VSOMEIP_UNSUBSCRIBE:
@@ -307,9 +339,33 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
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]);
std::memcpy(&its_instance, &_data[_size - sizeof(instance_t)
- sizeof(bool) - sizeof(bool)], sizeof(its_instance));
std::memcpy(&its_reliable, &_data[_size - sizeof(bool)], sizeof(its_reliable));
+ if (utility::is_request(its_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ if (!configuration_->is_client_allowed(its_client_from_header,
+ its_service, its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << its_client_from_header
+ << " isn't allow to send a request to service/instance "
+ << its_service << "/" << its_instance
+ << " : Skip message!";
+ return;
+ }
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_service,
+ its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x"
+ << get_client()
+ << " isn't allow receive a response from to service/instance "
+ << its_service << "/" << its_instance
+ << " respectively from client 0x" << its_client
+ << " : Skip message!";
+ return;
+ }
+ }
host_->on_message(its_service, its_instance, its_data, its_size, its_reliable);
break;
@@ -318,21 +374,22 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
its_service = VSOMEIP_BYTES_TO_WORD(
its_data[VSOMEIP_SERVICE_POS_MIN],
its_data[VSOMEIP_SERVICE_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(
- its_data[VSOMEIP_CLIENT_POS_MIN],
- its_data[VSOMEIP_CLIENT_POS_MAX]);
std::memcpy(&its_instance, &_data[_size - sizeof(instance_t)
- sizeof(bool) - sizeof(bool)], sizeof(its_instance));
- host_->on_notification(its_client, its_service, its_instance, its_data, its_size);
+ host_->on_notification(VSOMEIP_ROUTING_CLIENT, its_service, its_instance,
+ its_data, its_size);
break;
case VSOMEIP_NOTIFY_ONE:
its_data = &_data[VSOMEIP_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[_size - sizeof(instance_t)
- - sizeof(bool) - sizeof(bool)], sizeof(its_instance));
- host_->on_notification(its_client, its_service, its_instance, its_data, its_size, true);
+ std::memcpy(&its_instance, &_data[_size - sizeof(instance_t) -
+ sizeof(bool) - sizeof(bool) - sizeof(client_t)],
+ sizeof(its_instance));
+ std::memcpy(&its_target_client, &_data[_size - sizeof(client_t)], sizeof(client_t));
+ host_->on_notification(its_target_client, its_service, its_instance,
+ its_data, its_size, true);
break;
case VSOMEIP_REQUEST_SERVICE:
@@ -347,8 +404,15 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_minor));
std::memcpy(&use_exclusive_proxy, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
sizeof(use_exclusive_proxy));
- host_->request_service(its_client, its_service, its_instance,
- its_major, its_minor, use_exclusive_proxy);
+ if (configuration_->is_client_allowed(its_client, its_service, its_instance)) {
+ host_->request_service(its_client, its_service, its_instance,
+ its_major, its_minor, use_exclusive_proxy);
+ } else {
+ VSOMEIP_WARNING << "Security: Client " << std::hex
+ << its_client << " requests service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip request!";
+ }
break;
case VSOMEIP_RELEASE_SERVICE:
@@ -376,6 +440,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::memcpy(&is_provided,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
sizeof(is_provided));
+ if (is_provided
+ && !configuration_->is_offered_remote(its_service,
+ its_instance)) {
+ break;
+ }
for (std::size_t i = 8; i+1 < its_size; i++) {
std::memcpy(&its_eventgroup,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + i],
@@ -404,6 +473,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
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_event, is_provided);
VSOMEIP_DEBUG << "UNREGISTER EVENT("
@@ -430,6 +504,13 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< std::hex << std::setw(4) << std::setfill('0') << its_instance
<< ":is_reliable=" << its_reliable << "]";
break;
+
+ case VSOMEIP_REGISTERED_ACK:
+ VSOMEIP_DEBUG << "REGISTERED_ACK("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
+ std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
+ broadcast_routing_info(false, its_client);
+ break;
}
}
}
@@ -486,23 +567,20 @@ void routing_manager_stub::client_registration_func(void) {
on_deregister_application(r.first);
}
{
- // Inform (de)registered client first then broadcast all others
+ // Inform (de)registered client. All others will be informed after
+ // the client acknowledged its registered state!
// Don't inform client if we deregister because of an client
// endpoint error to avoid writing in an already closed socket
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
if (b != registration_type_e::DEREGISTER_ERROR_CASE) {
send_routing_info(r.first);
}
- for (auto& info : routing_info_) {
- if (info.first != VSOMEIP_ROUTING_CLIENT &&
- info.first != host_->get_client() &&
- info.first != r.first) {
- send_routing_info(info.first);
- }
- }
}
- if (b == registration_type_e::DEREGISTER
- || b == registration_type_e::DEREGISTER_ERROR_CASE) {
+ if (b != registration_type_e::REGISTER) {
+ {
+ std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
+ broadcast_routing_info(false, r.first);
+ }
host_->remove_local(r.first);
}
if (b == registration_type_e::DEREGISTER_ERROR_CASE) {
@@ -519,40 +597,73 @@ void routing_manager_stub::init_routing_endpoint() {
std::stringstream its_endpoint_path;
its_endpoint_path << VSOMEIP_BASE_PATH << VSOMEIP_ROUTING_CLIENT;
endpoint_path_ = its_endpoint_path.str();
-
-#if WIN32
- ::_unlink(endpoint_path_.c_str());
- int port = VSOMEIP_INTERNAL_BASE_PORT;
- VSOMEIP_DEBUG << "Routing endpoint at " << port;
-#else
- if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) {
- VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed ("
- << endpoint_path_ << "): "<< std::strerror(errno);
+ client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
+ if (configuration_->is_security_enabled() && get_client() != routing_host_id) {
+ VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint: "
+ << std::hex << "Client " << get_client() << " isn't allow"
+ << " to create the routing endpoint due to its not configured as the routing master!";
+ return;
}
- VSOMEIP_DEBUG << "Routing endpoint at " << endpoint_path_;
-
- const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
+ uint32_t native_socket_fd, num_fd = 0;
+#ifndef WITHOUT_SYSTEMD
+ num_fd = sd_listen_fds(0);
#endif
-
- try {
- endpoint_ =
- std::make_shared < local_server_endpoint_impl
- > (shared_from_this(),
- #ifdef WIN32
- boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
- #else
- boost::asio::local::stream_protocol::endpoint(endpoint_path_),
- #endif
- io_, configuration_->get_max_message_size_local());
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
- << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
- VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: "
- << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ if (num_fd > 1) {
+ VSOMEIP_ERROR << "Too many file descriptors received by systemd socket activation! num_fd: " << num_fd;
+ } else if (num_fd == 1) {
+ native_socket_fd = SD_LISTEN_FDS_START + 0;
+ VSOMEIP_INFO << "Using native socket created by systemd socket activation! fd: " << native_socket_fd;
+ #ifndef WIN32
+ try {
+ endpoint_ =
+ std::make_shared < local_server_endpoint_impl
+ > (shared_from_this(),
+ boost::asio::local::stream_protocol::endpoint(endpoint_path_),
+ io_, configuration_->get_max_message_size_local(), native_socket_fd);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
+ << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
+ VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: "
+ << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ }
+ #endif
+ is_socket_activated_ = true;
+ } else {
+ #if WIN32
+ ::_unlink(endpoint_path_.c_str());
+ int port = VSOMEIP_INTERNAL_BASE_PORT;
+ VSOMEIP_DEBUG << "Routing endpoint at " << port;
+ #else
+ if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) {
+ VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed ("
+ << endpoint_path_ << "): "<< std::strerror(errno);
+ }
+ VSOMEIP_DEBUG << "init_routing_endpoint Routing endpoint at " << endpoint_path_;
+
+ const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
+ #endif
+
+ try {
+ endpoint_ =
+ std::make_shared < local_server_endpoint_impl
+ > (shared_from_this(),
+ #ifdef WIN32
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
+ #else
+ boost::asio::local::stream_protocol::endpoint(endpoint_path_),
+ #endif
+ io_, configuration_->get_max_message_size_local());
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
+ << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
+ VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: "
+ << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ }
+ #ifndef WIN32
+ ::umask(previous_mask);
+ #endif
+ is_socket_activated_ = false;
}
-#ifndef WIN32
- ::umask(previous_mask);
-#endif
}
void routing_manager_stub::on_offer_service(client_t _client,
@@ -561,8 +672,17 @@ void routing_manager_stub::on_offer_service(client_t _client,
if (_client == host_->get_client()) {
create_local_receiver();
}
- routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
- broadcast_routing_info();
+
+ if (_client == VSOMEIP_ROUTING_CLIENT ||
+ configuration_->is_offer_allowed(_client, _service, _instance)) {
+ routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
+ broadcast_routing_info();
+ } else {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << _client
+ << " isn't allow to offer the following service/instance "
+ << _service << "/" << _instance
+ << " : Skip offer!";
+ }
}
void routing_manager_stub::on_stop_offer_service(client_t _client,
@@ -605,7 +725,7 @@ void routing_manager_stub::send_routing_info(client_t _client, bool _empty) {
its_command.push_back(VSOMEIP_ROUTING_INFO);
// Sender client
- client_t client = 0x0;
+ 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]);
@@ -705,9 +825,11 @@ void routing_manager_stub::send_routing_info(client_t _client, bool _empty) {
}
}
-void routing_manager_stub::broadcast_routing_info(bool _empty) {
+void routing_manager_stub::broadcast_routing_info(bool _empty, client_t _ignore) {
for (auto& info : routing_info_) {
- if (info.first != VSOMEIP_ROUTING_CLIENT && info.first != host_->get_client()) {
+ if (info.first != VSOMEIP_ROUTING_CLIENT &&
+ info.first != host_->get_client() &&
+ info.first != _ignore) {
send_routing_info(info.first, _empty);
}
}
@@ -788,8 +910,9 @@ void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _servi
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], &_client,
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
sizeof(_client));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
sizeof(its_size));
@@ -813,8 +936,9 @@ void routing_manager_stub::send_subscribe_nack(client_t _client, service_t _serv
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], &_client,
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
sizeof(_client));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
sizeof(its_size));
@@ -929,6 +1053,12 @@ void routing_manager_stub::create_local_receiver() {
::_unlink(local_receiver_path_.c_str());
int port = VSOMEIP_INTERNAL_BASE_PORT;
#else
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver: "
+ << std::hex << "Client " << get_client() << " isn't allow"
+ << " to create a server endpoint due to credential check failed!";
+ return;
+ }
if (-1 == ::unlink(local_receiver_path_.c_str()) && errno != ENOENT) {
VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver unlink (local receiver) failed ("
<< local_receiver_path_ << "): "<< std::strerror(errno);
@@ -936,7 +1066,6 @@ void routing_manager_stub::create_local_receiver() {
const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
#endif
-
try {
local_receiver_ =
std::make_shared < local_server_endpoint_impl
@@ -1115,4 +1244,14 @@ void routing_manager_stub::deregister_erroneous_client(client_t _client) {
client_registration_condition_.notify_one();
}
+client_t routing_manager_stub::get_client() const {
+ return host_->get_client();
+}
+
+#ifndef WIN32
+bool routing_manager_stub::check_credentials(client_t _client, uid_t _uid, gid_t _gid) {
+ return configuration_->check_credentials(_client, _uid, _gid);
+}
+#endif
+
} // namespace vsomeip
diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp
index fcf535e..f8db130 100644
--- a/implementation/routing/src/serviceinfo.cpp
+++ b/implementation/routing/src/serviceinfo.cpp
@@ -15,7 +15,8 @@ serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor,
ttl_(0),
reliable_(nullptr),
unreliable_(nullptr),
- is_local_(_is_local) {
+ is_local_(_is_local),
+ is_in_mainphase_(false) {
std::chrono::seconds ttl = static_cast<std::chrono::seconds> (_ttl);
ttl_ = std::chrono::duration_cast<std::chrono::milliseconds>(ttl);
@@ -87,5 +88,13 @@ bool serviceinfo::is_local() const {
return is_local_;
}
+bool serviceinfo::is_in_mainphase() const {
+ return is_in_mainphase_;
+}
+
+void serviceinfo::set_is_in_mainphase(bool _in_mainphase) {
+ is_in_mainphase_ = _in_mainphase;
+}
+
} // namespace vsomeip