This release addresses the following issues:
1. The crash bug fix when receiving file
2. Now the sending is based on MSRP messages, there is no longer file receiving or sending. Client sends data as MSRP was designed.
3. Soma MSRP stack was created so that the client told the correct session-id, Symbian stack generated it by itself. This is not allowed, it was changed so that clients tell the session-id (same as used in SIP INVITE).
4. Unnecessary division of data to chunks removed when there is no need to interrupt sending. The message is sent in as few chunks as possible.
5. Stack can now receive files and chunks with ?unlimited? size. Old stack wrote the incoming data to memory and did not utilize disk space until the end of chunk was reached (large chunks from another client crashed it).
6. Now when writing the incoming data to file, it will take into account the byte-range header values. So, this complies with the RFC4975 requirements that stack must be able to handle chunks that come in any sequence.
7. Some buffering changes to outgoing/incoming data.
8. The outgoing data is now checked that it does not contain the created transaction-id before sending the data.
9. MSRP success reports are now implemented and tested against servers.
10. Progress report system fixed so progress is now visible on client (all the way to 100%).
11. Message Cancel receiving / Cancel sending now corrected and made to work as rfc4975 requires. (termination from sender and error code from receiver when cancelling).
12. Bug correction related to messages received not belonging to any session, old stack implementation did send error response, but after response was written it did give the buffer to client anyway. Now corrected.
// 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();
}
}