📄 cppeercall.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#include "os/OsDefs.h"// APPLICATION INCLUDES#include "utl/UtlRegex.h"#include <cp/CpPeerCall.h>#include <cp/CpCallManager.h>#include <cp/CpStringMessage.h>#include <cp/CpIntMessage.h>#include <cp/CpMultiStringMessage.h>#include <net/SipMessageEvent.h>#include <cp/SipConnection.h>#include <cp/CpGhostConnection.h>#include <mi/CpMediaInterface.h>#include <net/SipUserAgent.h>#include <net/NameValueTokenizer.h>#include <net/Url.h>#include <net/SipSession.h>#include <ptapi/PtConnection.h>#include "ptapi/PtCall.h"#include "ptapi/PtEvent.h"#include <ptapi/PtTerminalConnection.h>#include <os/OsReadLock.h>#include <os/OsWriteLock.h>#include <os/OsProtectEvent.h>#include "os/OsQueuedEvent.h"#include "os/OsTimer.h"#include "os/OsTime.h"#include "os/OsDateTime.h"#include "tao/TaoProviderAdaptor.h"// EXTERNAL FUNCTIONS// EXTERNAL VARIABLES// CONSTANTS#define CALL_STATUS_FIELD "status"#ifdef _WIN32# define CALL_CONTROL_TONES#endif#define TEST_PRINT #undef TEST_PRINT// STATIC VARIABLE INITIALIZATIONS/* //////////////////////////// PUBLIC //////////////////////////////////// *//* ============================ CREATORS ================================== */// ConstructorCpPeerCall::CpPeerCall(UtlBoolean isEarlyMediaFor180Enabled, CpCallManager* callManager, CpMediaInterface* callMediaInterface, int callIndex, const char* callId, SipUserAgent* sipUA, int sipSessionReinviteTimer, const char* defaultCallExtension, int holdType, int offeringDelayMilliSeconds, int availableBehavior, const char* forwardUnconditionalUrl, int busyBehavior, const char* forwardOnBusyUrl, int forwardOnNoAnswerMilliSeconds, const char* forwardOnNoAnswerUrl, int ringingExpireSeconds) :CpCall(callManager, callMediaInterface, callIndex, callId, holdType), mConnectionMutex(OsRWMutex::Q_PRIORITY), mIsEarlyMediaFor180(TRUE){#ifdef TEST_PRINT if (callId) OsSysLog::add(FAC_CP, PRI_DEBUG, "CpPeerCall constructor: %s\n", callId); else OsSysLog::add(FAC_CP, PRI_DEBUG, "CpPeerCall constructor:: callId is Null\n");#endif // SIP and Peer to Peer call intialization sipUserAgent = sipUA; mIsEarlyMediaFor180 = isEarlyMediaFor180Enabled; mSipSessionReinviteTimer = sipSessionReinviteTimer; offeringDelay = offeringDelayMilliSeconds; lineAvailableBehavior = availableBehavior; if(lineAvailableBehavior == Connection::FORWARD_UNCONDITIONAL && forwardUnconditionalUrl != NULL) { forwardUnconditional.append(forwardUnconditionalUrl); } lineBusyBehavior = busyBehavior; if(lineBusyBehavior == Connection::FORWARD_ON_BUSY && forwardOnBusyUrl != NULL) { forwardOnBusy.append(forwardOnBusyUrl); }#ifdef TEST_PRINT osPrintf("%s-CpPeerCall: SIP Forward on busy: %s\n", mName.data(), forwardOnBusy.data());#endif if(forwardOnNoAnswerUrl != NULL && strlen(forwardOnNoAnswerUrl) > 0) { if ( forwardOnNoAnswerMilliSeconds > -1) noAnswerTimeout = forwardOnNoAnswerMilliSeconds; else noAnswerTimeout = 24; // default forwardOnNoAnswer.append(forwardOnNoAnswerUrl); } else { noAnswerTimeout = ringingExpireSeconds; } if(defaultCallExtension) { //extension.append(phoneExtension); //NameValueTokenizer::frontBackTrim(&extension, " \t\n\r"); Url outboundLine(defaultCallExtension); // For now the terminal id is the extension //mLocalTerminalId.append(extension); outboundLine.toString(mLocalTerminalId); mLocalAddress = mLocalTerminalId; } // Set the local address for the implied connection // This is a bit of a short cut // SIP specific stuff should not be here //UtlString myServerAddress; //UtlString myServerProtocol; //int myServerPort; //sipUserAgent->getDirectoryServer(0, &myServerAddress, // &myServerPort, &myServerProtocol); //if(myServerAddress.isNull()) //{ // sipUserAgent->getFromAddress(&myServerAddress, // &myServerPort, &myServerProtocol); //} //SipMessage::buildSipUrl(&mLocalAddress, myServerAddress.data(), // myServerPort, myServerProtocol.data(), extension.data()); mDialMode = ADD_PARTY; setCallType(CP_NORMAL_CALL);#ifdef TEST_PRINT osPrintf("%s-CpPeerCall::Call outbound line: %s\n", mName.data(), mLocalAddress.data());#endif mbRequestedDrop = false ;#ifdef TEST_PRINT if (callId) OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving CpPeerCall constructor: %s\n", callId); else OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving CpPeerCall constructor:: callId is Null\n");#endif eLastMajor = (SIPX_CALLSTATE_EVENT) -1 ; eLastMinor = (SIPX_CALLSTATE_CAUSE) -1 ;}// Copy constructorCpPeerCall::CpPeerCall(const CpPeerCall& rCpPeerCall) :mConnectionMutex(OsRWMutex::Q_PRIORITY){}// DestructorCpPeerCall::~CpPeerCall(){ waitUntilShutDown(20000) ;#ifdef TEST_PRINT UtlString name = getName(); if (!mCallId.isNull()) { OsSysLog::add(FAC_CP, PRI_DEBUG, "CpPeerCall-%s destructor: %s\n", name.data(), mCallId.data()); } else { OsSysLog::add(FAC_CP, PRI_DEBUG, "CpPeerCall-%s destructor:: callId is Null\n", name.data()); }#endif Connection* connection = NULL; while ((connection = (Connection*) mConnections.get())) { delete connection; connection = NULL; }#ifdef TEST_PRINT if (!mCallId.isNull()) { OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving CpPeerCall-%s destructor: %s\n", name.data(), mCallId.data()); } else { OsSysLog::add(FAC_CP, PRI_DEBUG, "Leaving CpPeerCall-%s destructor:: callId is Null\n", name.data()); }#endif #if 0 // We might have the memory leak here because those three objects might not being deleted yet!!! OsSysLog::add(FAC_CP, PRI_DEBUG, "CpPeerCall::~CpPeerCall deleting CpIntMessage %p queuedEvent %p timer %p", pExitMsg, queuedEvent, timer); if (pExitMsg) { delete pExitMsg; } if (queuedEvent) { delete queuedEvent; } if (timer) { delete timer; }#endif }/* ============================ MANIPULATORS ============================== */// Assignment operatorCpPeerCall& CpPeerCall::operator=(const CpPeerCall& rhs){ if (this == &rhs) // handle the assignment to self case return *this; return *this;}// Handles the processing of a CallManager::CP_DIAL_STRING messageUtlBoolean CpPeerCall::handleDialString(OsMsg* pEventMessage){ UtlString dialString; UtlString desiredCallId; UtlString remoteHostName; CONTACT_ID contactId ; ((CpMultiStringMessage*)pEventMessage)->getString1Data(dialString); ((CpMultiStringMessage*)pEventMessage)->getString2Data(desiredCallId); contactId = (CONTACT_TYPE) ((CpMultiStringMessage*)pEventMessage)->getInt1Data(); void* pDisplay = (void*) ((CpMultiStringMessage*)pEventMessage)->getInt2Data();#ifdef TEST_PRINT osPrintf("%s-CpPeerCall: dialing string: \'%s\' length: %d\n", mName.data(), dialString.data(), dialString.length());#endif addHistoryEvent("CP_DIAL_STRING (3) \n\tDialString: \"" + dialString + "\""); // If all digits or * assume this is a userid not a server address RegEx allDigits("^[0-9*]+$"); if(allDigits.Search(dialString.data())) { remoteHostName.append(dialString.data()); remoteHostName.append('@'); } else { remoteHostName.append(dialString.data()); } if(!isCallIdSet()) { UtlString callId; mpManager->getNewCallId(&callId); setCallId(callId.data()); } // Initial two party call or adding a party if(mDialMode == ADD_PARTY) { if (desiredCallId.length() != 0) { // Use supplied callId addParty(remoteHostName.data(), NULL, NULL, desiredCallId.data(), contactId, pDisplay); } else { // Use default call id addParty(remoteHostName.data(), NULL, NULL, NULL, contactId, pDisplay); } } return TRUE ;}// Handles the processing of a CallManager::CP_DEQUEUED_CALL messageUtlBoolean CpPeerCall::handleDequeueCall(OsMsg* pEventMessage){ Connection* connection = findQueuedConnection(); if(connection) {#ifdef TEST_PRINT osPrintf("%s-About to dequeue connection: %X\n", mName.data(), connection);#endif connection->dequeue(mCallInFocus); } return TRUE ;}// Handles the processing of a CallManager::CP_BLIND_TRANSFER and// CallManager::CP_CONSULT_TRANSFER messagesUtlBoolean CpPeerCall::handleTransfer(OsMsg* pEventMessage){ int msgSubType = pEventMessage->getMsgSubType(); // This message is received by the original call on // the transfer controller if(getCallType() == CP_NORMAL_CALL) { // case variable scope setCallType(CP_TRANSFER_CONTROLLER_ORIGINAL_CALL); int metaEventId = ((CpMultiStringMessage*)pEventMessage)->getInt1Data(); bool remoteHoldBeforeTransfer = ((CpMultiStringMessage*)pEventMessage)->getInt2Data(); UtlString targetCallId; ((CpMultiStringMessage*)pEventMessage)->getString3Data(targetCallId); setTargetCallId(targetCallId.data()); UtlString thisCallId; getCallId(thisCallId); const char* metaCallIds[2]; metaCallIds[0] = targetCallId.data(); // New call first metaCallIds[1] = thisCallId.data(); // Start the meta event startMetaEvent(metaEventId, PtEvent::META_CALL_TRANSFERRING, 2, metaCallIds); // Create the target call mpManager->createCall(&targetCallId, metaEventId, PtEvent::META_CALL_TRANSFERRING, 2, metaCallIds, FALSE); // Do not assume focus if there is no infocus call // as this is not a real call. It is a place holder for call // state on the remote call if(msgSubType == CallManager::CP_BLIND_TRANSFER) { // Transfer does an implicit hold. // The local hold is done here. The remote hold is // done on each connection. localHold(); } Connection* connection = NULL; UtlString transferTargetAddress; ((CpMultiStringMessage*)pEventMessage)->getString2Data(transferTargetAddress);#ifdef TEST_PRINT osPrintf("%s-CpPeerCall::CP_BLIND_TRANSFER targetCallId: %s targetAddress: %s metaEventId: %d\n", mName.data(), targetCallId.data(), transferTargetAddress.data());#endif OsReadLock lock(mConnectionMutex); UtlDListIterator iterator(mConnections);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -