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_LOCAL_SERVER_ENDPOINT_IMPL_HPP_
7 #define VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_
8 
9 #include <map>
10 #include <thread>
11 #include <condition_variable>
12 #include <memory>
13 
14 #include <boost/asio/io_service.hpp>
15 #include <boost/asio/local/stream_protocol_ext.hpp>
16 
17 
18 #ifdef _WIN32
19 #include <boost/asio/ip/tcp.hpp>
20 #endif
21 
22 #include <vsomeip/defines.hpp>
23 
24 #include "buffer.hpp"
25 #include "server_endpoint_impl.hpp"
26 
27 namespace vsomeip_v3 {
28 
29 #ifdef _WIN32
30 typedef server_endpoint_impl<
31             boost::asio::ip::tcp
32         > local_server_endpoint_base_impl;
33 #else
34 typedef server_endpoint_impl<
35             boost::asio::local::stream_protocol_ext
36         > local_server_endpoint_base_impl;
37 #endif
38 
39 class local_server_endpoint_impl: public local_server_endpoint_base_impl {
40 
41 public:
42     local_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
43                                const std::shared_ptr<routing_host>& _routing_host,
44                                const endpoint_type& _local,
45                                boost::asio::io_service &_io,
46                                const std::shared_ptr<configuration>& _configuration,
47                                bool _is_routing_endpoint);
48 
49     local_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
50                                const std::shared_ptr<routing_host>& _routing_host,
51                                const endpoint_type& _local,
52                                boost::asio::io_service &_io,
53                                int native_socket,
54                                const std::shared_ptr<configuration>& _configuration,
55                                bool _is_routing_endpoint);
56 
57     virtual ~local_server_endpoint_impl();
58 
59     void start();
60     void stop();
61 
62     void receive();
63 
64     // this overrides server_endpoint_impl::send to disable the nPDU feature
65     // for local communication
66     bool send(const uint8_t *_data, uint32_t _size);
67     bool send_to(const std::shared_ptr<endpoint_definition>,
68                  const byte_t *_data, uint32_t _size);
69     bool send_error(const std::shared_ptr<endpoint_definition> _target,
70                 const byte_t *_data, uint32_t _size);
71     void send_queued(const queue_iterator_type _queue_iterator);
72     void get_configured_times_from_endpoint(
73             service_t _service, method_t _method,
74             std::chrono::nanoseconds *_debouncing,
75             std::chrono::nanoseconds *_maximum_retention) const;
76 
77     bool get_default_target(service_t, endpoint_type &) const;
78 
79     bool is_local() const;
80 
81     void accept_client_func();
82     void print_status();
83 
84     bool is_reliable() const;
85     std::uint16_t get_local_port() const;
86     void set_local_port(std::uint16_t _port);
87 
88     client_t assign_client(const byte_t *_data, uint32_t _size);
89 
90 private:
91     class connection: public std::enable_shared_from_this<connection> {
92 
93     public:
94         typedef std::shared_ptr<connection> ptr;
95 
96         static ptr create(const std::shared_ptr<local_server_endpoint_impl>& _server,
97                           std::uint32_t _max_message_size,
98                           std::uint32_t _buffer_shrink_threshold,
99                           boost::asio::io_service &_io_service);
100         socket_type & get_socket();
101         std::unique_lock<std::mutex> get_socket_lock();
102 
103         void start();
104         void stop();
105 
106 
107         void send_queued(const message_buffer_ptr_t& _buffer);
108 
109         void set_bound_client(client_t _client);
110         client_t get_bound_client() const;
111 #ifndef _WIN32
112         void set_bound_uid_gid(uid_t _uid, gid_t _gid);
113 #endif
114 
115         std::size_t get_recv_buffer_capacity() const;
116 
117     private:
118         connection(const std::shared_ptr<local_server_endpoint_impl>& _server,
119                    std::uint32_t _max_message_size,
120                    std::uint32_t _initial_recv_buffer_size,
121                    std::uint32_t _buffer_shrink_threshold,
122                    boost::asio::io_service &_io_service);
123 
124         void send_cbk(const message_buffer_ptr_t _buffer,
125                 boost::system::error_code const &_error, std::size_t _bytes);
126         void receive_cbk(boost::system::error_code const &_error,
127                          std::size_t _bytes
128 #ifndef _WIN32
129                          , std::uint32_t const &_uid, std::uint32_t const &_gid
130 #endif
131         );
132         void calculate_shrink_count();
133         const std::string get_path_local() const;
134         const std::string get_path_remote() const;
135         void handle_recv_buffer_exception(const std::exception &_e);
136 
137         std::mutex socket_mutex_;
138         local_server_endpoint_impl::socket_type socket_;
139         std::weak_ptr<local_server_endpoint_impl> server_;
140 
141         const std::uint32_t recv_buffer_size_initial_;
142         const std::uint32_t max_message_size_;
143 
144         message_buffer_t recv_buffer_;
145         size_t recv_buffer_size_;
146         std::uint32_t missing_capacity_;
147         std::uint32_t shrink_count_;
148         const std::uint32_t buffer_shrink_threshold_;
149 
150         client_t bound_client_;
151 #ifndef _WIN32
152         uid_t bound_uid_;
153         gid_t bound_gid_;
154 #endif
155         bool assigned_client_;
156     };
157 
158     std::mutex acceptor_mutex_;
159 #ifdef _WIN32
160     boost::asio::ip::tcp::acceptor acceptor_;
161 #else
162     boost::asio::local::stream_protocol_ext::acceptor acceptor_;
163 #endif
164 
165     typedef std::map<client_t, connection::ptr> connections_t;
166     std::mutex connections_mutex_;
167     connections_t connections_;
168 
169     const std::uint32_t buffer_shrink_threshold_;
170 
171     const bool is_routing_endpoint_;
172 
173 private:
174     bool add_connection(const client_t &_client,
175             const std::shared_ptr<connection> &_connection);
176     void remove_connection(const client_t &_client);
177     void accept_cbk(const connection::ptr& _connection,
178                     boost::system::error_code const &_error);
179     std::string get_remote_information(
180             const queue_iterator_type _queue_iterator) const;
181     std::string get_remote_information(
182             const endpoint_type& _remote) const;
183 
184     bool check_packetizer_space(queue_iterator_type _queue_iterator,
185                                 message_buffer_ptr_t* _packetizer,
186                                 std::uint32_t _size);
187     bool tp_segmentation_enabled(service_t _service, method_t _method) const;
188     void send_client_identifier(const client_t &_client);
189 };
190 
191 } // namespace vsomeip_v3
192 
193 #endif // VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_
194