reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
TurnAsyncSocket.hxx
Go to the documentation of this file.
1#ifndef TURNASYNCSOCKET_HXX
2#define TURNASYNCSOCKET_HXX
3
4#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) \
5 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
6 && !defined(ASIO_ENABLE_CANCELIO)
7#error You must define ASIO_ENABLE_CANCELIO in your build settings.
8#endif
9
10#include <asio.hpp>
11#ifdef USE_SSL
12#include <asio/ssl.hpp>
13#endif
14
15#include <rutil/Data.hxx>
16#include <rutil/Mutex.hxx>
17
18#include <map>
19#include <queue>
20
21#include "reTurn/StunTuple.hxx"
26
27#include <functional>
28#include <memory>
29#include <utility>
30
31#define UDP_RT0 100 // RTO - Estimate of Roundtrip time - 100ms is recommened for fixed line transport - the initial value should be configurable
32 // Should also be calculation this on the fly
33#define UDP_MAX_RETRANSMITS 7 // Defined by RFC5389 (Rc) - should be configurable
34#define TCP_RESPONSE_TIME 39500 // Defined by RFC5389 (Ti) - should be configurable
35#define UDP_Rm 16 // Defined by RFC5389 - should be configurable
36#define UDP_FINAL_REQUEST_TIME (UDP_RT0 * UDP_Rm) // Defined by RFC5389
37#define DEFAULT_RETRANS_INTERVAL_MS 0 // special value, indicates that exponential backoff will be used
38
39namespace reTurn {
40
42{
43public:
44 static unsigned int UnspecifiedLifetime;
45 static unsigned int UnspecifiedBandwidth;
46 static unsigned short UnspecifiedToken;
47 static asio::ip::address UnspecifiedIpAddress;
48
49 explicit TurnAsyncSocket(asio::io_context& ioService,
52 const asio::ip::address& address = UnspecifiedIpAddress,
53 unsigned short port = 0);
54 virtual ~TurnAsyncSocket();
55
56 virtual void disableTurnAsyncHandler();
57 virtual unsigned int getSocketDescriptor() = 0;
58
61 const asio::error_code& getBindError() const { return mBindError; }
62
63 // Note: Shared Secret requests have been deprecated by RFC5389, and not
64 // widely implemented in RFC3489 - so not really needed at all
66
67 // Set the username and password for all future requests
68 void setUsernameAndPassword(const char* username, const char* password, bool shortTermAuth=false);
69
70 // Sets the local HmacKey, used to check the integrity of incoming STUN messages
71 void setLocalPassword(const char* password);
72
73 // Software attribute
74 void setSoftware(const char* software);
75
76 void connect(const std::string& address, unsigned short port);
77
78 // Stun Binding Method - use getReflexiveTuple() to get binding info
79 void bindRequest();
80
81 // ICE connectivity check
82 void connectivityCheck(const StunTuple& targetAddr, uint32_t peerRflxPriority, bool setIceControlling, bool setIceControlled, unsigned int numRetransmits, unsigned int retrans_iterval_ms);
83
84 // Turn Allocation Methods
86 unsigned int bandwidth = UnspecifiedBandwidth, // kilobits per second
90 void refreshAllocation(unsigned int lifetimeSecs);
91 void destroyAllocation();
92
93 // Methods to control active destination
94 void setActiveDestination(const asio::ip::address& address, unsigned short port);
96
97 asio::ip::address& getConnectedAddress() noexcept { return mAsyncSocketBase.getConnectedAddress(); }
98 unsigned short getConnectedPort() const noexcept { return mAsyncSocketBase.getConnectedPort(); }
99
100 // Turn Send Methods
101 virtual void send(const char* buffer, size_t size); // framed
102 virtual void sendTo(const asio::ip::address& address, unsigned short port, const char* buffer, size_t size); // framed
103
104 virtual void sendUnframed(const std::shared_ptr<DataBuffer>& data); // Send unframed data
105 virtual void sendFramed(const std::shared_ptr<DataBuffer>& data);
106 virtual void sendToUnframed(const asio::ip::address& address, unsigned short port, const std::shared_ptr<DataBuffer>& data);
107 virtual void sendToFramed(const asio::ip::address& address, unsigned short port, const std::shared_ptr<DataBuffer>& data);
108
109 // Receive Methods
110 //asio::error_code receive(char* buffer, unsigned int& size, unsigned int timeout, asio::ip::address* sourceAddress=0, unsigned short* sourcePort=0);
111 //asio::error_code receiveFrom(const asio::ip::address& address, unsigned short port, char* buffer, unsigned int& size, unsigned int timeout);
112
113 virtual void close();
114 virtual void turnReceive();
115
117
118protected:
119 asio::error_code mBindError; // set by the constructors of the transport specific sockets
120
121 void handleReceivedData(const asio::ip::address& address, unsigned short port, const std::shared_ptr<DataBuffer>& data);
122 void handleChannelData(const std::shared_ptr<DataBuffer>& data);
123
124 asio::io_context& mIOService;
127
128 // Local Binding Info
130
131 // Authentication Info
137
138 // Attributes
140
141 // Used to check integrity of incoming STUN messages
143
144 // Turn Allocation Properties used in request
146
147 // Turn Allocation Properties from response
150 unsigned int mLifetime;
151
154
155private:
156 AsyncSocketBase& mAsyncSocketBase;
157 bool mCloseAfterDestroyAllocationFinishes;
158
159 // Request map (for retransmissions)
160 class RequestEntry : public std::enable_shared_from_this<RequestEntry>
161 {
162 public:
163 RequestEntry(asio::io_context& ioService, TurnAsyncSocket* turnAsyncSocket, StunMessage* requestMessage, unsigned int rc, unsigned int retrans_iterval_ms, const StunTuple* dest=NULL);
164 ~RequestEntry();
165
166 void startTimer();
167 void stopTimer();
168 void requestTimerExpired(const asio::error_code& e);
169
170 asio::io_context& mIOService;
171 TurnAsyncSocket* mTurnAsyncSocket;
172 StunMessage* mRequestMessage;
173 asio::steady_timer mRequestTimer;
174 unsigned int mRequestsSent;
175 unsigned int mTimeout;
176 const StunTuple* mDest;
177 const unsigned int mRc;
178 const unsigned int mRetransIntervalMs;
179 };
180 typedef std::map<UInt128, std::shared_ptr<RequestEntry>> RequestMap;
181 RequestMap mActiveRequestMap;
182 friend class RequestEntry;
183 void requestTimeout(UInt128 tid);
184 void clearActiveRequestMap();
185
186 // weak functor template, used to reference the parent without explicitly
187 // preventing it from being garbage collected. Functor will only call the
188 // parent if it is still available.
189 template < typename P, typename F > class weak_bind
190 {
191 public:
192 // !jjg! WARNING! if you are using std::bind(..) to create the second
193 // argument for this constructor BE CAREFUL that you are passing 'this' and
194 // not 'shared_from_this()' to the bind(..) -- otherwise you will defeat the
195 // purpose of this class holding a weak_ptr
196 weak_bind(std::weak_ptr<P> parent, std::function<F> func)
197 : mParent(std::move(parent)), mFunction(std::move(func))
198 {
199 }
200
201 void operator()()
202 {
203 if (std::shared_ptr<P> ptr = mParent.lock())
204 {
205 if (mFunction)
206 mFunction();
207 }
208 }
209
210 void operator()(const asio::error_code& e)
211 {
212 if (std::shared_ptr<P> ptr = mParent.lock())
213 {
214 if (mFunction)
215 mFunction(e);
216 }
217 }
218
219 private:
220 std::weak_ptr<P> mParent;
221 std::function<F> mFunction;
222 };
223
224 asio::steady_timer mAllocationTimer;
225 void startAllocationTimer();
226 void cancelAllocationTimer();
227 void allocationTimerExpired(const asio::error_code& e);
228
229 typedef std::map<unsigned short, asio::steady_timer*> ChannelBindingTimerMap;
230 ChannelBindingTimerMap mChannelBindingTimers;
231 void startChannelBindingTimer(unsigned short channel);
232 void cancelChannelBindingTimers();
233 void channelBindingTimerExpired(const asio::error_code& e, unsigned short channel);
234
235 void doRequestSharedSecret();
236 void doSetUsernameAndPassword(resip::Data&& username, resip::Data&& password, bool shortTermAuth);
237 void doSetLocalPassword(resip::Data&& password);
238 void doSetSoftware(resip::Data&& software);
239 void doBindRequest();
240 void doConnectivityCheck(StunTuple* targetAddr, uint32_t peerRflxPriority, bool setIceControlling, bool setIceControlled, unsigned int numRetransmits, unsigned int retrans_iterval_ms);
241 void doCreateAllocation(unsigned int lifetime = UnspecifiedLifetime,
242 unsigned int bandwidth = UnspecifiedBandwidth,
246 void doRefreshAllocation(unsigned int lifetime);
247 void doDestroyAllocation();
248 void doSetActiveDestination(const asio::ip::address& address, unsigned short port);
249 void doClearActiveDestination();
250 void doSendFramed(const std::shared_ptr<DataBuffer>& data);
251 void doSendToFramed(const asio::ip::address& address, unsigned short port, const std::shared_ptr<DataBuffer>& data);
252 void doClose();
253 void actualClose();
254 void doChannelBinding(RemotePeer& remotePeer);
255
256 StunMessage* createNewStunMessage(uint16_t stunclass, uint16_t method, bool addAuthInfo=true);
257 void sendStunMessage(StunMessage* request, bool reTransmission=false, unsigned int numRetransmits=UDP_MAX_RETRANSMITS, unsigned int retrans_iterval_ms=DEFAULT_RETRANS_INTERVAL_MS, const StunTuple* targetAddress=NULL);
258 void sendToRemotePeer(RemotePeer& remotePeer, const std::shared_ptr<DataBuffer>& data);
259 void sendOverChannel(unsigned short channel, const std::shared_ptr<DataBuffer>& data); // send with turn framing
260
261 asio::error_code handleStunMessage(StunMessage& stunMessage);
262 asio::error_code handleDataInd(StunMessage& stunMessage);
263 asio::error_code handleChannelBindResponse(StunMessage &request, StunMessage &response);
264 asio::error_code handleSharedSecretResponse(StunMessage &request, StunMessage &response);
265 asio::error_code handleBindRequest(StunMessage& stunMessage);
266 asio::error_code handleBindResponse(StunMessage &request, StunMessage &response);
267 asio::error_code handleAllocateResponse(StunMessage &request, StunMessage &response);
268 asio::error_code handleRefreshResponse(StunMessage &request, StunMessage &response);
269};
270
271}
272
273#endif
274
275
276/* ====================================================================
277
278 Copyright (c) 2023-2026, SIP Specturm, Inc. http://sipspectrum.com
279 Copyright (c) 2007-2008, Plantronics, Inc.
280 All rights reserved.
281
282 Redistribution and use in source and binary forms, with or without
283 modification, are permitted provided that the following conditions are
284 met:
285
286 1. Redistributions of source code must retain the above copyright
287 notice, this list of conditions and the following disclaimer.
288
289 2. Redistributions in binary form must reproduce the above copyright
290 notice, this list of conditions and the following disclaimer in the
291 documentation and/or other materials provided with the distribution.
292
293 3. Neither the name of Plantronics nor the names of its contributors
294 may be used to endorse or promote products derived from this
295 software without specific prior written permission.
296
297 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
298 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
299 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
300 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
301 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
303 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
304 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
305 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
306 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
307 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
308
309 ==================================================================== */
#define UDP_MAX_RETRANSMITS
#define DEFAULT_RETRANS_INTERVAL_MS
asio::ip::address & getConnectedAddress() noexcept
unsigned short getConnectedPort() const noexcept
std::function< void(unsigned int)> BeforeClosedHandler
static const uint8_t PropsNone
void refreshAllocation(unsigned int lifetimeSecs)
virtual unsigned int getSocketDescriptor()=0
resip::RecursiveMutex mHandlerMutex
virtual void sendUnframed(const std::shared_ptr< DataBuffer > &data)
void connectivityCheck(const StunTuple &targetAddr, uint32_t peerRflxPriority, bool setIceControlling, bool setIceControlled, unsigned int numRetransmits, unsigned int retrans_iterval_ms)
unsigned short getConnectedPort() const noexcept
virtual void sendToFramed(const asio::ip::address &address, unsigned short port, const std::shared_ptr< DataBuffer > &data)
static unsigned int UnspecifiedBandwidth
void setUsernameAndPassword(const char *username, const char *password, bool shortTermAuth=false)
void handleReceivedData(const asio::ip::address &address, unsigned short port, const std::shared_ptr< DataBuffer > &data)
void connect(const std::string &address, unsigned short port)
StunTuple::TransportType mRelayTransportType
void createAllocation(unsigned int lifetimeSecs=UnspecifiedLifetime, unsigned int bandwidth=UnspecifiedBandwidth, unsigned char requestedPortProps=StunMessage::PropsNone, uint64_t reservationToken=UnspecifiedToken, StunTuple::TransportType requestedTransportType=StunTuple::None)
virtual void sendToUnframed(const asio::ip::address &address, unsigned short port, const std::shared_ptr< DataBuffer > &data)
TurnAsyncSocketHandler * mTurnAsyncSocketHandler
asio::ip::address & getConnectedAddress() noexcept
asio::io_context & mIOService
void setSoftware(const char *software)
StunTuple::TransportType mRequestedTransportType
const asio::error_code & getBindError() const
The outcome of binding the socket to the local address and port it was created with: eg.
static asio::ip::address UnspecifiedIpAddress
virtual void sendTo(const asio::ip::address &address, unsigned short port, const char *buffer, size_t size)
virtual void sendFramed(const std::shared_ptr< DataBuffer > &data)
static unsigned short UnspecifiedToken
void setActiveDestination(const asio::ip::address &address, unsigned short port)
static unsigned int UnspecifiedLifetime
void handleChannelData(const std::shared_ptr< DataBuffer > &data)
virtual void setOnBeforeSocketClosedFp(AsyncSocketBase::BeforeClosedHandler fp)
virtual void send(const char *buffer, size_t size)
void setLocalPassword(const char *password)
virtual void disableTurnAsyncHandler()
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
std::recursive_mutex RecursiveMutex
Definition Mutex.hxx:38
unsigned short uint16_t
Definition stdint.h:84
unsigned int uint32_t
Definition stdint.h:85
unsigned __int64 uint64_t
Definition stdint.h:95
void list()
Definition userAdmin.cxx:66