Hi all, I try to implement the STUN, but now I got a matter.
As I read the WIKI, I wrote some code for my UA, now the UA can be used the STUN to register to server,
The attachment is SIP message log and there are my source code, please help me to solve this problem.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool UserAgent::addUDPPort(int port, bool enableSTUN)
{
bool state = true;
try
{
mUDPTransport = (resip::UdpTransport*)mStack.addTransport(UDP, port, V4, StunEnabled);
}
catch(const Transport::Exception& e)
{
state = false;
}
return state;
}
void UserAgent::sendStunTest()
{
if (!mUDPTransport)
{
return;
}
hostent* h = gethostbyname(mStunServer.c_str());
if (!h)
{
return;
}
in_addr sin_addr = *(struct in_addr*)h->h_addr;
resip::Tuple tStunDest(sin_addr, 3478, UDP, Data::Empty);
mUDPTransport->stunSendTest(tStunDest);
mLastStunTestTime = GetTickCount();
}
resip::Tuple UserAgent::getStunAddress()
{
resip::Tuple mappedAddress;
mappedAddress.setPort(0);
if (!mUDPTransport)
{
return mappedAddress;
}
if (!mUDPTransport->stunResult(mappedAddress))
{
// 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 tmpLastStunTestTime = mLastStunTestTime;
while ((GetTickCount() - tmpLastStunTestTime) < 5 * 1000) // wait 5s for result
{
if (mUDPTransport->stunResult(mappedAddress))
{
break;
}
Sleep(200);
}
mLastStunTestTime = 0;
return mappedAddress;
}
void UserAgent::stunTest(const Data & stunServer, int stunPort)
{
mStunServer = stunServer;
mStunPort = stunPort;
if (stunServer.empty() == true)
{
return;
}
string ip;
int port;
Utility utility;
string emptyIP = "0.0.0.0";
for (int i=0; i<3; ++i)
{
Tuple mapAddress = getStunAddress();
ip = Tuple::inet_ntop(mapAddress).c_str();
port = mapAddress.getPort();
if (utility.compareStringNoCase(ip, emptyIP) != 0)
{
break;
}
}
if (utility.compareStringNoCase(ip, emptyIP) == 0)
{
return;
}
Data newUri = "sip:";
newUri += ip.c_str();
newUri += ":";
Data temPort(port);
newUri += temPort;
Uri stunUri(newUri);
mMasterProfile->setOverrideHostAndPort(stunUri);
StunMessageDecorator * stunMessageDec = new StunMessageDecorator;
stunMessageDec->setStunResult(ip, port);
SharedPtr<MessageDecorator> messageDec((MessageDecorator *)stunMessageDec);
mMasterProfile->setOutboundDecorator(messageDec);
}
void StunMessageDecorator::decorateMessage(SipMessage &msg, const Tuple &source, const Tuple &destination)
{
if (mStunPort!=0 && mStunIP.empty()==false)
{
Utility utility;
ParserContainer<Via>::iterator viaIter = msg.header(h_Vias).begin();
for (; viaIter!=msg.header(h_Vias).end(); ++viaIter)
{
string srcIP = Tuple::inet_ntop(source).c_str();
string viaIP = msg.header(h_Vias).front().sentHost().c_str();
if (utility.compareStringNoCase(srcIP, viaIP) == 0)
{
msg.header(h_Vias).front().sentPort() = mStunPort;
msg.header(h_Vias).front().sentHost() = mStunIP.c_str();
}
}
}
}