diff -r 000000000000 -r 1bce908db942 natfw/natfwstunturnclient/src/cstuntransaction.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/natfw/natfwstunturnclient/src/cstuntransaction.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,872 @@ +/* +* Copyright (c) 2006-2007 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: +* +*/ + + + + +#include "natfwunsaflog.h" +#include "cnatfwunsafudpsender.h" +#include "natfwunsafbindingrequest.h" +#include "natfwunsaferrorcodeattribute.h" +#include "natfwunsafunknownattributesattribute.h" +#include "natfwunsafmessageintegrityattribute.h" +#include "stunassert.h" +#include "stunutils.h" +#include "mstuntransactionobserver.h" +#include "cstuntransaction.h" +#include "ttransactioncleanup.h" +#include "stunturnclientlogs.h" +#include "tstuncallbackinfo.h" + +// ======== MEMBER FUNCTIONS ======== + +const TInt KInitCompareValue = 1; + +// Divide factor from uSecs to mSecs +const TInt KDivideFactor = 1000; + +const TInt KWaitingTime = 1600; // rfc3489bis-06#section-7.1 + +const TInt KMaxTCPWaitingTime = 7900; // rfc3489bis-06#section-7.1 + +// --------------------------------------------------------------------------- +// CSTUNTransaction::NewL +// --------------------------------------------------------------------------- +// +CSTUNTransaction* CSTUNTransaction::NewL( CNATFWUNSAFMessage& aRequest, + const TInetAddr& aAddress, + const TDesC8& aSharedSecret, + RSocket& aSocket, + CDeltaTimer& aTimer, + TInt aRetransmitInterval, + MSTUNTransactionObserver& aObserver, + const TDesC8& aProtocol, + TTransportProtocol aTransportProtocol ) + { + __ASSERT_ALWAYS( !aAddress.IsUnspecified(), User::Leave( KErrArgument ) ); + + CSTUNTransaction* self = + new ( ELeave ) CSTUNTransaction( aRequest, + aAddress, + aSharedSecret, + aTimer, + aRetransmitInterval, + aObserver, + aTransportProtocol ); + CleanupStack::PushL( self ); + self->ConstructL( aSocket, aProtocol ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::NewL - overloaded +// --------------------------------------------------------------------------- +// +CSTUNTransaction* CSTUNTransaction::NewL( CNATFWUNSAFMessage& aRequest, + const TInetAddr& aAddress, + const TDesC8& aSharedSecret, + TUint aStreamId, + TUint aConnectionId, + CDeltaTimer& aTimer, + TInt aRetransmitInterval, + MSTUNTransactionObserver& aObserver, + const TDesC8& aProtocol, + MNcmConnectionMultiplexer& aMux, + TTransportProtocol aTransportProtocol, + TBool aUseFingerprint, + const TInetAddr& aDestAddr ) + { + __ASSERT_ALWAYS( !aAddress.IsUnspecified(), User::Leave( KErrArgument ) ); + + CSTUNTransaction* self = + new ( ELeave ) CSTUNTransaction( aRequest, + aAddress, + aSharedSecret, + aStreamId, + aConnectionId, + aTimer, + aRetransmitInterval, + aObserver, + aDestAddr, + aTransportProtocol, + aUseFingerprint ); + CleanupStack::PushL( self ); + self->ConstructL( aProtocol, aMux ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::CSTUNTransaction +// --------------------------------------------------------------------------- +// +CSTUNTransaction::CSTUNTransaction( CNATFWUNSAFMessage& aRequest, + const TInetAddr& aAddress, + const TDesC8& aSharedSecret, + CDeltaTimer& aTimer, + TInt aRetransmitInterval, + MSTUNTransactionObserver& aObserver, + TTransportProtocol aTransportProtocol ) : + CSTUNTimerUser( aTimer ), + iObserver( aObserver ), + iRequest( aRequest ), + iAddress( aAddress ), + iSharedSecret( aSharedSecret ), + iInitialRetransmitInterval( aRetransmitInterval ), + iRetransmit( ETrue ), + iTransportProtocol( aTransportProtocol ), + iRetransmitCompareValue( KInitCompareValue ) + { + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::CSTUNTransaction - overloaded +// --------------------------------------------------------------------------- +// +CSTUNTransaction::CSTUNTransaction( CNATFWUNSAFMessage& aRequest, + const TInetAddr& aAddress, + const TDesC8& aSharedSecret, + TUint aStreamId, + TUint aConnectionId, + CDeltaTimer& aTimer, + TInt aRetransmitInterval, + MSTUNTransactionObserver& aObserver, + const TInetAddr& aDestAddr, + TTransportProtocol aTransportProtocol, + TBool aUseFingerprint ) : + CSTUNTimerUser( aTimer ), + iObserver( aObserver ), + iRequest( aRequest ), + iAddress( aAddress ), + iSharedSecret( aSharedSecret ), + iInitialRetransmitInterval( aRetransmitInterval ), + iRetransmit( ETrue ), + iStreamId( aStreamId ), + iSubstreamId( aConnectionId ), + iDestAddr( aDestAddr ), + iTransportProtocol( aTransportProtocol ), + iRetransmitCompareValue( KInitCompareValue ), + iUseFingerprint( aUseFingerprint ) + { + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::CSTUNTransaction +// Dummy implementation. Default constructor is declared private and not used. +// --------------------------------------------------------------------------- +// +CSTUNTransaction::CSTUNTransaction() : + CSTUNTimerUser( *( CDeltaTimer* )0x1 ), + iObserver( *( MSTUNTransactionObserver* )0x1 ), + iRequest( *( CNATFWUNSAFMessage* )0x1 ), + iAddress( *( TInetAddr* )0x1 ), + iSharedSecret( KNullDesC8 ) + { + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::CSTUNTransaction +// Dummy implementation, as copy constructor is declared private and not used. +// --------------------------------------------------------------------------- +// +CSTUNTransaction::CSTUNTransaction( const CSTUNTransaction& aTransaction ) : + CSTUNTimerUser( *( CDeltaTimer* )0x1 ), + iObserver( aTransaction.iObserver ), + iRequest( aTransaction.iRequest ), + iAddress( aTransaction.iAddress ), + iSharedSecret( aTransaction.iSharedSecret ) + { + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::ConstructL +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::ConstructL( RSocket& aSocket, const TDesC8& aProtocol ) + { + __STUNTURNCLIENT( "CSTUNTransaction::ConstructL with sender" ) + CheckProtocolL( aProtocol ); + iSender = CNATFWUNSAFUdpSender::NewL( aSocket, *this ); + SendRequestL(); + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::ConstructL +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::ConstructL( const TDesC8& aProtocol, + MNcmConnectionMultiplexer& aMux ) + { + __STUNTURNCLIENT( "CSTUNTransaction::ConstructL with mediaconsender" ) + CheckProtocolL( aProtocol ); + iMediaConSender = CNATFWUNSAFMediaConnSender::NewL( aMux ); + SendRequestL(); + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::~CSTUNTransaction +// --------------------------------------------------------------------------- +// +CSTUNTransaction::~CSTUNTransaction() + { + __STUNTURNCLIENT( "CSTUNTransaction::~CSTUNTransaction IN" ) + + if ( iMediaConSender ) + { + iMediaConSender->Cancel( iStreamId, iSubstreamId, this ); + } + + delete iMediaConSender; + delete iSender; + delete iUnknownAttr; + delete iProtocol; + + __STUNTURNCLIENT( "CSTUNTransaction::~CSTUNTransaction OUT" ) + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::NATFWUNSAFUdpMessageSentL +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::UNSAFUdpMessageSentL() + { + __STUNTURNCLIENT( "CSTUNTransaction::UNSAFUdpMessageSentL" ) + __TEST_INVARIANT; + + if ( !iTerminated ) + { + ++iSendCount; + + if ( iRetransmit ) + { + if ( ETcpProtocol == iTransportProtocol ) + { + StartTimer( KMaxTCPWaitingTime ); + } + else + { + iSendTime.HomeTime(); + StartTimer( RetransmitInterval() ); + } + } + } + + __TEST_INVARIANT; + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::NATFWUNSAFUdpMessageFailure +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::UNSAFUdpMessageFailure( TInt aError ) + { + __STUNTURNCLIENT_INT1( "\ + CSTUNTransaction::UNSAFUdpMessageFailure, error=", aError ) + __TEST_INVARIANT; + __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument ); + + if ( !iTerminated ) + { + Terminate( aError ); + } + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::MessageSent +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::MessageSent() + { + iRequestPending = EFalse; + + TRAP_IGNORE( UNSAFUdpMessageSentL() ); + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::MessageSentFailure +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::MessageSentFailure( TInt aError ) + { + __STUNTURNCLIENT_INT1( "\ + CSTUNTransaction::MessageSentFailure, error=", aError ) + iRequestPending = EFalse; + UNSAFUdpMessageFailure( aError ); + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::SendRequestL +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::SendRequestL() + { + __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL" ) + if ( iMediaConSender ) + { + __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL with mediaconsender" ) + if ( iDestAddr.IsUnspecified() ) + { + iMediaConSender->SendL( iStreamId, + iSubstreamId, iRequest, iSharedSecret, this, iUseFingerprint ); + iRequestPending = ETrue; + } + else + { + iMediaConSender->SendL( iStreamId, + iSubstreamId, iRequest, iSharedSecret, + iDestAddr, this, iUseFingerprint ); + + iRequestPending = ETrue; + } + } + else if ( iSender ) + { + __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL with original sender" ) + iSender->SendL( iAddress, iRequest, iSharedSecret ); + } + else + { + User::Leave( KErrNotReady ); + } + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::RetransmitRequestL +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::RetransmitRequestL() + { + __STUNTURNCLIENT_INT1( "\ + CSTUNTransaction::RetransmitRequestL, sendcount= ",iSendCount ) + if ( iSendCount < KMaxRequestSentCount ) + { + if ( !iDisableSending ) + { + SendRequestL(); + } + else + { + iSendTime.HomeTime(); + StartTimer( RetransmitInterval() ); + } + } + else + { + Terminate( KErrTimedOut ); + } + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::ReceiveL +// Also an ignored response stops retransmission. +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::ReceiveL( CNATFWUNSAFMessage& aResponse, + const TDesC8& aByteStream ) + { + __TEST_INVARIANT; + __STUN_ASSERT_L( + aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse || + aResponse.Type() == CNATFWUNSAFMessage::EBindingErrorResponse || + aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse || + aResponse.Type() == CNATFWUNSAFMessage::EAllocateErrorResponse || + aResponse.Type() == CNATFWUNSAFMessage::EConnectResponse || + aResponse.Type() == CNATFWUNSAFMessage::EConnectErrorResponse || + aResponse.Type() == + CNATFWUNSAFMessage::ESetActiveDestinationResponse || + aResponse.Type() == + CNATFWUNSAFMessage::ESetActiveDestinationErrorResponse, + KErrArgument ); + + if ( !iTerminated ) + { + iRetransmit = EFalse; + StopTimer(); + + if ( ShouldIgnoreResponse( aResponse ) ) + { + StartTimer( ComputeWaitDuration() ); + } + else + { + if ( EUdpProtocol == iTransportProtocol ) + { + MeasureNewRTTSample(); + } + + TTransactionCleanup taCleanup( *this ); + CleanupStack::PushL( taCleanup.CleanupItem() ); + + TInt status = ProcessResponseL( aResponse, aByteStream ); + + CleanupStack::Pop(); //cleanupItem + Terminate( status ); + } + } + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::ShouldIgnoreResponse +// 1xx-3xx response stops retransmissions, but doesn't terminate transaction. +// ----------------------------------------------------------------------------- +// +TBool +CSTUNTransaction::ShouldIgnoreResponse( const CNATFWUNSAFMessage& aResponse ) const + { + __TEST_INVARIANT; + + TInt responseCode = GetResponseCode( aResponse ); + return !aResponse.Validate() || + aResponse.HasUnknownMandatoryAttributes() || + ( responseCode >= E1XX && responseCode < E4XX ); + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::ProcessResponseL +// ----------------------------------------------------------------------------- +// +TInt CSTUNTransaction::ProcessResponseL( CNATFWUNSAFMessage& aResponse, + const TDesC8& aByteStream ) + { + __STUNTURNCLIENT( "CSTUNTransaction::ProcessResponseL" ) + __TEST_INVARIANT; + + TInt status = KErrNone; + + // binding response ( stun functionality ) + if ( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse ) + { + status = CheckIntegrityL( aResponse, aByteStream ); + if ( KErrNone == status ) + { + STUNUtils::GetMappedAddress( aResponse, iMappedAddress ); + STUNUtils::GetXorMappedAddressL( aResponse, iXorMappedAddress ); + } + } + + // allocate response ( stun relay functionality ) + else if ( aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse ) + { + status = CheckIntegrityL( aResponse, aByteStream ); + if ( KErrNone == status ) + { + // get server relay address + STUNUtils::GetRelayAddressL( aResponse, iRelayAddress ); + // get server reflexive address + STUNUtils::GetXorMappedAddressL( aResponse, iXorMappedAddress ); + } + } + + // Connect Response ( stun relay TCP functionality ) + else if ( aResponse.Type() == + CNATFWUNSAFMessage::EConnectResponse ) + { + status = CheckIntegrityL( aResponse, aByteStream ); + } + + // Active Destination Response ( stun relay functionality ) + else if ( aResponse.Type() == + CNATFWUNSAFMessage::ESetActiveDestinationResponse ) + { + __STUNTURNCLIENT( "do msg integrity check for active destination response" ) + status = CheckIntegrityL( aResponse, aByteStream ); + if ( KErrNone != status ) + { + __STUNTURNCLIENT_INT1( "msg integrity check for active\ + destination response FAILED - BUT IGNORE IT - SERVER MISBEHAVIOR DETECTED", status ) + status = KErrNone; + } + + if ( KErrNone == status ) + { + // notify stun relay implementation + STUNUtils::GetTimerValueL( aResponse, iTimerValue ); + } + } + + else + { + status = GetResponseCode( aResponse ); + if ( E4XX > status ) + { + //Invalid Binding Error Response received + status = KErrCorrupt; + } + if ( status == E420UnknownAttributes ) + { + __STUN_ASSERT_L( !iUnknownAttr, KErrAlreadyExists ); + iUnknownAttr = static_cast( + aResponse.Attribute( + CNATFWUNSAFAttribute::EUnknownAttributes ) ); + aResponse.DetachAttribute( iUnknownAttr ); + } + } + + __TEST_INVARIANT; + __STUNTURNCLIENT_INT1( "CSTUNTransaction::ProcessResponseL end, errorcode/status:", status ) + return status; + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::CheckIntegrityL +// MESSAGE-INTEGRITY is in the encoded message, not in iRequest. If iRequest has +// a USERNAME, then also a MESSAGE-INTEGRITY was sent in the Binding Request. +// ----------------------------------------------------------------------------- +// +TInt CSTUNTransaction::CheckIntegrityL( const CNATFWUNSAFMessage& aResponse, + const TDesC8& aByteStream ) + { + __TEST_INVARIANT; + __STUN_ASSERT_L( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse || + aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse || + aResponse.Type() == CNATFWUNSAFMessage::EConnectResponse || + aResponse.Type() == + CNATFWUNSAFMessage::ESetActiveDestinationResponse, + KErrArgument ); + + if ( !iRequest.Attribute( CNATFWUNSAFAttribute::EUsername ) ) + { + return KErrNone; + } + + if ( aResponse.HasAttribute( CNATFWUNSAFAttribute::EMessageIntegrity ) ) + { + if ( static_cast( + aResponse.Attribute( CNATFWUNSAFAttribute::EMessageIntegrity ) )-> + CheckMessageIntegrityL( aByteStream, iSharedSecret ) ) + { + return KErrNone; + } + + //If XOR-ONLY was already sent, maybe server doesn't support it. + if ( CheckForNatOverwriteL( aResponse ) && + !iRequest.Attribute( CNATFWUNSAFAttribute::EXorOnly ) ) + { + return ERetryAfterAddingXorOnly; + } + } + + return KErrCorrupt; + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::CheckForNatOverwriteL +// Be compatible with old STUN servers that don't understand XOR-MAPPED-ADDRESS +// or XOR-ONLY. Don't treat XOR-MAPPED-ADDRESS as mandatory in Binding Response. +// ----------------------------------------------------------------------------- +// +TBool CSTUNTransaction::CheckForNatOverwriteL( const CNATFWUNSAFMessage& aResponse ) + { + __TEST_INVARIANT; + __STUN_ASSERT_L( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse || + aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse, + KErrArgument ); + TInetAddr mappedAddr; + TInetAddr xorMappedAddr; + return STUNUtils::GetMappedAddress( aResponse, mappedAddr ) && + STUNUtils::GetXorMappedAddressL( aResponse, xorMappedAddr ) && + !mappedAddr.CmpAddr( xorMappedAddr ); + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::GetResponseCode +// ----------------------------------------------------------------------------- +// +TInt CSTUNTransaction:: + GetResponseCode( const CNATFWUNSAFMessage& aResponse ) const + { + __TEST_INVARIANT; + if ( aResponse.Type() == CNATFWUNSAFMessage::EBindingErrorResponse || + aResponse.Type() == CNATFWUNSAFMessage::EAllocateErrorResponse || + aResponse.Type() == CNATFWUNSAFMessage::EConnectErrorResponse || + aResponse.Type() == + CNATFWUNSAFMessage::ESetActiveDestinationErrorResponse ) + { + CNATFWUNSAFErrorCodeAttribute* errorCode = + static_cast + ( aResponse.Attribute( CNATFWUNSAFAttribute::EErrorCode ) ); + + if ( errorCode ) + { + return errorCode->ResponseCode(); + } + } + return KErrNotFound; + } + +// --------------------------------------------------------------------------- +// CSTUNTransaction::Terminate +// Don't use invariant at the end of Terminate nor elsewhere after calling it, +// as binding deletes this transaction. +// If PublicAddressObtainedL leaves, call TransactionError. +// --------------------------------------------------------------------------- +// +void CSTUNTransaction::Terminate( TInt aError ) + { + __STUNTURNCLIENT_INT1( "CSTUNTransaction::Terminate, error = ", aError ) + __TEST_INVARIANT; + + //Terminate only once + __STUN_ASSERT_RETURN( !iTerminated, KErrDied ); + NATFWUNSAF_INTLOG( "STUNTransaction terminated, reason:", aError ) + + iTerminated = ETrue; + + if ( aError == KErrNone ) + { + TInetAddr publicAddr = iXorMappedAddress; + if ( publicAddr.IsUnspecified() ) + { + publicAddr = iMappedAddress; + } + + if ( publicAddr.IsUnspecified() ) + { + if ( CNATFWUNSAFMessage::ESetActiveDestinationRequest == + iRequest.Type() ) + { + TRAP( aError, iObserver.TransactionEventOccurredL( + TSTUNCallbackInfo::EEventActiveDestinationSet ) ); + if ( aError ) + { + __STUNTURNCLIENT_INT1( + "TransactionEventOccurredL leaves, reason:", aError ) + } + } + else if ( CNATFWUNSAFMessage::EConnectRequest == iRequest.Type() ) + { + TRAP( aError, iObserver.TransactionEventOccurredL( + TSTUNCallbackInfo::EEventTCPConnectOk ) ); + if ( aError ) + { + __STUNTURNCLIENT_INT1( + "TransactionEventOccurredL leaves, reason:", aError ) + } + } + else + { + // Server sent invalid Binding Response + aError = KErrCorrupt; + } + } + else + { + if ( !StunRelayUsed() || iRelayAddress.IsUnspecified() ) + { + __STUNTURNCLIENT( "\ + CSTUNTransaction::Terminate StunRelay NOT Used." ) + TRAP( aError, iObserver.PublicAddressObtainedL( publicAddr ) ); + } + else + { + __STUNTURNCLIENT( "\ + CSTUNTransaction::Terminate StunRelay Used." ) + TRAP( aError, iObserver.PublicAddressObtainedL( + publicAddr, iRelayAddress ) ); + } + } + } + + if ( aError ) + { + CNATFWUNSAFUnknownAttributesAttribute* unknownAttr = iUnknownAttr; + iUnknownAttr = NULL; + iObserver.TransactionError( aError, unknownAttr ); + } + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::RetransmitInterval +// ----------------------------------------------------------------------------- +// +TInt CSTUNTransaction::RetransmitInterval() + { + __STUNTURNCLIENT( "CSTUNTransaction::RetransmitInterval" ) + __TEST_INVARIANT; + + if ( 0 == iRetransmitInterval ) + { + iRetransmitInterval = iInitialRetransmitInterval; + } + else if ( KMaxRequestSentCount == iSendCount ) + { + iRetransmitInterval = KWaitingTime; + } + else + { + iRetransmitInterval = iRetransmitInterval << 1; + } + + __TEST_INVARIANT; + return iRetransmitInterval; + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::ComputeWaitDuration +// ----------------------------------------------------------------------------- +// +TInt CSTUNTransaction::ComputeWaitDuration() + { + __STUNTURNCLIENT( "CSTUNTransaction::ComputeWaitDuration" ) + __TEST_INVARIANT; + + TInt duration( 0 ); + for ( TInt i = iSendCount; i < KMaxRequestSentCount; ++i ) + { + duration += RetransmitInterval(); + } + + __TEST_INVARIANT; + return duration; + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::TimerExpiredL +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::TimerExpiredL() + { + __STUNTURNCLIENT( "CSTUNTransaction::TimerExpiredL" ) + __TEST_INVARIANT; + + if ( iRetransmit && EUdpProtocol == iTransportProtocol ) + { + RetransmitRequestL(); + } + else + { + Terminate( KErrTimedOut ); + } + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::LeaveFromTimerExpired +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::LeaveFromTimerExpired( TInt aError ) + { + __STUNTURNCLIENT_INT1( "\ + CSTUNTransaction::LeaveFromTimerExpired, error = ", aError ) + __TEST_INVARIANT; + __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument ); + + Terminate( aError ); + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::TimerValue +// ----------------------------------------------------------------------------- +// +const TUint32& CSTUNTransaction::TimerValue() const + { + return iTimerValue; + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::CancelRetransmission +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::CancelRetransmission() + { + iDisableSending = ETrue; + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::CheckProtocolL +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::CheckProtocolL( const TDesC8& aProtocol ) + { + __STUNTURNCLIENT( "CSTUNTransaction::CheckProtocolL" ) + delete iProtocol; + iProtocol = NULL; + + if ( aProtocol.Compare( KStun ) ) + { + iProtocol = aProtocol.AllocL(); + } + else if ( aProtocol.Compare( KStunRelay ) ) + { + iProtocol = aProtocol.AllocL(); + } + else + { + User::Leave( KErrArgument ); + } + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::StunRelayUsed +// ----------------------------------------------------------------------------- +// +TBool CSTUNTransaction::StunRelayUsed() + { + __STUNTURNCLIENT( "CSTUNTransaction::StunRelayUsed()" ) + return !iProtocol->Compare( KStunRelay ); + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::MeasureNewRTTSample +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::MeasureNewRTTSample() + { + TTime curTime; + curTime.HomeTime(); + + //Measured RTT ( Round-trip time ) + TTimeIntervalMicroSeconds time = curTime.MicroSecondsFrom( iSendTime ); + // change microsecs to millisecs + TInt64 rttSample = time.Int64() / TInt64( KDivideFactor ); + + // rfc3489bis-06#section-7.1 + // As with TCP, the usage of Karn's + // algorithm is RECOMMENDED. When applied to STUN, it means that RTT + // estimates SHOULD NOT be computed from STUN transactions which result + // in the retransmission of a request. + + TBool retransmitted( EFalse ); + + if ( iRetransmitCompareValue < iSendCount ) + { + retransmitted = ETrue; + rttSample = iRetransmitInterval; + } + + iObserver.NewRTTSampleMeasured( rttSample, retransmitted ); + } + +// ----------------------------------------------------------------------------- +// CSTUNTransaction::__DbgTestInvariant +// ----------------------------------------------------------------------------- +// +void CSTUNTransaction::__DbgTestInvariant() const + { +#if defined( _DEBUG ) + if ( /*!iSender ||*/ + iAddress.IsUnspecified() || + iSendCount < 0 || + iSendCount > KMaxRequestSentCount || + iRetransmitInterval < 0 ) + { + __STUNTURNCLIENT( "CSTUNTransaction::__DbgTestInvariant()\ + stage#1 panic" ) + User::Invariant(); + } +#endif + }