⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 siptransceiver.cxx

📁 SIP(Session Initiation Protocol)是由IETF定义
💻 CXX
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0  *  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. *  * 3. The names "VOCAL", "Vovida Open Communication Application Library", *    and "Vovida Open Communication Application Library (VOCAL)" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor *    may "VOCAL" appear in their name, without prior written *    permission of Vovida Networks, Inc. *  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * ==================================================================== *  * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc.  For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */static const char* const SipTransceiver_cxx_Version =    "$Id: SipTransceiver.cxx,v 1.80.2.1 2003/02/25 01:18:17 bko Exp $";#include "global.h"#include <cstdlib>#include <cassert>#include <sys/time.h>#include <string>#include <Sptr.hxx>#include "SipCommand.hxx"#include "StatusMsg.hxx"#include "InviteMsg.hxx"#include "CancelMsg.hxx"#include "AckMsg.hxx"#include "ByeMsg.hxx"#include "RegisterMsg.hxx"#include "OptionsMsg.hxx"#include "InfoMsg.hxx"#include "ReferMsg.hxx"#include "TransferMsg.hxx"#include "SipVia.hxx"#include "SipFrom.hxx"#include "SipContact.hxx"#include "SipCSeq.hxx"#include "SipSnmpDetails.hxx"#include "SipTransactionId.hxx"#include "SipTransceiver.hxx"#include "SystemInfo.hxx"using namespace Vocal;class TransactionDBStatus: public SipDebuggingStatus{    public:        TransactionDBStatus(SipTransactionDB& x, Data label )            :myItem(x),             myLabel(label + ": ")            {            }        Data status()            {                return myLabel + myItem.getDetails();            }    private:        SipTransactionDB& myItem;        Data myLabel;};class SipUdpStatus : public SipDebuggingStatus{    public:        SipUdpStatus(SipUdpConnection& x, int port)            :myItem(x),             myLabel()            {                char buf[256];                sprintf(buf, "UDP Stack (port %d): ", port);                myLabel = buf;            }        Data status()            {                return myLabel + myItem.getDetails();            }    private:        SipUdpConnection& myItem;        Data myLabel;};SipAppContext SipTransceiver::myAppContext = APP_CONTEXT_GENERIC;SipTransceiver::SipTransceiver( Data adata, 				int siplistenPort, 				bool nat  /*Default Agruments*/,				SipAppContext aContext  /*Default Agruments*/)    :    recvdMsgsFifo(),    udpConnection(0),    tcpConnection(0),    sentRequestDB(),    sentResponseDB(){    myAppContext = aContext;    cpLog( LOG_DEBUG_STACK, "SipStack listening on port %d ", siplistenPort );    cpLog( LOG_DEBUG_STACK, "SipStack context %s ", (myAppContext == APP_CONTEXT_PROXY) ? "Proxy" : "Non-Proxy" );    udpConnection = new SipUdpConnection( &recvdMsgsFifo, siplistenPort );    if ( udpConnection == 0 )    {        cpLog(LOG_INFO, "SipTransceiver::unable to instantiate UDP connections");    }    tcpConnection = new SipTcpConnection( &recvdMsgsFifo, siplistenPort );    if ( tcpConnection == 0 )    {        cpLog(LOG_INFO, "SipTransceiver::unable to instantiate TCP connections");    }    application = adata;    Data nameport;    nameport += adata;    nameport += ":";    nameport += Data(siplistenPort);    //sipAgent = new SipAgent(nameport);    natOn = nat;    Vocal::theSystem.setSystemPort(siplistenPort);    char* port;    if((port = getenv("VOCAL_SIP_REPORTER")))    {        debugger = new SipDebuggingInterface(atoi(port));         debugger->add(new TransactionDBStatus(sentRequestDB, "Request DB"));        debugger->add(new TransactionDBStatus(sentResponseDB, "Response DB"));        debugger->add(new SipUdpStatus(*udpConnection, siplistenPort));    }    myLocalNamePort = nameport;}SipTransceiver::~SipTransceiver(){    // xxx - this needs to close up shop    SipTransactionGC::shutdown();}voidSipTransceiver::sendAsync(SipCommand& sipMessage){    if ( !(sipMessage.checkMaxForwards()) )    {        cpLog(LOG_DEBUG_STACK, "SipTransceiver: sendAsync: %s",              sipMessage.encode().logData());        cpLog(LOG_DEBUG_STACK, "reached MaxForwards limit, not sending");        return ;    }    SipMsgContainer* msgPtr 	= sentRequestDB.processSend(	    copyPtrtoSptr(&sipMessage));    if(msgPtr)    {	//// should this only be for actually sent messages? /////////	if (sipAgent != 0)	{	    updateSnmpData(copyPtrtoSptr(&sipMessage), OUTS);	}	//////////////////////////////////////////////////////////////		send(msgPtr);    }}voidSipTransceiver::sendAsync(Sptr<SipCommand> sipMessage, const Data& host,                       const Data& port) {    if ( !(sipMessage->checkMaxForwards()) )    {        cpLog(LOG_DEBUG_STACK, "SipTransceiver: sendAsync: %s",              sipMessage->encode().logData());        cpLog(LOG_DEBUG_STACK, "reached MaxForwards limit, not sending");        return ;    }    SipMsgContainer* msgPtr = sentRequestDB.processSend(sipMessage);        if(msgPtr)    {	//// should this only be for actually sent messages? /////////	if (sipAgent != 0)	{	    updateSnmpData(sipMessage, OUTS);	}	//////////////////////////////////////////////////////////////	send(msgPtr, host, port);    }}voidSipTransceiver::sendReply(StatusMsg& sipMessage){    //// should this not be symmetric to what we are doing in sendAsync????    //// (its missing all the checks and the snmp update)    SipMsgContainer *sipMsg 	= sentResponseDB.processSend(	    copyPtrtoSptr(&sipMessage));    if(sipMsg)    {	send(sipMsg);    }}voidSipTransceiver::sendReply(Sptr<StatusMsg> sipMessage){    //// should this not be symmetric to what we are doing in sendAsync????    //// (its missing all the checks and the snmp update)        SipMsgContainer *sipMsg = sentResponseDB.processSend(sipMessage);    if(sipMsg)    {	send(sipMsg);    }}voidSipTransceiver::send(SipMsgContainer *sipMsg, const Data& host,                       const Data& port){    if ((sipMsg->msg.transport == TCP) ||        (sipMsg->msg.transport == "tcp"))    {        if (tcpConnection != 0)        {            //send on tcp.            tcpConnection->send(sipMsg, host, port);        }        else        {            cpLog(LOG_INFO, "TCP connection not instantiated");	    /// hence delete the msg container	    SipTransactionGC::instance()->                collect(sipMsg, ORPHAN_CLEANUP_DELAY);        }    }    else    {        if (udpConnection != 0)        {            //send on udp.            udpConnection->send(sipMsg, host, port);        }        else        {            cpLog(LOG_INFO, "UDP connection not instantiated");	    /// hence delete the msg container	    SipTransactionGC::instance()->                collect(sipMsg, ORPHAN_CLEANUP_DELAY);        }    }}Sptr < SipMsgQueue > SipTransceiver::receive(int timeOut){    Sptr < SipMsgQueue > msgQPtr = 0;      timeval start, now;      if ( timeOut >= 0 )    {	gettimeofday(&start, 0);    }      while (msgQPtr == 0)    {	int timePassed = 0;	if ( timeOut >= 0 )        {	    gettimeofday(&now, 0);	  	    timePassed = ( now.tv_sec - start.tv_sec ) * 1000		+ ( now.tv_usec - start.tv_usec ) / 1000;	  	    if (timePassed >= timeOut)            {		//cpLog(LOG_DEBUG_STACK, "timeout value exceeded");		return 0;            }	}	recvdMsgsFifo.block(timeOut-timePassed);      	if ( !recvdMsgsFifo.messageAvailable() )	{	    continue;	}            	SipMsgContainer *msgPtr = recvdMsgsFifo.getNext();	if ( msgPtr == 0)	{	    assert(0);//            cpLog(LOG_CRIT, "received NULL");	    continue;	}	/********************** TO DO ****************************	 * not doing 'coz need to bring some stuff from udp impl	 * to here, so will do after 500 cps         * msgPtr->msg.in = SipMsg::decode(msgPtr->msg.out);	 *********************************************************/	/*****************************************************************	 * how does this affect the transactions, i.e. it is only being	 * done on received messages, so should this be before or after	 * going thru the data base (i.e. is it visible to transactionDB)?	 *****************************************************************/	/*********** decided to remove it from the stack ******************/        cpLog(LOG_DEBUG, "Received: %s",msgPtr->msg.in->briefString().c_str());        if ( natOn == true)	{	//changes for taking care of the NAT traversals	  SipVia natVia = msgPtr->msg.in->getVia(0);	  LocalScopeAllocator lo;           //cpLog (LOG_DEBUG, "natVia = %s", natVia.encode().logData());	  string addr1 = natVia.getHost().getData(lo);	  string addr2 = msgPtr->msg.in->getReceivedIPName().getData(lo);          //addr2 can be empty if stack had generated the message like 408          if(addr2 != "")          {	    NetworkAddress netaddr1(addr1);	    NetworkAddress netaddr2(addr2);	  	    if ( netaddr1.getIpName() != netaddr2.getIpName() || (addr1 == ""))	    {	      natVia.setReceivedhost(msgPtr->msg.in->getReceivedIPName());	      natVia.setReceivedport(msgPtr->msg.in->getReceivedIPPort());	      //remove the first item from the via list	      msgPtr->msg.in->removeVia(0);	      //insert natvia in the vector via list	      msgPtr->msg.in->setVia(natVia, 0);	    }          }	}	//---NAT/*	*********************************************************************/	              cpLog(LOG_DEBUG, "Received: %s",msgPtr->msg.in->briefString().c_str());	cpLog(LOG_DEBUG_STACK, "msg is; %s",msgPtr->msg.out.logData());      	SipMsgQueue *msgQ = 0;	Sptr<SipMsg> sipPtr = msgPtr->msg.in;	if(msgPtr->msg.in->getType() == SIP_STATUS)	    msgQ = sentRequestDB.processRecv(msgPtr);	else	    msgQ = sentResponseDB.processRecv(msgPtr);      	if(msgQ)	{	    msgQPtr = msgQ;	  	    //need to have snmpDetails for this.	    if (sipAgent != 0)	    {		updateSnmpData(sipPtr, INS);	    }	}	else if(msgPtr->msg.in != 0)	{	    send(msgPtr);	}	else if(msgPtr->msg.out.length())	{	    send(msgPtr);	}	else	{	    delete msgPtr;	}    }    return msgQPtr;}voidSipTransceiver::reTransOff(){    cpLog(LOG_DEBUG_STACK, "*** Retransmission is turned off ***");    SipUdpConnection::reTransOff();}voidSipTransceiver::reTransOn(){    cpLog(LOG_DEBUG_STACK, "*** Retransmission is turned on ***");    SipUdpConnection::reTransOn();}voidSipTransceiver::setRetransTime(int initial, int max){    cpLog(LOG_DEBUG_STACK, "Initial time set to %d ms", initial);    cpLog(LOG_DEBUG_STACK, "Max time set to %d ms", max);    SipUdpConnection::setRetransTime(initial, max);}voidSipTransceiver::setRandomLosePercent(int percent){    if (udpConnection != 0)    {        udpConnection->setRandomLosePercent(percent);    }}SipTransactionDB::CallLegVectorSipTransceiver::getCallLegMsgs(Sptr < SipMsg > sipmsg){    //// will it always be on SentRequest???    return (sentRequestDB.getCallLegMsgs(sipmsg));}voidSipTransceiver::updateSnmpData(Sptr < SipMsg > sipMsg, SnmpType snmpType){    //come here only if snmpAgent is valid.    if (sipAgent == 0)        return ;    Method type = sipMsg->getType();    if (type == SIP_STATUS)    {        if (snmpType == INS)        {            sipAgent->updateSipCounter(sipSummaryInResponses);        }        else if (snmpType == OUTS)        {            sipAgent->updateSipCounter(sipSummaryOutResponses);        }        //get the status code of this msg.        Sptr < StatusMsg > statusMsg;        statusMsg.dynamicCast(sipMsg);        int statusCode = statusMsg->getStatusLine().getStatusCode();        if (snmpType == INS)        {            sipAgent->updateStatusSnmpData(statusCode, INS);        }        else if (snmpType == OUTS)        {            sipAgent->updateStatusSnmpData(statusCode, OUTS);	}    }    else    {        //this is a command.        if (snmpType == INS)        {            sipAgent->updateSipCounter(sipSummaryInRequests);            sipAgent->updateCommandSnmpData(type, INS);        }        else if (snmpType == OUTS)        {            sipAgent->updateSipCounter(sipSummaryOutRequests);            sipAgent->updateCommandSnmpData(type, OUTS);        }    }}voidSipTransceiver::printSize(){    cpLog(LOG_ERR, "%s:::::\n%s\n%s\n\n%s\n%s\n\n%s\n%s",	  "Sip Stack Size",	  "SentResponseDB size...", sentResponseDB.getDetails().logData(),	  "SentRequestDB size...", sentRequestDB.getDetails().logData(),          "UDP stack details...", udpConnection->getDetails().logData());}DataSipTransceiver::getLocalNamePort() const{    return myLocalNamePort;}/* Local Variables: *//* c-file-style: "stroustrup" *//* indent-tabs-mode: nil *//* c-file-offsets: ((access-label . -) (inclass . ++)) *//* c-basic-offset: 4 *//* End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -