diff options
Diffstat (limited to 'implementation')
89 files changed, 5953 insertions, 3626 deletions
diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp new file mode 100644 index 0000000..2f106ee --- /dev/null +++ b/implementation/configuration/include/configuration.hpp @@ -0,0 +1,89 @@ +// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_CONFIGURATION_HPP +#define VSOMEIP_CONFIGURATION_HPP + +#include <map> +#include <memory> +#include <set> +#include <string> + +#include <boost/asio/ip/address.hpp> +#include <boost/log/trivial.hpp> + +#include <vsomeip/export.hpp> +#include <vsomeip/defines.hpp> +#include <vsomeip/primitive_types.hpp> + +#include "internal.hpp" + +namespace vsomeip { + +class event; + +class VSOMEIP_EXPORT configuration { +public: + static std::shared_ptr<configuration> get( + const std::set<std::string> &_input = std::set<std::string>()); + static void reset(); + virtual ~configuration() {} + + virtual const boost::asio::ip::address & get_unicast_address() const = 0; + virtual bool is_v4() const = 0; + virtual bool is_v6() const = 0; + + virtual bool has_console_log() const = 0; + virtual bool has_file_log() const = 0; + virtual bool has_dlt_log() const = 0; + virtual const std::string & get_logfile() const = 0; + virtual boost::log::trivial::severity_level get_loglevel() const = 0; + + virtual const std::string & get_routing_host() const = 0; + + virtual std::string get_unicast_address(service_t _service, + instance_t _instance) const = 0; + virtual std::string get_multicast_address(service_t _service, + instance_t _instance) const = 0; + virtual uint16_t get_multicast_port(service_t _service, + instance_t _instance) const = 0; + virtual uint16_t get_multicast_group(service_t _service, + instance_t _instance) const = 0; + virtual uint16_t get_reliable_port(service_t _service, + instance_t _instance) const = 0; + virtual bool is_someip(service_t _service, instance_t _instance) const = 0; + virtual bool has_enabled_magic_cookies(std::string _address, + uint16_t _port) const = 0; + virtual uint16_t get_unreliable_port(service_t _service, + instance_t _instance) const = 0; + + virtual std::set<std::pair<service_t, instance_t> > get_remote_services() const = 0; + + virtual client_t get_id(const std::string &_name) const = 0; + virtual std::size_t get_num_dispatchers(const std::string &_name) const = 0; + + virtual std::uint32_t get_max_message_size_local() const = 0; + virtual std::uint32_t get_message_size_reliable(const std::string& _address, + std::uint16_t _port) const = 0; + + // Service Discovery configuration + virtual bool is_sd_enabled() const = 0; + + virtual const std::string & get_sd_multicast() const = 0; + virtual uint16_t get_sd_port() const = 0; + virtual const std::string & get_sd_protocol() const = 0; + + virtual int32_t get_sd_initial_delay_min() const = 0; + virtual int32_t get_sd_initial_delay_max() const = 0; + virtual int32_t get_sd_repetitions_base_delay() const = 0; + virtual uint8_t get_sd_repetitions_max() const = 0; + virtual ttl_t get_sd_ttl() const = 0; + virtual int32_t get_sd_cyclic_offer_delay() const = 0; + virtual int32_t get_sd_request_response_delay() const = 0; +}; + +} // namespace vsomeip + +#endif // VSOMEIP_CONFIGURATION_HPP diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp index 8a57633..04f4a22 100644 --- a/implementation/configuration/include/configuration_impl.hpp +++ b/implementation/configuration/include/configuration_impl.hpp @@ -9,10 +9,11 @@ #include <map> #include <memory> #include <mutex> +#include <vector> #include <boost/property_tree/ptree.hpp> -#include <vsomeip/configuration.hpp> +#include "configuration.hpp" namespace vsomeip { namespace cfg { @@ -20,16 +21,20 @@ namespace cfg { struct service; struct servicegroup; -class configuration_impl: public configuration { +class VSOMEIP_EXPORT configuration_impl: public configuration { public: - static configuration * get(const std::string &_path); + static std::shared_ptr<configuration> get( + const std::set<std::string> &_input); + static void reset(); configuration_impl(); + configuration_impl(const configuration_impl &_cfg); virtual ~configuration_impl(); - bool load(const std::string &_path); + void load(const boost::property_tree::ptree &_tree); + void load_log(const std::vector<boost::property_tree::ptree> &_trees); - const boost::asio::ip::address & get_unicast() const; + const boost::asio::ip::address & get_unicast_address() const; bool is_v4() const; bool is_v6() const; @@ -39,18 +44,7 @@ public: const std::string & get_logfile() const; boost::log::trivial::severity_level get_loglevel() const; - std::string get_group(service_t _service, instance_t _instance) const; - std::set<std::string> get_servicegroups() const; - - bool is_local_servicegroup(const std::string &_name) const; - int32_t get_min_initial_delay(const std::string &_name) const; - int32_t get_max_initial_delay(const std::string &_name) const; - int32_t get_repetition_base_delay(const std::string &_name) const; - uint8_t get_repetition_max(const std::string &_name) const; - int32_t get_cyclic_offer_delay(const std::string &_name) const; - int32_t get_cyclic_request_delay(const std::string &_name) const; - - std::string get_unicast(service_t _service, instance_t _instance) const; + std::string get_unicast_address(service_t _service, instance_t _instance) const; std::string get_multicast_address(service_t _service, instance_t _instance) const; uint16_t get_multicast_port(service_t _service, @@ -63,56 +57,65 @@ public: uint16_t get_unreliable_port(service_t _service, instance_t _instance) const; - const std::string & get_routing_host() const; + bool is_someip(service_t _service, instance_t _instance) const; - bool is_service_discovery_enabled() const; - const std::string & get_service_discovery_multicast() const; - uint16_t get_service_discovery_port() const; - const std::string & get_service_discovery_protocol() const; + const std::string & get_routing_host() const; client_t get_id(const std::string &_name) const; std::size_t get_num_dispatchers(const std::string &_name) const; std::set<std::pair<service_t, instance_t> > get_remote_services() const; - std::map<service_t, - std::map<instance_t, - std::map<eventgroup_t, - std::set<event_t> > > > get_eventgroups() const; - std::map<service_t, - std::map<instance_t, - std::set<event_t> > > get_events() const; - void set_event(std::shared_ptr<event> &_event) const; + std::uint32_t get_max_message_size_local() const; + std::uint32_t get_message_size_reliable(const std::string& _address, + std::uint16_t _port) const; + + // Service Discovery configuration + bool is_sd_enabled() const; + + const std::string & get_sd_multicast() const; + uint16_t get_sd_port() const; + const std::string & get_sd_protocol() const; + + int32_t get_sd_initial_delay_min() const; + int32_t get_sd_initial_delay_max() const; + int32_t get_sd_repetitions_base_delay() const; + uint8_t get_sd_repetitions_max() const; + ttl_t get_sd_ttl() const; + int32_t get_sd_cyclic_offer_delay() const; + int32_t get_sd_request_response_delay() const; private: - bool get_someip_configuration(boost::property_tree::ptree &_tree); - bool get_logging_configuration(boost::property_tree::ptree &_tree); - bool get_services_configuration(boost::property_tree::ptree &_tree); - bool get_routing_configuration(boost::property_tree::ptree &_tree); - bool get_service_discovery_configuration( - boost::property_tree::ptree &_tree); - bool get_applications_configuration(boost::property_tree::ptree &_tree); - - bool get_servicegroup_configuration( - const boost::property_tree::ptree &_tree); - bool get_delays_configuration(std::shared_ptr<servicegroup> &_group, + void get_logging_configuration(const boost::property_tree::ptree &_tree); + + void get_someip_configuration(const boost::property_tree::ptree &_tree); + void get_services_configuration(const boost::property_tree::ptree &_tree); + void get_payload_sizes_configuration(const boost::property_tree::ptree &_tree); + void get_routing_configuration(const boost::property_tree::ptree &_tree); + void get_service_discovery_configuration( const boost::property_tree::ptree &_tree); - bool get_service_configuration(std::shared_ptr<servicegroup> &_group, + void get_applications_configuration(const boost::property_tree::ptree &_tree); + + void get_servicegroup_configuration( const boost::property_tree::ptree &_tree); - bool get_event_configuration(std::shared_ptr<service> &_service, + void get_delays_configuration(const boost::property_tree::ptree &_tree); + void get_service_configuration(const boost::property_tree::ptree &_tree, + const std::string &_unicast_address); + void get_event_configuration(std::shared_ptr<service> &_service, const boost::property_tree::ptree &_tree); - bool get_eventgroup_configuration(std::shared_ptr<service> &_service, + void get_eventgroup_configuration(std::shared_ptr<service> &_service, const boost::property_tree::ptree &_tree); - bool get_application_configuration( + void get_application_configuration( const boost::property_tree::ptree &_tree); servicegroup * find_servicegroup(const std::string &_name) const; service * find_service(service_t _service, instance_t _instance) const; private: - static std::map<std::string, configuration *> the_configurations; + static std::shared_ptr<configuration_impl> the_configuration; static std::mutex mutex_; +protected: // Configuration data boost::asio::ip::address unicast_; @@ -122,21 +125,31 @@ private: std::string logfile_; boost::log::trivial::severity_level loglevel_; - std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_; + std::map<std::string, std::pair<client_t, std::size_t>> applications_; + std::map<service_t, std::map<instance_t, std::shared_ptr<service> > > services_; std::string routing_host_; - bool is_service_discovery_enabled_; - std::string service_discovery_multicast_; - uint16_t service_discovery_port_; - std::string service_discovery_protocol_; + bool is_sd_enabled_; + std::string sd_protocol_; + std::string sd_multicast_; + uint16_t sd_port_; - std::map<std::string, std::pair<client_t, std::size_t>> applications_; + int32_t sd_initial_delay_min_; + int32_t sd_initial_delay_max_; + int32_t sd_repetitions_base_delay_; + uint8_t sd_repetitions_max_; + ttl_t sd_ttl_; + int32_t sd_cyclic_offer_delay_; + int32_t sd_request_response_delay_; std::map<std::string, std::set<uint16_t> > magic_cookies_; + + std::map<std::string, std::map<std::uint16_t, std::uint32_t>> message_sizes_; + std::uint32_t max_configured_message_size_; }; } // namespace cfg diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in index 4038b55..3700a89 100644 --- a/implementation/configuration/include/internal.hpp.in +++ b/implementation/configuration/include/internal.hpp.in @@ -8,53 +8,88 @@ #include <cstdint> -namespace vsomeip { +#define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME" +#define VSOMEIP_ENV_CONFIGURATION "VSOMEIP_CONFIGURATION" +#define VSOMEIP_ENV_CONFIGURATION_MODULE "VSOMEIP_CONFIGURATION_MODULE" + +#define VSOMEIP_DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json" +#define VSOMEIP_LOCAL_CONFIGURATION_FILE "./vsomeip.json" + +#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip" +#define VSOMEIP_LOCAL_CONFIGURATION_FOLDER "./vsomeip" + +#define VSOMEIP_BASE_PATH "/tmp/vsomeip-" + +#define VSOMEIP_SD_LIBRARY "libvsomeip-sd.so.@VSOMEIP_MAJOR_VERSION@" +#define VSOMEIP_SD_RUNTIME_SYMBOL VSOMEIP_SD_RUNTIME +#define VSOMEIP_SD_RUNTIME_SYMBOL_STRING "VSOMEIP_SD_RUNTIME" + +#define VSOMEIP_ROUTING "@VSOMEIP_ROUTING@" +#define VSOMEIP_ROUTING_CLIENT 0 -#define VSOMEIP_SD_LIBRARY "libvsomeip-sd.so.@VSOMEIP_MAJOR_VERSION@" -#define VSOMEIP_SD_RUNTIME_SYMBOL VSOMEIP_SD_RUNTIME -#define VSOMEIP_SD_RUNTIME_SYMBOL_STRING "VSOMEIP_SD_RUNTIME" +#ifdef WIN32 +#define VSOMEIP_INTERNAL_BASE_PORT 51234 +#endif -#define VSOMEIP_ROUTING_CLIENT 0 +#define VSOMEIP_UNICAST_ADDRESS "@VSOMEIP_UNICAST_ADDRESS@" -#define VSOMEIP_DEFAULT_CONNECT_TIMEOUT 100 -#define VSOMEIP_DEFAULT_FLUSH_TIMEOUT 1000 +#define VSOMEIP_DEFAULT_CONNECT_TIMEOUT 100 +#define VSOMEIP_DEFAULT_FLUSH_TIMEOUT 1000 -#define VSOMEIP_DEFAULT_WATCHDOG_CYCLE 1000 -#define VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT 1000 -#define VSOMEIP_DEFAULT_MAX_MISSING_PONGS 3 +#define VSOMEIP_DEFAULT_WATCHDOG_CYCLE 5000 +#define VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT 5000 +#define VSOMEIP_DEFAULT_MAX_MISSING_PONGS 3 -#define VSOMEIP_INVALID_PORT 0xFFFF +#define VSOMEIP_COMMAND_HEADER_SIZE 7 -#define VSOMEIP_COMMAND_HEADER_SIZE 7 +#define VSOMEIP_COMMAND_TYPE_POS 0 +#define VSOMEIP_COMMAND_CLIENT_POS 1 +#define VSOMEIP_COMMAND_SIZE_POS_MIN 3 +#define VSOMEIP_COMMAND_SIZE_POS_MAX 5 +#define VSOMEIP_COMMAND_PAYLOAD_POS 7 -#define VSOMEIP_COMMAND_TYPE_POS 0 -#define VSOMEIP_COMMAND_CLIENT_POS 1 -#define VSOMEIP_COMMAND_SIZE_POS_MIN 3 -#define VSOMEIP_COMMAND_SIZE_POS_MAX 5 -#define VSOMEIP_COMMAND_PAYLOAD_POS 7 +#define VSOMEIP_REGISTER_APPLICATION 0x00 +#define VSOMEIP_DEREGISTER_APPLICATION 0x01 +#define VSOMEIP_APPLICATION_LOST 0x02 +#define VSOMEIP_ROUTING_INFO 0x03 -#define VSOMEIP_REGISTER_APPLICATION 0x00 -#define VSOMEIP_DEREGISTER_APPLICATION 0x01 -#define VSOMEIP_APPLICATION_LOST 0x02 -#define VSOMEIP_ROUTING_INFO 0x03 +#define VSOMEIP_PING 0x0E +#define VSOMEIP_PONG 0x0F -#define VSOMEIP_PING 0x0E -#define VSOMEIP_PONG 0x0F +#define VSOMEIP_OFFER_SERVICE 0x10 +#define VSOMEIP_STOP_OFFER_SERVICE 0x11 +#define VSOMEIP_SUBSCRIBE 0x12 +#define VSOMEIP_UNSUBSCRIBE 0x13 +#define VSOMEIP_REQUEST_SERVICE 0x14 +#define VSOMEIP_RELEASE_SERVICE 0x15 -#define VSOMEIP_OFFER_SERVICE 0x10 -#define VSOMEIP_STOP_OFFER_SERVICE 0x11 -#define VSOMEIP_SUBSCRIBE 0x12 -#define VSOMEIP_UNSUBSCRIBE 0x13 -#define VSOMEIP_REQUEST_SERVICE 0x14 +#define VSOMEIP_SEND 0x17 +#define VSOMEIP_NOTIFY 0x18 -#define VSOMEIP_SEND 0x17 -#define VSOMEIP_SET 0x18 +#define VSOMEIP_REGISTER_EVENT 0x19 +#define VSOMEIP_UNREGISTER_EVENT 0x1A + +#define VSOMEIP_OFFER_SERVICE_COMMAND_SIZE 20 +#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 21 +#define VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE 11 +#define VSOMEIP_SUBSCRIBE_COMMAND_SIZE 18 +#define VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE 13 +#define VSOMEIP_REGISTER_EVENT_COMMAND_SIZE 15 +#define VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE 13 + +#include <mutex> + +#define VSOMEIP_DATA_ID 0x677D +#define VSOMEIP_SHM_NAME "/vsomeip" +#define VSOMEIP_DIAGNOSIS_ADDRESS @VSOMEIP_DIAGNOSIS_ADDRESS@ + +namespace vsomeip { -#define VSOMEIP_OFFER_SERVICE_COMMAND_SIZE 20 -#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 21 -#define VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE 11 -#define VSOMEIP_SUBSCRIBE_COMMAND_SIZE 18 -#define VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE 13 +struct configuration_data_t { + std::mutex mutex_; + unsigned short next_client_id_; + unsigned short ref_; +}; } // namespace vsomeip diff --git a/implementation/configuration/include/service.hpp b/implementation/configuration/include/service.hpp index 067dc41..bbe235e 100644 --- a/implementation/configuration/include/service.hpp +++ b/implementation/configuration/include/service.hpp @@ -20,6 +20,8 @@ struct service { service_t service_; instance_t instance_; + std::string unicast_address_; + uint16_t reliable_; uint16_t unreliable_; @@ -27,7 +29,7 @@ struct service { uint16_t multicast_port_; eventgroup_t multicast_group_; - bool use_magic_cookies_; + std::string protocol_; std::shared_ptr<servicegroup> group_; std::map<event_t, std::shared_ptr<event> > events_; diff --git a/implementation/configuration/include/servicegroup.hpp b/implementation/configuration/include/servicegroup.hpp deleted file mode 100644 index e44d79f..0000000 --- a/implementation/configuration/include/servicegroup.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef VSOMEIP_CFG_SERVICEGROUP_HPP -#define VSOMEIP_CFG_SERVICEGROUP_HPP - -namespace vsomeip { -namespace cfg { - -struct servicegroup { - std::string name_; // Name of the ServiceGroup - std::string unicast_; // either "local" or an IP address - - uint32_t min_initial_delay_; - uint32_t max_initial_delay_; - uint32_t repetition_base_delay_; - uint32_t cyclic_offer_delay_; - uint32_t cyclic_request_delay_; - uint8_t repetition_max_; -}; - -} // namespace cfg -} // namespace vsomeip - -#endif // VSOMEIP_CFG_SERVICEGROUP_HPP diff --git a/implementation/configuration/src/configuration.cpp b/implementation/configuration/src/configuration.cpp index 9a11b22..9bc90d4 100644 --- a/implementation/configuration/src/configuration.cpp +++ b/implementation/configuration/src/configuration.cpp @@ -7,8 +7,13 @@ namespace vsomeip { -configuration * configuration::get(const std::string &_path) { - return cfg::configuration_impl::get(_path); +std::shared_ptr<configuration> configuration::get( + const std::set<std::string> &_input) { + return cfg::configuration_impl::get(_input); +} + +void configuration::reset() { + cfg::configuration_impl::reset(); } } // namespace vsomeip diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp index 591a3dc..66a1219 100644 --- a/implementation/configuration/src/configuration_impl.cpp +++ b/implementation/configuration/src/configuration_impl.cpp @@ -4,12 +4,17 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include <fstream> -#include <map> +#include <set> #include <sstream> #define WIN32_LEAN_AND_MEAN +#if defined ( WIN32 ) +#define __func__ __FUNCTION__ +#endif + #include <boost/algorithm/string.hpp> +#include <boost/filesystem.hpp> #include <boost/foreach.hpp> #include <boost/property_tree/json_parser.hpp> @@ -18,102 +23,162 @@ #include "../include/configuration_impl.hpp" #include "../include/event.hpp" #include "../include/eventgroup.hpp" -#include "../include/servicegroup.hpp" #include "../include/service.hpp" +#include "../include/internal.hpp" #include "../../logging/include/logger_impl.hpp" #include "../../routing/include/event.hpp" #include "../../service_discovery/include/defines.hpp" +#include "../../utility/include/utility.hpp" namespace vsomeip { namespace cfg { -std::map<std::string, configuration *> configuration_impl::the_configurations; +std::shared_ptr<configuration_impl> configuration_impl::the_configuration; std::mutex configuration_impl::mutex_; -configuration * configuration_impl::get(const std::string &_path) { - configuration *its_configuration(0); - - bool is_freshly_loaded(false); - { - std::lock_guard<std::mutex> its_lock(mutex_); - - auto found_configuration = the_configurations.find(_path); - if (found_configuration != the_configurations.end()) { - its_configuration = found_configuration->second; - } else { - its_configuration = new configuration_impl; - if (its_configuration->load(_path)) { - the_configurations[_path] = its_configuration; - is_freshly_loaded = true; - } else { - delete its_configuration; - its_configuration = 0; +std::shared_ptr<configuration> configuration_impl::get( + const std::set<std::string> &_input) { + std::shared_ptr<configuration> its_configuration; + std::lock_guard<std::mutex> its_lock(mutex_); + + if (!the_configuration) { + the_configuration = std::make_shared<configuration_impl>(); + std::vector<boost::property_tree::ptree> its_tree_set; + + // Load logger configuration first + for (auto i : _input) { + if (utility::is_file(i)) { + boost::property_tree::ptree its_tree; + try { + boost::property_tree::json_parser::read_json(i, its_tree); + its_tree_set.push_back(its_tree); + } + catch (...) { + } + } else if (utility::is_folder(i)) { + boost::filesystem::path its_path(i); + for (auto j = boost::filesystem::directory_iterator(its_path); + j != boost::filesystem::directory_iterator(); + j++) { + auto its_file_path = j->path(); + if (!boost::filesystem::is_directory(its_file_path)) { + std::string its_name = its_file_path.string(); + boost::property_tree::ptree its_tree; + try { + boost::property_tree::json_parser::read_json(its_name, its_tree); + its_tree_set.push_back(its_tree); + } + catch (...) { + } + } + } } } + + // Load log configuration + the_configuration->load_log(its_tree_set); + + // Load other configuration parts + for (auto t : its_tree_set) + the_configuration->load(t); } - if (is_freshly_loaded) - logger_impl::init(_path); + return the_configuration; +} - return its_configuration; +void configuration_impl::reset() { + the_configuration.reset(); } configuration_impl::configuration_impl() : - has_console_log_(true), has_file_log_(false), has_dlt_log_(false), logfile_( - "/tmp/vsomeip.log"), loglevel_( - boost::log::trivial::severity_level::info), routing_host_( - "vsomeipd"), is_service_discovery_enabled_(false) { + has_console_log_(true), + has_file_log_(false), + has_dlt_log_(false), + logfile_("/tmp/vsomeip.log"), + loglevel_(boost::log::trivial::severity_level::info), + is_sd_enabled_(VSOMEIP_SD_DEFAULT_ENABLED), + sd_protocol_(VSOMEIP_SD_DEFAULT_PROTOCOL), + sd_multicast_(VSOMEIP_SD_DEFAULT_MULTICAST), + sd_port_(VSOMEIP_SD_DEFAULT_PORT), + sd_initial_delay_min_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN), + sd_initial_delay_max_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX), + sd_repetitions_base_delay_(VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY), + sd_repetitions_max_(VSOMEIP_SD_DEFAULT_REPETITIONS_MAX), + sd_ttl_(VSOMEIP_SD_DEFAULT_TTL), + sd_cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY), + sd_request_response_delay_(VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY), + max_configured_message_size_(0) { - unicast_ = unicast_.from_string("127.0.0.1"); + unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS); } -configuration_impl::~configuration_impl() { +configuration_impl::configuration_impl(const configuration_impl &_other) : + max_configured_message_size_(0) { + + applications_.insert(_other.applications_.begin(), _other.applications_.end()); + services_.insert(_other.services_.begin(), _other.services_.end()); + + unicast_ = _other.unicast_; + + has_console_log_ = _other.has_console_log_; + has_file_log_ = _other.has_file_log_; + has_dlt_log_ = _other.has_dlt_log_; + logfile_ = _other.logfile_; + + loglevel_ = _other.loglevel_; + + routing_host_ = _other.routing_host_; + + is_sd_enabled_ = _other.is_sd_enabled_; + sd_multicast_ = _other.sd_multicast_; + sd_port_ = _other.sd_port_; + sd_protocol_ = _other.sd_protocol_; + + sd_initial_delay_min_ = _other.sd_initial_delay_min_; + sd_initial_delay_max_ = _other.sd_initial_delay_max_; + sd_repetitions_base_delay_= _other.sd_repetitions_base_delay_; + sd_repetitions_max_ = _other.sd_repetitions_max_; + sd_ttl_ = _other.sd_ttl_; + sd_cyclic_offer_delay_= _other.sd_cyclic_offer_delay_; + sd_request_response_delay_= _other.sd_request_response_delay_; + + magic_cookies_.insert(_other.magic_cookies_.begin(), _other.magic_cookies_.end()); } -bool configuration_impl::load(const std::string &_path) { - bool is_loaded(true); - boost::property_tree::ptree its_tree; +configuration_impl::~configuration_impl() { +} +void configuration_impl::load(const boost::property_tree::ptree &_tree) { try { - boost::property_tree::json_parser::read_json(_path, its_tree); - // Read the configuration data - is_loaded = get_someip_configuration(its_tree); - is_loaded = get_logging_configuration(its_tree); - is_loaded = is_loaded && get_services_configuration(its_tree); - is_loaded = is_loaded && get_routing_configuration(its_tree); - is_loaded = is_loaded && get_service_discovery_configuration(its_tree); - is_loaded = is_loaded && get_applications_configuration(its_tree); + get_someip_configuration(_tree); + get_services_configuration(_tree); + get_payload_sizes_configuration(_tree); + get_routing_configuration(_tree); + get_service_discovery_configuration(_tree); + get_applications_configuration(_tree); } catch (std::exception &e) { - std::cerr << e.what() << std::endl; - is_loaded = false; } - - return is_loaded; } -bool configuration_impl::get_someip_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); - try { - std::string its_value = _tree.get<std::string>("unicast"); - unicast_ = unicast_.from_string(its_value); - } catch (...) { - is_loaded = false; - } - return is_loaded; +void configuration_impl::load_log(const std::vector<boost::property_tree::ptree> &_trees) { + // Read the logger configuration(s) + for (auto t : _trees) + get_logging_configuration(t); + + // Initialize logger + logger_impl::init(the_configuration); } -bool configuration_impl::get_logging_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_logging_configuration( + const boost::property_tree::ptree &_tree) { try { auto its_logging = _tree.get_child("logging"); for (auto i = its_logging.begin(); i != its_logging.end(); ++i) { std::string its_key(i->first); if (its_key == "console") { - std::string its_value(i->second.data()); - has_console_log_ = (its_value == "true"); + std::string its_value(i->second.data()); + has_console_log_ = (its_value == "true"); } else if (its_key == "file") { for (auto j : i->second) { std::string its_sub_key(j.first); @@ -129,127 +194,187 @@ bool configuration_impl::get_logging_configuration( has_dlt_log_ = (its_value == "true"); } else if (its_key == "level") { std::string its_value(i->second.data()); - loglevel_ = (its_value == "trace" ? - boost::log::trivial::severity_level::trace : - (its_value == "debug" ? - boost::log::trivial::severity_level::debug : - (its_value == "info" ? - boost::log::trivial::severity_level::info : - (its_value == "warning" ? - boost::log::trivial::severity_level::warning : - (its_value == "error" ? - boost::log::trivial::severity_level::error : - (its_value == "fatal" ? - boost::log::trivial::severity_level::fatal : - boost::log::trivial::severity_level::info)))))); + loglevel_ + = (its_value == "trace" ? + boost::log::trivial::severity_level::trace : + (its_value == "debug" ? + boost::log::trivial::severity_level::debug : + (its_value == "info" ? + boost::log::trivial::severity_level::info : + (its_value == "warning" ? + boost::log::trivial::severity_level::warning : + (its_value == "error" ? + boost::log::trivial::severity_level::error : + (its_value == "fatal" ? + boost::log::trivial::severity_level::fatal : + boost::log::trivial::severity_level::info)))))); } } } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_services_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_someip_configuration( + const boost::property_tree::ptree &_tree) { try { - auto its_services = _tree.get_child("servicegroups"); + std::string its_value = _tree.get<std::string>("unicast"); + unicast_ = unicast_.from_string(its_value); + } catch (...) { + } +} + +void configuration_impl::get_services_configuration( + const boost::property_tree::ptree &_tree) { + try { + auto its_services = _tree.get_child("services"); for (auto i = its_services.begin(); i != its_services.end(); ++i) - is_loaded = is_loaded && get_servicegroup_configuration(i->second); + get_service_configuration(i->second, ""); } catch (...) { - // This section is optional! + try { + auto its_servicegroups = _tree.get_child("servicegroups"); + for (auto i = its_servicegroups.begin(); i != its_servicegroups.end(); ++i) + get_servicegroup_configuration(i->second); + } catch (...) { + // intentionally left empty! + } } - return is_loaded; } -bool configuration_impl::get_servicegroup_configuration( +void configuration_impl::get_payload_sizes_configuration( const boost::property_tree::ptree &_tree) { - bool is_loaded(true); + const std::string payload_sizes("payload-sizes"); try { - std::shared_ptr<servicegroup> its_servicegroup( - std::make_shared<servicegroup>()); - its_servicegroup->unicast_ = "local"; // Default + if (_tree.get_child_optional(payload_sizes)) { + const std::string unicast("unicast"); + const std::string ports("ports"); + const std::string port("port"); + const std::string max_payload_size("max-payload-size"); + auto its_ps = _tree.get_child(payload_sizes); + for (auto i = its_ps.begin(); i != its_ps.end(); ++i) { + if (!i->second.get_child_optional(unicast) + || !i->second.get_child_optional(ports)) { + continue; + } + std::string its_unicast(i->second.get_child(unicast).data()); + for (auto j = i->second.get_child(ports).begin(); + j != i->second.get_child(ports).end(); ++j) { + + if (!j->second.get_child_optional(port) + || !j->second.get_child_optional(max_payload_size)) { + continue; + } + + std::uint16_t its_port = ILLEGAL_PORT; + std::uint32_t its_message_size = 0; + + try { + std::string p(j->second.get_child(port).data()); + its_port = static_cast<std::uint16_t>(std::stoul(p.c_str(), + NULL, 10)); + std::string s(j->second.get_child(max_payload_size).data()); + // add 16 Byte for the SOME/IP header + its_message_size = static_cast<std::uint32_t>(std::stoul( + s.c_str(), + NULL, 10) + 16); + } catch (const std::exception &e) { + VSOMEIP_ERROR << __func__ << ":" << e.what(); + } + + if (its_port == ILLEGAL_PORT || its_message_size == 0) { + continue; + } + if(max_configured_message_size_ < its_message_size) { + max_configured_message_size_ = its_message_size; + } + + message_sizes_[its_unicast][its_port] = its_message_size; + } + } + } + } catch (...) { + } +} + +void configuration_impl::get_servicegroup_configuration( + const boost::property_tree::ptree &_tree) { + try { + std::string its_unicast_address("local"); + for (auto i = _tree.begin(); i != _tree.end(); ++i) { std::string its_key(i->first); - if (its_key == "name") { - its_servicegroup->name_ = i->second.data(); - } else if (its_key == "unicast") { - its_servicegroup->unicast_ = i->second.data(); - } else if (its_key == "delays") { - is_loaded = is_loaded - && get_delays_configuration(its_servicegroup, - i->second); + if (its_key == "unicast") { + its_unicast_address = i->second.data(); + break; + } + } + + for (auto i = _tree.begin(); i != _tree.end(); ++i) { + std::string its_key(i->first); + if (its_key == "delays") { + get_delays_configuration(i->second); } else if (its_key == "services") { for (auto j = i->second.begin(); j != i->second.end(); ++j) - is_loaded = is_loaded - && get_service_configuration(its_servicegroup, - j->second); + get_service_configuration(j->second, its_unicast_address); } } - servicegroups_[its_servicegroup->name_] = its_servicegroup; } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_delays_configuration( - std::shared_ptr<servicegroup> &_group, +void configuration_impl::get_delays_configuration( const boost::property_tree::ptree &_tree) { - bool is_loaded(true); try { std::stringstream its_converter; for (auto i = _tree.begin(); i != _tree.end(); ++i) { std::string its_key(i->first); if (its_key == "initial") { - _group->min_initial_delay_ = i->second.get<uint32_t>("minimum"); - _group->max_initial_delay_ = i->second.get<uint32_t>("maximum"); + sd_initial_delay_min_ = i->second.get<uint32_t>("minimum"); + sd_initial_delay_max_ = i->second.get<uint32_t>("maximum"); } else if (its_key == "repetition-base") { its_converter << std::dec << i->second.data(); - its_converter >> _group->repetition_base_delay_; + its_converter >> sd_repetitions_base_delay_; } else if (its_key == "repetition-max") { int tmp_repetition_max; its_converter << std::dec << i->second.data(); its_converter >> tmp_repetition_max; - _group->repetition_max_ = tmp_repetition_max; + sd_repetitions_max_ = uint8_t(tmp_repetition_max); } else if (its_key == "cyclic-offer") { its_converter << std::dec << i->second.data(); - its_converter >> _group->cyclic_offer_delay_; + its_converter >> sd_cyclic_offer_delay_; } else if (its_key == "cyclic-request") { its_converter << std::dec << i->second.data(); - its_converter >> _group->cyclic_request_delay_; + its_converter >> sd_request_response_delay_; } its_converter.str(""); its_converter.clear(); } } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_service_configuration( - std::shared_ptr<servicegroup> &_group, - const boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_service_configuration( + const boost::property_tree::ptree &_tree, + const std::string &_unicast_address) { try { + bool is_loaded(true); bool use_magic_cookies(false); std::shared_ptr<service> its_service(std::make_shared<service>()); its_service->reliable_ = its_service->unreliable_ = ILLEGAL_PORT; - its_service->use_magic_cookies_ = false; - its_service->group_ = _group; + its_service->unicast_address_ = _unicast_address; its_service->multicast_address_ = ""; its_service->multicast_port_ = ILLEGAL_PORT; its_service->multicast_group_ = 0xFFFF; // TODO: use symbolic constant + its_service->protocol_ = "someip"; for (auto i = _tree.begin(); i != _tree.end(); ++i) { std::string its_key(i->first); std::string its_value(i->second.data()); std::stringstream its_converter; - if (its_key == "reliable") { + if (its_key == "unicast") { + its_service->unicast_address_ = its_value; + } else if (its_key == "reliable") { try { its_value = i->second.get_child("port").data(); its_converter << its_value; @@ -259,8 +384,8 @@ bool configuration_impl::get_service_configuration( its_converter >> its_service->reliable_; } try { - its_value = - i->second.get_child("enable-magic-cookies").data(); + its_value + = i->second.get_child("enable-magic-cookies").data(); use_magic_cookies = ("true" == its_value); } catch (...) { @@ -277,6 +402,8 @@ bool configuration_impl::get_service_configuration( its_converter >> its_service->multicast_port_; } catch (...) { } + } else if (its_key == "protocol") { + its_service->protocol_ = its_value; } else if (its_key == "events") { get_event_configuration(its_service, i->second); } else if (its_key == "eventgroups") { @@ -309,24 +436,18 @@ bool configuration_impl::get_service_configuration( if (is_loaded) { services_[its_service->service_][its_service->instance_] = its_service; - } - - if (use_magic_cookies) { - std::string its_unicast(_group->unicast_); - if (its_unicast == "local") - its_unicast = unicast_.to_string(); - magic_cookies_[its_unicast].insert(its_service->reliable_); + if (use_magic_cookies) { + magic_cookies_[its_service->unicast_address_].insert( + its_service->reliable_); + } } } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_event_configuration( +void configuration_impl::get_event_configuration( std::shared_ptr<service> &_service, const boost::property_tree::ptree &_tree) { - bool is_loaded(true); for (auto i = _tree.begin(); i != _tree.end(); ++i) { event_t its_event_id(0); bool its_is_field(false); @@ -361,12 +482,11 @@ bool configuration_impl::get_event_configuration( } } } - return is_loaded; } -bool configuration_impl::get_eventgroup_configuration( + +void configuration_impl::get_eventgroup_configuration( std::shared_ptr<service> &_service, const boost::property_tree::ptree &_tree) { - bool is_loaded(true); bool is_multicast; for (auto i = _tree.begin(); i != _tree.end(); ++i) { is_multicast = false; @@ -423,68 +543,80 @@ bool configuration_impl::get_eventgroup_configuration( _service->eventgroups_[its_eventgroup->id_] = its_eventgroup; } } - return is_loaded; } -bool configuration_impl::get_routing_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_routing_configuration( + const boost::property_tree::ptree &_tree) { try { auto its_routing = _tree.get_child("routing"); routing_host_ = its_routing.data(); } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_service_discovery_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_service_discovery_configuration( + const boost::property_tree::ptree &_tree) { try { auto its_service_discovery = _tree.get_child("service-discovery"); for (auto i = its_service_discovery.begin(); i != its_service_discovery.end(); ++i) { std::string its_key(i->first); std::string its_value(i->second.data()); + std::stringstream its_converter; if (its_key == "enable") { - is_service_discovery_enabled_ = (its_value == "true"); + is_sd_enabled_ = (its_value == "true"); } else if (its_key == "multicast") { - service_discovery_multicast_ = its_value; + sd_multicast_ = its_value; } else if (its_key == "port") { - std::stringstream its_converter; its_converter << its_value; - its_converter >> service_discovery_port_; + its_converter >> sd_port_; } else if (its_key == "protocol") { - service_discovery_protocol_ = its_value; + sd_protocol_ = its_value; + } else if (its_key == "initial_delay_min") { + its_converter << its_value; + its_converter >> sd_initial_delay_min_; + } else if (its_key == "initial_delay_max") { + its_converter << its_value; + its_converter >> sd_initial_delay_max_; + } else if (its_key == "repetitions_base_delay") { + its_converter << its_value; + its_converter >> sd_repetitions_base_delay_; + } else if (its_key == "repetitions_max") { + int tmp; + its_converter << its_value; + its_converter >> tmp; + sd_repetitions_max_ = (uint8_t)tmp; + } else if (its_key == "ttl") { + its_converter << its_value; + its_converter >> sd_ttl_; + } else if (its_key == "cyclic_offer_delay") { + its_converter << its_value; + its_converter >> sd_cyclic_offer_delay_; + } else if (its_key == "request_response_delay") { + its_converter << its_value; + its_converter >> sd_request_response_delay_; } } } catch (...) { - is_loaded = false; } - - return is_loaded; } -bool configuration_impl::get_applications_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_applications_configuration( + const boost::property_tree::ptree &_tree) { try { std::stringstream its_converter; auto its_applications = _tree.get_child("applications"); - for (auto i = its_applications.begin(); i != its_applications.end(); - ++i) - is_loaded = is_loaded && get_application_configuration(i->second); + for (auto i = its_applications.begin(); + i != its_applications.end(); + ++i) { + get_application_configuration(i->second); + } } catch (...) { - is_loaded = false; } - - return is_loaded; } -bool configuration_impl::get_application_configuration( +void configuration_impl::get_application_configuration( const boost::property_tree::ptree &_tree) { - bool is_loaded(true); std::string its_name(""); client_t its_id; std::size_t its_num_dispatchers(0); @@ -513,11 +645,10 @@ bool configuration_impl::get_application_configuration( if (its_name != "" && its_id != 0) { applications_[its_name] = {its_id, its_num_dispatchers}; } - return is_loaded; } // Public interface -const boost::asio::ip::address & configuration_impl::get_unicast() const { +const boost::asio::ip::address & configuration_impl::get_unicast_address() const { return unicast_; } @@ -549,107 +680,18 @@ boost::log::trivial::severity_level configuration_impl::get_loglevel() const { return loglevel_; } -std::set<std::string> configuration_impl::get_servicegroups() const { - std::set<std::string> its_keys; - for (auto i : servicegroups_) - its_keys.insert(i.first); - return its_keys; -} - -bool configuration_impl::is_local_servicegroup(const std::string &_name) const { - bool is_local(false); - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) { - is_local = (its_servicegroup->unicast_ == "local" - || its_servicegroup->unicast_ == get_unicast().to_string()); - } - - return is_local; -} - -int32_t configuration_impl::get_min_initial_delay( - const std::string &_name) const { - int32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->min_initial_delay_; - - return its_delay; -} - -int32_t configuration_impl::get_max_initial_delay( - const std::string &_name) const { - int32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->max_initial_delay_; - - return its_delay; -} - -int32_t configuration_impl::get_repetition_base_delay( - const std::string &_name) const { - int32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->repetition_base_delay_; - - return its_delay; -} - -uint8_t configuration_impl::get_repetition_max(const std::string &_name) const { - uint8_t its_max = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_max = its_servicegroup->repetition_max_; - - return its_max; -} - -int32_t configuration_impl::get_cyclic_offer_delay( - const std::string &_name) const { - uint32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->cyclic_offer_delay_; - - return its_delay; -} - -int32_t configuration_impl::get_cyclic_request_delay( - const std::string &_name) const { - uint32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->cyclic_request_delay_; - - return its_delay; -} - -std::string configuration_impl::get_group(service_t _service, +std::string configuration_impl::get_unicast_address(service_t _service, instance_t _instance) const { - std::string its_group("default"); + std::string its_unicast_address(""); service *its_service = find_service(_service, _instance); - if (nullptr != its_service) { - its_group = its_service->group_->name_; + if (its_service) { + its_unicast_address = its_service->unicast_address_; } - return its_group; -} -std::string configuration_impl::get_unicast(service_t _service, - instance_t _instance) const { - std::string its_unicast(""); - service *its_service = find_service(_service, _instance); - if (its_service) - its_unicast = its_service->group_->unicast_; - return its_unicast; + if (its_unicast_address == "local" || its_unicast_address == "") { + its_unicast_address = get_unicast_address().to_string(); + } + return its_unicast_address; } std::string configuration_impl::get_multicast_address(service_t _service, @@ -681,8 +723,7 @@ uint16_t configuration_impl::get_multicast_group(service_t _service, uint16_t configuration_impl::get_reliable_port(service_t _service, instance_t _instance) const { - uint16_t its_reliable = ILLEGAL_PORT; - + uint16_t its_reliable(ILLEGAL_PORT); service *its_service = find_service(_service, _instance); if (its_service) its_reliable = its_service->reliable_; @@ -690,6 +731,15 @@ uint16_t configuration_impl::get_reliable_port(service_t _service, return its_reliable; } +bool configuration_impl::is_someip(service_t _service, + instance_t _instance) const { + service *its_service = find_service(_service, _instance); + if (its_service) + return (its_service->protocol_ == "someip"); + return true; // we need to explicitely configure a service to + // be something else than SOME/IP +} + bool configuration_impl::has_enabled_magic_cookies(std::string _address, uint16_t _port) const { bool has_enabled(false); @@ -718,24 +768,6 @@ const std::string & configuration_impl::get_routing_host() const { return routing_host_; } -bool configuration_impl::is_service_discovery_enabled() const { - return is_service_discovery_enabled_; -} - -const std::string & -configuration_impl::get_service_discovery_protocol() const { - return service_discovery_protocol_; -} - -const std::string & -configuration_impl::get_service_discovery_multicast() const { - return service_discovery_multicast_; -} - -uint16_t configuration_impl::get_service_discovery_port() const { - return service_discovery_port_; -} - client_t configuration_impl::get_id(const std::string &_name) const { client_t its_client = 0; @@ -764,76 +796,13 @@ configuration_impl::get_remote_services() const { std::set<std::pair<service_t, instance_t> > its_remote_services; for (auto i : services_) { for (auto j : i.second) { - if (j.second->group_->unicast_ != "local") + if (j.second->unicast_address_ != "local" && j.second->unicast_address_ != "") its_remote_services.insert(std::make_pair(i.first, j.first)); } } return its_remote_services; } -std::map<service_t, - std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > -configuration_impl::get_eventgroups() const { - std::map<service_t, - std::map<instance_t, - std::map<eventgroup_t, std::set<event_t> > > > its_eventgroups; - for (auto i : services_) { - for (auto j : i.second) { - if (j.second->group_->unicast_ == "local") { - for (auto k : j.second->eventgroups_) { - for (auto l : k.second->events_) { - its_eventgroups[i.first][j.first] - [k.second->id_].insert(l->id_); - } - } - } - } - } - return its_eventgroups; -} - -std::map<service_t, std::map<instance_t, std::set<event_t> > > -configuration_impl::get_events() const { - std::map<service_t, std::map<instance_t, std::set<event_t> > > its_events; - for (auto i : services_) { - for (auto j : i.second) { - if (j.second->group_->unicast_ == "local") { - for (auto k : j.second->events_) { - its_events[i.first][j.first].insert(k.first); - } - } - } - } - return its_events; -} - -void configuration_impl::set_event( - std::shared_ptr<vsomeip::event> &_event) const { - auto found_service = services_.find(_event->get_service()); - if (found_service != services_.end()) { - auto found_instance = found_service->second.find( - _event->get_instance()); - if (found_instance != found_service->second.end()) { - auto found_event = found_instance->second->events_.find( - _event->get_event()); - if (found_event != found_instance->second->events_.end()) { - _event->set_field(found_event->second->is_field_); - _event->set_reliable(found_event->second->is_reliable_); - } - } - } -} - -servicegroup *configuration_impl::find_servicegroup( - const std::string &_name) const { - servicegroup *its_servicegroup(0); - auto find_servicegroup = servicegroups_.find(_name); - if (find_servicegroup != servicegroups_.end()) { - its_servicegroup = find_servicegroup->second.get(); - } - return its_servicegroup; -} - service *configuration_impl::find_service(service_t _service, instance_t _instance) const { service *its_service(0); @@ -847,5 +816,81 @@ service *configuration_impl::find_service(service_t _service, return its_service; } +std::uint32_t configuration_impl::get_max_message_size_local() const { + uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; + if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) { + its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; + } + if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) { + its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; + } + if(its_max_message_size < max_configured_message_size_) { + its_max_message_size = max_configured_message_size_; + } + + // add sizes of the the routing_manager_proxy's messages + // to the routing_manager stub + return std::uint32_t(its_max_message_size + + VSOMEIP_COMMAND_HEADER_SIZE + sizeof(instance_t) + + sizeof(bool) + sizeof(bool)); +} + +std::uint32_t configuration_impl::get_message_size_reliable( + const std::string& _address, std::uint16_t _port) const { + auto its_address = message_sizes_.find(_address); + if(its_address != message_sizes_.end()) { + auto its_port = its_address->second.find(_port); + if(its_port != its_address->second.end()) { + return its_port->second; + } + } + return VSOMEIP_MAX_TCP_MESSAGE_SIZE; +} + +// Service Discovery configuration +bool configuration_impl::is_sd_enabled() const { + return is_sd_enabled_; +} + +const std::string & configuration_impl::get_sd_multicast() const { + return sd_multicast_; +} + +uint16_t configuration_impl::get_sd_port() const { + return sd_port_; +} + +const std::string & configuration_impl::get_sd_protocol() const { + return sd_protocol_; +} + +int32_t configuration_impl::get_sd_initial_delay_min() const { + return sd_initial_delay_min_; +} + +int32_t configuration_impl::get_sd_initial_delay_max() const { + return sd_initial_delay_max_; +} + +int32_t configuration_impl::get_sd_repetitions_base_delay() const { + return sd_repetitions_base_delay_; +} + +uint8_t configuration_impl::get_sd_repetitions_max() const { + return sd_repetitions_max_; +} + +ttl_t configuration_impl::get_sd_ttl() const { + return sd_ttl_; +} + +int32_t configuration_impl::get_sd_cyclic_offer_delay() const { + return sd_cyclic_offer_delay_; +} + +int32_t configuration_impl::get_sd_request_response_delay() const { + return sd_request_response_delay_; +} + } // namespace config } // namespace vsomeip diff --git a/implementation/endpoints/include/buffer.hpp b/implementation/endpoints/include/buffer.hpp index f76c8d1..5641117 100644 --- a/implementation/endpoints/include/buffer.hpp +++ b/implementation/endpoints/include/buffer.hpp @@ -14,8 +14,7 @@ namespace vsomeip { -typedef std::array<byte_t, VSOMEIP_PACKET_SIZE> packet_buffer_t; -typedef std::shared_ptr<packet_buffer_t> packet_buffer_ptr_t; +typedef std::vector<byte_t> receive_buffer_t; typedef std::vector<byte_t> message_buffer_t; typedef std::shared_ptr<message_buffer_t> message_buffer_ptr_t; diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp index 0be6616..29f42a3 100644 --- a/implementation/endpoints/include/client_endpoint_impl.hpp +++ b/implementation/endpoints/include/client_endpoint_impl.hpp @@ -6,6 +6,7 @@ #ifndef VSOMEIP_CLIENT_ENDPOINT_IMPL_HPP
#define VSOMEIP_CLIENT_ENDPOINT_IMPL_HPP
+#include <condition_variable>
#include <deque>
#include <mutex>
#include <vector>
@@ -32,7 +33,8 @@ public: typedef typename Protocol::endpoint endpoint_type;
client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _remote, boost::asio::io_service &_io);
+ endpoint_type _remote, boost::asio::io_service &_io,
+ std::uint32_t _max_message_size);
virtual ~client_endpoint_impl();
bool send(const uint8_t *_data, uint32_t _size, bool _flush);bool send_to(
@@ -49,8 +51,7 @@ public: public:
void connect_cbk(boost::system::error_code const &_error);
void wait_connect_cbk(boost::system::error_code const &_error);
- void send_cbk(message_buffer_ptr_t _buffer,
- boost::system::error_code const &_error, std::size_t _bytes);
+ void send_cbk(boost::system::error_code const &_error, std::size_t _bytes);
void flush_cbk(boost::system::error_code const &_error);
public:
@@ -58,24 +59,21 @@ public: virtual void receive() = 0;
protected:
- virtual void send_queued(message_buffer_ptr_t) = 0;
+ virtual void send_queued() = 0;
socket_type socket_;
endpoint_type remote_;
boost::asio::system_timer flush_timer_;
boost::asio::system_timer connect_timer_;
- uint32_t connect_timeout_;bool is_connected_;
+ uint32_t connect_timeout_;
+ bool is_connected_;
// send data
message_buffer_ptr_t packetizer_;
-
- // receive data
- message_buffer_t message_;
+ std::deque<message_buffer_ptr_t> queue_;
std::mutex mutex_;
-
- uint32_t queued_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp index 49688ef..6acf164 100644 --- a/implementation/endpoints/include/endpoint.hpp +++ b/implementation/endpoints/include/endpoint.hpp @@ -42,6 +42,10 @@ public: virtual unsigned short get_remote_port() const = 0;
virtual bool is_reliable() const = 0;
virtual bool is_local() const = 0;
+
+ virtual void increment_use_count() = 0;
+ virtual void decrement_use_count() = 0;
+ virtual uint32_t get_use_count() = 0;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/endpoint_definition.hpp b/implementation/endpoints/include/endpoint_definition.hpp index 30f53fd..d7fb3a2 100644 --- a/implementation/endpoints/include/endpoint_definition.hpp +++ b/implementation/endpoints/include/endpoint_definition.hpp @@ -6,6 +6,9 @@ #ifndef VSOMEIP_ENDPOINT_DEFINITION_HPP #define VSOMEIP_ENDPOINT_DEFINITION_HPP +#include <map> +#include <memory> + #include <boost/asio/ip/address.hpp> #include <vsomeip/export.hpp> @@ -14,8 +17,7 @@ namespace vsomeip { class endpoint_definition { public: - VSOMEIP_EXPORT endpoint_definition(); - VSOMEIP_EXPORT endpoint_definition( + VSOMEIP_EXPORT static std::shared_ptr<endpoint_definition> get( const boost::asio::ip::address &_address, uint16_t _port, bool _is_reliable); @@ -31,11 +33,19 @@ public: VSOMEIP_EXPORT bool is_reliable() const; VSOMEIP_EXPORT void set_reliable(bool _is_reliable); + VSOMEIP_EXPORT endpoint_definition( + const boost::asio::ip::address &_address, + uint16_t _port, bool _is_reliable); private: boost::asio::ip::address address_; uint16_t port_; uint16_t remote_port_; bool is_reliable_; + + static std::map<boost::asio::ip::address, + std::map<uint16_t, + std::map<bool, + std::shared_ptr<endpoint_definition> > > > definitions_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/endpoint_host.hpp b/implementation/endpoints/include/endpoint_host.hpp index af0c9b1..d526ab4 100644 --- a/implementation/endpoints/include/endpoint_host.hpp +++ b/implementation/endpoints/include/endpoint_host.hpp @@ -22,6 +22,8 @@ public: virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0; virtual void on_message(const byte_t *_data, length_t _length, endpoint *_receiver) = 0; + virtual void on_error(const byte_t *_data, length_t _length, + endpoint *_receiver) = 0; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp index 5c6fe39..5d8350a 100644 --- a/implementation/endpoints/include/endpoint_impl.hpp +++ b/implementation/endpoints/include/endpoint_impl.hpp @@ -23,7 +23,8 @@ template<int MaxBufferSize> class endpoint_impl: public endpoint {
public:
endpoint_impl(std::shared_ptr<endpoint_host> _adapter,
- boost::asio::io_service &_io);
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size);
virtual ~endpoint_impl();
void enable_magic_cookies();
@@ -45,6 +46,10 @@ public: unsigned short get_remote_port() const;
bool is_reliable() const;
+ void increment_use_count();
+ void decrement_use_count();
+ uint32_t get_use_count();
+
public:
// required
virtual bool is_client() const = 0;
@@ -53,7 +58,7 @@ public: protected:
virtual bool is_magic_cookie() const;
- uint32_t find_magic_cookie(message_buffer_t &_buffer);
+ uint32_t find_magic_cookie(byte_t *_buffer, size_t _size);
protected:
// Reference to service context
@@ -62,10 +67,15 @@ protected: // Reference to host
std::weak_ptr<endpoint_host> host_;
- bool is_supporting_magic_cookies_;bool has_enabled_magic_cookies_;
+ bool is_supporting_magic_cookies_;
+ bool has_enabled_magic_cookies_;
// Filter configuration
std::map<service_t, uint8_t> opened_;
+
+ std::uint32_t max_message_size_;
+
+ uint32_t use_count_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp index 9891ae4..97f01ce 100644 --- a/implementation/endpoints/include/local_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp @@ -1,59 +1,65 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP
-#define VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP
-
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
-
-#ifdef WIN32
-#include <boost/asio/ip/tcp.hpp>
-#endif
-
-#include <vsomeip/defines.hpp>
-
-#include "client_endpoint_impl.hpp"
-
-namespace vsomeip {
-
-#ifdef WIN32
-typedef client_endpoint_impl<boost::asio::ip::tcp,
- VSOMEIP_MAX_TCP_MESSAGE_SIZE > local_client_endpoint_base_impl;
-#else
-typedef client_endpoint_impl<boost::asio::local::stream_protocol,
- VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> local_client_endpoint_base_impl;
-#endif
-
-class local_client_endpoint_impl: public local_client_endpoint_base_impl {
-public:
- local_client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- boost::asio::io_service &_io);
-
- virtual ~local_client_endpoint_impl();
-
- void start();
-
- void send_queued(message_buffer_ptr_t _data);
-
- bool is_local() const;
-
-private:
- void send_magic_cookie();
-
- void connect();
- void receive();
-
- void send_tag_cbk(boost::system::error_code const &_error,
- std::size_t _bytes);
- void receive_cbk(packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error,
- std::size_t _bytes);
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP +#define VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP + +#include <boost/asio/io_service.hpp> +#include <boost/asio/local/stream_protocol.hpp> + +#ifdef WIN32 +#include <boost/asio/ip/tcp.hpp> +#endif + +#include <vsomeip/defines.hpp> + +#include "client_endpoint_impl.hpp" + +namespace vsomeip { + +#ifdef WIN32 +typedef client_endpoint_impl<boost::asio::ip::tcp, + VSOMEIP_MAX_TCP_MESSAGE_SIZE > local_client_endpoint_base_impl; +#else +typedef client_endpoint_impl<boost::asio::local::stream_protocol, + VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> local_client_endpoint_base_impl; +#endif + +class local_client_endpoint_impl: public local_client_endpoint_base_impl { +public: + local_client_endpoint_impl(std::shared_ptr<endpoint_host> _host, + endpoint_type _local, + boost::asio::io_service &_io, + std::uint32_t _max_message_size); + + virtual ~local_client_endpoint_impl(); + + void start(); + + bool is_local() const; + +private: + void send_queued(); + + void send_start_tag(); + void send_queued_data(); + void send_end_tag(); + + void send_magic_cookie(); + + void connect(); + void receive(); + + void send_start_tag_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + void send_queued_data_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + void receive_cbk(boost::system::error_code const &_error, + std::size_t _bytes); +}; + +} // namespace vsomeip + +#endif // VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp index a47858a..626b30e 100644 --- a/implementation/endpoints/include/local_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp @@ -1,104 +1,107 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP
-#define VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP
-
-#include <map>
-
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
-#include <boost/enable_shared_from_this.hpp>
-
-#ifdef WIN32
-#include <boost/asio/ip/tcp.hpp>
-#endif
-
-#include <vsomeip/defines.hpp>
-
-#include "buffer.hpp"
-#include "server_endpoint_impl.hpp"
-
-namespace vsomeip {
-
-#ifdef WIN32
-typedef server_endpoint_impl<boost::asio::ip::tcp,
- VSOMEIP_MAX_TCP_MESSAGE_SIZE > local_server_endpoint_base_impl;
-#else
-typedef server_endpoint_impl<boost::asio::local::stream_protocol,
- VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> local_server_endpoint_base_impl;
-#endif
-
-class local_server_endpoint_impl: public local_server_endpoint_base_impl {
-
-public:
- local_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- boost::asio::io_service &_io);
- virtual ~local_server_endpoint_impl();
-
- void start();
- void stop();
-
- void restart();
- void receive();
-
- bool send_to(const std::shared_ptr<endpoint_definition>,
- const byte_t *_data, uint32_t _size, bool _flush);
- void send_queued(endpoint_type _target, message_buffer_ptr_t _data);
-
- endpoint_type get_remote() const;
- bool get_multicast(service_t, event_t, endpoint_type &) const;
-
- bool is_local() const;
-
-private:
- class connection: public boost::enable_shared_from_this<connection> {
-
- public:
- typedef boost::shared_ptr<connection> ptr;
-
- static ptr create(local_server_endpoint_impl *_server);
- socket_type & get_socket();
-
- void start();
-
- void send_queued(message_buffer_ptr_t _data);
-
- private:
- connection(local_server_endpoint_impl *_owner);
-
- void send_magic_cookie();
-
- local_server_endpoint_impl::socket_type socket_;
- local_server_endpoint_impl *server_;
-
- // the current message
- message_buffer_t message_;
-
- private:
- void receive_cbk(packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error,
- std::size_t _bytes);
- };
-
-#ifdef WIN32
- boost::asio::ip::tcp::acceptor acceptor_;
-#else
- boost::asio::local::stream_protocol::acceptor acceptor_;
-#endif
-
- std::map<endpoint_type, connection::ptr> connections_;
- connection *current_;
-
-private:
- void remove_connection(connection *_connection);
- void accept_cbk(connection::ptr _connection,
- boost::system::error_code const &_error);
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP +#define VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP + +#include <map> + +#include <boost/asio/io_service.hpp> +#include <boost/asio/local/stream_protocol.hpp> +#include <boost/enable_shared_from_this.hpp> + +#ifdef WIN32 +#include <boost/asio/ip/tcp.hpp> +#endif + +#include <vsomeip/defines.hpp> + +#include "buffer.hpp" +#include "server_endpoint_impl.hpp" + +namespace vsomeip { + +#ifdef WIN32 +typedef server_endpoint_impl<boost::asio::ip::tcp, + VSOMEIP_MAX_TCP_MESSAGE_SIZE > local_server_endpoint_base_impl; +#else +typedef server_endpoint_impl<boost::asio::local::stream_protocol, + VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> local_server_endpoint_base_impl; +#endif + +class local_server_endpoint_impl: public local_server_endpoint_base_impl { + +public: + local_server_endpoint_impl(std::shared_ptr<endpoint_host> _host, + endpoint_type _local, + boost::asio::io_service &_io, + std::uint32_t _max_message_size); + virtual ~local_server_endpoint_impl(); + + void start(); + void stop(); + + void restart(); + void receive(); + + bool send_to(const std::shared_ptr<endpoint_definition>, + const byte_t *_data, uint32_t _size, bool _flush); + void send_queued(queue_iterator_type _queue_iterator); + + endpoint_type get_remote() const; + bool get_multicast(service_t, event_t, endpoint_type &) const; + + bool is_local() const; + +private: + class connection: public boost::enable_shared_from_this<connection> { + + public: + typedef boost::shared_ptr<connection> ptr; + + static ptr create(local_server_endpoint_impl *_server, + std::uint32_t _max_message_size); + socket_type & get_socket(); + + void start(); + + void send_queued(queue_iterator_type _queue_iterator); + + private: + connection(local_server_endpoint_impl *_owner, std::uint32_t _max_message_size); + + void send_magic_cookie(); + + local_server_endpoint_impl::socket_type socket_; + local_server_endpoint_impl *server_; + + uint32_t max_message_size_; + + receive_buffer_t recv_buffer_; + size_t recv_buffer_size_; + + private: + void receive_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + }; + +#ifdef WIN32 + boost::asio::ip::tcp::acceptor acceptor_; +#else + boost::asio::local::stream_protocol::acceptor acceptor_; +#endif + + std::map<endpoint_type, connection::ptr> connections_; + connection *current_; + +private: + void remove_connection(connection *_connection); + void accept_cbk(connection::ptr _connection, + boost::system::error_code const &_error); +}; + +} // namespace vsomeip + +#endif // VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp index eca9c5a..c51cb49 100644 --- a/implementation/endpoints/include/server_endpoint_impl.hpp +++ b/implementation/endpoints/include/server_endpoint_impl.hpp @@ -6,6 +6,7 @@ #ifndef VSOMEIP_SERVER_IMPL_HPP
#define VSOMEIP_SERVER_IMPL_HPP
+#include <deque>
#include <map>
#include <memory>
#include <mutex>
@@ -28,9 +29,12 @@ public: typedef typename Protocol::socket socket_type;
typedef typename Protocol::endpoint endpoint_type;
typedef boost::array<uint8_t, MaxBufferSize> buffer_type;
+ typedef typename std::map<endpoint_type, std::deque<message_buffer_ptr_t> > queue_type;
+ typedef typename queue_type::iterator queue_iterator_type;
server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local, boost::asio::io_service &_io);
+ endpoint_type _local, boost::asio::io_service &_io,
+ std::uint32_t _max_message_size);
bool is_client() const;
bool is_connected() const;
@@ -40,7 +44,7 @@ public: public:
void connect_cbk(boost::system::error_code const &_error);
- void send_cbk(message_buffer_ptr_t _buffer,
+ void send_cbk(queue_iterator_type _queue_iterator,
boost::system::error_code const &_error, std::size_t _bytes);
void flush_cbk(endpoint_type _target,
const boost::system::error_code &_error);
@@ -48,8 +52,7 @@ public: public:
virtual bool send_intern(endpoint_type _target, const byte_t *_data,
uint32_t _port, bool _flush);
- virtual void send_queued(endpoint_type _target,
- message_buffer_ptr_t _buffer) = 0;
+ virtual void send_queued(queue_iterator_type _queue_iterator) = 0;
virtual endpoint_type get_remote() const = 0;
virtual bool get_multicast(service_t _service, event_t _event,
@@ -57,6 +60,8 @@ public: protected:
std::map<endpoint_type, message_buffer_ptr_t> packetizer_;
+ queue_type queues_;
+
std::map<client_t, std::map<session_t, endpoint_type> > clients_;
boost::asio::system_timer flush_timer_;
diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp index 3bb7f26..e5bf987 100644 --- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp @@ -20,11 +20,11 @@ class tcp_client_endpoint_impl: public tcp_client_endpoint_base_impl { public:
tcp_client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
endpoint_type _local,
- boost::asio::io_service &_io);
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size);
virtual ~tcp_client_endpoint_impl();
void start();
- void send_queued(message_buffer_ptr_t _buffer);
bool get_remote_address(boost::asio::ip::address &_address) const;
unsigned short get_local_port() const;
@@ -33,15 +33,18 @@ public: bool is_local() const;
private:
- bool is_magic_cookie() const;
+ void send_queued();
+ bool is_magic_cookie(size_t _offset) const;
void send_magic_cookie(message_buffer_ptr_t &_buffer);
- void receive_cbk(packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error,
+ void receive_cbk(boost::system::error_code const &_error,
std::size_t _bytes);
void connect();
void receive();
+
+ receive_buffer_t recv_buffer_;
+ size_t recv_buffer_size_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp index 10d52e6..57f0566 100644 --- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp @@ -24,7 +24,8 @@ class tcp_server_endpoint_impl: public tcp_server_endpoint_base_impl { public:
tcp_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
endpoint_type _local,
- boost::asio::io_service &_io);
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size);
virtual ~tcp_server_endpoint_impl();
void start();
@@ -32,7 +33,7 @@ public: bool send_to(const std::shared_ptr<endpoint_definition> _target,
const byte_t *_data, uint32_t _size, bool _flush);
- void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer);
+ void send_queued(queue_iterator_type _queue_iterator);
endpoint_type get_remote() const;
bool get_multicast(service_t, event_t, endpoint_type &) const;
@@ -54,30 +55,35 @@ private: public:
typedef boost::shared_ptr<connection> ptr;
- static ptr create(tcp_server_endpoint_impl *_server);
+ static ptr create(tcp_server_endpoint_impl *_server,
+ std::uint32_t _max_message_size);
socket_type & get_socket();
void start();
void stop();
+ void receive();
client_t get_client(endpoint_type _endpoint_type);
- void send_queued(message_buffer_ptr_t _buffer);
+ void send_queued(queue_iterator_type _queue_iterator);
private:
- connection(tcp_server_endpoint_impl *_owner);
+ connection(tcp_server_endpoint_impl *_owner, std::uint32_t _max_message_size);
void send_magic_cookie(message_buffer_ptr_t &_buffer);
tcp_server_endpoint_impl::socket_type socket_;
tcp_server_endpoint_impl *server_;
- message_buffer_t message_;
+ uint32_t max_message_size_;
+
+ receive_buffer_t recv_buffer_;
+ size_t recv_buffer_size_;
private:
- bool is_magic_cookie() const;
- void receive_cbk(packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error,
+ bool is_magic_cookie(size_t _offset) const;
+ void receive_cbk(boost::system::error_code const &_error,
std::size_t _bytes);
+ std::mutex stop_mutex_;
};
boost::asio::ip::tcp::acceptor acceptor_;
diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp index 0b20600..4a51db6 100644 --- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp @@ -31,13 +31,8 @@ public: virtual ~udp_client_endpoint_impl();
void start();
- void send_queued(message_buffer_ptr_t _buffer);
- void join(const std::string &_address);
- void leave(const std::string &_address);
-
- void receive_cbk(packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error,
+ void receive_cbk(boost::system::error_code const &_error,
std::size_t _bytes);
bool get_remote_address(boost::asio::ip::address &_address) const;
@@ -46,8 +41,12 @@ public: bool is_local() const;
private:
+ void send_queued();
void connect();
void receive();
+
+ receive_buffer_t recv_buffer_;
+ size_t recv_buffer_size_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp index 4c7beaf..d7e2b62 100644 --- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp @@ -33,7 +33,7 @@ public: bool send_to(const std::shared_ptr<endpoint_definition> _target,
const byte_t *_data, uint32_t _size, bool _flush);
- void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer);
+ void send_queued(queue_iterator_type _queue_iterator);
endpoint_type get_remote() const;
bool get_multicast(service_t _service, event_t _event,
@@ -51,8 +51,7 @@ public: client_t get_client(std::shared_ptr<endpoint_definition> _endpoint);
public:
- void receive_cbk(packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error,
+ void receive_cbk(boost::system::error_code const &_error,
std::size_t _size);
private:
@@ -62,7 +61,10 @@ private: socket_type socket_;
endpoint_type remote_;
std::map<service_t, std::map<instance_t, endpoint_type> > multicasts_;
- message_buffer_t message_;
+
+ receive_buffer_t recv_buffer_;
+ size_t recv_buffer_size_;
+ std::mutex stop_mutex_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp new file mode 100644 index 0000000..12484f5 --- /dev/null +++ b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp @@ -0,0 +1,62 @@ +// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP +#define VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP + +#include <vsomeip/primitive_types.hpp> + +#include "../include/endpoint.hpp" + +namespace vsomeip { + +class virtual_server_endpoint_impl : public endpoint { +public: + virtual_server_endpoint_impl( + const std::string &_address, + uint16_t _port, + bool _reliable); + + virtual ~virtual_server_endpoint_impl(); + + void start(); + void stop(); + + bool is_connected() const; + + bool send(const byte_t *_data, uint32_t _size, bool _flush); + bool send_to(const std::shared_ptr<endpoint_definition> _target, + const byte_t *_data, uint32_t _size, bool _flush); + void enable_magic_cookies(); + void receive(); + + void join(const std::string &_address); + void leave(const std::string &_address); + + void add_multicast(service_t _service, event_t _event, + const std::string &_address, uint16_t _port); + void remove_multicast(service_t _service, event_t _event); + + bool get_remote_address(boost::asio::ip::address &_address) const; + unsigned short get_local_port() const; + unsigned short get_remote_port() const; + bool is_reliable() const; + bool is_local() const; + + void increment_use_count(); + void decrement_use_count(); + uint32_t get_use_count(); + +private: + std::string address_; + uint16_t port_; + bool reliable_; + + uint32_t use_count_; +}; + +} // namespace vsomeip + +#endif // VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp index 5c2e399..6ed812a 100644 --- a/implementation/endpoints/src/client_endpoint_impl.cpp +++ b/implementation/endpoints/src/client_endpoint_impl.cpp @@ -6,6 +6,7 @@ #include <chrono>
#include <iomanip>
#include <sstream>
+#include <thread>
#include <boost/asio/buffer.hpp>
#include <boost/asio/ip/tcp.hpp>
@@ -13,11 +14,11 @@ #include <boost/asio/local/stream_protocol.hpp>
#include <vsomeip/defines.hpp>
-#include <vsomeip/logger.hpp>
#include "../include/client_endpoint_impl.hpp"
#include "../include/endpoint_host.hpp"
#include "../../configuration/include/internal.hpp"
+#include "../../logging/include/logger.hpp"
#include "../../utility/include/utility.hpp"
namespace vsomeip {
@@ -25,12 +26,13 @@ namespace vsomeip { template<typename Protocol, int MaxBufferSize>
client_endpoint_impl<Protocol, MaxBufferSize>::client_endpoint_impl(
std::shared_ptr<endpoint_host> _host, endpoint_type _remote,
- boost::asio::io_service &_io)
- : endpoint_impl<MaxBufferSize>(_host, _io), socket_(_io),
- connect_timer_(_io), flush_timer_(_io), remote_(_remote),
- packetizer_(std::make_shared<message_buffer_t>()),
+ boost::asio::io_service &_io, std::uint32_t _max_message_size)
+ : endpoint_impl<MaxBufferSize>(_host, _io, _max_message_size),
+ socket_(_io), remote_(_remote),
+ flush_timer_(_io), connect_timer_(_io),
connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT), // TODO: use config variable
- is_connected_(false) {
+ is_connected_(false),
+ packetizer_(std::make_shared<message_buffer_t>()) {
}
template<typename Protocol, int MaxBufferSize>
@@ -63,6 +65,11 @@ template<typename Protocol, int MaxBufferSize> bool client_endpoint_impl<Protocol, MaxBufferSize>::send_to(
const std::shared_ptr<endpoint_definition> _target, const byte_t *_data,
uint32_t _size, bool _flush) {
+ (void)_target;
+ (void)_data;
+ (void)_size;
+ (void)_flush;
+
VSOMEIP_ERROR<< "Clients endpoints must not be used to "
<< "send to explicitely specified targets";
return false;
@@ -72,6 +79,7 @@ template<typename Protocol, int MaxBufferSize> bool client_endpoint_impl<Protocol, MaxBufferSize>::send(const uint8_t *_data,
uint32_t _size, bool _flush) {
std::lock_guard<std::mutex> its_lock(mutex_);
+ bool is_flushing(false);
#if 0
std::stringstream msg;
msg << "cei::send: ";
@@ -80,8 +88,10 @@ bool client_endpoint_impl<Protocol, MaxBufferSize>::send(const uint8_t *_data, << (int)_data[i] << " ";
VSOMEIP_DEBUG << msg.str();
#endif
- if (packetizer_->size() + _size > MaxBufferSize) {
- send_queued(packetizer_);
+
+ if (packetizer_->size() + _size > endpoint_impl<MaxBufferSize>::max_message_size_) {
+ queue_.push_back(packetizer_);
+ is_flushing = true;
packetizer_ = std::make_shared<message_buffer_t>();
}
@@ -89,15 +99,22 @@ bool client_endpoint_impl<Protocol, MaxBufferSize>::send(const uint8_t *_data, if (_flush) {
flush_timer_.cancel();
- send_queued(packetizer_);
+ queue_.push_back(packetizer_);
+ is_flushing = true;
packetizer_ = std::make_shared<message_buffer_t>();
} else {
flush_timer_.expires_from_now(
std::chrono::milliseconds(VSOMEIP_DEFAULT_FLUSH_TIMEOUT)); // TODO: use config variable
flush_timer_.async_wait(
- std::bind(
- &client_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk,
- this->shared_from_this(), std::placeholders::_1));
+ std::bind(
+ &client_endpoint_impl<
+ Protocol, MaxBufferSize>::flush_cbk,
+ this->shared_from_this(),
+ std::placeholders::_1));
+ }
+
+ if (is_flushing && queue_.size() == 1) { // no writing in progress
+ send_queued();
}
return (true);
@@ -108,8 +125,12 @@ bool client_endpoint_impl<Protocol, MaxBufferSize>::flush() { bool is_successful(true);
if (!packetizer_->empty()) {
- send_queued(packetizer_);
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ queue_.push_back(packetizer_);
packetizer_ = std::make_shared<message_buffer_t>();
+ if (queue_.size() == 1) { // no writing in progress
+ send_queued();
+ }
} else {
is_successful = false;
}
@@ -163,17 +184,15 @@ void client_endpoint_impl<Protocol, MaxBufferSize>::wait_connect_cbk( template<typename Protocol, int MaxBufferSize>
void client_endpoint_impl<Protocol, MaxBufferSize>::send_cbk(
- message_buffer_ptr_t _buffer, boost::system::error_code const &_error,
- std::size_t _bytes) {
-#if 0
- std::stringstream msg;
- msg << "cei<" << this << ">::scb (" << _error.message() << "): ";
- for (std::size_t i = 0; i < _data->size(); ++i)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
-#endif
- if (_error == boost::asio::error::broken_pipe) {
+ boost::system::error_code const &_error, std::size_t _bytes) {
+ (void)_bytes;
+ if (!_error) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ queue_.pop_front();
+ if (queue_.size() > 0) {
+ send_queued();
+ }
+ } else if (_error == boost::asio::error::broken_pipe) {
is_connected_ = false;
socket_.close();
connect();
diff --git a/implementation/endpoints/src/endpoint_definition.cpp b/implementation/endpoints/src/endpoint_definition.cpp index 9a4caea..d748aa3 100644 --- a/implementation/endpoints/src/endpoint_definition.cpp +++ b/implementation/endpoints/src/endpoint_definition.cpp @@ -9,14 +9,41 @@ namespace vsomeip { -endpoint_definition::endpoint_definition() - : port_(ILLEGAL_PORT) { +std::map<boost::asio::ip::address, + std::map<uint16_t, + std::map<bool, std::shared_ptr<endpoint_definition> > > > +endpoint_definition::definitions_; + +std::shared_ptr<endpoint_definition> +endpoint_definition::get(const boost::asio::ip::address &_address, + uint16_t _port, bool _is_reliable) { + + std::shared_ptr<endpoint_definition> its_result; + + auto find_address = definitions_.find(_address); + if (find_address != definitions_.end()) { + auto find_port = find_address->second.find(_port); + if (find_port != find_address->second.end()) { + auto found_reliable = find_port->second.find(_is_reliable); + if (found_reliable != find_port->second.end()) { + its_result = found_reliable->second; + } + } + } + + if (!its_result) { + its_result = std::make_shared<endpoint_definition>( + _address, _port, _is_reliable); + definitions_[_address][_port][_is_reliable] = its_result; + } + return its_result; } endpoint_definition::endpoint_definition( const boost::asio::ip::address &_address, uint16_t _port, bool _is_reliable) - : address_(_address), port_(_port), is_reliable_(_is_reliable), remote_port_(_port) { + : address_(_address), port_(_port), remote_port_(_port), + is_reliable_(_is_reliable) { } const boost::asio::ip::address & endpoint_definition::get_address() const { diff --git a/implementation/endpoints/src/endpoint_impl.cpp b/implementation/endpoints/src/endpoint_impl.cpp index e7ffffa..5b0e088 100644 --- a/implementation/endpoints/src/endpoint_impl.cpp +++ b/implementation/endpoints/src/endpoint_impl.cpp @@ -5,20 +5,22 @@ #include <vsomeip/constants.hpp>
#include <vsomeip/defines.hpp>
-#include <vsomeip/logger.hpp>
#include "../include/endpoint_host.hpp"
#include "../include/endpoint_impl.hpp"
+#include "../../logging/include/logger.hpp"
namespace vsomeip {
template<int MaxBufferSize>
endpoint_impl<MaxBufferSize>::endpoint_impl(
- std::shared_ptr<endpoint_host> _host, boost::asio::io_service &_io)
- : host_(_host),
- service_(_io),
+ std::shared_ptr<endpoint_host> _host, boost::asio::io_service &_io,
+ std::uint32_t _max_message_size)
+ : service_(_io),
+ host_(_host),
is_supporting_magic_cookies_(false),
- has_enabled_magic_cookies_(false) {
+ has_enabled_magic_cookies_(false),
+ max_message_size_(_max_message_size) {
}
template<int MaxBufferSize>
@@ -37,7 +39,7 @@ bool endpoint_impl<MaxBufferSize>::is_magic_cookie() const { template<int MaxBufferSize>
uint32_t endpoint_impl<MaxBufferSize>::find_magic_cookie(
- message_buffer_t &_buffer) {
+ byte_t *_buffer, size_t _size) {
bool is_found(false);
uint32_t its_offset = 0xFFFFFFFF;
if (has_enabled_magic_cookies_) {
@@ -57,7 +59,7 @@ uint32_t endpoint_impl<MaxBufferSize>::find_magic_cookie( do {
its_offset++; // --> first loop has "its_offset = 0"
- if (_buffer.size() > its_offset + 16) {
+ if (_size > its_offset + 16) {
is_found = (_buffer[its_offset] == 0xFF
&& _buffer[its_offset + 1] == 0xFF
&& _buffer[its_offset + 2] == its_cookie_identifier
@@ -104,6 +106,7 @@ void endpoint_impl<MaxBufferSize>::remove_multicast(service_t, event_t) { template<int MaxBufferSize>
bool endpoint_impl<MaxBufferSize>::get_remote_address(
boost::asio::ip::address &_address) const {
+ (void)_address;
return false;
}
@@ -122,6 +125,22 @@ bool endpoint_impl<MaxBufferSize>::is_reliable() const { return false;
}
+template<int MaxBufferSize>
+void endpoint_impl<MaxBufferSize>::increment_use_count() {
+ use_count_++;
+}
+
+template<int MaxBufferSize>
+void endpoint_impl<MaxBufferSize>::decrement_use_count() {
+ if (use_count_ > 0)
+ use_count_--;
+}
+
+template<int MaxBufferSize>
+uint32_t endpoint_impl<MaxBufferSize>::get_use_count() {
+ return use_count_;
+}
+
// Instantiate template
template class endpoint_impl< VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> ;
template class endpoint_impl< VSOMEIP_MAX_TCP_MESSAGE_SIZE> ;
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp index b465baa..323c414 100644 --- a/implementation/endpoints/src/local_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp @@ -9,17 +9,17 @@ #include <boost/asio/write.hpp>
#include <vsomeip/defines.hpp>
-#include <vsomeip/logger.hpp>
#include "../include/endpoint_host.hpp"
#include "../include/local_client_endpoint_impl.hpp"
+#include "../../logging/include/logger.hpp"
namespace vsomeip {
local_client_endpoint_impl::local_client_endpoint_impl(
std::shared_ptr< endpoint_host > _host, endpoint_type _remote,
- boost::asio::io_service &_io)
- : local_client_endpoint_base_impl(_host, _remote, _io) {
+ boost::asio::io_service &_io, std::uint32_t _max_message_size)
+ : local_client_endpoint_base_impl(_host, _remote, _io, _max_message_size) {
is_supporting_magic_cookies_ = false;
}
@@ -49,34 +49,22 @@ void local_client_endpoint_impl::connect() { }
void local_client_endpoint_impl::receive() {
- packet_buffer_ptr_t its_buffer
- = std::make_shared< packet_buffer_t >();
+ receive_buffer_t its_buffer(VSOMEIP_MAX_LOCAL_MESSAGE_SIZE , 0);
socket_.async_receive(
- boost::asio::buffer(*its_buffer),
+ boost::asio::buffer(its_buffer),
std::bind(
&local_client_endpoint_impl::receive_cbk,
std::dynamic_pointer_cast<
local_client_endpoint_impl
>(shared_from_this()),
- its_buffer,
std::placeholders::_1,
std::placeholders::_2
)
);
}
-void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) {
-#if 0
- std::stringstream msg;
- msg << "lce<" << this << ">::sq: ";
- for (std::size_t i = 0; i < _buffer->size(); i++)
- msg << std::setw(2) << std::setfill('0') << std::hex
- << (int)(*_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
-#endif
-
+void local_client_endpoint_impl::send_queued() {
static byte_t its_start_tag[] = { 0x67, 0x37, 0x6D, 0x07 };
- static byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 };
boost::asio::async_write(
socket_,
@@ -85,7 +73,7 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { sizeof(its_start_tag)
),
std::bind(
- &local_client_endpoint_impl::send_tag_cbk,
+ &local_client_endpoint_impl::send_start_tag_cbk,
std::dynamic_pointer_cast<
local_client_endpoint_impl
>(shared_from_this()),
@@ -93,18 +81,36 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { std::placeholders::_2
)
);
+}
+
+void local_client_endpoint_impl::send_queued_data() {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ message_buffer_ptr_t its_buffer = queue_.front();
+ #if 0
+ std::stringstream msg;
+ msg << "lce<" << this << ">::sq: ";
+ for (std::size_t i = 0; i < its_buffer->size(); i++)
+ msg << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(*its_buffer)[i] << " ";
+ VSOMEIP_DEBUG << msg.str();
+ #endif
boost::asio::async_write(
socket_,
- boost::asio::buffer(*_buffer),
+ boost::asio::buffer(*its_buffer),
std::bind(
- &client_endpoint_impl::send_cbk,
- this->shared_from_this(),
- _buffer,
+ &local_client_endpoint_impl::send_queued_data_cbk,
+ std::dynamic_pointer_cast<
+ local_client_endpoint_impl
+ >(shared_from_this()),
std::placeholders::_1,
std::placeholders::_2
)
);
+}
+
+void local_client_endpoint_impl::send_end_tag() {
+ static byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 };
boost::asio::async_write(
socket_,
@@ -113,10 +119,8 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { sizeof(its_end_tag)
),
std::bind(
- &local_client_endpoint_impl::send_tag_cbk,
- std::dynamic_pointer_cast<
- local_client_endpoint_impl
- >(shared_from_this()),
+ &client_endpoint_impl::send_cbk,
+ shared_from_this(),
std::placeholders::_1,
std::placeholders::_2
)
@@ -126,13 +130,28 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { void local_client_endpoint_impl::send_magic_cookie() {
}
-void local_client_endpoint_impl::send_tag_cbk(
+void local_client_endpoint_impl::send_start_tag_cbk(
boost::system::error_code const &_error, std::size_t _bytes) {
+ (void)_bytes;
+ if (_error)
+ send_cbk(_error, 0);
+
+ send_queued_data();
+}
+
+void local_client_endpoint_impl::send_queued_data_cbk(
+ boost::system::error_code const &_error, std::size_t _bytes) {
+ (void)_bytes;
+ if (_error)
+ send_cbk(_error, 0);
+
+ send_end_tag();
}
void local_client_endpoint_impl::receive_cbk(
- packet_buffer_ptr_t _buffer,
boost::system::error_code const &_error, std::size_t _bytes) {
+ (void)_error;
+ (void)_bytes;
VSOMEIP_ERROR << "Local endpoint received message ("
<< _error.message() << ")";
}
diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp index 3a237c6..b392cec 100644 --- a/implementation/endpoints/src/local_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp @@ -1,252 +1,276 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <deque>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-
-#include <boost/asio/write.hpp>
-
-#include <vsomeip/logger.hpp>
-
-#include "../include/endpoint_host.hpp"
-#include "../include/local_server_endpoint_impl.hpp"
-
-namespace vsomeip {
-
-local_server_endpoint_impl::local_server_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _local, boost::asio::io_service &_io)
- : local_server_endpoint_base_impl(_host, _local, _io),
- acceptor_(_io, _local) {
- is_supporting_magic_cookies_ = false;
-}
-
-local_server_endpoint_impl::~local_server_endpoint_impl() {
-}
-
-bool local_server_endpoint_impl::is_local() const {
- return true;
-}
-
-void local_server_endpoint_impl::start() {
- connection::ptr new_connection = connection::create(this);
-
- acceptor_.async_accept(
- new_connection->get_socket(),
- std::bind(
- &local_server_endpoint_impl::accept_cbk,
- std::dynamic_pointer_cast<
- local_server_endpoint_impl
- >(shared_from_this()),
- new_connection,
- std::placeholders::_1
- )
- );
-}
-
-void local_server_endpoint_impl::stop() {
-}
-
-bool local_server_endpoint_impl::send_to(
- const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush) {
- return false;
-}
-
-void local_server_endpoint_impl::send_queued(
- endpoint_type _target, message_buffer_ptr_t _buffer) {
- auto connection_iterator = connections_.find(_target);
- if (connection_iterator != connections_.end())
- connection_iterator->second->send_queued(_buffer);
-}
-
-void local_server_endpoint_impl::receive() {
- // intentionally left empty
-}
-
-void local_server_endpoint_impl::restart() {
- current_->start();
-}
-
-local_server_endpoint_impl::endpoint_type
-local_server_endpoint_impl::get_remote() const {
- return current_->get_socket().remote_endpoint();
-}
-
-bool local_server_endpoint_impl::get_multicast(
- service_t, event_t,
- local_server_endpoint_impl::endpoint_type &) const {
- return false;
-}
-
-void local_server_endpoint_impl::remove_connection(
- local_server_endpoint_impl::connection *_connection) {
- std::map< endpoint_type, connection::ptr >::iterator i
- = connections_.end();
- for (i = connections_.begin(); i != connections_.end(); i++) {
- if (i->second.get() == _connection)
- break;
- }
-
- if (i != connections_.end()) {
- connections_.erase(i);
- }
-}
-
-void local_server_endpoint_impl::accept_cbk(
- connection::ptr _connection, boost::system::error_code const &_error) {
-
- if (!_error) {
- socket_type &new_connection_socket = _connection->get_socket();
- endpoint_type remote = new_connection_socket.remote_endpoint();
-
- connections_[remote] = _connection;
- _connection->start();
- }
-
- start();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// class local_service_impl::connection
-///////////////////////////////////////////////////////////////////////////////
-local_server_endpoint_impl::connection::connection(
- local_server_endpoint_impl *_server)
- : socket_(_server->service_), server_(_server) {
-}
-
-local_server_endpoint_impl::connection::ptr
-local_server_endpoint_impl::connection::create(
- local_server_endpoint_impl *_server) {
- return ptr(new connection(_server));
-}
-
-local_server_endpoint_impl::socket_type &
-local_server_endpoint_impl::connection::get_socket() {
- return socket_;
-}
-
-void local_server_endpoint_impl::connection::start() {
- packet_buffer_ptr_t its_buffer
- = std::make_shared< packet_buffer_t >();
- socket_.async_receive(
- boost::asio::buffer(*its_buffer),
- std::bind(
- &local_server_endpoint_impl::connection::receive_cbk,
- shared_from_this(),
- its_buffer,
- std::placeholders::_1,
- std::placeholders::_2
- )
- );
-}
-
-void local_server_endpoint_impl::connection::send_queued(
- message_buffer_ptr_t _buffer) {
-#if 0
- std::stringstream msg;
- msg << "lse::sq: ";
- for (std::size_t i = 0; i < _buffer->size(); i++)
- msg << std::setw(2) << std::setfill('0') << std::hex
- << (int)(*_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
-#endif
- boost::asio::async_write(
- socket_,
- boost::asio::buffer(*_buffer),
- std::bind(
- &local_server_endpoint_base_impl::send_cbk,
- server_->shared_from_this(),
- _buffer,
- std::placeholders::_1,
- std::placeholders::_2
- )
- );
-}
-
-void local_server_endpoint_impl::connection::send_magic_cookie() {
-}
-
-void local_server_endpoint_impl::connection::receive_cbk(
- packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error, std::size_t _bytes) {
-
- std::shared_ptr<endpoint_host> its_host = server_->host_.lock();
- if (its_host) {
- std::size_t its_start;
- std::size_t its_end;
-
- if (!_error && 0 < _bytes) {
- #if 0
- std::stringstream msg;
- msg << "lse::c<" << this << ">rcb: ";
- for (std::size_t i = 0; i < _bytes; i++)
- msg << std::setw(2) << std::setfill('0') << std::hex
- << (int)(*_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
- #endif
-
- message_.insert(message_.end(), _buffer->begin(),
- _buffer->begin() + _bytes);
-
- #define MESSAGE_IS_EMPTY (-1)
- #define FOUND_MESSAGE (-2)
-
- do {
- its_start = 0;
- while (its_start + 3 < message_.size() &&
- (message_[its_start] != 0x67 ||
- message_[its_start+1] != 0x37 ||
- message_[its_start+2] != 0x6d ||
- message_[its_start+3] != 0x07)) {
- its_start ++;
- }
-
- its_start = (its_start + 3 == message_.size() ?
- MESSAGE_IS_EMPTY : its_start+4);
-
- if (its_start != MESSAGE_IS_EMPTY) {
- its_end = its_start;
- while (its_end + 3 < message_.size() &&
- (message_[its_end] != 0x07 ||
- message_[its_end+1] != 0x6d ||
- message_[its_end+2] != 0x37 ||
- message_[its_end+3] != 0x67)) {
- its_end ++;
- }
- }
-
- if (its_start != MESSAGE_IS_EMPTY &&
- its_end+3 < message_.size()) {
- its_host->on_message(&message_[its_start],
- its_end - its_start, server_);
-
- #if 0
- std::stringstream local_msg;
- local_msg << "lse::c<" << this << ">rcb::thunk: ";
- for (std::size_t i = its_start; i < its_end; i++)
- local_msg << std::setw(2) << std::setfill('0') << std::hex
- << (int)(message_)[i] << " ";
- VSOMEIP_DEBUG << local_msg.str();
- #endif
-
- message_.erase(message_.begin(),
- message_.begin() + its_end + 4);
- its_start = FOUND_MESSAGE;
- }
- } while (message_.size() > 0 && its_start == FOUND_MESSAGE);
- }
-
- if (_error == boost::asio::error::misc_errors::eof) {
- server_->remove_connection(this);
- } else {
- start();
- }
- }
-}
-
-} // namespace vsomeip
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <deque> +#include <iomanip> +#include <iostream> +#include <sstream> + +#include <boost/asio/write.hpp> + +#include "../include/endpoint_host.hpp" +#include "../include/local_server_endpoint_impl.hpp" + +#include "../../logging/include/logger.hpp" + +namespace vsomeip { + +local_server_endpoint_impl::local_server_endpoint_impl( + std::shared_ptr< endpoint_host > _host, + endpoint_type _local, boost::asio::io_service &_io, + std::uint32_t _max_message_size) + : local_server_endpoint_base_impl(_host, _local, _io, _max_message_size), + acceptor_(_io, _local) { + is_supporting_magic_cookies_ = false; +} + +local_server_endpoint_impl::~local_server_endpoint_impl() { +} + +bool local_server_endpoint_impl::is_local() const { + return true; +} + +void local_server_endpoint_impl::start() { + connection::ptr new_connection = connection::create(this, max_message_size_); + + acceptor_.async_accept( + new_connection->get_socket(), + std::bind( + &local_server_endpoint_impl::accept_cbk, + std::dynamic_pointer_cast< + local_server_endpoint_impl + >(shared_from_this()), + new_connection, + std::placeholders::_1 + ) + ); +} + +void local_server_endpoint_impl::stop() { +} + +bool local_server_endpoint_impl::send_to( + const std::shared_ptr<endpoint_definition> _target, + const byte_t *_data, uint32_t _size, bool _flush) { + (void)_target; + (void)_data; + (void)_size; + (void)_flush; + return false; +} + +void local_server_endpoint_impl::send_queued( + queue_iterator_type _queue_iterator) { + auto connection_iterator = connections_.find(_queue_iterator->first); + if (connection_iterator != connections_.end()) + connection_iterator->second->send_queued(_queue_iterator); +} + +void local_server_endpoint_impl::receive() { + // intentionally left empty +} + +void local_server_endpoint_impl::restart() { + current_->start(); +} + +local_server_endpoint_impl::endpoint_type +local_server_endpoint_impl::get_remote() const { + return current_->get_socket().remote_endpoint(); +} + +bool local_server_endpoint_impl::get_multicast( + service_t, event_t, + local_server_endpoint_impl::endpoint_type &) const { + return false; +} + +void local_server_endpoint_impl::remove_connection( + local_server_endpoint_impl::connection *_connection) { + std::map< endpoint_type, connection::ptr >::iterator i + = connections_.end(); + for (i = connections_.begin(); i != connections_.end(); i++) { + if (i->second.get() == _connection) + break; + } + + if (i != connections_.end()) { + connections_.erase(i); + } +} + +void local_server_endpoint_impl::accept_cbk( + connection::ptr _connection, boost::system::error_code const &_error) { + + if (!_error) { + socket_type &new_connection_socket = _connection->get_socket(); + endpoint_type remote = new_connection_socket.remote_endpoint(); + + connections_[remote] = _connection; + _connection->start(); + } + + start(); +} + +/////////////////////////////////////////////////////////////////////////////// +// class local_service_impl::connection +/////////////////////////////////////////////////////////////////////////////// + +local_server_endpoint_impl::connection::connection( + local_server_endpoint_impl *_server, std::uint32_t _max_message_size) + : socket_(_server->service_), server_(_server), + max_message_size_(_max_message_size + 8), + recv_buffer_(max_message_size_, 0), + recv_buffer_size_(0) { +} + +local_server_endpoint_impl::connection::ptr +local_server_endpoint_impl::connection::create( + local_server_endpoint_impl *_server, std::uint32_t _max_message_size) { + return ptr(new connection(_server, _max_message_size)); +} + +local_server_endpoint_impl::socket_type & +local_server_endpoint_impl::connection::get_socket() { + return socket_; +} + +void local_server_endpoint_impl::connection::start() { + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + size_t buffer_size = max_message_size_ - recv_buffer_size_; + socket_.async_receive( + boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), + std::bind( + &local_server_endpoint_impl::connection::receive_cbk, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +void local_server_endpoint_impl::connection::send_queued( + queue_iterator_type _queue_iterator) { + + // TODO: We currently do _not_ use the send method of the local server + // endpoints. If we ever need it, we need to add the "start tag", "data", + // "end tag" sequence here. + + message_buffer_ptr_t its_buffer = _queue_iterator->second.front(); +#if 0 + std::stringstream msg; + msg << "lse::sq: "; + for (std::size_t i = 0; i < its_buffer->size(); i++) + msg << std::setw(2) << std::setfill('0') << std::hex + << (int)(*its_buffer)[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif + boost::asio::async_write( + socket_, + boost::asio::buffer(*its_buffer), + std::bind( + &local_server_endpoint_base_impl::send_cbk, + server_->shared_from_this(), + _queue_iterator, + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +void local_server_endpoint_impl::connection::send_magic_cookie() { +} + +void local_server_endpoint_impl::connection::receive_cbk( + boost::system::error_code const &_error, std::size_t _bytes) { + + std::shared_ptr<endpoint_host> its_host = server_->host_.lock(); + if (its_host) { + std::size_t its_start; + std::size_t its_end; + std::size_t its_iteration_gap = 0; + + if (!_error && 0 < _bytes) { + #if 0 + std::stringstream msg; + msg << "lse::c<" << this << ">rcb: "; + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; i++) + msg << std::setw(2) << std::setfill('0') << std::hex + << (int) (recv_buffer_[i]) << " "; + VSOMEIP_DEBUG << msg.str(); + #endif + + recv_buffer_size_ += _bytes; + + #define MESSAGE_IS_EMPTY std::size_t(-1) + #define FOUND_MESSAGE std::size_t(-2) + + do { + its_start = 0 + its_iteration_gap; + while (its_start + 3 < recv_buffer_size_ + its_iteration_gap && + (recv_buffer_[its_start] != 0x67 || + recv_buffer_[its_start+1] != 0x37 || + recv_buffer_[its_start+2] != 0x6d || + recv_buffer_[its_start+3] != 0x07)) { + its_start ++; + } + + its_start = (its_start + 3 == recv_buffer_size_ + its_iteration_gap ? + MESSAGE_IS_EMPTY : its_start+4); + + if (its_start != MESSAGE_IS_EMPTY) { + its_end = its_start; + while (its_end + 3 < recv_buffer_size_ + its_iteration_gap && + (recv_buffer_[its_end] != 0x07 || + recv_buffer_[its_end+1] != 0x6d || + recv_buffer_[its_end+2] != 0x37 || + recv_buffer_[its_end+3] != 0x67)) { + its_end ++; + } + } + + if (its_start != MESSAGE_IS_EMPTY && + its_end + 3 < recv_buffer_size_ + its_iteration_gap) { + its_host->on_message(&recv_buffer_[its_start], + uint32_t(its_end - its_start), server_); + + #if 0 + std::stringstream local_msg; + local_msg << "lse::c<" << this << ">rcb::thunk: "; + for (std::size_t i = its_start; i < its_end; i++) + local_msg << std::setw(2) << std::setfill('0') << std::hex + << (int) recv_buffer_[i] << " "; + VSOMEIP_DEBUG << local_msg.str(); + #endif + + recv_buffer_size_ -= (its_end + 4 - its_iteration_gap); + its_start = FOUND_MESSAGE; + its_iteration_gap = its_end + 4; + } else { + if (its_start != MESSAGE_IS_EMPTY && its_iteration_gap) { + // Message not complete and not in front of the buffer! + // Copy last part to front for consume in future receive_cbk call! + for (size_t i = 0; i < recv_buffer_size_; ++i) { + recv_buffer_[i] = recv_buffer_[i + its_iteration_gap]; + } + } + } + } while (recv_buffer_size_ > 0 && its_start == FOUND_MESSAGE); + } + + if (_error == boost::asio::error::misc_errors::eof) { + server_->remove_connection(this); + } else { + start(); + } + } +} + +} // namespace vsomeip diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp index 0158cf6..b67ecec 100644 --- a/implementation/endpoints/src/server_endpoint_impl.cpp +++ b/implementation/endpoints/src/server_endpoint_impl.cpp @@ -12,10 +12,10 @@ #include <boost/asio/local/stream_protocol.hpp>
#include <vsomeip/defines.hpp>
-#include <vsomeip/logger.hpp>
#include "../include/server_endpoint_impl.hpp"
#include "../../configuration/include/internal.hpp"
+#include "../../logging/include/logger.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
@@ -24,8 +24,9 @@ namespace vsomeip { template<typename Protocol, int MaxBufferSize>
server_endpoint_impl<Protocol, MaxBufferSize>::server_endpoint_impl(
std::shared_ptr<endpoint_host> _host, endpoint_type _local,
- boost::asio::io_service &_io)
- : endpoint_impl<MaxBufferSize>(_host, _io), flush_timer_(_io) {
+ boost::asio::io_service &_io, std::uint32_t _max_message_size)
+ : endpoint_impl<MaxBufferSize>(_host, _io, _max_message_size),
+ flush_timer_(_io), local_(_local) {
}
template<typename Protocol, int MaxBufferSize>
@@ -92,7 +93,10 @@ bool server_endpoint_impl<Protocol, MaxBufferSize>::send_intern( endpoint_type _target, const byte_t *_data, uint32_t _size,
bool _flush) {
- std::shared_ptr<std::vector<byte_t> > target_packetizer;
+ bool is_flushing(false);
+ message_buffer_ptr_t target_packetizer;
+ queue_iterator_type target_queue_iterator;
+
auto found_packetizer = packetizer_.find(_target);
if (found_packetizer != packetizer_.end()) {
target_packetizer = found_packetizer->second;
@@ -101,8 +105,19 @@ bool server_endpoint_impl<Protocol, MaxBufferSize>::send_intern( packetizer_.insert(std::make_pair(_target, target_packetizer));
}
- if (target_packetizer->size() + _size > MaxBufferSize) {
- send_queued(_target, target_packetizer);
+ target_queue_iterator = queues_.find(_target);
+ if (target_queue_iterator == queues_.end()) {
+ target_queue_iterator = queues_.insert(queues_.begin(),
+ std::make_pair(
+ _target,
+ std::deque<message_buffer_ptr_t>()
+ ));
+ }
+
+ // TODO compare against value from configuration here
+ if (target_packetizer->size() + _size > endpoint_impl<MaxBufferSize>::max_message_size_) {
+ target_queue_iterator->second.push_back(target_packetizer);
+ is_flushing = true;
packetizer_[_target] = std::make_shared<message_buffer_t>();
}
@@ -110,7 +125,8 @@ bool server_endpoint_impl<Protocol, MaxBufferSize>::send_intern( if (_flush) {
flush_timer_.cancel();
- send_queued(_target, target_packetizer);
+ target_queue_iterator->second.push_back(target_packetizer);
+ is_flushing = true;
packetizer_[_target] = std::make_shared<message_buffer_t>();
} else {
std::chrono::milliseconds flush_timeout(VSOMEIP_DEFAULT_FLUSH_TIMEOUT);
@@ -123,6 +139,11 @@ bool server_endpoint_impl<Protocol, MaxBufferSize>::send_intern( _target,
std::placeholders::_1));
}
+
+ if (is_flushing && target_queue_iterator->second.size() == 1) { // no writing in progress
+ send_queued(target_queue_iterator);
+ }
+
return true;
}
@@ -131,10 +152,9 @@ bool server_endpoint_impl<Protocol, MaxBufferSize>::flush( endpoint_type _target) {
bool is_flushed = false;
std::lock_guard<std::mutex> its_lock(mutex_);
- auto i = packetizer_.find(_target);
- if (i != packetizer_.end() && !i->second->empty()) {
- send_queued(_target, i->second);
- i->second = std::make_shared<message_buffer_t>();
+ auto queue_iterator = queues_.find(_target);
+ if (queue_iterator != queues_.end() && !queue_iterator->second.empty()) {
+ send_queued(queue_iterator);
is_flushed = true;
}
@@ -144,20 +164,22 @@ bool server_endpoint_impl<Protocol, MaxBufferSize>::flush( template<typename Protocol, int MaxBufferSize>
void server_endpoint_impl<Protocol, MaxBufferSize>::connect_cbk(
boost::system::error_code const &_error) {
+ (void)_error;
}
template<typename Protocol, int MaxBufferSize>
void server_endpoint_impl<Protocol, MaxBufferSize>::send_cbk(
- message_buffer_ptr_t _buffer, boost::system::error_code const &_error,
+ queue_iterator_type _queue_iterator, boost::system::error_code const &_error,
std::size_t _bytes) {
-#if 0
- std::stringstream msg;
- msg << "sei::scb (" << _error.message() << "): ";
- for (std::size_t i = 0; i < _buffer->size(); ++i)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
-#endif
+ (void)_bytes;
+
+ if (!_error) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ _queue_iterator->second.pop_front();
+ if (_queue_iterator->second.size() > 0) {
+ send_queued(_queue_iterator);
+ }
+ }
}
template<typename Protocol, int MaxBufferSize>
@@ -170,16 +192,15 @@ void server_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk( // Instantiate template
#ifndef WIN32
-template class server_endpoint_impl<boost::asio::local::stream_protocol,
-VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> ;
-#else
-// TODO: put instantiation for windows here!
-//template class server_endpoint_impl<boost::asio::ip::tcp,
-// VSOMEIP_MAX_TCP_MESSAGE_SIZE>;
+template class server_endpoint_impl<
+ boost::asio::local::stream_protocol,
+ VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> ;
#endif
-template class server_endpoint_impl<boost::asio::ip::tcp,
-VSOMEIP_MAX_TCP_MESSAGE_SIZE> ;
-template class server_endpoint_impl<boost::asio::ip::udp,
-VSOMEIP_MAX_UDP_MESSAGE_SIZE> ;
+template class server_endpoint_impl<
+ boost::asio::ip::tcp,
+ VSOMEIP_MAX_TCP_MESSAGE_SIZE> ;
+template class server_endpoint_impl<
+ boost::asio::ip::udp,
+ VSOMEIP_MAX_UDP_MESSAGE_SIZE> ;
} // namespace vsomeip
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp index cf91fa7..26c7424 100644 --- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp @@ -9,10 +9,10 @@ #include <vsomeip/constants.hpp>
#include <vsomeip/defines.hpp>
-#include <vsomeip/logger.hpp>
#include "../include/endpoint_host.hpp"
#include "../include/tcp_client_endpoint_impl.hpp"
+#include "../../logging/include/logger.hpp"
#include "../../utility/include/utility.hpp"
namespace ip = boost::asio::ip;
@@ -20,8 +20,11 @@ namespace ip = boost::asio::ip; namespace vsomeip {
tcp_client_endpoint_impl::tcp_client_endpoint_impl(
- std::shared_ptr< endpoint_host > _host, endpoint_type _remote, boost::asio::io_service &_io)
- : tcp_client_endpoint_base_impl(_host, _remote, _io) {
+ std::shared_ptr< endpoint_host > _host, endpoint_type _remote,
+ boost::asio::io_service &_io, std::uint32_t _max_message_size)
+ : tcp_client_endpoint_base_impl(_host, _remote, _io, _max_message_size),
+ recv_buffer_(_max_message_size, 0),
+ recv_buffer_size_(0) {
is_supporting_magic_cookies_ = true;
}
@@ -40,8 +43,7 @@ void tcp_client_endpoint_impl::connect() { socket_.open(remote_.protocol());
// Nagle algorithm off
- ip::tcp::no_delay option;
- socket_.set_option(option);
+ socket_.set_option(ip::tcp::no_delay(true));
socket_.async_connect(
remote_,
@@ -54,31 +56,44 @@ void tcp_client_endpoint_impl::connect() { }
void tcp_client_endpoint_impl::receive() {
- packet_buffer_ptr_t its_buffer
- = std::make_shared< packet_buffer_t >();
+ if (recv_buffer_size_ == max_message_size_) {
+ // Overrun -> Reset buffer
+ recv_buffer_size_ = 0;
+ }
+ size_t buffer_size = max_message_size_ - recv_buffer_size_;
socket_.async_receive(
- boost::asio::buffer(*its_buffer),
+ boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size),
std::bind(
&tcp_client_endpoint_impl::receive_cbk,
std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this()),
- its_buffer,
std::placeholders::_1,
std::placeholders::_2
)
);
}
-void tcp_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) {
+void tcp_client_endpoint_impl::send_queued() {
+ message_buffer_ptr_t its_buffer = queue_.front();
+
if (has_enabled_magic_cookies_)
- send_magic_cookie(_buffer);
+ send_magic_cookie(its_buffer);
+
+#if 0
+ std::stringstream msg;
+ msg << "tcei<" << remote_.address() << ":"
+ << std::dec << remote_.port() << ">::sq: ";
+ for (std::size_t i = 0; i < its_buffer->size(); i++)
+ msg << std::hex << std::setw(2) << std::setfill('0')
+ << (int)(*its_buffer)[i] << " ";
+ VSOMEIP_DEBUG << msg.str();
+#endif
boost::asio::async_write(
socket_,
- boost::asio::buffer(*_buffer),
+ boost::asio::buffer(*its_buffer),
std::bind(
&tcp_client_endpoint_base_impl::send_cbk,
shared_from_this(),
- _buffer,
std::placeholders::_1,
std::placeholders::_2
)
@@ -103,8 +118,8 @@ bool tcp_client_endpoint_impl::is_reliable() const { return true;
}
-bool tcp_client_endpoint_impl::is_magic_cookie() const {
- return (0 == std::memcmp(SERVICE_COOKIE, &message_[0], sizeof(SERVICE_COOKIE)));
+bool tcp_client_endpoint_impl::is_magic_cookie(size_t _offset) const {
+ return (0 == std::memcmp(SERVICE_COOKIE, &recv_buffer_[_offset], sizeof(SERVICE_COOKIE)));
}
void tcp_client_endpoint_impl::send_magic_cookie(message_buffer_ptr_t &_buffer) {
@@ -121,35 +136,36 @@ void tcp_client_endpoint_impl::send_magic_cookie(message_buffer_ptr_t &_buffer) }
void tcp_client_endpoint_impl::receive_cbk(
- packet_buffer_ptr_t _buffer,
boost::system::error_code const &_error, std::size_t _bytes) {
#if 0
std::stringstream msg;
msg << "cei::rcb (" << _error.message() << "): ";
- for (std::size_t i = 0; i < _bytes; ++i)
+ for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i)
msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*_buffer)[i] << " ";
+ << (int) recv_buffer_[i] << " ";
VSOMEIP_DEBUG << msg.str();
#endif
std::shared_ptr<endpoint_host> its_host = host_.lock();
if (its_host) {
if (!_error && 0 < _bytes) {
- this->message_.insert(this->message_.end(), _buffer->begin(),
- _buffer->begin() + _bytes);
+ recv_buffer_size_ += _bytes;
+ size_t its_iteration_gap = 0;
bool has_full_message;
do {
uint32_t current_message_size
- = utility::get_message_size(message_);
+ = utility::get_message_size(&recv_buffer_[its_iteration_gap],
+ (uint32_t) recv_buffer_size_);
has_full_message = (current_message_size > 0
- && current_message_size <= message_.size());
+ && current_message_size <= recv_buffer_size_);
if (has_full_message) {
bool needs_forwarding(true);
- if (is_magic_cookie()) {
+ if (is_magic_cookie(its_iteration_gap)) {
has_enabled_magic_cookies_ = true;
} else {
if (has_enabled_magic_cookies_) {
- uint32_t its_offset = find_magic_cookie(message_);
+ uint32_t its_offset = find_magic_cookie(&recv_buffer_[its_iteration_gap],
+ (uint32_t) recv_buffer_size_);
if (its_offset < current_message_size) {
VSOMEIP_ERROR << "Message includes Magic Cookie. Ignoring it.";
current_message_size = its_offset;
@@ -157,27 +173,44 @@ void tcp_client_endpoint_impl::receive_cbk( }
}
}
- if (needs_forwarding)
- its_host->on_message(&message_[0],
- current_message_size, this);
- message_.erase(message_.begin(),
- message_.begin() + current_message_size);
- } else if (has_enabled_magic_cookies_ && message_.size() > 0){
- uint32_t its_offset = find_magic_cookie(message_);
- if (its_offset < message_.size()) {
- message_.erase(message_.begin(),
- message_.begin() + its_offset);
+ if (needs_forwarding) {
+ if (!has_enabled_magic_cookies_) {
+ its_host->on_message(&recv_buffer_[its_iteration_gap],
+ current_message_size, this);
+ } else {
+ // Only call on_message without a magic cookie in front of the buffer!
+ if (!is_magic_cookie(its_iteration_gap)) {
+ its_host->on_message(&recv_buffer_[its_iteration_gap],
+ current_message_size, this);
+ }
+ }
+ }
+ recv_buffer_size_ -= current_message_size;
+ its_iteration_gap += current_message_size;
+ } else if (has_enabled_magic_cookies_ && recv_buffer_size_ > 0){
+ uint32_t its_offset = find_magic_cookie(&recv_buffer_[its_iteration_gap], recv_buffer_size_);
+ if (its_offset < recv_buffer_size_) {
+ recv_buffer_size_ -= its_offset;
+ its_iteration_gap += its_offset;
has_full_message = true; // trigger next loop
}
- } else if (message_.size() > VSOMEIP_MAX_TCP_MESSAGE_SIZE) {
+ } else if (current_message_size > max_message_size_) {
VSOMEIP_ERROR << "Message exceeds maximum message size. "
<< "Resetting receiver.";
- message_.clear();
+ recv_buffer_size_ = 0;
+ }
+ } while (has_full_message && recv_buffer_size_);
+ if (its_iteration_gap) {
+ // Copy incomplete message to front for next receive_cbk iteration
+ for (size_t i = 0; i < recv_buffer_size_; ++i) {
+ recv_buffer_[i] = recv_buffer_[i + its_iteration_gap];
}
- } while (has_full_message);
+ }
restart();
} else {
- receive();
+ if (socket_.is_open()) {
+ receive();
+ }
}
}
}
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp index be4ac5f..20391a0 100644 --- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp @@ -1,263 +1,322 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <iomanip>
-
-#include <boost/asio/write.hpp>
-
-#include <vsomeip/constants.hpp>
-#include <vsomeip/logger.hpp>
-
-#include "../include/endpoint_definition.hpp"
-#include "../include/endpoint_host.hpp"
-#include "../include/tcp_server_endpoint_impl.hpp"
-#include "../../utility/include/utility.hpp"
-
-namespace ip = boost::asio::ip;
-
-namespace vsomeip {
-
-tcp_server_endpoint_impl::tcp_server_endpoint_impl(
- std::shared_ptr<endpoint_host> _host, endpoint_type _local,
- boost::asio::io_service &_io)
- : tcp_server_endpoint_base_impl(_host, _local, _io),
- acceptor_(_io, _local),
- current_(0) {
- is_supporting_magic_cookies_ = true;
-}
-
-tcp_server_endpoint_impl::~tcp_server_endpoint_impl() {
-}
-
-bool tcp_server_endpoint_impl::is_local() const {
- return false;
-}
-
-void tcp_server_endpoint_impl::start() {
- connection::ptr new_connection = connection::create(this);
-
- acceptor_.async_accept(new_connection->get_socket(),
- std::bind(&tcp_server_endpoint_impl::accept_cbk,
- std::dynamic_pointer_cast<tcp_server_endpoint_impl>(
- shared_from_this()), new_connection,
- std::placeholders::_1));
-}
-
-void tcp_server_endpoint_impl::stop() {
- for (auto& i : connections_)
- i.second->stop();
- acceptor_.close();
-}
-
-bool tcp_server_endpoint_impl::send_to(
- const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data,
- uint32_t _size, bool _flush) {
- endpoint_type its_target(_target->get_address(), _target->get_port());
- return send_intern(its_target, _data, _size, _flush);
-}
-
-void tcp_server_endpoint_impl::send_queued(endpoint_type _target,
- message_buffer_ptr_t _buffer) {
- auto connection_iterator = connections_.find(_target);
- if (connection_iterator != connections_.end())
- connection_iterator->second->send_queued(_buffer);
-}
-
-tcp_server_endpoint_impl::endpoint_type
-tcp_server_endpoint_impl::get_remote() const {
- return current_->get_socket().remote_endpoint();
-}
-
-bool tcp_server_endpoint_impl::get_multicast(service_t, event_t,
- tcp_server_endpoint_impl::endpoint_type &) const {
- return false;
-}
-
-void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection,
- boost::system::error_code const &_error) {
-
- if (!_error) {
- socket_type &new_connection_socket = _connection->get_socket();
- endpoint_type remote = new_connection_socket.remote_endpoint();
-
- connections_[remote] = _connection;
- _connection->start();
- }
-
- start();
-}
-
-unsigned short tcp_server_endpoint_impl::get_local_port() const {
- return acceptor_.local_endpoint().port();
-}
-
-bool tcp_server_endpoint_impl::is_reliable() const {
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// class tcp_service_impl::connection
-///////////////////////////////////////////////////////////////////////////////
-tcp_server_endpoint_impl::connection::connection(
- tcp_server_endpoint_impl *_server) :
- socket_(_server->service_), server_(_server) {
-}
-
-tcp_server_endpoint_impl::connection::ptr
-tcp_server_endpoint_impl::connection::create(
- tcp_server_endpoint_impl *_server) {
- return ptr(new connection(_server));
-}
-
-tcp_server_endpoint_impl::socket_type &
-tcp_server_endpoint_impl::connection::get_socket() {
- return socket_;
-}
-
-void tcp_server_endpoint_impl::connection::start() {
- packet_buffer_ptr_t its_buffer = std::make_shared<packet_buffer_t>();
- socket_.async_receive(boost::asio::buffer(*its_buffer),
- std::bind(&tcp_server_endpoint_impl::connection::receive_cbk,
- shared_from_this(), its_buffer, std::placeholders::_1,
- std::placeholders::_2));
-}
-
-void tcp_server_endpoint_impl::connection::stop() {
- socket_.close();
-}
-
-void tcp_server_endpoint_impl::connection::send_queued(
- message_buffer_ptr_t _buffer) {
- if (server_->has_enabled_magic_cookies_)
- send_magic_cookie(_buffer);
-
- boost::asio::async_write(socket_, boost::asio::buffer(*_buffer),
- std::bind(&tcp_server_endpoint_base_impl::send_cbk,
- server_->shared_from_this(),
- _buffer, std::placeholders::_1,
- std::placeholders::_2));
-}
-
-void tcp_server_endpoint_impl::connection::send_magic_cookie(
- message_buffer_ptr_t &_buffer) {
- if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >=
- VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) {
- _buffer->insert(_buffer->begin(), SERVICE_COOKIE,
- SERVICE_COOKIE + sizeof(SERVICE_COOKIE));
- }
-}
-
-bool tcp_server_endpoint_impl::connection::is_magic_cookie() const {
- return (0 == std::memcmp(CLIENT_COOKIE, &message_[0],
- sizeof(CLIENT_COOKIE)));
-}
-
-void tcp_server_endpoint_impl::connection::receive_cbk(
- packet_buffer_ptr_t _buffer, boost::system::error_code const &_error,
- std::size_t _bytes) {
-#if 0
- std::stringstream msg;
- for (std::size_t i = 0; i < _bytes; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int) (*_buffer)[i] << " ";
- VSOMEIP_DEBUG<< msg.str();
-#endif
- std::shared_ptr<endpoint_host> its_host = server_->host_.lock();
- if (its_host) {
- if (!_error && 0 < _bytes) {
- message_.insert(message_.end(), _buffer->begin(),
- _buffer->begin() + _bytes);
-
- static int i = 1;
-
- bool has_full_message;
- do {
- uint32_t current_message_size
- = utility::get_message_size(message_);
- has_full_message = (current_message_size > 0
- && current_message_size <= message_.size());
- if (has_full_message) {
- bool needs_forwarding(true);
- if (is_magic_cookie()) {
- server_->has_enabled_magic_cookies_ = true;
- } else {
- if (server_->has_enabled_magic_cookies_) {
- uint32_t its_offset
- = server_->find_magic_cookie(message_);
- if (its_offset < current_message_size) {
- VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing.";
- current_message_size = its_offset;
- needs_forwarding = false;
- }
- }
- }
- if (needs_forwarding) {
- if (utility::is_request(message_[VSOMEIP_MESSAGE_TYPE_POS])) {
- client_t its_client;
- std::memcpy(&its_client,
- &message_[VSOMEIP_CLIENT_POS_MIN],
- sizeof(client_t));
- session_t its_session;
- std::memcpy(&its_session,
- &message_[VSOMEIP_SESSION_POS_MIN],
- sizeof(session_t));
- server_->clients_[its_client][its_session] =
- socket_.remote_endpoint();
- }
- its_host->on_message(&message_[0], current_message_size, server_);
- }
- message_.erase(message_.begin(), message_.begin() + current_message_size);
- } else if (server_->has_enabled_magic_cookies_ && message_.size() > 0){
- uint32_t its_offset = server_->find_magic_cookie(message_);
- if (its_offset < message_.size()) {
- VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing.";
- message_.erase(message_.begin(), message_.begin() + its_offset);
- has_full_message = true; // trigger next loop
- }
- } else if (message_.size() > VSOMEIP_MAX_TCP_MESSAGE_SIZE) {
- VSOMEIP_ERROR << "Message exceeds maximum message size. Resetting receiver.";
- message_.clear();
- }
- } while (has_full_message);
-
- start();
- }
- }
-}
-
-client_t tcp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) {
- endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
- auto its_remote = connections_.find(endpoint);
- if (its_remote != connections_.end()) {
- return its_remote->second->get_client(endpoint);
- }
- return 0;
-}
-
-client_t tcp_server_endpoint_impl::connection::get_client(endpoint_type _endpoint_type) {
- for (auto its_client : server_->clients_) {
- for (auto its_session : server_->clients_[its_client.first]) {
- auto endpoint = its_session.second;
- if (endpoint == _endpoint_type) {
- // TODO: Check system byte order before convert!
- client_t client = its_client.first << 8 | its_client.first >> 8;
- return client;
- }
- }
- }
- return 0;
-}
-
-// Dummies
-void tcp_server_endpoint_impl::receive() {
- // intentionally left empty
-}
-
-void tcp_server_endpoint_impl::restart() {
- // intentionally left empty
-}
-
-} // namespace vsomeip
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <iomanip> + +#include <boost/asio/write.hpp> + +#include <vsomeip/constants.hpp> + +#include "../include/endpoint_definition.hpp" +#include "../include/endpoint_host.hpp" +#include "../include/tcp_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" +#include "../../utility/include/utility.hpp" + +namespace ip = boost::asio::ip; + +namespace vsomeip { + +tcp_server_endpoint_impl::tcp_server_endpoint_impl( + std::shared_ptr<endpoint_host> _host, endpoint_type _local, + boost::asio::io_service &_io, std::uint32_t _max_message_size) + : tcp_server_endpoint_base_impl(_host, _local, _io, _max_message_size), + acceptor_(_io, _local), + current_(0) { + is_supporting_magic_cookies_ = true; +} + +tcp_server_endpoint_impl::~tcp_server_endpoint_impl() { +} + +bool tcp_server_endpoint_impl::is_local() const { + return false; +} + +void tcp_server_endpoint_impl::start() { + connection::ptr new_connection = connection::create(this, max_message_size_); + + acceptor_.async_accept(new_connection->get_socket(), + std::bind(&tcp_server_endpoint_impl::accept_cbk, + std::dynamic_pointer_cast<tcp_server_endpoint_impl>( + shared_from_this()), new_connection, + std::placeholders::_1)); +} + +void tcp_server_endpoint_impl::stop() { + for (auto& i : connections_) + i.second->stop(); + acceptor_.close(); +} + +bool tcp_server_endpoint_impl::send_to( + const std::shared_ptr<endpoint_definition> _target, + const byte_t *_data, + uint32_t _size, bool _flush) { + endpoint_type its_target(_target->get_address(), _target->get_port()); + return send_intern(its_target, _data, _size, _flush); +} + +void tcp_server_endpoint_impl::send_queued(queue_iterator_type _queue_iterator) { + auto connection_iterator = connections_.find(_queue_iterator->first); + if (connection_iterator != connections_.end()) + connection_iterator->second->send_queued(_queue_iterator); +} + +tcp_server_endpoint_impl::endpoint_type +tcp_server_endpoint_impl::get_remote() const { + return current_->get_socket().remote_endpoint(); +} + +bool tcp_server_endpoint_impl::get_multicast(service_t, event_t, + tcp_server_endpoint_impl::endpoint_type &) const { + return false; +} + +void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection, + boost::system::error_code const &_error) { + + if (!_error) { + socket_type &new_connection_socket = _connection->get_socket(); + endpoint_type remote = new_connection_socket.remote_endpoint(); + + connections_[remote] = _connection; + _connection->start(); + + start(); + } +} + +unsigned short tcp_server_endpoint_impl::get_local_port() const { + return acceptor_.local_endpoint().port(); +} + +bool tcp_server_endpoint_impl::is_reliable() const { + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// class tcp_service_impl::connection +/////////////////////////////////////////////////////////////////////////////// +tcp_server_endpoint_impl::connection::connection( + tcp_server_endpoint_impl *_server, std::uint32_t _max_message_size) : + socket_(_server->service_), server_(_server), + max_message_size_(_max_message_size), + recv_buffer_(_max_message_size, 0), + recv_buffer_size_(0) { +} + +tcp_server_endpoint_impl::connection::ptr +tcp_server_endpoint_impl::connection::create( + tcp_server_endpoint_impl *_server, std::uint32_t _max_message_size) { + return ptr(new connection(_server, _max_message_size)); +} + +tcp_server_endpoint_impl::socket_type & +tcp_server_endpoint_impl::connection::get_socket() { + return socket_; +} + +void tcp_server_endpoint_impl::connection::start() { + receive(); + // Nagle algorithm off + socket_.set_option(ip::tcp::no_delay(true)); +} + +void tcp_server_endpoint_impl::connection::receive() { + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + std::lock_guard<std::mutex> its_lock(stop_mutex_); + if(socket_.is_open()) { + size_t buffer_size = max_message_size_ - recv_buffer_size_; + socket_.async_receive(boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), + std::bind(&tcp_server_endpoint_impl::connection::receive_cbk, + shared_from_this(), std::placeholders::_1, + std::placeholders::_2)); + } +} + +void tcp_server_endpoint_impl::connection::stop() { + std::lock_guard<std::mutex> its_lock(stop_mutex_); + if(socket_.is_open()) { + socket_.shutdown(socket_.shutdown_both); + socket_.close(); + } +} + +void tcp_server_endpoint_impl::connection::send_queued( + queue_iterator_type _queue_iterator) { + message_buffer_ptr_t its_buffer = _queue_iterator->second.front(); + + if (server_->has_enabled_magic_cookies_) + send_magic_cookie(its_buffer); + + boost::asio::async_write(socket_, boost::asio::buffer(*its_buffer), + std::bind(&tcp_server_endpoint_base_impl::send_cbk, + server_->shared_from_this(), + _queue_iterator, std::placeholders::_1, + std::placeholders::_2)); +} + +void tcp_server_endpoint_impl::connection::send_magic_cookie( + message_buffer_ptr_t &_buffer) { + if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >= + VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) { + _buffer->insert(_buffer->begin(), SERVICE_COOKIE, + SERVICE_COOKIE + sizeof(SERVICE_COOKIE)); + } +} + +bool tcp_server_endpoint_impl::connection::is_magic_cookie(size_t _offset) const { + return (0 == std::memcmp(CLIENT_COOKIE, &recv_buffer_[_offset], + sizeof(CLIENT_COOKIE))); +} + +void tcp_server_endpoint_impl::connection::receive_cbk( + boost::system::error_code const &_error, + std::size_t _bytes) { +#if 0 + std::stringstream msg; + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') + << (int) recv_buffer_[i] << " "; + VSOMEIP_DEBUG<< msg.str(); +#endif + std::shared_ptr<endpoint_host> its_host = server_->host_.lock(); + if (its_host) { + if (!_error && 0 < _bytes) { + recv_buffer_size_ += _bytes; + + size_t its_iteration_gap = 0; + bool has_full_message; + do { + uint32_t current_message_size + = utility::get_message_size(&recv_buffer_[its_iteration_gap], + (uint32_t) recv_buffer_size_); + has_full_message = (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE + && current_message_size <= recv_buffer_size_); + if (has_full_message) { + bool needs_forwarding(true); + if (is_magic_cookie(its_iteration_gap)) { + server_->has_enabled_magic_cookies_ = true; + } else { + if (server_->has_enabled_magic_cookies_) { + uint32_t its_offset + = server_->find_magic_cookie(&recv_buffer_[its_iteration_gap], + recv_buffer_size_); + if (its_offset < current_message_size) { + VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_error(&recv_buffer_[its_iteration_gap], + static_cast<length_t>(recv_buffer_size_), server_); + } + current_message_size = its_offset; + needs_forwarding = false; + } + } + } + if (needs_forwarding) { + if (utility::is_request(recv_buffer_[VSOMEIP_MESSAGE_TYPE_POS])) { + client_t its_client; + std::memcpy(&its_client, + &recv_buffer_[VSOMEIP_CLIENT_POS_MIN], + sizeof(client_t)); + session_t its_session; + std::memcpy(&its_session, + &recv_buffer_[VSOMEIP_SESSION_POS_MIN], + sizeof(session_t)); + { + std::lock_guard<std::mutex> its_lock(stop_mutex_); + if (socket_.is_open()) { + server_->clients_[its_client][its_session] = + socket_.remote_endpoint(); + server_->current_ = this; + } + } + } + if (!server_->has_enabled_magic_cookies_) { + its_host->on_message(&recv_buffer_[its_iteration_gap], + current_message_size, server_); + } else { + // Only call on_message without a magic cookie in front of the buffer! + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_message(&recv_buffer_[its_iteration_gap], + current_message_size, server_); + } + } + } + recv_buffer_size_ -= current_message_size; + its_iteration_gap += current_message_size; + } else if (server_->has_enabled_magic_cookies_ && recv_buffer_size_ > 0){ + uint32_t its_offset = + server_->find_magic_cookie(&recv_buffer_[its_iteration_gap], + recv_buffer_size_); + if (its_offset < recv_buffer_size_) { + VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_error(&recv_buffer_[its_iteration_gap], + static_cast<length_t>(recv_buffer_size_), server_); + } + recv_buffer_size_ -= its_offset; + its_iteration_gap += its_offset; + has_full_message = true; // trigger next loop + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_error(&recv_buffer_[its_iteration_gap], + static_cast<length_t>(recv_buffer_size_), server_); + } + } + } else if (current_message_size > max_message_size_) { + VSOMEIP_ERROR << "Message exceeds maximum message size (" + << std::dec << current_message_size + << "). Resetting receiver."; + recv_buffer_size_ = 0; + } + } while (has_full_message && recv_buffer_size_); + if (its_iteration_gap) { + // Copy incomplete message to front for next receive_cbk iteration + for (size_t i = 0; i < recv_buffer_size_; ++i) { + recv_buffer_[i] = recv_buffer_[i + its_iteration_gap]; + } + } + receive(); + } + } +} + +client_t tcp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) { + endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port()); + auto its_remote = connections_.find(endpoint); + if (its_remote != connections_.end()) { + return its_remote->second->get_client(endpoint); + } + return 0; +} + +client_t tcp_server_endpoint_impl::connection::get_client(endpoint_type _endpoint_type) { + for (auto its_client : server_->clients_) { + for (auto its_session : server_->clients_[its_client.first]) { + auto endpoint = its_session.second; + if (endpoint == _endpoint_type) { + // TODO: Check system byte order before convert! + client_t client = client_t(its_client.first << 8 | its_client.first >> 8); + return client; + } + } + } + return 0; +} + +// Dummies +void tcp_server_endpoint_impl::receive() { + // intentionally left empty +} + +void tcp_server_endpoint_impl::restart() { + // intentionally left empty +} + +} // namespace vsomeip diff --git a/implementation/endpoints/src/udp_client_endpoint_impl.cpp b/implementation/endpoints/src/udp_client_endpoint_impl.cpp index 95f12c3..a5a90cc 100644 --- a/implementation/endpoints/src/udp_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/udp_client_endpoint_impl.cpp @@ -8,10 +8,9 @@ #include <boost/asio/ip/multicast.hpp>
-#include <vsomeip/logger.hpp>
-
#include "../include/endpoint_host.hpp"
#include "../include/udp_client_endpoint_impl.hpp"
+#include "../../logging/include/logger.hpp"
#include "../../utility/include/utility.hpp"
namespace vsomeip {
@@ -19,7 +18,9 @@ namespace vsomeip { udp_client_endpoint_impl::udp_client_endpoint_impl(
std::shared_ptr< endpoint_host > _host, endpoint_type _remote,
boost::asio::io_service &_io)
- : udp_client_endpoint_base_impl(_host, _remote, _io) {
+ : udp_client_endpoint_base_impl(_host, _remote, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE),
+ recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0),
+ recv_buffer_size_(0) {
}
udp_client_endpoint_impl::~udp_client_endpoint_impl() {
@@ -43,44 +44,44 @@ void udp_client_endpoint_impl::connect() { void udp_client_endpoint_impl::start() {
socket_.open(remote_.protocol());
connect();
- receive();
}
-void udp_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) {
+void udp_client_endpoint_impl::send_queued() {
+ message_buffer_ptr_t its_buffer = queue_.front();
#if 0
std::stringstream msg;
msg << "ucei<" << remote_.address() << ":"
<< std::dec << remote_.port() << ">::sq: ";
- for (std::size_t i = 0; i < _buffer->size(); i++)
+ for (std::size_t i = 0; i < its_buffer->size(); i++)
msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*_buffer)[i] << " ";
+ << (int)(*its_buffer)[i] << " ";
VSOMEIP_DEBUG << msg.str();
#endif
socket_.async_send(
- boost::asio::buffer(*_buffer),
+ boost::asio::buffer(*its_buffer),
std::bind(
&udp_client_endpoint_base_impl::send_cbk,
shared_from_this(),
- _buffer,
std::placeholders::_1,
std::placeholders::_2
)
);
- receive();
}
void udp_client_endpoint_impl::receive() {
- packet_buffer_ptr_t its_buffer
- = std::make_shared< packet_buffer_t >();
+ if (recv_buffer_size_ == max_message_size_) {
+ // Overrun -> Reset buffer
+ recv_buffer_size_ = 0;
+ }
+ size_t buffer_size = max_message_size_ - recv_buffer_size_;
socket_.async_receive_from(
- boost::asio::buffer(*its_buffer),
+ boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size),
remote_,
std::bind(
&udp_client_endpoint_impl::receive_cbk,
std::dynamic_pointer_cast<
udp_client_endpoint_impl
>(shared_from_this()),
- its_buffer,
std::placeholders::_1,
std::placeholders::_2
)
@@ -101,69 +102,37 @@ unsigned short udp_client_endpoint_impl::get_remote_port() const { return socket_.remote_endpoint().port();
}
-void udp_client_endpoint_impl::join(const std::string &_address) {
-
- if (remote_.address().is_v4()) {
- try {
- socket_.set_option(
- boost::asio::ip::udp::socket::reuse_address(true));
- socket_.set_option(boost::asio::ip::multicast::join_group(
- boost::asio::ip::address::from_string(_address)));
- }
- catch (...) {
- }
- } else {
- // TODO: support multicast for IPv6
- }
-}
-
-void udp_client_endpoint_impl::leave(const std::string &_address) {
- if (remote_.address().is_v4()) {
- try {
- socket_.set_option(
- boost::asio::ip::udp::socket::reuse_address(true));
- socket_.set_option(boost::asio::ip::multicast::leave_group(
- boost::asio::ip::address::from_string(_address)));
- }
- catch (...) {
- }
- } else {
- // TODO: support multicast for IPv6
- }
-}
-
void udp_client_endpoint_impl::receive_cbk(
- packet_buffer_ptr_t _buffer,
boost::system::error_code const &_error, std::size_t _bytes) {
std::shared_ptr<endpoint_host> its_host = host_.lock();
if (!_error && 0 < _bytes && its_host) {
#if 0
std::stringstream msg;
msg << "ucei::rcb(" << _error.message() << "): ";
- for (std::size_t i = 0; i < _bytes; ++i)
+ for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i)
msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*_buffer)[i] << " ";
+ << (int) recv_buffer_[i] << " ";
VSOMEIP_DEBUG << msg.str();
#endif
- this->message_.insert(this->message_.end(), _buffer->begin(),
- _buffer->begin() + _bytes);
-
- bool has_full_message;
- do {
- uint32_t current_message_size
- = utility::get_message_size(this->message_);
-
- has_full_message = (current_message_size > 0
- && current_message_size <= this->message_.size());
- if (has_full_message) {
- its_host->on_message(&message_[0], current_message_size, this);
- this->message_.erase(this->message_.begin(),
- this->message_.begin() + current_message_size);
- }
- } while (has_full_message);
+ recv_buffer_size_ += _bytes;
+ uint32_t current_message_size
+ = utility::get_message_size(&this->recv_buffer_[0],
+ (uint32_t) recv_buffer_size_);
+ if (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE &&
+ current_message_size <= _bytes) {
+ its_host->on_message(&recv_buffer_[0], current_message_size, this);
+ } else {
+ VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad length field";
+ }
+ recv_buffer_size_ = 0;
+ }
+ if (!_error) {
+ receive();
+ } else {
+ if (socket_.is_open()) {
+ receive();
+ }
}
-
- receive();
}
} // namespace vsomeip
diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp index f0fee37..f29dfba 100644 --- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp @@ -1,251 +1,264 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <iomanip>
-#include <sstream>
-
-#include <boost/asio/ip/multicast.hpp>
-
-#include <vsomeip/logger.hpp>
-
-#include "../include/endpoint_definition.hpp"
-#include "../include/endpoint_host.hpp"
-#include "../include/udp_server_endpoint_impl.hpp"
-#include "../../utility/include/byteorder.hpp"
-#include "../../utility/include/utility.hpp"
-
-namespace ip = boost::asio::ip;
-
-namespace vsomeip {
-
-udp_server_endpoint_impl::udp_server_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _local,
- boost::asio::io_service &_io)
- : server_endpoint_impl<
- ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE
- >(_host, _local, _io),
- socket_(_io, _local.protocol()) {
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <iomanip> +#include <sstream> + +#include <boost/asio/ip/multicast.hpp> + +#include "../include/endpoint_definition.hpp" +#include "../include/endpoint_host.hpp" +#include "../include/udp_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" +#include "../../utility/include/byteorder.hpp" +#include "../../utility/include/utility.hpp" +#include "../../service_discovery/include/defines.hpp" + +namespace ip = boost::asio::ip; + +namespace vsomeip { + +udp_server_endpoint_impl::udp_server_endpoint_impl( + std::shared_ptr< endpoint_host > _host, + endpoint_type _local, + boost::asio::io_service &_io) + : server_endpoint_impl< + ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE + >(_host, _local, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE), + socket_(_io, _local.protocol()), + recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0), + recv_buffer_size_(0) { boost::system::error_code ec; - boost::asio::socket_base::reuse_address optionReuseAddress(true);
+ boost::asio::socket_base::reuse_address optionReuseAddress(true); socket_.set_option(optionReuseAddress); socket_.bind(_local, ec); - boost::asio::detail::throw_error(ec, "bind");
-
- boost::asio::socket_base::broadcast option(true);
- socket_.set_option(option);
-}
-
-udp_server_endpoint_impl::~udp_server_endpoint_impl() {
-}
-
-bool udp_server_endpoint_impl::is_local() const {
- return false;
-}
-
-void udp_server_endpoint_impl::start() {
- receive();
-}
-
-void udp_server_endpoint_impl::stop() {
- if (socket_.is_open())
- socket_.close();
-}
-
-void udp_server_endpoint_impl::receive() {
- packet_buffer_ptr_t its_buffer
- = std::make_shared< packet_buffer_t >();
- socket_.async_receive_from(
- boost::asio::buffer(*its_buffer),
- remote_,
- std::bind(
- &udp_server_endpoint_impl::receive_cbk,
- std::dynamic_pointer_cast<
- udp_server_endpoint_impl >(shared_from_this()),
- its_buffer,
- std::placeholders::_1,
- std::placeholders::_2
- )
- );
-}
-
-void udp_server_endpoint_impl::restart() {
- receive();
-}
-
-bool udp_server_endpoint_impl::send_to(
- const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush) {
- endpoint_type its_target(_target->get_address(), _target->get_port());
- return send_intern(its_target, _data, _size, _flush);
-}
-
-void udp_server_endpoint_impl::send_queued(
- endpoint_type _target, message_buffer_ptr_t _buffer) {
-#if 0
- std::stringstream msg;
- msg << "usei::sq(" << _target.address().to_string() << ":"
- << _target.port() << "): ";
- for (std::size_t i = 0; i < _buffer->size(); ++i)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
-#endif
- socket_.async_send_to(
- boost::asio::buffer(*_buffer),
- _target,
- std::bind(
- &udp_server_endpoint_base_impl::send_cbk,
- shared_from_this(),
- _buffer,
- std::placeholders::_1,
- std::placeholders::_2
- )
- );
-}
-
-udp_server_endpoint_impl::endpoint_type
-udp_server_endpoint_impl::get_remote() const {
- return remote_;
-}
-
-bool udp_server_endpoint_impl::get_multicast(service_t _service, event_t _event,
- udp_server_endpoint_impl::endpoint_type &_target) const {
- bool is_valid(false);
- auto find_service = multicasts_.find(_service);
- if (find_service != multicasts_.end()) {
- auto find_event = find_service->second.find(_event);
- if (find_event != find_service->second.end()) {
- _target = find_event->second;
- is_valid = true;
- }
- }
- return is_valid;
-}
-
-void udp_server_endpoint_impl::join(const std::string &_address) {
- if (local_.address().is_v4()) {
- try {
- socket_.set_option(
- boost::asio::ip::udp::socket::reuse_address(true));
- socket_.set_option(
- boost::asio::ip::multicast::enable_loopback(false));
- socket_.set_option(boost::asio::ip::multicast::join_group(
- boost::asio::ip::address::from_string(_address).to_v4()));
- }
- catch (const std::exception &e) {
- VSOMEIP_ERROR << e.what();
- }
- } else {
- // TODO: support multicast for IPv6
- }
-}
-
-void udp_server_endpoint_impl::leave(const std::string &_address) {
- if (local_.address().is_v4()) {
- try {
- socket_.set_option(boost::asio::ip::multicast::leave_group(
- boost::asio::ip::address::from_string(_address)));
- }
- catch (...) {
-
- }
- } else {
- // TODO: support multicast for IPv6
- }
-}
-
-void udp_server_endpoint_impl::add_multicast(
- service_t _service, instance_t _instance,
- const std::string &_address, uint16_t _port) {
- endpoint_type its_endpoint(
- boost::asio::ip::address::from_string(_address), _port);
- multicasts_[_service][_instance] = its_endpoint;
-}
-
-void udp_server_endpoint_impl::remove_multicast(
- service_t _service, instance_t _instance) {
- auto found_service = multicasts_.find(_service);
- if (found_service != multicasts_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- found_service->second.erase(_instance);
- }
- }
-}
-
-unsigned short udp_server_endpoint_impl::get_local_port() const {
- return socket_.local_endpoint().port();
-}
-
-// TODO: find a better way to structure the receive functions
-void udp_server_endpoint_impl::receive_cbk(
- packet_buffer_ptr_t _buffer,
- boost::system::error_code const &_error, std::size_t _bytes) {
-#if 0
- std::stringstream msg;
- msg << "usei::rcb(" << _error.message() << "): ";
- for (std::size_t i = 0; i < _bytes; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
-#endif
- std::shared_ptr<endpoint_host> its_host = this->host_.lock();
- if (its_host) {
- if (!_error && 0 < _bytes) {
- message_.insert(message_.end(), _buffer->begin(),
- _buffer->begin() + _bytes);
-
- bool has_full_message;
- do {
- uint32_t current_message_size
- = utility::get_message_size(message_);
- has_full_message = (current_message_size > 0
- && current_message_size <= message_.size());
- if (has_full_message) {
- if (utility::is_request(
- message_[VSOMEIP_MESSAGE_TYPE_POS])) {
- client_t its_client;
- std::memcpy(&its_client,
- &message_[VSOMEIP_CLIENT_POS_MIN],
- sizeof(client_t));
- session_t its_session;
- std::memcpy(&its_session,
- &message_[VSOMEIP_SESSION_POS_MIN],
- sizeof(session_t));
- clients_[its_client][its_session] = remote_;
- }
-
- its_host->on_message(&message_[0],
- current_message_size, this);
- message_.erase(message_.begin(),
- message_.begin() + current_message_size);
- }
- } while (has_full_message);
-
- restart();
- } else {
- receive();
- }
- }
-}
-
-client_t udp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) {
- endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
- for (auto its_client : clients_) {
- for (auto its_session : clients_[its_client.first]) {
- if (endpoint == its_session.second) {
- // TODO: Check system byte order before convert!
- client_t client = its_client.first << 8 | its_client.first >> 8;
- return client;
- }
- }
- }
- return 0;
-}
-
-} // namespace vsomeip
+ boost::asio::detail::throw_error(ec, "bind"); + + boost::asio::socket_base::broadcast option(true); + socket_.set_option(option); +} + +udp_server_endpoint_impl::~udp_server_endpoint_impl() { +} + +bool udp_server_endpoint_impl::is_local() const { + return false; +} + +void udp_server_endpoint_impl::start() { + receive(); +} + +void udp_server_endpoint_impl::stop() { + std::lock_guard<std::mutex> its_lock(stop_mutex_); + if (socket_.is_open()) { + socket_.close(); + } +} + +void udp_server_endpoint_impl::receive() { + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + std::lock_guard<std::mutex> its_lock(stop_mutex_); + if(socket_.is_open()) { + size_t buffer_size = max_message_size_ - recv_buffer_size_; + socket_.async_receive_from( + boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), + remote_, + std::bind( + &udp_server_endpoint_impl::receive_cbk, + std::dynamic_pointer_cast< + udp_server_endpoint_impl >(shared_from_this()), + std::placeholders::_1, + std::placeholders::_2 + ) + ); + } +} + +void udp_server_endpoint_impl::restart() { + receive(); +} + +bool udp_server_endpoint_impl::send_to( + const std::shared_ptr<endpoint_definition> _target, + const byte_t *_data, uint32_t _size, bool _flush) { + endpoint_type its_target(_target->get_address(), _target->get_port()); + return send_intern(its_target, _data, _size, _flush); +} + +void udp_server_endpoint_impl::send_queued( + queue_iterator_type _queue_iterator) { + message_buffer_ptr_t its_buffer = _queue_iterator->second.front(); +#if 0 + std::stringstream msg; + msg << "usei::sq(" << _queue_iterator->first.address().to_string() << ":" + << _queue_iterator->first.port() << "): "; + for (std::size_t i = 0; i < its_buffer->size(); ++i) + msg << std::hex << std::setw(2) << std::setfill('0') + << (int)(*its_buffer)[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif + socket_.async_send_to( + boost::asio::buffer(*its_buffer), + _queue_iterator->first, + std::bind( + &udp_server_endpoint_base_impl::send_cbk, + shared_from_this(), + _queue_iterator, + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +udp_server_endpoint_impl::endpoint_type +udp_server_endpoint_impl::get_remote() const { + return remote_; +} + +bool udp_server_endpoint_impl::get_multicast(service_t _service, event_t _event, + udp_server_endpoint_impl::endpoint_type &_target) const { + bool is_valid(false); + auto find_service = multicasts_.find(_service); + if (find_service != multicasts_.end()) { + auto find_event = find_service->second.find(_event); + if (find_event != find_service->second.end()) { + _target = find_event->second; + is_valid = true; + } + } + return is_valid; +} + +void udp_server_endpoint_impl::join(const std::string &_address) { + try { + if (local_.address().is_v4()) { + socket_.set_option( + boost::asio::ip::udp::socket::reuse_address(true)); + socket_.set_option( + boost::asio::ip::multicast::enable_loopback(false)); + socket_.set_option(boost::asio::ip::multicast::join_group( + boost::asio::ip::address::from_string(_address).to_v4())); + } else if (local_.address().is_v6()) { + socket_.set_option( + boost::asio::ip::udp::socket::reuse_address(true)); + socket_.set_option( + boost::asio::ip::multicast::enable_loopback(false)); + socket_.set_option(boost::asio::ip::multicast::join_group( + boost::asio::ip::address::from_string(_address).to_v6())); + } + } + catch (const std::exception &e) { + VSOMEIP_ERROR << e.what(); + } +} + +void udp_server_endpoint_impl::leave(const std::string &_address) { + try { + if (local_.address().is_v4()) { + socket_.set_option(boost::asio::ip::multicast::leave_group( + boost::asio::ip::address::from_string(_address))); + } else if (local_.address().is_v6()) { + socket_.set_option(boost::asio::ip::multicast::leave_group( + boost::asio::ip::address::from_string(_address))); + } + } + catch (const std::exception &e) { + VSOMEIP_ERROR << e.what(); + } +} + +void udp_server_endpoint_impl::add_multicast( + service_t _service, instance_t _instance, + const std::string &_address, uint16_t _port) { + endpoint_type its_endpoint( + boost::asio::ip::address::from_string(_address), _port); + multicasts_[_service][_instance] = its_endpoint; +} + +void udp_server_endpoint_impl::remove_multicast( + service_t _service, instance_t _instance) { + auto found_service = multicasts_.find(_service); + if (found_service != multicasts_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + found_service->second.erase(_instance); + } + } +} + +unsigned short udp_server_endpoint_impl::get_local_port() const { + return socket_.local_endpoint().port(); +} + +// TODO: find a better way to structure the receive functions +void udp_server_endpoint_impl::receive_cbk( + boost::system::error_code const &_error, std::size_t _bytes) { +#if 0 + std::stringstream msg; + msg << "usei::rcb(" << _error.message() << "): "; + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') + << (int) recv_buffer_[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif + std::shared_ptr<endpoint_host> its_host = this->host_.lock(); + if (its_host) { + if (!_error && 0 < _bytes) { + recv_buffer_size_ += _bytes; + uint32_t current_message_size + = utility::get_message_size(&this->recv_buffer_[0], + (uint32_t) recv_buffer_size_); + if (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE && + current_message_size <= _bytes) { + if (utility::is_request( + recv_buffer_[VSOMEIP_MESSAGE_TYPE_POS])) { + client_t its_client; + std::memcpy(&its_client, + &recv_buffer_[VSOMEIP_CLIENT_POS_MIN], + sizeof(client_t)); + session_t its_session; + std::memcpy(&its_session, + &recv_buffer_[VSOMEIP_SESSION_POS_MIN], + sizeof(session_t)); + clients_[its_client][its_session] = remote_; + } + its_host->on_message(&recv_buffer_[0], current_message_size, this); + } else { + VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad length field"; + service_t its_service = VSOMEIP_BYTES_TO_WORD(recv_buffer_[VSOMEIP_SERVICE_POS_MIN], + recv_buffer_[VSOMEIP_SERVICE_POS_MAX]); + if (its_service != VSOMEIP_SD_SERVICE) { + its_host->on_error(&recv_buffer_[0], (uint32_t)_bytes, this); + } + } + recv_buffer_size_ = 0; + restart(); + } else { + receive(); + } + } +} + +client_t udp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) { + endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port()); + for (auto its_client : clients_) { + for (auto its_session : clients_[its_client.first]) { + if (endpoint == its_session.second) { + // TODO: Check system byte order before convert! + client_t client = client_t(its_client.first << 8 | its_client.first >> 8); + return client; + } + } + } + return 0; +} + +} // namespace vsomeip diff --git a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp new file mode 100644 index 0000000..7700874 --- /dev/null +++ b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp @@ -0,0 +1,114 @@ +// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <vsomeip/constants.hpp> + +#include "../include/virtual_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" + +namespace vsomeip { + +virtual_server_endpoint_impl::virtual_server_endpoint_impl( + const std::string &_address, uint16_t _port, bool _reliable) + : address_(_address), port_(_port), reliable_(_reliable), use_count_(0) { +} + +virtual_server_endpoint_impl::~virtual_server_endpoint_impl() { +} + +void virtual_server_endpoint_impl::start() { +} + +void virtual_server_endpoint_impl::stop() { +} + +bool virtual_server_endpoint_impl::is_connected() const { + return false; +} + +bool virtual_server_endpoint_impl::send(const byte_t *_data, uint32_t _size, + bool _flush) { + (void)_data; + (void)_size; + (void)_flush; + return false; +} + +bool virtual_server_endpoint_impl::send_to( + const std::shared_ptr<endpoint_definition> _target, + const byte_t *_data, uint32_t _size, bool _flush) { + (void)_target; + (void)_data; + (void)_size; + (void)_flush; + return false; +} + +void virtual_server_endpoint_impl::enable_magic_cookies() { +} + +void virtual_server_endpoint_impl::receive() { +} + +void virtual_server_endpoint_impl::join(const std::string &_address) { + (void)_address; +} + +void virtual_server_endpoint_impl::leave(const std::string &_address) { + (void)_address; +} + +void virtual_server_endpoint_impl::add_multicast( + service_t _service, event_t _event, + const std::string &_address, uint16_t _port) { + (void)_service; + (void)_event; + (void)_address; + (void)_port; +} + +void virtual_server_endpoint_impl::remove_multicast( + service_t _service, event_t _event) { + (void)_service; + (void)_event; +} + +bool virtual_server_endpoint_impl::get_remote_address( + boost::asio::ip::address &_address) const { + (void)_address; + return false; +} + +unsigned short virtual_server_endpoint_impl::get_local_port() const { + return port_; +} + +unsigned short virtual_server_endpoint_impl::get_remote_port() const { + return ILLEGAL_PORT; +} + +bool virtual_server_endpoint_impl::is_reliable() const { + return reliable_; +} + +bool virtual_server_endpoint_impl::is_local() const { + return true; +} + + +void virtual_server_endpoint_impl::increment_use_count() { + use_count_++; +} + +void virtual_server_endpoint_impl::decrement_use_count() { + if (use_count_ > 0) + use_count_--; +} + +uint32_t virtual_server_endpoint_impl::get_use_count() { + return use_count_; +} + +} // namespace vsomeip diff --git a/implementation/logging/include/logger.hpp b/implementation/logging/include/logger.hpp new file mode 100644 index 0000000..555f15e --- /dev/null +++ b/implementation/logging/include/logger.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_LOGGER_HPP
+#define VSOMEIP_LOGGER_HPP
+
+#include <string>
+
+#ifdef WIN32
+#include <iostream>
+#endif
+
+#include <vsomeip/export.hpp>
+
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/trivial.hpp>
+
+namespace vsomeip {
+
+class VSOMEIP_EXPORT logger {
+public:
+ static std::shared_ptr<logger> get();
+
+ virtual ~logger() {
+ }
+
+ virtual boost::log::sources::severity_logger<
+ boost::log::trivial::severity_level> & get_internal() = 0;
+};
+
+#define VSOMEIP_FATAL BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::fatal)
+#define VSOMEIP_ERROR BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::error)
+#define VSOMEIP_WARNING BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::warning)
+#define VSOMEIP_INFO BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::info)
+#define VSOMEIP_DEBUG BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::debug)
+#define VSOMEIP_TRACE BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::trace)
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_LOGGER_HPP
diff --git a/implementation/logging/include/logger_impl.hpp b/implementation/logging/include/logger_impl.hpp index de98f25..56c2397 100644 --- a/implementation/logging/include/logger_impl.hpp +++ b/implementation/logging/include/logger_impl.hpp @@ -14,10 +14,12 @@ #include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
-#include <vsomeip/logger.hpp>
+#include "logger.hpp"
namespace vsomeip {
+class configuration;
+
BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity",
boost::log::trivial::severity_level)
@@ -28,7 +30,7 @@ typedef boost::log::sinks::synchronous_sink< class logger_impl: public logger {
public:
static std::shared_ptr<logger_impl> & get();
- static void init(const std::string &_path);
+ static void init(const std::shared_ptr<configuration> &_configuration);
logger_impl();
diff --git a/implementation/logging/src/logger_impl.cpp b/implementation/logging/src/logger_impl.cpp index f354a40..ef98749 100644 --- a/implementation/logging/src/logger_impl.cpp +++ b/implementation/logging/src/logger_impl.cpp @@ -29,8 +29,8 @@ #include <boost/core/null_deleter.hpp>
#endif
-#include <vsomeip/configuration.hpp>
#include "../include/logger_impl.hpp"
+#include "../../configuration/include/configuration.hpp"
namespace logging = boost::log;
namespace sources = boost::log::sources;
@@ -59,19 +59,19 @@ logger_impl::get_internal() { return logger_;
}
-void logger_impl::init(const std::string &_path) {
- configuration *its_configuration = configuration::get(_path);
- get()->loglevel_ = its_configuration->get_loglevel();
+void logger_impl::init(const std::shared_ptr<configuration> &_configuration) {
+ get()->loglevel_ = _configuration->get_loglevel();
+
logging::core::get()->set_filter(
logging::trivial::severity >= get()->loglevel_);
- if (its_configuration->has_console_log())
+ if (_configuration->has_console_log())
get()->enable_console();
- if (its_configuration->has_file_log())
- get()->enable_file(its_configuration->get_logfile());
+ if (_configuration->has_file_log())
+ get()->enable_file(_configuration->get_logfile());
- if (its_configuration->has_dlt_log())
+ if (_configuration->has_dlt_log())
get()->enable_dlt();
}
diff --git a/implementation/message/include/message_header_impl.hpp b/implementation/message/include/message_header_impl.hpp index 1d3e70b..b233d75 100644 --- a/implementation/message/include/message_header_impl.hpp +++ b/implementation/message/include/message_header_impl.hpp @@ -9,7 +9,7 @@ #include <vsomeip/export.hpp>
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/enumeration_types.hpp>
-#include <vsomeip/serializable.hpp>
+#include <vsomeip/internal/serializable.hpp>
namespace vsomeip {
@@ -20,8 +20,8 @@ public: VSOMEIP_EXPORT message_header_impl();
VSOMEIP_EXPORT message_header_impl(const message_header_impl& header);
- VSOMEIP_EXPORT virtual bool serialize(serializer *_to) const;
- VSOMEIP_EXPORT virtual bool deserialize(deserializer *_from);
+ VSOMEIP_EXPORT bool serialize(serializer *_to) const;
+ VSOMEIP_EXPORT bool deserialize(deserializer *_from);
// internal
VSOMEIP_EXPORT message_base * get_owner() const;
diff --git a/implementation/message/src/deserializer.cpp b/implementation/message/src/deserializer.cpp index fb9cde6..6017d5a 100644 --- a/implementation/message/src/deserializer.cpp +++ b/implementation/message/src/deserializer.cpp @@ -9,7 +9,7 @@ #include <iomanip>
#include <sstream>
-#include <vsomeip/logger.hpp>
+#include "../../logging/include/logger.hpp"
#endif
#include "../include/message_impl.hpp"
@@ -19,186 +19,186 @@ namespace vsomeip {
deserializer::deserializer()
- : position_(data_.begin()),
- remaining_(0) {
+ : position_(data_.begin()),
+ remaining_(0) {
}
deserializer::deserializer(byte_t *_data, std::size_t _length)
- : data_(_data, _data + _length),
- position_(data_.begin()),
- remaining_(_length) {
+ : data_(_data, _data + _length),
+ position_(data_.begin()),
+ remaining_(_length) {
}
deserializer::deserializer(const deserializer &_other)
- : data_(_other.data_),
- position_(_other.position_){
+ : data_(_other.data_),
+ position_(_other.position_){
}
deserializer::~deserializer() {
}
std::size_t deserializer::get_available() const {
- return data_.size();
+ return data_.size();
}
std::size_t deserializer::get_remaining() const {
- return remaining_;
+ return remaining_;
}
void deserializer::set_remaining(std::size_t _remaining) {
- remaining_ = _remaining;
+ remaining_ = _remaining;
}
bool deserializer::deserialize(uint8_t& _value) {
- if (0 == remaining_)
- return false;
+ if (0 == remaining_)
+ return false;
- _value = *position_++;
+ _value = *position_++;
- remaining_--;
- return true;
+ remaining_--;
+ return true;
}
bool deserializer::deserialize(uint16_t& _value) {
- if (2 > remaining_)
- return false;
+ if (2 > remaining_)
+ return false;
- uint8_t byte0, byte1;
- byte0 = *position_++;
- byte1 = *position_++;
- remaining_ -= 2;
+ uint8_t byte0, byte1;
+ byte0 = *position_++;
+ byte1 = *position_++;
+ remaining_ -= 2;
- _value = VSOMEIP_BYTES_TO_WORD(byte0, byte1);
+ _value = VSOMEIP_BYTES_TO_WORD(byte0, byte1);
- return true;
+ return true;
}
bool deserializer::deserialize(uint32_t &_value, bool _omit_last_byte) {
- if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_))
- return false;
+ if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_))
+ return false;
- uint8_t byte0 = 0, byte1, byte2, byte3;
- if (!_omit_last_byte) {
- byte0 = *position_++;
- remaining_--;
- }
- byte1 = *position_++;
- byte2 = *position_++;
- byte3 = *position_++;
- remaining_ -= 3;
+ uint8_t byte0 = 0, byte1, byte2, byte3;
+ if (!_omit_last_byte) {
+ byte0 = *position_++;
+ remaining_--;
+ }
+ byte1 = *position_++;
+ byte2 = *position_++;
+ byte3 = *position_++;
+ remaining_ -= 3;
- _value = VSOMEIP_BYTES_TO_LONG(
- byte0, byte1, byte2, byte3);
+ _value = VSOMEIP_BYTES_TO_LONG(
+ byte0, byte1, byte2, byte3);
- return true;
+ return true;
}
bool deserializer::deserialize(uint8_t *_data, std::size_t _length) {
- if (_length > remaining_)
- return false;
+ if (_length > remaining_)
+ return false;
- std::memcpy(_data, &data_[position_ - data_.begin()], _length);
- position_ += _length;
- remaining_ -= _length;
+ std::memcpy(_data, &data_[position_ - data_.begin()], _length);
+ position_ += _length;
+ remaining_ -= _length;
- return true;
+ return true;
}
bool deserializer::deserialize(std::vector< uint8_t >& _value) {
- if (_value.capacity() > remaining_)
- return false;
+ if (_value.capacity() > remaining_)
+ return false;
- _value.assign(position_, position_ + _value.capacity());
- position_ += _value.capacity();
- remaining_ -= _value.capacity();
+ _value.assign(position_, position_ + _value.capacity());
+ position_ += _value.capacity();
+ remaining_ -= _value.capacity();
- return true;
+ return true;
}
bool deserializer::look_ahead(std::size_t _index, uint8_t &_value) const {
- if (_index >= data_.size())
- return false;
+ if (_index >= data_.size())
+ return false;
- _value = *(position_ + _index);
+ _value = *(position_ + _index);
- return true;
+ return true;
}
bool deserializer::look_ahead(std::size_t _index, uint16_t &_value) const {
- if (_index+1 >= data_.size())
- return false;
+ if (_index+1 >= data_.size())
+ return false;
- std::vector< uint8_t >::iterator i = position_ + _index;
- _value = VSOMEIP_BYTES_TO_WORD(*i, *(i+1));
+ std::vector< uint8_t >::iterator i = position_ + _index;
+ _value = VSOMEIP_BYTES_TO_WORD(*i, *(i+1));
- return true;
+ return true;
}
bool deserializer::look_ahead(std::size_t _index, uint32_t &_value) const {
- if (_index+3 >= data_.size())
- return false;
+ if (_index+3 >= data_.size())
+ return false;
- std::vector< uint8_t >::const_iterator i = position_ + _index;
- _value = VSOMEIP_BYTES_TO_LONG(*i, *(i+1), *(i+2), *(i+3));
+ std::vector< uint8_t >::const_iterator i = position_ + _index;
+ _value = VSOMEIP_BYTES_TO_LONG(*i, *(i+1), *(i+2), *(i+3));
- return true;
+ return true;
}
message * deserializer::deserialize_message() {
- message_impl* deserialized_message = new message_impl;
- if (0 != deserialized_message) {
- if (false == deserialized_message->deserialize(this)) {
- delete deserialized_message;
- deserialized_message = 0;
- }
- }
+ message_impl* deserialized_message = new message_impl;
+ if (0 != deserialized_message) {
+ if (false == deserialized_message->deserialize(this)) {
+ delete deserialized_message;
+ deserialized_message = 0;
+ }
+ }
- return deserialized_message;
+ return deserialized_message;
}
void deserializer::set_data(const byte_t *_data, std::size_t _length) {
- if (0 != _data) {
- data_.assign(_data, _data + _length);
- position_ = data_.begin();
- remaining_ = data_.end() - position_;
- } else {
- data_.clear();
- position_ = data_.end();
- remaining_ = 0;
- }
+ if (0 != _data) {
+ data_.assign(_data, _data + _length);
+ position_ = data_.begin();
+ remaining_ = data_.end() - position_;
+ } else {
+ data_.clear();
+ position_ = data_.end();
+ remaining_ = 0;
+ }
}
void deserializer::append_data(const byte_t *_data, std::size_t _length) {
- std::size_t offset = (position_ - data_.begin());
- data_.insert(data_.end(), _data, _data + _length);
- position_ = data_.begin() + offset;
- remaining_ += _length;
+ std::size_t offset = (position_ - data_.begin());
+ data_.insert(data_.end(), _data, _data + _length);
+ position_ = data_.begin() + offset;
+ remaining_ += _length;
}
void deserializer::drop_data(std::size_t _length) {
- if (position_ + _length < data_.end())
- position_ += _length;
- else
- position_ = data_.end();
+ if (position_ + _length < data_.end())
+ position_ += _length;
+ else
+ position_ = data_.end();
}
void deserializer::reset() {
- data_.erase(data_.begin(), position_);
- position_ = data_.begin();
- remaining_ = data_.size();
+ data_.erase(data_.begin(), position_);
+ position_ = data_.begin();
+ remaining_ = data_.size();
}
#ifdef VSOMEIP_DEBUGGING
void deserializer::show() const {
- std::stringstream its_message;
- its_message << "("
- << std::hex << std::setw(2) << std::setfill('0')
- << (int)*position_ << ", "
- << std:: dec << remaining_ << ") ";
- for (int i = 0; i < data_.size(); ++i)
- its_message << std::hex << std::setw(2) << std::setfill('0')
- << (int)data_[i] << " ";
- VSOMEIP_DEBUG << its_message;
+ std::stringstream its_message;
+ its_message << "("
+ << std::hex << std::setw(2) << std::setfill('0')
+ << (int)*position_ << ", "
+ << std:: dec << remaining_ << ") ";
+ for (int i = 0; i < data_.size(); ++i)
+ its_message << std::hex << std::setw(2) << std::setfill('0')
+ << (int)data_[i] << " ";
+ VSOMEIP_DEBUG << its_message;
}
#endif
diff --git a/implementation/message/src/message_base_impl.cpp b/implementation/message/src/message_base_impl.cpp index c5ab95a..616ed63 100644 --- a/implementation/message/src/message_base_impl.cpp +++ b/implementation/message/src/message_base_impl.cpp @@ -10,7 +10,7 @@ namespace vsomeip { message_base_impl::message_base_impl()
: is_reliable_(false) {
- header_.set_owner(this);
+ header_.set_owner(this);
}
message_base_impl::~message_base_impl() {
@@ -18,88 +18,88 @@ message_base_impl::~message_base_impl() { // header interface
message_t message_base_impl::get_message() const {
- return VSOMEIP_WORDS_TO_LONG(header_.service_, header_.method_);
+ return VSOMEIP_WORDS_TO_LONG(header_.service_, header_.method_);
}
void message_base_impl::set_message(message_t _message) {
- header_.service_ = VSOMEIP_LONG_WORD0(_message);
- header_.method_ = VSOMEIP_LONG_WORD1(_message);
+ header_.service_ = VSOMEIP_LONG_WORD0(_message);
+ header_.method_ = VSOMEIP_LONG_WORD1(_message);
}
service_t message_base_impl::get_service() const {
- return header_.service_;
+ return header_.service_;
}
void message_base_impl::set_service(service_t _service) {
- header_.service_ = _service;
+ header_.service_ = _service;
}
instance_t message_base_impl::get_instance() const {
- return header_.instance_;
+ return header_.instance_;
}
void message_base_impl::set_instance(instance_t _instance) {
- header_.instance_ = _instance;
+ header_.instance_ = _instance;
}
method_t message_base_impl::get_method() const {
- return header_.method_;
+ return header_.method_;
}
void message_base_impl::set_method(method_t _method) {
- header_.method_ = _method;
+ header_.method_ = _method;
}
request_t message_base_impl::get_request() const {
- return VSOMEIP_WORDS_TO_LONG(header_.client_, header_.session_);
+ return VSOMEIP_WORDS_TO_LONG(header_.client_, header_.session_);
}
client_t message_base_impl::get_client() const {
- return header_.client_;
+ return header_.client_;
}
void message_base_impl::set_client(client_t _client) {
- header_.client_ = _client;
+ header_.client_ = _client;
}
session_t message_base_impl::get_session() const {
- return header_.session_;
+ return header_.session_;
}
void message_base_impl::set_session(session_t _session) {
- header_.session_ = _session;
+ header_.session_ = _session;
}
protocol_version_t message_base_impl::get_protocol_version() const {
- return header_.protocol_version_;
+ return header_.protocol_version_;
}
void message_base_impl::set_protocol_version(protocol_version_t _protocol_version) {
- header_.protocol_version_ = _protocol_version;
+ header_.protocol_version_ = _protocol_version;
}
interface_version_t message_base_impl::get_interface_version() const {
- return header_.interface_version_;
+ return header_.interface_version_;
}
void message_base_impl::set_interface_version(interface_version_t _interface_version) {
- header_.interface_version_ = _interface_version;
+ header_.interface_version_ = _interface_version;
}
message_type_e message_base_impl::get_message_type() const {
- return header_.type_;
+ return header_.type_;
}
void message_base_impl::set_message_type(message_type_e _type) {
- header_.type_ = _type;
+ header_.type_ = _type;
}
return_code_e message_base_impl::get_return_code() const {
- return header_.code_;
+ return header_.code_;
}
void message_base_impl::set_return_code(return_code_e _code) {
- header_.code_ = _code;
+ header_.code_ = _code;
}
bool message_base_impl::is_reliable() const {
diff --git a/implementation/message/src/message_header_impl.cpp b/implementation/message/src/message_header_impl.cpp index 1bde36c..39446b7 100644 --- a/implementation/message/src/message_header_impl.cpp +++ b/implementation/message/src/message_header_impl.cpp @@ -13,66 +13,69 @@ namespace vsomeip {
message_header_impl::message_header_impl()
- : service_(0x0), instance_(0x0), method_(0x0),
- client_(0x0), session_(0x0),
- protocol_version_(0x1), interface_version_(0x0),
- type_(message_type_e::MT_UNKNOWN),
- code_(return_code_e::E_UNKNOWN) {
+ : service_(0x0), method_(0x0),
+ client_(0x0), session_(0x0),
+ protocol_version_(0x1), interface_version_(0x0),
+ type_(message_type_e::MT_UNKNOWN),
+ code_(return_code_e::E_UNKNOWN),
+ instance_(0x0) {
};
-message_header_impl::message_header_impl(const message_header_impl& _header)
- : service_(_header.service_), instance_(_header.instance_), method_(_header.method_),
- client_(_header.client_), session_(_header.session_),
- protocol_version_(_header.protocol_version_), interface_version_(_header.interface_version_),
- type_(_header.type_),
- code_(_header.code_) {
+message_header_impl::message_header_impl(const message_header_impl &_header)
+ : service_(_header.service_), method_(_header.method_),
+ client_(_header.client_), session_(_header.session_),
+ protocol_version_(_header.protocol_version_),
+ interface_version_(_header.interface_version_),
+ type_(_header.type_),
+ code_(_header.code_),
+ instance_(_header.instance_) {
};
bool message_header_impl::serialize(serializer *_to) const {
- return (0 != _to
- && _to->serialize(service_)
- && _to->serialize(method_)
- && _to->serialize(owner_->get_length())
- && _to->serialize(client_)
- && _to->serialize(session_)
- && _to->serialize(protocol_version_)
- && _to->serialize(interface_version_)
- && _to->serialize(static_cast<uint8_t>(type_))
- && _to->serialize(static_cast<uint8_t>(code_)));
+ return (0 != _to
+ && _to->serialize(service_)
+ && _to->serialize(method_)
+ && _to->serialize(owner_->get_length())
+ && _to->serialize(client_)
+ && _to->serialize(session_)
+ && _to->serialize(protocol_version_)
+ && _to->serialize(interface_version_)
+ && _to->serialize(static_cast<uint8_t>(type_))
+ && _to->serialize(static_cast<uint8_t>(code_)));
};
bool message_header_impl::deserialize(deserializer *_from) {
- bool is_successful;
+ bool is_successful;
- uint8_t tmp_message_type, tmp_return_code;
- uint32_t tmp_length;
+ uint8_t tmp_message_type, tmp_return_code;
+ uint32_t tmp_length;
- is_successful = (0 != _from
- && _from->deserialize(service_)
- && _from->deserialize(method_)
- && _from->deserialize(tmp_length)
- && _from->deserialize(client_)
- && _from->deserialize(session_)
- && _from->deserialize(protocol_version_)
- && _from->deserialize(interface_version_)
- && _from->deserialize(tmp_message_type)
- && _from->deserialize(tmp_return_code));
+ is_successful = (0 != _from
+ && _from->deserialize(service_)
+ && _from->deserialize(method_)
+ && _from->deserialize(tmp_length)
+ && _from->deserialize(client_)
+ && _from->deserialize(session_)
+ && _from->deserialize(protocol_version_)
+ && _from->deserialize(interface_version_)
+ && _from->deserialize(tmp_message_type)
+ && _from->deserialize(tmp_return_code));
- if (is_successful) {
- type_ = static_cast< message_type_e >(tmp_message_type);
- code_ = static_cast< return_code_e >(tmp_return_code);
- length_ = static_cast< length_t >(tmp_length - VSOMEIP_SOMEIP_HEADER_SIZE);
- }
+ if (is_successful) {
+ type_ = static_cast< message_type_e >(tmp_message_type);
+ code_ = static_cast< return_code_e >(tmp_return_code);
+ length_ = static_cast< length_t >(tmp_length - VSOMEIP_SOMEIP_HEADER_SIZE);
+ }
- return is_successful;
+ return is_successful;
};
message_base * message_header_impl::get_owner() const {
- return owner_;
+ return owner_;
}
void message_header_impl::set_owner(message_base *_owner) {
- owner_ = _owner;
+ owner_ = _owner;
}
} // namespace vsomeip
diff --git a/implementation/message/src/message_impl.cpp b/implementation/message/src/message_impl.cpp index 51596a0..c19ae76 100644 --- a/implementation/message/src/message_impl.cpp +++ b/implementation/message/src/message_impl.cpp @@ -20,31 +20,31 @@ message_impl::~message_impl() { }
length_t message_impl::get_length() const {
- return (VSOMEIP_SOMEIP_HEADER_SIZE
- + (payload_ ? payload_->get_length() : 0));
+ return (VSOMEIP_SOMEIP_HEADER_SIZE
+ + (payload_ ? payload_->get_length() : 0));
}
std::shared_ptr< payload > message_impl::get_payload() const {
- return payload_;
+ return payload_;
}
void message_impl::set_payload(std::shared_ptr< payload > _payload) {
- payload_ = _payload;
+ payload_ = _payload;
}
bool message_impl::serialize(serializer *_to) const {
- return (header_.serialize(_to)
- && (payload_ ? payload_->serialize(_to) : true));
+ return (header_.serialize(_to)
+ && (payload_ ? payload_->serialize(_to) : true));
}
bool message_impl::deserialize(deserializer *_from) {
- payload_ = runtime::get()->create_payload();
- bool is_successful = header_.deserialize(_from);
- if (is_successful) {
- payload_->set_capacity(header_.length_);
- is_successful = payload_->deserialize(_from);
- }
- return is_successful;
+ payload_ = runtime::get()->create_payload();
+ bool is_successful = header_.deserialize(_from);
+ if (is_successful) {
+ payload_->set_capacity(header_.length_);
+ is_successful = payload_->deserialize(_from);
+ }
+ return is_successful;
}
} // namespace vsomeip
diff --git a/implementation/message/src/payload_impl.cpp b/implementation/message/src/payload_impl.cpp index 62e48e0..3355788 100644 --- a/implementation/message/src/payload_impl.cpp +++ b/implementation/message/src/payload_impl.cpp @@ -10,66 +10,66 @@ namespace vsomeip {
payload_impl::payload_impl()
- : data_() {
+ : data_() {
}
payload_impl::payload_impl(const byte_t *_data, uint32_t _size) {
- data_.assign(_data, _data + _size);
+ data_.assign(_data, _data + _size);
}
payload_impl::payload_impl(const std::vector<byte_t> &_data)
- : data_(_data) {
+ : data_(_data) {
}
payload_impl::payload_impl(const payload_impl& _payload)
- : data_(_payload.data_) {
+ : data_(_payload.data_) {
}
payload_impl::~payload_impl() {
}
bool payload_impl::operator==(const payload &_other) {
- bool is_equal(true);
- try {
- const payload_impl &other = dynamic_cast< const payload_impl & >(_other);
- is_equal = (data_ == other.data_);
- }
- catch (...) {
- is_equal = false;
- }
- return is_equal;
+ bool is_equal(true);
+ try {
+ const payload_impl &other = dynamic_cast< const payload_impl & >(_other);
+ is_equal = (data_ == other.data_);
+ }
+ catch (...) {
+ is_equal = false;
+ }
+ return is_equal;
}
byte_t * payload_impl::get_data() {
- return data_.data();
+ return data_.data();
}
const byte_t * payload_impl::get_data() const {
- return data_.data();
+ return data_.data();
}
length_t payload_impl::get_length() const {
- return data_.size();
+ return length_t(data_.size());
}
void payload_impl::set_capacity(length_t _capacity) {
- data_.reserve(_capacity);
+ data_.reserve(_capacity);
}
void payload_impl::set_data(const byte_t *_data, const length_t _length) {
- data_.assign(_data, _data + _length);
+ data_.assign(_data, _data + _length);
}
void payload_impl::set_data(const std::vector< byte_t > &_data) {
- data_ = _data;
+ data_ = _data;
}
bool payload_impl::serialize(serializer *_to) const {
- return (0 != _to && _to->serialize(data_.data(), data_.size()));
+ return (0 != _to && _to->serialize(data_.data(), uint32_t(data_.size())));
}
bool payload_impl::deserialize(deserializer *_from) {
- return (0 != _from && _from->deserialize(data_));
+ return (0 != _from && _from->deserialize(data_));
}
} // namespace vsomeip
diff --git a/implementation/message/src/serializer.cpp b/implementation/message/src/serializer.cpp index cfa32ec..6c064ab 100644 --- a/implementation/message/src/serializer.cpp +++ b/implementation/message/src/serializer.cpp @@ -9,10 +9,10 @@ #include <iomanip>
#include <sstream>
-#include <vsomeip/logger.hpp>
+#include "../../logging/include/logger.hpp"
#endif
-#include <vsomeip/serializable.hpp>
+#include <vsomeip/internal/serializable.hpp>
#include "../include/serializer.hpp"
#include "../../utility/include/byteorder.hpp"
@@ -20,115 +20,117 @@ namespace vsomeip {
serializer::serializer()
- : data_(0), capacity_(0), position_(0), remaining_(0) {
+ : data_(0), capacity_(0), position_(0), remaining_(0) {
}
serializer::~serializer() {
+ if (0 != data_)
+ delete [] data_;
};
bool serializer::serialize(const serializable *_from) {
- return (_from && _from->serialize(this));
+ return (_from && _from->serialize(this));
}
bool serializer::serialize(const uint8_t _value) {
- if (1 > remaining_)
- return false;
+ if (1 > remaining_)
+ return false;
- *position_++ = _value;
- remaining_--;
+ *position_++ = _value;
+ remaining_--;
- return true;
+ return true;
}
bool serializer::serialize(const uint16_t _value) {
- if (2 > remaining_)
- return false;
+ if (2 > remaining_)
+ return false;
- *position_++ = VSOMEIP_WORD_BYTE1(_value);
- *position_++ = VSOMEIP_WORD_BYTE0(_value);
- remaining_ -= 2;
+ *position_++ = VSOMEIP_WORD_BYTE1(_value);
+ *position_++ = VSOMEIP_WORD_BYTE0(_value);
+ remaining_ -= 2;
- return true;
+ return true;
}
bool serializer::serialize(const uint32_t _value, bool _omit_last_byte) {
- if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_))
- return false;
-
- if (!_omit_last_byte) {
- *position_++ = VSOMEIP_LONG_BYTE3(_value);
- remaining_--;
- }
- *position_++ = VSOMEIP_LONG_BYTE2(_value);
- *position_++ = VSOMEIP_LONG_BYTE1(_value);
- *position_++ = VSOMEIP_LONG_BYTE0(_value);
- remaining_ -= 3;
-
- return true;
+ if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_))
+ return false;
+
+ if (!_omit_last_byte) {
+ *position_++ = VSOMEIP_LONG_BYTE3(_value);
+ remaining_--;
+ }
+ *position_++ = VSOMEIP_LONG_BYTE2(_value);
+ *position_++ = VSOMEIP_LONG_BYTE1(_value);
+ *position_++ = VSOMEIP_LONG_BYTE0(_value);
+ remaining_ -= 3;
+
+ return true;
}
bool serializer::serialize(const uint8_t *_data, uint32_t _length) {
- if (_length > remaining_)
- return false;
+ if (_length > remaining_)
+ return false;
- ::memcpy(position_, _data, _length);
- position_ += _length;
- remaining_ -= _length;
+ ::memcpy(position_, _data, _length);
+ position_ += _length;
+ remaining_ -= _length;
- return true;
+ return true;
}
byte_t * serializer::get_data() const {
- return data_;
+ return data_;
}
uint32_t serializer::get_capacity() const {
- return capacity_;
+ return capacity_;
}
uint32_t serializer::get_size() const {
- return capacity_ - remaining_;
+ return capacity_ - remaining_;
}
void serializer::create_data(uint32_t _capacity) {
- if (0 != data_)
- delete [] data_;
-
- data_ = new byte_t[_capacity];
- position_ = data_;
- if (0 != data_) {
- capacity_ = remaining_ = _capacity;
- } else {
- capacity_ = remaining_ = 0;
- }
+ if (0 != data_)
+ delete [] data_;
+
+ data_ = new byte_t[_capacity];
+ position_ = data_;
+ if (0 != data_) {
+ capacity_ = remaining_ = _capacity;
+ } else {
+ capacity_ = remaining_ = 0;
+ }
}
void serializer::set_data(byte_t *_data, uint32_t _capacity) {
- delete [] data_;
+ delete [] data_;
- data_ = _data;
- position_ = _data;
+ data_ = _data;
+ position_ = _data;
- if (0 != data_) {
- capacity_ = remaining_ = _capacity;
- } else {
- capacity_ = remaining_ = 0;
- }
+ if (0 != data_) {
+ capacity_ = remaining_ = _capacity;
+ } else {
+ capacity_ = remaining_ = 0;
+ }
}
void serializer::reset() {
- position_ = data_;
- remaining_ = capacity_;
+ position_ = data_;
+ remaining_ = capacity_;
}
#ifdef VSOMEIP_DEBUGGING
void serializer::show() {
- std::stringstream its_data;
- its_data << "SERIALIZED: ";
- for (int i = 0; i < position_ - data_; ++i)
- its_data << std::setw(2) << std::setfill('0')
- << std::hex << (int)data_[i];
- VSOMEIP_DEBUG << its_data.str();
+ std::stringstream its_data;
+ its_data << "SERIALIZED: ";
+ for (int i = 0; i < position_ - data_; ++i)
+ its_data << std::setw(2) << std::setfill('0')
+ << std::hex << (int)data_[i];
+ VSOMEIP_DEBUG << its_data.str();
}
#endif
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp index 7332c9a..89153ad 100644 --- a/implementation/routing/include/event.hpp +++ b/implementation/routing/include/event.hpp @@ -54,6 +54,9 @@ public: bool is_reliable() const; void set_reliable(bool _is_reliable); + bool is_provided() const; + void set_provided(bool _is_provided); + // SIP_RPC_357 void set_update_cycle(std::chrono::milliseconds &_cycle); @@ -69,6 +72,9 @@ public: void notify_one(const std::shared_ptr<endpoint_definition> &_target); void notify_one(client_t _client); + void add_ref(); + uint32_t remove_ref(); + private: void update_cbk(boost::system::error_code const &_error); void notify(); @@ -91,6 +97,9 @@ private: std::set<eventgroup_t> eventgroups_; bool is_set_; + bool is_provided_; + + uint32_t ref_; }; } // namespace vsomeip diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp index 558c3b9..08536e0 100644 --- a/implementation/routing/include/eventgroupinfo.hpp +++ b/implementation/routing/include/eventgroupinfo.hpp @@ -39,11 +39,12 @@ public: VSOMEIP_EXPORT const std::set<std::shared_ptr<event> > get_events() const; VSOMEIP_EXPORT void add_event(std::shared_ptr<event> _event); + VSOMEIP_EXPORT void remove_event(std::shared_ptr<event> _event); VSOMEIP_EXPORT const std::set< std::shared_ptr<endpoint_definition> > get_targets() const; - VSOMEIP_EXPORT void add_target(std::shared_ptr<endpoint_definition> _target); - VSOMEIP_EXPORT void del_target(std::shared_ptr<endpoint_definition> _target); + VSOMEIP_EXPORT bool add_target(std::shared_ptr<endpoint_definition> _target); + VSOMEIP_EXPORT bool remove_target(std::shared_ptr<endpoint_definition> _target); VSOMEIP_EXPORT void clear_targets(); private: diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp index 44a63ac..7791add 100644 --- a/implementation/routing/include/routing_manager.hpp +++ b/implementation/routing/include/routing_manager.hpp @@ -36,21 +36,21 @@ public: virtual void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) = 0; + minor_version_t _minor) = 0; virtual void stop_offer_service(client_t _client, service_t _service, instance_t _instance) = 0; virtual void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective) = 0; + minor_version_t _minor, bool _use_exclusive_proxy) = 0; virtual void release_service(client_t _client, service_t _service, instance_t _instance) = 0; virtual void subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) = 0; + major_version_t _major) = 0; virtual void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; @@ -67,6 +67,13 @@ public: virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target, 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, + bool _is_field, bool _is_provided) = 0; + + virtual void unregister_event(client_t _client, service_t _service, instance_t _instance, + event_t _event, bool _is_provided) = 0; + virtual void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload) = 0; diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp index a80b86d..7b96be0 100644 --- a/implementation/routing/include/routing_manager_host.hpp +++ b/implementation/routing/include/routing_manager_host.hpp @@ -29,7 +29,7 @@ public: virtual void on_availability(service_t _service, instance_t _instance, bool _is_available) const = 0; - virtual void on_event(event_type_e _event) = 0; + virtual void on_state(state_type_e _state) = 0; virtual void on_message(std::shared_ptr<message> _message) = 0; virtual void on_error(error_code_e _error) = 0; virtual bool on_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp index b2d5200..a0d692c 100644 --- a/implementation/routing/include/routing_manager_impl.hpp +++ b/implementation/routing/include/routing_manager_impl.hpp @@ -63,20 +63,20 @@ public: void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor); void stop_offer_service(client_t _client, service_t _service, instance_t _instance); void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective); + minor_version_t _minor, bool _use_exclusive_proxy); void release_service(client_t _client, service_t _service, instance_t _instance); void subscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); + eventgroup_t _eventgroup, major_version_t _major); void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); @@ -92,6 +92,15 @@ public: bool send_to(const std::shared_ptr<endpoint_definition> &_target, const byte_t *_data, uint32_t _size); + void register_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + std::set<eventgroup_t> _eventgroups, + bool _is_field, bool _is_provided); + + void unregister_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + bool _is_provided); + void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload); @@ -113,25 +122,31 @@ public: bool _reliable, client_t _client); void on_connect(std::shared_ptr<endpoint> _endpoint); void on_disconnect(std::shared_ptr<endpoint> _endpoint); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver); void on_message(service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _reliable); + void on_notification(client_t _client, service_t _service, + instance_t _instance, const byte_t *_data, length_t _size); // interface "service_discovery_host" typedef std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_t; const servicegroups_t & get_servicegroups() const; std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service, instance_t _instance, eventgroup_t _eventgroup) const; - services_t get_offered_services(const std::string &_name) const; - void create_service_discovery_endpoint(const std::string &_address, + services_t get_offered_services() const; + std::shared_ptr<endpoint> create_service_discovery_endpoint(const std::string &_address, uint16_t _port, bool _reliable); void init_routing_info(); void add_routing_info(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable); + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port); void del_routing_info(service_t _service, instance_t _instance, - bool _reliable); + bool _has_reliable, bool _has_unreliable); + ttl_t update_routing_info(ttl_t _elapsed); void on_subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, @@ -143,11 +158,11 @@ public: void on_subscribe_ack(service_t _service, instance_t _instance, const boost::asio::ip::address &_address, uint16_t _port); - void init_event_routing_info(); - private: bool deliver_message(const byte_t *_data, length_t _length, instance_t _instance, bool _reliable); + bool deliver_notification(service_t _service, instance_t _instance, + const byte_t *_data, length_t _length, bool _reliable); bool send_local( std::shared_ptr<endpoint> &_target, client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, @@ -160,56 +175,71 @@ private: std::shared_ptr<serviceinfo> find_service(service_t _service, instance_t _instance) const; - std::shared_ptr<serviceinfo> create_service(service_t _service, + std::shared_ptr<serviceinfo> create_service_info(service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor, ttl_t _ttl, bool _is_local_service); std::shared_ptr<endpoint> create_client_endpoint( const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client); - std::shared_ptr<endpoint> find_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client); - std::shared_ptr<endpoint> find_or_create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client); + bool _reliable, client_t _client, bool _start); + + void remove_eventgroup_info(service_t _service, instance_t _instance, + eventgroup_t _eventgroup); std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port, - bool _reliable); + bool _reliable, bool _start); std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port, - bool _reliable); + bool _reliable); std::shared_ptr<endpoint> find_or_create_server_endpoint(uint16_t _port, - bool _reliable); + bool _reliable, bool _start); std::set<std::shared_ptr<event> > find_events(service_t _service, instance_t _instance, eventgroup_t _eventgroup); std::shared_ptr<event> find_event(service_t _service, instance_t _instance, event_t _event) const; + bool is_field(service_t _service, instance_t _instance, + event_t _event) const; std::shared_ptr<endpoint> find_remote_client(service_t _service, - instance_t _instance, - bool _reliable, client_t _client); + instance_t _instance, bool _reliable, client_t _client); std::shared_ptr<endpoint> create_remote_client(service_t _service, - instance_t _instance, - bool _reliable, client_t _client); + instance_t _instance, bool _reliable, client_t _client); + + bool deliver_specific_endpoint_message(service_t _service, instance_t _instance, + const byte_t *_data, length_t _size, endpoint *_receiver); + + void clear_client_endpoints(service_t _service, instance_t _instance, bool _reliable); + void stop_and_delete_client_endpoint(std::shared_ptr<endpoint> _endpoint); + void clear_multicast_endpoints(service_t _service, instance_t _instance); + void clear_service_info(service_t _service, instance_t _instance, bool _reliable); private: void send_subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl); + major_version_t _major); void send_unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); - boost::asio::io_service &io_; - routing_manager_host *host_; + bool insert_subscription(service_t _service, instance_t _instance, + eventgroup_t _eventgroup, client_t _client); - std::shared_ptr<configuration> configuration_; + return_code_e check_error(const byte_t *_data, length_t _size, + instance_t _instance); + + void send_error(return_code_e _return_code, const byte_t *_data, + length_t _size, instance_t _instance, bool _reliable, + endpoint *_receiver); + + routing_manager_host *host_; + boost::asio::io_service &io_; std::shared_ptr<deserializer> deserializer_; std::shared_ptr<serializer> serializer_; + std::shared_ptr<configuration> configuration_; + std::shared_ptr<routing_manager_stub> stub_; std::shared_ptr<sd::service_discovery> discovery_; @@ -223,15 +253,20 @@ private: std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > server_endpoints_; std::map<service_t, std::map<endpoint *, instance_t> > service_instances_; + // Multicast endpoint info (notifications) + std::map<service_t, std::map<instance_t, std::shared_ptr<endpoint_definition> > > multicast_info; + // Client endpoints for remote services - std::map<boost::asio::ip::address, - std::map<uint16_t, std::map<client_t, std::map<bool, std::shared_ptr<endpoint> > > > > client_endpoints_; + std::map<service_t, + std::map<instance_t, std::map<bool, std::shared_ptr<endpoint_definition> > > > remote_service_info_; + std::map<service_t, std::map<instance_t, std::map<client_t, std::map<bool, std::shared_ptr<endpoint> > > > >remote_services_; + std::map<boost::asio::ip::address, + std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > > client_endpoints_by_ip_; - // Servicegroups - std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_; - std::map<service_t, std::map<instance_t, std::shared_ptr<serviceinfo> > > services_; + // Services + services_t services_; // Eventgroups std::map<service_t, @@ -246,6 +281,8 @@ private: mutable std::recursive_mutex endpoint_mutex_; mutable std::mutex local_mutex_; std::mutex serialize_mutex_; + mutable std::mutex services_mutex_; + mutable std::mutex eventgroups_mutex_; std::map<client_t, std::shared_ptr<endpoint_definition>> remote_subscriber_map_; diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp index a142db8..852ca19 100644 --- a/implementation/routing/include/routing_manager_proxy.hpp +++ b/implementation/routing/include/routing_manager_proxy.hpp @@ -39,20 +39,20 @@ public: void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor); void stop_offer_service(client_t _client, service_t _service, instance_t _instance); void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective); + minor_version_t _minor, bool _use_exclusive_proxy); void release_service(client_t _client, service_t _service, instance_t _instance); void subscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); + eventgroup_t _eventgroup, major_version_t _major); void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); @@ -68,15 +68,26 @@ public: bool send_to(const std::shared_ptr<endpoint_definition> &_target, const byte_t *_data, uint32_t _size); + void register_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + std::set<eventgroup_t> _eventgroups, + bool _is_field, bool _is_provided); + + void unregister_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + bool _is_provided); + void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload); void notify_one(service_t _service, instance_t _instance, - event_t _event, std::shared_ptr<payload> _payload, client_t _client); + event_t _event, std::shared_ptr<payload> _payload, + client_t _client); void on_connect(std::shared_ptr<endpoint> _endpoint); void on_disconnect(std::shared_ptr<endpoint> _endpoint); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); void on_routing_info(const byte_t *_data, uint32_t _size); @@ -95,36 +106,47 @@ private: void send_pong() const; void send_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor); + void send_request_service(client_t _client, service_t _service, + instance_t _instance, major_version_t _major, + 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, + 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, ttl_t _ttl); + major_version_t _major); - void send_request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _is_selective); + bool is_field(service_t _service, instance_t _instance, + event_t _event) const; private: - boost::asio::io_service &io_;bool is_connected_;bool is_started_; - event_type_e state_; + boost::asio::io_service &io_; + bool is_connected_; + bool is_started_; + state_type_e state_; routing_manager_host *host_; client_t client_; // store locally as it is needed in each message + std::shared_ptr<configuration> configuration_; + std::shared_ptr<serializer> serializer_; std::shared_ptr<deserializer> deserializer_; - std::shared_ptr<endpoint> sender_; // --> stub + std::shared_ptr<endpoint> sender_; // --> stub std::shared_ptr<endpoint> receiver_; // --> from everybody std::map<client_t, std::shared_ptr<endpoint> > local_endpoints_; std::map<service_t, std::map<instance_t, client_t> > local_services_; + std::mutex local_services_mutex_; struct service_data_t { service_t service_; instance_t instance_; major_version_t major_; minor_version_t minor_; - ttl_t ttl_; + bool use_exclusive_proxy_; // only used for requests! bool operator<(const service_data_t &_other) const { return (service_ < _other.service_ @@ -135,12 +157,30 @@ private: std::set<service_data_t> pending_offers_; std::set<service_data_t> pending_requests_; + struct event_data_t { + service_t service_; + instance_t instance_; + event_t event_; + bool is_field_; + bool is_provided_; + std::set<eventgroup_t> eventgroups_; + + bool operator<(const event_data_t &_other) const { + return (service_ < _other.service_ + || (service_ == _other.service_ + && instance_ < _other.instance_) + || (service_ == _other.service_ + && instance_ == _other.instance_ + && event_ < _other.event_)); + } + }; + std::set<event_data_t> pending_event_registrations_; + struct eventgroup_data_t { service_t service_; instance_t instance_; eventgroup_t eventgroup_; major_version_t major_; - ttl_t ttl_; bool operator<(const eventgroup_data_t &_other) const { return (service_ < _other.service_ @@ -163,7 +203,7 @@ private: std::mutex deserialize_mutex_; std::mutex pending_mutex_; - bool is_selective_; + std::map<service_t, std::map<instance_t, std::set<event_t> > > fields_; }; } // namespace vsomeip diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp index c261303..6a1ec38 100644 --- a/implementation/routing/include/routing_manager_stub.hpp +++ b/implementation/routing/include/routing_manager_stub.hpp @@ -19,12 +19,15 @@ namespace vsomeip { +class configuration; class routing_manager_stub_host; class routing_manager_stub: public endpoint_host, public std::enable_shared_from_this<routing_manager_stub> { public: - routing_manager_stub(routing_manager_stub_host *_host); + routing_manager_stub( + routing_manager_stub_host *_host, + std::shared_ptr<configuration> _configuration); virtual ~routing_manager_stub(); void init(); @@ -34,6 +37,7 @@ public: void on_connect(std::shared_ptr<endpoint> _endpoint); void on_disconnect(std::shared_ptr<endpoint> _endpoint); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); void on_offer_service(client_t _client, service_t _service, instance_t _instance); @@ -56,17 +60,17 @@ private: void send_application_lost(std::list<client_t> &_lost); private: + routing_manager_stub_host *host_; boost::asio::io_service &io_; boost::asio::system_timer watchdog_timer_; - routing_manager_stub_host *host_; - std::string endpoint_path_; std::shared_ptr<endpoint> endpoint_; std::map<client_t, std::pair<uint8_t, std::map<service_t, std::set<instance_t> > > > routing_info_; mutable std::mutex routing_info_mutex_; + std::shared_ptr<configuration> configuration_; }; } // namespace vsomeip diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp index 049bc13..f25eef2 100644 --- a/implementation/routing/include/routing_manager_stub_host.hpp +++ b/implementation/routing/include/routing_manager_stub_host.hpp @@ -17,21 +17,29 @@ public: virtual void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) = 0; + minor_version_t _minor) = 0; virtual void stop_offer_service(client_t _client, service_t _service, instance_t _instance) = 0; virtual void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective) = 0; + minor_version_t _minor, bool _use_exclusive_proxy) = 0; virtual void release_service(client_t _client, service_t _service, instance_t _instance) = 0; + virtual void register_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + 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, event_t _event, bool _is_provided) = 0; + virtual void subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) = 0; + major_version_t _major) = 0; virtual void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; @@ -39,6 +47,10 @@ public: virtual void on_message(service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _reliable) = 0; + virtual void on_notification(client_t _client, + service_t _service, instance_t _instance, + const byte_t *_data, length_t _size) = 0; + virtual void on_stop_offer_service(service_t _service, instance_t _instance) = 0; diff --git a/implementation/routing/include/servicegroup.hpp b/implementation/routing/include/servicegroup.hpp deleted file mode 100644 index 6014df1..0000000 --- a/implementation/routing/include/servicegroup.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef VSOMEIP_SERVICEGROUP_HPP -#define VSOMEIP_SERVICEGROUP_HPP - -#include <memory> -#include <set> -#include <string> - -#include "types.hpp" - -namespace vsomeip { - -class serviceinfo; - -class servicegroup { -public: - servicegroup(const std::string &_name, bool _is_local); - virtual ~servicegroup(); - - std::string get_name() const; - bool is_local() const; - - bool add_service(service_t _service, instance_t _instance, - std::shared_ptr<serviceinfo> _info); - bool remove_service(service_t _service, instance_t _instance); - - services_t get_services() const; - -private: - std::string name_; - bool is_local_; - services_t services_; -}; - -} // namespace vsomeip - -#endif // VSOMEIP_SERVICEGROUP_HPP diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp index a98127e..af3a50c 100644 --- a/implementation/routing/include/serviceinfo.hpp +++ b/implementation/routing/include/serviceinfo.hpp @@ -21,7 +21,7 @@ class servicegroup; class serviceinfo { public: VSOMEIP_EXPORT serviceinfo(major_version_t _major, minor_version_t _minor, - ttl_t _ttl); + ttl_t _ttl, bool _is_local); VSOMEIP_EXPORT ~serviceinfo(); VSOMEIP_EXPORT servicegroup * get_group() const; @@ -49,6 +49,8 @@ public: VSOMEIP_EXPORT void add_client(client_t _client); VSOMEIP_EXPORT void remove_client(client_t _client); + VSOMEIP_EXPORT bool is_local() const; + private: servicegroup *group_; @@ -64,6 +66,8 @@ private: eventgroup_t multicast_group_; std::set<client_t> requesters_; + + bool is_local_; }; } // namespace vsomeip diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp index eb86a12..4572632 100644 --- a/implementation/routing/src/event.cpp +++ b/implementation/routing/src/event.cpp @@ -4,7 +4,6 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include <vsomeip/defines.hpp> -#include <vsomeip/logger.hpp> #include <vsomeip/message.hpp> #include <vsomeip/payload.hpp> #include <vsomeip/runtime.hpp> @@ -12,6 +11,7 @@ #include "../include/event.hpp" #include "../include/routing_manager.hpp" #include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/payload_impl.hpp" namespace vsomeip { @@ -21,7 +21,8 @@ event::event(routing_manager *_routing) : message_(runtime::get()->create_notification()), cycle_timer_(_routing->get_io()), is_updating_on_change_(true), - is_set_(false) { + is_set_(false), + ref_(0) { } service_t event::get_service() const { @@ -56,6 +57,14 @@ void event::set_field(bool _is_field) { is_field_ = _is_field; } +bool event::is_provided() const { + return (is_provided_); +} + +void event::set_provided(bool _is_provided) { + is_provided_ = _is_provided; +} + bool event::is_reliable() const { return message_->is_reliable(); } @@ -69,64 +78,76 @@ const std::shared_ptr<payload> event::get_payload() const { } void event::set_payload(std::shared_ptr<payload> _payload) { - if (set_payload_helper(_payload)) { - std::shared_ptr<payload> its_new_payload - = runtime::get()->create_payload( - _payload->get_data(), _payload->get_length()); - - message_->set_payload(its_new_payload); - if (is_updating_on_change_) { - notify(); - } - } + if (is_provided_) { + if (set_payload_helper(_payload)) { + std::shared_ptr<payload> its_new_payload + = runtime::get()->create_payload( + _payload->get_data(), _payload->get_length()); + + message_->set_payload(its_new_payload); + if (is_updating_on_change_) { + notify(); + } + } + } } void event::set_payload(std::shared_ptr<payload> _payload, client_t _client) { - set_payload_helper(_payload); - std::shared_ptr<payload> its_new_payload - = runtime::get()->create_payload( - _payload->get_data(), _payload->get_length()); - - message_->set_payload(its_new_payload); - if (is_updating_on_change_) { - notify_one(_client); - } + if (is_provided_) { + set_payload_helper(_payload); + std::shared_ptr<payload> its_new_payload + = runtime::get()->create_payload( + _payload->get_data(), _payload->get_length()); + + message_->set_payload(its_new_payload); + if (is_updating_on_change_) { + notify_one(_client); + } + } } void event::set_payload(std::shared_ptr<payload> _payload, const std::shared_ptr<endpoint_definition> _target) { - - set_payload_helper(_payload); - std::shared_ptr<payload> its_new_payload - = runtime::get()->create_payload( - _payload->get_data(), _payload->get_length()); - - message_->set_payload(its_new_payload); - if (is_updating_on_change_) { - notify_one(_target); - } + if (is_provided_) { + if (set_payload_helper(_payload)) { + std::shared_ptr<payload> its_new_payload + = runtime::get()->create_payload( + _payload->get_data(), _payload->get_length()); + + message_->set_payload(its_new_payload); + if (is_updating_on_change_) { + notify_one(_target); + } + } + } } void event::unset_payload() { - is_set_ = false; - message_->set_payload(std::make_shared<payload_impl>()); + if (is_provided_) { + is_set_ = false; + message_->set_payload(std::make_shared<payload_impl>()); + } } void event::set_update_on_change(bool _is_active) { - is_updating_on_change_ = _is_active; + if (is_provided_) { + is_updating_on_change_ = _is_active; + } } void event::set_update_cycle(std::chrono::milliseconds &_cycle) { - cycle_ = _cycle; + if (is_provided_) { + cycle_ = _cycle; - cycle_timer_.cancel(); + cycle_timer_.cancel(); - if (std::chrono::milliseconds::zero() != _cycle) { - cycle_timer_.expires_from_now(cycle_); - std::function<void(boost::system::error_code const &)> its_handler = - std::bind(&event::update_cbk, shared_from_this(), - std::placeholders::_1); - cycle_timer_.async_wait(its_handler); + if (std::chrono::milliseconds::zero() != _cycle) { + cycle_timer_.expires_from_now(cycle_); + std::function<void(boost::system::error_code const &)> its_handler = + std::bind(&event::update_cbk, shared_from_this(), + std::placeholders::_1); + cycle_timer_.async_wait(its_handler); + } } } @@ -172,7 +193,7 @@ void event::notify_one(client_t _client) { bool event::set_payload_helper(std::shared_ptr<payload> _payload) { std::shared_ptr<payload> its_payload = message_->get_payload(); bool is_change(!is_field_); - if(is_field_) { + if (is_field_) { is_change = (its_payload->get_length() != _payload->get_length()); if (!is_change) { std::size_t its_pos = 0; @@ -189,4 +210,13 @@ bool event::set_payload_helper(std::shared_ptr<payload> _payload) { return is_change; } +void event::add_ref() { + ref_++; +} + +uint32_t event::remove_ref() { + ref_--; + return ref_; +} + } // namespace vsomeip diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp index 64d9b6b..0d098e4 100644 --- a/implementation/routing/src/eventgroupinfo.cpp +++ b/implementation/routing/src/eventgroupinfo.cpp @@ -10,76 +10,83 @@ namespace vsomeip { eventgroupinfo::eventgroupinfo() - : major_(DEFAULT_MAJOR), - ttl_(DEFAULT_TTL), - is_multicast_(false) { + : major_(DEFAULT_MAJOR), ttl_(DEFAULT_TTL), is_multicast_(false) { } eventgroupinfo::eventgroupinfo(major_version_t _major, ttl_t _ttl) - : major_(_major), - ttl_(_ttl), - is_multicast_(false) { + : major_(_major), ttl_(_ttl), is_multicast_(false) { } eventgroupinfo::~eventgroupinfo() { } major_version_t eventgroupinfo::get_major() const { - return major_; + return major_; } void eventgroupinfo::set_major(major_version_t _major) { - major_ = _major; + major_ = _major; } ttl_t eventgroupinfo::get_ttl() const { - return ttl_; + return ttl_; } void eventgroupinfo::set_ttl(ttl_t _ttl) { - ttl_ = _ttl; + ttl_ = _ttl; } bool eventgroupinfo::is_multicast() const { - return is_multicast_; + return is_multicast_; } -bool eventgroupinfo::get_multicast(boost::asio::ip::address &_address, uint16_t &_port) const { - if (is_multicast_) { - _address = address_; - _port = port_; - } - return is_multicast_; +bool eventgroupinfo::get_multicast(boost::asio::ip::address &_address, + uint16_t &_port) const { + if (is_multicast_) { + _address = address_; + _port = port_; + } + return is_multicast_; } -void eventgroupinfo::set_multicast(const boost::asio::ip::address &_address, uint16_t _port) { - address_ = _address; - port_ = _port; - is_multicast_ = true; +void eventgroupinfo::set_multicast(const boost::asio::ip::address &_address, + uint16_t _port) { + address_ = _address; + port_ = _port; + is_multicast_ = true; } const std::set<std::shared_ptr<event> > eventgroupinfo::get_events() const { - return events_; + return events_; } void eventgroupinfo::add_event(std::shared_ptr<event> _event) { - events_.insert(_event); + events_.insert(_event); +} + +void eventgroupinfo::remove_event(std::shared_ptr<event> _event) { + events_.erase(_event); } const std::set<std::shared_ptr<endpoint_definition> > eventgroupinfo::get_targets() const { - return targets_; + return targets_; } -void eventgroupinfo::add_target(std::shared_ptr<endpoint_definition> _target) { - targets_.insert(_target); +bool eventgroupinfo::add_target(std::shared_ptr<endpoint_definition> _target) { + std::size_t its_size = targets_.size(); + targets_.insert(_target); + return (its_size != targets_.size()); } -void eventgroupinfo::del_target(std::shared_ptr<endpoint_definition> _target) { - targets_.erase(_target); +bool eventgroupinfo::remove_target( + std::shared_ptr<endpoint_definition> _target) { + std::size_t its_size = targets_.size(); + targets_.erase(_target); + return (its_size != targets_.size()); } void eventgroupinfo::clear_targets() { - targets_.clear(); + targets_.clear(); } } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp index d22a76e..ff1c67e 100644 --- a/implementation/routing/src/routing_manager_impl.cpp +++ b/implementation/routing/src/routing_manager_impl.cpp @@ -7,9 +7,7 @@ #include <memory> #include <sstream> -#include <vsomeip/configuration.hpp> #include <vsomeip/constants.hpp> -#include <vsomeip/logger.hpp> #include <vsomeip/message.hpp> #include <vsomeip/payload.hpp> #include <vsomeip/runtime.hpp> @@ -19,8 +17,8 @@ #include "../include/routing_manager_host.hpp" #include "../include/routing_manager_impl.hpp" #include "../include/routing_manager_stub.hpp" -#include "../include/servicegroup.hpp" #include "../include/serviceinfo.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/endpoint_definition.hpp" #include "../../endpoints/include/local_client_endpoint_impl.hpp" @@ -28,6 +26,8 @@ #include "../../endpoints/include/tcp_server_endpoint_impl.hpp" #include "../../endpoints/include/udp_client_endpoint_impl.hpp" #include "../../endpoints/include/udp_server_endpoint_impl.hpp" +#include "../../endpoints/include/virtual_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/deserializer.hpp" #include "../../message/include/serializer.hpp" #include "../../service_discovery/include/constants.hpp" @@ -40,10 +40,11 @@ namespace vsomeip { routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : - host_(_host), io_(_host->get_io()), deserializer_( - std::make_shared<deserializer>()), serializer_( - std::make_shared<serializer>()), configuration_( - host_->get_configuration()) { + host_(_host), + io_(_host->get_io()), + deserializer_(std::make_shared<deserializer>()), + serializer_(std::make_shared<serializer>()), + configuration_(host_->get_configuration()) { } routing_manager_impl::~routing_manager_impl() { @@ -58,22 +59,16 @@ client_t routing_manager_impl::get_client() const { } void routing_manager_impl::init() { - uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; - if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; - - serializer_->create_data(its_max_message_size); + serializer_->create_data(configuration_->get_max_message_size_local()); // TODO: Only instantiate the stub if needed - stub_ = std::make_shared<routing_manager_stub>(this); + stub_ = std::make_shared<routing_manager_stub>(this, configuration_); stub_->init(); // We need to be able to send messages to ourself (for delivering events) (void)create_local(VSOMEIP_ROUTING_CLIENT); - if (configuration_->is_service_discovery_enabled()) { + if (configuration_->is_sd_enabled()) { VSOMEIP_INFO<< "Service Discovery enabled. Trying to load module."; std::shared_ptr<sd::runtime> *its_runtime = static_cast<std::shared_ptr<sd::runtime> *>(utility::load_library( @@ -85,10 +80,8 @@ void routing_manager_impl::init() { discovery_ = (*its_runtime)->create_service_discovery(this); discovery_->init(); } - - init_event_routing_info(); } else { - init_routing_info(); + init_routing_info(); // Static routing } } @@ -97,11 +90,11 @@ void routing_manager_impl::start() { if (discovery_) discovery_->start(); - host_->on_event(event_type_e::ET_REGISTERED); + host_->on_state(state_type_e::ST_REGISTERED); } void routing_manager_impl::stop() { - host_->on_event(event_type_e::ET_DEREGISTERED); + host_->on_state(state_type_e::ST_DEREGISTERED); if (discovery_) discovery_->stop(); @@ -109,8 +102,7 @@ void routing_manager_impl::stop() { } void routing_manager_impl::offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl) { + instance_t _instance, major_version_t _major, minor_version_t _minor) { std::shared_ptr<serviceinfo> its_info; { std::lock_guard<std::mutex> its_lock(local_mutex_); @@ -121,20 +113,18 @@ void routing_manager_impl::offer_service(client_t _client, service_t _service, if (its_info) { if (its_info->get_major() == _major && its_info->get_minor() == _minor) { - its_info->set_ttl(_ttl); + its_info->set_ttl(DEFAULT_TTL); } else { host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); } } else { - its_info = create_service(_service, _instance, _major, _minor, _ttl); + its_info = create_service_info(_service, _instance, _major, _minor, + DEFAULT_TTL, true); } } if (discovery_ && its_info) { - std::string group_name("default"); - if (its_info->get_group()) - group_name = its_info->get_group()->get_name(); - discovery_->on_offer_change(group_name); + discovery_->on_offer_change(); } stub_->on_offer_service(_client, _service, _instance); @@ -149,26 +139,26 @@ void routing_manager_impl::stop_offer_service(client_t _client, void routing_manager_impl::request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl, bool _has_selective) { + bool _use_exclusive_proxy) { std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); if (its_info) { - if ((_major < ANY_MAJOR && _major > its_info->get_major()) - || (_major == its_info->get_major() - && _minor < ANY_MINOR && _minor > its_info->get_minor()) - || (_ttl > its_info->get_ttl())) { - host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); - } else { + if ((_major == its_info->get_major() + || DEFAULT_MAJOR == its_info->get_major()) + && (_minor <= its_info->get_minor() + || DEFAULT_MINOR == its_info->get_minor())) { its_info->add_client(_client); + } else { + host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); } } else { if (discovery_) discovery_->request_service(_service, _instance, _major, _minor, - _ttl); + DEFAULT_TTL); } // TODO: Mutex?! - if (_has_selective) { + if (_use_exclusive_proxy) { specific_endpoint_clients.insert(_client); } } @@ -185,35 +175,36 @@ 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, - ttl_t _ttl) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { if (discovery_) { if (!host_->on_subscription(_service, _instance, _eventgroup, _client, true)) { VSOMEIP_INFO << "Subscription request for eventgroup " << _eventgroup - << " rejected from application handler"; + << " rejected from application handler"; return; } - eventgroup_clients_[_service][_instance][_eventgroup].insert(_client); - if (0 == find_local_client(_service, _instance)) { - client_t subscriber = VSOMEIP_ROUTING_CLIENT; - // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint - auto its_selective = specific_endpoint_clients.find(_client); - if (its_selective != specific_endpoint_clients.end()) { - subscriber = _client; - } - discovery_->subscribe(_service, _instance, _eventgroup, _major, - _ttl, subscriber); - } else { - send_subscribe(_client, _service, _instance, _eventgroup, _major, _ttl); - std::shared_ptr<eventgroupinfo> its_eventgroup - = find_eventgroup(_service, _instance, _eventgroup); - if (its_eventgroup) { - std::set<std::shared_ptr<event> > its_events - = its_eventgroup->get_events(); - for (auto e : its_events) { - if (e->is_field()) - e->notify_one(_client); + if (insert_subscription(_service, _instance, _eventgroup, _client)) { + if (0 == find_local_client(_service, _instance)) { + client_t subscriber = VSOMEIP_ROUTING_CLIENT; + // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint + auto its_selective = specific_endpoint_clients.find(_client); + if (its_selective != specific_endpoint_clients.end()) { + subscriber = _client; + } + discovery_->subscribe(_service, _instance, _eventgroup, + _major, DEFAULT_TTL, subscriber); + } else { + send_subscribe(_client, _service, _instance, _eventgroup, _major); + + std::shared_ptr<eventgroupinfo> its_eventgroup + = find_eventgroup(_service, _instance, _eventgroup); + if (its_eventgroup) { + std::set<std::shared_ptr<event> > its_events + = its_eventgroup->get_events(); + for (auto e : its_events) { + if (e->is_field()) + e->notify_one(_client); + } } } } @@ -240,12 +231,18 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service, } } host_->on_subscription(_service, _instance, _eventgroup, _client, false); - if (0 == find_local_client(_service, _instance)) { - discovery_->unsubscribe(_service, _instance, _eventgroup); + client_t subscriber = VSOMEIP_ROUTING_CLIENT; + // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint + auto its_selective = specific_endpoint_clients.find(_client); + if (its_selective != specific_endpoint_clients.end()) { + subscriber = _client; + } + discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber); } else { send_unsubscribe(_client, _service, _instance, _eventgroup); } + clear_multicast_endpoints(_service, _instance); } else { VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!"; } @@ -265,6 +262,8 @@ bool routing_manager_impl::send(client_t its_client, serializer_->get_size(), _message->get_instance(), _flush, _message->is_reliable()); serializer_->reset(); + } else { + VSOMEIP_ERROR << "Failed to serialize message. Check message size!"; } return (is_sent); @@ -409,7 +408,7 @@ bool routing_manager_impl::send_local( std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t) + sizeof(bool)], &_reliable, sizeof(bool)); - return _target->send(&its_command[0], its_command.size(), _flush); + return _target->send(&its_command[0], uint32_t(its_command.size()), _flush); } bool routing_manager_impl::send_to( @@ -430,12 +429,94 @@ 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) { - std::shared_ptr<endpoint> its_endpoint = find_or_create_server_endpoint( + std::shared_ptr<endpoint> its_endpoint = find_server_endpoint( _target->get_remote_port(), _target->is_reliable()); return (its_endpoint && its_endpoint->send_to(_target, _data, _size)); } +void routing_manager_impl::register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, std::set<eventgroup_t> _eventgroups, + bool _is_field, bool _is_provided) { + (void)_client; + + std::shared_ptr<event> its_event = find_event(_service, _instance, _event); + if (its_event) { + if (its_event->is_field() == _is_field) { + if (_is_provided) { + its_event->set_provided(true); + } + for (auto eg : _eventgroups) { + its_event->add_eventgroup(eg); + } + } else { + VSOMEIP_ERROR << "Event registration update failed. " + "Specified arguments do not match existing registration."; + } + } else { + its_event = std::make_shared<event>(this); + its_event->set_service(_service); + its_event->set_instance(_instance); + its_event->set_event(_event); + its_event->set_field(_is_field); + its_event->set_provided(_is_provided); + + if (_eventgroups.size() == 0) { // No eventgroup specified + _eventgroups.insert(_event); + } + + its_event->set_eventgroups(_eventgroups); + } + + its_event->add_ref(); + + for (auto eg : _eventgroups) { + std::shared_ptr<eventgroupinfo> its_eventgroup_info + = find_eventgroup(_service, _instance, eg); + if (!its_eventgroup_info) { + its_eventgroup_info = std::make_shared<eventgroupinfo>(); + eventgroups_[_service][_instance][eg] = its_eventgroup_info; + } + its_eventgroup_info->add_event(its_event); + } + + events_[_service][_instance][_event] = its_event; +} + +void routing_manager_impl::unregister_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, bool _is_provided) { + (void)_client; + + auto found_service = events_.find(_service); + if (found_service != events_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_event = found_instance->second.find(_event); + if (found_event != found_instance->second.end()) { + auto its_event = found_event->second; + if (!its_event->remove_ref()) { + auto its_eventgroups = its_event->get_eventgroups(); + for (auto eg : its_eventgroups) { + std::shared_ptr<eventgroupinfo> its_eventgroup_info + = find_eventgroup(_service, _instance, eg); + if (its_eventgroup_info) { + its_eventgroup_info->remove_event(its_event); + if (0 == its_eventgroup_info->get_events().size()) { + remove_eventgroup_info(_service, _instance, eg); + } + } + } + found_instance->second.erase(_event); + } else if (_is_provided) { + its_event->set_provided(false); + } + } + } + } +} + void routing_manager_impl::notify( service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload) { @@ -443,9 +524,9 @@ void routing_manager_impl::notify( if (its_event) { its_event->set_payload(_payload); } else { - VSOMEIP_ERROR << "routing_manager_impl::notify: event [" + VSOMEIP_WARNING << "Attempt to update the undefined event/field [" << std::hex << _service << "." << _instance << "." << _event - << "] is unknown."; + << "]"; } } @@ -466,10 +547,21 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance, } } } else { - VSOMEIP_ERROR << "routing_manager_impl::notify: event [" + VSOMEIP_WARNING << "Attempt to update the undefined event/field [" << std::hex << _service << "." << _instance << "." << _event - << "] is unknown."; + << "]"; + } +} + +void routing_manager_impl::on_error(const byte_t *_data, length_t _length, endpoint *_receiver) { + instance_t its_instance = 0; + if (_length >= VSOMEIP_SERVICE_POS_MAX) { + service_t its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + its_instance = find_instance(its_service, _receiver); } + send_error(return_code_e::E_MALFORMED_MESSAGE, _data, _length, + its_instance, _receiver->is_reliable(), _receiver); } void routing_manager_impl::on_message(const byte_t *_data, length_t _size, @@ -482,9 +574,6 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, VSOMEIP_DEBUG << msg.str(); #endif service_t its_service; - instance_t its_instance; - message_type_e its_message_type; - if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) { its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); @@ -492,41 +581,21 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, if (discovery_) discovery_->on_message(_data, _size); } else { - its_instance = find_instance(its_service, _receiver); - its_message_type = static_cast<message_type_e>(_data[VSOMEIP_MESSAGE_TYPE_POS]); - if (its_instance == 0xFFFF) { - VSOMEIP_WARNING << "Receiving endpoint is not configured for service 0x" - << std::hex << its_service; + instance_t its_instance = find_instance(its_service, _receiver); + return_code_e return_code = check_error(_data, _size, its_instance); + if (return_code != return_code_e::E_OK) { + if (return_code != return_code_e::E_NOT_OK) { + send_error(return_code, _data, _size, its_instance, + _receiver->is_reliable(), _receiver); + } return; } - // TODO: move specific endpoint handling to to a method! - auto found_service = remote_services_.find(its_service); - if (found_service != remote_services_.end()) { - auto found_instance = found_service->second.find(its_instance); - if (found_instance != found_service->second.end()) { - for (auto client_entry : found_instance->second) { - client_t client = client_entry.first; - if (!client) { - continue; - } - auto found_reliability = client_entry.second.find(_receiver->is_reliable()); - if (found_reliability != client_entry.second.end()) { - auto found_enpoint = found_reliability->second; - if (found_enpoint.get() == _receiver) { - auto local_endpoint = find_local(client); - if (client != get_client()) { - send_local(local_endpoint, client, _data, _size, its_instance, true, _receiver->is_reliable()); - } else { - deliver_message(_data, _size, its_instance, _receiver->is_reliable()); - } - return; - } - } - } - } + if (!deliver_specific_endpoint_message( + its_service, its_instance, _data, _size, _receiver)) { + // Common way of message handling + on_message(its_service, its_instance, _data, _size, _receiver->is_reliable()); } - on_message(its_service, its_instance, _data, _size, _receiver->is_reliable()); } } } @@ -535,6 +604,15 @@ void routing_manager_impl::on_message( service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _reliable) { +#if 0 + std::stringstream msg; + msg << "rmi::on_message(" + << std::hex << std::setw(4) << std::setfill('0') + << _service << ", " << _instance << "): "; + for (uint32_t i = 0; i < _size; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif method_t its_method; client_t its_client; session_t its_session; @@ -552,10 +630,6 @@ void routing_manager_impl::on_message( const_cast<byte_t *>(_data)[VSOMEIP_CLIENT_POS_MIN] = 0; const_cast<byte_t *>(_data)[VSOMEIP_CLIENT_POS_MAX] = 0; - its_method = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_METHOD_POS_MIN], - _data[VSOMEIP_METHOD_POS_MAX]); - auto it_subscriber = remote_subscriber_map_.find(its_client); if (it_subscriber != remote_subscriber_map_.end()) { send_to(it_subscriber->second, _data, _size); @@ -574,11 +648,11 @@ void routing_manager_impl::on_message( = find_event(_service, _instance, its_method); if (its_event) { uint32_t its_length = utility::get_payload_size(_data, _size); - std::shared_ptr<payload> its_payload = - runtime::get()->create_payload( - &_data[VSOMEIP_PAYLOAD_POS], - its_length); - its_event->set_payload(its_payload); + std::shared_ptr<payload> its_payload = + runtime::get()->create_payload( + &_data[VSOMEIP_PAYLOAD_POS], + its_length); + its_event->set_payload(its_payload); if (!utility::is_request_no_return( _data[VSOMEIP_MESSAGE_TYPE_POS])) { @@ -622,27 +696,59 @@ void routing_manager_impl::on_message( _data[VSOMEIP_CLIENT_POS_MAX]); } - if ((its_client == VSOMEIP_ROUTING_CLIENT - && utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) - || its_client == host_->get_client()) { + if (its_client == VSOMEIP_ROUTING_CLIENT + && utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + deliver_notification(_service, _instance, _data, _size, _reliable); + } else if (its_client == host_->get_client()) { deliver_message(_data, _size, _instance, _reliable); } else { send(its_client, _data, _size, _instance, true, _reliable); } } +void routing_manager_impl::on_notification(client_t _client, + service_t _service, instance_t _instance, + const byte_t *_data, length_t _size) { + event_t its_event_id = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], + _data[VSOMEIP_METHOD_POS_MAX]); + + std::shared_ptr<event> its_event = find_event(_service, _instance, its_event_id); + if (its_event) { + uint32_t its_length = utility::get_payload_size(_data, _size); + std::shared_ptr<payload> its_payload = + runtime::get()->create_payload( + &_data[VSOMEIP_PAYLOAD_POS], + its_length); + + if (_client == VSOMEIP_ROUTING_CLIENT) + its_event->set_payload(its_payload); + else + its_event->set_payload(its_payload, _client); + } +} + void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) { + // Is called when endpoint->connect succeded! for (auto &its_service : remote_services_) { for (auto &its_instance : its_service.second) { - auto found_endpoint = its_instance.second.find(false); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, - true); - } else { - found_endpoint = its_instance.second.find(true); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, - its_instance.first, true); + for (auto &its_client : its_instance.second) { + if (its_client.first == VSOMEIP_ROUTING_CLIENT || + its_client.first == get_client()) { + auto found_endpoint = its_client.second.find(false); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, its_instance.first, + true); + } + } + found_endpoint = its_client.second.find(true); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, + its_instance.first, true); + } + } } } } @@ -650,17 +756,26 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) { } void routing_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) { + // Is called when endpoint->connect fails! for (auto &its_service : remote_services_) { for (auto &its_instance : its_service.second) { - auto found_endpoint = its_instance.second.find(false); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, - false); - } else { - found_endpoint = its_instance.second.find(true); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, - its_instance.first, false); + for (auto &its_client : its_instance.second) { + if (its_client.first == VSOMEIP_ROUTING_CLIENT || + its_client.first == get_client()) { + auto found_endpoint = its_client.second.find(false); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, its_instance.first, + false); + } + } + found_endpoint = its_client.second.find(true); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, + its_instance.first, false); + } + } } } } @@ -675,50 +790,147 @@ void routing_manager_impl::on_stop_offer_service(service_t _service, for (auto &e : i.second) e.second->unset_payload(); - host_->on_availability(_service, _instance, false); + /** + * Hold reliable & unreliable server-endpoints from service info + * because if "del_routing_info" is called those entries could be freed + * and we can't be sure this happens synchronous when SD is active. + * After triggering "del_routing_info" this endpoints gets cleanup up + * within this method if they not longer used by any other local service. + */ + std::shared_ptr<endpoint> its_reliable_endpoint; + std::shared_ptr<endpoint> its_unreliable_endpoint; + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (its_info) { + its_reliable_endpoint = its_info->get_endpoint(true); + its_unreliable_endpoint = its_info->get_endpoint(false); + } + // Trigger "del_routing_info" either over SD or static if (discovery_) { auto found_service = services_.find(_service); if (found_service != services_.end()) { auto found_instance = found_service->second.find(_instance); if (found_instance != found_service->second.end()) { found_instance->second->set_ttl(0); - discovery_->on_offer_change( - found_instance->second->get_group()->get_name()); + discovery_->on_offer_change(); } } } else { - // TODO: allow to withdraw a service on one endpoint only - del_routing_info(_service, _instance, false); - del_routing_info(_service, _instance, true); + del_routing_info(_service, _instance, + (its_reliable_endpoint != nullptr), + (its_unreliable_endpoint != nullptr)); + } + + // Cleanup reliable & unreliable server endpoints hold before + if (its_info) { + std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); + std::shared_ptr<endpoint> its_empty_endpoint; + bool reliable = true; + + // Loop over reliable/unreliable and cleanup if needed + for (uint8_t i = 0; i < 2; ++i) { + std::shared_ptr<endpoint> its_endpoint; + if (reliable) { + its_endpoint = its_reliable_endpoint; + } else { + its_endpoint = its_unreliable_endpoint; + } + if (!its_endpoint) { + reliable = !reliable; + continue; + } + + // Check whether any service still uses this endpoint + its_endpoint->decrement_use_count(); + bool isLastService = (its_endpoint->get_use_count() == 0); + + // Clear service_instances_ + if (1 >= service_instances_[_service].size()) { + service_instances_.erase(_service); + } else { + service_instances_[_service].erase(its_endpoint.get()); + } + + // Clear server endpoint if no service remains using it + if (isLastService) { + uint16_t port = its_endpoint->get_local_port(); + if (server_endpoints_.find(port) != server_endpoints_.end()) { + server_endpoints_[port].erase(reliable); + if (server_endpoints_[port].find(!reliable) == server_endpoints_[port].end()) { + server_endpoints_.erase(port); + } + } + + // Stop endpoint (close socket) to release its async_handlers! + its_endpoint->stop(); + } + + // Clear service info and service group + clear_service_info(_service, _instance, reliable); + + // Invert reliable flag and loop again + reliable = !reliable; + } } } bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, instance_t _instance, bool _reliable) { - bool is_sent(false); + bool is_delivered(false); deserializer_->set_data(_data, _size); std::shared_ptr<message> its_message(deserializer_->deserialize_message()); if (its_message) { its_message->set_instance(_instance); its_message->set_reliable(_reliable); host_->on_message(its_message); - is_sent = true; + is_delivered = true; } else { - // TODO: send error "Malformed Message" - //send_error(); + VSOMEIP_ERROR << "Deserialization of vSomeIP message failed"; + if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + send_error(return_code_e::E_MALFORMED_MESSAGE, _data, + _size, _instance, _reliable, nullptr); + } } - return (is_sent); + return is_delivered; } -const std::map<std::string, std::shared_ptr<servicegroup> > & -routing_manager_impl::get_servicegroups() const { - return (servicegroups_); +bool routing_manager_impl::deliver_notification( + service_t _service, instance_t _instance, + const byte_t *_data, length_t _length, + bool _reliable) { + bool is_delivered(false); + + method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], + _data[VSOMEIP_METHOD_POS_MAX]); + + std::shared_ptr<event> its_event = find_event(_service, _instance, its_method); + if (its_event) { + std::vector< byte_t > its_data; + + for (auto its_group : its_event->get_eventgroups()) { + auto its_local_clients = find_local_clients(_service, _instance, its_group); + for (auto its_local_client : its_local_clients) { + if (its_local_client == host_->get_client()) { + deliver_message(_data, _length, _instance, _reliable); + } else { + std::shared_ptr<endpoint> its_local_target = find_local(its_local_client); + if (its_local_target) { + send_local(its_local_target, VSOMEIP_ROUTING_CLIENT, + _data, _length, _instance, true, _reliable); + } + } + } + } + } + + return is_delivered; } std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup( service_t _service, instance_t _instance, eventgroup_t _eventgroup) const { + std::lock_guard<std::mutex> its_lock(eventgroups_mutex_); + std::shared_ptr<eventgroupinfo> its_info(nullptr); auto found_service = eventgroups_.find(_service); if (found_service != eventgroups_.end()) { @@ -758,20 +970,33 @@ std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup( return (its_info); } +void routing_manager_impl::remove_eventgroup_info(service_t _service, + instance_t _instance, eventgroup_t _eventgroup) { + std::lock_guard<std::mutex> its_lock(eventgroups_mutex_); + auto found_service = eventgroups_.find(_service); + if (found_service != eventgroups_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + found_instance->second.erase(_eventgroup); + } + } +} + std::shared_ptr<configuration> routing_manager_impl::get_configuration() const { return (host_->get_configuration()); } -void routing_manager_impl::create_service_discovery_endpoint( +std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoint( const std::string &_address, uint16_t _port, bool _reliable) { std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint(_port, _reliable); if (!its_service_endpoint) { - its_service_endpoint = create_server_endpoint(_port, _reliable); + its_service_endpoint = create_server_endpoint(_port, _reliable, true); if (its_service_endpoint) { std::shared_ptr<serviceinfo> its_info( - std::make_shared<serviceinfo>(ANY_MAJOR, ANY_MINOR, ANY_TTL)); + std::make_shared<serviceinfo>(ANY_MAJOR, ANY_MINOR, DEFAULT_TTL, + false)); // false, because we do _not_ want to announce it... its_info->set_endpoint(its_service_endpoint, _reliable); // routing info @@ -780,35 +1005,33 @@ void routing_manager_impl::create_service_discovery_endpoint( its_service_endpoint->add_multicast(VSOMEIP_SD_SERVICE, VSOMEIP_SD_METHOD, _address, _port); its_service_endpoint->join(_address); - its_service_endpoint->start(); } else { VSOMEIP_ERROR << "Service Discovery endpoint could not be created. " "Please check your network configuration."; } } + return its_service_endpoint; } -services_t routing_manager_impl::get_offered_services( - const std::string &_name) const { +services_t routing_manager_impl::get_offered_services() const { services_t its_offers; - auto find_servicegroup = servicegroups_.find(_name); - if (find_servicegroup != servicegroups_.end()) { - if (find_servicegroup->second->is_local()) { - return (find_servicegroup->second->get_services()); + std::lock_guard<std::mutex> its_lock(services_mutex_); + for (auto s : services_) { + for (auto i : s.second) { + if (i.second->is_local()) { + its_offers[s.first][i.first] = i.second; + } } } - return (its_offers); } std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client( service_t _service, instance_t _instance, bool _reliable, client_t _client) { + std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); std::shared_ptr<endpoint> its_endpoint = find_remote_client(_service, _instance, _reliable, _client); - // Create specific IP-client-endpoint for selective clients - if (!its_endpoint && - specific_endpoint_clients.find(_client) != specific_endpoint_clients.end()) { - + if (!its_endpoint) { its_endpoint = create_remote_client(_service, _instance, _reliable, _client); } return its_endpoint; @@ -820,6 +1043,7 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client( std::shared_ptr<serviceinfo> routing_manager_impl::find_service( service_t _service, instance_t _instance) const { std::shared_ptr<serviceinfo> its_info; + std::lock_guard<std::mutex> its_lock(services_mutex_); auto found_service = services_.find(_service); if (found_service != services_.end()) { auto found_instance = found_service->second.find(_instance); @@ -830,19 +1054,20 @@ std::shared_ptr<serviceinfo> routing_manager_impl::find_service( return (its_info); } -std::shared_ptr<serviceinfo> routing_manager_impl::create_service( +std::shared_ptr<serviceinfo> routing_manager_impl::create_service_info( service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { - + minor_version_t _minor, ttl_t _ttl, bool _is_local_service) { std::shared_ptr<serviceinfo> its_info; if (configuration_) { - its_info = std::make_shared<serviceinfo>(_major, _minor, _ttl); + its_info = std::make_shared<serviceinfo>(_major, _minor, _ttl, _is_local_service); uint16_t its_reliable_port = configuration_->get_reliable_port(_service, _instance); uint16_t its_unreliable_port = configuration_->get_unreliable_port( _service, _instance); + bool is_someip = configuration_->is_someip(_service, _instance); + its_info->set_multicast_address( configuration_->get_multicast_address(_service, _instance)); its_info->set_multicast_port( @@ -853,41 +1078,41 @@ std::shared_ptr<serviceinfo> routing_manager_impl::create_service( std::shared_ptr<endpoint> its_reliable_endpoint; std::shared_ptr<endpoint> its_unreliable_endpoint; - if (ILLEGAL_PORT != its_reliable_port) { - its_reliable_endpoint = find_or_create_server_endpoint( - its_reliable_port, - true); - its_info->set_endpoint(its_reliable_endpoint, true); - - // TODO: put this in a method and check whether an assignment already exists! - service_instances_[_service][its_reliable_endpoint.get()] = - _instance; - } + // Create server endpoints for local services only + if (_is_local_service) { + if (ILLEGAL_PORT != its_reliable_port) { + its_reliable_endpoint = find_or_create_server_endpoint( + its_reliable_port, true, is_someip); + if (its_reliable_endpoint) { + its_info->set_endpoint(its_reliable_endpoint, true); + its_reliable_endpoint->increment_use_count(); + service_instances_[_service][its_reliable_endpoint.get()] = + _instance; + } + } - if (ILLEGAL_PORT != its_unreliable_port) { - its_unreliable_endpoint = find_or_create_server_endpoint( - its_unreliable_port, false); - its_info->set_endpoint(its_unreliable_endpoint, false); + if (ILLEGAL_PORT != its_unreliable_port) { + its_unreliable_endpoint = find_or_create_server_endpoint( + its_unreliable_port, false, is_someip); + if (its_unreliable_endpoint) { + its_info->set_endpoint(its_unreliable_endpoint, false); + its_unreliable_endpoint->increment_use_count(); + service_instances_[_service][its_unreliable_endpoint.get()] = + _instance; + } + } - service_instances_[_service][its_unreliable_endpoint.get()] = - _instance; + if (ILLEGAL_PORT == its_reliable_port + && ILLEGAL_PORT == its_unreliable_port) { + VSOMEIP_DEBUG << "Port configuration missing for [" + << std::hex << _service << "." << _instance + << "]. Service is internal."; + } } - if (ILLEGAL_PORT != its_reliable_port - || ILLEGAL_PORT != its_unreliable_port) { - std::string its_servicegroup = configuration_->get_group(_service, - _instance); - auto found_servicegroup = servicegroups_.find(its_servicegroup); - if (found_servicegroup == servicegroups_.end()) { - servicegroups_[its_servicegroup] = - std::make_shared<servicegroup>(its_servicegroup, - configuration_->is_local_servicegroup(its_servicegroup)); - } - servicegroups_[its_servicegroup]->add_service(_service, _instance, - its_info); + { + std::lock_guard<std::mutex> its_lock(services_mutex_); services_[_service][_instance] = its_info; - } else { - VSOMEIP_DEBUG << "Port configuration missing. Assuming internal service."; } } else { host_->on_error(error_code_e::CONFIGURATION_MISSING); @@ -898,13 +1123,17 @@ std::shared_ptr<serviceinfo> routing_manager_impl::create_service( std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint( const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client) { + bool _reliable, client_t _client, bool _start) { + (void)_client; + std::shared_ptr<endpoint> its_endpoint; try { if (_reliable) { its_endpoint = std::make_shared<tcp_client_endpoint_impl>( shared_from_this(), - boost::asio::ip::tcp::endpoint(_address, _port), io_); + boost::asio::ip::tcp::endpoint(_address, _port), io_, + configuration_->get_message_size_reliable( + _address.to_string(), _port)); if (configuration_->has_enabled_magic_cookies(_address.to_string(), _port)) { @@ -915,9 +1144,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint( shared_from_this(), boost::asio::ip::udp::endpoint(_address, _port), io_); } - - client_endpoints_[_address][_port][_client][_reliable] = its_endpoint; - its_endpoint->start(); + if (_start) + its_endpoint->start(); } catch (...) { host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED); } @@ -925,63 +1153,38 @@ std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint( return (its_endpoint); } -std::shared_ptr<endpoint> routing_manager_impl::find_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client) { - std::shared_ptr<endpoint> its_endpoint; - auto found_address = client_endpoints_.find(_address); - if (found_address != client_endpoints_.end()) { - auto found_port = found_address->second.find(_port); - if (found_port != found_address->second.end()) { - auto found_client = found_port->second.find(_client); - if (found_client != found_port->second.end()) { - auto found_endpoint = found_client->second.find(_reliable); - if (found_endpoint != found_client->second.end()) { - its_endpoint = found_endpoint->second; - } - } - } - } - return (its_endpoint); -} - -std::shared_ptr<endpoint> routing_manager_impl::find_or_create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client) { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); - std::shared_ptr<endpoint> its_endpoint = find_client_endpoint(_address, - _port, _reliable, _client); - if (0 == its_endpoint) { - its_endpoint = create_client_endpoint(_address, _port, _reliable, _client); - } - return (its_endpoint); -} - std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( - uint16_t _port, bool _reliable) { + uint16_t _port, bool _reliable, bool _start) { + std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); std::shared_ptr<endpoint> its_endpoint; - try { - boost::asio::ip::address its_unicast = configuration_->get_unicast(); - if (_reliable) { - its_endpoint = std::make_shared<tcp_server_endpoint_impl>( - shared_from_this(), - boost::asio::ip::tcp::endpoint(its_unicast, _port), io_); - if (configuration_->has_enabled_magic_cookies( - its_unicast.to_string(), _port)) { - its_endpoint->enable_magic_cookies(); - } - } else { - // TODO: this should be more specific. - if (its_unicast.is_v4()) { - its_unicast = boost::asio::ip::address_v4::any(); + boost::asio::ip::address its_unicast = configuration_->get_unicast_address(); + if (_start) { + if (_reliable) { + its_endpoint = std::make_shared<tcp_server_endpoint_impl>( + shared_from_this(), + boost::asio::ip::tcp::endpoint(its_unicast, _port), io_, + configuration_->get_message_size_reliable( + its_unicast.to_string(), _port)); + if (configuration_->has_enabled_magic_cookies( + its_unicast.to_string(), _port)) { + its_endpoint->enable_magic_cookies(); + } } else { - // TODO: how is "ANY" specified in IPv6? + 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(); + } + boost::asio::ip::udp::endpoint ep(its_unicast, _port); + its_endpoint = std::make_shared<udp_server_endpoint_impl>( + shared_from_this(), + ep, io_); } - boost::asio::ip::udp::endpoint ep(its_unicast, _port); - its_endpoint = std::make_shared<udp_server_endpoint_impl>( - shared_from_this(), - ep, io_); + + } else { + its_endpoint = std::make_shared<virtual_server_endpoint_impl>( + its_unicast.to_string(), _port, _reliable); } if (its_endpoint) { @@ -999,6 +1202,7 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( std::shared_ptr<endpoint> routing_manager_impl::find_server_endpoint( uint16_t _port, bool _reliable) { std::shared_ptr<endpoint> its_endpoint; + std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); auto found_port = server_endpoints_.find(_port); if (found_port != server_endpoints_.end()) { auto found_endpoint = found_port->second.find(_reliable); @@ -1010,12 +1214,11 @@ std::shared_ptr<endpoint> routing_manager_impl::find_server_endpoint( } std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint( - uint16_t _port, bool _reliable) { - std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); + uint16_t _port, bool _reliable, bool _start) { std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port, _reliable); if (0 == its_endpoint) { - its_endpoint = create_server_endpoint(_port, _reliable); + its_endpoint = create_server_endpoint(_port, _reliable, _start); } return (its_endpoint); } @@ -1038,7 +1241,7 @@ std::shared_ptr<endpoint> routing_manager_impl::create_local(client_t _client) { #ifdef WIN32 boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1"); - int port = 51235 + _client; + int port = VSOMEIP_INTERNAL_BASE_PORT + _client; #endif std::shared_ptr<endpoint> its_endpoint = std::make_shared< @@ -1048,7 +1251,7 @@ std::shared_ptr<endpoint> routing_manager_impl::create_local(client_t _client) { #else boost::asio::local::stream_protocol::endpoint(its_path.str()) #endif - , io_); + , io_, configuration_->get_max_message_size_local()); local_clients_[_client] = its_endpoint; its_endpoint->start(); return (its_endpoint); @@ -1144,26 +1347,35 @@ instance_t routing_manager_impl::find_instance(service_t _service, std::shared_ptr<endpoint> routing_manager_impl::create_remote_client( service_t _service, instance_t _instance, bool _reliable, client_t _client) { std::shared_ptr<endpoint> its_endpoint; - auto found_service = remote_services_.find(_service); - if (found_service != remote_services_.end()) { + std::shared_ptr<endpoint_definition> its_endpoint_def; + auto found_service = remote_service_info_.find(_service); + if (found_service != remote_service_info_.end()) { auto found_instance = found_service->second.find(_instance); if (found_instance != found_service->second.end()) { - for (auto its_client : found_instance->second) { - auto found_reliability = its_client.second.find(_reliable); - if (found_reliability != its_client.second.end()) { - std::shared_ptr<endpoint> endpoint = found_reliability->second; - boost::asio::ip::address address; - endpoint->get_remote_address(address); - its_endpoint = find_or_create_client_endpoint(address, - endpoint->get_remote_port(), _reliable, _client); - break; - } + auto found_reliability = found_instance->second.find(_reliable); + if (found_reliability != found_instance->second.end()) { + its_endpoint_def = found_reliability->second; + its_endpoint = create_client_endpoint( + its_endpoint_def->get_address(), + its_endpoint_def->get_port(), _reliable, _client, + configuration_->is_someip(_service, _instance) + ); } } } if (its_endpoint) { - remote_services_[_service][_instance][_client][_reliable] = its_endpoint; service_instances_[_service][its_endpoint.get()] = _instance; + remote_services_[_service][_instance][_client][_reliable] = its_endpoint; + if (_client == VSOMEIP_ROUTING_CLIENT) { + client_endpoints_by_ip_[its_endpoint_def->get_address()] + [its_endpoint_def->get_port()] + [_reliable] = its_endpoint; + // Set the basic route to the service in the service info + auto found_service_info = find_service(_service, _instance); + if (found_service_info) { + found_service_info->set_endpoint(its_endpoint, _reliable); + } + } } return its_endpoint; } @@ -1185,6 +1397,41 @@ std::shared_ptr<endpoint> routing_manager_impl::find_remote_client( } } } + if(its_endpoint || _client != VSOMEIP_ROUTING_CLIENT) { + return its_endpoint; + } + + // If another service is hosted on the same server_endpoint + // reuse the existing client_endpoint. + auto found_service_info = remote_service_info_.find(_service); + if(found_service_info != remote_service_info_.end()) { + auto found_instance = found_service_info->second.find(_instance); + if(found_instance != found_service_info->second.end()) { + auto found_reliable = found_instance->second.find(_reliable); + if(found_reliable != found_instance->second.end()) { + std::shared_ptr<endpoint_definition> its_ep_def = + found_reliable->second; + auto found_address = client_endpoints_by_ip_.find( + its_ep_def->get_address()); + if(found_address != client_endpoints_by_ip_.end()) { + auto found_port = found_address->second.find( + its_ep_def->get_remote_port()); + if(found_port != found_address->second.end()) { + auto found_reliable2 = found_port->second.find( + _reliable); + if(found_reliable2 != found_port->second.end()) { + its_endpoint = found_reliable2->second; + // store the endpoint under this service/instance id + // as well - needed for later cleanup + remote_services_[_service][_instance][_client][_reliable] = + its_endpoint; + service_instances_[_service][its_endpoint.get()] = _instance; + } + } + } + } + } + } return its_endpoint; } @@ -1220,190 +1467,203 @@ std::set<std::shared_ptr<event> > routing_manager_impl::find_events( return (its_events); } -void routing_manager_impl::add_routing_info(service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable) { - std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if (!its_info) { - its_info = create_service(_service, _instance, _major, _minor, _ttl); - services_[_service][_instance] = its_info; - } - // If host doesn't have a specific endpoint we create it here - if (specific_endpoint_clients.find(get_client()) == specific_endpoint_clients.end()) { - std::shared_ptr<endpoint> its_endpoint( - find_or_create_client_endpoint(_address, _port, _reliable, VSOMEIP_ROUTING_CLIENT)); - its_info->set_endpoint(its_endpoint, _reliable); +bool routing_manager_impl::is_field(service_t _service, instance_t _instance, + event_t _event) const { + auto find_service = events_.find(_service); + if (find_service != events_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) { + auto find_event = find_instance->second.find(_event); + if (find_event != find_instance->second.end()) + return find_event->second->is_field(); + } + } + return false; +} - remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT][_reliable] = its_endpoint; - service_instances_[_service][its_endpoint.get()] = _instance; +void routing_manager_impl::add_routing_info( + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, ttl_t _ttl, + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port) { - if (its_endpoint->is_connected()) { - host_->on_availability(_service, _instance, true); + // Create/Update service info + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (!its_info) { + boost::asio::ip::address its_unicast_address + = configuration_->get_unicast_address(); + bool is_local(false); + if (_reliable_port != ILLEGAL_PORT + && its_unicast_address == _reliable_address) + is_local = true; + else if (_unreliable_port != ILLEGAL_PORT + && its_unicast_address == _unreliable_address) + is_local = true; + + its_info = create_service_info(_service, _instance, _major, _minor, _ttl, is_local); + { + std::lock_guard<std::mutex> its_lock(services_mutex_); + services_[_service][_instance] = its_info; } + } else { + its_info->set_ttl(_ttl); } - // Create all specific endpoints for proxies probably like them - for (client_t client : specific_endpoint_clients) { - std::shared_ptr<endpoint> its_endpoint( - find_or_create_client_endpoint(_address, _port, _reliable, client)); + // Check whether remote services are unchanged + bool is_reliable_known(false); + bool is_unreliable_known(false); - if (client == get_client()) { - its_info->set_endpoint(its_endpoint, _reliable); + auto found_service = remote_service_info_.find(_service); + if (found_service != remote_service_info_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + std::shared_ptr<endpoint_definition> its_definition; + if (_reliable_port != ILLEGAL_PORT) { + auto found_reliable = found_instance->second.find(true); + if (found_reliable != found_instance->second.end()) { + its_definition = found_reliable->second; + if (its_definition->get_address() == _reliable_address + && its_definition->get_port() == _reliable_port) { + is_reliable_known = true; + } + } else { + VSOMEIP_WARNING << "Reliable service endpoint has changed!"; + } + } + if (_unreliable_port != ILLEGAL_PORT) { + auto found_unreliable = found_instance->second.find(false); + if (found_unreliable != found_instance->second.end()) { + its_definition = found_unreliable->second; + if (its_definition->get_address() == _unreliable_address + && its_definition->get_port() == _unreliable_port) { + is_unreliable_known = true; + } else { + VSOMEIP_WARNING << "Unreliable service endpoint has changed!"; + } + } + } } + } - remote_services_[_service][_instance][client][_reliable] = its_endpoint; - service_instances_[_service][its_endpoint.get()] = _instance; + // Add endpoint(s) if necessary + bool is_added(false); + if (_reliable_port != ILLEGAL_PORT && !is_reliable_known) { + std::shared_ptr<endpoint_definition> endpoint_def + = endpoint_definition::get(_reliable_address, _reliable_port, true); + remote_service_info_[_service][_instance][true] = endpoint_def; + is_added = !is_unreliable_known; + } - if (its_endpoint->is_connected()) { - host_->on_availability(_service, _instance, true); - } + if (_unreliable_port != ILLEGAL_PORT && !is_unreliable_known) { + std::shared_ptr<endpoint_definition> endpoint_def + = endpoint_definition::get(_unreliable_address, _unreliable_port, false); + remote_service_info_[_service][_instance][false] = endpoint_def; + is_added = !is_reliable_known; } - stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); + if (is_added) { + host_->on_availability(_service, _instance, true); + stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); + } } -void routing_manager_impl::del_routing_info(service_t _service, - instance_t _instance, - bool _reliable) { - std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if (its_info) { - std::shared_ptr<endpoint> its_empty_endpoint; +void routing_manager_impl::del_routing_info(service_t _service, instance_t _instance, + bool _has_reliable, bool _has_unreliable) { - // TODO: only tell the application if the service is completely gone - host_->on_availability(_service, _instance, false); - stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, - _instance); + host_->on_availability(_service, _instance, false); + stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); - // Implicit unsubscribe - auto found_service = eventgroups_.find(_service); - if (found_service != eventgroups_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - for (auto &its_eventgroup : found_instance->second) { - its_eventgroup.second->clear_targets(); - } + // Implicit unsubscribe + auto found_service = eventgroups_.find(_service); + if (found_service != eventgroups_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + for (auto &its_eventgroup : found_instance->second) { + its_eventgroup.second->clear_targets(); } } + } - std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint( - _reliable); - if (its_endpoint) { - if (1 >= service_instances_[_service].size()) { - service_instances_.erase(_service); - } else { - service_instances_[_service].erase(its_endpoint.get()); - } + if (_has_reliable) + clear_client_endpoints(_service, _instance, true); + if (_has_unreliable) + clear_client_endpoints(_service, _instance, false); - remote_services_[_service][_instance].erase(_reliable); - auto found_endpoint = remote_services_[_service][_instance].find( - !_reliable); - if (found_endpoint == remote_services_[_service][_instance].end()) { - remote_services_[_service].erase(_instance); - } - if (1 >= remote_services_[_service].size()) { - remote_services_.erase(_service); - } - } + clear_multicast_endpoints(_service, _instance); - if (!its_info->get_endpoint(!_reliable)) { - if (its_info->get_group()) { - its_info->get_group()->remove_service(_service, _instance); - if (1 >= services_[_service].size()) { - services_.erase(_service); + if (_has_reliable) + clear_service_info(_service, _instance, true); + if (_has_unreliable) + clear_service_info(_service, _instance, false); +} + +ttl_t routing_manager_impl::update_routing_info(ttl_t _elapsed) { + ttl_t its_smallest_ttl(DEFAULT_TTL); + std::map<service_t, + std::map<instance_t, + std::pair<bool, bool> > > its_expired_offers; + + for (auto &s : services_) { + for (auto &i : s.second) { + ttl_t its_ttl = i.second->get_ttl(); + if (its_ttl < DEFAULT_TTL) { // do not touch "forever" + if (its_ttl < _elapsed || its_ttl == 0) { + i.second->set_ttl(0); + 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 + }; } else { - services_[_service].erase(_instance); + ttl_t its_new_ttl(its_ttl - _elapsed); + i.second->set_ttl(its_new_ttl); + if (its_smallest_ttl > its_new_ttl) + its_smallest_ttl = its_new_ttl; } } - } else { - its_info->set_endpoint(its_empty_endpoint, _reliable); } } -} - -void routing_manager_impl::init_routing_info() { - VSOMEIP_INFO<< "Service Discovery disabled. Using static routing information."; - for (auto i : configuration_->get_remote_services()) { - std::string its_address = configuration_->get_unicast(i.first, i.second); - uint16_t its_reliable = configuration_->get_reliable_port(i.first, - i.second); - uint16_t its_unreliable = configuration_->get_unreliable_port(i.first, - i.second); - - if (VSOMEIP_INVALID_PORT != its_reliable) { - VSOMEIP_DEBUG << "Initializing route to service [" - << std::hex << i.first << "." << i.second << "]"; - add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, - DEFAULT_TTL, - boost::asio::ip::address::from_string(its_address), - its_reliable, true); - } - if (VSOMEIP_INVALID_PORT != its_unreliable) { - add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, - DEFAULT_TTL, - boost::asio::ip::address::from_string(its_address), - its_unreliable, false); + for (auto &s : its_expired_offers) { + for (auto &i : s.second) { + del_routing_info(s.first, i.first, i.second.first, i.second.second); } } + + return its_smallest_ttl; } -void routing_manager_impl::init_event_routing_info() { - // TODO: the following should be done before(!) initializing - // the configuration object to allow the configuration to - // directly write to the target structure! - std::map<service_t, std::map<instance_t, std::set<event_t> > > its_events = - configuration_->get_events(); - for (auto i : its_events) { - for (auto j : i.second) { - for (auto k : j.second) { - std::shared_ptr<event> its_event(std::make_shared<event>(this)); - its_event->set_service(i.first); - its_event->set_instance(j.first); - its_event->set_event(k); - configuration_->set_event(its_event); // sets is_field/is_reliable - events_[i.first][j.first][k] = its_event; +void routing_manager_impl::init_routing_info() { + VSOMEIP_INFO<< "Service Discovery disabled. Using static routing information."; + for (auto i : configuration_->get_remote_services()) { + boost::asio::ip::address its_address( + boost::asio::ip::address::from_string( + configuration_->get_unicast_address(i.first, i.second))); + uint16_t its_reliable_port + = configuration_->get_reliable_port(i.first, i.second); + uint16_t its_unreliable_port + = configuration_->get_unreliable_port(i.first, i.second); + + if (its_reliable_port != ILLEGAL_PORT + || its_unreliable_port != ILLEGAL_PORT) { + + add_routing_info(i.first, i.second, + DEFAULT_MAJOR, DEFAULT_MINOR, DEFAULT_TTL, + its_address, its_reliable_port, + its_address, its_unreliable_port); + + if(its_reliable_port != ILLEGAL_PORT) { + find_or_create_remote_client(i.first, i.second, true, VSOMEIP_ROUTING_CLIENT); } - } - } - - std::map<service_t, - std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > its_eventgroups = - configuration_->get_eventgroups(); - for (auto i : its_eventgroups) { - for (auto j : i.second) { - for (auto k : j.second) { - eventgroups_[i.first][j.first][k.first] = std::make_shared< - eventgroupinfo>(); - for (auto l : k.second) { - std::shared_ptr<event> its_event = find_event(i.first, - j.first, l); - if (its_event) { - eventgroups_[i.first][j.first][k.first]->add_event( - its_event); - its_event->add_eventgroup(k.first); - } - } + if(its_unreliable_port != ILLEGAL_PORT) { + find_or_create_remote_client(i.first, i.second, false, VSOMEIP_ROUTING_CLIENT); } } } - -#if 0 - for (auto i : eventgroups_) { - for (auto j : i.second) { - for (auto k : j.second) { - VSOMEIP_DEBUG<< "Eventgroup [" << std::hex << std::setw(4) - << std::setfill('0') << i.first << "." << j.first << "." << k.first - << "]"; - for (auto l : k.second->get_events()) { - VSOMEIP_DEBUG << " Event " << std::hex << std::setw(4) - << std::setfill('0') << l->get_event(); - } - } - } - } -#endif } void routing_manager_impl::on_subscribe( @@ -1413,42 +1673,47 @@ void routing_manager_impl::on_subscribe( std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - std::shared_ptr < eventgroupinfo > its_info = find_eventgroup( - _service, _instance, _eventgroup); - client_t client = 0; - if (!its_info->is_multicast()) { + if (!its_eventgroup->is_multicast()) { if (!_target->is_reliable()) { uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance); - auto endpoint = find_or_create_server_endpoint(unreliable_port, false); - client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)->get_client(_target); _target->set_remote_port(unreliable_port); + auto endpoint = find_server_endpoint(unreliable_port, false); + if (endpoint) { + client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)-> + get_client(_target); + } } else { uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance); - auto endpoint = find_or_create_server_endpoint(reliable_port, true); - client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)->get_client(_target); + auto endpoint = find_server_endpoint(reliable_port, true); _target->set_remote_port(reliable_port); + if (endpoint) { + client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)-> + get_client(_target); + } } } if(!host_->on_subscription(_service, _instance, _eventgroup, client, true)) { VSOMEIP_INFO << "Subscription request for eventgroup " << _eventgroup - << " rejected from application handler"; + << " rejected from application handler"; return; } VSOMEIP_DEBUG << "on_subscribe: target=" << _target->get_address().to_string() - << ":" <<_target->get_port() << ":Client=" << std::hex << client; + << ":" << std::dec <<_target->get_port() << ":Client=" << std::hex + << client << (_target->is_reliable() ? " reliable" : " unreliable"); - send_subscribe(client, _service, _instance, _eventgroup, 0, 0); + send_subscribe(client, _service, _instance, _eventgroup, its_eventgroup->get_major()); remote_subscriber_map_[client] = _target; - its_eventgroup->add_target(_target); // unicast or multicast - for (auto its_event : its_eventgroup->get_events()) { - if (its_event->is_field()) { - its_event->notify_one(_subscriber); // unicast + if (its_eventgroup->add_target(_target)) { // unicast or multicast + for (auto its_event : its_eventgroup->get_events()) { + if (its_event->is_field()) { + its_event->notify_one(_subscriber); // unicast + } } } } else { @@ -1462,28 +1727,30 @@ void routing_manager_impl::on_unsubscribe(service_t _service, std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - std::shared_ptr < eventgroupinfo > its_info = find_eventgroup( - _service, _instance, _eventgroup); - client_t client = 0; - if (!its_info->is_multicast()) { + if (!its_eventgroup->is_multicast()) { if (!_target->is_reliable()) { - uint16_t unreliable_port = _target->get_remote_port(); - auto endpoint = find_or_create_server_endpoint(unreliable_port, false); - client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)-> - get_client(_target); + 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(_target); + } } else { - uint16_t reliable_port = _target->get_remote_port(); - auto endpoint = find_or_create_server_endpoint(reliable_port, true); - client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)-> - get_client(_target); + 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(_target); + } } } VSOMEIP_DEBUG << "on_unsubscribe: target=" << _target->get_address().to_string() - << ":" <<_target->get_port() << ":Client=" << std::hex << client; + << ":" << std::dec <<_target->get_port() << ":Client=" << std::hex + << client << (_target->is_reliable() ? " reliable" : " unreliable");; - its_eventgroup->del_target(_target); + its_eventgroup->remove_target(_target); if (remote_subscriber_map_.find(client) != remote_subscriber_map_.end()) { remote_subscriber_map_.erase(client); @@ -1498,11 +1765,31 @@ void routing_manager_impl::on_unsubscribe(service_t _service, void routing_manager_impl::on_subscribe_ack(service_t _service, instance_t _instance, const boost::asio::ip::address &_address, uint16_t _port) { - // TODO: find a way of getting rid of the following endpoint in - // case it is used for multicast exclusively and the subscription - // is withdrawn or the service got lost - std::shared_ptr<endpoint> its_endpoint = find_or_create_server_endpoint( - _port, false); + + if (multicast_info.find(_service) != multicast_info.end()) { + if (multicast_info[_service].find(_instance) != multicast_info[_service].end()) { + auto endpoint_def = multicast_info[_service][_instance]; + if (endpoint_def->get_address() == _address && + endpoint_def->get_port() == _port) { + + // Multicast info and endpoint already created before + // This can happen when more than one client subscribe on the same instance! + return; + } + } + } + + // Save multicast info to be able to delete the endpoint + // as soon as the instance stops offering its service + std::shared_ptr<endpoint_definition> endpoint_def = + endpoint_definition::get(_address, _port, false); + multicast_info[_service][_instance] = endpoint_def; + + bool is_someip = configuration_->is_someip(_service, _instance); + + // Create multicast endpoint & join multicase group + std::shared_ptr<endpoint> its_endpoint + = find_or_create_server_endpoint(_port, false, is_someip); if (its_endpoint) { service_instances_[_service][its_endpoint.get()] = _instance; its_endpoint->join(_address.to_string()); @@ -1513,7 +1800,7 @@ void routing_manager_impl::on_subscribe_ack(service_t _service, void routing_manager_impl::send_subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) { + major_version_t _major) { byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE @@ -1531,8 +1818,6 @@ void routing_manager_impl::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], &_ttl, - sizeof(_ttl)); std::shared_ptr<vsomeip::endpoint> target = find_local(_service, _instance); if (target) { @@ -1565,5 +1850,326 @@ void routing_manager_impl::send_unsubscribe(client_t _client, service_t _service } } +bool routing_manager_impl::insert_subscription( + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + client_t _client) { + + auto found_service = eventgroup_clients_.find(_service); + if (found_service != eventgroup_clients_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + if (found_eventgroup->second.find(_client) + != found_eventgroup->second.end()) + return false; + } + } + } + + eventgroup_clients_[_service][_instance][_eventgroup].insert(_client); + return true; +} + + +bool routing_manager_impl::deliver_specific_endpoint_message(service_t _service, + instance_t _instance, const byte_t *_data, length_t _size, endpoint *_receiver) { + // Try to deliver specific endpoint message (for selective subscribers) + auto found_servic = remote_services_.find(_service); + if (found_servic != remote_services_.end()) { + auto found_instance = found_servic->second.find(_instance); + if (found_instance != found_servic->second.end()) { + for (auto client_entry : found_instance->second) { + client_t client = client_entry.first; + if (!client) { + continue; + } + auto found_reliability = client_entry.second.find(_receiver->is_reliable()); + if (found_reliability != client_entry.second.end()) { + auto found_enpoint = found_reliability->second; + if (found_enpoint.get() == _receiver) { + auto local_endpoint = find_local(client); + if (client != get_client()) { + send_local(local_endpoint, client, _data, _size, _instance, true, _receiver->is_reliable()); + } else { + deliver_message(_data, _size, _instance, _receiver->is_reliable()); + } + return true; + } + } + } + } + } + + return false; +} + +void routing_manager_impl::clear_client_endpoints(service_t _service, instance_t _instance, + bool _reliable) { + std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); + std::shared_ptr<endpoint> deleted_endpoint; + // Clear client endpoints for remote services (generic and specific ones) + if (remote_services_.find(_service) != remote_services_.end()) { + if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { + auto endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT][_reliable]; + if (endpoint) { + service_instances_[_service].erase(endpoint.get()); + deleted_endpoint = endpoint; + } + remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].erase(_reliable); + auto found_endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].find( + !_reliable); + if (found_endpoint == remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].end()) { + remote_services_[_service][_instance].erase(VSOMEIP_ROUTING_CLIENT); + } + } + } + for (client_t client : specific_endpoint_clients) { + if (remote_services_.find(_service) != remote_services_.end()) { + if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { + auto endpoint = remote_services_[_service][_instance][client][_reliable]; + if (endpoint) { + service_instances_[_service].erase(endpoint.get()); + endpoint->stop(); + } + remote_services_[_service][_instance][client].erase(_reliable); + auto found_endpoint = remote_services_[_service][_instance][client].find(!_reliable); + if (found_endpoint == remote_services_[_service][_instance][client].end()) { + remote_services_[_service][_instance].erase(client); + } + } + } + } + if (remote_services_.find(_service) != remote_services_.end()) { + if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { + if (!remote_services_[_service][_instance].size()) { + remote_services_[_service].erase(_instance); + if (0 >= remote_services_[_service].size()) { + remote_services_.erase(_service); + } + } + } + } + // Clear remote_service_info_ + if (remote_service_info_.find(_service) != remote_service_info_.end()) { + if (remote_service_info_[_service].find(_instance) != remote_service_info_[_service].end()) { + remote_service_info_[_service][_instance].erase(_reliable); + auto found_endpoint_def = remote_service_info_[_service][_instance].find(!_reliable); + if (found_endpoint_def == remote_service_info_[_service][_instance].end()) { + remote_service_info_[_service].erase(_instance); + if (0 >= remote_service_info_[_service].size()) { + remote_service_info_.erase(_service); + } + } + } + } + + if (1 >= service_instances_[_service].size()) { + service_instances_.erase(_service); + } + if(deleted_endpoint) { + stop_and_delete_client_endpoint(deleted_endpoint); + } +} + +void routing_manager_impl::stop_and_delete_client_endpoint( + std::shared_ptr<endpoint> _endpoint) { + // Only stop and delete the endpoint if none of the services + // reachable through it is online anymore. + bool delete_endpoint(true); + + for (const auto& service : remote_services_) { + for (const auto& instance : service.second) { + const auto& client = instance.second.find(VSOMEIP_ROUTING_CLIENT); + if(client != instance.second.end()) { + for (const auto& reliable : client->second) { + if(reliable.second == _endpoint) { + delete_endpoint = false; + break; + } + } + } + if(!delete_endpoint) { break; } + } + if(!delete_endpoint) { break; } + } + + if(delete_endpoint) { + _endpoint->stop(); + for (auto address = client_endpoints_by_ip_.begin(); + address != client_endpoints_by_ip_.end();) { + for (auto port = address->second.begin(); + port != address->second.end();) { + for (auto reliable = port->second.begin(); + reliable != port->second.end();) { + std::shared_ptr<endpoint> its_endpoint = reliable->second; + if (_endpoint == its_endpoint) { + reliable = port->second.erase(reliable); + } else { + ++reliable; + } + } + if (!port->second.size()) { + port = address->second.erase(port); + } else { + ++port; + } + } + if(!address->second.size()) { + address = client_endpoints_by_ip_.erase(address); + } else { + ++address; + } + } + } +} + +void routing_manager_impl::clear_multicast_endpoints(service_t _service, instance_t _instance) { + std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); + // Clear multicast info and endpoint and multicast instance (remote service) + if (multicast_info.find(_service) != multicast_info.end()) { + if (multicast_info[_service].find(_instance) != multicast_info[_service].end()) { + std::string address = multicast_info[_service][_instance]->get_address().to_string(); + uint16_t port = multicast_info[_service][_instance]->get_port(); + auto multicast_endpoint = server_endpoints_[port][false]; + multicast_endpoint->leave(address); + multicast_endpoint->stop(); + server_endpoints_[port].erase(false); + if (server_endpoints_[port].find(true) == server_endpoints_[port].end()) { + server_endpoints_.erase(port); + } + multicast_info[_service].erase(_instance); + if (0 >= multicast_info[_service].size()) { + multicast_info.erase(_service); + } + // Clear service_instances_ for multicase endpoint + if (1 >= service_instances_[_service].size()) { + service_instances_.erase(_service); + } else { + service_instances_[_service].erase(multicast_endpoint.get()); + } + } + } +} + +void routing_manager_impl::clear_service_info(service_t _service, instance_t _instance, + bool _reliable) { + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (!its_info) { + return; + } + // Clear service_info and service_group + std::shared_ptr<endpoint> its_empty_endpoint; + if (!its_info->get_endpoint(!_reliable)) { + if (1 >= services_[_service].size()) { + services_.erase(_service); + } else { + services_[_service].erase(_instance); + } + } else { + its_info->set_endpoint(its_empty_endpoint, _reliable); + } +} + +return_code_e routing_manager_impl::check_error(const byte_t *_data, length_t _size, + instance_t _instance) { + + service_t its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], + _data[VSOMEIP_SERVICE_POS_MAX]); + + if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + if (_size >= VSOMEIP_PAYLOAD_POS) { + if (_data[VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) { + VSOMEIP_WARNING << "Received a message with unsupported protocol version for service 0x" + << std::hex << its_service; + return return_code_e::E_WRONG_PROTOCOL_VERSION; + } + if (_instance == 0xFFFF) { + VSOMEIP_WARNING << "Receiving endpoint is not configured for service 0x" + << 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; + } + 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! + return return_code_e::E_NOT_OK; + } + } else { + // Message shorter than vSomeIP message header + return return_code_e::E_MALFORMED_MESSAGE; + } + } + return return_code_e::E_OK; +} + +void routing_manager_impl::send_error(return_code_e _return_code, + const byte_t *_data, length_t _size, + instance_t _instance, bool _reliable, + endpoint *_receiver) { + + client_t its_client = 0; + service_t its_service = 0; + method_t its_method = 0; + session_t its_session = 0; + + if (_size >= VSOMEIP_CLIENT_POS_MAX) { + its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN], + _data[VSOMEIP_CLIENT_POS_MAX]); + } + if (_size >= VSOMEIP_SERVICE_POS_MAX) { + its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + } + if (_size >= VSOMEIP_METHOD_POS_MAX) { + its_method = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); + } + if (_size >= VSOMEIP_SESSION_POS_MAX) { + its_session = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SESSION_POS_MIN], + _data[VSOMEIP_SESSION_POS_MAX]); + } + + auto error_message = runtime::get()->create_message(_reliable); + error_message->set_client(its_client); + error_message->set_instance(_instance); + error_message->set_interface_version(0); + error_message->set_message_type(message_type_e::MT_ERROR); + error_message->set_method(its_method); + error_message->set_return_code(_return_code); + error_message->set_service(its_service); + error_message->set_session(its_session); + + std::lock_guard<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(error_message.get())) { + if (_receiver) { + boost::asio::ip::address adr; + uint16_t port; + if (_receiver->is_reliable()) { + auto remote = static_cast<tcp_server_endpoint_impl*>(_receiver)->get_remote(); + adr = remote.address(); + port = remote.port(); + } else { + auto remote = static_cast<udp_server_endpoint_impl*>(_receiver)->get_remote(); + adr = remote.address(); + port = remote.port(); + } + 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()); + } else { + send(get_client(), serializer_->get_data(), serializer_->get_size(), + _instance, true, _reliable); + } + serializer_->reset(); + } else { + VSOMEIP_ERROR << "Failed to serialize error message."; + } +} + } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp index 1df8b90..cbf14ff 100644 --- a/implementation/routing/src/routing_manager_proxy.cpp +++ b/implementation/routing/src/routing_manager_proxy.cpp @@ -6,17 +6,17 @@ #include <iomanip> #include <mutex> -#include <vsomeip/configuration.hpp> #include <vsomeip/constants.hpp> -#include <vsomeip/logger.hpp> #include <vsomeip/runtime.hpp> #include "../include/event.hpp" #include "../include/routing_manager_host.hpp" #include "../include/routing_manager_proxy.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/local_client_endpoint_impl.hpp" #include "../../endpoints/include/local_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/deserializer.hpp" #include "../../message/include/serializer.hpp" #include "../../service_discovery/include/runtime.hpp" @@ -26,10 +26,17 @@ namespace vsomeip { routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host) : - io_(_host->get_io()), host_(_host), client_(_host->get_client()), sender_( - 0), receiver_(0), serializer_(std::make_shared<serializer>()), deserializer_( - std::make_shared<deserializer>()), is_connected_(false), is_started_(false), - state_(event_type_e::ET_DEREGISTERED) { + io_(_host->get_io()), + is_connected_(false), + is_started_(false), + state_(state_type_e::ST_DEREGISTERED), + host_(_host), + client_(_host->get_client()), + configuration_(host_->get_configuration()), + serializer_(std::make_shared<serializer>()), + deserializer_(std::make_shared<deserializer>()), + sender_(0), + receiver_(0) { } routing_manager_proxy::~routing_manager_proxy() { @@ -44,13 +51,7 @@ client_t routing_manager_proxy::get_client() const { } void routing_manager_proxy::init() { - uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; - if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; - - serializer_->create_data(its_max_message_size); + serializer_->create_data(configuration_->get_max_message_size_local()); std::stringstream its_sender_path; sender_ = create_local(VSOMEIP_ROUTING_CLIENT); @@ -59,7 +60,7 @@ void routing_manager_proxy::init() { its_client << VSOMEIP_BASE_PATH << std::hex << client_; #ifdef WIN32 ::_unlink(its_client.str().c_str()); - int port = 51235 + client_; + int port = VSOMEIP_INTERNAL_BASE_PORT + client_; #else ::unlink(its_client.str().c_str()); #endif @@ -69,7 +70,7 @@ void routing_manager_proxy::init() { #else boost::asio::local::stream_protocol::endpoint(its_client.str()), #endif - io_); + io_, configuration_->get_max_message_size_local()); #ifdef WIN32 VSOMEIP_DEBUG << "Listening at " << port; @@ -110,13 +111,12 @@ 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, - ttl_t _ttl) { + instance_t _instance, major_version_t _major, minor_version_t _minor) { if (is_connected_) { - send_offer_service(_client, _service, _instance, _major, _minor, _ttl); + send_offer_service(_client, _service, _instance, _major, _minor); } else { - service_data_t offer = { _service, _instance, _major, _minor, _ttl }; + service_data_t offer = { _service, _instance, _major, _minor, false }; std::lock_guard<std::mutex> its_lock(pending_mutex_); pending_offers_.insert(offer); } @@ -124,7 +124,8 @@ void routing_manager_proxy::offer_service(client_t _client, service_t _service, void routing_manager_proxy::send_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { + minor_version_t _minor) { + (void)_client; byte_t its_command[VSOMEIP_OFFER_SERVICE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_OFFER_SERVICE_COMMAND_SIZE @@ -142,14 +143,13 @@ void routing_manager_proxy::send_offer_service(client_t _client, its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, sizeof(_minor)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_ttl, - sizeof(_ttl)); sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::stop_offer_service(client_t _client, service_t _service, instance_t _instance) { + (void)_client; if (is_connected_) { byte_t its_command[VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE]; @@ -184,31 +184,109 @@ void routing_manager_proxy::stop_offer_service(client_t _client, void routing_manager_proxy::request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective) { - - is_selective_ = _has_selective; - send_request_service(_client, _service, _instance, _major, _minor, _ttl, _has_selective); + minor_version_t _minor, bool _use_exclusive_proxy) { + send_request_service(_client, _service, _instance, _major, _minor, + _use_exclusive_proxy); } void routing_manager_proxy::release_service(client_t _client, service_t _service, instance_t _instance) { + (void)_client; + (void)_service; + (void)_instance; +} + +void routing_manager_proxy::register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, std::set<eventgroup_t> _eventgroups, + bool _is_field, bool _is_provided) { + (void)_client; + + if (_is_field) + fields_[_service][_instance].insert(_event); + + send_register_event(client_, _service, _instance, + _event, _eventgroups, _is_field, _is_provided); +} + +void routing_manager_proxy::unregister_event(client_t _client, + service_t _service, instance_t _instance, event_t _event, + bool _is_provided) { + (void)_client; + auto find_service = fields_.find(_service); + if (find_service != fields_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) { + find_instance->second.erase(_event); + if (find_instance->second.size() == 0) + find_service->second.erase(find_instance); + } + if (find_service->second.size() == 0) + fields_.erase(find_service); + } + + if (is_connected_) { + 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 + 5] + = static_cast<byte_t>(_is_provided); + + sender_->send(its_command, sizeof(its_command)); + } else { + std::lock_guard<std::mutex> its_lock(pending_mutex_); + auto it = pending_event_registrations_.begin(); + while (it != pending_event_registrations_.end()) { + if (it->service_ == _service + && it->instance_ == _instance + && it->event_ == _event) { + break; + } + it++; + } + + if (it != pending_event_registrations_.end()) + pending_event_registrations_.erase(it); + } +} +bool routing_manager_proxy::is_field(service_t _service, instance_t _instance, + event_t _event) const { + auto find_service = fields_.find(_service); + if (find_service != fields_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) + return (find_instance->second.find(_event) != find_instance->second.end()); + } + return false; } void routing_manager_proxy::subscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, - ttl_t _ttl) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { if (is_connected_) { - send_subscribe(_client, _service, _instance, _eventgroup, _major, _ttl); + send_subscribe(_client, _service, _instance, _eventgroup, _major); } else { - eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major, _ttl }; + eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major }; 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, - ttl_t _ttl) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { + (void)_client; + byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE; @@ -225,14 +303,13 @@ 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], &_ttl, - sizeof(_ttl)); sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) { + (void)_client; if (is_connected_) { byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE]; @@ -278,6 +355,8 @@ bool routing_manager_proxy::send(client_t its_client, serializer_->get_size(), _message->get_instance(), _flush, _message->is_reliable()); serializer_->reset(); + } else { + VSOMEIP_ERROR << "Failed to serialize message. Check message size!"; } return (is_sent); } @@ -311,7 +390,10 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, std::vector<byte_t> its_command( VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t) + sizeof(bool) + sizeof(bool)); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND; + its_command[VSOMEIP_COMMAND_TYPE_POS] + = utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) ? + VSOMEIP_NOTIFY : VSOMEIP_SEND; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client, sizeof(client_t)); std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size, @@ -323,16 +405,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, _flush; its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t) + sizeof(bool)] = _reliable; - -#if 0 - std::stringstream msg; - msg << "rmp:send: "; - for (int i = 0; i < its_command.size(); i++) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif - - is_sent = its_target->send(&its_command[0], its_command.size()); + is_sent = its_target->send(&its_command[0], uint32_t(its_command.size())); } return (is_sent); } @@ -340,27 +413,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) { + (void)_target; + (void)_message; return (false); } bool routing_manager_proxy::send_to( const std::shared_ptr<endpoint_definition> &_target, const byte_t *_data, uint32_t _size) { + (void)_target; + (void)_data; + (void)_size; return (false); } void routing_manager_proxy::notify( service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload) { - std::shared_ptr<message> its_notification = runtime::get()->create_request(); - its_notification->set_message_type(message_type_e::MT_REQUEST_NO_RETURN); + std::shared_ptr<message> its_notification + = runtime::get()->create_notification(); its_notification->set_service(_service); its_notification->set_instance(_instance); its_notification->set_method(_event); its_notification->set_payload(_payload); if (is_connected_) { send(VSOMEIP_ROUTING_CLIENT, its_notification, true); - } else { + } else if (is_field(_service, _instance, _event)) { std::lock_guard<std::mutex> its_lock(pending_mutex_); pending_notifications_[_service][_instance][_event] = its_notification; } @@ -369,7 +447,8 @@ void routing_manager_proxy::notify( void routing_manager_proxy::notify_one(service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload, client_t _client) { - std::shared_ptr<message> its_notification = runtime::get()->create_notification(); + std::shared_ptr<message> its_notification + = runtime::get()->create_notification(); its_notification->set_service(_service); its_notification->set_instance(_instance); its_notification->set_method(_event); @@ -388,12 +467,24 @@ void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) { void routing_manager_proxy::on_disconnect(std::shared_ptr<endpoint> _endpoint) { is_connected_ = !(_endpoint == sender_); if (!is_connected_) { - host_->on_event(event_type_e::ET_DEREGISTERED); + host_->on_state(state_type_e::ST_DEREGISTERED); } } +void routing_manager_proxy::on_error(const byte_t *_data, length_t _length, + endpoint *_receiver) { + + // Implement me when needed + + (void)(_data); + (void)(_length); + (void)(_receiver); +} + + void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, endpoint *_receiver) { + (void)_receiver; #if 0 std::stringstream msg; msg << "rmp::on_message: "; @@ -407,9 +498,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, service_t its_service; instance_t its_instance; eventgroup_t its_eventgroup; - //event_t its_event; major_version_t its_major; - minor_version_t its_minor; ttl_t its_ttl; if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) { @@ -425,15 +514,19 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, std::memcpy(&its_instance, &_data[_size - sizeof(instance_t) - sizeof(bool) - sizeof(bool)], sizeof(instance_t)); + bool its_reliable; + std::memcpy(&its_reliable, &_data[_size - sizeof(bool)], + sizeof(its_reliable)); deserializer_->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length); std::shared_ptr<message> its_message( deserializer_->deserialize_message()); if (its_message) { its_message->set_instance(its_instance); + its_message->set_reliable(its_reliable); host_->on_message(its_message); } else { - // TODO: send_error(return_code_e::E_MALFORMED_MESSAGE); + VSOMEIP_ERROR << "Deserialization of vSomeIP message failed"; } deserializer_->reset(); } @@ -487,62 +580,64 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; VSOMEIP_DEBUG << msg.str(); #endif - event_type_e its_state(event_type_e::ET_DEREGISTERED); - - std::map<service_t, - std::map<instance_t, client_t> > old_local_services = local_services_; - local_services_.clear(); - - uint32_t i = 0; - while (i + sizeof(uint32_t) <= _size) { - uint32_t its_client_size; - std::memcpy(&its_client_size, &_data[i], sizeof(uint32_t)); - i += sizeof(uint32_t); - - if (i + sizeof(client_t) <= _size) { - client_t its_client; - std::memcpy(&its_client, &_data[i], sizeof(client_t)); - i += sizeof(client_t); - - if (its_client != client_) { - (void) find_or_create_local(its_client); - } else { - its_state = event_type_e::ET_REGISTERED; - } + state_type_e its_state(state_type_e::ST_DEREGISTERED); + std::map<service_t, std::map<instance_t, client_t> > old_local_services; + { + std::lock_guard<std::mutex> its_lock(local_services_mutex_); + old_local_services = local_services_; + local_services_.clear(); + + uint32_t i = 0; + while (i + sizeof(uint32_t) <= _size) { + uint32_t its_client_size; + std::memcpy(&its_client_size, &_data[i], sizeof(uint32_t)); + i += uint32_t(sizeof(uint32_t)); + + if (i + sizeof(client_t) <= _size) { + client_t its_client; + std::memcpy(&its_client, &_data[i], sizeof(client_t)); + i += uint32_t(sizeof(client_t)); + + if (its_client != client_) { + (void) find_or_create_local(its_client); + } else { + its_state = state_type_e::ST_REGISTERED; + } - uint32_t j = 0; - while (j + sizeof(uint32_t) <= its_client_size) { - uint32_t its_services_size; - std::memcpy(&its_services_size, &_data[i + j], sizeof(uint32_t)); - j += sizeof(uint32_t); + uint32_t j = 0; + while (j + sizeof(uint32_t) <= its_client_size) { + uint32_t its_services_size; + std::memcpy(&its_services_size, &_data[i + j], sizeof(uint32_t)); + j += uint32_t(sizeof(uint32_t)); - if (its_services_size >= sizeof(service_t) + sizeof(instance_t)) { - its_services_size -= sizeof(service_t); + if (its_services_size >= sizeof(service_t) + sizeof(instance_t)) { + its_services_size -= uint32_t(sizeof(service_t)); - service_t its_service; - std::memcpy(&its_service, &_data[i + j], sizeof(service_t)); - j += sizeof(service_t); + service_t its_service; + std::memcpy(&its_service, &_data[i + j], sizeof(service_t)); + j += uint32_t(sizeof(service_t)); - while (its_services_size >= sizeof(instance_t)) { - instance_t its_instance; - std::memcpy(&its_instance, &_data[i + j], sizeof(instance_t)); - j += sizeof(instance_t); + while (its_services_size >= sizeof(instance_t)) { + instance_t its_instance; + std::memcpy(&its_instance, &_data[i + j], sizeof(instance_t)); + j += uint32_t(sizeof(instance_t)); - if (its_client != client_) - local_services_[its_service][its_instance] = its_client; + if (its_client != client_) + local_services_[its_service][its_instance] = its_client; - its_services_size -= sizeof(instance_t); + its_services_size -= uint32_t(sizeof(instance_t)); + } } } - } - i += j; + i += j; + } } } // inform host about its own registration state changes if (state_ != its_state) { - host_->on_event(its_state); + host_->on_state(its_state); state_ = its_state; } @@ -595,7 +690,12 @@ void routing_manager_proxy::register_application() { for (auto &po : pending_offers_) send_offer_service(client_, po.service_, po.instance_, - po.major_, po.minor_, po.ttl_); + po.major_, po.minor_); + + for (auto &per : pending_event_registrations_) + send_register_event(client_, per.service_, per.instance_, + per.event_, per.eventgroups_, + per.is_field_, per.is_provided_); for (auto &s : pending_notifications_) { for (auto &i : s.second) { @@ -607,13 +707,13 @@ void routing_manager_proxy::register_application() { for (auto &po : pending_requests_) { send_request_service(client_, po.service_, po.instance_, - po.major_, po.minor_, po.ttl_, is_selective_); + po.major_, po.minor_, po.use_exclusive_proxy_); } 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.ttl_); + ps.eventgroup_, ps.major_); pending_offers_.clear(); pending_requests_.clear(); @@ -632,7 +732,7 @@ void routing_manager_proxy::deregister_application() { std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(its_size)); if (is_connected_) - (void)sender_->send(&its_command[0], its_command.size()); + (void)sender_->send(&its_command[0], uint32_t(its_command.size())); } std::shared_ptr<endpoint> routing_manager_proxy::find_local(client_t _client) { @@ -651,7 +751,7 @@ std::shared_ptr<endpoint> routing_manager_proxy::create_local( #ifdef WIN32 boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1"); - int port = 51234; + int port = VSOMEIP_INTERNAL_BASE_PORT + _client; VSOMEIP_DEBUG<< "Connecting to [" << std::hex << _client << "] at " << port; #else @@ -666,7 +766,7 @@ std::shared_ptr<endpoint> routing_manager_proxy::create_local( #else boost::asio::local::stream_protocol::endpoint(its_path.str()), #endif - io_); + io_, configuration_->get_max_message_size_local()); local_endpoints_[_client] = its_endpoint; @@ -693,6 +793,7 @@ void routing_manager_proxy::remove_local(client_t _client) { std::shared_ptr<endpoint> routing_manager_proxy::find_local(service_t _service, instance_t _instance) { client_t its_client(0); + std::lock_guard<std::mutex> its_lock(local_services_mutex_); auto found_service = local_services_.find(_service); if (found_service != local_services_.end()) { auto found_instance = found_service->second.find(_instance); @@ -716,35 +817,87 @@ void routing_manager_proxy::send_pong() const { void routing_manager_proxy::send_request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _is_selective) { + minor_version_t _minor, bool _use_exclusive_proxy) { + (void)_client; - byte_t its_command[VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE]; - uint32_t its_size = VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE - - VSOMEIP_COMMAND_HEADER_SIZE; + if (is_connected_) { + byte_t its_command[VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE]; + uint32_t its_size = VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE + - VSOMEIP_COMMAND_HEADER_SIZE; - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, - sizeof(_service)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, - sizeof(_instance)); - its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, - sizeof(_minor)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_ttl, - sizeof(_ttl)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 13], &_is_selective, - sizeof(_is_selective)); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, + sizeof(_service)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, + sizeof(_instance)); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, + sizeof(_minor)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_use_exclusive_proxy, + sizeof(_use_exclusive_proxy)); - if (is_connected_) { sender_->send(its_command, sizeof(its_command)); } else { - service_data_t offer = { _service, _instance, _major, _minor, _ttl }; + service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy }; + std::lock_guard<std::mutex> its_lock(pending_mutex_); + pending_requests_.insert(request); + } +} + +void routing_manager_proxy::send_register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, 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)); + byte_t *its_command = new byte_t[VSOMEIP_REGISTER_EVENT_COMMAND_SIZE + its_eventgroups_size]; + uint32_t its_size = VSOMEIP_REGISTER_EVENT_COMMAND_SIZE + + its_eventgroups_size + - VSOMEIP_COMMAND_HEADER_SIZE; + + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REGISTER_EVENT; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(_client)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, + sizeof(_service)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, + sizeof(_instance)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_event, + sizeof(_event)); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] + = static_cast<byte_t>(_is_field); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7] + = static_cast<byte_t>(_is_provided); + + std::size_t i = 8; + for (auto eg : _eventgroups) { + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + i], &eg, + sizeof(eventgroup_t)); + i += sizeof(eventgroup_t); + } + + sender_->send(its_command, + uint32_t(VSOMEIP_REGISTER_EVENT_COMMAND_SIZE + + its_eventgroups_size)); + + delete[] its_command; + } else { + event_data_t registration = { + _service, + _instance, + _event, + _is_field, + _is_provided, + _eventgroups + }; std::lock_guard<std::mutex> its_lock(pending_mutex_); - pending_requests_.insert(offer); + pending_event_registrations_.insert(registration); } } diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp index 1c3a53c..dfca76f 100644 --- a/implementation/routing/src/routing_manager_stub.cpp +++ b/implementation/routing/src/routing_manager_stub.cpp @@ -11,195 +11,217 @@ #include <boost/system/error_code.hpp> #include <vsomeip/constants.hpp> -#include <vsomeip/logger.hpp> #include <vsomeip/primitive_types.hpp> #include <vsomeip/runtime.hpp> #include "../include/routing_manager_stub.hpp" #include "../include/routing_manager_stub_host.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/local_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../utility/include/byteorder.hpp" namespace vsomeip { -routing_manager_stub::routing_manager_stub(routing_manager_stub_host *_host) : - host_(_host), io_(_host->get_io()), watchdog_timer_(_host->get_io()) { +routing_manager_stub::routing_manager_stub( + routing_manager_stub_host *_host, + std::shared_ptr<configuration> _configuration) : + host_(_host), + io_(_host->get_io()), + watchdog_timer_(_host->get_io()), + configuration_(_configuration) { } routing_manager_stub::~routing_manager_stub() { } void routing_manager_stub::init() { - std::stringstream its_endpoint_path; - its_endpoint_path << VSOMEIP_BASE_PATH << VSOMEIP_ROUTING_CLIENT; - endpoint_path_ = its_endpoint_path.str(); + 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 = 51234; - VSOMEIP_DEBUG << "Routing endpoint at " << port; + ::_unlink(endpoint_path_.c_str()); + int port = VSOMEIP_INTERNAL_BASE_PORT; + VSOMEIP_DEBUG << "Routing endpoint at " << port; #else - ::unlink(endpoint_path_.c_str()); - VSOMEIP_DEBUG << "Routing endpoint at " << endpoint_path_; + ::unlink(endpoint_path_.c_str()); + VSOMEIP_DEBUG << "Routing endpoint at " << endpoint_path_; #endif - 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_); + 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()); } void routing_manager_stub::start() { - endpoint_->start(); + endpoint_->start(); - // Start watchdog (TODO: only if configured) - start_watchdog(); + // Start watchdog (TODO: only if configured) + start_watchdog(); } void routing_manager_stub::stop() { - watchdog_timer_.cancel(); - endpoint_->stop(); + watchdog_timer_.cancel(); + endpoint_->stop(); #ifdef WIN32 - ::_unlink(endpoint_path_.c_str()); + ::_unlink(endpoint_path_.c_str()); #else - ::unlink(endpoint_path_.c_str()); + ::unlink(endpoint_path_.c_str()); #endif } void routing_manager_stub::on_connect(std::shared_ptr<endpoint> _endpoint) { - + (void)_endpoint; } void routing_manager_stub::on_disconnect(std::shared_ptr<endpoint> _endpoint) { + (void)_endpoint; +} + +void routing_manager_stub::on_error(const byte_t *_data, length_t _length, + endpoint *_receiver) { + + // Implement me when needed + (void)(_data); + (void)(_length); + (void)(_receiver); } void routing_manager_stub::on_message(const byte_t *_data, length_t _size, - endpoint *_receiver) { + endpoint *_receiver) { + (void)_receiver; #if 0 - std::stringstream msg; - msg << "rms::on_message: "; - for (int i = 0; i < _size; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + std::stringstream msg; + msg << "rms::on_message: "; + for (length_t i = 0; i < _size; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + VSOMEIP_DEBUG << msg.str(); #endif - if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) { - byte_t its_command; - client_t its_client; - //session_t its_session; - std::string its_client_endpoint; - service_t its_service; - instance_t its_instance; - eventgroup_t its_eventgroup; - //event_t its_event; - major_version_t its_major; - minor_version_t its_minor; - ttl_t its_ttl; - std::shared_ptr<payload> its_payload; - const byte_t *its_data; - uint32_t its_size; - bool its_reliable(false); - bool its_flush(true); - - its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; - std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], - sizeof(its_client)); - - std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN], - sizeof(its_size)); - - if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) { - switch (its_command) { - case VSOMEIP_REGISTER_APPLICATION: - on_register_application(its_client); - VSOMEIP_DEBUG << "Application/Client " - << std::hex << std::setw(4) << std::setfill('0') - << its_client << " got registered!"; - break; - - case VSOMEIP_DEREGISTER_APPLICATION: - on_deregister_application(its_client); - VSOMEIP_DEBUG << "Application/Client " - << std::hex << std::setw(4) << std::setfill('0') - << its_client << " got deregistered!"; - break; - - case VSOMEIP_PONG: - on_pong(its_client); - break; - - case VSOMEIP_OFFER_SERVICE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, - &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_major)); - std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], - sizeof(its_minor)); - std::memcpy(&its_ttl, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9], - sizeof(its_ttl)); - host_->offer_service(its_client, its_service, its_instance, - its_major, its_minor, its_ttl); - on_offer_service(its_client, its_service, its_instance); - break; - - case VSOMEIP_STOP_OFFER_SERVICE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, - &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - host_->stop_offer_service(its_client, its_service, its_instance); - on_stop_offer_service(its_client, its_service, its_instance); - break; - - case VSOMEIP_SUBSCRIBE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_eventgroup)); - std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], - sizeof(its_major)); - std::memcpy(&its_ttl, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], - sizeof(its_ttl)); - - host_->subscribe(its_client, its_service, - its_instance, its_eventgroup, its_major, its_ttl); - break; - - case VSOMEIP_UNSUBSCRIBE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_eventgroup)); - host_->unsubscribe(its_client, its_service, - its_instance, its_eventgroup); - break; - - case VSOMEIP_SEND: - 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 - 4], sizeof(its_instance)); - std::memcpy(&its_reliable, &_data[_size - 1], sizeof(its_reliable)); - host_->on_message(its_service, its_instance, its_data, its_size, its_reliable); - break; - - case VSOMEIP_REQUEST_SERVICE: - bool its_selective; + if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) { + byte_t its_command; + client_t its_client; + std::string its_client_endpoint; + service_t its_service; + instance_t its_instance; + eventgroup_t its_eventgroup; + std::set<eventgroup_t> its_eventgroups; + event_t its_event; + bool is_field(false); + bool is_provided(false); + major_version_t its_major; + minor_version_t its_minor; + std::shared_ptr<payload> its_payload; + const byte_t *its_data; + uint32_t its_size; + bool its_reliable(false); + bool use_exclusive_proxy(false); + + its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; + std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], + sizeof(its_client)); + + std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN], + sizeof(its_size)); + + if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) { + switch (its_command) { + case VSOMEIP_REGISTER_APPLICATION: + on_register_application(its_client); + VSOMEIP_DEBUG << "Application/Client " + << std::hex << std::setw(4) << std::setfill('0') + << its_client << " got registered!"; + break; + + case VSOMEIP_DEREGISTER_APPLICATION: + on_deregister_application(its_client); + VSOMEIP_DEBUG << "Application/Client " + << std::hex << std::setw(4) << std::setfill('0') + << its_client << " got deregistered!"; + break; + + case VSOMEIP_PONG: + on_pong(its_client); + break; + + case VSOMEIP_OFFER_SERVICE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_major)); + std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], + sizeof(its_minor)); + host_->offer_service(its_client, its_service, its_instance, + its_major, its_minor); + on_offer_service(its_client, its_service, its_instance); + break; + + case VSOMEIP_STOP_OFFER_SERVICE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + host_->stop_offer_service(its_client, its_service, its_instance); + on_stop_offer_service(its_client, its_service, its_instance); + break; + + case VSOMEIP_SUBSCRIBE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_eventgroup)); + std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], + sizeof(its_major)); + + host_->subscribe(its_client, its_service, + its_instance, its_eventgroup, its_major); + break; + + case VSOMEIP_UNSUBSCRIBE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_eventgroup)); + host_->unsubscribe(its_client, its_service, + its_instance, its_eventgroup); + break; + + case VSOMEIP_SEND: + 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 - 4], sizeof(its_instance)); + std::memcpy(&its_reliable, &_data[_size - 1], sizeof(its_reliable)); + host_->on_message(its_service, its_instance, its_data, its_size, its_reliable); + break; + + case VSOMEIP_NOTIFY: + 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 - 4], sizeof(its_instance)); + host_->on_notification(its_client, its_service, its_instance, its_data, its_size); + break; + + case VSOMEIP_REQUEST_SERVICE: std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(its_service)); std::memcpy(&its_instance, @@ -209,238 +231,286 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_major)); std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], sizeof(its_minor)); - std::memcpy(&its_ttl, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9], - sizeof(its_ttl)); - std::memcpy(&its_selective, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 13], - sizeof(its_selective)); - host_->request_service(its_client, its_service, its_instance, - its_major, its_minor, its_ttl, its_selective); - break; - } - } - } + 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); + break; + + + case VSOMEIP_RELEASE_SERVICE: + break; + + case VSOMEIP_REGISTER_EVENT: + std::memcpy(&its_service, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_event, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_event)); + std::memcpy(&is_field, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], + sizeof(is_field)); + std::memcpy(&is_provided, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], + sizeof(is_provided)); + for (std::size_t i = 8; i+1 < its_size; i++) { + std::memcpy(&its_eventgroup, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + i], + sizeof(its_eventgroup)); + its_eventgroups.insert(its_eventgroup); + } + host_->register_event(its_client, its_service, + its_instance, its_event, its_eventgroups, + is_field, is_provided); + break; + + case VSOMEIP_UNREGISTER_EVENT: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_event)); + std::memcpy(&is_provided, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], + sizeof(is_provided)); + host_->unregister_event(its_client, its_service, its_instance, + its_event, is_provided); + break; + } + } + } } void routing_manager_stub::on_register_application(client_t _client) { - std::lock_guard<std::mutex> its_guard(routing_info_mutex_); - (void)host_->find_or_create_local(_client); - routing_info_[_client].first = 0; - broadcast_routing_info(); + std::lock_guard<std::mutex> its_guard(routing_info_mutex_); + (void)host_->find_or_create_local(_client); + routing_info_[_client].first = 0; + broadcast_routing_info(); } void routing_manager_stub::on_deregister_application(client_t _client) { - routing_info_mutex_.lock(); - auto its_info = routing_info_.find(_client); - if (its_info != routing_info_.end()) { - for (auto &its_service : its_info->second.second) { - for (auto &its_instance : its_service.second) { - routing_info_mutex_.unlock(); - host_->on_stop_offer_service(its_service.first, its_instance); - routing_info_mutex_.lock(); - } - } - } - routing_info_mutex_.unlock(); - - std::lock_guard<std::mutex> its_lock(routing_info_mutex_); - host_->remove_local(_client); - routing_info_.erase(_client); - broadcast_routing_info(); + routing_info_mutex_.lock(); + auto its_info = routing_info_.find(_client); + if (its_info != routing_info_.end()) { + for (auto &its_service : its_info->second.second) { + for (auto &its_instance : its_service.second) { + routing_info_mutex_.unlock(); + host_->on_stop_offer_service(its_service.first, its_instance); + routing_info_mutex_.lock(); + } + } + } + routing_info_mutex_.unlock(); + + std::lock_guard<std::mutex> its_lock(routing_info_mutex_); + host_->remove_local(_client); + routing_info_.erase(_client); + broadcast_routing_info(); } void routing_manager_stub::on_offer_service(client_t _client, - service_t _service, instance_t _instance) { - std::lock_guard<std::mutex> its_guard(routing_info_mutex_); - routing_info_[_client].second[_service].insert(_instance); - broadcast_routing_info(); + service_t _service, instance_t _instance) { + std::lock_guard<std::mutex> its_guard(routing_info_mutex_); + routing_info_[_client].second[_service].insert(_instance); + broadcast_routing_info(); } void routing_manager_stub::on_stop_offer_service(client_t _client, - service_t _service, instance_t _instance) { - std::lock_guard<std::mutex> its_guard(routing_info_mutex_); - auto found_client = routing_info_.find(_client); - if (found_client != routing_info_.end()) { - auto found_service = found_client->second.second.find(_service); - if (found_service != found_client->second.second.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - found_service->second.erase(_instance); - if (0 == found_service->second.size()) { - found_client->second.second.erase(_service); - } - broadcast_routing_info(); - } - } - } + service_t _service, instance_t _instance) { + std::lock_guard<std::mutex> its_guard(routing_info_mutex_); + auto found_client = routing_info_.find(_client); + if (found_client != routing_info_.end()) { + auto found_service = found_client->second.second.find(_service); + if (found_service != found_client->second.second.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + found_service->second.erase(_instance); + if (0 == found_service->second.size()) { + found_client->second.second.erase(_service); + } + broadcast_routing_info(); + } + } + } } void routing_manager_stub::send_routing_info(client_t _client) { - std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client); - if (its_endpoint) { - uint32_t its_capacity = 4096; // TODO: dynamic resizing - std::vector<byte_t> its_command(its_capacity); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ROUTING_INFO; - std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, - sizeof(client_t)); - uint32_t its_size = VSOMEIP_COMMAND_PAYLOAD_POS; - - for (auto &info : routing_info_) { - uint32_t its_size_pos = its_size; - uint32_t its_entry_size = its_size; - - its_size += sizeof(uint32_t); // placeholder - - if (info.first != host_->get_client()) { - std::memcpy(&its_command[its_size], &info.first, sizeof(client_t)); - } else { - std::memset(&its_command[its_size], 0x0, sizeof(client_t)); - } - - its_size += sizeof(client_t); - - for (auto &service : info.second.second) { - uint32_t its_service_entry_size = sizeof(service_t) - + service.second.size() * sizeof(instance_t); - - std::memcpy(&its_command[its_size], &its_service_entry_size, - sizeof(uint32_t)); - its_size += sizeof(uint32_t); - - std::memcpy(&its_command[its_size], &service.first, - sizeof(service_t)); - its_size += sizeof(service_t); - - for (auto &instance : service.second) { - std::memcpy(&its_command[its_size], &instance, - sizeof(instance_t)); - its_size += sizeof(instance_t); - } - } - - its_entry_size = its_size - its_entry_size - sizeof(uint32_t); - std::memcpy(&its_command[its_size_pos], &its_entry_size, - sizeof(uint32_t)); - } - - its_size -= VSOMEIP_COMMAND_PAYLOAD_POS; - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - its_size += VSOMEIP_COMMAND_PAYLOAD_POS; + std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client); + if (its_endpoint) { + uint32_t its_capacity = 4096; // TODO: dynamic resizing + std::vector<byte_t> its_command(its_capacity); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ROUTING_INFO; + std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, + sizeof(client_t)); + uint32_t its_size = VSOMEIP_COMMAND_PAYLOAD_POS; + + for (auto &info : routing_info_) { + uint32_t its_size_pos = its_size; + uint32_t its_entry_size = its_size; + + its_size += uint32_t(sizeof(uint32_t)); // placeholder + + if (info.first != host_->get_client()) { + std::memcpy(&its_command[its_size], &info.first, sizeof(client_t)); + } else { + std::memset(&its_command[its_size], 0x0, sizeof(client_t)); + } + + its_size += uint32_t(sizeof(client_t)); + + for (auto &service : info.second.second) { + uint32_t its_service_entry_size = uint32_t(sizeof(service_t) + + service.second.size() * sizeof(instance_t)); + + std::memcpy(&its_command[its_size], &its_service_entry_size, + sizeof(uint32_t)); + its_size += uint32_t(sizeof(uint32_t)); + + std::memcpy(&its_command[its_size], &service.first, + sizeof(service_t)); + its_size += uint32_t(sizeof(service_t)); + + for (auto &instance : service.second) { + std::memcpy(&its_command[its_size], &instance, + sizeof(instance_t)); + its_size += uint32_t(sizeof(instance_t)); + } + } + + its_entry_size = its_size - its_entry_size - uint32_t(sizeof(uint32_t)); + std::memcpy(&its_command[its_size_pos], &its_entry_size, + sizeof(uint32_t)); + } + + its_size -= VSOMEIP_COMMAND_PAYLOAD_POS; + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + its_size += VSOMEIP_COMMAND_PAYLOAD_POS; #if 0 - std::stringstream msg; - msg << "rms::send_routing_info "; - for (int i = 0; i < its_size; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; - VSOMEIP_DEBUG << msg.str(); + std::stringstream msg; + msg << "rms::send_routing_info "; + for (int i = 0; i < its_size; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; + VSOMEIP_DEBUG << msg.str(); #endif - its_endpoint->send(&its_command[0], its_size, true); - } + its_endpoint->send(&its_command[0], its_size, true); + } } void routing_manager_stub::broadcast_routing_info() { - for (auto& info : routing_info_) { - if (info.first != host_->get_client()) - send_routing_info(info.first); - } + for (auto& info : routing_info_) { + if (info.first != VSOMEIP_ROUTING_CLIENT) + send_routing_info(info.first); + } } void routing_manager_stub::broadcast(std::vector<byte_t> &_command) const { - std::lock_guard<std::mutex> its_guard(routing_info_mutex_); - for (auto a : routing_info_) { - if (a.first > 0) { - std::shared_ptr<endpoint> its_endpoint - = host_->find_local(a.first); - if (its_endpoint) { - its_endpoint->send(&_command[0], _command.size(), true); - } - } - } + std::lock_guard<std::mutex> its_guard(routing_info_mutex_); + for (auto a : routing_info_) { + if (a.first > 0) { + std::shared_ptr<endpoint> its_endpoint + = host_->find_local(a.first); + if (its_endpoint) { + its_endpoint->send(&_command[0], uint32_t(_command.size()), true); + } + } + } } // Watchdog void routing_manager_stub::broadcast_ping() const { - const byte_t its_ping[] = { - VSOMEIP_PING, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; + const byte_t its_ping[] = { + VSOMEIP_PING, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - std::vector<byte_t> its_command(sizeof(its_ping)); - its_command.assign(its_ping, its_ping + sizeof(its_ping)); - broadcast(its_command); + std::vector<byte_t> its_command(sizeof(its_ping)); + its_command.assign(its_ping, its_ping + sizeof(its_ping)); + broadcast(its_command); } void routing_manager_stub::on_pong(client_t _client) { - auto found_info = routing_info_.find(_client); - if (found_info != routing_info_.end()) { - found_info->second.first = 0; - } else { - VSOMEIP_ERROR << "Received PONG from unregistered application!"; - } + auto found_info = routing_info_.find(_client); + if (found_info != routing_info_.end()) { + found_info->second.first = 0; + } else { + VSOMEIP_ERROR << "Received PONG from unregistered application!"; + } } void routing_manager_stub::start_watchdog() { - watchdog_timer_.expires_from_now( - std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_CYCLE)); // TODO: use config variable + watchdog_timer_.expires_from_now( + std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_CYCLE)); // TODO: use config variable - std::function<void(boost::system::error_code const &)> its_callback = - [this](boost::system::error_code const &_error) { - if (!_error) - check_watchdog(); - }; + std::function<void(boost::system::error_code const &)> its_callback = + [this](boost::system::error_code const &_error) { + if (!_error) + check_watchdog(); + }; - watchdog_timer_.async_wait(its_callback); + watchdog_timer_.async_wait(its_callback); } void routing_manager_stub::check_watchdog() { - for (auto i = routing_info_.begin(); i != routing_info_.end(); ++i) { - i->second.first++; - } - broadcast_ping(); - - watchdog_timer_.expires_from_now( - std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT)); // TODO: use config variable - - std::function<void(boost::system::error_code const &)> its_callback = - [this](boost::system::error_code const &_error) { - std::list< client_t > lost; - { - std::lock_guard<std::mutex> its_lock(routing_info_mutex_); - for (auto i : routing_info_) { - if (i.first > 0 && i.first != host_->get_client()) { - if (i.second.first > VSOMEIP_DEFAULT_MAX_MISSING_PONGS) { // TODO: use config variable - VSOMEIP_WARNING << "Lost contact to application " << std::hex << (int)i.first; - lost.push_back(i.first); - } - } - } - - for (auto i : lost) { - routing_info_.erase(i); - } - } - if (0 < lost.size()) - send_application_lost(lost); - - start_watchdog(); - }; - - watchdog_timer_.async_wait(its_callback); + { + std::lock_guard<std::mutex> its_guard(routing_info_mutex_); + for (auto i = routing_info_.begin(); i != routing_info_.end(); ++i) { + i->second.first++; + } + } + broadcast_ping(); + + watchdog_timer_.expires_from_now( + std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT)); // TODO: use config variable + + std::function<void(boost::system::error_code const &)> its_callback = + [this](boost::system::error_code const &_error) { + (void)_error; + std::list< client_t > lost; + { + std::lock_guard<std::mutex> its_lock(routing_info_mutex_); + for (auto i : routing_info_) { + if (i.first > 0 && i.first != host_->get_client()) { + if (i.second.first > VSOMEIP_DEFAULT_MAX_MISSING_PONGS) { // TODO: use config variable + VSOMEIP_WARNING << "Lost contact to application " << std::hex << (int)i.first; + lost.push_back(i.first); + } + } + } + + for (auto i : lost) { + routing_info_.erase(i); + } + } + if (0 < lost.size()) + send_application_lost(lost); + + start_watchdog(); + }; + + watchdog_timer_.async_wait(its_callback); } void routing_manager_stub::send_application_lost(std::list<client_t> &_lost) { - uint32_t its_size = _lost.size() * sizeof(client_t); - std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_APPLICATION_LOST; - std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, sizeof(client_t)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(uint32_t)); - - uint32_t its_offset = 0; - for (auto i : _lost) { - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + its_offset], &i, - sizeof(client_t)); - its_offset += sizeof(client_t); - } - - broadcast(its_command); + uint32_t its_size = uint32_t(_lost.size() * sizeof(client_t)); + std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_APPLICATION_LOST; + std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, sizeof(client_t)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(uint32_t)); + + uint32_t its_offset = 0; + for (auto i : _lost) { + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + its_offset], &i, + sizeof(client_t)); + its_offset += uint32_t(sizeof(client_t)); + } + + broadcast(its_command); } } // namespace vsomeip diff --git a/implementation/routing/src/servicegroup.cpp b/implementation/routing/src/servicegroup.cpp deleted file mode 100644 index ce4739e..0000000 --- a/implementation/routing/src/servicegroup.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include "../include/servicegroup.hpp" -#include "../include/serviceinfo.hpp" - -namespace vsomeip { - -servicegroup::servicegroup(const std::string &_name, bool _is_local) - : name_(_name), is_local_(_is_local) { -} - -servicegroup::~servicegroup() { -} - -std::string servicegroup::get_name() const { - return name_; -} - -bool servicegroup::is_local() const { - return is_local_; -} - -bool servicegroup::add_service( - service_t _service, instance_t _instance, - std::shared_ptr< serviceinfo > _info) { - bool its_result(true); - auto find_service = services_.find(_service); - if (find_service != services_.end()) { - auto find_instance = find_service->second.find(_instance); - if (find_instance != find_service->second.end()) { - its_result = false; - } else { - find_service->second[_instance] = _info; - } - } else { - services_[_service][_instance] = _info; - } - - _info->set_group(this); - - return its_result; -} - -bool servicegroup::remove_service(service_t _service, instance_t _instance) { - bool its_result(false); - auto find_service = services_.find(_service); - if (find_service != services_.end()) { - auto find_instance = find_service->second.find(_instance); - if (find_instance != find_service->second.end()) { - find_service->second.erase(_instance); - if (0 == find_service->second.size()) { - services_.erase(_service); - } - its_result = true; - } - } - return its_result; -} - -services_t servicegroup::get_services() const { - return services_; -} - -} // namespace vsomeip - - - diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp index 60704ad..75d11dd 100644 --- a/implementation/routing/src/serviceinfo.cpp +++ b/implementation/routing/src/serviceinfo.cpp @@ -8,14 +8,15 @@ namespace vsomeip { serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor, - ttl_t _ttl) + ttl_t _ttl, bool _is_local) : group_(0), major_(_major), minor_(_minor), ttl_(_ttl), reliable_(nullptr), unreliable_(nullptr), - multicast_group_(0xFFFF) { + multicast_group_(0xFFFF), + is_local_(_is_local) { } serviceinfo::~serviceinfo() { @@ -90,5 +91,9 @@ void serviceinfo::remove_client(client_t _client) { requesters_.erase(_client); } +bool serviceinfo::is_local() const { + return is_local_; +} + } // namespace vsomeip diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp index 3b37df0..76d316e 100644 --- a/implementation/runtime/include/application_impl.hpp +++ b/implementation/runtime/include/application_impl.hpp @@ -37,30 +37,47 @@ public: VSOMEIP_EXPORT application_impl(const std::string &_name); VSOMEIP_EXPORT ~application_impl(); + VSOMEIP_EXPORT void set_configuration(const std::shared_ptr<configuration> _configuration); + VSOMEIP_EXPORT bool init(); VSOMEIP_EXPORT void start(); VSOMEIP_EXPORT void stop(); + // Provide services / events VSOMEIP_EXPORT void offer_service(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, ttl_t _ttl); + major_version_t _major, minor_version_t _minor); VSOMEIP_EXPORT void stop_offer_service(service_t _service, instance_t _instance); - // Consume services + VSOMEIP_EXPORT void offer_event(service_t _service, + instance_t _instance, event_t _event, + std::set<eventgroup_t> _eventgroups, + bool _is_field); + VSOMEIP_EXPORT void stop_offer_event(service_t _service, + instance_t _instance, event_t _event); + + // Consume services / events VSOMEIP_EXPORT void request_service(service_t _service, - instance_t _instance, bool _has_selective, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + instance_t _instance, major_version_t _major, + minor_version_t _minor, bool _use_exclusive_proxy); VSOMEIP_EXPORT void release_service(service_t _service, instance_t _instance); + VSOMEIP_EXPORT void request_event(service_t _service, + instance_t _instance, event_t _event, + std::set<eventgroup_t> _eventgroups, + bool _is_field); + VSOMEIP_EXPORT void release_event(service_t _service, + instance_t _instance, event_t _event); + VSOMEIP_EXPORT void subscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); + eventgroup_t _eventgroup, major_version_t _major); VSOMEIP_EXPORT void unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup); - VSOMEIP_EXPORT bool is_available(service_t _service, instance_t _instance); + VSOMEIP_EXPORT bool is_available(service_t _service, instance_t _instance) const; VSOMEIP_EXPORT void send(std::shared_ptr<message> _message, bool _flush); @@ -70,8 +87,8 @@ public: VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance, event_t _event, std::shared_ptr<payload> _payload, client_t _client) const; - VSOMEIP_EXPORT void register_event_handler(event_handler_t _handler); - VSOMEIP_EXPORT void unregister_event_handler(); + VSOMEIP_EXPORT void register_state_handler(state_handler_t _handler); + VSOMEIP_EXPORT void unregister_state_handler(); VSOMEIP_EXPORT void register_message_handler(service_t _service, instance_t _instance, method_t _method, message_handler_t _handler); @@ -94,10 +111,9 @@ public: VSOMEIP_EXPORT std::shared_ptr<configuration> get_configuration() const; VSOMEIP_EXPORT boost::asio::io_service & get_io(); - VSOMEIP_EXPORT void on_event(event_type_e _event); - VSOMEIP_EXPORT void on_availability(service_t _service, - instance_t _instance, - bool _is_available) const; + VSOMEIP_EXPORT void on_state(state_type_e _state); + VSOMEIP_EXPORT void on_availability(service_t _service, instance_t _instance, + bool _is_available) const; VSOMEIP_EXPORT void on_message(std::shared_ptr<message> _message); VSOMEIP_EXPORT void on_error(error_code_e _error); VSOMEIP_EXPORT bool on_subscription(service_t _service, instance_t _instance, @@ -116,24 +132,28 @@ private: } void dispatch(); + void wait_for_stop(); private: client_t client_; // unique application identifier session_t session_; + std::mutex session_mutex_; std::mutex initialize_mutex_; bool is_initialized_; std::string name_; std::shared_ptr<configuration> configuration_; + std::string file_; // configuration file + std::string folder_; // configuration folder boost::asio::io_service io_; // Proxy to or the Routing Manager itself std::shared_ptr<routing_manager> routing_; - // (Non-SOME/IP) Event handler - event_handler_t handler_; + // vsomeip state handler + state_handler_t handler_; // Method/Event (=Member) handlers std::map<service_t, @@ -169,6 +189,11 @@ private: // Workaround for destruction problem std::shared_ptr<logger> logger_; + + std::condition_variable stop_cv_; + std::mutex start_stop_mutex_; + bool stopped_; + std::thread stop_thread_; }; } // namespace vsomeip diff --git a/implementation/runtime/include/runtime_impl.hpp b/implementation/runtime/include/runtime_impl.hpp index 6240969..123272b 100644 --- a/implementation/runtime/include/runtime_impl.hpp +++ b/implementation/runtime/include/runtime_impl.hpp @@ -7,6 +7,7 @@ #define VSOMEIP_RUNTIME_IMPL_HPP #include <vsomeip/runtime.hpp> +#include <map> namespace vsomeip { @@ -17,7 +18,7 @@ public: virtual ~runtime_impl(); std::shared_ptr<application> create_application( - const std::string &_name) const; + const std::string &_name); std::shared_ptr<message> create_message(bool _reliable) const; std::shared_ptr<message> create_request(bool _reliable) const; @@ -30,6 +31,14 @@ public: uint32_t _size) const; std::shared_ptr<payload> create_payload( const std::vector<byte_t> &_data) const; + + std::shared_ptr<application> get_application( + const std::string &_name) const; + +private: + static std::shared_ptr<runtime> the_runtime_; + + std::map<std::string, std::shared_ptr<application>> applications_; }; } // namespace vsomeip diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp index 77eef78..f713e28 100644 --- a/implementation/runtime/src/application_impl.cpp +++ b/implementation/runtime/src/application_impl.cpp @@ -3,70 +3,175 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +#include <future> #include <thread> -#include <iostream> +#include <iomanip> -#include <vsomeip/configuration.hpp> +#ifndef WIN32 +#include <dlfcn.h> +#endif +#include <iostream> #include <vsomeip/defines.hpp> -#include <vsomeip/logger.hpp> #include "../include/application_impl.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/serializer.hpp" #include "../../routing/include/routing_manager_impl.hpp" #include "../../routing/include/routing_manager_proxy.hpp" #include "../../utility/include/utility.hpp" +#include "../../configuration/include/configuration_impl.hpp" namespace vsomeip { application_impl::application_impl(const std::string &_name) - : name_(_name), is_initialized_(false), routing_(0), signals_(io_, - SIGINT, SIGTERM), num_dispatchers_(0), logger_(logger::get()) { + : is_initialized_(false), name_(_name), + file_(VSOMEIP_DEFAULT_CONFIGURATION_FILE), + folder_(VSOMEIP_DEFAULT_CONFIGURATION_FOLDER), + routing_(0), + signals_(io_, SIGINT, SIGTERM), + num_dispatchers_(0), logger_(logger::get()), + stopped_(false) { } application_impl::~application_impl() { #ifdef WIN32 - // killemall - exit(0); + exit(0); // TODO: clean solution... #endif + stop_thread_.join(); } -bool application_impl::init() { - bool is_initialized(false); +void application_impl::set_configuration( + const std::shared_ptr<configuration> _configuration) { + if(_configuration) + configuration_ = std::make_shared<cfg::configuration_impl>(*(std::static_pointer_cast<cfg::configuration_impl, configuration>(_configuration))); +} +bool application_impl::init() { // Application name if (name_ == "") { const char *its_name = getenv(VSOMEIP_ENV_APPLICATION_NAME); if (nullptr != its_name) { name_ = its_name; + } + } + + // load configuration from module + std::string config_module = ""; + const char *its_config_module = getenv(VSOMEIP_ENV_CONFIGURATION_MODULE); + if(nullptr != its_config_module) { + config_module = its_config_module; + if (config_module.rfind(".so") != config_module.length() - 3) { + config_module += ".so"; + } + VSOMEIP_INFO << "Loading configuration from module \"" << config_module << "\"."; +#ifdef WIN32 + HMODULE config = LoadLibrary(config_module.c_str()); + if (config != 0) { + VSOMEIP_INFO << "\"" << config_module << "\" was loaded"; + if (!configuration_) { + VSOMEIP_ERROR << "Configuration not set."; + return false; + } } else { - VSOMEIP_ERROR<< "Missing application name. " - "Please set environment variable VSOMEIP_APPLICATION_NAME."; + VSOMEIP_ERROR << "\"" << config_module << "\" could not be loaded (" << GetLastError() << ")"; return false; } + FreeModule(config); +#else + void *config = dlopen(config_module.c_str(), RTLD_LAZY | RTLD_GLOBAL); + if(config != 0) { + VSOMEIP_INFO << "\"" << config_module << "\" was loaded"; + if(!configuration_) { + VSOMEIP_ERROR << "Configuration not set."; + return false; + } + } else { + VSOMEIP_ERROR << "\"" << config_module << "\" could not be loaded (" << dlerror() << ")"; + return false; + } + dlclose(config); +#endif + } else { + // Override with local file /folder + std::string its_local_file(VSOMEIP_LOCAL_CONFIGURATION_FILE); + if (utility::is_file(its_local_file)) { + file_ = its_local_file; + } + + std::string its_local_folder(VSOMEIP_LOCAL_CONFIGURATION_FOLDER); + if (utility::is_folder(its_local_folder)) { + folder_ = its_local_folder; + } + + // Finally, override with path from environment + const char *its_env = getenv(VSOMEIP_ENV_CONFIGURATION); + if (nullptr != its_env) { + if (utility::is_file(its_env)) { + file_ = its_env; + folder_ = ""; + } else if (utility::is_folder(its_env)) { + folder_ = its_env; + file_ = ""; + } + } } - // Set default path - std::string its_path(VSOMEIP_DEFAULT_CONFIGURATION_FILE_PATH); + std::shared_ptr<configuration> its_configuration = get_configuration(); + if (its_configuration) { + VSOMEIP_INFO << "Initializing vsomeip application \"" << name_ << "\""; - // Override with path from environment - const char *its_env_path = getenv(VSOMEIP_ENV_CONFIGURATION_FILE_PATH); - if (nullptr != its_env_path && utility::exists(its_env_path)) - its_path = its_env_path; + if (utility::is_file(file_)) + VSOMEIP_INFO << "Using configuration file: \"" << file_ << "\""; - // Override with local path - std::string its_local_path(VSOMEIP_LOCAL_CONFIGURATION_FILE_PATH); - if (utility::exists(its_local_path)) - its_path = its_local_path; + if (utility::is_folder(folder_)) + VSOMEIP_INFO << "Using configuration folder: \"" << folder_ << "\""; - configuration_.reset(configuration::get(its_path)); - VSOMEIP_INFO<< "Using configuration file: " << its_path; + bool is_routing_manager_host(false); + client_ = its_configuration->get_id(name_); + std::string its_routing_host = its_configuration->get_routing_host(); - if (configuration_) { - client_ = configuration_->get_id(name_); + if (client_ == 0 || its_routing_host == "") { +#ifndef WIN32 + if (!utility::auto_configuration_init()) { + VSOMEIP_ERROR << "Configuration incomplete and " + "Auto-configuration failed!"; + return false; + } +#else + return false; +#endif + } + // Client ID + if (client_ == 0) { +#ifndef WIN32 + client_ = utility::get_client_id(); + VSOMEIP_INFO << "No SOME/IP client identifier configured. " + << "Using auto-configured " + << std::hex << std::setfill('0') << std::setw(4) + << client_; +#else + return false; +#endif + } // Routing - if (name_ == configuration_->get_routing_host()) { + if (its_routing_host == "") { +#ifndef WIN32 + is_routing_manager_host = utility::is_routing_manager_host(); + VSOMEIP_INFO << "No routing manager configured. " + << "Using auto-configuration (" + << (is_routing_manager_host ? + "Host" : "Proxy") << ")"; +#else + return false; +#endif + } else { + is_routing_manager_host = (its_routing_host == name_); + } + + if (is_routing_manager_host) { routing_ = std::make_shared<routing_manager_impl>(this); } else { routing_ = std::make_shared<routing_manager_proxy>(this); @@ -74,19 +179,22 @@ bool application_impl::init() { routing_->init(); - num_dispatchers_ = configuration_->get_num_dispatchers(name_); + num_dispatchers_ = its_configuration->get_num_dispatchers(name_); // Smallest allowed session identifier session_ = 0x0001; - VSOMEIP_DEBUG<< "Application(" << name_ << ", " - << std::hex << client_ << ") is initialized (uses " + VSOMEIP_DEBUG<< "Application(" << (name_ != "" ? name_ : "unnamed") + << ", " << std::hex << client_ << ") is initialized (uses " << std::dec << num_dispatchers_ << " dispatcher threads)."; is_initialized_ = true; } if (is_initialized_) { + signals_.add(SIGINT); + signals_.add(SIGTERM); + // Register signal handler std::function<void(boost::system::error_code const &, int)> its_signal_handler = [this] (boost::system::error_code const &_error, int _signal) { @@ -109,35 +217,60 @@ bool application_impl::init() { } void application_impl::start() { - is_dispatching_ = true; + { + std::lock_guard<std::mutex> its_lock(start_stop_mutex_); + if(io_.stopped()) { + io_.reset(); + } else if(stop_thread_.joinable()) { + VSOMEIP_ERROR << "Trying to start an already started application."; + return; + } - for (size_t i = 0; i < num_dispatchers_; i++) - dispatchers_.push_back( - std::thread(std::bind(&application_impl::dispatch, this))); + is_dispatching_ = true; - if (routing_) - routing_->start(); + for (size_t i = 0; i < num_dispatchers_; i++) + dispatchers_.push_back( + std::thread(std::bind(&application_impl::dispatch, this))); + if(stop_thread_.joinable()) { + stop_thread_.join(); + } + stop_thread_= std::thread(&application_impl::wait_for_stop, this); + + if (routing_) + routing_->start(); + } + VSOMEIP_INFO << "Starting vsomeip application \"" << name_ << "\""; io_.run(); } void application_impl::stop() { + VSOMEIP_INFO << "Stopping vsomeip application \"" << name_ << "\""; + std::lock_guard<std::mutex> its_lock(start_stop_mutex_); is_dispatching_ = false; dispatch_condition_.notify_all(); - for (auto &t : dispatchers_) - t.join(); + for (auto &t : dispatchers_) { + if(t.get_id() == std::this_thread::get_id()) { + continue; + } + if(t.joinable()) { + t.join(); + } + } if (routing_) routing_->stop(); - - io_.stop(); +#ifndef WIN32 + utility::auto_configuration_exit(); +#endif + stopped_ = true; + stop_cv_.notify_one(); } void application_impl::offer_service(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, ttl_t _ttl) { + major_version_t _major, minor_version_t _minor) { if (routing_) - routing_->offer_service(client_, _service, _instance, _major, _minor, - _ttl); + routing_->offer_service(client_, _service, _instance, _major, _minor); } void application_impl::stop_offer_service(service_t _service, @@ -147,11 +280,10 @@ void application_impl::stop_offer_service(service_t _service, } void application_impl::request_service(service_t _service, instance_t _instance, - bool _has_selective, major_version_t _major, minor_version_t _minor, - ttl_t _ttl) { + major_version_t _major, minor_version_t _minor, bool _use_exclusive_proxy) { if (routing_) routing_->request_service(client_, _service, _instance, _major, _minor, - _ttl, _has_selective); + _use_exclusive_proxy); } void application_impl::release_service(service_t _service, @@ -161,10 +293,9 @@ void application_impl::release_service(service_t _service, } void application_impl::subscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl) { + eventgroup_t _eventgroup, major_version_t _major) { if (routing_) - routing_->subscribe(client_, _service, _instance, _eventgroup, _major, - _ttl); + routing_->subscribe(client_, _service, _instance, _eventgroup, _major); } void application_impl::unsubscribe(service_t _service, instance_t _instance, @@ -173,7 +304,8 @@ void application_impl::unsubscribe(service_t _service, instance_t _instance, routing_->unsubscribe(client_, _service, _instance, _eventgroup); } -bool application_impl::is_available(service_t _service, instance_t _instance) { +bool application_impl::is_available( + service_t _service, instance_t _instance) const { auto found_available = available_.find(_service); if (found_available == available_.end()) return false; @@ -183,6 +315,7 @@ bool application_impl::is_available(service_t _service, instance_t _instance) { } void application_impl::send(std::shared_ptr<message> _message, bool _flush) { + std::lock_guard<std::mutex> its_lock(session_mutex_); if (routing_) { // in case of requests set the request-id (client-id|session-id) bool is_request = utility::is_request(_message); @@ -214,18 +347,23 @@ void application_impl::notify_one(service_t _service, instance_t _instance, } } -void application_impl::register_event_handler(event_handler_t _handler) { +void application_impl::register_state_handler(state_handler_t _handler) { handler_ = _handler; } -void application_impl::unregister_event_handler() { +void application_impl::unregister_state_handler() { handler_ = nullptr; } void application_impl::register_availability_handler(service_t _service, instance_t _instance, availability_handler_t _handler) { - std::unique_lock<std::mutex> its_lock(availability_mutex_); - availability_[_service][_instance] = _handler; + { + std::unique_lock<std::mutex> its_lock(availability_mutex_); + availability_[_service][_instance] = _handler; + } + std::async(std::launch::async, [this, _service, _instance, _handler]() { + _handler(_service, _instance, is_available(_service, _instance)); + }); } void application_impl::unregister_availability_handler(service_t _service, @@ -302,6 +440,32 @@ void application_impl::unregister_message_handler(service_t _service, } } +void application_impl::offer_event(service_t _service, instance_t _instance, + event_t _event, std::set<eventgroup_t> _eventgroups, bool _is_field) { + if (routing_) + routing_->register_event(client_, _service, _instance, _event, + _eventgroups, _is_field, true); +} + +void application_impl::stop_offer_event(service_t _service, instance_t _instance, + event_t _event) { + if (routing_) + routing_->unregister_event(client_, _service, _instance, _event, true); +} + +void application_impl::request_event(service_t _service, instance_t _instance, + event_t _event, std::set<eventgroup_t> _eventgroups, bool _is_field) { + if (routing_) + routing_->register_event(client_, _service, _instance, _event, + _eventgroups, _is_field, false); + } + +void application_impl::release_event(service_t _service, instance_t _instance, + event_t _event) { + if (routing_) + routing_->unregister_event(client_, _service, _instance, _event, false); +} + // Interface "routing_manager_host" const std::string & application_impl::get_name() const { return name_; @@ -312,23 +476,36 @@ client_t application_impl::get_client() const { } std::shared_ptr<configuration> application_impl::get_configuration() const { - return configuration_; + if(configuration_) { + return configuration_; + } else { + std::set<std::string> its_input; + std::shared_ptr<configuration> its_configuration; + if (file_ != "") { + its_input.insert(file_); + } + if (folder_ != "") { + its_input.insert(folder_); + } + its_configuration = configuration::get(its_input); + return its_configuration; + } } boost::asio::io_service & application_impl::get_io() { return io_; } -void application_impl::on_event(event_type_e _event) { +void application_impl::on_state(state_type_e _state) { if (handler_) { if (num_dispatchers_ > 0) { std::unique_lock<std::mutex> its_lock(dispatch_mutex_); - handlers_.push_back([this, _event]() { - handler_(_event); + handlers_.push_back([this, _state]() { + handler_(_state); }); dispatch_condition_.notify_one(); } else { - handler_(_event); + handler_(_state); } } } @@ -346,6 +523,9 @@ void application_impl::on_availability(service_t _service, instance_t _instance, { std::unique_lock<std::mutex> its_lock(availability_mutex_); + if (_is_available == is_available(_service, _instance)) + return; + if (_is_available) { available_[_service].insert(_instance); } else { @@ -474,4 +654,19 @@ void application_impl::dispatch() { } } +void application_impl::wait_for_stop() { + std::unique_lock<std::mutex> its_lock(start_stop_mutex_); + while(!stopped_) { + stop_cv_.wait(its_lock); + } + stopped_ = false; + + for (auto &t : dispatchers_) { + if(t.joinable()) { + t.join(); + } + } + io_.stop(); +} + } // namespace vsomeip diff --git a/implementation/runtime/src/runtime_impl.cpp b/implementation/runtime/src/runtime_impl.cpp index 896ed15..e50ceca 100644 --- a/implementation/runtime/src/runtime_impl.cpp +++ b/implementation/runtime/src/runtime_impl.cpp @@ -12,18 +12,20 @@ namespace vsomeip { +std::shared_ptr<runtime> runtime_impl::the_runtime_ = std::make_shared<runtime_impl>(); + std::shared_ptr<runtime> runtime_impl::get() { - static std::shared_ptr<runtime> the_runtime = - std::make_shared<runtime_impl>(); - return the_runtime; + return the_runtime_; } runtime_impl::~runtime_impl() { } std::shared_ptr<application> runtime_impl::create_application( - const std::string &_name) const { - return (std::make_shared<application_impl>(_name)); + const std::string &_name) { + std::shared_ptr<application> application = std::make_shared<application_impl>(_name); + applications_[_name] = application; + return application; } std::shared_ptr<message> runtime_impl::create_message(bool _reliable) const { @@ -86,4 +88,12 @@ std::shared_ptr<payload> runtime_impl::create_payload( return (std::make_shared<payload_impl>(_data)); } +std::shared_ptr<application> runtime_impl::get_application( + const std::string &_name) const { + auto found_application = applications_.find(_name); + if(found_application != applications_.end()) + return found_application->second; + return nullptr; +} + } // namespace vsomeip diff --git a/implementation/service_discovery/include/defines.hpp b/implementation/service_discovery/include/defines.hpp index a239f54..2d23c3c 100644 --- a/implementation/service_discovery/include/defines.hpp +++ b/implementation/service_discovery/include/defines.hpp @@ -15,11 +15,18 @@ #define VSOMEIP_SD_METHOD 0x8100 #define VSOMEIP_SD_CLIENT 0x0000 -#define VSOMEIP_SD_DEFAULT_MIN_INITIAL_DELAY 0 -#define VSOMEIP_SD_DEFAULT_MAX_INITIAL_DELAY 3000 -#define VSOMEIP_SD_DEFAULT_REPETITION_BASE_DELAY 10 -#define VSOMEIP_SD_DEFAULT_REPETITION_MAX 5 -#define VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY 1000 -#define VSOMEIP_SD_DEFAULT_CYCLIC_REQUEST_DELAY 2000 + +#define VSOMEIP_SD_DEFAULT_ENABLED true +#define VSOMEIP_SD_DEFAULT_PROTOCOL "udp" +#define VSOMEIP_SD_DEFAULT_MULTICAST "224.224.224.0" +#define VSOMEIP_SD_DEFAULT_PORT 30490 + +#define VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN 0 +#define VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX 3000 +#define VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY 10 +#define VSOMEIP_SD_DEFAULT_REPETITIONS_MAX 3 +#define VSOMEIP_SD_DEFAULT_TTL 5 +#define VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY 1000 +#define VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY 2000 #endif // VSOMEIP_SD_DEFINES_HPP diff --git a/implementation/service_discovery/include/entry_impl.hpp b/implementation/service_discovery/include/entry_impl.hpp index 2da3a5f..fde425c 100755 --- a/implementation/service_discovery/include/entry_impl.hpp +++ b/implementation/service_discovery/include/entry_impl.hpp @@ -10,12 +10,12 @@ #include <vector>
#include <vsomeip/primitive_types.hpp>
-#include <vsomeip/serializable.hpp>
+#include <vsomeip/internal/serializable.hpp>
#include "enumeration_types.hpp"
#include "message_element_impl.hpp"
-#define VSOMEIP_MAX_OPTION_RUN 2
+#define VSOMEIP_MAX_OPTION_RUN 2
namespace vsomeip {
@@ -57,6 +57,8 @@ public: virtual bool serialize(vsomeip::serializer *_to) const;
virtual bool deserialize(vsomeip::deserializer *_from);
+ uint8_t get_num_options(uint8_t _run) const;
+
protected:
entry_type_e type_;
service_t service_;
@@ -66,6 +68,8 @@ protected: std::vector<uint8_t> options_[VSOMEIP_MAX_OPTION_RUN];
+ uint8_t num_options_[VSOMEIP_MAX_OPTION_RUN];
+
entry_impl();
entry_impl(const entry_impl &entry_);
};
diff --git a/implementation/service_discovery/include/enumeration_types.hpp b/implementation/service_discovery/include/enumeration_types.hpp index 8584bca..016fdae 100644 --- a/implementation/service_discovery/include/enumeration_types.hpp +++ b/implementation/service_discovery/include/enumeration_types.hpp @@ -39,6 +39,13 @@ enum class entry_type_e UNKNOWN = 0xFF }; +enum class layer_four_protocol_e + : uint8_t { + TCP = 0x06, + UDP = 0x11, + UNKNOWN = 0xFF +}; + } // namespace sd } // namespace vsomeip diff --git a/implementation/service_discovery/include/ip_option_impl.hpp b/implementation/service_discovery/include/ip_option_impl.hpp new file mode 100644 index 0000000..8fd426b --- /dev/null +++ b/implementation/service_discovery/include/ip_option_impl.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_SD_IP_OPTION_IMPL_HPP +#define VSOMEIP_SD_IP_OPTION_IMPL_HPP + +#include <vsomeip/primitive_types.hpp> + +#include "option_impl.hpp" + +namespace vsomeip { +namespace sd { + +class ip_option_impl: public option_impl { +public: + ip_option_impl(); + virtual ~ip_option_impl(); + bool operator ==(const option_impl &_option) const; + + uint16_t get_port() const; + void set_port(uint16_t _port); + + layer_four_protocol_e get_layer_four_protocol() const; + void set_layer_four_protocol(layer_four_protocol_e _protocol); + + bool is_multicast() const; + + virtual bool serialize(vsomeip::serializer *_to) const = 0; + virtual bool deserialize(vsomeip::deserializer *_from) = 0; + +protected: + layer_four_protocol_e protocol_; + uint16_t port_; +}; + +} // namespace sd +} // namespace vsomeip + +#endif // VSOMEIP_SD_IP_OPTION_IMPL_HPP diff --git a/implementation/service_discovery/include/ipv4_option_impl.hpp b/implementation/service_discovery/include/ipv4_option_impl.hpp index 179d82f..b8051cc 100644 --- a/implementation/service_discovery/include/ipv4_option_impl.hpp +++ b/implementation/service_discovery/include/ipv4_option_impl.hpp @@ -8,35 +8,24 @@ #include <vsomeip/primitive_types.hpp>
-#include "option_impl.hpp"
+#include "ip_option_impl.hpp"
namespace vsomeip {
namespace sd {
-class ipv4_option_impl: public option_impl {
+class ipv4_option_impl: public ip_option_impl {
public:
ipv4_option_impl(bool _is_multicast);
virtual ~ipv4_option_impl();
- bool operator ==(const option_impl &_option) const;
const ipv4_address_t & get_address() const;
void set_address(const ipv4_address_t &_address);
- unsigned short get_port() const;
- void set_port(unsigned short _port);
-
- bool is_udp() const;
- void set_udp(bool _is_udp);
-
- bool is_multicast() const;
-
bool serialize(vsomeip::serializer *_to) const;
bool deserialize(vsomeip::deserializer *_from);
-protected:
+private:
ipv4_address_t address_;
- unsigned short port_;
- bool is_udp_;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/ipv6_option_impl.hpp b/implementation/service_discovery/include/ipv6_option_impl.hpp index f1a7a1c..48938b0 100644 --- a/implementation/service_discovery/include/ipv6_option_impl.hpp +++ b/implementation/service_discovery/include/ipv6_option_impl.hpp @@ -6,39 +6,26 @@ #ifndef VSOMEIP_SD_IPV6_OPTION_IMPL_HPP
#define VSOMEIP_SD_IPV6_OPTION_IMPL_HPP
-#include <vector>
-
#include <vsomeip/primitive_types.hpp>
-#include "option_impl.hpp"
+#include "ip_option_impl.hpp"
namespace vsomeip {
namespace sd {
-class ipv6_option_impl: public option_impl {
+class ipv6_option_impl: public ip_option_impl {
public:
ipv6_option_impl(bool _is_multicast);
virtual ~ipv6_option_impl();
- bool operator ==(const option_impl &_option) const;
const ipv6_address_t & get_address() const;
void set_address(const ipv6_address_t &_address);
- unsigned short get_port() const;
- void set_port(unsigned short _port);
-
- bool is_udp() const;
- void set_udp(bool _is_udp);
-
- bool is_multicast() const;
-
bool serialize(vsomeip::serializer *_to) const;
bool deserialize(vsomeip::deserializer *_from);
-protected:
+private:
ipv6_address_t address_;
- unsigned short port_;
- bool is_udp_;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/message_impl.hpp b/implementation/service_discovery/include/message_impl.hpp index e471ace..b0702df 100755 --- a/implementation/service_discovery/include/message_impl.hpp +++ b/implementation/service_discovery/include/message_impl.hpp @@ -55,6 +55,7 @@ public: const std::vector<std::shared_ptr<option_impl> > & get_options() const;
int16_t get_option_index(const std::shared_ptr<option_impl> &_option) const;
+ uint32_t get_options_length();
std::shared_ptr<payload> get_payload() const;
void set_payload(std::shared_ptr<payload> _payload);
@@ -68,6 +69,7 @@ private: private:
flags_t flags_;
+ uint32_t options_length_;
std::vector<std::shared_ptr<entry_impl> > entries_;
std::vector<std::shared_ptr<option_impl> > options_;
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp index 0d10388..38b414f 100644 --- a/implementation/service_discovery/include/service_discovery.hpp +++ b/implementation/service_discovery/include/service_discovery.hpp @@ -35,13 +35,14 @@ public: virtual void subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client) = 0; virtual void unsubscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup) = 0; + eventgroup_t _eventgroup, client_t _client) = 0; + virtual void unsubscribe_all(service_t _service, instance_t _instance) = 0; - virtual void send(const std::string &_name, bool _is_announcing) = 0; + virtual void send(bool _is_announcing) = 0; virtual void on_message(const byte_t *_data, length_t _length) = 0; - virtual void on_offer_change(const std::string &_name) = 0; + virtual void on_offer_change() = 0; }; } // namespace sd diff --git a/implementation/service_discovery/include/service_discovery_fsm.hpp b/implementation/service_discovery/include/service_discovery_fsm.hpp index d731b0b..f3fe7fd 100644 --- a/implementation/service_discovery/include/service_discovery_fsm.hpp +++ b/implementation/service_discovery/include/service_discovery_fsm.hpp @@ -43,8 +43,8 @@ struct fsm: sc::state_machine<fsm, inactive>, public fsm_base { void timer_expired(const boost::system::error_code &_error); uint32_t initial_delay_; - uint32_t repetition_base_delay_; - uint8_t repetition_max_; + uint32_t repetitions_base_delay_; + uint8_t repetitions_max_; uint32_t cyclic_offer_delay_; bool is_up_; @@ -116,10 +116,7 @@ struct announce: sc::state<announce, active> { class service_discovery_fsm: public std::enable_shared_from_this< service_discovery_fsm> { public: - service_discovery_fsm(const std::string &_name, - std::shared_ptr<service_discovery> _discovery); - - const std::string & get_name() const; + service_discovery_fsm(std::shared_ptr<service_discovery> _discovery); void start(); void stop(); @@ -132,8 +129,6 @@ public: } private: - std::string name_; - std::weak_ptr<service_discovery> discovery_; std::shared_ptr<_sd::fsm> fsm_; diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp index f9ad9e5..de1dd93 100644 --- a/implementation/service_discovery/include/service_discovery_host.hpp +++ b/implementation/service_discovery/include/service_discovery_host.hpp @@ -30,10 +30,10 @@ public: virtual boost::asio::io_service & get_io() = 0; virtual std::shared_ptr<configuration> get_configuration() const = 0; - virtual void create_service_discovery_endpoint(const std::string &_address, - uint16_t _port, bool _reliable) = 0; + virtual std::shared_ptr<endpoint> create_service_discovery_endpoint( + const std::string &_address, uint16_t _port, bool _reliable) = 0; - virtual services_t get_offered_services(const std::string &_name) const = 0; + virtual services_t get_offered_services() const = 0; virtual std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service, instance_t _instance, eventgroup_t _eventgroup) const = 0; @@ -45,11 +45,15 @@ public: virtual void add_routing_info(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable) = 0; + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port) = 0; virtual void del_routing_info(service_t _service, instance_t _instance, - bool _reliable) = 0; + bool _has_reliable, bool _has_unreliable) = 0; + + virtual ttl_t update_routing_info(ttl_t _elapsed) = 0; virtual void on_subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp index d07698e..0aceb02 100644 --- a/implementation/service_discovery/include/service_discovery_impl.hpp +++ b/implementation/service_discovery/include/service_discovery_impl.hpp @@ -11,10 +11,12 @@ #include <mutex> #include <set> +#include <boost/asio/system_timer.hpp> #include <boost/asio/ip/address.hpp> #include "service_discovery.hpp" #include "../../routing/include/types.hpp" +#include "ip_option_impl.hpp" namespace vsomeip { @@ -54,13 +56,14 @@ public: void subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client); void unsubscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup); + eventgroup_t _eventgroup, client_t _client); + void unsubscribe_all(service_t _service, instance_t _instance); - void send(const std::string &_name, bool _is_announcing); + void send(bool _is_announcing); void on_message(const byte_t *_data, length_t _length); - void on_offer_change(const std::string &_name); + void on_offer_change(); private: session_t get_session(const boost::asio::ip::address &_address); @@ -74,22 +77,39 @@ private: requests_t &_requests); void insert_offer_entries(std::shared_ptr<message_impl> &_message, services_t &_services); + void insert_offer_service(std::shared_ptr<message_impl> _message, + service_t _service, instance_t _instance, + const std::shared_ptr<const serviceinfo> &_info); void insert_subscription(std::shared_ptr<message_impl> &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, std::shared_ptr<subscription> &_subscription); void insert_subscription_ack(std::shared_ptr<message_impl> &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl); + void insert_subscription_nack(std::shared_ptr<message_impl> &_message, service_t _service, + instance_t _instance, eventgroup_t _eventgroup, std::shared_ptr<eventgroupinfo> &_info); void process_serviceentry(std::shared_ptr<serviceentry_impl> &_entry, const std::vector<std::shared_ptr<option_impl> > &_options); + void process_offerservice_serviceentry( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl, + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port); + void send_unicast_offer_service(const std::shared_ptr<const serviceinfo>& _info, + service_t _service, instance_t _instance, + major_version_t _major, + minor_version_t _minor); + void process_findservice_serviceentry(service_t _service, + instance_t _instance, + major_version_t _major, + minor_version_t _minor); void process_eventgroupentry(std::shared_ptr<eventgroupentry_impl> &_entry, const std::vector<std::shared_ptr<option_impl> > &_options); - void handle_service_availability(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable); void handle_eventgroup_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, @@ -99,6 +119,21 @@ private: instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port); + void serialize_and_send(std::shared_ptr<message_impl> _message, + const boost::asio::ip::address &_address); + + void start_ttl_timer(); + ttl_t stop_ttl_timer(); + void check_ttl(const boost::system::error_code &_error); + boost::asio::ip::address get_current_remote_address() const; + bool check_static_header_fields( + const std::shared_ptr<const message> &_message) const; + void send_eventgroup_subscription_nack(service_t _service, + instance_t _instance, + eventgroup_t _eventgroup, + major_version_t _major); + bool check_layer_four_protocol( + const std::shared_ptr<const ip_option_impl> _ip_option) const; private: boost::asio::io_service &io_; @@ -107,6 +142,7 @@ private: boost::asio::ip::address unicast_; uint16_t port_; bool reliable_; + std::shared_ptr<endpoint> endpoint_; std::shared_ptr<serializer> serializer_; std::shared_ptr<deserializer> deserializer_; @@ -119,6 +155,7 @@ private: std::map<service_t, std::map<instance_t, std::map<eventgroup_t, std::map<client_t, std::shared_ptr<subscription> > > > > subscribed_; + std::mutex subscribed_mutex_; std::mutex serialize_mutex_; @@ -127,6 +164,11 @@ private: // Runtime std::weak_ptr<runtime> runtime_; + + // TTL handling + boost::asio::system_timer ttl_timer_; + ttl_t smallest_ttl_; + ttl_t ttl_; }; } // namespace sd diff --git a/implementation/service_discovery/include/subscription.hpp b/implementation/service_discovery/include/subscription.hpp index c710b9d..bda9698 100644 --- a/implementation/service_discovery/include/subscription.hpp +++ b/implementation/service_discovery/include/subscription.hpp @@ -20,8 +20,7 @@ class subscription { public: subscription(major_version_t _major, ttl_t _ttl, std::shared_ptr<endpoint> _reliable, - std::shared_ptr<endpoint> _unreliable, - client_t _target); + std::shared_ptr<endpoint> _unreliable); ~subscription(); major_version_t get_major() const; @@ -30,7 +29,7 @@ public: std::shared_ptr<endpoint> get_endpoint(bool _reliable) const; void set_endpoint(std::shared_ptr<endpoint> _endpoint, bool _reliable); - bool is_acknowleged() const; + bool is_acknowledged() const; void set_acknowledged(bool _is_acknowledged); private: diff --git a/implementation/service_discovery/src/configuration_option_impl.cpp b/implementation/service_discovery/src/configuration_option_impl.cpp index e6092da..67a9d4c 100755 --- a/implementation/service_discovery/src/configuration_option_impl.cpp +++ b/implementation/service_discovery/src/configuration_option_impl.cpp @@ -33,13 +33,13 @@ bool configuration_option_impl::operator ==(const option_impl &_other) const { void configuration_option_impl::add_item(const std::string &_key,
const std::string &_value) {
configuration_[_key] = _value;
- length_ += (_key.length() + _value.length() + 2); // +2 for the '=' and length
+ length_ = uint16_t(length_ + _key.length() + _value.length() + 2u); // +2 for the '=' and length
}
void configuration_option_impl::remove_item(const std::string &_key) {
auto it = configuration_.find(_key);
if (it != configuration_.end()) {
- length_ -= (it->first.length() + it->second.length() + 2);
+ length_ = uint16_t(length_ - (it->first.length() + it->second.length() + 2u));
configuration_.erase(it);
}
}
@@ -72,7 +72,7 @@ bool configuration_option_impl::serialize(vsomeip::serializer *_to) const { std::string configuration_string;
for (auto i = configuration_.begin(); i != configuration_.end(); ++i) {
- char l_length = 1 + i->first.length() + i->second.length();
+ char l_length = char(1 + i->first.length() + i->second.length());
configuration_string.push_back(l_length);
configuration_string.append(i->first);
configuration_string.push_back('=');
@@ -84,7 +84,7 @@ bool configuration_option_impl::serialize(vsomeip::serializer *_to) const { if (is_successful) {
is_successful = _to->serialize(
reinterpret_cast<const uint8_t*>(configuration_string.c_str()),
- configuration_string.length());
+ uint32_t(configuration_string.length()));
}
return is_successful;
diff --git a/implementation/service_discovery/src/entry_impl.cpp b/implementation/service_discovery/src/entry_impl.cpp index 735f120..ea7a511 100755 --- a/implementation/service_discovery/src/entry_impl.cpp +++ b/implementation/service_discovery/src/entry_impl.cpp @@ -20,6 +20,8 @@ entry_impl::entry_impl() { service_ = 0x0;
instance_ = 0x0;
ttl_ = 0x0;
+ num_options_[0] = 0;
+ num_options_[1] = 0;
}
entry_impl::entry_impl(const entry_impl &_entry) {
@@ -28,6 +30,8 @@ entry_impl::entry_impl(const entry_impl &_entry) { service_ = _entry.service_;
instance_ = _entry.instance_;
ttl_ = _entry.ttl_;
+ num_options_[0] = _entry.num_options_[0];
+ num_options_[1] = _entry.num_options_[1];
}
entry_impl::~entry_impl() {
@@ -86,7 +90,7 @@ void entry_impl::assign_option(const std::shared_ptr<option_impl> &_option, if (_run > 0 && _run <= VSOMEIP_MAX_OPTION_RUN) {
_run--; // Index = Run-1
- uint8_t option_index = get_owning_message()->get_option_index(_option);
+ uint8_t option_index = uint8_t(get_owning_message()->get_option_index(_option));
if (0x10 > option_index) { // as we have only a nibble for the option counter
options_[_run].push_back(option_index);
std::sort(options_[_run].begin(), options_[_run].end());
@@ -112,7 +116,7 @@ bool entry_impl::serialize(vsomeip::serializer *_to) const { index_second_option_run = options_[1][0];
is_successful = is_successful && _to->serialize(index_second_option_run);
- uint8_t number_of_options = ((((uint8_t) options_[0].size()) << 4)
+ uint8_t number_of_options = uint8_t((((uint8_t) options_[0].size()) << 4)
| (((uint8_t) options_[1].size()) & 0x0F));
is_successful = is_successful && _to->serialize(number_of_options);
@@ -128,7 +132,7 @@ bool entry_impl::serialize(vsomeip::serializer *_to) const { bool entry_impl::deserialize(vsomeip::deserializer *_from) {
bool is_successful = (0 != _from);
- uint8_t its_type;
+ uint8_t its_type(0);
is_successful = is_successful && _from->deserialize(its_type);
type_ = static_cast<entry_type_e>(its_type);
@@ -141,13 +145,13 @@ bool entry_impl::deserialize(vsomeip::deserializer *_from) { uint8_t its_numbers;
is_successful = is_successful && _from->deserialize(its_numbers);
- uint8_t its_numbers1 = (its_numbers >> 4);
- uint8_t its_numbers2 = (its_numbers & 0xF);
+ num_options_[0] = uint8_t(its_numbers >> 4);
+ num_options_[1] = uint8_t(its_numbers & 0xF);
- for (uint8_t i = its_index1; i < its_index1 + its_numbers1; ++i)
+ for (uint8_t i = its_index1; i < its_index1 + num_options_[0]; ++i)
options_[0].push_back(i);
- for (uint8_t i = its_index2; i < its_index2 + its_numbers2; ++i)
+ for (uint8_t i = its_index2; i < its_index2 + num_options_[1]; ++i)
options_[1].push_back(i);
uint16_t its_id;
@@ -169,5 +173,12 @@ bool entry_impl::is_eventgroup_entry() const { && type_ <= entry_type_e::SUBSCRIBE_EVENTGROUP_ACK);
}
+uint8_t entry_impl::get_num_options(uint8_t _run) const {
+ if (_run < 1 || _run > VSOMEIP_MAX_OPTION_RUN) {
+ return 0x0;
+ }
+ return num_options_[_run-1];
+}
+
} // namespace sd
} // namespace vsomeip
diff --git a/implementation/service_discovery/src/eventgroupentry_impl.cpp b/implementation/service_discovery/src/eventgroupentry_impl.cpp index ba303d9..024756d 100755 --- a/implementation/service_discovery/src/eventgroupentry_impl.cpp +++ b/implementation/service_discovery/src/eventgroupentry_impl.cpp @@ -34,7 +34,7 @@ void eventgroupentry_impl::set_eventgroup(eventgroup_t _eventgroup) { bool eventgroupentry_impl::serialize(vsomeip::serializer *_to) const {
bool is_successful = entry_impl::serialize(_to);
- is_successful = is_successful && _to->serialize(protocol::reserved_byte);
+ is_successful = is_successful && _to->serialize(major_version_);
is_successful = is_successful
&& _to->serialize(static_cast<uint32_t>(ttl_), true);
@@ -50,8 +50,9 @@ bool eventgroupentry_impl::serialize(vsomeip::serializer *_to) const { bool eventgroupentry_impl::deserialize(vsomeip::deserializer *_from) {
bool is_successful = entry_impl::deserialize(_from);
- uint8_t its_reserved0;
- is_successful = is_successful && _from->deserialize(its_reserved0);
+ uint8_t tmp_major_version;
+ is_successful = is_successful && _from->deserialize(tmp_major_version);
+ major_version_ = static_cast<major_version_t>(tmp_major_version);
uint32_t its_ttl;
is_successful = is_successful && _from->deserialize(its_ttl, true);
diff --git a/implementation/service_discovery/src/ip_option_impl.cpp b/implementation/service_discovery/src/ip_option_impl.cpp new file mode 100644 index 0000000..3fcffac --- /dev/null +++ b/implementation/service_discovery/src/ip_option_impl.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <vsomeip/constants.hpp> + +#include "../include/constants.hpp" +#include "../include/ip_option_impl.hpp" +#include "../../message/include/deserializer.hpp" +#include "../../message/include/serializer.hpp" + +namespace vsomeip { +namespace sd { + +ip_option_impl::ip_option_impl() : + protocol_(layer_four_protocol_e::UNKNOWN), + port_(0xFFFF) { +} + +ip_option_impl::~ip_option_impl() { +} + +bool ip_option_impl::operator ==(const option_impl &_other) const { + if (type_ != _other.get_type()) + return false; + +#ifdef VSOMEIP_TODO + const ip_option_impl & other = + dynamic_cast<const ip_option_impl &>(_other); +#endif + return true; +} + +unsigned short ip_option_impl::get_port() const { + return port_; +} + +void ip_option_impl::set_port(unsigned short _port) { + port_ = _port; +} + +layer_four_protocol_e ip_option_impl::get_layer_four_protocol() const { + return protocol_; +} + +void ip_option_impl::set_layer_four_protocol( + layer_four_protocol_e _protocol) { + protocol_ = _protocol; +} + +bool ip_option_impl::is_multicast() const { + return (type_ == option_type_e::IP4_MULTICAST + || type_ == option_type_e::IP6_MULTICAST); +} + +} // namespace sd +} // namespace vsomeip + diff --git a/implementation/service_discovery/src/ipv4_option_impl.cpp b/implementation/service_discovery/src/ipv4_option_impl.cpp index 6416cf0..ca5a2c5 100644 --- a/implementation/service_discovery/src/ipv4_option_impl.cpp +++ b/implementation/service_discovery/src/ipv4_option_impl.cpp @@ -13,26 +13,17 @@ namespace vsomeip {
namespace sd {
-ipv4_option_impl::ipv4_option_impl(bool _is_multicast) {
+ipv4_option_impl::ipv4_option_impl(bool _is_multicast) :
+ address_({0}) {
length_ = (1 + 4 + 1 + 1 + 2);
type_ = (
_is_multicast ?
option_type_e::IP4_MULTICAST : option_type_e::IP4_ENDPOINT);
- is_udp_ = _is_multicast;
}
ipv4_option_impl::~ipv4_option_impl() {
}
-bool ipv4_option_impl::operator ==(const option_impl &_other) const {
- if (type_ != _other.get_type())
- return false;
-
- const ipv4_option_impl & other =
- dynamic_cast<const ipv4_option_impl &>(_other);
- return true;
-}
-
const ipv4_address_t & ipv4_option_impl::get_address() const {
return address_;
}
@@ -41,31 +32,11 @@ void ipv4_option_impl::set_address(const ipv4_address_t &_address) { address_ = _address;
}
-unsigned short ipv4_option_impl::get_port() const {
- return port_;
-}
-
-void ipv4_option_impl::set_port(unsigned short _port) {
- port_ = _port;
-}
-
-bool ipv4_option_impl::is_udp() const {
- return is_udp_;
-}
-
-void ipv4_option_impl::set_udp(bool _is_udp) {
- is_udp_ = _is_udp;
-}
-
-bool ipv4_option_impl::is_multicast() const {
- return (type_ == option_type_e::IP4_MULTICAST);
-}
-
bool ipv4_option_impl::serialize(vsomeip::serializer *_to) const {
bool is_successful = option_impl::serialize(_to);
- _to->serialize(&address_[0], address_.size());
+ _to->serialize(&address_[0], uint32_t(address_.size()));
_to->serialize(protocol::reserved_byte);
- _to->serialize(is_udp_ ? protocol::udp : protocol::tcp);
+ _to->serialize(static_cast<uint8_t>(protocol_));
_to->serialize(port_);
return is_successful;
}
@@ -76,7 +47,14 @@ bool ipv4_option_impl::deserialize(vsomeip::deserializer *_from) { _from->deserialize(address_.data(), 4);
_from->deserialize(its_reserved);
_from->deserialize(its_reserved);
- is_udp_ = (protocol::udp == its_reserved);
+ switch (static_cast<layer_four_protocol_e>(its_reserved)) {
+ case layer_four_protocol_e::TCP:
+ case layer_four_protocol_e::UDP:
+ protocol_ = static_cast<layer_four_protocol_e>(its_reserved);
+ break;
+ default:
+ protocol_ = layer_four_protocol_e::UNKNOWN;
+ }
_from->deserialize(port_);
return is_successful;
}
diff --git a/implementation/service_discovery/src/ipv6_option_impl.cpp b/implementation/service_discovery/src/ipv6_option_impl.cpp index 556045c..1aa2570 100755 --- a/implementation/service_discovery/src/ipv6_option_impl.cpp +++ b/implementation/service_discovery/src/ipv6_option_impl.cpp @@ -13,27 +13,17 @@ namespace vsomeip {
namespace sd {
-ipv6_option_impl::ipv6_option_impl(bool _is_multicast) {
+ipv6_option_impl::ipv6_option_impl(bool _is_multicast) :
+ address_({0}) {
length_ = (1 + 16 + 1 + 1 + 2);
type_ = (
_is_multicast ?
option_type_e::IP6_MULTICAST : option_type_e::IP6_ENDPOINT);
- is_udp_ = _is_multicast;
}
ipv6_option_impl::~ipv6_option_impl() {
}
-bool ipv6_option_impl::operator ==(const option_impl &_other) const {
- if (_other.get_type() != option_type_e::IP6_ENDPOINT)
- return false;
-
- const ipv6_option_impl& other =
- dynamic_cast<const ipv6_option_impl &>(_other);
-
- return true; // TODO:
-}
-
const ipv6_address_t & ipv6_option_impl::get_address() const {
return address_;
}
@@ -42,27 +32,11 @@ void ipv6_option_impl::set_address(const ipv6_address_t &_address) { address_ = _address;
}
-unsigned short ipv6_option_impl::get_port() const {
- return port_;
-}
-
-void ipv6_option_impl::set_port(unsigned short _port) {
- port_ = _port;
-}
-
-bool ipv6_option_impl::is_udp() const {
- return is_udp_;
-}
-
-void ipv6_option_impl::set_udp(bool _is_udp) {
- is_udp_ = _is_udp;
-}
-
bool ipv6_option_impl::serialize(vsomeip::serializer *_to) const {
bool is_successful = option_impl::serialize(_to);
- _to->serialize(&address_[0], address_.size());
+ _to->serialize(&address_[0], uint32_t(address_.size()));
_to->serialize(protocol::reserved_byte);
- _to->serialize(is_udp_ ? protocol::udp : protocol::tcp);
+ _to->serialize(static_cast<uint8_t>(protocol_));
_to->serialize(port_);
return is_successful;
}
@@ -73,7 +47,14 @@ bool ipv6_option_impl::deserialize(vsomeip::deserializer *_from) { _from->deserialize(address_.data(), 16);
_from->deserialize(its_reserved);
_from->deserialize(its_reserved);
- is_udp_ = (protocol::udp == its_reserved);
+ switch (static_cast<layer_four_protocol_e>(its_reserved)) {
+ case layer_four_protocol_e::TCP:
+ case layer_four_protocol_e::UDP:
+ protocol_ = static_cast<layer_four_protocol_e>(its_reserved);
+ break;
+ default:
+ protocol_ = layer_four_protocol_e::UNKNOWN;
+ }
_from->deserialize(port_);
return is_successful;
}
diff --git a/implementation/service_discovery/src/message_impl.cpp b/implementation/service_discovery/src/message_impl.cpp index 6736b50..3130dda 100755 --- a/implementation/service_discovery/src/message_impl.cpp +++ b/implementation/service_discovery/src/message_impl.cpp @@ -7,7 +7,6 @@ #include <vsomeip/constants.hpp>
#include <vsomeip/defines.hpp>
-#include <vsomeip/logger.hpp>
#include "../include/constants.hpp"
#include "../include/defines.hpp"
@@ -19,6 +18,7 @@ #include "../include/load_balancing_option_impl.hpp"
#include "../include/protection_option_impl.hpp"
#include "../include/message_impl.hpp"
+#include "../../logging/include/logger.hpp"
#include "../../message/include/deserializer.hpp"
#include "../../message/include/payload_impl.hpp"
#include "../../message/include/serializer.hpp"
@@ -31,15 +31,16 @@ message_impl::message_impl() { header_.method_ = 0x8100;
header_.protocol_version_ = 0x01;
flags_ = 0x00;
+ options_length_ = 0x0000;
}
message_impl::~message_impl() {
}
length_t message_impl::get_length() const {
- length_t current_length = VSOMEIP_SOMEIP_HEADER_SIZE
- + VSOMEIP_SOMEIP_SD_DATA_SIZE;
- current_length += (entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
+ length_t current_length = (VSOMEIP_SOMEIP_HEADER_SIZE
+ + VSOMEIP_SOMEIP_SD_DATA_SIZE);
+ current_length += uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
for (size_t i = 0; i < options_.size(); ++i) {
current_length += (options_[i]->get_length()
+ VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE);
@@ -55,9 +56,9 @@ bool message_impl::get_reboot_flag() const { void message_impl::set_reboot_flag(bool _is_set) {
if (_is_set)
- flags_ |= VSOMEIP_REBOOT_FLAG;
+ flags_ |= flags_t(VSOMEIP_REBOOT_FLAG);
else
- flags_ &= ~VSOMEIP_REBOOT_FLAG;
+ flags_ &= flags_t(~VSOMEIP_REBOOT_FLAG);
}
#define VSOMEIP_UNICAST_FLAG 0x40
@@ -68,12 +69,13 @@ bool message_impl::get_unicast_flag() const { void message_impl::set_unicast_flag(bool _is_set) {
if (_is_set)
- flags_ |= VSOMEIP_UNICAST_FLAG;
+ flags_ |= flags_t(VSOMEIP_UNICAST_FLAG);
else
- flags_ &= ~VSOMEIP_UNICAST_FLAG;
+ flags_ &= flags_t(~VSOMEIP_UNICAST_FLAG);
}
void message_impl::set_length(length_t _length) {
+ (void)_length;
}
std::shared_ptr<eventgroupentry_impl> message_impl::create_eventgroup_entry() {
@@ -154,7 +156,7 @@ int16_t message_impl::get_option_index( const std::shared_ptr<option_impl> &_option) const {
int16_t i = 0;
- while (i < options_.size()) {
+ while (i < int16_t(options_.size())) {
if (options_[i] == _option)
return i;
i++;
@@ -163,11 +165,16 @@ int16_t message_impl::get_option_index( return -1;
}
+uint32_t message_impl::get_options_length() {
+ return options_length_;
+}
+
std::shared_ptr<payload> message_impl::get_payload() const {
return std::make_shared<payload_impl>();
}
void message_impl::set_payload(std::shared_ptr<payload> _payload) {
+ (void)_payload;
}
bool message_impl::serialize(vsomeip::serializer *_to) const {
@@ -177,7 +184,7 @@ bool message_impl::serialize(vsomeip::serializer *_to) const { is_successful = is_successful
&& _to->serialize(protocol::reserved_long, true);
- uint32_t entries_length = (entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
+ uint32_t entries_length = uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
is_successful = is_successful && _to->serialize(entries_length);
for (auto it = entries_.begin(); it != entries_.end(); ++it)
@@ -213,7 +220,7 @@ bool message_impl::deserialize(vsomeip::deserializer *_from) { is_successful = is_successful && _from->deserialize(entries_length);
// backup the current remaining length
- uint32_t save_remaining = _from->get_remaining();
+ uint32_t save_remaining = uint32_t(_from->get_remaining());
// set remaining bytes to length of entries array
_from->set_remaining(entries_length);
@@ -231,9 +238,18 @@ bool message_impl::deserialize(vsomeip::deserializer *_from) { // set length to remaining bytes after entries array
_from->set_remaining(save_remaining - entries_length);
+ // Don't try to deserialize options if there aren't any
+ if(_from->get_remaining() == 0) {
+ return is_successful;
+ }
+
// deserialize the options
- uint32_t options_length = 0;
- is_successful = is_successful && _from->deserialize(options_length);
+ is_successful = is_successful && _from->deserialize(options_length_);
+
+ // check if there is unreferenced data behind the last option and discard it
+ if(_from->get_remaining() > options_length_) {
+ _from->set_remaining(options_length_);
+ }
while (is_successful && _from->get_remaining()) {
std::shared_ptr < option_impl > its_option(deserialize_option(_from));
@@ -279,6 +295,7 @@ entry_impl * message_impl::deserialize_entry(vsomeip::deserializer *_from) { // deserialize object
if (0 != deserialized_entry) {
+ deserialized_entry->set_owning_message(this);
if (!deserialized_entry->deserialize(_from)) {
delete deserialized_entry;
deserialized_entry = 0;
@@ -323,6 +340,7 @@ option_impl * message_impl::deserialize_option(vsomeip::deserializer *_from) { break;
default:
+ deserialized_option = new option_impl();
break;
};
diff --git a/implementation/service_discovery/src/option_impl.cpp b/implementation/service_discovery/src/option_impl.cpp index a9ac4a9..71bbc6a 100755 --- a/implementation/service_discovery/src/option_impl.cpp +++ b/implementation/service_discovery/src/option_impl.cpp @@ -20,6 +20,7 @@ option_impl::~option_impl() { }
bool option_impl::operator ==(const option_impl &_other) const {
+ (void)_other;
return false;
}
@@ -43,7 +44,25 @@ bool option_impl::deserialize(vsomeip::deserializer *_from) { && _from->deserialize(its_type) && _from->deserialize(reserved));
if (l_result) {
- type_ = static_cast<option_type_e>(its_type);
+ switch(static_cast<option_type_e>(its_type)) {
+ case option_type_e::CONFIGURATION:
+ case option_type_e::LOAD_BALANCING:
+ case option_type_e::PROTECTION:
+ case option_type_e::IP4_ENDPOINT:
+ case option_type_e::IP6_ENDPOINT:
+ case option_type_e::IP4_MULTICAST:
+ case option_type_e::IP6_MULTICAST:
+ type_ = static_cast<option_type_e>(its_type);
+ break;
+ default:
+ type_ = option_type_e::UNKNOWN;
+ // reduce remaining bytes of the deserializer by the length of
+ // the unknown option to make it look like it was deserialized.
+ // - 1 because the reserved byte which is included in the length
+ // was already deserialized (s. above)
+ std::size_t remaining = _from->get_remaining();
+ _from->set_remaining(remaining - (length_ - 1));
+ }
}
return l_result;
diff --git a/implementation/service_discovery/src/service_discovery_fsm.cpp b/implementation/service_discovery/src/service_discovery_fsm.cpp index 8b2cb17..d2428dd 100644 --- a/implementation/service_discovery/src/service_discovery_fsm.cpp +++ b/implementation/service_discovery/src/service_discovery_fsm.cpp @@ -6,12 +6,11 @@ #include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int_distribution.hpp> -#include <vsomeip/configuration.hpp> -#include <vsomeip/logger.hpp> - #include "../include/defines.hpp" #include "../include/service_discovery.hpp" #include "../include/service_discovery_fsm.hpp" +#include "../../configuration/include/configuration.hpp" +#include "../../logging/include/logger.hpp" namespace vsomeip { namespace sd { @@ -48,12 +47,14 @@ inactive::inactive(my_context context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::inactive"; + VSOMEIP_TRACE << "sd::inactive"; outermost_context().run_ = 0; } } sc::result inactive::react(const ev_none &_event) { + (void)_event; + if (outermost_context().is_up_) { return transit<active>(); } @@ -62,6 +63,8 @@ sc::result inactive::react(const ev_none &_event) { } sc::result inactive::react(const ev_status_change &_event) { + (void)_event; + outermost_context().is_up_ = _event.is_up_; if (outermost_context().is_up_) { return transit<active>(); @@ -78,7 +81,7 @@ active::active(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active"; + VSOMEIP_TRACE << "sd::active"; } } @@ -86,6 +89,8 @@ active::~active() { } sc::result active::react(const ev_status_change &_event) { + (void)_event; + outermost_context().stop_timer(); outermost_context().is_up_ = _event.is_up_; if (!outermost_context().is_up_) @@ -102,12 +107,13 @@ initial::initial(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active.initial"; + VSOMEIP_TRACE << "sd::active.initial"; outermost_context().start_timer(outermost_context().initial_delay_); } } sc::result initial::react(const ev_timeout &_event) { + (void)_event; return transit<repeat>(); } @@ -119,8 +125,8 @@ repeat::repeat(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active.repeat"; - uint32_t its_timeout = (outermost_context().repetition_base_delay_ + VSOMEIP_TRACE << "sd::active.repeat"; + uint32_t its_timeout = (outermost_context().repetitions_base_delay_ << outermost_context().run_); outermost_context().run_++; fsm->send(false); @@ -129,13 +135,16 @@ repeat::repeat(my_context _context) } sc::result repeat::react(const ev_timeout &_event) { - if (outermost_context().run_ < outermost_context().repetition_max_) + (void)_event; + + if (outermost_context().run_ < outermost_context().repetitions_max_) return transit<repeat>(); return transit<announce>(); } sc::result repeat::react(const ev_find_service &_event) { + (void)_event; return discard_event(); } @@ -147,7 +156,7 @@ announce::announce(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active.announce"; + VSOMEIP_TRACE << "sd::active.announce"; outermost_context().start_timer( outermost_context().cyclic_offer_delay_); fsm->send(true); @@ -155,14 +164,17 @@ announce::announce(my_context _context) } sc::result announce::react(const ev_timeout &_event) { + (void)_event; return transit<announce>(); } sc::result announce::react(const ev_find_service &_event) { + (void)_event; return discard_event(); } sc::result announce::react(const ev_offer_change &_event) { + (void)_event; return transit<announce>(); } @@ -171,9 +183,9 @@ sc::result announce::react(const ev_offer_change &_event) { /////////////////////////////////////////////////////////////////////////////// // Interface /////////////////////////////////////////////////////////////////////////////// -service_discovery_fsm::service_discovery_fsm(const std::string &_name, +service_discovery_fsm::service_discovery_fsm( std::shared_ptr<service_discovery> _discovery) - : name_(_name), discovery_(_discovery), fsm_( + : discovery_(_discovery), fsm_( std::make_shared < _sd::fsm > (_discovery->get_io())) { std::shared_ptr < service_discovery > discovery = discovery_.lock(); @@ -181,57 +193,54 @@ service_discovery_fsm::service_discovery_fsm(const std::string &_name, std::shared_ptr < configuration > its_configuration = discovery->get_configuration(); - int32_t its_min_initial_delay = - its_configuration->get_min_initial_delay(name_); - if (its_min_initial_delay < 0) - its_min_initial_delay = VSOMEIP_SD_DEFAULT_MIN_INITIAL_DELAY; + int32_t its_initial_delay_min + = its_configuration->get_sd_initial_delay_min(); + if (its_initial_delay_min < 0) + its_initial_delay_min = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN; - int32_t its_max_initial_delay = - its_configuration->get_max_initial_delay(name_); - if (its_max_initial_delay <= 0) - its_max_initial_delay = VSOMEIP_SD_DEFAULT_MAX_INITIAL_DELAY; + int32_t its_initial_delay_max + = its_configuration->get_sd_initial_delay_max(); + if (its_initial_delay_max <= 0) + its_initial_delay_max = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX; - if (its_min_initial_delay > its_max_initial_delay) { - int32_t tmp_initial_delay = its_min_initial_delay; - its_min_initial_delay = its_max_initial_delay; - its_max_initial_delay = its_min_initial_delay; + if (its_initial_delay_min > its_initial_delay_max) { + int32_t tmp_initial_delay = its_initial_delay_min; + its_initial_delay_min = its_initial_delay_max; + its_initial_delay_max = tmp_initial_delay; } - VSOMEIP_TRACE << "Inital delay [" << its_min_initial_delay << ", " - << its_max_initial_delay << "]"; + VSOMEIP_TRACE << "Inital delay [" << its_initial_delay_min << ", " + << its_initial_delay_max << "]"; boost::random::mt19937 its_generator; boost::random::uniform_int_distribution<> its_distribution( - its_min_initial_delay, its_max_initial_delay); + its_initial_delay_min, its_initial_delay_max); fsm_->initial_delay_ = its_distribution(its_generator); - fsm_->repetition_base_delay_ = - its_configuration->get_repetition_base_delay(name_); - if (fsm_->repetition_base_delay_ <= 0) - fsm_->repetition_base_delay_ - = VSOMEIP_SD_DEFAULT_REPETITION_BASE_DELAY; - fsm_->repetition_max_ = its_configuration->get_repetition_max(name_); - if (fsm_->repetition_max_ <= 0) - fsm_->repetition_max_ = VSOMEIP_SD_DEFAULT_REPETITION_MAX; - - fsm_->cyclic_offer_delay_ = - its_configuration->get_cyclic_offer_delay(name_); + fsm_->repetitions_base_delay_ + = its_configuration->get_sd_repetitions_base_delay(); + if (fsm_->repetitions_base_delay_ <= 0) + fsm_->repetitions_base_delay_ + = VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY; + fsm_->repetitions_max_ + = its_configuration->get_sd_repetitions_max(); + if (fsm_->repetitions_max_ <= 0) + fsm_->repetitions_max_ = VSOMEIP_SD_DEFAULT_REPETITIONS_MAX; + + fsm_->cyclic_offer_delay_ + = its_configuration->get_sd_cyclic_offer_delay(); if (fsm_->cyclic_offer_delay_ <= 0) fsm_->cyclic_offer_delay_ = VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY; VSOMEIP_INFO << "SD configuration [" << fsm_->initial_delay_ << ":" - << fsm_->repetition_base_delay_ << ":" - << (int) fsm_->repetition_max_ << ":" + << fsm_->repetitions_base_delay_ << ":" + << (int) fsm_->repetitions_max_ << ":" << fsm_->cyclic_offer_delay_ << "]"; } else { VSOMEIP_ERROR << "SD initialization failed"; } } -const std::string & service_discovery_fsm::get_name() const { - return name_; -} - void service_discovery_fsm::start() { fsm_->set_fsm(shared_from_this()); fsm_->initiate(); @@ -243,7 +252,7 @@ void service_discovery_fsm::stop() { void service_discovery_fsm::send(bool _is_announcing) { std::shared_ptr < service_discovery > discovery = discovery_.lock(); if (discovery) - discovery->send(name_, _is_announcing); + discovery->send(_is_announcing); } } // namespace sd diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp index 42d93b6..38975fb 100644 --- a/implementation/service_discovery/src/service_discovery_impl.cpp +++ b/implementation/service_discovery/src/service_discovery_impl.cpp @@ -3,8 +3,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <vsomeip/configuration.hpp> -#include <vsomeip/logger.hpp> +#include <vsomeip/constants.hpp> #include "../include/constants.hpp" #include "../include/defines.hpp" @@ -21,23 +20,27 @@ #include "../include/service_discovery_impl.hpp" #include "../include/serviceentry_impl.hpp" #include "../include/subscription.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/endpoint.hpp" #include "../../endpoints/include/endpoint_definition.hpp" #include "../../endpoints/include/tcp_server_endpoint_impl.hpp" #include "../../endpoints/include/udp_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/serializer.hpp" #include "../../routing/include/eventgroupinfo.hpp" -#include "../../routing/include/servicegroup.hpp" #include "../../routing/include/serviceinfo.hpp" namespace vsomeip { namespace sd { service_discovery_impl::service_discovery_impl(service_discovery_host *_host) - : host_(_host), io_(_host->get_io()), serializer_( - std::make_shared<serializer>()), deserializer_( - std::make_shared<deserializer>()) { + : io_(_host->get_io()), + host_(_host), + serializer_(std::make_shared<serializer>()), + deserializer_(std::make_shared<deserializer>()), + ttl_timer_(_host->get_io()), + smallest_ttl_(DEFAULT_TTL) { } service_discovery_impl::~service_discovery_impl() { @@ -53,27 +56,15 @@ boost::asio::io_service & service_discovery_impl::get_io() { void service_discovery_impl::init() { runtime_ = runtime::get(); - default_ = std::make_shared < service_discovery_fsm - > ("default", shared_from_this()); + default_ = std::make_shared<service_discovery_fsm>(shared_from_this()); std::shared_ptr < configuration > its_configuration = host_->get_configuration(); if (its_configuration) { - unicast_ = its_configuration->get_unicast(); - - std::set < std::string > its_servicegroups = - its_configuration->get_servicegroups(); - for (auto its_group : its_servicegroups) { - if (its_group != "default" - && its_configuration->is_local_servicegroup(its_group)) { - additional_[its_group] = std::make_shared - < service_discovery_fsm - > (its_group, shared_from_this()); - } - } + unicast_ = its_configuration->get_unicast_address(); - port_ = its_configuration->get_service_discovery_port(); - reliable_ = (its_configuration->get_service_discovery_protocol() + port_ = its_configuration->get_sd_port(); + reliable_ = (its_configuration->get_sd_protocol() == "tcp"); serializer_->create_data( @@ -81,10 +72,10 @@ void service_discovery_impl::init() { VSOMEIP_MAX_TCP_MESSAGE_SIZE : VSOMEIP_MAX_UDP_MESSAGE_SIZE); - host_->create_service_discovery_endpoint( - its_configuration->get_service_discovery_multicast(), port_, - reliable_); + endpoint_ = host_->create_service_discovery_endpoint( + its_configuration->get_sd_multicast(), port_, reliable_); + ttl_ = its_configuration->get_sd_ttl(); } else { VSOMEIP_ERROR << "SD: no configuration found!"; } @@ -134,6 +125,8 @@ void service_discovery_impl::release_service(service_t _service, void service_discovery_impl::subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client) { + std::lock_guard<std::mutex> its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); if (found_service != subscribed_.end()) { auto found_instance = found_service->second.find(_instance); @@ -155,70 +148,108 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance, } } + // New subscription std::shared_ptr < endpoint > its_reliable = host_->find_or_create_remote_client( _service, _instance, true, _client); std::shared_ptr < endpoint > its_unreliable = host_->find_or_create_remote_client( _service, _instance, false, _client); std::shared_ptr < subscription > its_subscription = std::make_shared - < subscription > (_major, _ttl, its_reliable, its_unreliable, _client); + < subscription > (_major, _ttl, its_reliable, its_unreliable); subscribed_[_service][_instance][_eventgroup][_client] = its_subscription; - if (!its_subscription->is_acknowleged()) { - bool has_address(false); - boost::asio::ip::address its_address; - - std::shared_ptr<endpoint> its_endpoint - = host_->find_or_create_remote_client(_service, _instance, false, _client); + bool has_address(false); + boost::asio::ip::address its_address; - if (its_endpoint) { - has_address = its_endpoint->get_remote_address(its_address); - its_subscription->set_endpoint(its_endpoint, false); - } + std::shared_ptr<endpoint> its_endpoint + = host_->find_or_create_remote_client(_service, _instance, false, _client); - its_endpoint = host_->find_or_create_remote_client(_service, _instance, true, _client); - if (its_endpoint) { - has_address = has_address || its_endpoint->get_remote_address(its_address); - its_subscription->set_endpoint(its_endpoint, true); - } + if (its_endpoint) { + has_address = its_endpoint->get_remote_address(its_address); + its_subscription->set_endpoint(its_endpoint, false); + } - if (has_address) { - std::shared_ptr < runtime > its_runtime = runtime_.lock(); - if (!its_runtime) - return; + its_endpoint = host_->find_or_create_remote_client(_service, _instance, true, _client); + if (its_endpoint) { + has_address = has_address || its_endpoint->get_remote_address(its_address); + its_subscription->set_endpoint(its_endpoint, true); + } - std::shared_ptr < message_impl > its_message - = its_runtime->create_message(); + if (has_address) { + std::shared_ptr<runtime> its_runtime = runtime_.lock(); + if (!its_runtime) + return; - // TODO: consume major & ttl - insert_subscription(its_message, _service, _instance, _eventgroup, - its_subscription); - its_message->set_session(get_session(its_address)); + std::shared_ptr<message_impl> its_message + = its_runtime->create_message(); - serializer_->serialize(its_message.get()); + // TODO: consume major & ttl + insert_subscription(its_message, _service, _instance, _eventgroup, + its_subscription); + serialize_and_send(its_message, its_address); - if (host_->send_to( - std::make_shared<endpoint_definition>( - its_address, port_, reliable_), - serializer_->get_data(), - serializer_->get_size())) { - increment_session(its_address); - } - serializer_->reset(); - } + its_subscription->set_acknowledged(false); } } void service_discovery_impl::unsubscribe(service_t _service, - instance_t _instance, eventgroup_t _eventgroup) { - // TODO: add client_id!!! + instance_t _instance, eventgroup_t _eventgroup, client_t _client) { + + std::lock_guard<std::mutex> its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); if (found_service != subscribed_.end()) { auto found_instance = found_service->second.find(_instance); if (found_instance != found_service->second.end()) { auto found_eventgroup = found_instance->second.find(_eventgroup); if (found_eventgroup != found_instance->second.end()) { - for (auto its_client : found_eventgroup->second) { - its_client.second->set_ttl(0); // is read once and removed afterwards! + auto found_client = found_eventgroup->second.find(_client); + if (found_client != found_eventgroup->second.end()) { + found_client->second->set_ttl(0); + } + } + } + } + + boost::asio::ip::address its_address; + + std::shared_ptr < runtime > its_runtime = runtime_.lock(); + if (!its_runtime) + return; + + std::shared_ptr < subscription > its_subscription = + subscribed_[_service][_instance][_eventgroup][_client]; + + auto endpoint = its_subscription->get_endpoint(false); + if (endpoint) { + endpoint->get_remote_address(its_address); + } else { + endpoint = its_subscription->get_endpoint(true); + if (endpoint) { + endpoint->get_remote_address(its_address); + } + } + + std::shared_ptr < message_impl > its_message + = its_runtime->create_message(); + + insert_subscription(its_message, _service, _instance, _eventgroup, + its_subscription); + its_message->set_session(get_session(its_address)); + + serialize_and_send(its_message, its_address); +} + +void service_discovery_impl::unsubscribe_all(service_t _service, instance_t _instance) { + std::lock_guard<std::mutex> its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + for (auto &its_eventgroup : found_instance->second) { + for (auto its_client : its_eventgroup.second) { + its_client.second->set_acknowledged(true); + its_client.second->set_endpoint(nullptr, true); + its_client.second->set_endpoint(nullptr, false); } } } @@ -262,7 +293,9 @@ void service_discovery_impl::insert_option( if (its_option) { its_option->set_address(its_address); its_option->set_port(_port); - its_option->set_udp(!_is_reliable); + its_option->set_layer_four_protocol( + _is_reliable ? layer_four_protocol_e::TCP : + layer_four_protocol_e::UDP); _entry->assign_option(its_option, 1); } } else { @@ -272,7 +305,9 @@ void service_discovery_impl::insert_option( if (its_option) { its_option->set_address(its_address); its_option->set_port(_port); - its_option->set_udp(!_is_reliable); + its_option->set_layer_four_protocol( + _is_reliable ? layer_four_protocol_e::TCP : + layer_four_protocol_e::UDP); _entry->assign_option(its_option, 1); } } @@ -325,40 +360,8 @@ void service_discovery_impl::insert_offer_entries( std::shared_ptr<message_impl> &_message, services_t &_services) { for (auto its_service : _services) { for (auto its_instance : its_service.second) { - auto its_info = its_instance.second; - std::shared_ptr < serviceentry_impl > its_entry = - _message->create_service_entry(); - if (its_entry) { - its_entry->set_type(entry_type_e::OFFER_SERVICE); - its_entry->set_service(its_service.first); - its_entry->set_instance(its_instance.first); - its_entry->set_major_version(its_info->get_major()); - its_entry->set_minor_version(its_info->get_minor()); - its_entry->set_ttl(its_info->get_ttl()); - - std::shared_ptr < endpoint > its_endpoint = - its_info->get_endpoint(true); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, - its_endpoint->get_local_port(), true); - if (0 == its_info->get_ttl()) { - host_->del_routing_info(its_service.first, - its_instance.first, true); - } - } - - its_endpoint = its_info->get_endpoint(false); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, - its_endpoint->get_local_port(), false); - if (0 == its_info->get_ttl()) { - host_->del_routing_info(its_service.first, - its_instance.first, false); - } - } - } else { - VSOMEIP_ERROR << "Failed to create service entry."; - } + insert_offer_service(_message, its_service.first, + its_instance.first, its_instance.second); } } } @@ -391,7 +394,7 @@ void service_discovery_impl::insert_subscription( void service_discovery_impl::insert_subscription_ack( std::shared_ptr<message_impl> &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<eventgroupinfo> &_info) { + std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl) { std::shared_ptr < eventgroupentry_impl > its_entry = _message->create_eventgroup_entry(); its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP_ACK); @@ -399,7 +402,8 @@ void service_discovery_impl::insert_subscription_ack( its_entry->set_instance(_instance); its_entry->set_eventgroup(_eventgroup); its_entry->set_major_version(_info->get_major()); - its_entry->set_ttl(_info->get_ttl()); + // SWS_SD_00315 + its_entry->set_ttl(_ttl); boost::asio::ip::address its_address; uint16_t its_port; @@ -408,8 +412,29 @@ void service_discovery_impl::insert_subscription_ack( } } -void service_discovery_impl::send(const std::string &_name, - bool _is_announcing) { +void service_discovery_impl::insert_subscription_nack( + std::shared_ptr<message_impl> &_message, service_t _service, + instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr<eventgroupinfo> &_info) { + std::shared_ptr < eventgroupentry_impl > its_entry = + _message->create_eventgroup_entry(); + // SWS_SD_00316 and SWS_SD_00385 + its_entry->set_type(entry_type_e::STOP_SUBSCRIBE_EVENTGROUP_ACK); + its_entry->set_service(_service); + its_entry->set_instance(_instance); + its_entry->set_eventgroup(_eventgroup); + its_entry->set_major_version(_info->get_major()); + // SWS_SD_00432 + its_entry->set_ttl(0x0); + + boost::asio::ip::address its_address; + uint16_t its_port; + if (_info->get_multicast(its_address, its_port)) { + insert_option(_message, its_entry, its_address, its_port, false); + } +} + +void service_discovery_impl::send(bool _is_announcing) { std::shared_ptr < runtime > its_runtime = runtime_.lock(); if (!its_runtime) @@ -420,13 +445,13 @@ void service_discovery_impl::send(const std::string &_name, // TODO: optimize building of SD message (common options, utilize the two runs) - // If we are the default group and not in main phase, include "FindOffer"-entries - if (_name == "default" && !_is_announcing) { + // If we are not in main phase, include "FindOffer"-entries + if (!_is_announcing) { insert_find_entries(its_message, requested_); } // Always include the "OfferService"-entries for the service group - services_t its_offers = host_->get_offered_services(_name); + services_t its_offers = host_->get_offered_services(); insert_offer_entries(its_message, its_offers); // Serialize and send @@ -451,6 +476,13 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length) { std::shared_ptr < message_impl > its_message(deserializer_->deserialize_sd_message()); if (its_message) { + // ignore all messages which are sent with invalid header fields + if(!check_static_header_fields(its_message)) { + return; + } + ttl_t expired = stop_ttl_timer(); + smallest_ttl_ = host_->update_routing_info(expired); + std::vector < std::shared_ptr<option_impl> > its_options = its_message->get_options(); for (auto its_entry : its_message->get_entries()) { @@ -466,35 +498,42 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length) { process_eventgroupentry(its_eventgroup_entry, its_options); } } + start_ttl_timer(); + } else { + VSOMEIP_ERROR << "service_discovery_impl::on_message: deserialization error."; + return; } } -void service_discovery_impl::on_offer_change(const std::string &_name) { - if (_name == "default") { - default_->process(ev_offer_change()); - } else { - auto found_group = additional_.find(_name); - if (found_group != additional_.end()) { - found_group->second->process(ev_offer_change()); - } - } +void service_discovery_impl::on_offer_change() { + default_->process(ev_offer_change()); } // Entry processing void service_discovery_impl::process_serviceentry( std::shared_ptr<serviceentry_impl> &_entry, const std::vector<std::shared_ptr<option_impl> > &_options) { + + // Read service info from entry + entry_type_e its_type = _entry->get_type(); service_t its_service = _entry->get_service(); instance_t its_instance = _entry->get_instance(); major_version_t its_major = _entry->get_major_version(); minor_version_t its_minor = _entry->get_minor_version(); ttl_t its_ttl = _entry->get_ttl(); + // Read address info from options + boost::asio::ip::address its_reliable_address; + uint16_t its_reliable_port(ILLEGAL_PORT); + + boost::asio::ip::address its_unreliable_address; + uint16_t its_unreliable_port(ILLEGAL_PORT); + + for (auto i : { 1, 2 }) { - for (auto its_index : _entry->get_options(i)) { - std::vector < byte_t > its_option_address; - uint16_t its_option_port = VSOMEIP_INVALID_PORT; + for (auto its_index : _entry->get_options(uint8_t(i))) { std::shared_ptr < option_impl > its_option = _options[its_index]; + switch (its_option->get_type()) { case option_type_e::IP4_ENDPOINT: { std::shared_ptr < ipv4_option_impl > its_ipv4_option = @@ -503,12 +542,15 @@ void service_discovery_impl::process_serviceentry( boost::asio::ip::address_v4 its_ipv4_address( its_ipv4_option->get_address()); - boost::asio::ip::address its_address(its_ipv4_address); - its_option_port = its_ipv4_option->get_port(); - handle_service_availability(its_service, its_instance, - its_major, its_minor, its_ttl, its_address, - its_option_port, !its_ipv4_option->is_udp()); + if (its_ipv4_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { + its_unreliable_address = its_ipv4_address; + its_unreliable_port = its_ipv4_option->get_port(); + } else { + its_reliable_address = its_ipv4_address; + its_reliable_port = its_ipv4_option->get_port(); + } break; } case option_type_e::IP6_ENDPOINT: { @@ -518,24 +560,211 @@ void service_discovery_impl::process_serviceentry( boost::asio::ip::address_v6 its_ipv6_address( its_ipv6_option->get_address()); - boost::asio::ip::address its_address(its_ipv6_address); - its_option_port = its_ipv6_option->get_port(); - handle_service_availability(its_service, its_instance, - its_major, its_minor, its_ttl, its_address, - its_option_port, !its_ipv6_option->is_udp()); + if (its_ipv6_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { + its_unreliable_address = its_ipv6_address; + its_unreliable_port = its_ipv6_option->get_port(); + } else { + its_reliable_address = its_ipv6_address; + its_reliable_port = its_ipv6_option->get_port(); + } break; } case option_type_e::IP4_MULTICAST: case option_type_e::IP6_MULTICAST: VSOMEIP_ERROR << "Invalid service option (Multicast)"; break; + case option_type_e::UNKNOWN: default: - VSOMEIP_WARNING << "Unsupported service option"; + VSOMEIP_ERROR << "Unsupported service option"; break; } } } + + if (0 < its_ttl) { + switch(its_type) { + case entry_type_e::FIND_SERVICE: + process_findservice_serviceentry(its_service, its_instance, + its_major, its_minor); + break; + case entry_type_e::OFFER_SERVICE: + process_offerservice_serviceentry(its_service, its_instance, + its_major, its_minor, its_ttl, + its_reliable_address, its_reliable_port, + its_unreliable_address, its_unreliable_port); + break; + case entry_type_e::UNKNOWN: + default: + VSOMEIP_ERROR << "Unsupported serviceentry type"; + } + + } else { + unsubscribe_all(its_service, its_instance); + host_->del_routing_info(its_service, its_instance, + (its_reliable_port != ILLEGAL_PORT), + (its_unreliable_port != ILLEGAL_PORT)); + } +} + +void service_discovery_impl::process_offerservice_serviceentry( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl, + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port) { + std::shared_ptr < runtime > its_runtime = runtime_.lock(); + if (!its_runtime) + return; + + host_->add_routing_info(_service, _instance, + _major, _minor, _ttl, + _reliable_address, _reliable_port, + _unreliable_address, _unreliable_port); + + std::lock_guard<std::mutex> its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + if (0 < found_instance->second.size()) { + std::shared_ptr<message_impl> its_message + = its_runtime->create_message(); + + for (auto its_eventgroup : found_instance->second) { + for (auto its_client : its_eventgroup.second) { + std::shared_ptr<subscription> its_subscription(its_client.second); + if (its_subscription->is_acknowledged()) { + its_subscription->set_endpoint( + host_->find_or_create_remote_client(_service, + _instance, true, its_client.first), true); + its_subscription->set_endpoint( + host_->find_or_create_remote_client(_service, + _instance, false, its_client.first), false); + + // TODO: consume major & ttl + insert_subscription(its_message, + _service, _instance, + its_eventgroup.first, + its_subscription); + + its_subscription->set_acknowledged(false); + } + } + } + + if (0 < its_message->get_entries().size()) { + std::shared_ptr<endpoint_definition> its_target; + session_t its_session(0); + if (_reliable_port != ILLEGAL_PORT) { + its_target = endpoint_definition::get( + _reliable_address, port_, reliable_); + its_session = get_session(_reliable_address); + } else if (_unreliable_port != ILLEGAL_PORT) { + its_target = endpoint_definition::get( + _unreliable_address, port_, reliable_); + its_session = get_session(_unreliable_address); + } + + if (its_target) { + its_message->set_session(its_session); + serializer_->serialize(its_message.get()); + if (host_->send_to(its_target, + serializer_->get_data(), + serializer_->get_size())) { + increment_session(its_target->get_address()); + } + serializer_->reset(); + } + } + } + } + } +} + +void service_discovery_impl::process_findservice_serviceentry( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor) { + services_t offered_services = host_->get_offered_services(); + auto found_service = offered_services.find(_service); + if (found_service != offered_services.end()) { + if (_instance != ANY_INSTANCE) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + std::shared_ptr<serviceinfo> its_info = found_instance->second; + send_unicast_offer_service(its_info, _service, _instance, + _major, _minor); + } + } else { + // send back all available instances + for (const auto &found_instance : found_service->second) { + send_unicast_offer_service(found_instance.second, _service, + _instance, _major, _minor); + } + } + } +} + +void service_discovery_impl::send_unicast_offer_service( + const std::shared_ptr<const serviceinfo> &_info, service_t _service, + instance_t _instance, major_version_t _major, minor_version_t _minor) { + if (_major == ANY_MAJOR || _major == _info->get_major()) { + if (_minor == 0xFFFFFFFF || _minor == _info->get_minor()) { + std::shared_ptr<runtime> its_runtime = runtime_.lock(); + if (!its_runtime) { + return; + } + std::shared_ptr<message_impl> its_message = + its_runtime->create_message(); + insert_offer_service(its_message, _service, _instance, _info); + + serialize_and_send(its_message, get_current_remote_address()); + } + } +} + +void service_discovery_impl::insert_offer_service( + std::shared_ptr < message_impl > _message, service_t _service, + instance_t _instance, const std::shared_ptr<const serviceinfo> &_info) { + std::shared_ptr < serviceentry_impl > its_entry = + _message->create_service_entry(); + if (its_entry) { + its_entry->set_type(entry_type_e::OFFER_SERVICE); + its_entry->set_service(_service); + its_entry->set_instance(_instance); + its_entry->set_major_version(_info->get_major()); + its_entry->set_minor_version(_info->get_minor()); + + ttl_t its_ttl = _info->get_ttl(); + if (its_ttl > 0) + its_ttl = ttl_; + its_entry->set_ttl(its_ttl); + + std::shared_ptr < endpoint > its_endpoint = + _info->get_endpoint(true); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, + its_endpoint->get_local_port(), true); + if (0 == _info->get_ttl()) { + host_->del_routing_info(_service, + _instance, true, false); + } + } + + its_endpoint = _info->get_endpoint(false); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, + its_endpoint->get_local_port(), false); + if (0 == _info->get_ttl()) { + host_->del_routing_info(_service, + _instance, false, true); + } + } + } else { + VSOMEIP_ERROR << "Failed to create service entry."; + } } void service_discovery_impl::process_eventgroupentry( @@ -548,27 +777,74 @@ void service_discovery_impl::process_eventgroupentry( major_version_t its_major = _entry->get_major_version(); ttl_t its_ttl = _entry->get_ttl(); + if (_entry->get_owning_message()->get_return_code() != return_code) { + VSOMEIP_ERROR << "Invalid return code in SD header"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + + if(its_type == entry_type_e::SUBSCRIBE_EVENTGROUP) { + if (_entry->get_num_options(1) == 0 + && _entry->get_num_options(2) == 0) { + VSOMEIP_ERROR << "Invalid number of options in SubscribeEventGroup entry"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + if(_entry->get_owning_message()->get_options_length() < 12) { + VSOMEIP_ERROR << "Invalid options length in SD message"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + if (_options.size() + < (_entry->get_num_options(1) + _entry->get_num_options(2))) { + VSOMEIP_ERROR << "Fewer options in SD message than " + "referenced in EventGroup entry"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + } + boost::asio::ip::address its_reliable_address; - uint16_t its_reliable_port = VSOMEIP_INVALID_PORT; + uint16_t its_reliable_port(ILLEGAL_PORT); boost::asio::ip::address its_unreliable_address; - uint16_t its_unreliable_port = VSOMEIP_INVALID_PORT; + uint16_t its_unreliable_port(ILLEGAL_PORT); for (auto i : { 1, 2 }) { - for (auto its_index : _entry->get_options(i)) { - std::vector < byte_t > its_option_address; - std::shared_ptr < option_impl > its_option = _options[its_index]; + for (auto its_index : _entry->get_options(uint8_t(i))) { + std::shared_ptr < option_impl > its_option; + try { + its_option = _options.at(its_index); + } catch(const std::out_of_range& e) { + VSOMEIP_ERROR << "Fewer options in SD message than " + "referenced in EventGroup entry for " + "option run number: " << i; + if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + } + return; + } switch (its_option->get_type()) { case option_type_e::IP4_ENDPOINT: { - if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { std::shared_ptr < ipv4_option_impl > its_ipv4_option = std::dynamic_pointer_cast < ipv4_option_impl > (its_option); boost::asio::ip::address_v4 its_ipv4_address( its_ipv4_option->get_address()); - + if (!check_layer_four_protocol(its_ipv4_option)) { + send_eventgroup_subscription_nack(its_service, + its_instance, its_eventgroup, its_major); + return; + } // TODO: add error handling (port already set) here - if (its_ipv4_option->is_udp()) { + if (its_ipv4_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { its_unreliable_address = its_ipv4_address; its_unreliable_port = its_ipv4_option->get_port(); } else { @@ -582,20 +858,25 @@ void service_discovery_impl::process_eventgroupentry( break; } case option_type_e::IP6_ENDPOINT: { - if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { std::shared_ptr < ipv6_option_impl > its_ipv6_option = std::dynamic_pointer_cast < ipv6_option_impl > (its_option); boost::asio::ip::address_v6 its_ipv6_address( its_ipv6_option->get_address()); - + if (!check_layer_four_protocol(its_ipv6_option)) { + send_eventgroup_subscription_nack(its_service, + its_instance, its_eventgroup, its_major); + return; + } // TODO: add error handling (port already set) here - if (its_ipv6_option->is_udp()) { + if (its_ipv6_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { its_unreliable_address = its_ipv6_address; its_unreliable_port = its_ipv6_option->get_port(); } else { - its_unreliable_address = its_ipv6_address; + its_reliable_address = its_ipv6_address; its_reliable_port = its_ipv6_option->get_port(); } } else { @@ -605,8 +886,7 @@ void service_discovery_impl::process_eventgroupentry( break; } case option_type_e::IP4_MULTICAST: - if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK - == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == its_type) { std::shared_ptr < ipv4_option_impl > its_ipv4_option = std::dynamic_pointer_cast < ipv4_option_impl > (its_option); @@ -622,8 +902,7 @@ void service_discovery_impl::process_eventgroupentry( } break; case option_type_e::IP6_MULTICAST: - if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK - == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == its_type) { std::shared_ptr < ipv6_option_impl > its_ipv6_option = std::dynamic_pointer_cast < ipv6_option_impl > (its_option); @@ -638,8 +917,11 @@ void service_discovery_impl::process_eventgroupentry( << "Invalid eventgroup option (IPv6 Multicast)"; } break; + case option_type_e::UNKNOWN: default: VSOMEIP_WARNING << "Unsupported eventgroup option"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); break; } } @@ -648,7 +930,7 @@ void service_discovery_impl::process_eventgroupentry( if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { handle_eventgroup_subscription(its_service, its_instance, its_eventgroup, its_major, its_ttl, - (its_reliable_port != VSOMEIP_INVALID_PORT ? + (its_reliable_port != ILLEGAL_PORT ? its_reliable_address : its_unreliable_address), its_reliable_port, its_unreliable_port); } else { @@ -658,78 +940,6 @@ void service_discovery_impl::process_eventgroupentry( } } -void service_discovery_impl::handle_service_availability(service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable) { - - std::shared_ptr < runtime > its_runtime = runtime_.lock(); - if (!its_runtime) - return; - - if (0 < _ttl) { - host_->add_routing_info(_service, _instance, _major, _minor, _ttl, - _address, _port, _reliable); - - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - if (0 < found_instance->second.size()) { - std::shared_ptr < message_impl > its_message = - its_runtime->create_message(); - for (auto its_eventgroup : found_instance->second) { - for (auto its_client : its_eventgroup.second) { - std::shared_ptr < subscription - > its_subscription(its_client.second); - if (!its_subscription->is_acknowleged()) { - its_subscription->set_endpoint( - host_->find_or_create_remote_client(_service, - _instance, true, its_client.first), true); - its_subscription->set_endpoint( - host_->find_or_create_remote_client(_service, - _instance, false, its_client.first), false); - - // TODO: consume major & ttl - insert_subscription(its_message, _service, - _instance, its_eventgroup.first, - its_subscription); - } - } - - } - - if (0 < its_message->get_entries().size()) { - its_message->set_session(get_session(_address)); - serializer_->serialize(its_message.get()); - if (host_->send_to( - std::make_shared < endpoint_definition - > (_address, port_, reliable_), - serializer_->get_data(), - serializer_->get_size())) { - increment_session(_address); - } - serializer_->reset(); - } - } - } - } - } else { - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - for (auto &its_eventgroup : found_instance->second) { - for (auto its_client : its_eventgroup.second) { - its_client.second->set_acknowledged(false); - } - } - } - } - host_->del_routing_info(_service, _instance, _reliable); - } -} - void service_discovery_impl::handle_eventgroup_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, const boost::asio::ip::address &_address, @@ -746,51 +956,67 @@ void service_discovery_impl::handle_eventgroup_subscription(service_t _service, _service, _instance, _eventgroup); bool is_nack(false); - std::shared_ptr < endpoint_definition > its_subscriber; - std::shared_ptr < endpoint_definition > its_target; - - // Could not find eventgroup --> send Nack - if (!its_info || _major > its_info->get_major() - || _ttl > its_info->get_ttl()) { + std::shared_ptr < endpoint_definition > its_reliable_subscriber, + its_unreliable_subscriber; + std::shared_ptr < endpoint_definition > its_reliable_target, + its_unreliable_target; + + // Could not find eventgroup or wrong version + if (!its_info || _major != its_info->get_major()) { + // Create a temporary info object with TTL=0 --> send NACK its_info = std::make_shared < eventgroupinfo > (_major, 0); is_nack = true; + insert_subscription_nack(its_message, _service, _instance, _eventgroup, + its_info); + serialize_and_send(its_message, _address); + //TODO add check if required tcp connection is open + return; } else { boost::asio::ip::address its_target_address; uint16_t its_target_port; - if (VSOMEIP_INVALID_PORT != _unreliable_port) { - its_subscriber = std::make_shared < endpoint_definition - > (_address, _unreliable_port, false); + if (ILLEGAL_PORT != _unreliable_port) { + its_unreliable_subscriber = endpoint_definition::get( + _address, _unreliable_port, false); if (its_info->get_multicast(its_target_address, its_target_port)) { - its_target = std::make_shared < endpoint_definition - > (its_target_address, its_target_port, false); + its_unreliable_target = endpoint_definition::get( + its_target_address, its_target_port, false); } else { - its_target = its_subscriber; + its_unreliable_target = its_unreliable_subscriber; } - } else { - its_subscriber = std::make_shared < endpoint_definition - > (_address, _reliable_port, true); - its_target = its_subscriber; } + if (ILLEGAL_PORT != _reliable_port) { + its_reliable_subscriber = endpoint_definition::get( + _address, _reliable_port, true); + its_reliable_target = its_reliable_subscriber; + } + } + + if (_ttl == 0) { // --> unsubscribe + if (its_unreliable_target) { + host_->on_unsubscribe(_service, _instance, _eventgroup, its_unreliable_target); + } + if (its_reliable_target) { + host_->on_unsubscribe(_service, _instance, _eventgroup, its_reliable_target); + } + return; } insert_subscription_ack(its_message, _service, _instance, _eventgroup, - its_info); + its_info, _ttl); - its_message->set_session(get_session(_address)); - serializer_->serialize(its_message.get()); - if (host_->send_to( - std::make_shared < endpoint_definition - > (_address, port_, reliable_), serializer_->get_data(), - serializer_->get_size())) { - increment_session(_address); - } - serializer_->reset(); + serialize_and_send(its_message, _address); // Finally register the new subscriber and send him all the fields(!) if (!is_nack) { - host_->on_subscribe(_service, _instance, _eventgroup, - its_subscriber, its_target); + if (its_unreliable_target && its_unreliable_subscriber) { + host_->on_subscribe(_service, _instance, _eventgroup, + its_unreliable_subscriber, its_unreliable_target); + } + if (its_reliable_target && its_reliable_subscriber) { + host_->on_subscribe(_service, _instance, _eventgroup, + its_reliable_subscriber, its_reliable_target); + } } } } @@ -799,6 +1025,9 @@ void service_discovery_impl::handle_eventgroup_subscription_ack( service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port) { + (void)_major; + (void)_ttl; + auto found_service = subscribed_.find(_service); if (found_service != subscribed_.end()) { auto found_instance = found_service->second.find(_instance); @@ -818,5 +1047,96 @@ void service_discovery_impl::handle_eventgroup_subscription_ack( } } +void service_discovery_impl::serialize_and_send( + std::shared_ptr<message_impl> _message, + const boost::asio::ip::address &_address) { + _message->set_session(get_session(_address)); + if(!serializer_->serialize(_message.get())) { + VSOMEIP_ERROR << "service_discovery_impl::serialize_and_send: serialization error."; + return; + } + if (host_->send_to(endpoint_definition::get(_address, port_, reliable_), + serializer_->get_data(), serializer_->get_size())) { + increment_session(_address); + } + serializer_->reset(); +} + +void service_discovery_impl::start_ttl_timer() { + ttl_timer_.expires_from_now(std::chrono::seconds(smallest_ttl_)); + ttl_timer_.async_wait( + std::bind(&service_discovery_impl::check_ttl, shared_from_this(), + std::placeholders::_1)); +} + +ttl_t service_discovery_impl::stop_ttl_timer() { + ttl_t remaining = ttl_t(std::chrono::duration_cast< + std::chrono::seconds + >(ttl_timer_.expires_from_now()).count()); + ttl_timer_.cancel(); + return (smallest_ttl_ - remaining); +} + +void service_discovery_impl::check_ttl(const boost::system::error_code &_error) { + if (!_error) { + smallest_ttl_ = host_->update_routing_info(smallest_ttl_); + start_ttl_timer(); + } +} + +boost::asio::ip::address service_discovery_impl::get_current_remote_address() const { + if (reliable_) { + return std::static_pointer_cast<tcp_server_endpoint_impl>(endpoint_)->get_remote().address(); + } else { + return std::static_pointer_cast<udp_server_endpoint_impl>(endpoint_)->get_remote().address(); + } +} + +bool service_discovery_impl::check_static_header_fields( + const std::shared_ptr<const message> &_message) const { + if(_message->get_protocol_version() != protocol_version) { + VSOMEIP_ERROR << "Invalid protocol version in SD header"; + return false; + } + if(_message->get_interface_version() != interface_version) { + VSOMEIP_ERROR << "Invalid interface version in SD header"; + return false; + } + if(_message->get_message_type() != message_type) { + VSOMEIP_ERROR << "Invalid message type in SD header"; + return false; + } + return true; +} + +void service_discovery_impl::send_eventgroup_subscription_nack( + service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { + std::shared_ptr<runtime> its_runtime = runtime_.lock(); + if (!its_runtime) { + return; + } + std::shared_ptr<message_impl> its_message = its_runtime->create_message(); + if (its_message) { + std::shared_ptr<eventgroupinfo> its_info = host_->find_eventgroup( + _service, _instance, _eventgroup); + if(!its_info) { + // Create a temporary info object with TTL=0 + its_info = std::make_shared < eventgroupinfo > (_major, 0); + } + insert_subscription_nack(its_message, _service, _instance, _eventgroup, + its_info); + serialize_and_send(its_message, get_current_remote_address()); + } +} + +bool service_discovery_impl::check_layer_four_protocol( + const std::shared_ptr<const ip_option_impl> _ip_option) const { + if (_ip_option->get_layer_four_protocol() == layer_four_protocol_e::UNKNOWN) { + VSOMEIP_ERROR << "Invalid layer 4 protocol in IP endpoint option"; + return false; + } + return true; +} + } // namespace sd } // namespace vsomeip diff --git a/implementation/service_discovery/src/subscription.cpp b/implementation/service_discovery/src/subscription.cpp index 4b823be..76b9c9f 100644 --- a/implementation/service_discovery/src/subscription.cpp +++ b/implementation/service_discovery/src/subscription.cpp @@ -10,10 +10,10 @@ namespace sd { subscription::subscription(major_version_t _major, ttl_t _ttl, std::shared_ptr<endpoint> _reliable, - std::shared_ptr<endpoint> _unreliable, - client_t _target) - : major_(_major), ttl_(_ttl), reliable_(_reliable), unreliable_( - _unreliable), is_acknowledged_(false) { + std::shared_ptr<endpoint> _unreliable) + : major_(_major), ttl_(_ttl), + reliable_(_reliable), unreliable_(_unreliable), + is_acknowledged_(true) { } subscription::~subscription() { @@ -43,7 +43,7 @@ void subscription::set_endpoint(std::shared_ptr<endpoint> _endpoint, unreliable_ = _endpoint; } -bool subscription::is_acknowleged() const { +bool subscription::is_acknowledged() const { return is_acknowledged_; } diff --git a/implementation/utility/include/byteorder.hpp b/implementation/utility/include/byteorder.hpp index 55088f1..baea175 100644 --- a/implementation/utility/include/byteorder.hpp +++ b/implementation/utility/include/byteorder.hpp @@ -17,37 +17,37 @@ #if __BYTE_ORDER == __LITTLE_ENDIAN
-#define VSOMEIP_BYTES_TO_WORD(x0, x1) ((x0) << 8 | (x1))
-#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) ((x0) << 24 | (x1) << 16 | (x2) << 8 | (x3))
+#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x0) << 8 | (x1)))
+#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x0) << 24 | (x1) << 16 | (x2) << 8 | (x3)))
-#define VSOMEIP_WORDS_TO_LONG(x0, x1) ((x0) << 16 | (x1))
+#define VSOMEIP_WORDS_TO_LONG(x0, x1) (uint32_t((x0) << 16 | (x1)))
-#define VSOMEIP_WORD_BYTE0(x) ((x) & 0xFF)
-#define VSOMEIP_WORD_BYTE1(x) ((x) >> 8)
+#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) & 0xFF))
+#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) >> 8))
-#define VSOMEIP_LONG_BYTE0(x) ((x) & 0xFF)
-#define VSOMEIP_LONG_BYTE1(x) (((x) >> 8) & 0xFF)
-#define VSOMEIP_LONG_BYTE2(x) (((x) >> 16) & 0xFF)
-#define VSOMEIP_LONG_BYTE3(x) (((x) >> 24) & 0xFF)
+#define VSOMEIP_LONG_BYTE0(x) (uint8_t((x) & 0xFF))
+#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 8) & 0xFF))
+#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 16) & 0xFF))
+#define VSOMEIP_LONG_BYTE3(x) (uint8_t(((x) >> 24) & 0xFF))
-#define VSOMEIP_LONG_WORD0(x) ((x) & 0xFFFF)
-#define VSOMEIP_LONG_WORD1(x) (((x) >> 16) & 0xFFFF)
+#define VSOMEIP_LONG_WORD0(x) (uint16_t((x) & 0xFFFF))
+#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) >> 16) & 0xFFFF))
#elif __BYTE_ORDER == __BIG_ENDIAN
-#define VSOMEIP_BYTES_TO_WORD(x0, x1) ((x1) << 8 | (x0))
-#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) ((x3) << 24 | (x2) << 16 | (x1) << 8 | (x0))
+#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x1) << 8 | (x0)))
+#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x3) << 24 | (x2) << 16 | (x1) << 8 | (x0)))
-#define VSOMEIP_WORD_BYTE0(x) ((x) >> 8)
-#define VSOMEIP_WORD_BYTE1(x) ((x) & 0xFF)
+#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) >> 8))
+#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) & 0xFF))
-#define VSOMEIP_LONG_BYTE0(x) (((x) >> 24) & 0xFF)
-#define VSOMEIP_LONG_BYTE1(x) (((x) >> 16) & 0xFF)
-#define VSOMEIP_LONG_BYTE2(x) (((x) >> 8) & 0xFF)
-#define VSOMEIP_LONG_BYTE3(x) ((x) & 0xFF)
+#define VSOMEIP_LONG_BYTE0(x) (uint8_t(((x) >> 24) & 0xFF))
+#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 16) & 0xFF))
+#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 8) & 0xFF))
+#define VSOMEIP_LONG_BYTE3(x) (uint8_t((x) & 0xFF))
-#define VSOMEIP_LONG_WORD0(x) ((((x) >> 16) & 0xFFFF)
-#define VSOMEIP_LONG_WORD1(x) (((x) & 0xFFFF)
+#define VSOMEIP_LONG_WORD0(x) (uint16_t((((x) >> 16) & 0xFFFF))
+#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) & 0xFFFF))
#else
diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp index 000ca9b..a366075 100644 --- a/implementation/utility/include/utility.hpp +++ b/implementation/utility/include/utility.hpp @@ -61,7 +61,7 @@ public: static uint32_t get_message_size(const byte_t *_data, uint32_t _size); static inline uint32_t get_message_size(std::vector<byte_t> &_data) { if (_data.size() > 0) { - return (get_message_size(&_data[0], _data.size())); + return (get_message_size(&_data[0], uint32_t(_data.size()))); } return 0; } @@ -69,6 +69,17 @@ public: static uint32_t get_payload_size(const byte_t *_data, uint32_t _size); static bool exists(const std::string &_path); + static bool is_file(const std::string &_path); + static bool is_folder(const std::string &_path); + + static struct configuration_data_t *the_configuration_data__; + static bool auto_configuration_init(); + static void auto_configuration_exit(); + + static bool is_routing_manager_host__; + static bool is_routing_manager_host(); + + static client_t get_client_id(); }; } // namespace vsomeip diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp index 28eef27..e2cbde4 100644 --- a/implementation/utility/src/utility.cpp +++ b/implementation/utility/src/utility.cpp @@ -8,15 +8,21 @@ #include <iostream> #else #include <dlfcn.h> +#include <sys/mman.h> #endif #include <sys/stat.h> +#ifndef WIN32 +#include <fcntl.h> +#endif + #include <vsomeip/defines.hpp> -#include <vsomeip/logger.hpp> #include "../include/byteorder.hpp" #include "../include/utility.hpp" +#include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" namespace vsomeip { @@ -83,4 +89,84 @@ bool utility::exists(const std::string &_path) { return (stat(_path.c_str(), &its_stat) == 0); } +bool utility::is_file(const std::string &_path) { + struct stat its_stat; + if (stat(_path.c_str(), &its_stat) == 0) { + if (its_stat.st_mode & S_IFREG) + return true; + } + return false; +} + +bool utility::is_folder(const std::string &_path) { + struct stat its_stat; + if (stat(_path.c_str(), &its_stat) == 0) { + if (its_stat.st_mode & S_IFDIR) + return true; + } + return false; +} + +configuration_data_t *utility::the_configuration_data__(nullptr); +bool utility::is_routing_manager_host__(false); + +bool utility::auto_configuration_init() { +#ifndef WIN32 + int its_descriptor = shm_open(VSOMEIP_SHM_NAME, O_RDWR|O_CREAT|O_EXCL, 0660); + if (its_descriptor > -1) { + if (0 == ftruncate(its_descriptor, sizeof(configuration_data_t))) { + void *its_segment = mmap(0, sizeof(configuration_data_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + its_descriptor, 0); + the_configuration_data__ + = reinterpret_cast<configuration_data_t *>(its_segment); + if (the_configuration_data__ != nullptr) { + std::lock_guard<std::mutex> its_lock(the_configuration_data__->mutex_); + the_configuration_data__->ref_ = 0; + the_configuration_data__->next_client_id_ = (VSOMEIP_DIAGNOSIS_ADDRESS << 8); + is_routing_manager_host__ = true; + } + } else { + // TODO: an error message + } + } else { + its_descriptor = shm_open(VSOMEIP_SHM_NAME, O_RDWR, 0660); + if (its_descriptor > -1) { + void *its_segment = mmap(0, sizeof(configuration_data_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + its_descriptor, 0); + the_configuration_data__ + = reinterpret_cast<configuration_data_t *>(its_segment); + } else { + // TODO: an error message + } + } +#endif + return (the_configuration_data__ != nullptr); +} + +void utility::auto_configuration_exit() { +#ifndef WIN32 + if (the_configuration_data__) { + munmap(the_configuration_data__, sizeof(configuration_data_t)); + if (is_routing_manager_host__) { + shm_unlink(VSOMEIP_SHM_NAME); + } + } +#endif +} + +client_t utility::get_client_id() { + if (the_configuration_data__ != nullptr) { + std::lock_guard<std::mutex> its_lock(the_configuration_data__->mutex_); + the_configuration_data__->next_client_id_++; + return the_configuration_data__->next_client_id_; + } + return VSOMEIP_DIAGNOSIS_ADDRESS; +} + +bool utility::is_routing_manager_host() { + return is_routing_manager_host__; +} + } // namespace vsomeip |