/src/Fast-DDS/src/cpp/rtps/transport/TCPChannelResource.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima). |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef _FASTDDS_TCP_CHANNEL_RESOURCE_BASE_ |
16 | | #define _FASTDDS_TCP_CHANNEL_RESOURCE_BASE_ |
17 | | |
18 | | #include <asio.hpp> |
19 | | #include <fastdds/rtps/transport/TCPTransportDescriptor.hpp> |
20 | | #include <fastdds/rtps/transport/TransportReceiverInterface.hpp> |
21 | | #include <fastdds/rtps/common/Locator.hpp> |
22 | | #include <rtps/transport/ChannelResource.h> |
23 | | #include <rtps/transport/tcp/RTCPMessageManager.h> |
24 | | |
25 | | |
26 | | namespace eprosima { |
27 | | namespace fastdds { |
28 | | namespace rtps { |
29 | | |
30 | | class TCPConnector; |
31 | | class TCPTransportInterface; |
32 | | |
33 | | enum eSocketErrorCodes |
34 | | { |
35 | | eNoError, |
36 | | eBrokenPipe, |
37 | | eAsioError, |
38 | | eSystemError, |
39 | | eException, |
40 | | eConnectionAborted = 125 |
41 | | }; |
42 | | |
43 | | class TCPChannelResource : public ChannelResource |
44 | | { |
45 | | |
46 | | protected: |
47 | | |
48 | | enum TCPConnectionType |
49 | | { |
50 | | TCP_ACCEPT_TYPE = 0, |
51 | | TCP_CONNECT_TYPE = 1 |
52 | | }; |
53 | | |
54 | | enum eConnectionStatus |
55 | | { |
56 | | eDisconnected = 0, |
57 | | eConnecting, // Output -> Trying connection. |
58 | | eConnected, // Output -> Send bind message. |
59 | | eWaitingForBind, // Input -> Waiting for the bind message. |
60 | | eWaitingForBindResponse, // Output -> Waiting for the bind response message. |
61 | | eEstablished, |
62 | | eUnbinding |
63 | | }; |
64 | | |
65 | | TCPTransportInterface* parent_; |
66 | | Locator locator_; |
67 | | bool waiting_for_keep_alive_; |
68 | | // Must be accessed after lock pending_logical_mutex_ |
69 | | std::map<TCPTransactionId, uint16_t> negotiating_logical_ports_; |
70 | | std::map<TCPTransactionId, uint16_t> last_checked_logical_port_; |
71 | | std::vector<uint16_t> pending_logical_output_ports_; // Must be accessed after lock pending_logical_mutex_ |
72 | | std::vector<uint16_t> logical_output_ports_; |
73 | | std::condition_variable_any logical_output_ports_updated_cv; |
74 | | std::mutex read_mutex_; |
75 | | std::recursive_mutex pending_logical_mutex_; |
76 | | std::atomic<eConnectionStatus> connection_status_; |
77 | | |
78 | | public: |
79 | | |
80 | | void add_logical_port( |
81 | | uint16_t port, |
82 | | RTCPMessageManager* rtcp_manager); |
83 | | |
84 | | void set_logical_port_pending( |
85 | | uint16_t port); |
86 | | |
87 | | bool remove_logical_port( |
88 | | uint16_t port); |
89 | | |
90 | | virtual void disable() override; |
91 | | |
92 | | bool is_logical_port_opened( |
93 | | uint16_t port); |
94 | | |
95 | | bool is_logical_port_added( |
96 | | uint16_t port); |
97 | | |
98 | | /** |
99 | | * This method checks if a logical port is under negotiation. If it is, it waits for the negotiation to finish up to a timeout. |
100 | | * Independently if being under negotiation or not, it returns true if the port is opened, false otherwise. |
101 | | * |
102 | | * @param port The logical port to check. |
103 | | * @param timeout The maximum time to wait for the negotiation to finish. Zero value means no wait |
104 | | * |
105 | | * @return true if the port is opened, false otherwise. |
106 | | */ |
107 | | bool wait_logical_port_under_negotiation( |
108 | | uint16_t port, |
109 | | const std::chrono::milliseconds& timeout); |
110 | | |
111 | | bool connection_established() |
112 | 0 | { |
113 | 0 | return connection_status_ == eConnectionStatus::eEstablished; |
114 | 0 | } |
115 | | |
116 | | eConnectionStatus connection_status() |
117 | 0 | { |
118 | 0 | return connection_status_; |
119 | 0 | } |
120 | | |
121 | | inline const Locator& locator() const |
122 | 0 | { |
123 | 0 | return locator_; |
124 | 0 | } |
125 | | |
126 | | ResponseCode process_bind_request( |
127 | | const Locator& locator); |
128 | | |
129 | | // Socket related methods |
130 | | virtual void connect( |
131 | | const std::shared_ptr<TCPChannelResource>& myself) = 0; |
132 | | |
133 | | virtual void disconnect() = 0; |
134 | | |
135 | | virtual uint32_t read( |
136 | | octet* buffer, |
137 | | std::size_t size, |
138 | | asio::error_code& ec) = 0; |
139 | | |
140 | | /** |
141 | | * Sends the provided TCP header and data over the TCP channel. |
142 | | * Used solely during TCP connection negotiations. |
143 | | * |
144 | | * @param header Pointer to the octet array containing the TCP header. |
145 | | * @param header_size Size of the TCP header array. |
146 | | * @param data Pointer to the octet array containing the data. |
147 | | * @param data_size Size of the data array. |
148 | | * @param ec Reference to the asio::error_code object to store any error that occurs during the send operation. |
149 | | * @return The number of bytes actually sent. |
150 | | */ |
151 | | size_t send( |
152 | | const fastdds::rtps::octet* header, |
153 | | size_t header_size, |
154 | | const fastdds::rtps::octet* data, |
155 | | uint32_t data_size, |
156 | | asio::error_code& ec) |
157 | 0 | { |
158 | 0 | NetworkBuffer buffers(data, data_size); |
159 | 0 | std::vector<NetworkBuffer> buffer_list; |
160 | 0 | buffer_list.push_back(buffers); |
161 | 0 | return send(header, header_size, buffer_list, data_size, ec); |
162 | 0 | } |
163 | | |
164 | | /** |
165 | | * Sends the provided TCP header and data over the TCP channel. |
166 | | * Used for TCP metatraffic and data transmission. |
167 | | * |
168 | | * @param header Pointer to the TCP header data. |
169 | | * @param header_size Size of the TCP header data. |
170 | | * @param buffers Vector of network buffers containing the data to be sent. |
171 | | * @param total_bytes Total number of bytes to be sent. |
172 | | * @param ec Reference to an asio::error_code object to store any error that occurs during the send operation. |
173 | | * @return The number of bytes actually sent. |
174 | | */ |
175 | | virtual size_t send( |
176 | | const octet* header, |
177 | | size_t header_size, |
178 | | const std::vector<NetworkBuffer>& buffers, |
179 | | uint32_t total_bytes, |
180 | | asio::error_code& ec) = 0; |
181 | | |
182 | | /** |
183 | | * @brief Gets the remote endpoint of the socket connection. |
184 | | * @throws Exception on failure. |
185 | | * @return asio::ip::tcp::endpoint of the remote endpoint. |
186 | | */ |
187 | | virtual asio::ip::tcp::endpoint remote_endpoint() const = 0; |
188 | | |
189 | | /** |
190 | | * @brief Gets the local endpoint of the socket connection. |
191 | | * @throws Exception on failure. |
192 | | * @return asio::ip::tcp::endpoint of the local endpoint. |
193 | | */ |
194 | | virtual asio::ip::tcp::endpoint local_endpoint() const = 0; |
195 | | |
196 | | /** |
197 | | * @brief Gets the remote endpoint, setting error code if any. |
198 | | * @param ec Set to indicate what error occurred, if any. |
199 | | * @return asio::ip::tcp::endpoint of the remote endpoint or returns a default-constructed endpoint object if an error occurred. |
200 | | */ |
201 | | virtual asio::ip::tcp::endpoint remote_endpoint( |
202 | | asio::error_code& ec) const = 0; |
203 | | |
204 | | /** |
205 | | * @brief Gets the local endpoint, setting error code if any. |
206 | | * @param ec Set to indicate what error occurred, if any. |
207 | | * @return asio::ip::tcp::endpoint of the remote endpoint or returns a default-constructed endpoint object if an error occurred. |
208 | | */ |
209 | | virtual asio::ip::tcp::endpoint local_endpoint( |
210 | | asio::error_code& ec) const = 0; |
211 | | |
212 | | virtual void set_options( |
213 | | const TCPTransportDescriptor* options) = 0; |
214 | | |
215 | | virtual void cancel() = 0; |
216 | | |
217 | | virtual void close() = 0; |
218 | | |
219 | | virtual void shutdown( |
220 | | asio::socket_base::shutdown_type what) = 0; |
221 | | |
222 | | TCPConnectionType tcp_connection_type() const |
223 | 0 | { |
224 | 0 | return tcp_connection_type_; |
225 | 0 | } |
226 | | |
227 | | protected: |
228 | | |
229 | | // Constructor called when trying to connect to a remote server |
230 | | TCPChannelResource( |
231 | | TCPTransportInterface* parent, |
232 | | const Locator& locator, |
233 | | uint32_t maxMsgSize); |
234 | | |
235 | | // Constructor called when local server accepted connection |
236 | | TCPChannelResource( |
237 | | TCPTransportInterface* parent, |
238 | | uint32_t maxMsgSize); |
239 | | |
240 | | inline eConnectionStatus change_status( |
241 | | eConnectionStatus s, |
242 | | RTCPMessageManager* rtcp_manager = nullptr) |
243 | 0 | { |
244 | 0 | eConnectionStatus old = connection_status_.exchange(s); |
245 | |
|
246 | 0 | if (old != s) |
247 | 0 | { |
248 | 0 | if (s == eEstablished) |
249 | 0 | { |
250 | 0 | assert(rtcp_manager != nullptr); |
251 | 0 | send_pending_open_logical_ports(rtcp_manager); |
252 | 0 | } |
253 | 0 | } |
254 | |
|
255 | 0 | return old; |
256 | 0 | } |
257 | | |
258 | | void add_logical_port_response( |
259 | | const TCPTransactionId& id, |
260 | | bool success, |
261 | | RTCPMessageManager* rtcp_manager); |
262 | | |
263 | | void process_check_logical_ports_response( |
264 | | const TCPTransactionId& transactionId, |
265 | | const std::vector<uint16_t>& availablePorts, |
266 | | RTCPMessageManager* rtcp_manager); |
267 | | |
268 | | bool check_socket_send_buffer( |
269 | | const size_t& msg_size, |
270 | | const asio::ip::tcp::socket::native_handle_type& socket_native_handle); |
271 | | |
272 | | /** |
273 | | * @brief Set descriptor options on a socket. |
274 | | * |
275 | | * @param socket Socket on which to set the options. |
276 | | * @param options Descriptor with the options to set. |
277 | | */ |
278 | | static void set_socket_options( |
279 | | asio::basic_socket<asio::ip::tcp>& socket, |
280 | | const TCPTransportDescriptor* options); |
281 | | |
282 | | TCPConnectionType tcp_connection_type_; |
283 | | |
284 | | friend class TCPTransportInterface; |
285 | | friend class RTCPMessageManager; |
286 | | |
287 | | private: |
288 | | |
289 | | bool is_logical_port_opened_nts( |
290 | | uint16_t port); |
291 | | |
292 | | void prepare_send_check_logical_ports_req( |
293 | | uint16_t closedPort, |
294 | | RTCPMessageManager* rtcp_manager); |
295 | | |
296 | | void send_pending_open_logical_ports( |
297 | | RTCPMessageManager* rtcp_manager); |
298 | | |
299 | | void set_all_ports_pending(); |
300 | | |
301 | | TCPChannelResource( |
302 | | const TCPChannelResource&) = delete; |
303 | | |
304 | | TCPChannelResource& operator =( |
305 | | const TCPChannelResource&) = delete; |
306 | | }; |
307 | | |
308 | | |
309 | | } // namespace rtps |
310 | | } // namespace fastdds |
311 | | } // namespace eprosima |
312 | | |
313 | | #endif // _FASTDDS_TCP_CHANNEL_RESOURCE_BASE_ |