8#define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
13#ifdef BOOST_ASIO_HAS_STD_CHRONO
14using namespace std::chrono;
17using namespace std::chrono;
24 mRequestHandler(requestHandler),
25 mAlternatePortUdpServer(0),
26 mAlternateIpUdpServer(0),
27 mAlternateIpPortUdpServer(0)
29 asio::error_code ec =
bind(address, port);
32 ErrLog(<<
"Unable to start UdpServer listening on " << address.to_string() <<
":" << port <<
", error=" << ec.value() <<
" - " << ec.message());
33 throw asio::system_error(ec);
37 InfoLog(<<
"UdpServer started. Listening on " << address.to_string() <<
":" << port);
43 ResponseMap::iterator it = mResponseMap.begin();
44 for(;it != mResponseMap.end(); it++)
55 mLocalAddress =
mSocket.local_endpoint(ec).address();
56 mLocalPort =
mSocket.local_endpoint(ec).port();
66 mAlternatePortUdpServer = alternatePort;
67 mAlternateIpUdpServer = alternateIp;
68 mAlternateIpPortUdpServer = alternateIpPort;
74 return mAlternatePortUdpServer != 0;
84UdpServer::onReceiveSuccess(
const asio::ip::address& address,
unsigned short port,
const std::shared_ptr<DataBuffer>& data)
98 if(((*data)[0] & 0xC0) == 0)
103 (
char*)&(*data)[0], (
unsigned int)data->size());
104 if(request.isValid())
108 ResponseMap::iterator it = mResponseMap.find(request.mHeader.magicCookieAndTid);
109 if(it == mResponseMap.end())
122 responseUdpServer = mAlternatePortUdpServer;
125 responseUdpServer = mAlternateIpUdpServer;
128 responseUdpServer = mAlternateIpPortUdpServer;
132 responseUdpServer =
this;
141 InfoLog(<<
"UdpServer: received retransmission of request with tid: " << request.mHeader.magicCookieAndTid);
142 response = it->second->mResponseMessage;
143 responseUdpServer = it->second->mResponseUdpServer;
146 constexpr size_t RESPONSE_BUFFER_SIZE = 1024;
148 unsigned int responseSize;
149 responseSize = response->
stunEncodeMessage((
char*)buffer->data(), RESPONSE_BUFFER_SIZE);
150 buffer->truncate(responseSize);
157 unsigned short channelNumber;
158 memcpy(&channelNumber, &(*data)[0], 2);
159 channelNumber = ntohs(channelNumber);
161 unsigned short dataLen;
162 memcpy(&dataLen, &(*data)[2], 2);
163 dataLen = ntohs(dataLen);
166 if(data->size() < (
unsigned int)(dataLen + 4))
168 WarningLog(<<
"ChannelData message size=" << dataLen+4 <<
" too larger for UDP packet size=" << data->size() <<
". Dropping.");
182 WarningLog(<<
"Not enough data for stun message or framed message. Dropping.");
189UdpServer::onReceiveFailure(
const asio::error_code& e)
191 if(e != asio::error::operation_aborted)
193 InfoLog(<<
"UdpServer::onReceiveFailure: " << e.value() <<
"-" << e.message());
200UdpServer::onSendSuccess()
205UdpServer::onSendFailure(
const asio::error_code& error)
207 if(error != asio::error::operation_aborted)
209 InfoLog(<<
"UdpServer::onSendFailure: " << error.value() <<
"-" << error.message());
213UdpServer::ResponseEntry::ResponseEntry(UdpServer* requestUdpServer, UdpServer* responseUdpServer,
StunMessage* responseMessage) :
214 mResponseUdpServer(responseUdpServer),
215 mResponseMessage(responseMessage),
216 mCleanupTimer(requestUdpServer->mIOService)
219 mCleanupTimer.expires_after(seconds(10));
220 mCleanupTimer.async_wait(std::bind(&
UdpServer::cleanupResponseMap, requestUdpServer, std::placeholders::_1, responseMessage->mHeader.magicCookieAndTid));
223UdpServer::ResponseEntry::~ResponseEntry()
225 delete mResponseMessage;
231 ResponseMap::iterator it = mResponseMap.find(tid);
232 if(it != mResponseMap.end())
234 DebugLog(<<
"UdpServer::cleanupResponseMap - removing transaction id=" << tid);
236 mResponseMap.erase(it);
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
static std::shared_ptr< DataBuffer > allocateBuffer(size_t size)
Utility API.
virtual void doSend(const StunTuple &destination, unsigned short channel, const std::shared_ptr< DataBuffer > &data, const std::size_t bufferStartPos=0)
Use these if you already operating within the ioService thread.
asio::ip::udp::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...
The common handler for all incoming requests.
void processTurnData(TurnAllocationManager &turnAllocationManager, unsigned short channelNumber, const StunTuple &localTuple, const StunTuple &remoteTuple, const std::shared_ptr< DataBuffer > &data)
ProcessResult processStunMessage(AsyncSocketBase *turnSocket, TurnAllocationManager &turnAllocationManager, StunMessage &request, StunMessage &response, bool isRFC3489BackwardsCompatServer=false)
Process a received StunMessage, and produce a reply Returns true if the response message is to be sen...
@ RespondFromAlternateIpPort
@ RespondFromAlternatePort
unsigned int stunEncodeMessage(char *buf, unsigned int bufLen)
virtual void start() override
void setAlternateUdpServers(UdpServer *alternatePort, UdpServer *alternateIp, UdpServer *alternateIpPort)
This method is used if this UdpServer supports RFC3489 operation - note turnFraming in constructor mu...
bool isRFC3489BackwardsCompatServer()
asio::ip::udp::socket & getSocket()
UdpServer(asio::io_context &ioService, RequestHandler &requestHandler, const asio::ip::address &address, unsigned short port)
Create the server to listen on the specified UDP address and port.
void cleanupResponseMap(const asio::error_code &e, UInt128 tid)
dcm! – add UnusedChecking(_enum) below;
UInt128 magicCookieAndTid