diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/Refreshes/src/CSipRefreshBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/Refreshes/src/CSipRefreshBase.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,925 @@ +// Copyright (c) 2005-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 : CSipRefreshBase.cpp +// Part of : SIPRefreshes +// Version : SIP/4.0 +// + + + +#include "SipStackServerDefs.h" +#include "MTransactionUser.h" +#include "MRefreshOwner.h" +#include "CSipRefreshMgr.h" +#include "siprequest.h" +#include "sipresponse.h" +#include "sipcontactheader.h" +#include "sipaddress.h" +#include "sipcseqheader.h" +#include "sipexpiresheader.h" +#include "siptoheader.h" +#include "sipfromheader.h" +#include "SipLogs.h" +#include "sipcallidheader.h" +#include "uricontainer.h" +#include "siprouteheader.h" +#include "siprecordrouteheader.h" +#include "sipheaderbase.h" +#include "siperr.h" +#include "SipAssert.h" +#include "sipstrings.h" +#include "sipstrconsts.h" +#include "TSIPTransportParams.h" +#include "CSipRefreshBase.h" +#include "sipsec.h" + + +const TInt KOneSecInMilliSecs = 1000; // one second is 1000 millisecond + + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::CSipRefreshBase +// ----------------------------------------------------------------------------- +// +CSipRefreshBase::CSipRefreshBase (MTransactionUser& aTU, + MTimerManager& aTimerMgr, + CSIPSec& aSIPSec, + CSipRefreshMgr& aRefreshMgr, + TRegistrationId aRegistrationId, + MRefreshOwner* aOwner, + MSIPSecUser& aSIPSecUser) + : iRefreshMgr (aRefreshMgr), + iRefreshId (aRefreshMgr.NextRefreshId()), + iCurrentTransactionId (KEmptyTransactionId), + iFirstRequest (ETrue), + iSIPSecUser (aSIPSecUser), + iOwner (aOwner), + iTU (aTU), + iTimerMgr (aTimerMgr), + iSIPSec (aSIPSec), + iTransactionOwnerCleared (EFalse), + iIntervalUpdated (EFalse), + iRegistrationId (aRegistrationId), + iOwnRequest (ETrue), + iRemoveRouteHeaders (EFalse) + { + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::BaseConstructL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::BaseConstructL(CURIContainer& aRemoteTarget, + CSIPRequest& aRequest) + { + iRemoteTarget = CURIContainer::NewL(aRemoteTarget); + TInt expiresInSeconds = ExpirationTimeFromRequestL(aRequest); + iIntervalInMilliSeconds = CalculateInterval(expiresInSeconds); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::~CSipRefreshBase +// ----------------------------------------------------------------------------- +// +CSipRefreshBase::~CSipRefreshBase () + { + if (iTimerMgr.IsRunning(iTimerId)) + { + iTimerMgr.Stop(iTimerId); + } + + if (!iTransactionOwnerCleared) + { + iTU.ClearTransactionOwner (this); + } + + if (iOwnRequest) + { + delete iRequest; + } + + delete iRemoteTarget; + delete iUpdatedHeader; + iSIPSec.ClearCache(this); + iUpdatedRouteHeaders.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ClearTransactionOwner +// Needs to be called before the refresh is put to DeleteMgr, +// so that TU will not call this refresh anymore. +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::ClearTransactionOwner() + { + iTU.ClearTransactionOwner (this); + iTransactionOwnerCleared = ETrue; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::Owner +// ----------------------------------------------------------------------------- +// +MRefreshOwner* CSipRefreshBase::Owner() + { + return iOwner; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::Id +// ----------------------------------------------------------------------------- +// +const TRefreshId& CSipRefreshBase::Id() const + { + return iRefreshId; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::CurrentTransactionId +// ----------------------------------------------------------------------------- +// +TTransactionId CSipRefreshBase::CurrentTransactionId() const + { + return iCurrentTransactionId; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::Request +// ----------------------------------------------------------------------------- +// +CSIPRequest* CSipRefreshBase::Request() + { + return iRequest; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::Request +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetIntervalL(TInt aInterval) + { + __ASSERT_ALWAYS(aInterval > 0, User::Leave(KErrArgument)); + + TInt tmp = CalculateInterval(aInterval); + if (iTimerMgr.IsRunning(iTimerId)) + { + iTimerMgr.Stop(iTimerId); + StartTimerL(tmp); + } + iIntervalInMilliSeconds = tmp; + iIntervalUpdated = ETrue; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::Request +// ----------------------------------------------------------------------------- +// +TInt CSipRefreshBase::Interval() const + { + if (iIntervalInMilliSeconds < KOneSecInMilliSecs) + { + return 1; + } + return iIntervalInMilliSeconds/KOneSecInMilliSecs; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ReceiveL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::ReceiveL (TUint32 /*aIapId*/, + TTransactionId /*aTransactionId*/, + CSIPRequest* /*aRequest*/) + { + // Must not ever receive SIP requests from TU. + __SIP_ASSERT_LEAVE (EFalse, KErrArgument); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ReceiveL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::ReceiveL (TTransactionId aTransactionId, + CSIPResponse* aResponse) + { + __SIP_ASSERT_LEAVE (iRequest, KErrArgument); + + __SIP_ASSERT_LEAVE (aResponse, KErrArgument); + + __SIP_ASSERT_LEAVE (aTransactionId == iCurrentTransactionId, KErrArgument); + + __SIP_MESSAGE_LOG ("Refreshes", *aResponse) + + if (aResponse->Type() == CSIPResponse::E1XX) + { + ReceivedProvisonalResponseL (aResponse); + } + else if (aResponse->Type() == CSIPResponse::E2XX) + { + Received200ClassResponseL (aResponse); + } + else // error response + { + ReceivedErrorResponseL (aResponse); + } + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::TransactionEnded +// ----------------------------------------------------------------------------- +// +TInt CSipRefreshBase::TransactionEnded(TUint32 /*aIapId*/, + TTransactionId aTransactionId, + TInt aReason) + { + __SIP_ASSERT_RETURN_VALUE (aTransactionId == iCurrentTransactionId, + KErrArgument); + + TInt err = KErrNone; + if (aReason != KErrNone) + { + RefreshErrorOccured(aTransactionId,aReason); + err = iRefreshMgr.RemoveRefreshBy (this); + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::NextCSeq +// ----------------------------------------------------------------------------- +// +TInt CSipRefreshBase::NextCSeq (TUint& aCSeq) + { + return iOwner->NextRefreshCSeq (aCSeq); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SIPSecUser +// ----------------------------------------------------------------------------- +// +const MSIPSecUser* CSipRefreshBase::SIPSecUser() const + { + return this; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::TimerExpiredL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::TimerExpiredL (TTimerId aTimerId, TAny* /*aTimerParam*/) + { + __ASSERT_ALWAYS (aTimerId == iTimerId, User::Leave (KErrNotFound)); + + if(NULL == iRequest) + { + StopTimer(); + return; + } + + UpdateCSeqValueL(*iRequest); + + TRAPD (err, SendL(iCurrentTransactionId, iRequest)); + + if (err != KErrNone) + { + // Convert network states to a SIP stack error + if (err == CSIPConnection::ESuspended || + err == CSIPConnection::EInactive || + err == CSIPConnection::EUnavailable) + { + err = KErrSIPTransportFailure; + } + User::LeaveIfError(RefreshErrorOccured(iCurrentTransactionId, err)); + User::LeaveIfError(iRefreshMgr.RemoveRefreshBy(this)); + } + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::PassOnlyRealmsToUser +// From MSIPSecUser +// ----------------------------------------------------------------------------- +// +TBool CSipRefreshBase::PassOnlyRealmsToUser() const + { + return iSIPSecUser.PassOnlyRealmsToUser(); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::RequestCredentialsL +// From MSIPSecUser +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::RequestCredentialsL(const TDesC8& aRealm) + { + iSIPSecUser.RequestCredentialsL(aRealm); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::RequestCredentialsL +// From MSIPSecUser +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::RequestCredentialsL( + CSIPResponse& aResponse, + TTransactionId aTransactionId, + TRefreshId /*aRefreshId*/) + { + iSIPSecUser.RequestCredentialsL(aResponse,aTransactionId,iRefreshId); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::TrustedUser +// From MSIPSecUser +// ----------------------------------------------------------------------------- +// +const MSIPSecUser* CSipRefreshBase::TrustedUser(TRegistrationId aRegistrationId) + { + return iSIPSecUser.TrustedUser(aRegistrationId); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ByPassSIPSec +// From MSIPSecUser +// ----------------------------------------------------------------------------- +// +TBool CSipRefreshBase::ByPassSIPSec() const + { + return iSIPSecUser.ByPassSIPSec(); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetRequest +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetRequest (CSIPRequest* aRequest, + TBool aDeleteRequest) + { + if (iOwnRequest) + { + delete iRequest; + } + iRequest = aRequest; + iOwnRequest = aDeleteRequest; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SendL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SendL (TTransactionId& aTransactionId, + CSIPRequest* aRequest) + { + if (iUpdatedHeader) + { + UpdateHeaderForL(*aRequest); + } + if (iRemoveRouteHeaders) + { + RemoveRouteHeadersFor(*aRequest); + } + if (iUpdatedRouteHeaders.Count() > 0) + { + UpdateRouteHeadersForL(*aRequest); + } + + iTU.SendL (aTransactionId, iRegistrationId, aRequest, + this, *iRemoteTarget, + iOwner->TransportParams(iRegistrationId), EFalse); + + iIntervalUpdated = EFalse; + iCurrentTransactionId = aTransactionId; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SendAndGetHeadersL +// ----------------------------------------------------------------------------- +// +MTransactionHeaders* CSipRefreshBase::SendAndGetHeadersL ( + TTransactionId& aTransactionId, + CSIPRequest* aRequest) + { + MTransactionHeaders* headers = iTU.SendAndGetHeadersL( + aTransactionId, iRegistrationId, aRequest, this, + *iRemoteTarget, iOwner->TransportParams(iRegistrationId), EFalse); + iCurrentTransactionId = aTransactionId; + return headers; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::UpdateRemoteTargetL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::UpdateRemoteTargetL(CURIContainer& aRemoteTarget) + { + CURIContainer* tempRemoteTarget = CURIContainer::NewL(aRemoteTarget); + delete iRemoteTarget; + iRemoteTarget = tempRemoteTarget; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetUpdatedHeader +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetUpdatedHeader(CSIPHeaderBase* aHeader) + { + delete iUpdatedHeader; + iUpdatedHeader = aHeader; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetUpdatedRouteHeadersL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetUpdatedRouteHeadersL ( + const RPointerArray& aHeaderArray) + { + RPointerArray tempHeaderArray; + CSIPHeaderBase::PushLC(&tempHeaderArray); + + for (TInt i = 0; i < aHeaderArray.Count(); i++) + { + CSIPHeaderBase* tempHeader = (aHeaderArray[i])->CloneL(); + CleanupStack::PushL(tempHeader); + User::LeaveIfError(tempHeaderArray.Append(tempHeader)); + CleanupStack::Pop(tempHeader); + } + + CleanupStack::Pop(); // tempHeaderArray + iUpdatedRouteHeaders.ResetAndDestroy(); + iUpdatedRouteHeaders = tempHeaderArray; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::RemoveRouteHeaders +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::RemoveRouteHeaders () + { + // reset the route headers array + iUpdatedRouteHeaders.ResetAndDestroy(); + iRemoveRouteHeaders = ETrue; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SendUpdateRequestL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SendUpdateRequestL (TTransactionId& aTransactionId, + CSIPRequest* aRequest) + { + CheckUpdateRequestMethodL(*aRequest); + CheckUpdateRequestHeadersL(*aRequest); + + delete iUpdatedHeader; + iUpdatedHeader = NULL; + + iUpdatedRouteHeaders.ResetAndDestroy(); + + if (iTimerMgr.IsRunning(iTimerId)) + { + iTimerMgr.Stop(iTimerId); + } + + iTU.ClearTransactionOwner(iCurrentTransactionId); + + SendL(aTransactionId,aRequest); + + iFirstRequest = ETrue; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::UpdateRequestL +// ----------------------------------------------------------------------------- +// +void +CSipRefreshBase::UpdateRequestL (TTransactionId& aTransactionId, + CSIPRequest* aRequest) + { + CheckUpdateRequestExpiresValueL (*aRequest); + SendUpdateRequestL(aTransactionId, aRequest); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::TerminateRequestL +// ----------------------------------------------------------------------------- +// +void +CSipRefreshBase::TerminateRequestL (TTransactionId& aTransactionId, + CSIPRequest* aRequest) + { + CheckTerminateRequestExpiresValueL(*aRequest); + SendUpdateRequestL(aTransactionId, aRequest); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::IAPId +// ----------------------------------------------------------------------------- +// +TUint CSipRefreshBase::IAPId () const + { + return iOwner->TransportParams(iRegistrationId).IapId(); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ResetRegistrationId +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::ResetRegistrationId() + { + iRegistrationId = KEmptyRegistrationId; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::Received200ClassResponseL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::Received200ClassResponseL (CSIPResponse* aResponse) + { + TInt expirationTimeInRequest = ExpirationTimeFromRequestL(*iRequest); + // if is terminate, expires in request is 0 + if (expirationTimeInRequest == 0) + { + User::LeaveIfError(iRefreshMgr.RemoveRefreshBy (this)); + RefreshReceivedL(iCurrentTransactionId, aResponse); + iTU.ClearTransactionOwner(this); + return; + } + + TInt expirationTimeInResponse = ExpirationTimeFromResponse(*aResponse); + + // response expire value lowered to 0 + if (expirationTimeInResponse == 0) + { + User::LeaveIfError(RefreshErrorOccured(iCurrentTransactionId, + KErrSIPMalformedMessage)); + User::LeaveIfError(iRefreshMgr.RemoveRefreshBy (this)); + delete aResponse; + return; + } + + // no expires time from response + if (expirationTimeInResponse == KErrNotFound) + { + // copy the expires value from request to response + SetExpirationTimeToResponseL(*aResponse, expirationTimeInRequest); + expirationTimeInResponse = ExpirationTimeFromResponse(*aResponse); + } + + if (!iIntervalUpdated) + { + if(expirationTimeInResponse <= expirationTimeInRequest) + iIntervalInMilliSeconds = CalculateInterval(expirationTimeInResponse); + else + iIntervalInMilliSeconds = CalculateInterval(expirationTimeInRequest); + } + + StartTimerL(iIntervalInMilliSeconds); + + TRAPD(err, Forward2xxResponseToCallerL(aResponse)); + + if (err) + { + iTimerMgr.Stop(iTimerId); + User::Leave(err); + } + + iTU.ClearTransactionOwner(iCurrentTransactionId); + + iFirstRequest = EFalse; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ReceivedErrorResponseL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::ReceivedErrorResponseL (CSIPResponse* aResponse) + { + User::LeaveIfError(iRefreshMgr.RemoveRefreshBy (this)); + RefreshReceivedL(iCurrentTransactionId, aResponse); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ReceivedProvisonalResponseL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::ReceivedProvisonalResponseL (CSIPResponse* aResponse) + { + // if is first request, send response. + if (iFirstRequest) + { + RefreshReceivedL(iCurrentTransactionId,aResponse); + } + else + { + delete aResponse; + } + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::UpdateCSeqValueL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::UpdateCSeqValueL(CSIPRequest& aRequest) + { + CSIPCSeqHeader* cseqHeader = aRequest.CSeq(); + + __SIP_ASSERT_LEAVE (cseqHeader, KErrArgument); + + TUint cseq = cseqHeader->Seq(); + + // ask Cseq value from refresh owner, leaves if error + User::LeaveIfError(iOwner->NextRefreshCSeq(cseq)); + + cseqHeader->SetSeq(cseq); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::UpdateHeaderForL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::UpdateHeaderForL(CSIPRequest& aRequest) + { + if (aRequest.HasHeader(iUpdatedHeader->Name())) + { + CSIPHeaderBase* oldHeader = aRequest.Header(iUpdatedHeader->Name(), 0); + // ownership of iUpdatedHeader is passed. + // the oldHeader is deleted. + aRequest.ReplaceHeaderL(oldHeader, iUpdatedHeader); + oldHeader = NULL; + } + else + { + // the ownership of iUpdatedHeader header is transferred. + aRequest.AddHeaderL(iUpdatedHeader); + } + iUpdatedHeader = NULL; // detach the iUpdatedHeader. + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::UpdateRouteHeadersForL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::UpdateRouteHeadersForL(CSIPRequest& aRequest) + { + if (aRequest.HasHeader(SIPStrings::StringF(SipStrConsts::ERouteHeader))) + { + aRequest.ReplaceHeadersL(iUpdatedRouteHeaders); + } + else + { + for (TInt i = 0; i < iUpdatedRouteHeaders.Count(); i++) + { + CSIPHeaderBase* header = (iUpdatedRouteHeaders[i])->CloneL(); + CleanupStack::PushL(header); + aRequest.AddHeaderL(header); + CleanupStack::Pop(header); + } + } + // clear the route headers array after update those to aRequest + iUpdatedRouteHeaders.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::RemoveRouteHeadersFor +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::RemoveRouteHeadersFor (CSIPRequest& aRequest) + { + if (aRequest.HasHeader(SIPStrings::StringF(SipStrConsts::ERouteHeader))) + { + aRequest.DeleteHeaders(SIPStrings::StringF(SipStrConsts::ERouteHeader)); + } + + // change the flag to EFalse after remove route headers from aRequest + iRemoveRouteHeaders = EFalse; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetToFromOriginalRequestL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetToFromOriginalRequestL(CSIPRequest& aRequest) + { + CSIPToHeader* originalTo = iRequest->To(); + __SIP_ASSERT_LEAVE (originalTo, KErrGeneral); + CSIPToHeader* newTo = CSIPToHeader::NewLC(*originalTo); + aRequest.AddHeaderL(newTo); + CleanupStack::Pop(newTo); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetFromFromOriginalRequestL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetFromFromOriginalRequestL(CSIPRequest& aRequest) + { + CSIPFromHeader* originalFrom = iRequest->From(); + __SIP_ASSERT_LEAVE (originalFrom, KErrGeneral); + CSIPFromHeader* newFrom = CSIPFromHeader::NewLC(*originalFrom); + aRequest.AddHeaderL(newFrom); + CleanupStack::Pop(newFrom); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetCallIdFromOriginalRequestL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetCallIdFromOriginalRequestL(CSIPRequest& aRequest) + { + const CSIPCallIDHeader* originalCallId = iRequest->CallID(); + __SIP_ASSERT_LEAVE (originalCallId != 0, KErrGeneral); + CSIPHeaderBase* newCallId = originalCallId->CloneL(); + CleanupStack::PushL(newCallId); + aRequest.AddHeaderL(newCallId); + CleanupStack::Pop(newCallId); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetCSeqFromOriginalRequestL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetCSeqFromOriginalRequestL(CSIPRequest& aRequest) + { + const CSIPCSeqHeader* originalCSeq = iRequest->CSeq(); + __SIP_ASSERT_LEAVE (originalCSeq != 0, KErrGeneral); + + CSIPCSeqHeader* newCseq = + static_cast(originalCSeq->CloneL()); + CleanupStack::PushL(newCseq); + // ask the next CSeq number + TUint cseq = newCseq->Seq(); + User::LeaveIfError(iOwner->NextRefreshCSeq(cseq)); + newCseq->SetSeq(cseq); + + aRequest.AddHeaderL(newCseq); + CleanupStack::Pop(newCseq); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::RefreshErrorOccured +// ----------------------------------------------------------------------------- +// +TInt CSipRefreshBase::RefreshErrorOccured(TTransactionId aTransactionId, + TInt aError) + { + return iOwner->RefreshError(iRefreshId, aTransactionId, aError); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::RefreshReceivedL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::RefreshReceivedL(TTransactionId aTransactionId, + CSIPResponse* aResponse) + { + iOwner->RefreshReceivedL(aTransactionId, iRefreshId, aResponse); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::StartTimerL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::StartTimerL(TInt aMilliSeconds) + { + iTimerId = iTimerMgr.StartL(this,aMilliSeconds); + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::ExpireTimeFromResponseExpiresHeader +// ----------------------------------------------------------------------------- +// +TInt CSipRefreshBase::ExpireTimeFromResponseExpiresHeader ( + CSIPResponse& aResponse) + { + if(!aResponse.HasHeader(SIPStrings::StringF(SipStrConsts::EExpiresHeader))) + { + return KErrNotFound; + } + CSIPHeaderBase* resHeader = + aResponse.Header(SIPStrings::StringF(SipStrConsts::EExpiresHeader), 0); + CSIPExpiresHeader* resContact = static_cast(resHeader); + return resContact->Value(); + } + + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::SetExpireTimeToResponseExpiresHeaderL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::SetExpireTimeToResponseExpiresHeaderL ( + CSIPResponse& aResponse, + TUint aTimeInSeconds) + { + CSIPExpiresHeader* expires = static_cast( + aResponse.Header(SIPStrings::StringF(SipStrConsts::EExpiresHeader),0)); + + if(expires) + { + expires->SetValue(aTimeInSeconds); + } + else + { + expires = new(ELeave)CSIPExpiresHeader(aTimeInSeconds); + CleanupStack::PushL(expires); + aResponse.AddHeaderL(expires); + CleanupStack::Pop(expires); + } + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::CheckUpdateRequestMethodL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::CheckUpdateRequestMethodL(CSIPRequest& aRequest) + { + if (aRequest.Method().DesC().Length() == 0) + { + // copy method from original request + aRequest.SetMethodL(iRequest->Method()); + } + else + { + if(aRequest.Method() != iRequest->Method()) + { + User::Leave(KErrArgument); // methods are different + } + } + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::CheckUpdateRequestHeadersL +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::CheckUpdateRequestHeadersL(CSIPRequest& aRequest) + { + if (!aRequest.To()) + { + SetToFromOriginalRequestL(aRequest); + } + if (!aRequest.From()) + { + SetFromFromOriginalRequestL(aRequest); + } + if (!aRequest.CallID()) + { + SetCallIdFromOriginalRequestL(aRequest); + } + if (!aRequest.CSeq()) + { + SetCSeqFromOriginalRequestL(aRequest); + } + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::CalculateInterval +// ----------------------------------------------------------------------------- +// +TInt CSipRefreshBase::CalculateInterval(TInt aValueInSeconds) const + { + TInt interval = 0; // milliseconds + if (aValueInSeconds > 0) + { + const TInt KDelimiter1 = 1200; + const TInt KDelimiter2 = 600; + const TInt KDivider = 2; + + // If expiration time is greater than 1200 seconds, + // the interval is set to 600 seconds lower than expiration time. + // Otherwise, interval is set to half of the expiration time + + if (aValueInSeconds > KDelimiter1) + { + interval = KOneSecInMilliSecs*(aValueInSeconds-KDelimiter2); + + } + else + { + interval = (KOneSecInMilliSecs*aValueInSeconds)/KDivider; + } + } + return interval; + } + +// ----------------------------------------------------------------------------- +// CSipRefreshBase::StopTimer +// ----------------------------------------------------------------------------- +// +void CSipRefreshBase::StopTimer() +{ + if( iTimerMgr.IsRunning(iTimerId) ) + { + iTimerMgr.Stop(iTimerId); + } +}