diff options
Diffstat (limited to 'implementation/routing/src')
-rw-r--r-- | implementation/routing/src/event.cpp | 33 | ||||
-rw-r--r-- | implementation/routing/src/routing_manager_base.cpp | 84 | ||||
-rw-r--r-- | implementation/routing/src/routing_manager_impl.cpp | 301 | ||||
-rw-r--r-- | implementation/routing/src/routing_manager_proxy.cpp | 358 | ||||
-rw-r--r-- | implementation/routing/src/routing_manager_stub.cpp | 275 | ||||
-rw-r--r-- | implementation/routing/src/serviceinfo.cpp | 11 |
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 |