int SipUdpServer::run(void* runArg) { int cseq = 1; if(mSipUserAgent) { UtlString contact; mSipUserAgent->getContactUri(&contact); // Add a tag to the contact and build the from field UtlString from(contact); int tagRand1 = rand(); int tagRand2 = rand(); char fromTag[80]; sprintf(fromTag, ";tag=%d%d", tagRand1, tagRand2); from.append(fromTag); UtlString rawAddress; int port; Url pingUrl(mNatPingUrl); // Create a cannonized version of the ping URL in case // it does not specify "sip:", etc. UtlString cannonizedPingUrl = pingUrl.toString(); // Get the address and port in the png URL so that // we can look up the DNS stuff if needed port = pingUrl.getHostPort(); pingUrl.getHostAddress(rawAddress); // Resolve the raw address from a DNS SRV, A record // to an IP address server_t* dnsSrvRecords = SipSrvLookup::servers(rawAddress.data(), "sip", OsSocket::UDP, port); // Do a DNS SRV or A record lookup // If we started with an IP address, we will still get an IP // address in the result UtlString address; if(dnsSrvRecords[0].isValidServerT()) { // Get the highest priority address and port from the // list with randomization of those according to the // weights. // Note: we are not doing any failover here as that is // a little tricky with the NAT stuff. We cannot change // addresses with every transaction as we may get different // ports and addresses every time we send a ping. For now // we do one DNS SRV lookup at the begining of time and // stick to that result. dnsSrvRecords[0].getIpAddressFromServerT(address); port = dnsSrvRecords[0].getPortFromServerT(); // If the ping URL or DNS SRV did not specify a port // bind it to the default port. if (!portIsValid(port)) { port = SIP_PORT; } } // Did not get a valid response from the DNS lookup else { // Configured with a bad DNS name that did not resolve. // Or the DNS server did not respond. if(!rawAddress.isNull()) { OsSysLog::add(FAC_SIP, PRI_INFO, "SipUdpServer::run DNS lookup failed for ping host: %s in URI: %s", rawAddress.data(), mNatPingUrl.data()); } // Else no ping address, this means we are not supposed to // do a ping } // Free the list of server addresses. delete[] dnsSrvRecords; // Get the address to be used in the callId scoping int dummyPort; UtlString callId; if (mSipUserAgent) { mSipUserAgent->getViaInfo(OsSocket::UDP, callId, dummyPort); } // Make up a call Id long epochTime = OsDateTime::getSecsSinceEpoch(); int randNum = rand(); char callIdPrefix[80]; sprintf(callIdPrefix, "%ld%d-ping@", epochTime, randNum); callId.insert(0,callIdPrefix); while(mNatPingFrequencySeconds > 0 && !mNatPingUrl.isNull() && !mNatPingMethod.isNull() && !address.isNull()) { // Send a no-op SIP message to the // server to keep a port open through a NAT // based firewall SipMessage pingMessage; pingMessage.setRequestData(mNatPingMethod, cannonizedPingUrl.data(), from.data(), mNatPingUrl.data(), callId, cseq, contact.data()); // Get the UDP via info from the SipUserAgent UtlString viaAddress; int viaPort; if (mSipUserAgent) { mSipUserAgent->getViaInfo(OsSocket::UDP, viaAddress, viaPort); } pingMessage.addVia(viaAddress.data(), viaPort, SIP_TRANSPORT_UDP); // Mark the via so the receiver knows we support and want the // received port to be set pingMessage.setLastViaTag("", "rport"); # ifdef TEST_PRINT osPrintf("Sending ping to %s %d, From: %s\n", address.data(), port, contact.data()); # endif // Send from the same UDP port that we receive from if (mSipUserAgent) { mSipUserAgent->sendSymmetricUdp(pingMessage, address.data(), port); } cseq++; // Wait until it is time to send another ping delay(mNatPingFrequencySeconds * 1000); } } return(mNatPingFrequencySeconds); }