natfw/natfwstunturnclient/src/cstuntransaction.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 #include "natfwunsaflog.h"
       
    22 #include "cnatfwunsafudpsender.h"
       
    23 #include "natfwunsafbindingrequest.h"
       
    24 #include "natfwunsaferrorcodeattribute.h"
       
    25 #include "natfwunsafunknownattributesattribute.h"
       
    26 #include "natfwunsafmessageintegrityattribute.h"
       
    27 #include "stunassert.h"
       
    28 #include "stunutils.h"
       
    29 #include "mstuntransactionobserver.h"
       
    30 #include "cstuntransaction.h"
       
    31 #include "ttransactioncleanup.h"
       
    32 #include "stunturnclientlogs.h"
       
    33 #include "tstuncallbackinfo.h"
       
    34 
       
    35 // ======== MEMBER FUNCTIONS ========
       
    36 
       
    37 const TInt KInitCompareValue = 1;
       
    38 
       
    39 // Divide factor from uSecs to mSecs
       
    40 const TInt KDivideFactor = 1000;
       
    41 
       
    42 const TInt KWaitingTime = 1600; // rfc3489bis-06#section-7.1
       
    43 
       
    44 const TInt KMaxTCPWaitingTime = 7900; // rfc3489bis-06#section-7.1
       
    45 
       
    46 // ---------------------------------------------------------------------------
       
    47 // CSTUNTransaction::NewL
       
    48 // ---------------------------------------------------------------------------
       
    49 //
       
    50 CSTUNTransaction* CSTUNTransaction::NewL( CNATFWUNSAFMessage& aRequest,
       
    51                                           const TInetAddr& aAddress,
       
    52                                           const TDesC8& aSharedSecret,
       
    53                                           RSocket& aSocket,
       
    54                                           CDeltaTimer& aTimer,
       
    55                                           TInt aRetransmitInterval,
       
    56                                           MSTUNTransactionObserver& aObserver,
       
    57                                           const TDesC8& aProtocol,
       
    58                                           TTransportProtocol aTransportProtocol )
       
    59     {
       
    60     __ASSERT_ALWAYS( !aAddress.IsUnspecified(), User::Leave( KErrArgument ) );
       
    61 
       
    62     CSTUNTransaction* self =
       
    63         new ( ELeave ) CSTUNTransaction( aRequest,
       
    64                                          aAddress,
       
    65                                          aSharedSecret,
       
    66                                          aTimer,
       
    67                                          aRetransmitInterval,
       
    68                                          aObserver,
       
    69                                          aTransportProtocol );
       
    70     CleanupStack::PushL( self );
       
    71     self->ConstructL( aSocket, aProtocol );
       
    72     CleanupStack::Pop( self );
       
    73     return self;
       
    74     }
       
    75 
       
    76 // ---------------------------------------------------------------------------
       
    77 // CSTUNTransaction::NewL - overloaded
       
    78 // ---------------------------------------------------------------------------
       
    79 //
       
    80 CSTUNTransaction* CSTUNTransaction::NewL( CNATFWUNSAFMessage& aRequest,
       
    81                                           const TInetAddr& aAddress,
       
    82                                           const TDesC8& aSharedSecret,
       
    83                                           TUint aStreamId,
       
    84                                           TUint aConnectionId,
       
    85                                           CDeltaTimer& aTimer,
       
    86                                           TInt aRetransmitInterval,
       
    87                                           MSTUNTransactionObserver& aObserver,
       
    88                                           const TDesC8& aProtocol,
       
    89                                           MNcmConnectionMultiplexer& aMux,
       
    90                                           TTransportProtocol aTransportProtocol,
       
    91                                           TBool aUseFingerprint,
       
    92                                           const TInetAddr& aDestAddr )
       
    93     {
       
    94     __ASSERT_ALWAYS( !aAddress.IsUnspecified(), User::Leave( KErrArgument ) );
       
    95 
       
    96     CSTUNTransaction* self =
       
    97         new ( ELeave ) CSTUNTransaction( aRequest,
       
    98                                          aAddress,
       
    99                                          aSharedSecret,
       
   100                                          aStreamId,
       
   101                                          aConnectionId,
       
   102                                          aTimer,
       
   103                                          aRetransmitInterval,
       
   104                                          aObserver,
       
   105                                          aDestAddr,
       
   106                                          aTransportProtocol,
       
   107                                          aUseFingerprint );
       
   108     CleanupStack::PushL( self );
       
   109     self->ConstructL( aProtocol, aMux );
       
   110     CleanupStack::Pop( self );
       
   111     return self;
       
   112     }
       
   113 
       
   114 // ---------------------------------------------------------------------------
       
   115 // CSTUNTransaction::CSTUNTransaction
       
   116 // ---------------------------------------------------------------------------
       
   117 //
       
   118 CSTUNTransaction::CSTUNTransaction( CNATFWUNSAFMessage& aRequest,
       
   119                                     const TInetAddr& aAddress,
       
   120                                     const TDesC8& aSharedSecret,
       
   121                                     CDeltaTimer& aTimer,
       
   122                                     TInt aRetransmitInterval,
       
   123                                     MSTUNTransactionObserver& aObserver,
       
   124                                     TTransportProtocol aTransportProtocol ) :
       
   125     CSTUNTimerUser( aTimer ),
       
   126     iObserver( aObserver ),
       
   127     iRequest( aRequest ),
       
   128     iAddress( aAddress ),
       
   129     iSharedSecret( aSharedSecret ),
       
   130     iInitialRetransmitInterval( aRetransmitInterval ),
       
   131     iRetransmit( ETrue ),
       
   132     iTransportProtocol( aTransportProtocol ),
       
   133     iRetransmitCompareValue( KInitCompareValue )
       
   134     {
       
   135     }
       
   136 
       
   137 // ---------------------------------------------------------------------------
       
   138 // CSTUNTransaction::CSTUNTransaction - overloaded
       
   139 // ---------------------------------------------------------------------------
       
   140 //
       
   141 CSTUNTransaction::CSTUNTransaction( CNATFWUNSAFMessage& aRequest,
       
   142                                     const TInetAddr& aAddress,
       
   143                                     const TDesC8& aSharedSecret,
       
   144                                     TUint aStreamId,
       
   145                                     TUint aConnectionId,
       
   146                                     CDeltaTimer& aTimer,
       
   147                                     TInt aRetransmitInterval,
       
   148                                     MSTUNTransactionObserver& aObserver,
       
   149                                     const TInetAddr& aDestAddr,
       
   150                                     TTransportProtocol aTransportProtocol,
       
   151                                     TBool aUseFingerprint ) :
       
   152     CSTUNTimerUser( aTimer ),
       
   153     iObserver( aObserver ),
       
   154     iRequest( aRequest ),
       
   155     iAddress( aAddress ),
       
   156     iSharedSecret( aSharedSecret ),
       
   157     iInitialRetransmitInterval( aRetransmitInterval ),
       
   158     iRetransmit( ETrue ),
       
   159     iStreamId( aStreamId ),
       
   160     iSubstreamId( aConnectionId ),
       
   161     iDestAddr( aDestAddr ),
       
   162     iTransportProtocol( aTransportProtocol ),
       
   163     iRetransmitCompareValue( KInitCompareValue ),
       
   164     iUseFingerprint( aUseFingerprint )
       
   165     {
       
   166     }
       
   167 
       
   168 // ---------------------------------------------------------------------------
       
   169 // CSTUNTransaction::CSTUNTransaction
       
   170 // Dummy implementation. Default constructor is declared private and not used.
       
   171 // ---------------------------------------------------------------------------
       
   172 //
       
   173 CSTUNTransaction::CSTUNTransaction() :
       
   174     CSTUNTimerUser( *( CDeltaTimer* )0x1 ),
       
   175     iObserver( *( MSTUNTransactionObserver* )0x1 ),
       
   176     iRequest( *( CNATFWUNSAFMessage* )0x1 ),
       
   177     iAddress( *( TInetAddr* )0x1 ),
       
   178     iSharedSecret( KNullDesC8 )
       
   179     {
       
   180     }
       
   181 
       
   182 // ---------------------------------------------------------------------------
       
   183 // CSTUNTransaction::CSTUNTransaction
       
   184 // Dummy implementation, as copy constructor is declared private and not used.
       
   185 // ---------------------------------------------------------------------------
       
   186 //
       
   187 CSTUNTransaction::CSTUNTransaction( const CSTUNTransaction& aTransaction ) :
       
   188     CSTUNTimerUser( *( CDeltaTimer* )0x1 ),
       
   189     iObserver( aTransaction.iObserver ),
       
   190     iRequest( aTransaction.iRequest ),
       
   191     iAddress( aTransaction.iAddress ),
       
   192     iSharedSecret( aTransaction.iSharedSecret )
       
   193     {
       
   194     }
       
   195 
       
   196 // ---------------------------------------------------------------------------
       
   197 // CSTUNTransaction::ConstructL
       
   198 // ---------------------------------------------------------------------------
       
   199 //
       
   200 void CSTUNTransaction::ConstructL( RSocket& aSocket, const TDesC8& aProtocol )
       
   201     {
       
   202     __STUNTURNCLIENT( "CSTUNTransaction::ConstructL with sender" )
       
   203     CheckProtocolL( aProtocol );
       
   204     iSender = CNATFWUNSAFUdpSender::NewL( aSocket, *this );
       
   205     SendRequestL();
       
   206     }
       
   207 
       
   208 // ---------------------------------------------------------------------------
       
   209 // CSTUNTransaction::ConstructL
       
   210 // ---------------------------------------------------------------------------
       
   211 //
       
   212 void CSTUNTransaction::ConstructL( const TDesC8& aProtocol, 
       
   213     MNcmConnectionMultiplexer& aMux  )
       
   214     {
       
   215     __STUNTURNCLIENT( "CSTUNTransaction::ConstructL with mediaconsender" )
       
   216     CheckProtocolL( aProtocol );
       
   217     iMediaConSender = CNATFWUNSAFMediaConnSender::NewL( aMux );
       
   218     SendRequestL();
       
   219     }
       
   220       
       
   221 // ---------------------------------------------------------------------------
       
   222 // CSTUNTransaction::~CSTUNTransaction
       
   223 // ---------------------------------------------------------------------------
       
   224 //
       
   225 CSTUNTransaction::~CSTUNTransaction()
       
   226     {
       
   227     __STUNTURNCLIENT( "CSTUNTransaction::~CSTUNTransaction IN" )
       
   228     
       
   229     if ( iMediaConSender )
       
   230         {
       
   231         iMediaConSender->Cancel( iStreamId, iSubstreamId, this );
       
   232         }
       
   233     
       
   234     delete iMediaConSender;
       
   235     delete iSender;
       
   236     delete iUnknownAttr;
       
   237     delete iProtocol;
       
   238     
       
   239     __STUNTURNCLIENT( "CSTUNTransaction::~CSTUNTransaction OUT" )
       
   240     }
       
   241 
       
   242 // ---------------------------------------------------------------------------
       
   243 // CSTUNTransaction::NATFWUNSAFUdpMessageSentL
       
   244 // ---------------------------------------------------------------------------
       
   245 //
       
   246 void CSTUNTransaction::UNSAFUdpMessageSentL()
       
   247     {
       
   248     __STUNTURNCLIENT( "CSTUNTransaction::UNSAFUdpMessageSentL" )
       
   249     __TEST_INVARIANT;
       
   250     
       
   251     if ( !iTerminated )
       
   252         {
       
   253         ++iSendCount;
       
   254         
       
   255         if ( iRetransmit )
       
   256             {
       
   257             if ( ETcpProtocol == iTransportProtocol )
       
   258                 {
       
   259                 StartTimer( KMaxTCPWaitingTime );
       
   260                 }
       
   261             else
       
   262                 {                       
       
   263                 iSendTime.HomeTime();
       
   264                 StartTimer( RetransmitInterval() );
       
   265                 }
       
   266             }
       
   267         }
       
   268 
       
   269     __TEST_INVARIANT;
       
   270     }
       
   271 
       
   272 // ---------------------------------------------------------------------------
       
   273 // CSTUNTransaction::NATFWUNSAFUdpMessageFailure
       
   274 // ---------------------------------------------------------------------------
       
   275 //
       
   276 void CSTUNTransaction::UNSAFUdpMessageFailure( TInt aError )
       
   277     {
       
   278     __STUNTURNCLIENT_INT1( "\
       
   279     CSTUNTransaction::UNSAFUdpMessageFailure, error=", aError )
       
   280     __TEST_INVARIANT;
       
   281     __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument );
       
   282 
       
   283     if ( !iTerminated )
       
   284         {
       
   285         Terminate( aError );
       
   286         }
       
   287     }
       
   288 
       
   289 // ---------------------------------------------------------------------------
       
   290 // CSTUNTransaction::MessageSent
       
   291 // ---------------------------------------------------------------------------
       
   292 //
       
   293 void CSTUNTransaction::MessageSent()
       
   294     {
       
   295     iRequestPending = EFalse;
       
   296     
       
   297     TRAP_IGNORE( UNSAFUdpMessageSentL() );
       
   298     }
       
   299 
       
   300 // ---------------------------------------------------------------------------
       
   301 // CSTUNTransaction::MessageSentFailure
       
   302 // ---------------------------------------------------------------------------
       
   303 // 
       
   304 void CSTUNTransaction::MessageSentFailure( TInt aError )
       
   305     {
       
   306     __STUNTURNCLIENT_INT1( "\
       
   307     CSTUNTransaction::MessageSentFailure, error=", aError )
       
   308     iRequestPending = EFalse;
       
   309     UNSAFUdpMessageFailure( aError );
       
   310     }
       
   311 
       
   312 // -----------------------------------------------------------------------------
       
   313 // CSTUNTransaction::SendRequestL
       
   314 // -----------------------------------------------------------------------------
       
   315 //
       
   316 void CSTUNTransaction::SendRequestL()
       
   317     {
       
   318     __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL" )
       
   319     if ( iMediaConSender )
       
   320         {
       
   321         __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL with mediaconsender" )
       
   322         if ( iDestAddr.IsUnspecified() )
       
   323             {
       
   324             iMediaConSender->SendL( iStreamId, 
       
   325                 iSubstreamId, iRequest, iSharedSecret, this, iUseFingerprint );
       
   326             iRequestPending = ETrue;
       
   327             }
       
   328         else
       
   329             {
       
   330             iMediaConSender->SendL( iStreamId, 
       
   331                                     iSubstreamId, iRequest, iSharedSecret, 
       
   332                                     iDestAddr, this, iUseFingerprint );
       
   333             
       
   334             iRequestPending = ETrue;
       
   335             }
       
   336         }
       
   337     else if ( iSender )
       
   338         {
       
   339         __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL with original sender" )
       
   340         iSender->SendL( iAddress, iRequest, iSharedSecret );
       
   341         }
       
   342     else
       
   343         {
       
   344         User::Leave( KErrNotReady );
       
   345         }
       
   346     }
       
   347 
       
   348 // -----------------------------------------------------------------------------
       
   349 // CSTUNTransaction::RetransmitRequestL
       
   350 // -----------------------------------------------------------------------------
       
   351 //
       
   352 void CSTUNTransaction::RetransmitRequestL()
       
   353     {
       
   354     __STUNTURNCLIENT_INT1( "\
       
   355     CSTUNTransaction::RetransmitRequestL, sendcount= ",iSendCount )
       
   356     if ( iSendCount < KMaxRequestSentCount )
       
   357         {
       
   358         if ( !iDisableSending )
       
   359             {
       
   360             SendRequestL();
       
   361             }
       
   362         else
       
   363             {
       
   364             iSendTime.HomeTime();
       
   365             StartTimer( RetransmitInterval() );
       
   366             }
       
   367         }
       
   368     else
       
   369         {
       
   370         Terminate( KErrTimedOut );
       
   371         }
       
   372     }
       
   373 
       
   374 // ---------------------------------------------------------------------------
       
   375 // CSTUNTransaction::ReceiveL
       
   376 // Also an ignored response stops retransmission.
       
   377 // ---------------------------------------------------------------------------
       
   378 //
       
   379 void CSTUNTransaction::ReceiveL( CNATFWUNSAFMessage& aResponse,
       
   380                                  const TDesC8& aByteStream )
       
   381     {
       
   382     __TEST_INVARIANT;
       
   383     __STUN_ASSERT_L( 
       
   384         aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse ||
       
   385         aResponse.Type() == CNATFWUNSAFMessage::EBindingErrorResponse ||
       
   386         aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse ||
       
   387         aResponse.Type() == CNATFWUNSAFMessage::EAllocateErrorResponse ||
       
   388         aResponse.Type() == CNATFWUNSAFMessage::EConnectResponse ||
       
   389         aResponse.Type() == CNATFWUNSAFMessage::EConnectErrorResponse ||
       
   390         aResponse.Type() ==
       
   391             CNATFWUNSAFMessage::ESetActiveDestinationResponse ||
       
   392         aResponse.Type() ==
       
   393             CNATFWUNSAFMessage::ESetActiveDestinationErrorResponse,
       
   394         KErrArgument );
       
   395     
       
   396     if ( !iTerminated )
       
   397         {
       
   398         iRetransmit = EFalse;
       
   399         StopTimer();
       
   400         
       
   401         if ( ShouldIgnoreResponse( aResponse ) )
       
   402             {
       
   403             StartTimer( ComputeWaitDuration() );
       
   404             }
       
   405         else
       
   406             {
       
   407             if ( EUdpProtocol == iTransportProtocol )
       
   408                 {
       
   409                 MeasureNewRTTSample();
       
   410                 }
       
   411             
       
   412             TTransactionCleanup taCleanup( *this );
       
   413             CleanupStack::PushL( taCleanup.CleanupItem() );
       
   414 
       
   415             TInt status = ProcessResponseL( aResponse, aByteStream );
       
   416 
       
   417             CleanupStack::Pop(); //cleanupItem
       
   418             Terminate( status );
       
   419             }
       
   420         }
       
   421     }
       
   422 
       
   423 // -----------------------------------------------------------------------------
       
   424 // CSTUNTransaction::ShouldIgnoreResponse
       
   425 // 1xx-3xx response stops retransmissions, but doesn't terminate transaction.
       
   426 // -----------------------------------------------------------------------------
       
   427 //
       
   428 TBool
       
   429 CSTUNTransaction::ShouldIgnoreResponse( const CNATFWUNSAFMessage& aResponse ) const
       
   430     {
       
   431     __TEST_INVARIANT;
       
   432 
       
   433     TInt responseCode = GetResponseCode( aResponse );
       
   434     return !aResponse.Validate() ||
       
   435            aResponse.HasUnknownMandatoryAttributes() ||
       
   436            ( responseCode >= E1XX && responseCode < E4XX );
       
   437     }
       
   438 
       
   439 // -----------------------------------------------------------------------------
       
   440 // CSTUNTransaction::ProcessResponseL
       
   441 // -----------------------------------------------------------------------------
       
   442 //
       
   443 TInt CSTUNTransaction::ProcessResponseL( CNATFWUNSAFMessage& aResponse,
       
   444                                          const TDesC8& aByteStream )
       
   445     {
       
   446     __STUNTURNCLIENT( "CSTUNTransaction::ProcessResponseL" )
       
   447     __TEST_INVARIANT;
       
   448                      
       
   449     TInt status = KErrNone;
       
   450     
       
   451     // binding response ( stun functionality )
       
   452     if ( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse )
       
   453         {
       
   454         status = CheckIntegrityL( aResponse, aByteStream );
       
   455         if ( KErrNone == status )
       
   456             {
       
   457             STUNUtils::GetMappedAddress( aResponse, iMappedAddress );
       
   458             STUNUtils::GetXorMappedAddressL( aResponse, iXorMappedAddress );
       
   459             }
       
   460         }
       
   461     
       
   462     // allocate response ( stun relay functionality )
       
   463     else if ( aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse )
       
   464         {
       
   465         status = CheckIntegrityL( aResponse, aByteStream );
       
   466         if ( KErrNone == status )
       
   467             {
       
   468             // get server relay address
       
   469             STUNUtils::GetRelayAddressL( aResponse, iRelayAddress );
       
   470             // get server reflexive address
       
   471             STUNUtils::GetXorMappedAddressL( aResponse, iXorMappedAddress );
       
   472             }
       
   473         }
       
   474     
       
   475     // Connect Response ( stun relay TCP functionality )
       
   476     else if ( aResponse.Type() == 
       
   477         CNATFWUNSAFMessage::EConnectResponse )
       
   478         {
       
   479         status = CheckIntegrityL( aResponse, aByteStream );
       
   480         }
       
   481     
       
   482     // Active Destination Response ( stun relay functionality )
       
   483     else if ( aResponse.Type() == 
       
   484         CNATFWUNSAFMessage::ESetActiveDestinationResponse )
       
   485         {
       
   486         __STUNTURNCLIENT( "do msg integrity check for active destination response" )
       
   487         status = CheckIntegrityL( aResponse, aByteStream );
       
   488         if ( KErrNone != status )
       
   489             {
       
   490             __STUNTURNCLIENT_INT1( "msg integrity check for active\
       
   491             destination response FAILED - BUT IGNORE IT - SERVER MISBEHAVIOR DETECTED", status )
       
   492             status = KErrNone; 
       
   493             }
       
   494             
       
   495         if ( KErrNone == status )
       
   496             {
       
   497             // notify stun relay implementation
       
   498             STUNUtils::GetTimerValueL( aResponse, iTimerValue );
       
   499             }
       
   500         }
       
   501         
       
   502     else
       
   503         {
       
   504         status = GetResponseCode( aResponse );
       
   505         if ( E4XX > status )
       
   506             {
       
   507             //Invalid Binding Error Response received
       
   508             status = KErrCorrupt;
       
   509             }            
       
   510         if ( status == E420UnknownAttributes )
       
   511             {
       
   512             __STUN_ASSERT_L( !iUnknownAttr, KErrAlreadyExists );
       
   513             iUnknownAttr = static_cast<CNATFWUNSAFUnknownAttributesAttribute*>(
       
   514                 aResponse.Attribute(
       
   515                     CNATFWUNSAFAttribute::EUnknownAttributes ) );
       
   516             aResponse.DetachAttribute( iUnknownAttr );
       
   517             }
       
   518         }
       
   519 
       
   520     __TEST_INVARIANT;
       
   521     __STUNTURNCLIENT_INT1( "CSTUNTransaction::ProcessResponseL end, errorcode/status:", status )
       
   522     return status;
       
   523     }
       
   524 
       
   525 // -----------------------------------------------------------------------------
       
   526 // CSTUNTransaction::CheckIntegrityL
       
   527 // MESSAGE-INTEGRITY is in the encoded message, not in iRequest. If iRequest has
       
   528 // a USERNAME, then also a MESSAGE-INTEGRITY was sent in the Binding Request.
       
   529 // -----------------------------------------------------------------------------
       
   530 //
       
   531 TInt CSTUNTransaction::CheckIntegrityL( const CNATFWUNSAFMessage& aResponse,
       
   532                                          const TDesC8& aByteStream )
       
   533     {
       
   534     __TEST_INVARIANT;
       
   535     __STUN_ASSERT_L( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse ||
       
   536                      aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse ||
       
   537                      aResponse.Type() == CNATFWUNSAFMessage::EConnectResponse ||
       
   538                      aResponse.Type() == 
       
   539                         CNATFWUNSAFMessage::ESetActiveDestinationResponse,
       
   540                      KErrArgument );
       
   541 
       
   542     if ( !iRequest.Attribute( CNATFWUNSAFAttribute::EUsername ) )
       
   543         {
       
   544         return KErrNone;
       
   545         }
       
   546 
       
   547     if ( aResponse.HasAttribute( CNATFWUNSAFAttribute::EMessageIntegrity ) )
       
   548         {
       
   549         if ( static_cast<CNATFWUNSAFMessageIntegrityAttribute*>(
       
   550                 aResponse.Attribute( CNATFWUNSAFAttribute::EMessageIntegrity ) )->
       
   551                     CheckMessageIntegrityL( aByteStream, iSharedSecret ) )
       
   552             {
       
   553             return KErrNone;
       
   554             }
       
   555 
       
   556         //If XOR-ONLY was already sent, maybe server doesn't support it.
       
   557         if ( CheckForNatOverwriteL( aResponse ) &&
       
   558              !iRequest.Attribute( CNATFWUNSAFAttribute::EXorOnly ) )
       
   559             {
       
   560             return ERetryAfterAddingXorOnly;
       
   561             }
       
   562         }
       
   563 
       
   564     return KErrCorrupt;
       
   565     }
       
   566 
       
   567 // -----------------------------------------------------------------------------
       
   568 // CSTUNTransaction::CheckForNatOverwriteL
       
   569 // Be compatible with old STUN servers that don't understand XOR-MAPPED-ADDRESS
       
   570 // or XOR-ONLY. Don't treat XOR-MAPPED-ADDRESS as mandatory in Binding Response.
       
   571 // -----------------------------------------------------------------------------
       
   572 //
       
   573 TBool CSTUNTransaction::CheckForNatOverwriteL( const CNATFWUNSAFMessage& aResponse )
       
   574     {
       
   575     __TEST_INVARIANT;    
       
   576     __STUN_ASSERT_L( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse ||
       
   577                      aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse,
       
   578                      KErrArgument );
       
   579     TInetAddr mappedAddr;
       
   580     TInetAddr xorMappedAddr;
       
   581     return STUNUtils::GetMappedAddress( aResponse, mappedAddr ) &&
       
   582            STUNUtils::GetXorMappedAddressL( aResponse, xorMappedAddr ) &&
       
   583            !mappedAddr.CmpAddr( xorMappedAddr );
       
   584     }
       
   585 
       
   586 // -----------------------------------------------------------------------------
       
   587 // CSTUNTransaction::GetResponseCode
       
   588 // -----------------------------------------------------------------------------
       
   589 //
       
   590 TInt CSTUNTransaction::
       
   591     GetResponseCode( const CNATFWUNSAFMessage& aResponse ) const
       
   592     {
       
   593     __TEST_INVARIANT;
       
   594     if ( aResponse.Type() == CNATFWUNSAFMessage::EBindingErrorResponse ||
       
   595          aResponse.Type() == CNATFWUNSAFMessage::EAllocateErrorResponse ||
       
   596          aResponse.Type() == CNATFWUNSAFMessage::EConnectErrorResponse ||
       
   597          aResponse.Type() == 
       
   598                 CNATFWUNSAFMessage::ESetActiveDestinationErrorResponse )
       
   599         {
       
   600         CNATFWUNSAFErrorCodeAttribute* errorCode =
       
   601             static_cast<CNATFWUNSAFErrorCodeAttribute*>
       
   602             ( aResponse.Attribute( CNATFWUNSAFAttribute::EErrorCode ) );
       
   603         
       
   604         if ( errorCode )
       
   605             {
       
   606             return errorCode->ResponseCode();
       
   607             }
       
   608         }
       
   609     return KErrNotFound;
       
   610     }
       
   611 
       
   612 // ---------------------------------------------------------------------------
       
   613 // CSTUNTransaction::Terminate
       
   614 // Don't use invariant at the end of Terminate nor elsewhere after calling it,
       
   615 // as binding deletes this transaction.
       
   616 // If PublicAddressObtainedL leaves, call TransactionError.
       
   617 // ---------------------------------------------------------------------------
       
   618 //
       
   619 void CSTUNTransaction::Terminate( TInt aError )
       
   620     {
       
   621     __STUNTURNCLIENT_INT1( "CSTUNTransaction::Terminate, error = ", aError )
       
   622     __TEST_INVARIANT;
       
   623     
       
   624     //Terminate only once
       
   625     __STUN_ASSERT_RETURN( !iTerminated, KErrDied );
       
   626     NATFWUNSAF_INTLOG( "STUNTransaction terminated, reason:", aError )
       
   627 
       
   628     iTerminated = ETrue;
       
   629 
       
   630     if ( aError == KErrNone )
       
   631         {
       
   632         TInetAddr publicAddr = iXorMappedAddress;
       
   633         if ( publicAddr.IsUnspecified() )
       
   634             {
       
   635             publicAddr = iMappedAddress;
       
   636             }
       
   637         
       
   638         if ( publicAddr.IsUnspecified() )
       
   639             {
       
   640             if ( CNATFWUNSAFMessage::ESetActiveDestinationRequest ==
       
   641                         iRequest.Type() )
       
   642                 {
       
   643                 TRAP( aError, iObserver.TransactionEventOccurredL( 
       
   644                     TSTUNCallbackInfo::EEventActiveDestinationSet ) );
       
   645                 if ( aError )
       
   646                     {
       
   647                     __STUNTURNCLIENT_INT1(
       
   648                         "TransactionEventOccurredL leaves, reason:", aError )
       
   649                     }
       
   650                 }
       
   651             else if ( CNATFWUNSAFMessage::EConnectRequest == iRequest.Type() )
       
   652                 {
       
   653                 TRAP( aError, iObserver.TransactionEventOccurredL( 
       
   654                     TSTUNCallbackInfo::EEventTCPConnectOk ) );
       
   655                 if ( aError )
       
   656                     {
       
   657                     __STUNTURNCLIENT_INT1(
       
   658                         "TransactionEventOccurredL leaves, reason:", aError )
       
   659                     }
       
   660                 }
       
   661             else
       
   662                 {
       
   663                 // Server sent invalid Binding Response
       
   664                 aError = KErrCorrupt;
       
   665                 }
       
   666             }
       
   667         else
       
   668             {
       
   669             if ( !StunRelayUsed() || iRelayAddress.IsUnspecified() )
       
   670                 {
       
   671                 __STUNTURNCLIENT( "\
       
   672                 CSTUNTransaction::Terminate StunRelay NOT Used." )
       
   673                 TRAP( aError, iObserver.PublicAddressObtainedL( publicAddr ) );
       
   674                 }
       
   675             else
       
   676                 {
       
   677                 __STUNTURNCLIENT( "\
       
   678                 CSTUNTransaction::Terminate StunRelay Used." )
       
   679                 TRAP( aError, iObserver.PublicAddressObtainedL( 
       
   680                     publicAddr, iRelayAddress ) );
       
   681                 }
       
   682             }
       
   683         }
       
   684         
       
   685     if ( aError )
       
   686         {
       
   687         CNATFWUNSAFUnknownAttributesAttribute* unknownAttr = iUnknownAttr;
       
   688         iUnknownAttr = NULL;
       
   689         iObserver.TransactionError( aError, unknownAttr );
       
   690         }
       
   691     }
       
   692 
       
   693 // -----------------------------------------------------------------------------
       
   694 // CSTUNTransaction::RetransmitInterval
       
   695 // -----------------------------------------------------------------------------
       
   696 //
       
   697 TInt CSTUNTransaction::RetransmitInterval()
       
   698     {
       
   699     __STUNTURNCLIENT( "CSTUNTransaction::RetransmitInterval" )
       
   700     __TEST_INVARIANT;
       
   701     
       
   702     if ( 0 == iRetransmitInterval )
       
   703         {
       
   704         iRetransmitInterval = iInitialRetransmitInterval;
       
   705         }
       
   706     else if ( KMaxRequestSentCount == iSendCount )
       
   707         {
       
   708         iRetransmitInterval = KWaitingTime;
       
   709         }
       
   710     else
       
   711         {
       
   712         iRetransmitInterval = iRetransmitInterval << 1;
       
   713         }
       
   714 
       
   715     __TEST_INVARIANT;
       
   716     return iRetransmitInterval;
       
   717     }
       
   718 
       
   719 // -----------------------------------------------------------------------------
       
   720 // CSTUNTransaction::ComputeWaitDuration
       
   721 // -----------------------------------------------------------------------------
       
   722 //
       
   723 TInt CSTUNTransaction::ComputeWaitDuration()
       
   724     {
       
   725     __STUNTURNCLIENT( "CSTUNTransaction::ComputeWaitDuration" )
       
   726     __TEST_INVARIANT;
       
   727 
       
   728     TInt duration( 0 );
       
   729     for ( TInt i = iSendCount; i < KMaxRequestSentCount; ++i )
       
   730         {
       
   731         duration += RetransmitInterval();
       
   732         }
       
   733 
       
   734     __TEST_INVARIANT;
       
   735     return duration;
       
   736     }
       
   737 
       
   738 // -----------------------------------------------------------------------------
       
   739 // CSTUNTransaction::TimerExpiredL
       
   740 // -----------------------------------------------------------------------------
       
   741 //
       
   742 void CSTUNTransaction::TimerExpiredL()
       
   743     {
       
   744     __STUNTURNCLIENT( "CSTUNTransaction::TimerExpiredL" )
       
   745     __TEST_INVARIANT;
       
   746 
       
   747     if ( iRetransmit && EUdpProtocol == iTransportProtocol )
       
   748         {
       
   749         RetransmitRequestL();
       
   750         }
       
   751     else
       
   752         {
       
   753         Terminate( KErrTimedOut );
       
   754         }
       
   755     }
       
   756 
       
   757 // -----------------------------------------------------------------------------
       
   758 // CSTUNTransaction::LeaveFromTimerExpired
       
   759 // -----------------------------------------------------------------------------
       
   760 //
       
   761 void CSTUNTransaction::LeaveFromTimerExpired( TInt aError )
       
   762     {
       
   763     __STUNTURNCLIENT_INT1( "\
       
   764     CSTUNTransaction::LeaveFromTimerExpired, error = ", aError )
       
   765     __TEST_INVARIANT;
       
   766     __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument );
       
   767 
       
   768     Terminate( aError );
       
   769     }
       
   770 
       
   771 // -----------------------------------------------------------------------------
       
   772 // CSTUNTransaction::TimerValue
       
   773 // -----------------------------------------------------------------------------
       
   774 //
       
   775 const TUint32& CSTUNTransaction::TimerValue() const
       
   776     {
       
   777     return iTimerValue;
       
   778     }
       
   779 
       
   780 // -----------------------------------------------------------------------------
       
   781 // CSTUNTransaction::CancelRetransmission
       
   782 // -----------------------------------------------------------------------------
       
   783 //
       
   784 void CSTUNTransaction::CancelRetransmission()
       
   785     {
       
   786     iDisableSending = ETrue;
       
   787     }
       
   788 
       
   789 // -----------------------------------------------------------------------------
       
   790 // CSTUNTransaction::CheckProtocolL
       
   791 // -----------------------------------------------------------------------------
       
   792 //
       
   793 void CSTUNTransaction::CheckProtocolL( const TDesC8& aProtocol )
       
   794     {
       
   795     __STUNTURNCLIENT( "CSTUNTransaction::CheckProtocolL" )
       
   796     delete iProtocol;
       
   797     iProtocol = NULL;
       
   798     
       
   799     if ( aProtocol.Compare( KStun ) )
       
   800         {
       
   801         iProtocol = aProtocol.AllocL();
       
   802         }
       
   803     else if ( aProtocol.Compare( KStunRelay ) )
       
   804         {
       
   805         iProtocol = aProtocol.AllocL();
       
   806         }
       
   807     else
       
   808         {
       
   809         User::Leave( KErrArgument );
       
   810         }
       
   811     }
       
   812     
       
   813 // -----------------------------------------------------------------------------
       
   814 // CSTUNTransaction::StunRelayUsed
       
   815 // -----------------------------------------------------------------------------
       
   816 //
       
   817 TBool CSTUNTransaction::StunRelayUsed()
       
   818     {
       
   819     __STUNTURNCLIENT( "CSTUNTransaction::StunRelayUsed()" )
       
   820     return !iProtocol->Compare( KStunRelay );
       
   821     }
       
   822 
       
   823 // -----------------------------------------------------------------------------
       
   824 // CSTUNTransaction::MeasureNewRTTSample
       
   825 // -----------------------------------------------------------------------------
       
   826 //
       
   827 void CSTUNTransaction::MeasureNewRTTSample()
       
   828     {
       
   829     TTime curTime;
       
   830     curTime.HomeTime();
       
   831     
       
   832     //Measured RTT ( Round-trip time )
       
   833     TTimeIntervalMicroSeconds time = curTime.MicroSecondsFrom( iSendTime );
       
   834     // change microsecs to millisecs
       
   835     TInt64 rttSample = time.Int64() / TInt64( KDivideFactor );
       
   836     
       
   837     // rfc3489bis-06#section-7.1
       
   838     // As with TCP, the usage of Karn's
       
   839     // algorithm is RECOMMENDED.  When applied to STUN, it means that RTT
       
   840     // estimates SHOULD NOT be computed from STUN transactions which result
       
   841     // in the retransmission of a request.
       
   842 
       
   843     TBool retransmitted( EFalse );
       
   844     
       
   845     if ( iRetransmitCompareValue < iSendCount )
       
   846         {
       
   847         retransmitted = ETrue;
       
   848         rttSample = iRetransmitInterval;
       
   849         }
       
   850         
       
   851     iObserver.NewRTTSampleMeasured( rttSample, retransmitted );
       
   852     }
       
   853 
       
   854 // -----------------------------------------------------------------------------
       
   855 // CSTUNTransaction::__DbgTestInvariant
       
   856 // -----------------------------------------------------------------------------
       
   857 // 
       
   858 void CSTUNTransaction::__DbgTestInvariant() const
       
   859     {
       
   860 #if defined( _DEBUG )
       
   861     if ( /*!iSender ||*/
       
   862          iAddress.IsUnspecified() ||
       
   863          iSendCount < 0 ||
       
   864          iSendCount > KMaxRequestSentCount ||         
       
   865          iRetransmitInterval < 0 )
       
   866         {
       
   867         __STUNTURNCLIENT( "CSTUNTransaction::__DbgTestInvariant()\
       
   868         stage#1 panic" )
       
   869         User::Invariant();
       
   870         }
       
   871 #endif
       
   872     }