Resiprocate implements STUN client and server support
reSIProcate is able to act as an STUN server on each configured UDP transport. This means that reSIProcate will accept and respond to STUN requests from external clients. Usually STUN is done through a separate STUN server which operates on a different port (or even a different machine). The advantage of using STUN through the SIP port is that this may help traversing even symmetric NATs. Though, this method is not very popular currently and it doesn't really help if RTP streams are involved.
To activate STUN server support you must simply pass the "StunEnabled" value with the "AddTransport" method.
Note: The DialogUsageManager::AddTransport method simply maps through to the SipStack::AddTransport but with fewer parameters. Therefore probably it's best to use the method on the SipStack directly.
The UdpTransport class includes support for sending STUN requests to a STUN server. To use this feature you need to store a pointer to UdpTransport when adding the transport:
m_pUdpTransport = (resip::UdpTransport*)mStack->addTransport(UDP, UDPPort, V4, StunEnabled, IPAddress));
UdpTransport includes two methods for STUN client support:
bool stunSendTest(const Tuple& dest);
bool stunResult(Tuple& mappedAddress);
The first one sends a STUN request to dest, the second one retrieves the result (if any).
Obviously this implementation is asynchronous. If you need to determine the mapped STUN address in a synchronous way (e.g. in order to make a call) you could use something similar to this:
if (!m_pUdpTransport) return;
hostent* h = gethostbyname(STUNServer);
in_addr sin_addr = *(struct in_addr*)h->h_addr;
resip::Tuple tStunDest(sin_addr, STUNPort, UDP, Data::Empty);
mLastStunTestTime = GetTickCount();
..for sending the STUN request and the following to retrieve a result synchronously:
if (!m_pUdpTransport) return mMappedAddress;
// no valid result available, send another request
else if ((GetTickCount() - mLastStunTestTime) > 1000 * 60 * 3)
// don't use a STUN response that is older than 3 minutes
DWORD dwTmpLastStunTestTime = mLastStunTestTime;
while ((GetTickCount() - dwTmpLastStunTestTime) < 5 * 1000) // wait 5s for result