--- /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<CSIPClientTransaction*>(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<CSIPServerTransaction&>(*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<CSIPClientTransaction*>
+ (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<CSIPClientTransaction*>(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<CSIPClientTransaction*>(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<CSIPClientTransaction*>(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();
+ }
+ }