diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/sipapi/src/SipConnectionImplementation.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/sipapi/src/SipConnectionImplementation.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,1237 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Name : SipConnectionImplementation.cpp +// Part of : SIPAPI +// Version : SIP/5.0 +// + + + +#include "SipAssert.h" +#include "SipConnectionImplementation.h" +#include "sipconnectionobserver.h" +#include "sipclientconnection.h" +#include "sip.h" +#include "SipImplementation.h" +#include "siperr.h" +#include "sipinternalerr.h" +#include "sipmessageelements.h" +#include "siprequestelements.h" +#include "sipresponseelements.h" +#include "sipclienttransaction.h" +#include "sipservertransaction.h" +#include "RegBindingImplementation.h" +#include "SipDialogImplementation.h" +#include "siprefresh.h" +#include "sipconnectioncallback.h" +#include "sipstrings.h" +#include "sipstrconsts.h" + +#ifdef CPPUNIT_TEST +#include "TestCleanupStack.h" +#endif + + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::NewL +// ----------------------------------------------------------------------------- +// +CSIPConnectionImplementation* +CSIPConnectionImplementation::NewL(CSIP& aSIP, + CSIPConnection& aConnection, + TUint32 aIapId, + MSIPConnectionObserver& aObserver) + { + CSIPConnectionImplementation* self = + new (ELeave) CSIPConnectionImplementation(aSIP, + aConnection, + aIapId, + aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::CSIPConnectionImplementation +// ----------------------------------------------------------------------------- +// +CSIPConnectionImplementation::CSIPConnectionImplementation(CSIP& aSIP, + CSIPConnection& aConnection, + TUint32 aIapId, + MSIPConnectionObserver& aObserver) : + iSIP(&aSIP), + iConnection(aConnection), + iIapId(aIapId), + iObserver(aObserver) +#ifdef CPPUNIT_TEST + , iRegistrations(1), + iDialogs(1), + iTransactions(1), + iRefreshes(1) +#endif + { + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::ConstructL +// Pass "*this" to AddConnectionL which asks for CSIPConnection. Can't pass +// CSIPConnection, as AddConnectionL asks for CSIPConnection::iImplementation +// which is NULL, as execution is inside CSIPConnectionImplementation::NewL. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::ConstructL() + { + CheckCSipL(); + + iCallbackInfo = CConnectionCallback::NewL(); + iClientConnection = + CSIPClientConnection::NewL(iSIP->Implementation().SIPClient(), + *this, + iIapId); + iSIP->Implementation().AddConnectionL(*this, iIapId); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::~CSIPConnectionImplementation +// ----------------------------------------------------------------------------- +// +CSIPConnectionImplementation::~CSIPConnectionImplementation() + { + if (iSIP) + { + iSIP->Implementation().RemoveConnection(iConnection); + } + + TInt i = 0; + for (i = 0; i < iRegistrations.Count(); i++) + { + iRegistrations[i]->ConnectionDeleted(); + } + iRegistrations.Reset(); + + for (i = 0; i < iDialogs.Count(); i++) + { + iDialogs[i]->ConnectionDeleted(); + } + iDialogs.Reset(); + + for (i = 0; i < iTransactions.Count(); i++) + { + iTransactions[i]->Detach(*this); + } + iTransactions.Reset(); + + for (i = 0; i < iRefreshes.Count(); i++) + { + iRefreshes[i]->RemoveRefreshOwner(*this); + } + iRefreshes.Reset(); + + delete iClientConnection; + delete iCallbackInfo; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::State +// ----------------------------------------------------------------------------- +// +CSIPConnection::TState CSIPConnectionImplementation::State() const + { + __TEST_INVARIANT; + return iClientConnection->State(); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::SendRequestL +// No need to check connection state. It is checked in SIPClient. +// ----------------------------------------------------------------------------- +// +CSIPClientTransaction* +CSIPConnectionImplementation::SendRequestL(CSIPRequestElements* aElements, + TUint32* aRegistrationId, + CSIPRefresh* aRefresh) + { + __TEST_INVARIANT; + __ASSERT_ALWAYS(aElements && + (aRegistrationId || (aElements->FromHeader() != NULL)), + User::Leave(KErrArgument)); + RStringF method = aElements->Method(); + __ASSERT_ALWAYS(method != SIPStrings::StringF(SipStrConsts::ERegister) && + method != SIPStrings::StringF(SipStrConsts::EInvite) && + method != SIPStrings::StringF(SipStrConsts::EPrack) && + method != SIPStrings::StringF(SipStrConsts::EAck) && + method != SIPStrings::StringF(SipStrConsts::ECancel) && + method != SIPStrings::StringF(SipStrConsts::EUpdate) && + method != SIPStrings::StringF(SipStrConsts::EBye) && + method != SIPStrings::StringF(SipStrConsts::ESubscribe) && + method != SIPStrings::StringF(SipStrConsts::ERefer) && + method != SIPStrings::StringF(SipStrConsts::ENotify), + User::Leave(KErrArgument)); + CSIPClientTransaction* ta = + CSIPClientTransaction::NewLC(method, *this, aRefresh); + TUint32 requestId(0); + iClientConnection->SendRequestL(*aElements, + requestId, + aRegistrationId ? *aRegistrationId : 0, + (aRefresh != NULL)); + if (aRefresh) + { + iRefreshes.AppendL(aRefresh); + aRefresh->SetRequestType(method); + aRefresh->SetRefreshOwner(*this); + } + CleanupStack::Pop(ta); + ta->SetRequestId(requestId); + delete aElements; + + __TEST_INVARIANT; + return ta; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FetchRegistrationsL +// ----------------------------------------------------------------------------- +// +CSIPClientTransaction* CSIPConnectionImplementation::FetchRegistrationsL( + CSIPRequestElements* aElements) + { + __TEST_INVARIANT; + + CSIPClientTransaction* ta = CSIPClientTransaction::NewL( + SIPStrings::StringF(SipStrConsts::ERegister), + *this); + CleanupStack::PushL(ta); + TUint32 requestId(0); + iClientConnection->FetchRegistrationsL(*aElements, requestId); + CleanupStack::Pop(ta); + ta->SetRequestId(requestId); + delete aElements; + + __TEST_INVARIANT; + return ta; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingRequestL +// Invariant mustn't be used after callback, as observer may delete this object +// ----------------------------------------------------------------------------- +// +void +CSIPConnectionImplementation::IncomingRequestL(CSIPRequestElements* aElements, + TUint32 aRequestId) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aElements, KErrArgument); + + iObserver.IncomingRequest( + CSIPServerTransaction::NewL(aRequestId, *this, aElements)); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingDialogRequestL +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::IncomingDialogRequestL( + CSIPRequestElements* aElements, + TUint32 aRequestId, + TUint32 aDialogId) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aElements, KErrArgument); + + CSIPDialogImplementation* dialog = FindDialog(aDialogId); + if (dialog) + { + CSIPServerTransaction* ta = + CSIPServerTransaction::NewLC(aRequestId, *this, aElements); + CleanupStack::PushL(TCleanupItem( + CSIPServerTransaction::DetachRequestElements, ta)); + + TBool useCallback = dialog->IncomingRequestL(ta, *iCallbackInfo); + CleanupStack::Pop(2); //TCleanupItem, ta + + if (useCallback) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + else + { + delete aElements; + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingResponseL +// An error response to REGISTER comes without registerId. +// This response is not related to any existing refresh or dialog. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::IncomingResponseL( + CSIPResponseElements* aElements, + TUint32 aRequestId) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aElements != NULL, KErrArgument); + + CSIPTransactionBase* ta = FindTransaction(aRequestId); + if (ta) + { + __SIP_ASSERT_LEAVE(ta->IsSIPClientTransaction(), KErrArgument); + + CSIPClientTransaction* clientTa = + static_cast(ta); + clientTa->SetResponseElements(aElements); + + iObserver.IncomingResponse(*clientTa); + } + else + { + CRegBindingImplementation* reg = FindRegistration(aRequestId); + if (reg) + { + if (reg->IncomingResponseL(aElements, + aRequestId, + 0 /* empty registration id */, + 0 /* empty refresh id */, + *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + else + { + delete aElements; + } + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingRegistrationResponseL +// Response to an existing refreshed registration, or a response creating a +// refreshed registration. +// If the response to the initial REGISTER is an error response, it comes in +// IncomingResponseL or IncomingRefreshResponseL. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::IncomingRegistrationResponseL( + CSIPResponseElements* aElements, + TUint32 aRequestId, + TUint32 aRefreshId, + TUint32 aRegistrationId) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aElements != NULL, KErrArgument); + + CRegBindingImplementation* reg = FindRegistration(aRegistrationId, + aRequestId); + if (reg) + { + if (reg->IncomingResponseL(aElements, + aRequestId, + aRegistrationId, + aRefreshId, + *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + else + { + delete aElements; + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingRefreshResponseL +// Response creating a refresh or an error response to an existing refresh. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::IncomingRefreshResponseL( + CSIPResponseElements* aElements, + TUint32 aRequestId, + TUint32 aRefreshId) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aElements != NULL, KErrArgument); + + CSIPRefresh* refresh = NULL; + CSIPClientTransaction* ta = NULL; + if (FindRefresh(aRequestId, aRefreshId, &refresh, &ta)) + { + refresh->SetRefreshIdIfEmpty(aRefreshId); + refresh->UpdateRefreshState(aElements->StatusCode()); + + TUint statusCode = aElements->StatusCode(); + if (ta) + { + ta->SetResponseElements(aElements); + aElements = NULL; // Ownership of aElements was passed + } + if (statusCode >= 300) + { + iObserver.ErrorOccured(KErrSIPTerminatedWithResponse, *refresh); + } + else + { + // Ignore the response if application has deleted the transaction + if (ta) + { + iObserver.IncomingResponse(*ta); + } + } + } + else + { + CRegBindingImplementation* reg = FindRegistration(aRequestId); + if (reg) + { + if (reg->IncomingResponseL(aElements, + aRequestId, + 0 /* empty registration id */, + aRefreshId, + *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + aElements = NULL; // Ownership of aElements was passed + } + } + + delete aElements; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::ErrorOccured +// If the initial REGISTER failed, the error is related to a requestId of a +// registration transaction. RegisterId is received together with 2xx. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::ErrorOccured(TInt aError, TUint32 aRequestId) + { + __TEST_INVARIANT; + + CRegBindingImplementation* reg = FindRegistration(aRequestId); + if (reg) + { + if (reg->ErrorOccured(aError, aRequestId, *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + else + { + CSIPTransactionBase* ta = FindTransaction(aRequestId); + if (ta) + { + ta->ChangeState(CSIPTransactionBase::ETerminated); + + if (aError == KInviteTransactionCancelled) + { + __SIP_ASSERT_RETURN(!ta->IsSIPClientTransaction(), + KErrArgument); + iObserver.InviteCanceled( + static_cast(*ta)); + } + else + { + iObserver.ErrorOccured(aError, *ta); + } + } + else + { + CSIPDialogImplementation* dialog = + FindDialogByRequestId(aRequestId); + if (dialog && + dialog->ErrorOccured(aError, aRequestId, *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::RefreshErrorOccured +// Error to a standalone refresh request, not to registration or dialog refresh. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::RefreshErrorOccured(TInt aError, + TUint32 aRefreshId) + { + __TEST_INVARIANT; + + TUint32 dummyRequestId(0); + CSIPRefresh* refresh = NULL; + CSIPClientTransaction* ta = NULL; + if (FindRefresh(dummyRequestId, aRefreshId, &refresh, &ta)) + { + if (ta) + { + ta->ChangeState(CSIPTransactionBase::ETerminated); + } + refresh->ChangeState(CSIPRefresh::ETerminated); + + iObserver.ErrorOccured(aError, *refresh); + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::RegistrationErrorOccured +// ----------------------------------------------------------------------------- +// +void +CSIPConnectionImplementation::RegistrationErrorOccured(TInt aError, + TUint32 aRegistrationId, + TUint32 aRequestId) + { + __TEST_INVARIANT; + + CRegBindingImplementation* reg = FindRegistration(aRegistrationId, + aRequestId); + if (reg && reg->ErrorOccured(aError, aRequestId, *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::DialogErrorOccured +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::DialogErrorOccured(TInt aError, + TUint32 aDialogId, + TUint32 aRequestId) + { + __TEST_INVARIANT; + + CSIPDialogImplementation* dialog = FindDialog(aDialogId); + if (dialog && dialog->ErrorOccured(aError, aRequestId, *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::DialogErrorOccured +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::DialogErrorOccured(TInt aError, + TUint32 aDialogId, + TUint32 aRefreshId, + TUint32 aRequestId) + { + __TEST_INVARIANT; + + CSIPDialogImplementation* dialog = FindDialog(aDialogId); + if (dialog && + dialog->ErrorOccured(aError, aRefreshId, aRequestId, *iCallbackInfo)) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::ConnectionStateChanged +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::ConnectionStateChanged( + CSIPConnection::TState aState) + { + __TEST_INVARIANT; + + if (aState == CSIPConnection::EInactive || + aState == CSIPConnection::EUnavailable) + { + ConnectionLost(); + } + + iObserver.ConnectionStateChanged(aState); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::ConnectionLost +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::ConnectionLost() const + { + __TEST_INVARIANT; + + TInt i = 0; + for (i = 0; i < iRegistrations.Count(); i++) + { + iRegistrations[i]->ConnectionLost(); + } + + for (i = 0; i < iDialogs.Count(); i++) + { + iDialogs[i]->ConnectionLost(); + } + + for (i = 0; i < iRefreshes.Count(); i++) + { + iRefreshes[i]->ChangeState(CSIPRefresh::ETerminated); + } + + for (i = 0; i < iTransactions.Count(); i++) + { + iTransactions[i]->ChangeState(CSIPTransactionBase::ETerminated); + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::InviteCompleted +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::InviteCompleted(TUint32 aRequestId) + { + __TEST_INVARIANT; + + CSIPDialogImplementation* dialog = FindDialogByRequestId(aRequestId); + if (dialog) + { + CSIPClientTransaction* ta = static_cast + (dialog->FindTransaction(aRequestId)); + __SIP_ASSERT_RETURN(ta, KErrNotFound); + + ta->ChangeState(CSIPTransactionBase::ETerminated); + iObserver.InviteCompleted(*ta); + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IapId +// ----------------------------------------------------------------------------- +// +TUint32 CSIPConnectionImplementation::IapId() const + { + __TEST_INVARIANT; + return iIapId; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::SIP +// ----------------------------------------------------------------------------- +// +CSIP* CSIPConnectionImplementation::SIP() + { + __TEST_INVARIANT; + return iSIP; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::SIP +// ----------------------------------------------------------------------------- +// +const CSIP* CSIPConnectionImplementation::SIP() const + { + __TEST_INVARIANT; + return iSIP; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::SetOptL +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::SetOptL(TUint aOptionName, + TUint aOptionLevel, + const TDesC8& aOption) + { + __TEST_INVARIANT; + return iClientConnection->SetOptL(aOptionName, aOptionLevel, aOption); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::SetOptL +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::SetOptL(TUint aOptionName, + TUint aOptionLevel, + TInt aOption) + { + __TEST_INVARIANT; + return iClientConnection->SetOptL(aOptionName, aOptionLevel, aOption); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::AddRegistrationL +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::AddRegistrationL( + CRegBindingImplementation& aRegistration) + { + __TEST_INVARIANT; + iRegistrations.AppendL(&aRegistration); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::RemoveRegistration +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::RemoveRegistration( + const CRegBindingImplementation& aRegistration) + { + __TEST_INVARIANT; + + TInt pos = iRegistrations.Find(&aRegistration); + if (pos != KErrNotFound) + { + iRegistrations.Remove(pos); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::AddDialog +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::AddDialogL(CSIPDialogImplementation& aDialog) + { + __TEST_INVARIANT; + iDialogs.AppendL(&aDialog); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::RemoveDialog +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::RemoveDialog( + const CSIPDialogImplementation& aDialog) + { + __TEST_INVARIANT; + + iClientConnection->TerminateDialog(aDialog.DialogId()); + + TInt pos = iDialogs.Find(&aDialog); + if (pos != KErrNotFound) + { + iDialogs.Remove(pos); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindTransaction +// ----------------------------------------------------------------------------- +// +CSIPTransactionBase* CSIPConnectionImplementation::FindTransaction( + TUint32 aRequestId) const + { + __TEST_INVARIANT; + + for (TInt i = 0; i < iTransactions.Count(); i++) + { + if (iTransactions[i]->RequestId() == aRequestId) + { + return iTransactions[i]; + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindClientTransaction +// ----------------------------------------------------------------------------- +// +CSIPClientTransaction* CSIPConnectionImplementation::FindClientTransaction( + TUint32 aRequestId) const + { + __TEST_INVARIANT; + + CSIPTransactionBase* ta = FindTransaction(aRequestId); + if (ta && ta->IsSIPClientTransaction()) + { + return static_cast(ta); + } + + CRegBindingImplementation* registration = FindRegistration(aRequestId); + if (registration) + { + return registration->FindTransaction(aRequestId); + } + + CSIPDialogImplementation* dialog = FindDialogByRequestId(aRequestId); + if (dialog) + { + ta = dialog->FindTransaction(aRequestId); + if (ta && ta->IsSIPClientTransaction()) + { + return static_cast(ta); + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindRefresh +// ----------------------------------------------------------------------------- +// +CSIPRefresh* CSIPConnectionImplementation::FindRefresh( + TUint32 aRequestId, + TUint32 aRefreshId) const + { + CSIPRefresh* refresh = NULL; + + CSIPClientTransaction* dummyTa = NULL; + if (FindRefresh(aRequestId,aRefreshId,&refresh,&dummyTa)) + { + return refresh; + } + + for (TInt i = 0; i < iDialogs.Count(); i++) + { + refresh = iDialogs[i]->FindRefresh(aRequestId,aRefreshId); + } + + for (TInt i = 0; !refresh && i < iRegistrations.Count(); i++) + { + CSIPRefresh* regRefresh = iRegistrations[i]->SIPRefresh(); + if (regRefresh) + { + if((regRefresh->RefreshId() == aRefreshId) || + (regRefresh->SIPTransaction() && + regRefresh->SIPTransaction()->RequestId() == aRequestId)) + { + refresh = regRefresh; + } + } + } + + return refresh; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindRefresh +// ----------------------------------------------------------------------------- +// +TBool CSIPConnectionImplementation::FindRefresh(TUint32 aRequestId, + TUint32 aRefreshId, + CSIPRefresh** aRefresh, + CSIPClientTransaction** aTransaction) const + { + __TEST_INVARIANT; + + for (TInt i = 0; i < iRefreshes.Count(); i++) + { + if (iRefreshes[i]->DoesMatch(aRefreshId)) + { + *aRefresh = iRefreshes[i]; + //Transaction can be NULL + *aTransaction = iRefreshes[i]->Transaction(); + return ETrue; + } + } + + CSIPTransactionBase* ta = FindTransaction(aRequestId); + if (ta && ta->IsSIPClientTransaction()) + { + CSIPClientTransaction* clientTa = + static_cast(ta); + + //Application may've deleted the refresh, even if transaction is found + if (clientTa->Refresh()) + { + *aTransaction = clientTa; + *aRefresh = clientTa->Refresh(); + return ETrue; + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindRegistration +// First search by aRegistrationId. If not found, the RegistrationId hasn't yet +// been received from SIP client. Search again with aRequestId. +// ----------------------------------------------------------------------------- +// +CRegBindingImplementation* +CSIPConnectionImplementation::FindRegistration(TUint32 aRegistrationId, + TUint32 aRequestId) const + { + __TEST_INVARIANT; + + for (TInt i = 0; i < iRegistrations.Count(); i++) + { + if (iRegistrations[i]->ContextId() == aRegistrationId) + { + return iRegistrations[i]; + } + } + + return FindRegistration(aRequestId); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindRegistration +// ----------------------------------------------------------------------------- +// +CRegBindingImplementation* +CSIPConnectionImplementation::FindRegistration(TUint32 aRequestId) const + { + __TEST_INVARIANT; + + for (TInt i = 0; i < iRegistrations.Count(); i++) + { + if (iRegistrations[i]->FindTransaction(aRequestId)) + { + return iRegistrations[i]; + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindDialog +// ----------------------------------------------------------------------------- +// +CSIPDialogImplementation* +CSIPConnectionImplementation::FindDialog(TUint32 aDialogId) const + { + __TEST_INVARIANT; + + for (TInt i = 0; i < iDialogs.Count(); i++) + { + if (iDialogs[i]->DialogId() == aDialogId) + { + return iDialogs[i]; + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::FindDialogByRequestId +// ----------------------------------------------------------------------------- +// +CSIPDialogImplementation* +CSIPConnectionImplementation::FindDialogByRequestId(TUint32 aRequestId) const + { + __TEST_INVARIANT; + + for (TInt i = 0; i < iDialogs.Count(); i++) + { + if (iDialogs[i]->FindTransaction(aRequestId)) + { + return iDialogs[i]; + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::InitialRegisterStateL +// ----------------------------------------------------------------------------- +// +CRegistrationState* CSIPConnectionImplementation::InitialRegisterStateL() const + { + __TEST_INVARIANT; + CheckCSipL(); + + return iSIP->Implementation().InitialRegisterState(); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::InitialDialogStateL +// ----------------------------------------------------------------------------- +// +CDialogState* CSIPConnectionImplementation::InitialDialogStateL() const + { + __TEST_INVARIANT; + CheckCSipL(); + + return iSIP->Implementation().InitialDialogState(); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::CSIPDeleted +// Inform registrations and dialogs, as CSIP deletes their state handlers. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::CSIPDeleted() + { + __TEST_INVARIANT; + + iSIP = NULL; + + TInt i = 0; + for (i = 0; i < iRegistrations.Count(); i++) + { + iRegistrations[i]->ChangeState(NULL); + } + + for (i = 0; i < iDialogs.Count(); i++) + { + iDialogs[i]->ChangeState(NULL); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::CheckCSipL +// Don't call invariant as CheckCSipL is also used by ConstructL. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::CheckCSipL() const + { + __ASSERT_ALWAYS(iSIP, User::Leave(KErrSIPResourceNotAvailable)); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::ClientConnectionL +// ----------------------------------------------------------------------------- +// +CSIPClientConnection& CSIPConnectionImplementation::ClientConnectionL() + { + __TEST_INVARIANT; + return *iClientConnection; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::ClientConnection +// ----------------------------------------------------------------------------- +// +CSIPClientConnection* CSIPConnectionImplementation::ClientConnection() + { + __TEST_INVARIANT; + return iClientConnection; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::SIPConnectionL +// ----------------------------------------------------------------------------- +// +CSIPConnection& CSIPConnectionImplementation::SIPConnectionL() + { + __TEST_INVARIANT; + return iConnection; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::UpdateRefreshL +// No need to check connection state. It is checked in SIPClient. +// ----------------------------------------------------------------------------- +// +CSIPClientTransaction* +CSIPConnectionImplementation::UpdateRefreshL(CSIPRefresh& aRefresh, + CSIPMessageElements* aElements, + TBool aTerminate) + { + __TEST_INVARIANT; + __ASSERT_ALWAYS(iRefreshes.Find(&aRefresh) != KErrNotFound, + User::Leave(KErrNotFound)); + + CSIPClientTransaction* ta = + CSIPClientTransaction::NewLC(aRefresh.RequestType(), + *this, + &aRefresh); + TUint32 requestId(0); + if (aTerminate) + { + iClientConnection->SendRequestAndTerminateRefreshL(aRefresh.RefreshId(), + requestId, + aElements); + } + else + { + iClientConnection->SendRequestAndUpdateRefreshL(aRefresh.RefreshId(), + requestId, + aElements); + } + CleanupStack::Pop(ta); + ta->SetRequestId(requestId); + delete aElements; + + __TEST_INVARIANT; + return ta; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::DeletingRefresh +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::DeletingRefresh(CSIPRefresh& aRefresh, + TUint32 aRefreshId) + { + __TEST_INVARIANT; + + TInt pos = iRefreshes.Find(&aRefresh); + if (pos != KErrNotFound) + { + iRefreshes.Remove(pos); + } + + iClientConnection->TerminateRefresh(aRefreshId); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::TransactionAssociation +// ----------------------------------------------------------------------------- +// +MTransactionAssociation& CSIPConnectionImplementation::TransactionAssociation() + { + __TEST_INVARIANT; + return *this; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::CheckIfStandAlone +// ----------------------------------------------------------------------------- +// +TInt CSIPConnectionImplementation::CheckIfStandAlone() + { + __TEST_INVARIANT; + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::AddTransactionL +// ----------------------------------------------------------------------------- +// +void +CSIPConnectionImplementation::AddTransactionL(CSIPTransactionBase& aTransaction) + { + __TEST_INVARIANT; + + iTransactions.AppendL(&aTransaction); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::RemoveTransaction +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::RemoveTransaction( + const CSIPTransactionBase& aTransaction) + { + __TEST_INVARIANT; + + TInt pos = iTransactions.Find(&aTransaction); + if (pos != KErrNotFound) + { + iTransactions.Remove(pos); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingDialogResponseL +// Response in a dialog or a one that creates a dialog has been received. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::IncomingDialogResponseL( + CSIPResponseElements* aElements, + TUint32 aRequestId, + TUint32 aDialogId) + { + __TEST_INVARIANT; + + IncomingResponseToDialogL(aElements, aRequestId, aDialogId, NULL); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingDialogResponseL +// Refresh related response in a dialog or a one that creates a dialog. +// If error response to an existing refresh, aRequestId is the transactionId of +// a transaction initiated by Refresh subsystem, and not recognized by SIP API. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::IncomingDialogResponseL( + CSIPResponseElements* aElements, + TUint32 aRequestId, + TUint32 aRefreshId, + TUint32 aDialogId) + { + __TEST_INVARIANT; + + IncomingResponseToDialogL(aElements, aRequestId, aDialogId, &aRefreshId); + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::IncomingResponseToDialogL +// If forked response, aDialogId won't find the CSIPDialogImplementation, so +// aRequestId is also used for searching. +// ----------------------------------------------------------------------------- +// +void CSIPConnectionImplementation::IncomingResponseToDialogL( + CSIPResponseElements* aElements, + TUint32 aRequestId, + TUint32 aDialogId, + TUint32* aRefreshId) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aElements != NULL, KErrArgument); + + CSIPDialogImplementation* dialog = FindDialog(aDialogId); + if (!dialog) + { + dialog = FindDialogByRequestId(aRequestId); + } + + if (dialog) + { + TBool useCallback = EFalse; + if (aRefreshId) + { + useCallback = dialog->IncomingResponseL(aElements, + aRequestId, + *aRefreshId, + aDialogId, + *iCallbackInfo); + } + else + { + useCallback = dialog->IncomingResponseL(aElements, + aRequestId, + aDialogId, + *iCallbackInfo); + } + if (useCallback) + { + iCallbackInfo->ExecuteCallback(iObserver); + } + } + else + { + delete aElements; + } + } + +// ----------------------------------------------------------------------------- +// CSIPConnectionImplementation::__DbgTestInvariant +// ----------------------------------------------------------------------------- +// + +void CSIPConnectionImplementation::__DbgTestInvariant() const + { + if (!iClientConnection) + { + User::Invariant(); + } + }