Coverage Report

Created: 2025-06-13 06:46

/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_