diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/ConnectionMgr/src/multipleaddrressender.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/ConnectionMgr/src/multipleaddrressender.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,376 @@ +// Copyright (c) 2004-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 : multipleaddrressender.cpp +// Part of : ConnectionMgr +// Version : SIP/4.0 +// + + + + +#include "multipleaddrressender.h" +#include "sipresponse.h" +#include "multiaddrsenderowner.h" +#include "CSIPServerResolver.h" +#include "sipuri.h" +#include "sipviaheader.h" +#include "siphostport.h" +#include "SipLogs.h" +#include "MSIPResolvingResult.h" +#include "sipstrings.h" +#include "sipstrconsts.h" +#include "TSIPTransportParams.h" +#include "siperr.h" + + +const TInt CMultipleAddrResSender::iMultisenderOffset = + _FOFF(CMultipleAddrResSender, iMultisenderLink); + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::CMultipleAddrResSender +// ----------------------------------------------------------------------------- +// +CMultipleAddrResSender::CMultipleAddrResSender( + const TSIPTransportParams& aParams, + MMultiAddrSenderOwner& aOwner, + MTimerManager& aTimer, + CSIPServerResolver& aServerResolver, + TUint aICMPErrorWaitTime + ) : + CActive( CActive::EPriorityStandard ), + iTransportParams( aParams ), + iOwner( &aOwner ), + iTimer( aTimer ), + iServerResolver( aServerResolver ), + iICMPErrorWaitTime( aICMPErrorWaitTime ), + iInUse( EFalse ), + iState( EInitialized ), + iICMPErrorOccuredWhileActive( EFalse ) + { + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::~CMultipleAddrResSender +// ----------------------------------------------------------------------------- +// +CMultipleAddrResSender::~CMultipleAddrResSender() + { + CompleteClientRequest( KErrSIPTransportFailure ); + iTimer.Stop( iTimerId ); + iServerResolver.Cancel( this ); + Cancel(); + iResultArray.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::SendL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::SendL ( CSIPResponse& aResponse, + const TInetAddr& aAddr, + TRequestStatus& aStat ) + { + __ASSERT_ALWAYS( !iInUse, User::Leave( KErrInUse ) ); + + iFirstAddr = aAddr; + iResponse = &aResponse; + iInUse = ETrue; + + iOwner->SendToNetL( iTransportParams, aResponse, aAddr, iStatus); + + iState = CMultipleAddrResSender::ESendingFirst; + aStat = KRequestPending; + iClientStatus = &aStat; + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::ICMPErrorL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::ICMPErrorL( + CSipConnectionMgr::TICMPError /*aICMPError*/, + const TInetAddr& aErrAddress ) + { + if ( iState == CMultipleAddrResSender::ESendingList && + IndexWithinBounds() && + iResultArray[ iCurrentIndex ]->Address().CmpAddr( aErrAddress ) ) + { + iResultArray[ iCurrentIndex ]->SetFailed(ETrue); + ICMPErrorWithCurrentAddressL(); + } + else if ( iState == CMultipleAddrResSender::ESendingFirst ) + { + if ( iFirstAddr.Match(aErrAddress) && + iFirstAddr.Port() == aErrAddress.Port() ) + { + ICMPErrorWithCurrentAddressL(); + } + } + else + { + // Required by PC-Lint + } + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::RunL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::RunL() + { + CompleteClientRequest( iStatus.Int() ); + + if ( iStatus == KErrNone ) + { + switch ( iState ) + { + case CMultipleAddrResSender::ESendingFirst: + case CMultipleAddrResSender::ESendingList: + WaitForICMPErrorsL(); + break; + default: + break; + } + } + else + { + iOwner->Remove( this ); + } + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::CancelResponse +// ----------------------------------------------------------------------------- +// +TBool CMultipleAddrResSender::CancelResponse( TRequestStatus& aStat ) + { + if ( &aStat == iClientStatus && + iState == CMultipleAddrResSender::ESendingFirst ) + { + CompleteClientRequest( KErrSIPTransportFailure ); + if ( IsActive() ) + { + iOwner->CancelRequest( iStatus ); + } + else + { + iTimer.Stop( iTimerId ); + iOwner->Remove( this ); + } + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::DoCancel +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::DoCancel() + { + iOwner->CancelRequest( iStatus ); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::RunError +// ----------------------------------------------------------------------------- +// +TInt CMultipleAddrResSender::RunError( TInt aError ) + { + if ( aError != KErrNoMemory ) + { + return KErrNone; + } + return aError; + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::ICMPErrorWithCurrentAddressL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::ICMPErrorWithCurrentAddressL() + { + if ( !IsActive() ) + { + iTimer.Stop( iTimerId ); + SendNextL(); + } + else + { + iICMPErrorOccuredWhileActive = ETrue; + } + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::WaitForICMPErrorsL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::WaitForICMPErrorsL() + { + if ( iICMPErrorOccuredWhileActive ) + { + SendNextL(); + iICMPErrorOccuredWhileActive = EFalse; + } + else + { + iTimerId = iTimer.StartL( this, iICMPErrorWaitTime ); + } + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::SendNextL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::SendNextL() + { + if ( IsActive() ) + { + return; + } + + if ( iState == CMultipleAddrResSender::ESendingFirst ) + { + ResolveL(); + iState = CMultipleAddrResSender::EResolving; + return; + } + + if ( iState == CMultipleAddrResSender::EResolving || + iState == CMultipleAddrResSender::ESendingList ) + { + MSIPResolvingResult* result = FirstUnfailedResult(); + if ( result ) + { + SendToNetL( *result ); + iState = CMultipleAddrResSender::ESendingList; + } + else + { + // Sending to every resolved address failed, resolve more + ResolveL(); + iState = CMultipleAddrResSender::EResolving; + } + } + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::TimerExpiredL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::TimerExpiredL (TTimerId /*aTimerId*/, + TAny* /*aTimerParam*/) + { + __SIP_LOG( "CMultipleAddrResSender::TimerExpiredL" ) + iOwner->Remove( this ); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::Has2xxResponse +// ----------------------------------------------------------------------------- +// +TBool CMultipleAddrResSender::Has2xxResponse() const + { + return ( iResponse && iResponse->Type() == CSIPResponse::E2XX ); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::CompletedL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::CompletedL() + { + SendNextL(); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::ErrorOccured +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::ErrorOccured( TInt /*aError*/ ) + { + iOwner->Remove( this ); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::SendToNetL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::SendToNetL( MSIPResolvingResult& aResult ) + { + iOwner->SendToNetL( iTransportParams, *iResponse, aResult.Address(), iStatus ); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::ResolveL +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::ResolveL() + { + if ( iResponse->HasHeader( SIPStrings::StringF(SipStrConsts::EViaHeader) ) ) + { + CSIPHeaderBase* header = iResponse->Header( + SIPStrings::StringF(SipStrConsts::EViaHeader), 0 ); + CSIPViaHeader* via = static_cast( header ); + iServerResolver.GetByViaL( *via, iResultArray, this ); + } + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::CompleteClientRequest +// ----------------------------------------------------------------------------- +// +void CMultipleAddrResSender::CompleteClientRequest(TInt aReason) + { + if ( iState == CMultipleAddrResSender::ESendingFirst ) + { + TRequestStatus* stat = iClientStatus; + if ( stat && *stat == KRequestPending ) + { + User::RequestComplete( stat, aReason ); + } + iClientStatus = 0; + } + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::IndexWithinBounds +// ----------------------------------------------------------------------------- +// +TBool CMultipleAddrResSender::IndexWithinBounds() + { + return ( iCurrentIndex >= 0 && iCurrentIndex < iResultArray.Count() ); + } + +// ----------------------------------------------------------------------------- +// CMultipleAddrResSender::FirstUnfailedResult +// ----------------------------------------------------------------------------- +// +MSIPResolvingResult* CMultipleAddrResSender::FirstUnfailedResult() + { + for ( TInt i = 0; i < iResultArray.Count(); i++ ) + { + MSIPResolvingResult* result = iResultArray[ i ]; + if ( !result->Failed() ) + { + iCurrentIndex = i; + return result; + } + } + iCurrentIndex = KErrNotFound; + return 0; + }