📄 connection.cpp
字号:
// // // Copyright (C) 2005-2006 SIPez LLC.// Licensed to SIPfoundry under a Contributor Agreement.// // Copyright (C) 2004-2006 SIPfoundry Inc.// Licensed by SIPfoundry under the LGPL license.// // Copyright (C) 2004-2006 Pingtel Corp.// Licensed to SIPfoundry under a Contributor Agreement.// // $$//////////////////////////////////////////////////////////////////////////////// Author: Dan Petrie (dpetrie AT SIPez DOT com) // SYSTEM INCLUDES// APPLICATION INCLUDES#include <cp/Connection.h>#include <cp/CpGhostConnection.h>#include <mi/CpMediaInterface.h>#include <cp/CpMultiStringMessage.h>#include <cp/CpCall.h>#include <net/SdpCodec.h>#include <net/SipSession.h>#include <os/OsLock.h>#include <os/OsMsg.h>#include <os/OsDatagramSocket.h>#include <os/OsServerTask.h>#include <os/OsQueuedEvent.h>#include <os/OsTimer.h>#include "os/OsDateTime.h"#include "os/OsUtil.h"#include <tao/TaoObjectMap.h>#include <tao/TaoReference.h>#include <tao/TaoListenerEventMessage.h>#include <ptapi/PtConnection.h>#include <net/TapiMgr.h>// EXTERNAL FUNCTIONS// EXTERNAL VARIABLES// CONSTANTS#define CONN_DELETE_DELAY_SECS 10 // Number of seconds to wait before a // connection should be removed from a // call and deleted.// STATIC VARIABLE INITIALIZATIONS/* //////////////////////////// PUBLIC //////////////////////////////////// *//* ============================ CREATORS ================================== */// ConstructorConnection::Connection(CpCallManager* callMgr, CpCall* call, CpMediaInterface* mediaInterface, //UiContext* callUiContext, int offeringDelayMilliSeconds, int availableBehavior, const char* forwardUnconditionalUrl, int busyBehavior, const char* forwardOnBusyUrl, int forwardOnNoAnswerSeconds) : mConnectionId(-1) , callIdMutex(OsMutex::Q_FIFO) , mDeleteAfter(OsTime::OS_INFINITY){#ifdef TEST_PRINT UtlString callId; if (call) { call->getCallId(callId); OsSysLog::add(FAC_CP, PRI_DEBUG, "Connection constructed: %s\n", callId.data()); } else OsSysLog::add(FAC_CP, PRI_DEBUG, "Connection constructed: call is Null\n");#endif mOfferingDelay = offeringDelayMilliSeconds; mLineAvailableBehavior = availableBehavior; if(mLineAvailableBehavior == FORWARD_UNCONDITIONAL && forwardUnconditionalUrl != NULL) { mForwardUnconditional.append(forwardUnconditionalUrl); } mLineBusyBehavior = busyBehavior; if(mLineBusyBehavior == FORWARD_ON_BUSY && forwardOnBusyUrl != NULL) { mForwardOnBusy.append(forwardOnBusyUrl); } mForwardOnNoAnswerSeconds = forwardOnNoAnswerSeconds; mRemoteIsCallee = FALSE; mRemoteRequestedHold = FALSE; remoteRtpPort = PORT_NONE; sendCodec = -1; receiveCodec = -1; mLocalConnectionState = CONNECTION_IDLE; mRemoteConnectionState = CONNECTION_IDLE; mConnectionStateCause = CONNECTION_CAUSE_NORMAL; mTerminalConnState = PtTerminalConnection::IDLE; mFarEndHoldState = TERMCONNECTION_NONE; mResponseCode = 0; mResponseText.remove(0); mpCallManager = callMgr; mpCall = call; mpMediaInterface = mediaInterface; mConnectionId = -10; //mpCallUiContext = callUiContext; mpListenerCnt = new TaoReference(); mpListeners = new TaoObjectMap(); m_eLastMajor = (SIPX_CALLSTATE_EVENT) -1 ; m_eLastMinor = (SIPX_CALLSTATE_CAUSE) -1 ; m_eLastAudioMajor = (SIPX_CALLSTATE_EVENT) -1 ; m_eLastAudioMinor = (SIPX_CALLSTATE_CAUSE) -1 ; mpCallManager->getNewSessionId(this) ;#ifdef TEST_PRINT if (!callId.isNull()) OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving Connection constructed: %s\n", callId.data()); else OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving Connection constructed: call is Null\n");#endif}// Copy constructorConnection::Connection(const Connection& rConnection) : UtlString(rConnection) , callIdMutex(OsMutex::Q_FIFO){ mpListenerCnt = rConnection.mpListenerCnt; mpListeners = rConnection.mpListeners;}// DestructorConnection::~Connection(){#ifdef TEST_PRINT UtlString callId; if (mpCall) { mpCall->getCallId(callId); OsSysLog::add(FAC_CP, PRI_DEBUG, "Connection destructed: %s\n", callId.data()); } else OsSysLog::add(FAC_CP, PRI_DEBUG, "Connection destructed: call is Null\n");#endif if ( mpListenerCnt ) { delete mpListenerCnt; mpListenerCnt = 0; } if ( mpListeners ) { delete mpListeners; mpListeners = 0; }#ifdef TEST_PRINT if (!callId.isNull()) OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving Connection destructed: %s\n", callId.data()); else OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving Connection destructed: call is Null\n");#endif}/* ============================ MANIPULATORS ============================== */void Connection::prepareForSplit() { if ((mpMediaInterface) && (mConnectionId != -1)) { mpMediaInterface->deleteConnection(mConnectionId) ; } mpCall = NULL ; mpMediaInterface = NULL ; mConnectionId = -1 ;}void Connection::prepareForJoin(CpCall* pNewCall, CpMediaInterface* pNewMediaInterface) { mpCall = pNewCall ; mpMediaInterface = pNewMediaInterface ; mpMediaInterface->createConnection(mConnectionId, NULL) ; // VIDEO: Need to include window handle!}void Connection::setState(int newState, int isLocal, int newCause, int termState){ UtlString oldStateString; UtlString newStateString; int currentState = isLocal ? mLocalConnectionState : mRemoteConnectionState; getStateString(currentState, &oldStateString); getStateString(newState, &newStateString); int metaEventId = 0; int metaEventType = PtEvent::META_EVENT_NONE; int numCalls = 0; const UtlString* metaEventCallIds = NULL; if (mpCall) { mpCall->getMetaEvent(metaEventId, metaEventType, numCalls, &metaEventCallIds); } UtlString callId; if (mpCall) { mpCall->getCallId(callId); } if (callId.isNull()) callId="null"; UtlString strCallName; if (mpCall) { strCallName = mpCall->getName(); } if (strCallName.isNull()) { strCallName="null"; } if (!isStateTransitionAllowed(newState, currentState)) { // Under some conditions, "invalid" state changes are allowed. if (!(!isLocal && metaEventId > 0 && metaEventType == PtEvent::META_CALL_TRANSFERRING)) { if (newState == currentState) { OsSysLog::add(FAC_CP, PRI_DEBUG, "Connection::setState: " "Questionable connection state change - isLocal %d, for call " "'%s' with callid '%s' from %s to %s, cause %d", isLocal, strCallName.data(), callId.data(), oldStateString.data(), newStateString.data(), newCause); } else { OsSysLog::add(FAC_CP, PRI_ERR, "Connection::setState: " "Invalid connection state change - isLocal %d, for call " "'%s' with callid '%s' from %s to %s, cause %d", isLocal, strCallName.data(), callId.data(), oldStateString.data(), newStateString.data(), newCause); } return; } } UtlBoolean bPostStateChange = FALSE; if (newState != currentState || newCause != CONNECTION_CAUSE_NORMAL) { if (isLocal && newState == CONNECTION_DISCONNECTED) { if ((mpCall->canDisconnectConnection(this) || newCause == CONNECTION_CAUSE_CANCELLED) && metaEventType != PtEvent::META_CALL_TRANSFERRING) { bPostStateChange = TRUE; } } else { bPostStateChange = TRUE; } } OsSysLog::add(FAC_CP, PRI_DEBUG, "Call %s %s state isLocal %d\nchange\nfrom %s to\n\t %s\ncause=%d\npost change to upper layer %d", strCallName.data(), callId.data(), isLocal, oldStateString.data(), newStateString.data(), newCause, bPostStateChange); if (bPostStateChange) { mConnectionStateCause = newCause; mTerminalConnState = termState == -1 ? terminalConnectionState(newState) : termState; if (isLocal) { mLocalConnectionState = newState; } else { mRemoteConnectionState = newState; } postTaoListenerMessage(newState, newCause, isLocal); }}void Connection::setTerminalConnectionState(int newState, int isLocal, int newCause){ mTerminalConnState = newState; mConnectionStateCause = newCause;} #if 1int Connection::getState(int isLocal) const{ int state; if (mRemoteIsCallee) state = mRemoteConnectionState; else state = mLocalConnectionState; if ((mLocalConnectionState == CONNECTION_FAILED) && state != mLocalConnectionState) { UtlString oldStateString, newStateString; getStateString(mLocalConnectionState, &oldStateString); getStateString(state, &newStateString); state = mLocalConnectionState; } else if ((mRemoteConnectionState == CONNECTION_FAILED) && mRemoteConnectionState != state) { UtlString oldStateString, newStateString; getStateString(mRemoteConnectionState, &oldStateString); getStateString(state, &newStateString); state = mRemoteConnectionState; } return state;}#endif /* 1 */int Connection::getState(int isLocal, int& cause) const{ cause = mConnectionStateCause; int state; if (isLocal) state = mLocalConnectionState; else state = mRemoteConnectionState; if ((mLocalConnectionState == CONNECTION_FAILED) && state != mLocalConnectionState) { UtlString oldStateString, newStateString; getStateString(mLocalConnectionState, &oldStateString); getStateString(state, &newStateString); state = mLocalConnectionState; } else if ((mRemoteConnectionState == CONNECTION_FAILED) && mRemoteConnectionState != state) { UtlString oldStateString, newStateString; getStateString(mRemoteConnectionState, &oldStateString); getStateString(state, &newStateString); state = mRemoteConnectionState; } return state;}int Connection::getTerminalState(int isLocal) const{ int state; state = mTerminalConnState; return state;}void Connection::getStateString(int state, UtlString* stateLabel){ stateLabel->remove(0); switch(state) { case CONNECTION_IDLE: stateLabel->append("CONNECTION_IDLE"); break; case CONNECTION_INITIATED: stateLabel->append("CONNECTION_INITIATED"); break; case CONNECTION_QUEUED: stateLabel->append("CONNECTION_QUEUED"); break; case CONNECTION_OFFERING: stateLabel->append("CONNECTION_OFFERING"); break; case CONNECTION_ALERTING: stateLabel->append("CONNECTION_ALERTING"); break; case CONNECTION_ESTABLISHED: stateLabel->append("CONNECTION_ESTABLISHED"); break; case CONNECTION_FAILED: stateLabel->append("CONNECTION_FAILED"); break; case CONNECTION_DISCONNECTED: stateLabel->append("CONNECTION_DISCONNECTED"); break; case CONNECTION_DIALING: stateLabel->append("CONNECTION_DIALING"); break; default: stateLabel->append("CONNECTION_UNKNOWN"); break; }}// Assignment operatorConnection& Connection::operator=(const Connection& rhs){ if (this == &rhs) // handle the assignment to self case return *this; return *this;}void Connection::setLocalAddress(const char* address){ OsLock lock(callIdMutex); mLocalAddress.remove(0); mLocalAddress.append(address);}void Connection::unimplemented(const char* methodName) const{ osPrintf("%s NO IMPLEMENTED\n",methodName);}// Is this connection marked for deletion?void Connection::markForDeletion() { OsTime timeNow ; OsTime deleteAfterSecs(CONN_DELETE_DELAY_SECS, 0) ; OsDateTime::getCurTimeSinceBoot(deleteAfterSecs) ; mDeleteAfter = timeNow + deleteAfterSecs ;}void Connection::setMediaInterface(CpMediaInterface* pMediaInterface) { if ((mpMediaInterface) && (mConnectionId != -1)) { mpMediaInterface->deleteConnection( mConnectionId ); } mConnectionId = -1; mpMediaInterface = pMediaInterface ;}UtlBoolean Connection::validStateTransition(SIPX_CALLSTATE_EVENT eFrom, SIPX_CALLSTATE_EVENT eTo){ UtlBoolean bValid = TRUE ; switch (eFrom) { case DISCONNECTED: bValid = (eTo == DESTROYED) ; break ; case DESTROYED: bValid = FALSE ; break ; default: break; } // Make sure a local focus change doesn't kick off an established event if ((eTo == CONNECTED) && (getLocalState() != CONNECTION_ESTABLISHED)) { bValid = FALSE ; } return bValid ;}void Connection::fireSipXEvent(SIPX_CALLSTATE_EVENT eventCode, SIPX_CALLSTATE_CAUSE causeCode, void* pEventData, const char* assertedRemoteIdentity) { UtlString callId ; UtlString remoteAddress ; SipSession session ; UtlBoolean bDuplicateAudio = (eventCode == CALLSTATE_AUDIO_EVENT && causeCode == m_eLastAudioMinor) ? TRUE : FALSE; // Avoid sending duplicate events if (( (eventCode != m_eLastMajor) || (causeCode != m_eLastMinor)) && validStateTransition(m_eLastMajor, eventCode) && !bDuplicateAudio) { if (eventCode == CALLSTATE_AUDIO_EVENT) { m_eLastAudioMajor = eventCode; m_eLastAudioMinor = causeCode; } else if(eventCode == CALLSTATE_IDENTITY_CHANGE) { // Do not cache the asserted identity change as it // should always be sent through. Also do not cache so // we do not duplicate other event types (e.g. // CALLSTATE_FOO, CALLSTATE_IDENTITY_CHANGE, CALLSTATE_FOO // should not notify CALLSTATE_FOO twice } else { m_eLastMajor = eventCode; m_eLastMinor = causeCode; } getCallId(&callId) ; getRemoteAddress(&remoteAddress); getSession(session) ; TapiMgr::getInstance().fireCallEvent(mpCallManager, callId.data(), &session, remoteAddress.data(), eventCode, causeCode, pEventData, assertedRemoteIdentity); }}/* ============================ ACCESSORS ================================= */void Connection::getLocalAddress(UtlString* address){ *address = mLocalAddress;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -