Difference between revisions of "STUN support"

From reSIProcate
Jump to navigation Jump to search
Line 39: Line 39:
  
 
''void SendStunTest()''
 
''void SendStunTest()''
 +
 
''{''
 
''{''
 +
 
'' if (!m_pUdpTransport) return;''
 
'' if (!m_pUdpTransport) return;''
 +
 
'' hostent* h = gethostbyname(STUNServer);''
 
'' hostent* h = gethostbyname(STUNServer);''
 +
 
'' in_addr sin_addr = *(struct in_addr*)h->h_addr;''
 
'' in_addr sin_addr = *(struct in_addr*)h->h_addr;''
 +
 
'' resip::Tuple tStunDest(sin_addr, STUNPort, UDP, Data::Empty);''
 
'' resip::Tuple tStunDest(sin_addr, STUNPort, UDP, Data::Empty);''
 +
 
'' m_pUdpTransport->stunSendTest(tStunDest);''
 
'' m_pUdpTransport->stunSendTest(tStunDest);''
 +
 
'' mLastStunTestTime = GetTickCount();''
 
'' mLastStunTestTime = GetTickCount();''
 +
 
''}''
 
''}''
 +
  
  
Line 53: Line 62:
  
 
''resip::Tuple GetStunAddress()''
 
''resip::Tuple GetStunAddress()''
 +
 
''{''
 
''{''
 +
 
'' resip::Tuple mMappedAddress;''
 
'' resip::Tuple mMappedAddress;''
 +
 
'' mMappedAddress.setPort(0);''
 
'' mMappedAddress.setPort(0);''
 +
  
 
'' if (!m_pUdpTransport) return mMappedAddress;''
 
'' if (!m_pUdpTransport) return mMappedAddress;''
  
 
'' if (!m_pUdpTransport->stunResult(mMappedAddress))''
 
'' if (!m_pUdpTransport->stunResult(mMappedAddress))''
 +
 
'' {''
 
'' {''
 +
 
'' // no valid result available, send another request''
 
'' // no valid result available, send another request''
 +
 
'' SendStunTest();''
 
'' SendStunTest();''
 +
 
'' }''
 
'' }''
 +
 
'' else if ((GetTickCount() - mLastStunTestTime) > 1000 * 60 * 3)''  
 
'' else if ((GetTickCount() - mLastStunTestTime) > 1000 * 60 * 3)''  
 +
 
'' {''
 
'' {''
'' // don't use a STUN response that is older than 3 minutes''
+
 
 +
'' // don't use a STUN response that is older than 3 minutes''
 +
 
'' SendStunTest();''
 
'' SendStunTest();''
 +
 
'' }''
 
'' }''
 +
  
 
'' DWORD dwTmpLastStunTestTime = mLastStunTestTime;''
 
'' DWORD dwTmpLastStunTestTime = mLastStunTestTime;''
 +
 
'' while ((GetTickCount() - dwTmpLastStunTestTime) < 5 * 1000) // wait 5s for result''
 
'' while ((GetTickCount() - dwTmpLastStunTestTime) < 5 * 1000) // wait 5s for result''
 +
 
'' {''
 
'' {''
 +
 
'' if (m_pUdpTransport->stunResult(mMappedAddress))''
 
'' if (m_pUdpTransport->stunResult(mMappedAddress))''
 +
 
'' break;''
 
'' break;''
 +
 
'' Sleep(200);''
 
'' Sleep(200);''
 +
 
'' }''
 
'' }''
 +
  
 
'' return mMappedAddress;''
 
'' return mMappedAddress;''
 +
 
''}''
 
''}''

Revision as of 17:01, 9 April 2006

Resiprocate implements STUN client and server support


STUN Server

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.


STUN Client

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:


void SendStunTest()

{

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);

m_pUdpTransport->stunSendTest(tStunDest);

mLastStunTestTime = GetTickCount();

}


..for sending the STUN request and the following to retrieve a result synchronously:


resip::Tuple GetStunAddress()

{

resip::Tuple mMappedAddress;

mMappedAddress.setPort(0);


if (!m_pUdpTransport) return mMappedAddress;

if (!m_pUdpTransport->stunResult(mMappedAddress))

{

// no valid result available, send another request

SendStunTest();

}

else if ((GetTickCount() - mLastStunTestTime) > 1000 * 60 * 3)

{

// don't use a STUN response that is older than 3 minutes

SendStunTest();

}


DWORD dwTmpLastStunTestTime = mLastStunTestTime;

while ((GetTickCount() - dwTmpLastStunTestTime) < 5 * 1000) // wait 5s for result

{

if (m_pUdpTransport->stunResult(mMappedAddress))

break;

Sleep(200);

}


return mMappedAddress;

}