reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
AsyncTcpSocketBase.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <functional>
6
9#include <rutil/Logger.hxx>
10#include "ReTurnSubsystem.hxx"
11
12#define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
13
14using namespace std;
15
16namespace reTurn {
17
18AsyncTcpSocketBase::AsyncTcpSocketBase(asio::io_context& ioService)
19 : AsyncSocketBase(ioService),
20 mSocket(ioService),
21 mResolver(ioService)
22{
23}
24
25unsigned int
27{
28 return (unsigned int)mSocket.native_handle();
29}
30
31asio::error_code
32AsyncTcpSocketBase::bind(const asio::ip::address& address, unsigned short port)
33{
34 // connect() binds the socket again, for each address it tries
35 mLocalTcpEndpoint = asio::ip::tcp::endpoint(address, port);
36 return openAndBind(mSocket);
37}
38
39void
40AsyncTcpSocketBase::connect(const std::string& address, unsigned short port)
41{
42 // Start an asynchronous resolve to translate the address
43 // into a list of endpoints.
44 resip::Data service(port);
45 mResolver.async_resolve(mLocalTcpEndpoint.protocol(), address, service.c_str(),
46 std::bind(&AsyncSocketBase::handleTcpResolve, shared_from_this(),
47 std::placeholders::_1,
48 std::placeholders::_2));
49}
50
51void
52AsyncTcpSocketBase::handleTcpResolve(const asio::error_code& ec,
53 const asio::ip::tcp::resolver::results_type& endpoints)
54{
55 if (!ec)
56 {
57 // Attempt a connection to the first endpoint in the list. Each endpoint
58 // will be tried until we successfully establish a connection.
59 asyncConnect(mSocket, endpoints);
60 }
61 else
62 {
64 }
65}
66
67void
68AsyncTcpSocketBase::handleConnect(const asio::error_code& ec,
69 const asio::ip::tcp::endpoint& endpoint)
70{
71 if (!ec)
72 {
73 // The connection was successful.
74 mConnected = true;
75 mConnectedAddress = endpoint.address();
76 mConnectedPort = endpoint.port();
77
79 }
80 else
81 {
83 }
84}
85
86void
88{
89 asio::error_code ec;
90 mConnectedAddress = mSocket.remote_endpoint(ec).address();
91 mConnectedPort = mSocket.remote_endpoint(ec).port();
92}
93
94asio::ip::address
99
100unsigned short
105
106void
107AsyncTcpSocketBase::transportSend(const StunTuple& destination, std::vector<asio::const_buffer>& buffers)
108{
109 // Note: destination is ignored for TCP
110 asio::async_write(mSocket, buffers,
111 std::bind(&AsyncTcpSocketBase::handleSend, shared_from_this(), std::placeholders::_1));
112}
113
114void
116{
117 mSocket.async_read_some(asio::buffer((void*)mReceiveBuffer->data(), RECEIVE_BUFFER_SIZE),
118 std::bind(&AsyncTcpSocketBase::handleReceive, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
119}
120
121void
123{
124 asio::async_read(mSocket, asio::buffer((void*)mReceiveBuffer->data(), 4),
125 std::bind(&AsyncSocketBase::handleReadHeader, shared_from_this(), std::placeholders::_1));
126}
127
128void
129AsyncTcpSocketBase::handleReadHeader(const asio::error_code& e)
130{
131 if (!e)
132 {
133 /*
134 std::cout << "Read header from tcp socket: " << std::endl;
135 for(unsigned int i = 0; i < 4; i++)
136 {
137 std::cout << (char)(*mReceiveBuffer)[i] << "(" << (int)(*mReceiveBuffer)[i] << ") ";
138 }
139 std::cout << std::endl;
140 */
141
142 // Note: For both StunMessages and ChannelData messages the length in bytes 3 and 4
143 uint16_t dataLen;
144 memcpy(&dataLen, &(*mReceiveBuffer)[2], 2);
145 dataLen = ntohs(dataLen);
146
147 // ChannelData's padding is read with it, but not passed on
148 size_t padding = 0;
149 if(((*mReceiveBuffer)[0] & 0xC0) == 0) // If first 2 bits are 00 then this is a stun message
150 {
151 dataLen += 16; // There are 20 bytes in total in the header, and we have already read 4 - read the rest of the header + the body
152 }
153 else
154 {
155 padding = channelDataPadding(dataLen);
156 }
157 if (dataLen + padding + 4U < RECEIVE_BUFFER_SIZE)
158 {
159 asio::async_read(mSocket, asio::buffer(&(*mReceiveBuffer)[4], dataLen + padding),
160 std::bind(&AsyncTcpSocketBase::handleReceive, shared_from_this(), std::placeholders::_1, dataLen+4));
161 }
162 else
163 {
164 WarningLog(<< "Receive buffer (" << RECEIVE_BUFFER_SIZE << ") is not large enough to accommodate incoming framed data (" << dataLen+4 << ") closing connection.");
165 close();
166 }
167 }
168 else if (e != asio::error::operation_aborted)
169 {
170 if(e != asio::error::eof &&
171#ifdef _WIN32
172 e.value() != ERROR_CONNECTION_ABORTED && // This happens on Windows 7 when closing the socket
173#endif
174 e != asio::error::connection_reset)
175 {
176 WarningLog(<< "Read header error: " << e.value() << "-" << e.message());
177 }
178 close();
179 }
180}
181
182void
184{
186 {
187 mOnBeforeSocketCloseFp((unsigned int)mSocket.native_handle());
188 }
189
190 asio::error_code ec;
191 mSocket.close(ec);
192}
193
194}
195
196
197/* ====================================================================
198
199 Copyright (c) 2008-2026 SIP Spectrum, Inc. https://www.sipspectrum.com
200 Copyright (c) 2007-2008, Plantronics, Inc.
201 All rights reserved.
202
203 Redistribution and use in source and binary forms, with or without
204 modification, are permitted provided that the following conditions are
205 met:
206
207 1. Redistributions of source code must retain the above copyright
208 notice, this list of conditions and the following disclaimer.
209
210 2. Redistributions in binary form must reproduce the above copyright
211 notice, this list of conditions and the following disclaimer in the
212 documentation and/or other materials provided with the distribution.
213
214 3. Neither the name of Plantronics nor the names of its contributors
215 may be used to endorse or promote products derived from this
216 software without specific prior written permission.
217
218 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
219 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
220 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
221 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
222 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
223 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
225 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
226 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
227 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
228 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
229
230 ==================================================================== */
231
constexpr size_t RECEIVE_BUFFER_SIZE
#define WarningLog(args_)
Definition Logger.hxx:134
virtual void handleReceive(const asio::error_code &e, size_t bytesTransferred)
asio::ip::tcp::endpoint mLocalTcpEndpoint
asio::error_code openAndBind(asio::ip::tcp::socket &socket)
For TCP and TLS client sockets.
virtual void handleTcpResolve(const asio::error_code &ec, const asio::ip::tcp::resolver::results_type &endpoints)
BeforeClosedHandler mOnBeforeSocketCloseFp
Provides an opportunity for the app to clean up, e.g., QoS-related data or resources just before the ...
static size_t channelDataPadding(size_t length)
Over TCP and TLS, a TURN ChannelData message is padded to a multiple of 4 bytes, the padding not coun...
virtual void onConnectFailure(const asio::error_code &e)
virtual void onConnectSuccess()
Class override callbacks.
virtual void handleSend(const asio::error_code &e)
Handle completion of a sendData operation.
virtual void handleReadHeader(const asio::error_code &e)
void asyncConnect(asio::ip::tcp::socket &socket, const asio::ip::tcp::resolver::results_type &endpoints)
std::shared_ptr< DataBuffer > mReceiveBuffer
Receive Buffer and state.
asio::ip::address mConnectedAddress
Connected Info and State.
void handleReadHeader(const asio::error_code &e) override
asio::ip::address getSenderEndpointAddress() override
void connect(const std::string &address, unsigned short port) override
unsigned int getSocketDescriptor() override
asio::ip::tcp::socket mSocket
asio::error_code bind(const asio::ip::address &address, unsigned short port) override
Note: The following API's are thread safe and queue the request to be handled by the ioService thread...
asio::ip::tcp::resolver mResolver
void handleConnect(const asio::error_code &ec, const asio::ip::tcp::endpoint &endpoint) override
void handleTcpResolve(const asio::error_code &ec, const asio::ip::tcp::resolver::results_type &endpoints) override
void transportSend(const StunTuple &destination, std::vector< asio::const_buffer > &buffers) override
unsigned short getSenderEndpointPort() override
AsyncTcpSocketBase(asio::io_context &ioService)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
unsigned short uint16_t
Definition stdint.h:84