コード例 #1
0
ファイル: SipUdpServer.cpp プロジェクト: Konnekt/lib-sipx
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);
}