📄 sipconnection.cpp
字号:
// // // Copyright (C) 2005, 2006 SIPez LLC// Licensed to SIPfoundry under a Contributor Agreement.//// Copyright (C) 2005, 2006 SIPfoundry Inc.// Licensed by SIPfoundry under the LGPL license.// // Copyright (C) 2004, 2005 Pingtel Corp.// Licensed to SIPfoundry under a Contributor Agreement.// // $$//////////////////////////////////////////////////////////////////////////////// Author: Dan Petrie (dpetrie AT SIPez DOT com)// SYSTEM INCLUDES#ifdef __pingtel_on_posix__#include <stdlib.h>#endif// APPLICATION INCLUDES#include <os/OsQueuedEvent.h>#include <os/OsTimer.h>#include <os/OsUtil.h>#include <net/SipMessageEvent.h>#include <net/SipUserAgent.h>#include <net/NameValueTokenizer.h>#include <net/SdpCodecFactory.h>#include <net/Url.h>#include <net/SipSession.h>#include <net/NetBase64Codec.h>#include <cp/SipConnection.h>#include <mi/CpMediaInterface.h>#include <cp/CallManager.h>#include <cp/CpCallManager.h>#include <cp/CpPeerCall.h>#include <cp/CpMultiStringMessage.h>#include <cp/CpIntMessage.h>#if defined(_VXWORKS)#include <inetLib.h>#endif#include "ptapi/PtCall.h"#include <net/TapiMgr.h>// EXTERNAL FUNCTIONS// EXTERNAL VARIABLES// CONSTANTS#define CALL_STATUS_FIELD "status"#ifdef _WIN32# define CALL_CONTROL_TONES#endif// STATIC VARIABLE INITIALIZATIONS/* //////////////////////////// PUBLIC //////////////////////////////////// *//* ============================ CREATORS ================================== */// ConstructorSipConnection::SipConnection(const char* outboundLineAddress, UtlBoolean isEarlyMediaFor180Enabled, CpCallManager* callMgr, CpCall* call, CpMediaInterface* mediaInterface, //UiContext* callUiContext, SipUserAgent* sipUA, int offeringDelayMilliSeconds, int sessionReinviteTimer, int availableBehavior, const char* forwardUnconditionalUrl, int busyBehavior, const char* forwardOnBusyUrl) : Connection(callMgr, call, mediaInterface, offeringDelayMilliSeconds, availableBehavior, forwardUnconditionalUrl, busyBehavior, forwardOnBusyUrl) , inviteFromThisSide(0) , mIsEarlyMediaFor180(TRUE) , mContactId(0){ sipUserAgent = sipUA; inviteMsg = NULL; mReferMessage = NULL; lastLocalSequenceNumber = 0; lastRemoteSequenceNumber = -1; reinviteState = ACCEPT_INVITE; mIsEarlyMediaFor180 = isEarlyMediaFor180Enabled; // Build a from tag int fromTagInt = rand(); char fromTagBuffer[60]; sprintf(fromTagBuffer, "%dc%d", call->getCallIndex(), fromTagInt); mFromTag = fromTagBuffer; if(outboundLineAddress) { mFromUrl = outboundLineAddress; // Before adding the from tag, construct the local contact with the // device's NAT friendly contact information (getContactUri). The host // and port from that replaces the public address or record host and // port. The UserId and URL parameters should be retained. UtlString contactHostPort; UtlString address; Url tempUrl(mFromUrl); sipUserAgent->getContactUri(&contactHostPort); Url hostPort(contactHostPort); hostPort.getHostAddress(address); tempUrl.setHostAddress(address); tempUrl.setHostPort(hostPort.getHostPort()); tempUrl.toString(mLocalContact); // Set the from tag in case this is an outbound call // If this is an in bound call, the from URL will get // over written by the To field from the SIP request mFromUrl.setFieldParameter("tag", mFromTag); } mDefaultSessionReinviteTimer = sessionReinviteTimer; mSessionReinviteTimer = 0;#ifdef TEST_PRINT osPrintf("SipConnection::mDefaultSessionReinviteTimer = %d\n", mDefaultSessionReinviteTimer);#endif mIsReferSent = FALSE; mIsAcceptSent = FALSE; mbCancelling = FALSE; // this is the flag that indicates CANCEL is sent // but no response has been received if set to TRUE // State variable which indicates an action to // perform after hold has completed. mHoldCompleteAction = CpCallManager::CP_UNSPECIFIED;#ifdef TEST_PRINT UtlString callId; if (mpCall) mpCall->getCallId(callId); if (!callId.isNull()) OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving SipConnection constructor: %s\n", callId.data()); else OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving SipConnection constructor: call is Null\n");#endif}// Copy constructorSipConnection::SipConnection(const SipConnection& rSipConnection){}// DestructorSipConnection::~SipConnection(){ UtlString callId;#ifdef TEST_PRINT if (mpCall) { mpCall->getCallId(callId); OsSysLog::add(FAC_CP, PRI_DEBUG, "Entering SipConnection destructor: %s\n", callId.data()); } else OsSysLog::add(FAC_CP, PRI_DEBUG, "Entering SipConnection destructor: call is Null\n");#endif if(inviteMsg) { delete inviteMsg; inviteMsg = NULL; } if(mReferMessage) { delete mReferMessage; mReferMessage = NULL; }#ifdef TEST_PRINT if (!callId.isNull()) OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving SipConnection destructor: %s\n", callId.data()); else OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving SipConnection destructor: call is Null\n");#endif if ((mpMediaInterface) && (mConnectionId != -1)) { mpMediaInterface->deleteConnection( mConnectionId ); } mConnectionId = -1;}/* ============================ MANIPULATORS ============================== */// Assignment operatorSipConnection&SipConnection::operator=(const SipConnection& rhs){ if (this == &rhs) // handle the assignment to self case return *this; return *this;}UtlBoolean SipConnection::dequeue(UtlBoolean callInFocus){ UtlBoolean connectionDequeued = FALSE;#ifdef TEST_PRINT osPrintf("Connection::dequeue this: %p inviteMsg: %p\n", this, inviteMsg);#endif if(getState() == CONNECTION_QUEUED) { int tagNum = -1; proceedToRinging(inviteMsg, sipUserAgent, tagNum, mLineAvailableBehavior); setState(CONNECTION_ALERTING, CONNECTION_LOCAL); /** SIPXTAPI: TBD **/ connectionDequeued = TRUE; } return(connectionDequeued);}UtlBoolean SipConnection::requestShouldCreateConnection(const SipMessage* sipMsg, SipUserAgent& sipUa, SdpCodecFactory* codecFactory){ UtlBoolean createConnection = FALSE; UtlString method; sipMsg->getRequestMethod(&method); UtlString toField; UtlString address; UtlString protocol; int port; UtlString user; UtlString userLabel; UtlString tag; sipMsg->getToAddress(&address, &port, &protocol, &user, &userLabel, &tag); // Dangling or delated ACK if(method.compareTo(SIP_ACK_METHOD) == 0) { // Ignore it and do not create a connection createConnection = FALSE; } // INVITE to create a connection //if to tag is already set then return 481 error else if(method.compareTo(SIP_INVITE_METHOD) == 0 && tag.isNull()) { // Assume the best case, as this will be checked // again before the call is answered UtlBoolean atLeastOneCodecSupported = TRUE; if(codecFactory == NULL || codecFactory->getCodecCount() == 0) atLeastOneCodecSupported = TRUE; // Verify that we have some RTP codecs in common else { // Get the SDP and findout if there are any // codecs in common UtlString rtpAddress; int rtpPort; int rtcpPort; int videoRtpPort; int videoRtcpPort; const SdpBody* bodyPtr = sipMsg->getSdpBody(); if(bodyPtr) { int numMatchingCodecs = 0; SdpCodec** matchingCodecs = NULL; bodyPtr->getBestAudioCodecs(*codecFactory, numMatchingCodecs, matchingCodecs, rtpAddress, rtpPort, rtcpPort, videoRtpPort, videoRtcpPort); if(numMatchingCodecs > 0) { // Need to cleanup the codecs for(int codecIndex = 0; codecIndex < numMatchingCodecs; codecIndex++) { delete matchingCodecs[codecIndex]; matchingCodecs[codecIndex] = NULL; } delete[] matchingCodecs; atLeastOneCodecSupported = TRUE; } else { atLeastOneCodecSupported = FALSE; // Send back a bad media error // There are no codecs in common SipMessage badMediaResponse; badMediaResponse.setInviteBadCodecs(sipMsg, &sipUa); sipUa.send(badMediaResponse); } } // Assume that SDP will be sent in ACK else atLeastOneCodecSupported = TRUE; } if(atLeastOneCodecSupported) { // Create a new connection createConnection = TRUE; } else { createConnection = FALSE;#ifdef TEST_PRINT osPrintf("SipConnection::requestShouldCreateConnection FALSE INVITE with no supported RTP codecs\n");#endif } } // NOTIFY for REFER // a non-existing transaction. else if(method.compareTo(SIP_NOTIFY_METHOD) == 0) { UtlString eventType; sipMsg->getEventField(eventType); eventType.toLower(); int typeIndex = eventType.index(SIP_EVENT_REFER); if(typeIndex >=0) { // Send a bad callId/transaction message SipMessage badTransactionMessage; badTransactionMessage.setBadTransactionData(sipMsg); sipUa.send(badTransactionMessage); } // All other NOTIFY events are ignored createConnection = FALSE; } else if(method.compareTo(SIP_REFER_METHOD) == 0) { createConnection = TRUE; } // All other methods: this is part of // a non-existing transaction. else { // Send a bad callId/transaction message SipMessage badTransactionMessage; badTransactionMessage.setBadTransactionData(sipMsg); sipUa.send(badTransactionMessage); createConnection = FALSE; } return createConnection;}UtlBoolean SipConnection::shouldCreateConnection(SipUserAgent& sipUa, OsMsg& eventMessage, SdpCodecFactory* codecFactory){ UtlBoolean createConnection = FALSE; int msgType = eventMessage.getMsgType(); int msgSubType = eventMessage.getMsgSubType(); const SipMessage* sipMsg = NULL; int messageType; if(msgType == OsMsg::PHONE_APP && msgSubType == CallManager::CP_SIP_MESSAGE) { sipMsg = ((SipMessageEvent&)eventMessage).getMessage(); messageType = ((SipMessageEvent&)eventMessage).getMessageStatus();#ifdef TEST_PRINT osPrintf("SipConnection::messageType: %d\n", messageType);#endif switch(messageType) { // This is a request which failed to get sent case SipMessageEvent::TRANSPORT_ERROR: case SipMessageEvent::SESSION_REINVITE_TIMER: case SipMessageEvent::AUTHENTICATION_RETRY: // Ignore it and do not create a connection createConnection = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -