diff options
Diffstat (limited to 'implementation/endpoints/include')
26 files changed, 966 insertions, 313 deletions
diff --git a/implementation/endpoints/include/buffer.hpp b/implementation/endpoints/include/buffer.hpp index af0582d..089a526 100644 --- a/implementation/endpoints/include/buffer.hpp +++ b/implementation/endpoints/include/buffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -11,13 +11,18 @@ #include <memory> #include <set> -#include <boost/asio/io_service.hpp> +#if VSOMEIP_BOOST_VERSION < 106600 +# include <boost/asio/io_service.hpp> +#define io_context io_service +#else +# include <boost/asio/io_context.hpp> +#endif #include <boost/asio/steady_timer.hpp> #include <vsomeip/defines.hpp> #include <vsomeip/primitive_types.hpp> -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_MSVC_LANG) #define DEFAULT_NANOSECONDS_MAX 1000000000 #else #define DEFAULT_NANOSECONDS_MAX std::chrono::nanoseconds::max() @@ -25,37 +30,41 @@ namespace vsomeip_v3 { -typedef std::vector<byte_t> message_buffer_t; -typedef std::shared_ptr<message_buffer_t> message_buffer_ptr_t; +using message_buffer_t = std::vector<byte_t>; +using message_buffer_ptr_t = std::shared_ptr<message_buffer_t>; +#if 0 struct timing { timing() : debouncing_(0), maximum_retention_(DEFAULT_NANOSECONDS_MAX) {}; std::chrono::nanoseconds debouncing_; std::chrono::nanoseconds maximum_retention_; }; +#endif struct train { - train(boost::asio::io_service& _io) : buffer_(std::make_shared<message_buffer_t>()), - departure_(DEFAULT_NANOSECONDS_MAX), - minimal_debounce_time_(DEFAULT_NANOSECONDS_MAX), - minimal_max_retention_time_(DEFAULT_NANOSECONDS_MAX), - last_departure_(std::chrono::steady_clock::now() - std::chrono::hours(1)), - departure_timer_(std::make_shared<boost::asio::steady_timer>(_io)) {}; + train() + : buffer_(std::make_shared<message_buffer_t>()), + minimal_debounce_time_(DEFAULT_NANOSECONDS_MAX), + minimal_max_retention_time_(DEFAULT_NANOSECONDS_MAX), + departure_(std::chrono::steady_clock::now() + std::chrono::hours(6)) { + }; + + void reset() { + buffer_ = std::make_shared<message_buffer_t>(); + passengers_.clear(); + minimal_debounce_time_ = DEFAULT_NANOSECONDS_MAX; + minimal_max_retention_time_ = DEFAULT_NANOSECONDS_MAX; + departure_ = std::chrono::steady_clock::now() + std::chrono::hours(6); + } message_buffer_ptr_t buffer_; - std::chrono::nanoseconds departure_; + std::set<std::pair<service_t, method_t> > passengers_; + std::chrono::nanoseconds minimal_debounce_time_; std::chrono::nanoseconds minimal_max_retention_time_; - std::chrono::steady_clock::time_point last_departure_; - std::shared_ptr<boost::asio::steady_timer> departure_timer_; - std::set<std::pair<service_t, method_t> > passengers_; - void update_departure_time_and_stop_departure() { - departure_ = departure_timer_->expires_from_now(); - boost::system::error_code ec; - departure_timer_->cancel(ec); - } + std::chrono::steady_clock::time_point departure_; }; diff --git a/implementation/endpoints/include/client_endpoint.hpp b/implementation/endpoints/include/client_endpoint.hpp index 3429a92..372a122 100644 --- a/implementation/endpoints/include/client_endpoint.hpp +++ b/implementation/endpoints/include/client_endpoint.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -12,12 +12,7 @@ namespace vsomeip_v3 { class client_endpoint : public virtual endpoint { public: - virtual ~client_endpoint() -#ifndef ANDROID - {} -#else - ; -#endif + virtual ~client_endpoint() {} virtual bool get_remote_address(boost::asio::ip::address &_address) const = 0; virtual std::uint16_t get_remote_port() const = 0; diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp index 518e696..f7e7567 100644 --- a/implementation/endpoints/include/client_endpoint_impl.hpp +++ b/implementation/endpoints/include/client_endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -6,15 +6,15 @@ #ifndef VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_ #define VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_ +#include <atomic> #include <condition_variable> #include <deque> #include <mutex> #include <vector> -#include <atomic> #include <chrono> +#include <thread> #include <boost/array.hpp> -#include <boost/asio/io_service.hpp> #include <boost/asio/strand.hpp> #include <boost/asio/ip/udp.hpp> #include <boost/utility.hpp> @@ -35,13 +35,13 @@ template<typename Protocol> class client_endpoint_impl: public endpoint_impl<Protocol>, public client_endpoint, public std::enable_shared_from_this<client_endpoint_impl<Protocol> > { public: - typedef typename Protocol::endpoint endpoint_type; - typedef typename Protocol::socket socket_type; + using endpoint_type = typename Protocol::endpoint; + using socket_type = typename Protocol::socket; client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, const std::shared_ptr<routing_host>& _routing_host, const endpoint_type& _local, const endpoint_type& _remote, - boost::asio::io_service &_io, + boost::asio::io_context &_io, std::uint32_t _max_message_size, configuration::endpoint_queue_limit_t _queue_limit, const std::shared_ptr<configuration>& _configuration); @@ -56,7 +56,7 @@ public: const byte_t *_data, uint32_t _size); bool flush(); - void prepare_stop(endpoint::prepare_stop_handler_t _handler, service_t _service); + void prepare_stop(const endpoint::prepare_stop_handler_t &_handler, service_t _service); virtual void stop(); virtual void restart(bool _force = false) = 0; @@ -78,6 +78,7 @@ public: public: void connect_cbk(boost::system::error_code const &_error); void wait_connect_cbk(boost::system::error_code const &_error); + void wait_connecting_cbk(boost::system::error_code const &_error); virtual void send_cbk(boost::system::error_code const &_error, std::size_t _bytes, const message_buffer_ptr_t& _sent_msg); void flush_cbk(boost::system::error_code const &_error); @@ -94,8 +95,8 @@ protected: CONNECTED, ESTABLISHED }; - message_buffer_ptr_t get_front(); - virtual void send_queued(message_buffer_ptr_t _buffer) = 0; + std::pair<message_buffer_ptr_t, uint32_t> get_front(); + virtual void send_queued(std::pair<message_buffer_ptr_t, uint32_t> &_entry) = 0; virtual void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, @@ -103,10 +104,13 @@ protected: void shutdown_and_close_socket(bool _recreate_socket); void shutdown_and_close_socket_unlocked(bool _recreate_socket); void start_connect_timer(); + void start_connecting_timer(); typename endpoint_impl<Protocol>::cms_ret_e check_message_size( const std::uint8_t * const _data, std::uint32_t _size); bool check_queue_limit(const uint8_t *_data, std::uint32_t _size) const; - void queue_train(bool _queue_size_zero_on_entry); + void queue_train(const std::shared_ptr<train> &_train, + bool _queue_size_zero_on_entry); + void update_last_departure(); protected: mutable std::mutex socket_mutex_; @@ -121,10 +125,20 @@ protected: std::atomic<cei_state_e> state_; std::atomic<std::uint32_t> reconnect_counter_; - // send data - train train_; + std::mutex connecting_timer_mutex_; + boost::asio::steady_timer connecting_timer_; + std::atomic<uint32_t> connecting_timeout_; + - std::deque<message_buffer_ptr_t> queue_; + // send data + std::shared_ptr<train> train_; + std::map<std::chrono::steady_clock::time_point, + std::deque<std::shared_ptr<train> > > dispatched_trains_; + boost::asio::steady_timer dispatch_timer_; + std::chrono::steady_clock::time_point last_departure_; + std::atomic<bool> has_last_departure_; + + std::deque<std::pair<message_buffer_ptr_t, uint32_t> > queue_; std::size_t queue_size_; mutable std::mutex mutex_; @@ -133,7 +147,7 @@ protected: std::atomic<std::uint16_t> local_port_; - boost::asio::io_service::strand strand_; + boost::asio::io_context::strand strand_; private: virtual void set_local_port() = 0; @@ -142,8 +156,13 @@ private: method_t _method) const = 0; virtual std::uint32_t get_max_allowed_reconnects() const = 0; virtual void max_allowed_reconnects_reached() = 0; - void send_segments(const tp::tp_split_messages_t &_segments); - void wait_until_debounce_time_reached() const; + void send_segments(const tp::tp_split_messages_t &_segments, + std::uint32_t _separation_time); + + void schedule_train(); + + void start_dispatch_timer(const std::chrono::steady_clock::time_point &_now); + void cancel_dispatch_timer(); }; } // namespace vsomeip_v3 diff --git a/implementation/endpoints/include/credentials.hpp b/implementation/endpoints/include/credentials.hpp index 2fe9060..bb4ee44 100644 --- a/implementation/endpoints/include/credentials.hpp +++ b/implementation/endpoints/include/credentials.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -6,6 +6,10 @@ #ifndef VSOMEIP_V3_ENDPOINTS_INCLUDE_CREDENTIALS_HPP_ #define VSOMEIP_V3_ENDPOINTS_INCLUDE_CREDENTIALS_HPP_ +#include <tuple> + +#include <boost/optional.hpp> + #include <vsomeip/primitive_types.hpp> namespace vsomeip_v3 { @@ -16,9 +20,10 @@ public: static void deactivate_credentials(const int _fd); - static client_t receive_credentials(const int _fd, uid_t& _uid, gid_t& _gid); + using received_t = std::tuple<client_t, uid_t, gid_t, std::string>; + static boost::optional<received_t> receive_credentials(const int _fd); - static void send_credentials(const int _fd, client_t _client); + static void send_credentials(const int _fd, client_t _client, std::string _client_host); }; } // namespace vsomeip_v3 diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp index 3eafc3a..f3a76b7 100644 --- a/implementation/endpoints/include/endpoint.hpp +++ b/implementation/endpoints/include/endpoint.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -19,18 +19,13 @@ class endpoint_definition; class endpoint { public: - typedef std::function<void()> error_handler_t; - typedef std::function<void(const std::shared_ptr<endpoint>&, service_t)> prepare_stop_handler_t; + using error_handler_t = std::function<void()>; + using prepare_stop_handler_t = std::function<void(const std::shared_ptr<endpoint>&, service_t)>; - virtual ~endpoint() -#ifndef ANDROID - {} -#else - ; -#endif + virtual ~endpoint() {} virtual void start() = 0; - virtual void prepare_stop(prepare_stop_handler_t _handler, + virtual void prepare_stop(const prepare_stop_handler_t &_handler, service_t _service = ANY_SERVICE) = 0; virtual void stop() = 0; @@ -38,8 +33,6 @@ public: virtual bool is_established_or_connected() const = 0; virtual bool send(const byte_t *_data, uint32_t _size) = 0; - virtual bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data, - uint32_t _size) = 0; virtual bool send_to(const std::shared_ptr<endpoint_definition> _target, const byte_t *_data, uint32_t _size) = 0; virtual bool send_error(const std::shared_ptr<endpoint_definition> _target, @@ -62,7 +55,7 @@ public: virtual void restart(bool _force = false) = 0; - virtual void register_error_handler(error_handler_t _error) = 0; + virtual void register_error_handler(const error_handler_t &_error) = 0; virtual void print_status() = 0; virtual size_t get_queue_size() const = 0; diff --git a/implementation/endpoints/include/endpoint_definition.hpp b/implementation/endpoints/include/endpoint_definition.hpp index 5a7e9eb..2dca226 100644 --- a/implementation/endpoints/include/endpoint_definition.hpp +++ b/implementation/endpoints/include/endpoint_definition.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/implementation/endpoints/include/endpoint_host.hpp b/implementation/endpoints/include/endpoint_host.hpp index 2af1697..e5ca6d1 100644 --- a/implementation/endpoints/include/endpoint_host.hpp +++ b/implementation/endpoints/include/endpoint_host.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -23,19 +23,31 @@ namespace vsomeip_v3 { class configuration; class endpoint; +struct multicast_option_t { + std::shared_ptr<endpoint> endpoint_; + bool is_join_; + boost::asio::ip::address address_; +}; + class endpoint_host { public: virtual ~endpoint_host() = default; virtual void on_connect(std::shared_ptr<endpoint> _endpoint) = 0; virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0; - virtual bool on_bind_error(std::shared_ptr<endpoint> _endpoint, uint16_t _remote_port) = 0; + virtual bool on_bind_error(std::shared_ptr<endpoint> _endpoint, + const boost::asio::ip::address &_remote_address, + uint16_t _remote_port) = 0; virtual void on_error(const byte_t *_data, length_t _length, - endpoint* const _receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port) = 0; + endpoint* const _receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) = 0; virtual void release_port(uint16_t _port, bool _reliable) = 0; virtual client_t get_client() const = 0; + virtual std::string get_client_host() const = 0; + virtual instance_t find_instance(service_t _service, + endpoint * const _endpoint) const = 0; + virtual void add_multicast_option(const multicast_option_t &_option) = 0; }; } // namespace vsomeip_v3 diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp index 76f4698..730c290 100644 --- a/implementation/endpoints/include/endpoint_impl.hpp +++ b/implementation/endpoints/include/endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -11,7 +11,6 @@ #include <mutex> #include <atomic> -#include <boost/asio/io_service.hpp> #include <boost/asio/steady_timer.hpp> #include "buffer.hpp" @@ -26,12 +25,12 @@ class routing_host; template<typename Protocol> class endpoint_impl: public virtual endpoint { public: - typedef typename Protocol::endpoint endpoint_type; + using endpoint_type = typename Protocol::endpoint; endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, const std::shared_ptr<routing_host>& _routing_host, const endpoint_type& _local, - boost::asio::io_service &_io, + boost::asio::io_context &_io, std::uint32_t _max_message_size, configuration::endpoint_queue_limit_t _queue_limit, const std::shared_ptr<configuration>& _configuration); @@ -50,7 +49,7 @@ public: void decrement_use_count(); uint32_t get_use_count(); - void register_error_handler(error_handler_t _error_handler); + void register_error_handler(const error_handler_t &_error_handler); virtual void print_status() = 0; virtual size_t get_queue_size() const = 0; @@ -63,6 +62,7 @@ public: protected: uint32_t find_magic_cookie(byte_t *_buffer, size_t _size); + instance_t get_instance(service_t _service); protected: enum class cms_ret_e : uint8_t { @@ -72,7 +72,7 @@ protected: }; // Reference to service context - boost::asio::io_service &service_; + boost::asio::io_context &io_; // References to hosts std::weak_ptr<endpoint_host> endpoint_host_; diff --git a/implementation/endpoints/include/endpoint_manager_base.hpp b/implementation/endpoints/include/endpoint_manager_base.hpp index aa21269..fec39cc 100644 --- a/implementation/endpoints/include/endpoint_manager_base.hpp +++ b/implementation/endpoints/include/endpoint_manager_base.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -12,7 +12,12 @@ #include <unordered_set> #include <memory> -#include <boost/asio/io_service.hpp> +#if VSOMEIP_BOOST_VERSION < 106600 +# include <boost/asio/io_service.hpp> +# define io_context io_service +#else +# include <boost/asio/io_context.hpp> +#endif #include <vsomeip/primitive_types.hpp> @@ -23,7 +28,6 @@ namespace vsomeip_v3 { class routing_manager_base; class configuration; -class local_server_endpoint_impl; class routing_host; class endpoint_manager_base @@ -31,7 +35,7 @@ class endpoint_manager_base public endpoint_host { public: endpoint_manager_base(routing_manager_base* const _rm, - boost::asio::io_service& _io, + boost::asio::io_context &_io, const std::shared_ptr<configuration>& _configuration); virtual ~endpoint_manager_base() = default; @@ -44,23 +48,31 @@ public: std::unordered_set<client_t> get_connected_clients() const; - std::shared_ptr<local_server_endpoint_impl> create_local_server( + std::shared_ptr<endpoint> create_local_server( const std::shared_ptr<routing_host> &_routing_host); // endpoint_host interface virtual void on_connect(std::shared_ptr<endpoint> _endpoint); virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint); - virtual bool on_bind_error(std::shared_ptr<endpoint> _endpoint, uint16_t _remote_port); + virtual bool on_bind_error(std::shared_ptr<endpoint> _endpoint, + const boost::asio::ip::address &_remote_address, + uint16_t _remote_port); virtual void on_error(const byte_t *_data, length_t _length, - endpoint* const _receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port); + endpoint* const _receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); virtual void release_port(uint16_t _port, bool _reliable); client_t get_client() const; + std::string get_client_host() const; + instance_t find_instance(service_t _service, + endpoint* const _endpoint) const; // Statistics void log_client_states() const; + // Multicast options + void add_multicast_option(const multicast_option_t &_option); + protected: std::map<client_t, std::shared_ptr<endpoint>> get_local_endpoints() const; @@ -68,14 +80,23 @@ private: std::shared_ptr<endpoint> create_local_unlocked(client_t _client); std::shared_ptr<endpoint> find_local_unlocked(client_t _client); + bool get_local_server_port(port_t &_port, const std::set<port_t> &_used_ports) const; + protected: routing_manager_base* const rm_; - boost::asio::io_service& io_; + boost::asio::io_context &io_; std::shared_ptr<configuration> configuration_; + bool is_local_routing_; + port_t local_port_; // local (client) port when connecting to other + // vsomeip application via TCP + private: mutable std::mutex local_endpoint_mutex_; std::map<client_t, std::shared_ptr<endpoint> > local_endpoints_; + + mutable std::mutex create_local_server_endpoint_mutex_; + }; } // namespace vsomeip_v3 diff --git a/implementation/endpoints/include/endpoint_manager_impl.hpp b/implementation/endpoints/include/endpoint_manager_impl.hpp index 3354947..a354fb5 100644 --- a/implementation/endpoints/include/endpoint_manager_impl.hpp +++ b/implementation/endpoints/include/endpoint_manager_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -6,6 +6,10 @@ #ifndef VSOMEIP_V3_ENDPOINT_MANAGER_IMPL_HPP_ #define VSOMEIP_V3_ENDPOINT_MANAGER_IMPL_HPP_ +#include <condition_variable> +#include <queue> +#include <thread> + #include "../include/endpoint_manager_base.hpp" namespace vsomeip_v3 { @@ -15,9 +19,9 @@ class routing_host; class endpoint_manager_impl : public endpoint_manager_base { public: endpoint_manager_impl(routing_manager_base* const _rm, - boost::asio::io_service& _io, + boost::asio::io_context &_io, const std::shared_ptr<configuration>& _configuration); - ~endpoint_manager_impl() = default; + ~endpoint_manager_impl(); std::shared_ptr<endpoint> find_or_create_remote_client(service_t _service, instance_t _instance, @@ -66,9 +70,10 @@ public: void print_status() const; - std::shared_ptr<local_server_endpoint_impl> create_local_server( - bool* _is_socket_activated, - const std::shared_ptr<routing_host>& _routing_host); + bool create_routing_root( + std::shared_ptr<endpoint> &_root, + bool &_is_socket_activated, + const std::shared_ptr<routing_host> &_host); instance_t find_instance(service_t _service, endpoint* const _endpoint) const; @@ -83,17 +88,30 @@ public: void on_connect(std::shared_ptr<endpoint> _endpoint); void on_disconnect(std::shared_ptr<endpoint> _endpoint); bool on_bind_error(std::shared_ptr<endpoint> _endpoint, + const boost::asio::ip::address &_remote_address, std::uint16_t _remote_port); void on_error(const byte_t *_data, length_t _length, - endpoint* const _receiver, - const boost::asio::ip::address &_remote_address, - std::uint16_t _remote_port); - void release_port(uint16_t _port, bool _reliable); + endpoint* const _receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); + + void get_used_client_ports( + const boost::asio::ip::address &_remote_address, port_t _remote_port, + std::map<bool, std::set<port_t> > &_used_ports); + void request_used_client_port( + const boost::asio::ip::address &_remote_address, port_t _remote_port, + bool _reliable, port_t _local_port); + void release_used_client_port( + const boost::asio::ip::address &_remote_address, port_t _remote_port, + bool _reliable, port_t _local_port); // Statistics void log_client_states() const; void log_server_states() const; + // add join/leave options + void add_multicast_option(const multicast_option_t &_option); + private: std::shared_ptr<endpoint> find_remote_client(service_t _service, instance_t _instance, @@ -105,40 +123,49 @@ private: const boost::asio::ip::address &_address, uint16_t _local_port, uint16_t _remote_port, bool _reliable); + // process join/leave options + void process_multicast_options(); + private: mutable std::recursive_mutex endpoint_mutex_; // Client endpoints for remote services std::map<service_t, std::map<instance_t, std::map<bool, std::shared_ptr<endpoint_definition>>>> remote_service_info_; - typedef std::map<service_t, std::map<instance_t, - std::map<bool, std::shared_ptr<endpoint>>>> remote_services_t; + using remote_services_t = + std::map<service_t, std::map<instance_t, std::map<bool, std::shared_ptr<endpoint>>>>; remote_services_t remote_services_; - typedef std::map<boost::asio::ip::address, - std::map<uint16_t, - std::map<bool, - std::map<partition_id_t, - std::shared_ptr<endpoint> - > - > - > - > client_endpoints_by_ip_t; + using client_endpoints_by_ip_t = + std::map<boost::asio::ip::address, + std::map<std::uint16_t, + std::map<bool, std::map<partition_id_t, std::shared_ptr<endpoint>>>>>; client_endpoints_by_ip_t client_endpoints_by_ip_; std::map<service_t, std::map<endpoint *, instance_t> > service_instances_; std::map<service_t, std::map<boost::asio::ip::address, instance_t> > service_instances_multicast_; - std::map<bool, std::set<uint16_t>> used_client_ports_; + std::map<boost::asio::ip::address, + std::map<port_t, + std::map<bool, std::set<port_t> > + > + > used_client_ports_; std::mutex used_client_ports_mutex_; // Server endpoints for local services - typedef std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint>>> server_endpoints_t; + using server_endpoints_t = std::map<std::uint16_t, std::map<bool, std::shared_ptr<endpoint>>>; server_endpoints_t server_endpoints_; // Multicast endpoint info (notifications) std::map<service_t, std::map<instance_t, std::shared_ptr<endpoint_definition>>> multicast_info; + + // Socket option processing (join, leave) + std::mutex options_mutex_; + bool is_processing_options_; + std::condition_variable options_condition_; + std::queue<multicast_option_t> options_queue_; + std::thread options_thread_; }; } // namespace vsomeip_v3 diff --git a/implementation/endpoints/include/local_server_endpoint_impl_receive_op.hpp b/implementation/endpoints/include/local_server_endpoint_impl_receive_op.hpp new file mode 100644 index 0000000..38e1662 --- /dev/null +++ b/implementation/endpoints/include/local_server_endpoint_impl_receive_op.hpp @@ -0,0 +1,118 @@ +// Copyright (C) 2020-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_ +#define VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_ + +#if VSOMEIP_BOOST_VERSION >= 106600 +#if defined(__linux__) || defined(ANDROID) + +#include <boost/asio/local/stream_protocol.hpp> + +namespace vsomeip_v3 { + +using socket_type_t = boost::asio::local::stream_protocol::socket; +using receive_handler_t = std::function< + void (boost::system::error_code const &_error, size_t _size, + const std::uint32_t &, const std::uint32_t &)>; + +struct local_server_endpoint_impl_receive_op { + + socket_type_t &socket_; + receive_handler_t handler_; + byte_t *buffer_; + size_t length_; + uid_t uid_; + gid_t gid_; + size_t bytes_; + + void operator()(boost::system::error_code _error) { + + if (!_error) { + if (!socket_.native_non_blocking()) + socket_.native_non_blocking(true, _error); + + for (;;) { + ssize_t its_result; + int its_flags(0); + + // Set buffer + struct iovec its_vec[1]; + its_vec[0].iov_base = buffer_; + its_vec[0].iov_len = length_; + + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(struct ucred))]; + } control_un; + + // Set 'control_un' to describe ancillary data that we want to receive + control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); + control_un.cmh.cmsg_level = SOL_SOCKET; + control_un.cmh.cmsg_type = SCM_CREDENTIALS; + + // Build header with all informations to call ::recvmsg + msghdr its_header = msghdr(); + its_header.msg_iov = its_vec; + its_header.msg_iovlen = 1; + its_header.msg_control = control_un.control; + its_header.msg_controllen = sizeof(control_un.control); + + // Call recvmsg and handle its result + errno = 0; + its_result = ::recvmsg(socket_.native_handle(), &its_header, its_flags); + _error = boost::system::error_code(its_result < 0 ? errno : 0, + boost::asio::error::get_system_category()); + bytes_ += _error ? 0 : static_cast<size_t>(its_result); + + if (_error == boost::asio::error::interrupted) + continue; + + if (_error == boost::asio::error::would_block + || _error == boost::asio::error::try_again) { + socket_.async_wait(socket_type_t::wait_read, *this); + return; + } + + if (_error) + break; + + if (bytes_ == 0) + _error = boost::asio::error::eof; + + // Extract credentials (UID/GID) + struct ucred *its_credentials; + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&its_header); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&its_header, cmsg)) + { + if (cmsg->cmsg_level == SOL_SOCKET + && cmsg->cmsg_type == SCM_CREDENTIALS + && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + + its_credentials = (struct ucred *) CMSG_DATA(cmsg); + if (its_credentials) { + uid_ = its_credentials->uid; + gid_ = its_credentials->gid; + break; + } + } + } + + break; + } + } + + // Call the handler + handler_(_error, bytes_, uid_, gid_); + } +}; + +} // namespace vsomeip + +#endif // __linux__ || ANDROID +#endif // VSOMEIP_BOOST_VERSION >= 106600 + +#endif // VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_ diff --git a/implementation/endpoints/include/local_tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/local_tcp_client_endpoint_impl.hpp new file mode 100644 index 0000000..45b6e72 --- /dev/null +++ b/implementation/endpoints/include/local_tcp_client_endpoint_impl.hpp @@ -0,0 +1,74 @@ +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_V3_LOCAL_TCP_CLIENT_ENDPOINT_IMPL_HPP_ +#define VSOMEIP_V3_LOCAL_TCP_CLIENT_ENDPOINT_IMPL_HPP_ + +#include <boost/asio/ip/tcp.hpp> + +#include <vsomeip/defines.hpp> + +#include "client_endpoint_impl.hpp" + +namespace vsomeip_v3 { + +using local_tcp_client_endpoint_base_impl = client_endpoint_impl<boost::asio::ip::tcp>; + +class local_tcp_client_endpoint_impl: public local_tcp_client_endpoint_base_impl { +public: + local_tcp_client_endpoint_impl(const std::shared_ptr<endpoint_host> &_endpoint_host, + const std::shared_ptr<routing_host> &_routing_host, + const endpoint_type &_local, + const endpoint_type &_remote, + boost::asio::io_context &_io, + const std::shared_ptr<configuration> &_configuration); + + virtual ~local_tcp_client_endpoint_impl(); + + void start(); + void stop(); + + bool is_local() const; + + bool get_remote_address(boost::asio::ip::address &_address) const; + std::uint16_t get_remote_port() const; + + void restart(bool _force); + void print_status(); + + bool is_reliable() const; + + // this overrides client_endpoint_impl::send to disable the pull method + // for local communication + bool send(const uint8_t *_data, uint32_t _size); + void get_configured_times_from_endpoint( + service_t _service, method_t _method, + std::chrono::nanoseconds *_debouncing, + std::chrono::nanoseconds *_maximum_retention) const; +private: + void send_queued(std::pair<message_buffer_ptr_t, uint32_t> &_entry); + + void send_magic_cookie(); + + void connect(); + void receive(); + void receive_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + void set_local_port(); + std::string get_remote_information() const; + bool check_packetizer_space(std::uint32_t _size); + bool tp_segmentation_enabled(service_t _service, method_t _method) const; + std::uint32_t get_max_allowed_reconnects() const; + void max_allowed_reconnects_reached(); + + message_buffer_t recv_buffer_; + + // send data + message_buffer_ptr_t send_data_buffer_; +}; + +} // namespace vsomeip_v3 + +#endif // VSOMEIP_V3_LOCAL_TCP_CLIENT_ENDPOINT_IMPL_HPP_ diff --git a/implementation/endpoints/include/local_tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/local_tcp_server_endpoint_impl.hpp new file mode 100644 index 0000000..d4b27c3 --- /dev/null +++ b/implementation/endpoints/include/local_tcp_server_endpoint_impl.hpp @@ -0,0 +1,166 @@ +// Copyright (C) 2014-2022 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_V3_LOCAL_TCP_SERVER_ENDPOINT_IMPL_HPP_ +#define VSOMEIP_V3_LOCAL_TCP_SERVER_ENDPOINT_IMPL_HPP_ + +#include <map> +#include <thread> +#include <condition_variable> +#include <memory> + +#include <boost/asio/ip/tcp.hpp> + +#include <vsomeip/defines.hpp> + +#include "buffer.hpp" +#include "server_endpoint_impl.hpp" + +namespace vsomeip_v3 { + +using local_tcp_server_endpoint_base_impl = server_endpoint_impl<boost::asio::ip::tcp>; + +class local_tcp_server_endpoint_impl + : public local_tcp_server_endpoint_base_impl { + +public: + local_tcp_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, + const std::shared_ptr<routing_host>& _routing_host, + const endpoint_type& _local, + boost::asio::io_context &_io, + const std::shared_ptr<configuration>& _configuration, + bool _is_routing_endpoint); + + virtual ~local_tcp_server_endpoint_impl(); + + void start(); + void stop(); + + void receive(); + + // this overrides server_endpoint_impl::send to disable the nPDU feature + // for local communication + bool send(const uint8_t *_data, uint32_t _size); + bool send_to(const std::shared_ptr<endpoint_definition>, + const byte_t *_data, uint32_t _size); + bool send_error(const std::shared_ptr<endpoint_definition> _target, + const byte_t *_data, uint32_t _size); + bool send_queued(const target_data_iterator_type _queue_iterator); + void get_configured_times_from_endpoint( + service_t _service, method_t _method, + std::chrono::nanoseconds *_debouncing, + std::chrono::nanoseconds *_maximum_retention) const; + + bool get_default_target(service_t, endpoint_type &) const; + + bool is_local() const; + + void accept_client_func(); + void print_status(); + + bool is_reliable() const; + std::uint16_t get_local_port() const; + void set_local_port(std::uint16_t _port); + + client_t assign_client(const byte_t *_data, uint32_t _size); + +private: + class connection: public std::enable_shared_from_this<connection> { + + public: + using ptr = std::shared_ptr<connection>; + + static ptr create(const std::shared_ptr<local_tcp_server_endpoint_impl>& _server, + std::uint32_t _max_message_size, + std::uint32_t _buffer_shrink_threshold, + boost::asio::io_context &_io); + socket_type & get_socket(); + std::unique_lock<std::mutex> get_socket_lock(); + + void start(); + void stop(); + + + void send_queued(const message_buffer_ptr_t& _buffer); + + void set_bound_client(client_t _client); + client_t get_bound_client() const; + + void set_bound_client_host(const std::string &_bound_client_host); + std::string get_bound_client_host() const; + + std::size_t get_recv_buffer_capacity() const; + + private: + connection(const std::shared_ptr<local_tcp_server_endpoint_impl>& _server, + std::uint32_t _max_message_size, + std::uint32_t _initial_recv_buffer_size, + std::uint32_t _buffer_shrink_threshold, + boost::asio::io_context &_io); + + void send_cbk(const message_buffer_ptr_t _buffer, + boost::system::error_code const &_error, std::size_t _bytes); + void receive_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + void calculate_shrink_count(); + std::string get_path_local() const; + std::string get_path_remote() const; + void handle_recv_buffer_exception(const std::exception &_e); + + std::mutex socket_mutex_; + local_tcp_server_endpoint_impl::socket_type socket_; + std::weak_ptr<local_tcp_server_endpoint_impl> server_; + + const std::uint32_t recv_buffer_size_initial_; + const std::uint32_t max_message_size_; + + message_buffer_t recv_buffer_; + size_t recv_buffer_size_; + std::uint32_t missing_capacity_; + std::uint32_t shrink_count_; + const std::uint32_t buffer_shrink_threshold_; + + client_t bound_client_; + std::string bound_client_host_; + + vsomeip_sec_client_t sec_client_; + + bool assigned_client_; + }; + + std::mutex acceptor_mutex_; + boost::asio::ip::tcp::acceptor acceptor_; + + using connections_t = std::map<client_t, connection::ptr>; + std::mutex connections_mutex_; + connections_t connections_; + + const std::uint32_t buffer_shrink_threshold_; + + port_t local_port_; + + const bool is_routing_endpoint_; + +private: + bool add_connection(const client_t &_client, + const std::shared_ptr<connection> &_connection); + void remove_connection(const client_t &_client); + void accept_cbk(const connection::ptr& _connection, + boost::system::error_code const &_error); + std::string get_remote_information( + const target_data_iterator_type _queue_iterator) const; + std::string get_remote_information( + const endpoint_type& _remote) const; + + bool check_packetizer_space(target_data_iterator_type _queue_iterator, + message_buffer_ptr_t* _packetizer, + std::uint32_t _size); + bool tp_segmentation_enabled(service_t _service, method_t _method) const; + void send_client_identifier(const client_t &_client); +}; + +} // namespace vsomeip_v3 + +#endif // VSOMEIP_V3_LOCAL_TCP_SERVER_ENDPOINT_IMPL_HPP_ diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_uds_client_endpoint_impl.hpp index 3eae191..74ba316 100644 --- a/implementation/endpoints/include/local_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_uds_client_endpoint_impl.hpp @@ -1,43 +1,30 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2022 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef VSOMEIP_V3_LOCAL_CLIENT_ENDPOINT_IMPL_HPP_ -#define VSOMEIP_V3_LOCAL_CLIENT_ENDPOINT_IMPL_HPP_ +#ifndef VSOMEIP_V3_LOCAL_UDS_CLIENT_ENDPOINT_IMPL_HPP_ +#define VSOMEIP_V3_LOCAL_UDS_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_v3 { -#ifdef _WIN32 -typedef client_endpoint_impl< - boost::asio::ip::tcp - > local_client_endpoint_base_impl; -#else -typedef client_endpoint_impl< - boost::asio::local::stream_protocol - > local_client_endpoint_base_impl; -#endif - -class local_client_endpoint_impl: public local_client_endpoint_base_impl { -public: - local_client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, - const std::shared_ptr<routing_host>& _routing_host, - const endpoint_type& _remote, - boost::asio::io_service &_io, - const std::shared_ptr<configuration>& _configuration); +using local_uds_client_endpoint_base_impl = + client_endpoint_impl<boost::asio::local::stream_protocol>; - virtual ~local_client_endpoint_impl(); +class local_uds_client_endpoint_impl: public local_uds_client_endpoint_base_impl { +public: + local_uds_client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, + const std::shared_ptr<routing_host>& _routing_host, + const endpoint_type& _remote, + boost::asio::io_context &_io, + const std::shared_ptr<configuration>& _configuration); + virtual ~local_uds_client_endpoint_impl(); void start(); void stop(); @@ -55,14 +42,12 @@ public: // this overrides client_endpoint_impl::send to disable the pull method // for local communication bool send(const uint8_t *_data, uint32_t _size); - bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data, - uint32_t _size); void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, std::chrono::nanoseconds *_maximum_retention) const; private: - void send_queued(message_buffer_ptr_t _buffer); + void send_queued(std::pair<message_buffer_ptr_t, uint32_t> &_entry); void send_magic_cookie(); @@ -85,4 +70,4 @@ private: } // namespace vsomeip_v3 -#endif // VSOMEIP_V3_LOCAL_CLIENT_ENDPOINT_IMPL_HPP_ +#endif // VSOMEIP_V3_LOCAL_UDS_CLIENT_ENDPOINT_IMPL_HPP_ diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_uds_server_endpoint_impl.hpp index 8fbb619..256d866 100644 --- a/implementation/endpoints/include/local_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_uds_server_endpoint_impl.hpp @@ -1,60 +1,56 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2022 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_ -#define VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_ +#ifndef VSOMEIP_V3_LOCAL_UDS_SERVER_ENDPOINT_IMPL_HPP_ +#define VSOMEIP_V3_LOCAL_UDS_SERVER_ENDPOINT_IMPL_HPP_ #include <map> #include <thread> #include <condition_variable> #include <memory> -#include <boost/asio/io_service.hpp> -#include <boost/asio/local/stream_protocol_ext.hpp> - - -#ifdef _WIN32 -#include <boost/asio/ip/tcp.hpp> +#if VSOMEIP_BOOST_VERSION < 106600 +# include <boost/asio/local/stream_protocol_ext.hpp> +#else +# include <boost/asio/local/stream_protocol.hpp> #endif #include <vsomeip/defines.hpp> +#include <vsomeip/vsomeip_sec.h> #include "buffer.hpp" #include "server_endpoint_impl.hpp" namespace vsomeip_v3 { -#ifdef _WIN32 -typedef server_endpoint_impl< - boost::asio::ip::tcp - > local_server_endpoint_base_impl; +using local_uds_server_endpoint_base_impl = server_endpoint_impl< +#if VSOMEIP_BOOST_VERSION < 106600 + boost::asio::local::stream_protocol_ext #else -typedef server_endpoint_impl< - boost::asio::local::stream_protocol_ext - > local_server_endpoint_base_impl; + boost::asio::local::stream_protocol #endif + >; -class local_server_endpoint_impl: public local_server_endpoint_base_impl { - +class local_uds_server_endpoint_impl: public local_uds_server_endpoint_base_impl { public: - local_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, - const std::shared_ptr<routing_host>& _routing_host, - const endpoint_type& _local, - boost::asio::io_service &_io, - const std::shared_ptr<configuration>& _configuration, - bool _is_routing_endpoint); - - local_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, - const std::shared_ptr<routing_host>& _routing_host, - const endpoint_type& _local, - boost::asio::io_service &_io, - int native_socket, - const std::shared_ptr<configuration>& _configuration, - bool _is_routing_endpoint); - - virtual ~local_server_endpoint_impl(); + local_uds_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, + const std::shared_ptr<routing_host>& _routing_host, + const endpoint_type& _local, + boost::asio::io_context &_io, + const std::shared_ptr<configuration>& _configuration, + bool _is_routing_endpoint); + + local_uds_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, + const std::shared_ptr<routing_host>& _routing_host, + const endpoint_type& _local, + boost::asio::io_context &_io, + int native_socket, + const std::shared_ptr<configuration>& _configuration, + bool _is_routing_endpoint); + + virtual ~local_uds_server_endpoint_impl(); void start(); void stop(); @@ -68,7 +64,7 @@ public: const byte_t *_data, uint32_t _size); bool send_error(const std::shared_ptr<endpoint_definition> _target, const byte_t *_data, uint32_t _size); - void send_queued(const queue_iterator_type _queue_iterator); + bool send_queued(const target_data_iterator_type _queue_iterator); void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, @@ -91,52 +87,55 @@ private: class connection: public std::enable_shared_from_this<connection> { public: - typedef std::shared_ptr<connection> ptr; + using ptr = std::shared_ptr<connection>; - static ptr create(const std::shared_ptr<local_server_endpoint_impl>& _server, + static ptr create(const std::shared_ptr<local_uds_server_endpoint_impl>& _server, std::uint32_t _max_message_size, std::uint32_t _buffer_shrink_threshold, - boost::asio::io_service &_io_service); + boost::asio::io_context &_io); socket_type & get_socket(); std::unique_lock<std::mutex> get_socket_lock(); void start(); void stop(); - void send_queued(const message_buffer_ptr_t& _buffer); void set_bound_client(client_t _client); client_t get_bound_client() const; -#ifndef _WIN32 - void set_bound_uid_gid(uid_t _uid, gid_t _gid); + + void set_bound_client_host(const std::string &_bound_client_host); + std::string get_bound_client_host() const; + +#if defined(__linux__) || defined(ANDROID) + void set_bound_sec_client(const vsomeip_sec_client_t &_sec_client); #endif std::size_t get_recv_buffer_capacity() const; private: - connection(const std::shared_ptr<local_server_endpoint_impl>& _server, + connection(const std::shared_ptr<local_uds_server_endpoint_impl>& _server, std::uint32_t _max_message_size, std::uint32_t _initial_recv_buffer_size, std::uint32_t _buffer_shrink_threshold, - boost::asio::io_service &_io_service); + boost::asio::io_context &_io); void send_cbk(const message_buffer_ptr_t _buffer, boost::system::error_code const &_error, std::size_t _bytes); void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes -#ifndef _WIN32 +#if defined(__linux__) || defined(ANDROID) , std::uint32_t const &_uid, std::uint32_t const &_gid #endif ); void calculate_shrink_count(); - const std::string get_path_local() const; - const std::string get_path_remote() const; + std::string get_path_local() const; + std::string get_path_remote() const; void handle_recv_buffer_exception(const std::exception &_e); std::mutex socket_mutex_; - local_server_endpoint_impl::socket_type socket_; - std::weak_ptr<local_server_endpoint_impl> server_; + local_uds_server_endpoint_impl::socket_type socket_; + std::weak_ptr<local_uds_server_endpoint_impl> server_; const std::uint32_t recv_buffer_size_initial_; const std::uint32_t max_message_size_; @@ -148,21 +147,20 @@ private: const std::uint32_t buffer_shrink_threshold_; client_t bound_client_; -#ifndef _WIN32 - uid_t bound_uid_; - gid_t bound_gid_; -#endif + std::string bound_client_host_; + + vsomeip_sec_client_t sec_client_; + bool assigned_client_; }; std::mutex acceptor_mutex_; -#ifdef _WIN32 - boost::asio::ip::tcp::acceptor acceptor_; -#else +#if VSOMEIP_BOOST_VERSION < 106600 boost::asio::local::stream_protocol_ext::acceptor acceptor_; +#else + boost::asio::local::stream_protocol::acceptor acceptor_; #endif - - typedef std::map<client_t, connection::ptr> connections_t; + using connections_t = std::map<client_t, connection::ptr>; std::mutex connections_mutex_; connections_t connections_; @@ -177,11 +175,11 @@ private: void accept_cbk(const connection::ptr& _connection, boost::system::error_code const &_error); std::string get_remote_information( - const queue_iterator_type _queue_iterator) const; + const target_data_iterator_type _queue_iterator) const; std::string get_remote_information( const endpoint_type& _remote) const; - bool check_packetizer_space(queue_iterator_type _queue_iterator, + bool check_packetizer_space(target_data_iterator_type _queue_iterator, message_buffer_ptr_t* _packetizer, std::uint32_t _size); bool tp_segmentation_enabled(service_t _service, method_t _method) const; @@ -190,4 +188,4 @@ private: } // namespace vsomeip_v3 -#endif // VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_ +#endif // VSOMEIP_V3_LOCAL_UDS_SERVER_ENDPOINT_IMPL_HPP_ diff --git a/implementation/endpoints/include/netlink_connector.hpp b/implementation/endpoints/include/netlink_connector.hpp index bb484b8..0a7c94e 100644 --- a/implementation/endpoints/include/netlink_connector.hpp +++ b/implementation/endpoints/include/netlink_connector.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -6,7 +6,7 @@ #ifndef VSOMEIP_V3_NETLINK_CONNECTOR_HPP_ #define VSOMEIP_V3_NETLINK_CONNECTOR_HPP_ -#ifndef _WIN32 +#if defined(__linux__) || defined(ANDROID) #include <sys/socket.h> #include <linux/netlink.h> @@ -15,7 +15,6 @@ #include <map> #include <mutex> -#include <boost/asio/io_service.hpp> #include <boost/asio/basic_raw_socket.hpp> #include <boost/asio/ip/address.hpp> @@ -27,23 +26,23 @@ template <typename Protocol> class nl_endpoint { public: /// The protocol type associated with the endpoint. - typedef Protocol protocol_type; - typedef boost::asio::detail::socket_addr_type data_type; + using protocol_type = Protocol; + using data_type = boost::asio::detail::socket_addr_type; /// Default constructor. nl_endpoint() { sockaddr.nl_family = PF_NETLINK; sockaddr.nl_groups = 0; - sockaddr.nl_pid = static_cast<unsigned int>(getpid()); + sockaddr.nl_pid = 0; // Let the kernel do the assignment } /// Construct an endpoint using the specified path name. - nl_endpoint(int group, int pid=getpid()) + nl_endpoint(int group) { sockaddr.nl_family = PF_NETLINK; sockaddr.nl_groups = static_cast<unsigned int>(group); - sockaddr.nl_pid = static_cast<unsigned int>(pid); + sockaddr.nl_pid = 0; } /// Copy constructor. @@ -124,25 +123,31 @@ public: return PF_NETLINK; } - typedef nl_endpoint<nl_protocol> endpoint; - typedef boost::asio::basic_raw_socket<nl_protocol> socket; + using endpoint = nl_endpoint<nl_protocol>; + using socket = boost::asio::basic_raw_socket<nl_protocol>; private: int proto; }; -typedef std::function< void (bool, std::string, bool) > net_if_changed_handler_t; +using net_if_changed_handler_t = std::function< void ( + bool, // true = is interface, false = is route + std::string, // interface name + bool) // available? +>; class netlink_connector : public std::enable_shared_from_this<netlink_connector> { public: - netlink_connector(boost::asio::io_service& _io, boost::asio::ip::address _address, - boost::asio::ip::address _multicast_address): + netlink_connector(boost::asio::io_context &_io, const boost::asio::ip::address &_address, + const boost::asio::ip::address &_multicast_address, + bool _is_requiring_link = true): net_if_index_for_address_(0), handler_(nullptr), socket_(_io), recv_buffer_(recv_buffer_size, 0), address_(_address), - multicast_address_(_multicast_address) { + multicast_address_(_multicast_address), + is_requiring_link_(_is_requiring_link) { } ~netlink_connector() {} @@ -180,10 +185,11 @@ private: boost::asio::ip::address address_; boost::asio::ip::address multicast_address_; + bool is_requiring_link_; }; } // namespace vsomeip_v3 -#endif // NOT _WIN32 +#endif // __linux__ || ANDROID #endif // VSOMEIP_V3_NETLINK_CONNECTOR_HPP_ diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp index dfa22e6..b7ee74d 100644 --- a/implementation/endpoints/include/server_endpoint_impl.hpp +++ b/implementation/endpoints/include/server_endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -14,7 +14,6 @@ #include <vector> #include <boost/array.hpp> -#include <boost/asio/io_service.hpp> #include "buffer.hpp" #include "endpoint_impl.hpp" @@ -26,14 +25,33 @@ template<typename Protocol> class server_endpoint_impl: public endpoint_impl<Protocol>, public std::enable_shared_from_this<server_endpoint_impl<Protocol> > { public: - typedef typename Protocol::socket socket_type; - typedef typename Protocol::endpoint endpoint_type; - typedef typename std::map<endpoint_type, std::pair<size_t, std::deque<message_buffer_ptr_t>>> queue_type; - typedef typename queue_type::iterator queue_iterator_type; + using socket_type = typename Protocol::socket; + using endpoint_type = typename Protocol::endpoint; + struct endpoint_data_type { + endpoint_data_type(boost::asio::io_context &_io) + : train_(std::make_shared<train>()), + dispatch_timer_(std::make_shared<boost::asio::steady_timer>(_io)), + has_last_departure_(false), + queue_size_(0) { + } + + std::shared_ptr<train> train_; + std::map<std::chrono::steady_clock::time_point, + std::deque<std::shared_ptr<train> > > dispatched_trains_; + std::shared_ptr<boost::asio::steady_timer> dispatch_timer_; + std::chrono::steady_clock::time_point last_departure_; + bool has_last_departure_; + + std::deque<std::pair<message_buffer_ptr_t, uint32_t> > queue_; + std::size_t queue_size_; + }; + + using target_data_type = typename std::map<endpoint_type, endpoint_data_type>; + using target_data_iterator_type = typename target_data_type::iterator; server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, const std::shared_ptr<routing_host>& _routing_host, - endpoint_type _local, boost::asio::io_service &_io, + endpoint_type _local, boost::asio::io_context &_io, std::uint32_t _max_message_size, configuration::endpoint_queue_limit_t _queue_limit, const std::shared_ptr<configuration>& _configuration); @@ -49,11 +67,10 @@ public: bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data, uint32_t _size); - void prepare_stop(endpoint::prepare_stop_handler_t _handler, + void prepare_stop(const endpoint::prepare_stop_handler_t &_handler, service_t _service); virtual void stop(); - bool flush(endpoint_type _target, - const std::shared_ptr<train>& _train); + bool flush(target_data_iterator_type _it); size_t get_queue_size() const; @@ -63,16 +80,15 @@ public: public: void connect_cbk(boost::system::error_code const &_error); - void send_cbk(const queue_iterator_type _queue_iterator, + void send_cbk(const target_data_iterator_type _it, boost::system::error_code const &_error, std::size_t _bytes); - void flush_cbk(endpoint_type _target, - const std::shared_ptr<train>& _train, - const boost::system::error_code &_error_code); + void flush_cbk(target_data_iterator_type _it, + const boost::system::error_code &_error_code); protected: virtual bool send_intern(endpoint_type _target, const byte_t *_data, uint32_t _port); - virtual void send_queued(const queue_iterator_type _queue_iterator) = 0; + virtual bool send_queued(const target_data_iterator_type _it) = 0; virtual void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, @@ -85,26 +101,23 @@ protected: typename endpoint_impl<Protocol>::cms_ret_e check_message_size( const std::uint8_t * const _data, std::uint32_t _size, - const endpoint_type& _target); + const endpoint_type &_target); bool check_queue_limit(const uint8_t *_data, std::uint32_t _size, std::size_t _current_queue_size) const; - void queue_train(const queue_iterator_type _queue_iterator, - const std::shared_ptr<train>& _train, - bool _queue_size_zero_on_entry); - queue_iterator_type find_or_create_queue_unlocked(const endpoint_type& _target); - std::shared_ptr<train> find_or_create_train_unlocked(const endpoint_type& _target); + bool queue_train(const target_data_iterator_type _it, + const std::shared_ptr<train> &_train, + bool _queue_size_zero_on_entry); - void send_segments(const tp::tp_split_messages_t &_segments, const endpoint_type &_target); + void send_segments(const tp::tp_split_messages_t &_segments, + std::uint32_t _separation_time, const endpoint_type &_target); -protected: - queue_type queues_; + target_data_iterator_type find_or_create_target_unlocked(endpoint_type _target); - std::mutex requests_mutex_; - std::map<client_t, - std::map<std::tuple<session_t, service_t, instance_t>, endpoint_type> - > requests_; +protected: + std::mutex clients_mutex_; + std::map<client_t, std::map<session_t, endpoint_type> > clients_; - std::map<endpoint_type, std::shared_ptr<train>> trains_; + target_data_type targets_; std::map<service_t, endpoint::prepare_stop_handler_t> prepare_stop_handlers_; @@ -116,12 +129,18 @@ protected: private: virtual std::string get_remote_information( - const queue_iterator_type _queue_iterator) const = 0; + const target_data_iterator_type _queue_iterator) const = 0; virtual std::string get_remote_information( const endpoint_type& _remote) const = 0; virtual bool tp_segmentation_enabled(service_t _service, method_t _method) const = 0; - void wait_until_debounce_time_reached(const std::shared_ptr<train>& _train) const; + + void schedule_train(endpoint_data_type &_target); + void update_last_departure(endpoint_data_type &_data); + + void start_dispatch_timer(target_data_iterator_type _it, + const std::chrono::steady_clock::time_point &_now); + void cancel_dispatch_timer(target_data_iterator_type _it); }; } // namespace vsomeip_v3 diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp index 137571c..8a314bc 100644 --- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -16,9 +16,8 @@ namespace vsomeip_v3 { -typedef client_endpoint_impl< - boost::asio::ip::tcp - > tcp_client_endpoint_base_impl; +using tcp_client_endpoint_base_impl = + client_endpoint_impl<boost::asio::ip::tcp>; class tcp_client_endpoint_impl: public tcp_client_endpoint_base_impl { public: @@ -26,7 +25,7 @@ public: const std::shared_ptr<routing_host>& _routing_host, const endpoint_type& _local, const endpoint_type& _remote, - boost::asio::io_service &_io, + boost::asio::io_context &_io, const std::shared_ptr<configuration>& _configuration); virtual ~tcp_client_endpoint_impl(); @@ -42,7 +41,7 @@ public: void send_cbk(boost::system::error_code const &_error, std::size_t _bytes, const message_buffer_ptr_t& _sent_msg); private: - void send_queued(message_buffer_ptr_t _buffer); + void send_queued(std::pair<message_buffer_ptr_t, uint32_t> &_entry); void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, @@ -63,8 +62,8 @@ private: std::size_t _missing_capacity); void calculate_shrink_count(const message_buffer_ptr_t& _recv_buffer, std::size_t _recv_buffer_size); - const std::string get_address_port_remote() const; - const std::string get_address_port_local() const; + std::string get_address_port_remote() const; + std::string get_address_port_local() const; void handle_recv_buffer_exception(const std::exception &_e, const message_buffer_ptr_t& _recv_buffer, std::size_t _recv_buffer_size); diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp index bf0e1b9..1a2cf4e 100644 --- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -19,9 +19,8 @@ namespace vsomeip_v3 { -typedef server_endpoint_impl< - boost::asio::ip::tcp - > tcp_server_endpoint_base_impl; +using tcp_server_endpoint_base_impl = + server_endpoint_impl<boost::asio::ip::tcp>; class tcp_server_endpoint_impl: public tcp_server_endpoint_base_impl { @@ -29,7 +28,7 @@ public: tcp_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, const std::shared_ptr<routing_host>& _routing_host, const endpoint_type& _local, - boost::asio::io_service &_io, + boost::asio::io_context &_io, const std::shared_ptr<configuration>& _configuration); virtual ~tcp_server_endpoint_impl(); @@ -40,14 +39,14 @@ public: const byte_t *_data, uint32_t _size); bool send_error(const std::shared_ptr<endpoint_definition> _target, const byte_t *_data, uint32_t _size); - void send_queued(const queue_iterator_type _queue_iterator); - void send_queued_sync(const queue_iterator_type _queue_iterator); + bool send_queued(const target_data_iterator_type _it); + void send_queued_sync(const target_data_iterator_type _it); void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, std::chrono::nanoseconds *_maximum_retention) const; - VSOMEIP_EXPORT bool is_established(const std::shared_ptr<endpoint_definition>& _endpoint); + VSOMEIP_EXPORT bool is_established_to(const std::shared_ptr<endpoint_definition>& _endpoint); bool get_default_target(service_t, endpoint_type &) const; @@ -64,14 +63,17 @@ private: class connection: public std::enable_shared_from_this<connection> { public: - typedef std::shared_ptr<connection> ptr; + using ptr = std::shared_ptr<connection>; static ptr create(const std::weak_ptr<tcp_server_endpoint_impl>& _server, std::uint32_t _max_message_size, std::uint32_t _buffer_shrink_threshold, bool _magic_cookies_enabled, - boost::asio::io_service & _io_service, + boost::asio::io_context & _io, std::chrono::milliseconds _send_timeout); + + ~connection(); + socket_type & get_socket(); std::unique_lock<std::mutex> get_socket_lock(); @@ -79,11 +81,11 @@ private: void stop(); void receive(); - void send_queued(const queue_iterator_type _queue_iterator); - void send_queued_sync(const queue_iterator_type _queue_iterator); + void send_queued(const target_data_iterator_type _it); + void send_queued_sync(const target_data_iterator_type _it); void set_remote_info(const endpoint_type &_remote); - const std::string get_address_port_remote() const; + std::string get_address_port_remote() const; std::size_t get_recv_buffer_capacity() const; private: @@ -92,14 +94,14 @@ private: std::uint32_t _recv_buffer_size_initial, std::uint32_t _buffer_shrink_threshold, bool _magic_cookies_enabled, - boost::asio::io_service & _io_service, + boost::asio::io_context &_io, std::chrono::milliseconds _send_timeout); bool send_magic_cookie(message_buffer_ptr_t &_buffer); bool is_magic_cookie(size_t _offset) const; void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); void calculate_shrink_count(); - const std::string get_address_port_local() const; + std::string get_address_port_local() const; void handle_recv_buffer_exception(const std::exception &_e); std::size_t write_completion_condition( const boost::system::error_code& _error, @@ -134,7 +136,7 @@ private: std::mutex acceptor_mutex_; boost::asio::ip::tcp::acceptor acceptor_; std::mutex connections_mutex_; - typedef std::map<endpoint_type, connection::ptr> connections_t; + using connections_t = std::map<endpoint_type, connection::ptr>; connections_t connections_; const std::uint32_t buffer_shrink_threshold_; const std::uint16_t local_port_; @@ -145,7 +147,7 @@ private: void accept_cbk(const connection::ptr& _connection, boost::system::error_code const &_error); std::string get_remote_information( - const queue_iterator_type _queue_iterator) const; + const target_data_iterator_type _it) const; std::string get_remote_information(const endpoint_type& _remote) const; bool tp_segmentation_enabled(service_t _service, method_t _method) const; }; diff --git a/implementation/endpoints/include/tp.hpp b/implementation/endpoints/include/tp.hpp index 0e3a9d0..ec185b2 100644 --- a/implementation/endpoints/include/tp.hpp +++ b/implementation/endpoints/include/tp.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2019-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -24,9 +24,9 @@ namespace tp { #define VSOMEIP_TP_PAYLOAD_POS 20 // 28 bit length + 3 bit reserved + 1 bit more segments -typedef std::uint32_t tp_header_t; -typedef std::uint8_t tp_message_type_t; -typedef std::vector<message_buffer_ptr_t> tp_split_messages_t; +using tp_header_t = std::uint32_t; +using tp_message_type_t = std::uint8_t; +using tp_split_messages_t = std::vector<message_buffer_ptr_t>; const std::uint8_t TP_FLAG = 0x20; @@ -49,9 +49,10 @@ public: } static tp_split_messages_t tp_split_message( - const std::uint8_t * const _data, std::uint32_t _size); + const std::uint8_t * const _data, std::uint32_t _size, + std::uint16_t _max_segment_length); - static const std::uint16_t tp_max_segment_length_; + static const std::uint16_t tp_max_segment_length_ = 1392; }; } // namespace tp diff --git a/implementation/endpoints/include/tp_message.hpp b/implementation/endpoints/include/tp_message.hpp index 269a1f1..13aef2d 100644 --- a/implementation/endpoints/include/tp_message.hpp +++ b/implementation/endpoints/include/tp_message.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2019-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/implementation/endpoints/include/tp_reassembler.hpp b/implementation/endpoints/include/tp_reassembler.hpp index aaf61c5..5e50c8c 100644 --- a/implementation/endpoints/include/tp_reassembler.hpp +++ b/implementation/endpoints/include/tp_reassembler.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2019-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -11,8 +11,13 @@ #include <mutex> #include <memory> +#if VSOMEIP_BOOST_VERSION < 106600 +# include <boost/asio/io_service.hpp> +# define io_context io_service +#else +# include <boost/asio/io_context.hpp> +#endif #include <boost/asio/ip/address.hpp> -#include <boost/asio/io_service.hpp> #include <boost/asio/steady_timer.hpp> #include <vsomeip/primitive_types.hpp> @@ -25,7 +30,7 @@ namespace tp { class tp_reassembler : public std::enable_shared_from_this<tp_reassembler> { public: - tp_reassembler(std::uint32_t _max_message_size, boost::asio::io_service &_io); + tp_reassembler(std::uint32_t _max_message_size, boost::asio::io_context &_io); /** * @return Returns a pair consisting of a bool and a message_buffer_t. The * value of the bool is set to true if the pair contains a finished message diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp index 3a3fdcb..56fcc20 100644 --- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -8,7 +8,6 @@ #include <memory> -#include <boost/asio/io_service.hpp> #include <boost/asio/strand.hpp> #include <boost/asio/ip/udp.hpp> @@ -21,9 +20,8 @@ namespace vsomeip_v3 { class endpoint_adapter; -typedef client_endpoint_impl< - boost::asio::ip::udp - > udp_client_endpoint_base_impl; +using udp_client_endpoint_base_impl = + client_endpoint_impl<boost::asio::ip::udp>; class udp_client_endpoint_impl: virtual public udp_client_endpoint_base_impl { @@ -32,7 +30,7 @@ public: const std::shared_ptr<routing_host>& _routing_host, const endpoint_type& _local, const endpoint_type& _remote, - boost::asio::io_service &_io, + boost::asio::io_context &_io, const std::shared_ptr<configuration>& _configuration); virtual ~udp_client_endpoint_impl(); @@ -48,10 +46,10 @@ public: void print_status(); bool is_reliable() const; - void send_cbk(boost::system::error_code const &_error, std::size_t _bytes, - const message_buffer_ptr_t &_sent_msg); + void send_cbk(boost::system::error_code const &_error, + std::size_t _bytes, const message_buffer_ptr_t &_sent_msg); private: - void send_queued(message_buffer_ptr_t _buffer); + void send_queued(std::pair<message_buffer_ptr_t, uint32_t> &_entry); void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, @@ -59,8 +57,8 @@ private: void connect(); void receive(); void set_local_port(); - const std::string get_address_port_remote() const; - const std::string get_address_port_local() const; + std::string get_address_port_remote() const; + std::string get_address_port_local() const; std::string get_remote_information() const; bool tp_segmentation_enabled(service_t _service, method_t _method) const; std::uint32_t get_max_allowed_reconnects() const; @@ -69,7 +67,7 @@ private: private: const boost::asio::ip::address remote_address_; const std::uint16_t remote_port_; - int udp_receive_buffer_size_; + const int udp_receive_buffer_size_; std::shared_ptr<tp::tp_reassembler> tp_reassembler_; }; diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp index fef09dc..dd7e224 100644 --- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -6,10 +6,11 @@ #ifndef VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_HPP_ #define VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_HPP_ -#include <boost/asio/io_service.hpp> +#if VSOMEIP_BOOST_VERSION < 106600 #include <boost/asio/ip/udp_ext.hpp> - -#include <atomic> +#else +#include <boost/asio/ip/udp.hpp> +#endif #include <vsomeip/defines.hpp> @@ -18,9 +19,13 @@ namespace vsomeip_v3 { -typedef server_endpoint_impl< - boost::asio::ip::udp_ext - > udp_server_endpoint_base_impl; +#if VSOMEIP_BOOST_VERSION < 106600 +using udp_server_endpoint_base_impl = + server_endpoint_impl<boost::asio::ip::udp_ext>; +#else +using udp_server_endpoint_base_impl = + server_endpoint_impl<boost::asio::ip::udp>; +#endif class udp_server_endpoint_impl: public udp_server_endpoint_base_impl { @@ -28,7 +33,7 @@ public: udp_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host, const std::shared_ptr<routing_host>& _routing_host, const endpoint_type& _local, - boost::asio::io_service &_io, + boost::asio::io_context &_io, const std::shared_ptr<configuration>& _configuration); virtual ~udp_server_endpoint_impl(); @@ -41,7 +46,7 @@ public: const byte_t *_data, uint32_t _size); bool send_error(const std::shared_ptr<endpoint_definition> _target, const byte_t *_data, uint32_t _size); - void send_queued(const queue_iterator_type _queue_iterator); + bool send_queued(const target_data_iterator_type _it); void get_configured_times_from_endpoint( service_t _service, method_t _method, std::chrono::nanoseconds *_debouncing, @@ -49,7 +54,9 @@ public: VSOMEIP_EXPORT void join(const std::string &_address); VSOMEIP_EXPORT void join_unlocked(const std::string &_address); - void leave(const std::string &_address); + VSOMEIP_EXPORT void leave(const std::string &_address); + VSOMEIP_EXPORT void set_multicast_option( + const boost::asio::ip::address &_address, bool _is_join); void add_default_target(service_t _service, const std::string &_address, uint16_t _port); @@ -71,33 +78,35 @@ private: bool is_joined(const std::string &_address) const; bool is_joined(const std::string &_address, bool* _received) const; std::string get_remote_information( - const queue_iterator_type _queue_iterator) const; + const target_data_iterator_type _it) const; std::string get_remote_information(const endpoint_type& _remote) const; - const std::string get_address_port_local() const; + std::string get_address_port_local() const; bool tp_segmentation_enabled(service_t _service, method_t _method) const; void on_unicast_received(boost::system::error_code const &_error, - std::size_t _bytes, - boost::asio::ip::address const &_destination); + std::size_t _bytes); void on_multicast_received(boost::system::error_code const &_error, - std::size_t _bytes, - boost::asio::ip::address const &_destination, - uint8_t _multicast_id); + std::size_t _bytes, uint8_t _multicast_id, + const boost::asio::ip::address &_destination); void on_message_received(boost::system::error_code const &_error, std::size_t _bytes, - boost::asio::ip::address const &_destination, + bool _is_multicast, endpoint_type const &_remote, message_buffer_t const &_buffer); + bool is_same_subnet(const boost::asio::ip::address &_address) const; + private: socket_type unicast_socket_; endpoint_type unicast_remote_; message_buffer_t unicast_recv_buffer_; mutable std::mutex unicast_mutex_; + bool is_v4_; + std::unique_ptr<socket_type> multicast_socket_; std::unique_ptr<endpoint_type> multicast_local_; endpoint_type multicast_remote_; @@ -110,6 +119,9 @@ private: mutable std::mutex default_targets_mutex_; std::map<service_t, endpoint_type> default_targets_; + boost::asio::ip::address netmask_; + unsigned short prefix_; + const std::uint16_t local_port_; std::shared_ptr<tp::tp_reassembler> tp_reassembler_; diff --git a/implementation/endpoints/include/udp_server_endpoint_impl_receive_op.hpp b/implementation/endpoints/include/udp_server_endpoint_impl_receive_op.hpp new file mode 100644 index 0000000..71fad4d --- /dev/null +++ b/implementation/endpoints/include/udp_server_endpoint_impl_receive_op.hpp @@ -0,0 +1,186 @@ +// Copyright (C) 2022 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_ +#define VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_ + +#if VSOMEIP_BOOST_VERSION >= 106600 +#if defined(__linux__) || defined(ANDROID) + +#include <iomanip> + +#include <boost/asio/ip/udp.hpp> + +#include <vsomeip/internal/logger.hpp> + +namespace vsomeip_v3 { + +struct udp_server_endpoint_impl_receive_op { + + using socket_type_t = boost::asio::ip::udp::socket; + using endpoint_type_t = boost::asio::ip::udp::endpoint; + using receive_handler_t = + std::function<void(boost::system::error_code const &_error, std::size_t _size, + std::uint8_t, const boost::asio::ip::address &)>; + + socket_type_t &socket_; + endpoint_type_t &sender_; + receive_handler_t handler_; + byte_t *buffer_; + size_t length_; + uint8_t multicast_id_; + bool is_v4_; + boost::asio::ip::address destination_; + size_t bytes_; + + void operator()(boost::system::error_code _error) { + + sender_ = endpoint_type_t(); // reset + + if (!_error) { + + if (!socket_.native_non_blocking()) + socket_.native_non_blocking(true, _error); + + for (;;) { + ssize_t its_result; + int its_flags(0); + + // Create control elements + msghdr its_header = msghdr(); + struct iovec its_vec[1]; + + // Prepare + its_vec[0].iov_base = buffer_; + its_vec[0].iov_len = length_; + + // Add io buffer + its_header.msg_iov = its_vec; + its_header.msg_iovlen = 1; + + // Sender & destination address info + union { + struct sockaddr_in v4; + struct sockaddr_in6 v6; + } addr; + + union { + struct cmsghdr cmh; + union { + char v4[CMSG_SPACE(sizeof(struct in_pktinfo))]; + char v6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + } control; + } control_un; + + // Prepare + if (is_v4_) { + its_header.msg_name = &addr; + its_header.msg_namelen = sizeof(sockaddr_in); + + its_header.msg_control = control_un.control.v4; + its_header.msg_controllen = sizeof(control_un.control.v4); + } else { + its_header.msg_name = &addr; + its_header.msg_namelen = sizeof(sockaddr_in6); + + its_header.msg_control = control_un.control.v6; + its_header.msg_controllen = sizeof(control_un.control.v6); + } + + // Call recvmsg and handle its result + errno = 0; + its_result = ::recvmsg(socket_.native_handle(), &its_header, its_flags); + + _error = boost::system::error_code(its_result < 0 ? errno : 0, + boost::asio::error::get_system_category()); + bytes_ += _error ? 0 : static_cast<size_t>(its_result); + + if (_error == boost::asio::error::interrupted) + continue; + + if (_error == boost::asio::error::would_block + || _error == boost::asio::error::try_again) { + + socket_.async_wait(socket_type_t::wait_read, *this); + return; + } + + if (_error) + break; + + if (bytes_ == 0) + _error = boost::asio::error::eof; + + // Extract sender & destination addresses + if (is_v4_) { + // sender + boost::asio::ip::address_v4 its_sender_address( + ntohl(addr.v4.sin_addr.s_addr)); + in_port_t its_sender_port(ntohs(addr.v4.sin_port)); + sender_ = endpoint_type_t(its_sender_address, its_sender_port); + + // destination + struct in_pktinfo *its_pktinfo_v4; + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&its_header); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&its_header, cmsg)) { + + if (cmsg->cmsg_level == IPPROTO_IP + && cmsg->cmsg_type == IP_PKTINFO + && cmsg->cmsg_len == CMSG_LEN(sizeof(*its_pktinfo_v4))) { + + its_pktinfo_v4 = (struct in_pktinfo*) CMSG_DATA(cmsg); + if (its_pktinfo_v4) { + destination_ = boost::asio::ip::address_v4( + ntohl(its_pktinfo_v4->ipi_addr.s_addr)); + break; + } + } + } + } else { + boost::asio::ip::address_v6::bytes_type its_bytes; + + // sender + boost::asio::ip::address_v6 its_sender_address; + for (size_t i = 0; i < its_bytes.size(); i++) + its_bytes[i] = addr.v6.sin6_addr.s6_addr[i]; + in_port_t its_sender_port(ntohs(addr.v6.sin6_port)); + sender_ = endpoint_type_t(its_sender_address, its_sender_port); + + struct in6_pktinfo *its_pktinfo_v6; + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&its_header); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&its_header, cmsg)) { + + if (cmsg->cmsg_level == IPPROTO_IPV6 + && cmsg->cmsg_type == IPV6_PKTINFO + && cmsg->cmsg_len == CMSG_LEN(sizeof(*its_pktinfo_v6))) { + + its_pktinfo_v6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); + if (its_pktinfo_v6) { + for (size_t i = 0; i < its_bytes.size(); i++) + its_bytes[i] = its_pktinfo_v6->ipi6_addr.s6_addr[i]; + destination_ = boost::asio::ip::address_v6(its_bytes); + break; + } + } + } + } + + break; + } + } + + // Call the handler + handler_(_error, bytes_, multicast_id_, destination_); + } +}; + +} // namespace vsomeip + +#endif // __linux__ || ANDROID +#endif // VSOMEIP_BOOST_VERSION >= 106600 + +#endif // VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_ diff --git a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp index adf3972..98b3958 100644 --- a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -6,7 +6,12 @@ #ifndef VSOMEIP_V3_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP_ #define VSOMEIP_V3_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP_ -#include <boost/asio/io_service.hpp> +#if VSOMEIP_BOOST_VERSION < 106600 +# include <boost/asio/io_service.hpp> +# define io_context io_service +#else +# include <boost/asio/io_context.hpp> +#endif #include <vsomeip/primitive_types.hpp> @@ -20,12 +25,12 @@ public: const std::string &_address, uint16_t _port, bool _reliable, - boost::asio::io_service& _service); + boost::asio::io_context &_io); virtual ~virtual_server_endpoint_impl(); void start(); - void prepare_stop(endpoint::prepare_stop_handler_t _handler, + void prepare_stop(const endpoint::prepare_stop_handler_t &_handler, service_t _service); void stop(); @@ -35,8 +40,6 @@ public: void set_connected(bool _connected); bool send(const byte_t *_data, uint32_t _size); - bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data, - uint32_t _size); bool send_to(const std::shared_ptr<endpoint_definition> _target, const byte_t *_data, uint32_t _size); bool send_error(const std::shared_ptr<endpoint_definition> _target, @@ -61,7 +64,7 @@ public: void restart(bool _force); - void register_error_handler(error_handler_t _handler); + void register_error_handler(const error_handler_t &_handler); void print_status(); size_t get_queue_size() const; @@ -72,7 +75,7 @@ private: bool reliable_; uint32_t use_count_; - boost::asio::io_service& service_; + boost::asio::io_context &io_; }; } // namespace vsomeip_v3 |