1 // Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 
6 #ifndef VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_
7 #define VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_
8 
9 #include <condition_variable>
10 #include <deque>
11 #include <mutex>
12 #include <vector>
13 #include <atomic>
14 #include <chrono>
15 
16 #include <boost/array.hpp>
17 #include <boost/asio/io_service.hpp>
18 #include <boost/asio/strand.hpp>
19 #include <boost/asio/ip/udp.hpp>
20 #include <boost/utility.hpp>
21 #include <vsomeip/constants.hpp>
22 
23 #include "buffer.hpp"
24 #include "endpoint_impl.hpp"
25 #include "client_endpoint.hpp"
26 #include "tp.hpp"
27 
28 
29 namespace vsomeip_v3 {
30 
31 class endpoint;
32 class endpoint_host;
33 
34 template<typename Protocol>
35 class client_endpoint_impl: public endpoint_impl<Protocol>, public client_endpoint,
36         public std::enable_shared_from_this<client_endpoint_impl<Protocol> > {
37 public:
38     typedef typename Protocol::endpoint endpoint_type;
39     typedef typename Protocol::socket socket_type;
40 
41     client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
42                          const std::shared_ptr<routing_host>& _routing_host,
43                          const endpoint_type& _local, const endpoint_type& _remote,
44                          boost::asio::io_service &_io,
45                          std::uint32_t _max_message_size,
46                          configuration::endpoint_queue_limit_t _queue_limit,
47                          const std::shared_ptr<configuration>& _configuration);
48     virtual ~client_endpoint_impl();
49 
50     bool send(const uint8_t *_data, uint32_t _size);
51     bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
52               uint32_t _size);
53     bool send_to(const std::shared_ptr<endpoint_definition> _target,
54                  const byte_t *_data, uint32_t _size);
55     bool send_error(const std::shared_ptr<endpoint_definition> _target,
56                 const byte_t *_data, uint32_t _size);
57     bool flush();
58 
59     void prepare_stop(endpoint::prepare_stop_handler_t _handler, service_t _service);
60     virtual void stop();
61     virtual void restart(bool _force = false) = 0;
62 
63     bool is_client() const;
64 
65     bool is_established() const;
66     bool is_established_or_connected() const;
67     void set_established(bool _established);
68     void set_connected(bool _connected);
69     virtual bool get_remote_address(boost::asio::ip::address &_address) const;
70     virtual std::uint16_t get_remote_port() const;
71 
72     std::uint16_t get_local_port() const;
73     void set_local_port(uint16_t _port);
74     virtual bool is_reliable() const = 0;
75 
76     size_t get_queue_size() const;
77 
78 public:
79     void connect_cbk(boost::system::error_code const &_error);
80     void wait_connect_cbk(boost::system::error_code const &_error);
81     virtual void send_cbk(boost::system::error_code const &_error,
82                           std::size_t _bytes, const message_buffer_ptr_t& _sent_msg);
83     void flush_cbk(boost::system::error_code const &_error);
84 
85 public:
86     virtual void connect() = 0;
87     virtual void receive() = 0;
88     virtual void print_status() = 0;
89 
90 protected:
91     enum class cei_state_e : std::uint8_t {
92         CLOSED,
93         CONNECTING,
94         CONNECTED,
95         ESTABLISHED
96     };
97     message_buffer_ptr_t get_front();
98     virtual void send_queued(message_buffer_ptr_t _buffer) = 0;
99     virtual void get_configured_times_from_endpoint(
100             service_t _service, method_t _method,
101             std::chrono::nanoseconds *_debouncing,
102             std::chrono::nanoseconds *_maximum_retention) const = 0;
103     void shutdown_and_close_socket(bool _recreate_socket);
104     void shutdown_and_close_socket_unlocked(bool _recreate_socket);
105     void start_connect_timer();
106     typename endpoint_impl<Protocol>::cms_ret_e check_message_size(
107             const std::uint8_t * const _data, std::uint32_t _size);
108     bool check_queue_limit(const uint8_t *_data, std::uint32_t _size) const;
109     void queue_train(bool _queue_size_zero_on_entry);
110 
111 protected:
112     mutable std::mutex socket_mutex_;
113     std::unique_ptr<socket_type> socket_;
114     const endpoint_type remote_;
115 
116     boost::asio::steady_timer flush_timer_;
117 
118     std::mutex connect_timer_mutex_;
119     boost::asio::steady_timer connect_timer_;
120     std::atomic<uint32_t> connect_timeout_;
121     std::atomic<cei_state_e> state_;
122     std::atomic<std::uint32_t> reconnect_counter_;
123 
124     // send data
125     train train_;
126 
127     std::deque<message_buffer_ptr_t> queue_;
128     std::size_t queue_size_;
129 
130     mutable std::mutex mutex_;
131 
132     std::atomic<bool> was_not_connected_;
133 
134     std::atomic<std::uint16_t> local_port_;
135 
136     boost::asio::io_service::strand strand_;
137 
138 private:
139     virtual void set_local_port() = 0;
140     virtual std::string get_remote_information() const = 0;
141     virtual bool tp_segmentation_enabled(service_t _service,
142                                          method_t _method) const = 0;
143     virtual std::uint32_t get_max_allowed_reconnects() const = 0;
144     virtual void max_allowed_reconnects_reached() = 0;
145     void send_segments(const tp::tp_split_messages_t &_segments);
146     void wait_until_debounce_time_reached() const;
147 };
148 
149 } // namespace vsomeip_v3
150 
151 #endif // VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_
152