diff options
author | Dirk Huss <dirk_huss@mentor.com> | 2015-12-09 14:50:34 +0100 |
---|---|---|
committer | Dirk Huss <dirk_huss@mentor.com> | 2015-12-09 14:50:34 +0100 |
commit | 2b7442a4c2452f8f3bd9e0f09f829478256d39af (patch) | |
tree | e857c964b2a0a5d7e539efa00d17e6dccec5990a /implementation/routing | |
parent | 78be04b467566633318a277ccd2d968c1c4e46bf (diff) | |
download | vSomeIP-2b7442a4c2452f8f3bd9e0f09f829478256d39af.tar.gz |
vSomeIP 2.0.12.0.1
Diffstat (limited to 'implementation/routing')
9 files changed, 180 insertions, 49 deletions
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp index 89153ad..2036636 100644 --- a/implementation/routing/include/event.hpp +++ b/implementation/routing/include/event.hpp @@ -35,6 +35,9 @@ public: instance_t get_instance() const; void set_instance(instance_t _instance); + major_version_t get_version() const; + void set_version(major_version_t _major); + event_t get_event() const; void set_event(event_t _event); @@ -51,9 +54,6 @@ public: bool is_field() const; void set_field(bool _is_field); - bool is_reliable() const; - void set_reliable(bool _is_reliable); - bool is_provided() const; void set_provided(bool _is_provided); diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp index 7791add..2642677 100644 --- a/implementation/routing/include/routing_manager.hpp +++ b/implementation/routing/include/routing_manager.hpp @@ -50,7 +50,7 @@ public: virtual void subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major) = 0; + major_version_t _major, subscription_type_e _subscription_type) = 0; virtual void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; @@ -68,7 +68,7 @@ public: const byte_t *_data, uint32_t _size) = 0; virtual void register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, std::set<eventgroup_t> _eventgroups, + event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field, bool _is_provided) = 0; virtual void unregister_event(client_t _client, service_t _service, instance_t _instance, diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp index a0d692c..9741f3e 100644 --- a/implementation/routing/include/routing_manager_impl.hpp +++ b/implementation/routing/include/routing_manager_impl.hpp @@ -76,7 +76,8 @@ public: instance_t _instance); void subscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major); + eventgroup_t _eventgroup, major_version_t _major, + subscription_type_e _subscription_type); void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); @@ -94,7 +95,7 @@ public: void register_event(client_t _client, service_t _service, instance_t _instance, event_t _event, - std::set<eventgroup_t> _eventgroups, + const std::set<eventgroup_t> &_eventgroups, bool _is_field, bool _is_provided); void unregister_event(client_t _client, service_t _service, @@ -158,6 +159,9 @@ public: void on_subscribe_ack(service_t _service, instance_t _instance, const boost::asio::ip::address &_address, uint16_t _port); + void expire_subscriptions(const boost::asio::ip::address &_address); + void expire_services(const boost::asio::ip::address &_address); + private: bool deliver_message(const byte_t *_data, length_t _length, instance_t _instance, bool _reliable); diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp index 852ca19..0577597 100644 --- a/implementation/routing/include/routing_manager_proxy.hpp +++ b/implementation/routing/include/routing_manager_proxy.hpp @@ -13,6 +13,7 @@ #include "routing_manager.hpp" #include "../../endpoints/include/endpoint_host.hpp" +#include <vsomeip/enumeration_types.hpp> namespace vsomeip { @@ -52,7 +53,8 @@ public: instance_t _instance); void subscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major); + eventgroup_t _eventgroup, major_version_t _major, + subscription_type_e _subscription_type); void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); @@ -70,7 +72,7 @@ public: void register_event(client_t _client, service_t _service, instance_t _instance, event_t _event, - std::set<eventgroup_t> _eventgroups, + const std::set<eventgroup_t> &_eventgroups, bool _is_field, bool _is_provided); void unregister_event(client_t _client, service_t _service, @@ -112,11 +114,11 @@ private: minor_version_t _minor, bool _use_exclusive_proxy); void send_register_event(client_t _client, service_t _service, instance_t _instance, event_t _event, - std::set<eventgroup_t> _eventgroup, + const std::set<eventgroup_t> &_eventgroup, bool _is_field, bool _is_provided); void send_subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major); + major_version_t _major, subscription_type_e _subscription_type); bool is_field(service_t _service, instance_t _instance, event_t _event) const; @@ -139,6 +141,7 @@ private: std::map<client_t, std::shared_ptr<endpoint> > local_endpoints_; std::map<service_t, std::map<instance_t, client_t> > local_services_; + std::map<service_t, std::map<instance_t, major_version_t> > service_versions_; std::mutex local_services_mutex_; struct service_data_t { @@ -181,6 +184,7 @@ private: instance_t instance_; eventgroup_t eventgroup_; major_version_t major_; + subscription_type_e subscription_type_; bool operator<(const eventgroup_data_t &_other) const { return (service_ < _other.service_ diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp index f25eef2..d56f2d3 100644 --- a/implementation/routing/include/routing_manager_stub_host.hpp +++ b/implementation/routing/include/routing_manager_stub_host.hpp @@ -31,7 +31,7 @@ public: virtual void register_event(client_t _client, service_t _service, instance_t _instance, event_t _event, - std::set<eventgroup_t> _eventgroups, + const std::set<eventgroup_t> &_eventgroups, bool _is_field, bool _is_provided) = 0; virtual void unregister_event(client_t _client, service_t _service, @@ -39,7 +39,7 @@ public: virtual void subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major) = 0; + major_version_t _major, subscription_type_e _subscription_type) = 0; virtual void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp index 4572632..b553415 100644 --- a/implementation/routing/src/event.cpp +++ b/implementation/routing/src/event.cpp @@ -41,6 +41,14 @@ void event::set_instance(instance_t _instance) { message_->set_instance(_instance); } +major_version_t event::get_version() const { + return message_->get_interface_version(); +} + +void event::set_version(major_version_t _major) { + message_->set_interface_version(_major); +} + event_t event::get_event() const { return (message_->get_method()); } @@ -65,14 +73,6 @@ void event::set_provided(bool _is_provided) { is_provided_ = _is_provided; } -bool event::is_reliable() const { - return message_->is_reliable(); -} - -void event::set_reliable(bool _is_reliable) { - message_->set_reliable(_is_reliable); -} - const std::shared_ptr<payload> event::get_payload() const { return (message_->get_payload()); } diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp index ff1c67e..13ec332 100644 --- a/implementation/routing/src/routing_manager_impl.cpp +++ b/implementation/routing/src/routing_manager_impl.cpp @@ -175,7 +175,8 @@ void routing_manager_impl::release_service(client_t _client, service_t _service, } void routing_manager_impl::subscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, + subscription_type_e _subscription_type) { if (discovery_) { if (!host_->on_subscription(_service, _instance, _eventgroup, _client, true)) { VSOMEIP_INFO << "Subscription request for eventgroup " << _eventgroup @@ -192,7 +193,7 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service, subscriber = _client; } discovery_->subscribe(_service, _instance, _eventgroup, - _major, DEFAULT_TTL, subscriber); + _major, DEFAULT_TTL, subscriber, _subscription_type); } else { send_subscribe(_client, _service, _instance, _eventgroup, _major); @@ -323,7 +324,6 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, } else { std::shared_ptr<serviceinfo> its_info(find_service(its_service, _instance)); if (its_info) { - its_target = its_info->get_endpoint(_reliable); if (is_notification && !is_service_discovery) { method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); @@ -347,19 +347,26 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, send_local(its_local_target, _client, _data, _size, _instance, _flush, _reliable); } } - - if (its_target) { + // we need both endpoints as clients can subscribe to events via TCP and UDP + std::shared_ptr<endpoint> its_unreliable_target = its_info->get_endpoint(false); + std::shared_ptr<endpoint> its_reliable_target = its_info->get_endpoint(true); + if (its_unreliable_target || its_reliable_target) { // remote auto its_eventgroup = find_eventgroup(its_service, _instance, its_group); if (its_eventgroup) { for (auto its_remote : its_eventgroup->get_targets()) { - its_target->send_to(its_remote, _data, _size); + if(its_remote->is_reliable() && its_reliable_target) { + its_reliable_target->send_to(its_remote, _data, _size); + } else if(its_unreliable_target) { + its_unreliable_target->send_to(its_remote, _data, _size); + } } } } } } } else { + its_target = its_info->get_endpoint(_reliable); if (its_target) { is_sent = its_target->send(_data, _size, _flush); } else { @@ -437,7 +444,7 @@ bool routing_manager_impl::send_to( void routing_manager_impl::register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, std::set<eventgroup_t> _eventgroups, + event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field, bool _is_provided) { (void)_client; @@ -461,12 +468,18 @@ void routing_manager_impl::register_event(client_t _client, its_event->set_event(_event); its_event->set_field(_is_field); its_event->set_provided(_is_provided); + std::shared_ptr<serviceinfo> its_service = find_service(_service, _instance); + if (its_service) { + its_event->set_version(its_service->get_major()); + } if (_eventgroups.size() == 0) { // No eventgroup specified - _eventgroups.insert(_event); + std::set<eventgroup_t> its_eventgroups; + its_eventgroups.insert(_event); + its_event->set_eventgroups(its_eventgroups); + } else { + its_event->set_eventgroups(_eventgroups); } - - its_event->set_eventgroups(_eventgroups); } its_event->add_ref(); @@ -578,8 +591,14 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); if (its_service == VSOMEIP_SD_SERVICE) { - if (discovery_) - discovery_->on_message(_data, _size); + if (discovery_) { + boost::asio::ip::address its_address; + if (_receiver->get_remote_address(its_address)) { + discovery_->on_message(_data, _size, its_address); + } else { + VSOMEIP_ERROR << "Ignored SD message from unknown address."; + } + } } else { instance_t its_instance = find_instance(its_service, _receiver); return_code_e return_code = check_error(_data, _size, its_instance); @@ -661,11 +680,13 @@ void routing_manager_impl::on_message( its_session = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_SESSION_POS_MIN], _data[VSOMEIP_SESSION_POS_MAX]); + major_version_t its_version = _data[VSOMEIP_INTERFACE_VERSION_POS]; its_response->set_service(_service); its_response->set_method(its_method); its_response->set_client(its_client); its_response->set_session(its_session); + its_response->set_interface_version(its_version); if (its_event->is_field()) { its_response->set_message_type( @@ -677,10 +698,13 @@ void routing_manager_impl::on_message( std::lock_guard<std::mutex> its_lock(serialize_mutex_); if (serializer_->serialize(its_response.get())) { + // always pass reliable = false, but this won't be used, as + // the event is sent out via TCP or UDP dependent on which + // L4Proto the subscriber passed in the endpoint option in + // its subscription to the eventgroup send(its_client, serializer_->get_data(), serializer_->get_size(), - _instance, - true, its_event->is_reliable()); + _instance, true, false); } else { VSOMEIP_ERROR << "routing_manager_impl::on_message: serialization error."; } @@ -1167,7 +1191,9 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( configuration_->get_message_size_reliable( its_unicast.to_string(), _port)); if (configuration_->has_enabled_magic_cookies( - its_unicast.to_string(), _port)) { + its_unicast.to_string(), _port) || + configuration_->has_enabled_magic_cookies( + "local", _port)) { its_endpoint->enable_magic_cookies(); } } else { @@ -1637,6 +1663,65 @@ ttl_t routing_manager_impl::update_routing_info(ttl_t _elapsed) { return its_smallest_ttl; } +void routing_manager_impl::expire_services(const boost::asio::ip::address &_address) { + std::map<service_t, + std::map<instance_t, + std::pair<bool, bool> > > its_expired_offers; + + for (auto &s : services_) { + for (auto &i : s.second) { + bool is_gone(false); + boost::asio::ip::address its_address; + std::shared_ptr<endpoint> its_endpoint = i.second->get_endpoint(true); + if (its_endpoint) { + if (its_endpoint->get_remote_address(its_address)) { + is_gone = (its_address == _address); + } + } else { + its_endpoint = i.second->get_endpoint(false); + if (its_endpoint) { + if (its_endpoint->get_remote_address(its_address)) { + is_gone = (its_address == _address); + } + } + } + + if (is_gone) { + if (discovery_) + discovery_->unsubscribe_all(s.first, i.first); + its_expired_offers[s.first][i.first] = { + i.second->get_endpoint(true) != nullptr, + i.second->get_endpoint(false) != nullptr + }; + } + } + } + + for (auto &s : its_expired_offers) { + for (auto &i : s.second) { + del_routing_info(s.first, i.first, i.second.first, i.second.second); + } + } +} + +void routing_manager_impl::expire_subscriptions(const boost::asio::ip::address &_address) { + for (auto &its_service : eventgroups_) { + for (auto &its_instance : its_service.second) { + for (auto &its_eventgroup : its_instance.second) { + std::set<std::shared_ptr<endpoint_definition>> its_invalid_targets; + for (auto &its_target : its_eventgroup.second->get_targets()) { + if (its_target->get_address() == _address) + its_invalid_targets.insert(its_target); + } + + for (auto &its_target : its_invalid_targets) { + its_eventgroup.second->remove_target(its_target); + } + } + } + } +} + void routing_manager_impl::init_routing_info() { VSOMEIP_INFO<< "Service Discovery disabled. Using static routing information."; for (auto i : configuration_->get_remote_services()) { @@ -2089,10 +2174,17 @@ return_code_e routing_manager_impl::check_error(const byte_t *_data, length_t _s << std::hex << its_service; return return_code_e::E_UNKNOWN_SERVICE; } - // TODO: Check interface version handling?! - if (_data[VSOMEIP_INTERFACE_VERSION_POS] != 0x0) { - // Interface is currently set to zero always! - return return_code_e::E_WRONG_INTERFACE_VERSION; + // Check interface version of service/instance + auto found_service = services_.find(its_service); + if (found_service != services_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto its_info = found_instance->second; + major_version_t its_version = _data[VSOMEIP_INTERFACE_VERSION_POS]; + if (its_version != its_info->get_major()) { + return return_code_e::E_WRONG_INTERFACE_VERSION; + } + } } if (_data[VSOMEIP_RETURN_CODE_POS] != static_cast<byte_t> (return_code_e::E_OK)) { // Request calls must to have return code E_OK set! diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp index cbf14ff..45346bf 100644 --- a/implementation/routing/src/routing_manager_proxy.cpp +++ b/implementation/routing/src/routing_manager_proxy.cpp @@ -113,6 +113,7 @@ void routing_manager_proxy::stop() { void routing_manager_proxy::offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { + service_versions_[_service][_instance] = _major; if (is_connected_) { send_offer_service(_client, _service, _instance, _major, _minor); } else { @@ -151,6 +152,14 @@ void routing_manager_proxy::stop_offer_service(client_t _client, service_t _service, instance_t _instance) { (void)_client; + auto its_service = service_versions_.find(_service); + if (its_service != service_versions_.end()) { + auto its_instance = its_service->second.find(_instance); + if (its_instance != its_service->second.end()) { + its_service->second.clear(); + } + } + if (is_connected_) { byte_t its_command[VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE @@ -198,7 +207,7 @@ void routing_manager_proxy::release_service(client_t _client, void routing_manager_proxy::register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, std::set<eventgroup_t> _eventgroups, + event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field, bool _is_provided) { (void)_client; @@ -273,18 +282,22 @@ bool routing_manager_proxy::is_field(service_t _service, instance_t _instance, } void routing_manager_proxy::subscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, + subscription_type_e _subscription_type) { if (is_connected_) { - send_subscribe(_client, _service, _instance, _eventgroup, _major); + send_subscribe(_client, _service, _instance, _eventgroup, _major, + _subscription_type); } else { - eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major }; + eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major, + _subscription_type}; std::lock_guard<std::mutex> its_lock(pending_mutex_); pending_subscriptions_.insert(subscription); } } void routing_manager_proxy::send_subscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, + subscription_type_e _subscription_type) { (void)_client; byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; @@ -303,6 +316,8 @@ void routing_manager_proxy::send_subscribe(client_t _client, service_t _service, std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, sizeof(_eventgroup)); its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major; + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_subscription_type, + sizeof(_subscription_type)); sender_->send(its_command, sizeof(its_command)); } @@ -436,6 +451,13 @@ void routing_manager_proxy::notify( its_notification->set_instance(_instance); its_notification->set_method(_event); its_notification->set_payload(_payload); + auto its_service = service_versions_.find(_service); + if (its_service != service_versions_.end()) { + auto its_instance = its_service->second.find(_instance); + if (its_instance != its_service->second.end()) { + its_notification->set_interface_version(its_instance->second); + } + } if (is_connected_) { send(VSOMEIP_ROUTING_CLIENT, its_notification, true); } else if (is_field(_service, _instance, _event)) { @@ -454,6 +476,13 @@ void routing_manager_proxy::notify_one(service_t _service, instance_t _instance, its_notification->set_method(_event); its_notification->set_payload(_payload); its_notification->set_client(_client); + auto its_service = service_versions_.find(_service); + if (its_service != service_versions_.end()) { + auto its_instance = its_service->second.find(_instance); + if (its_instance != its_service->second.end()) { + its_notification->set_interface_version(its_instance->second); + } + } send(VSOMEIP_ROUTING_CLIENT, its_notification, true); } @@ -713,7 +742,7 @@ void routing_manager_proxy::register_application() { std::lock_guard<std::mutex> its_lock(pending_mutex_); for (auto &ps : pending_subscriptions_) send_subscribe(client_, ps.service_, ps.instance_, - ps.eventgroup_, ps.major_); + ps.eventgroup_, ps.major_, ps.subscription_type_); pending_offers_.clear(); pending_requests_.clear(); @@ -850,7 +879,7 @@ void routing_manager_proxy::send_request_service(client_t _client, service_t _se void routing_manager_proxy::send_register_event(client_t _client, service_t _service, instance_t _instance, - event_t _event, std::set<eventgroup_t> _eventgroups, + event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field, bool _is_provided) { if (is_connected_) { uint32_t its_eventgroups_size = uint32_t(_eventgroups.size() * sizeof(eventgroup_t)); diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp index dfca76f..7f8aad8 100644 --- a/implementation/routing/src/routing_manager_stub.cpp +++ b/implementation/routing/src/routing_manager_stub.cpp @@ -124,6 +124,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, uint32_t its_size; bool its_reliable(false); bool use_exclusive_proxy(false); + subscription_type_e its_subscription_type; its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], @@ -186,9 +187,10 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_eventgroup)); std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], sizeof(its_major)); - + std::memcpy(&its_subscription_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], + sizeof(its_subscription_type)); host_->subscribe(its_client, its_service, - its_instance, its_eventgroup, its_major); + its_instance, its_eventgroup, its_major, its_subscription_type); break; case VSOMEIP_UNSUBSCRIBE: |