natfw/natfwstunturnclient/src/cstunbindingimplementation.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 // INCLUDES
       
    22 #include "stunassert.h"
       
    23 #include "natfwunsaflog.h"
       
    24 #include "natfwunsafmessagefactory.h"
       
    25 #include "natfwunsafbindingrequest.h"
       
    26 #include "natfwunsafbindingindication.h"
       
    27 #include "cstunbindingimplementation.h"
       
    28 #include "natfwstunbinding.h"
       
    29 #include "cstunbindinginit.h"
       
    30 #include "cstunbindinggetsharedsecret.h"
       
    31 #include "cstunbindinggetaddress.h"
       
    32 #include "cstunbindingactive.h"
       
    33 #include "cstunbindingwaittoretry.h"
       
    34 #include "mstunbindingobserver.h"
       
    35 #include "cstuntransaction.h"
       
    36 #include "stunutils.h"
       
    37 #include "natfwstunclientdefs.h"
       
    38 #include "cstunindicationtransmitter.h"
       
    39 
       
    40 // Attribures
       
    41 #include "natfwunsafusernameattribute.h"
       
    42 #include "natfwunsafxoronlyattribute.h"
       
    43 #include "natfwunsafunknownattributesattribute.h"
       
    44 #include "natfwunsafusecandidateattribute.h"
       
    45 #include "natfwunsafpriorityattribute.h"
       
    46 #include "natfwunsafdataattribute.h"
       
    47 #include "natfwunsafremoteaddressattribute.h"
       
    48 #include "natfwunsaficecontrollingattribute.h"
       
    49 #include "natfwunsaficecontrolledattribute.h"
       
    50 #include "natfwunsafalternateserverattribute.h"
       
    51 #include "natfwunsafrealmattribute.h"
       
    52 #include "natfwunsafnonceattribute.h"
       
    53 
       
    54 
       
    55 
       
    56 // ======== MEMBER FUNCTIONS ========
       
    57 
       
    58 // ---------------------------------------------------------------------------
       
    59 // CSTUNBindingImplementation::NewL
       
    60 // ---------------------------------------------------------------------------
       
    61 //
       
    62 CSTUNBindingImplementation*
       
    63     CSTUNBindingImplementation::NewL( CBinding& aBinding,
       
    64                                       MSTUNBindingObserver& aClient,
       
    65                                       RSocket& aSocket )
       
    66     {
       
    67 
       
    68     CSTUNBindingImplementation* self =
       
    69     new ( ELeave ) CSTUNBindingImplementation( aBinding, aClient, aSocket );
       
    70     CleanupStack::PushL( self );
       
    71     self->ConstructL();
       
    72     CleanupStack::Pop( self );
       
    73     return self;
       
    74     }
       
    75 
       
    76 // ---------------------------------------------------------------------------
       
    77 // CSTUNBindingImplementation::NewL - overloaded
       
    78 // ---------------------------------------------------------------------------
       
    79 //
       
    80 CSTUNBindingImplementation*
       
    81     CSTUNBindingImplementation::NewL( CBinding& aBinding,
       
    82                                       MSTUNBindingObserver& aClient,
       
    83                                       TUint aStreamId,
       
    84                                       TUint aConnectionId,
       
    85                                       MNcmConnectionMultiplexer* aMux )
       
    86     {
       
    87 
       
    88     CSTUNBindingImplementation* self =
       
    89     new ( ELeave ) CSTUNBindingImplementation( aBinding, aClient, aStreamId,
       
    90                                                aConnectionId, aMux );
       
    91     CleanupStack::PushL( self );
       
    92     self->ConstructL( );
       
    93     CleanupStack::Pop( self );
       
    94     return self;
       
    95     }
       
    96 
       
    97 // ---------------------------------------------------------------------------
       
    98 // CSTUNBindingImplementation::CSTUNBindingImplementation
       
    99 // ---------------------------------------------------------------------------
       
   100 //
       
   101 CSTUNBindingImplementation::CSTUNBindingImplementation(
       
   102     CBinding& aBinding,
       
   103     MSTUNBindingObserver& aClient,
       
   104     RSocket& aSocket ) :
       
   105     CBindingImplementation( aClient, aBinding, aSocket )
       
   106     {
       
   107     }
       
   108 
       
   109 // ---------------------------------------------------------------------------
       
   110 // CSTUNBindingImplementation::CSTUNBindingImplementation
       
   111 // ---------------------------------------------------------------------------
       
   112 //
       
   113 CSTUNBindingImplementation::CSTUNBindingImplementation(
       
   114     CBinding& aBinding,
       
   115     MSTUNBindingObserver& aClient,
       
   116     TUint aStreamId,
       
   117     TUint aConnectionId,
       
   118     MNcmConnectionMultiplexer* aMux ) :
       
   119     CBindingImplementation( aClient, aBinding, aStreamId, aConnectionId,
       
   120     aMux ), iDestAddr( KAFUnspec )
       
   121     {
       
   122     }
       
   123 
       
   124 // ---------------------------------------------------------------------------
       
   125 // CSTUNBindingImplementation::ConstructL
       
   126 // ---------------------------------------------------------------------------
       
   127 //
       
   128 void CSTUNBindingImplementation::ConstructL()
       
   129     {
       
   130     ClientL().AttachBindingL( iBinding );
       
   131 
       
   132     iRetransmitInterval = ClientL().RetransmitInterval();
       
   133 
       
   134     iGetAddress = new ( ELeave ) CSTUNBindingGetAddress();
       
   135     iGetSharedSecret =
       
   136     new ( ELeave ) CSTUNBindingGetSharedSecret( *iGetAddress );
       
   137     iInit = new ( ELeave ) CSTUNBindingInit( *iGetSharedSecret );
       
   138     iActive = new ( ELeave ) CSTUNBindingActive( *iGetSharedSecret );
       
   139     iWaitToRetry = new ( ELeave ) CSTUNBindingWaitToRetry( *iGetSharedSecret );
       
   140     iGetAddress->SetNeighbourStates( *iGetSharedSecret,
       
   141                                      *iWaitToRetry,
       
   142                                      *iActive );
       
   143     
       
   144     iIndicationTx = CStunIndicationTransmitter::NewL( *iMux, 
       
   145         iStreamId, iConnectionId );
       
   146     
       
   147     ChangeState( *iInit );
       
   148     }
       
   149 
       
   150 // ---------------------------------------------------------------------------
       
   151 // CSTUNBindingImplementation::~CSTUNBindingImplementation
       
   152 // ---------------------------------------------------------------------------
       
   153 //
       
   154 CSTUNBindingImplementation::~CSTUNBindingImplementation()
       
   155     {
       
   156     __STUNTURNCLIENT( "CSTUNBindingImplementation::~CSTUNBindingImplementation" )
       
   157     if ( iClient )
       
   158         {
       
   159         iClient->DetachBinding( iBinding );
       
   160         }
       
   161 
       
   162     this->FreeRequestData();
       
   163 
       
   164     delete iInit;
       
   165     delete iGetSharedSecret;
       
   166     delete iGetAddress;
       
   167     delete iWaitToRetry;
       
   168     delete iActive;
       
   169     delete iIndicationTx;
       
   170 
       
   171     iSocket = NULL;
       
   172     iMux = NULL;
       
   173 
       
   174     __STUNTURNCLIENT( "CSTUNBindingImplementation::~CSTUNBindingImplementation exit" )
       
   175     }
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // CSTUNBindingImplementation::TimerExpiredL
       
   179 // -----------------------------------------------------------------------------
       
   180 //
       
   181 void CSTUNBindingImplementation::TimerExpiredL()
       
   182     {
       
   183     iState->TimerExpiredL( *this );
       
   184     }
       
   185 
       
   186 // -----------------------------------------------------------------------------
       
   187 // CSTUNBindingImplementation::LeaveFromTimerExpired
       
   188 // -----------------------------------------------------------------------------
       
   189 //
       
   190 void CSTUNBindingImplementation::LeaveFromTimerExpired( TInt aError )
       
   191     {
       
   192     __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument );
       
   193 
       
   194     Terminate( aError );
       
   195     }
       
   196 
       
   197 // ---------------------------------------------------------------------------
       
   198 // CSTUNBindingImplementation::PublicAddressObtainedL
       
   199 // ---------------------------------------------------------------------------
       
   200 //
       
   201 void CSTUNBindingImplementation::PublicAddressObtainedL(
       
   202     const TInetAddr& aAddress )
       
   203     {
       
   204     iState->PublicAddressReceivedL( *this, aAddress );
       
   205     }
       
   206 
       
   207 // ---------------------------------------------------------------------------
       
   208 // CSTUNBindingImplementation::PublicAddressObtainedL
       
   209 // ---------------------------------------------------------------------------
       
   210 //
       
   211 void CSTUNBindingImplementation::PublicAddressObtainedL(
       
   212     const TInetAddr& aReflexiveAddr, const TInetAddr& aRelayAddr )
       
   213     {
       
   214     iState->PublicAddressReceivedL( *this, aReflexiveAddr, aRelayAddr );
       
   215     }
       
   216 
       
   217 // ---------------------------------------------------------------------------
       
   218 // CSTUNBindingImplementation::TransactionError
       
   219 // ---------------------------------------------------------------------------
       
   220 //
       
   221 void CSTUNBindingImplementation::TransactionError( TInt aError,
       
   222     CNATFWUNSAFUnknownAttributesAttribute* aUnknownAttr )
       
   223     {
       
   224     delete iUnknownAttr;
       
   225     iUnknownAttr = aUnknownAttr;
       
   226 
       
   227     __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument );
       
   228     iState->TransactionError( *this, aError );
       
   229     }
       
   230 
       
   231 // ---------------------------------------------------------------------------
       
   232 // CSTUNBindingImplementation::TransactionEventOccurredL
       
   233 // ---------------------------------------------------------------------------
       
   234 //
       
   235 void CSTUNBindingImplementation::TransactionEventOccurredL(
       
   236     TSTUNCallbackInfo::TFunction /*aEvent*/ )
       
   237     {
       
   238     __STUNTURNCLIENT(
       
   239         "CSTUNBindingImplementation::TransactionEventOccurredL -should not get called" )
       
   240     }
       
   241 
       
   242 // ---------------------------------------------------------------------------
       
   243 // CSTUNBindingImplementation::HandleTransactionError
       
   244 // ---------------------------------------------------------------------------
       
   245 
       
   246 TBool CSTUNBindingImplementation::HandleTransactionError( TInt aError )
       
   247     {
       
   248     __STUNTURNCLIENT_INT1( "HandleTransactionError, reason", aError )
       
   249 
       
   250     const TInt KMaxErrorResponseCount = 3;
       
   251 
       
   252     __STUN_ASSERT_RETURN_VALUE( iRequest && aError != KErrNone,
       
   253     EFalse );
       
   254 
       
   255     delete iTransaction;
       
   256     iTransaction = NULL;
       
   257     iTransactionError = aError;
       
   258 
       
   259     if ( ( aError > 0 ) && ( ++iErrorResponseCount >= KMaxErrorResponseCount ) )
       
   260         {
       
   261         iErrorResponseCount = 0;
       
   262         return EFalse;
       
   263         }
       
   264 
       
   265     CNATFWUNSAFAlternateServerAttribute* alternateServer = NULL;
       
   266     HBufC8* realmValue = NULL;
       
   267 
       
   268     switch ( aError )
       
   269         {
       
   270         case KErrTimedOut:
       
   271             __STUNTURNCLIENT(
       
   272                 "CSTUNBindingImplementation - KErrTimedOut" )
       
   273             //Clear iAddXorOnly as another address is tried
       
   274             iAddXorOnly = EFalse;
       
   275             return iClient && iClient->ObtainServerAddress( iServerAddress );
       
   276 
       
   277         case E300TryAlternate:
       
   278             // The client SHOULD attempt a new transaction to the server
       
   279             // indicated in the ALTERNATE-SERVER attribute.
       
   280             alternateServer = static_cast<CNATFWUNSAFAlternateServerAttribute*>
       
   281             ( iRequest->Attribute( CNATFWUNSAFAttribute::EAlternateServer ) );
       
   282             if ( alternateServer )
       
   283                 {
       
   284                 iServerAddress = alternateServer->Address();
       
   285                 return ETrue;
       
   286                 }
       
   287             return EFalse;
       
   288 
       
   289         case E4XX:
       
   290             return EFalse;
       
   291 
       
   292         case E401Unauthorized:
       
   293             if ( iSharedSecret )
       
   294                 {
       
   295                 CNATFWUNSAFRealmAttribute* realm =
       
   296                     static_cast<CNATFWUNSAFRealmAttribute*>
       
   297                     ( iRequest->Attribute( CNATFWUNSAFAttribute::ERealm ) );
       
   298                 if ( realm || !iRealmFromResponse )
       
   299                     {
       
   300                     // indicates that this was retry and it did not work.
       
   301                     // notify client -> unrecoverable error
       
   302                     return EFalse;
       
   303                     }
       
   304                 }
       
   305             return ETrue;
       
   306 
       
   307         case E420UnknownAttributes:
       
   308             //Remove the unknown attributes and retry
       
   309             return iUnknownAttr != NULL;
       
   310 
       
   311         case E430StaleCredentials:
       
   312             // Client used a short term credential that has expired so
       
   313             // generate a new Shared Secret request
       
   314             return iSharedSecret != NULL;
       
   315 
       
   316         case E431IntegrityCheckFailure:
       
   317             {
       
   318             TBool retry = EFalse;
       
   319             TRAPD( err, retry =
       
   320                 ClientL().SharedSecretRejectedL( iBinding,
       
   321                                                 Username(),
       
   322                                                 *iSharedSecret ) );
       
   323             return err == KErrNone && retry;
       
   324             }
       
   325 
       
   326         case E432MissingUsername:
       
   327             //If missing USERNAME or MESSAGE-INTEGRITY, add them and retry
       
   328             return !iRequest->Attribute( CNATFWUNSAFAttribute::EUsername ) ||
       
   329                !iSharedSecret;
       
   330 
       
   331         case E433UseTLS:
       
   332             // If request was a Shared Secret request and wasn't sent over
       
   333             // TLS, the client SHOULD retry the request with TLS.
       
   334             return iSharedSecret != NULL;
       
   335 
       
   336         case E434MissingRealm:
       
   337             if ( !iRequest->Attribute( CNATFWUNSAFAttribute::ERealm ) &&
       
   338                  iSharedSecret )
       
   339                 {
       
   340                 // use a long term credential and retry the request using the username
       
   341                 // and password associated with the REALM
       
   342                 return ETrue;
       
   343                 }  
       
   344             TRAPD( err, realmValue = ( static_cast<CNATFWUNSAFRealmAttribute*>
       
   345                 ( iRequest->Attribute( CNATFWUNSAFAttribute::ERealm ) ) )->
       
   346                 Value().AllocL() );
       
   347             if ( err || !realmValue )
       
   348                 {
       
   349                 delete realmValue;
       
   350                 return EFalse;
       
   351                 }
       
   352                 
       
   353             if ( realmValue->Compare( *iRealmFromResponse ) )
       
   354                 {
       
   355                 // the client SHOULD retry using the username and
       
   356                 // password associated with the REALM in the response
       
   357                 iUseRealmFromResponse = ETrue;
       
   358                 delete realmValue;
       
   359                 return ETrue;
       
   360                 }
       
   361             delete realmValue;
       
   362             return EFalse;
       
   363 
       
   364 
       
   365         case E435MissingNonce:
       
   366             if ( iRequest->Attribute( CNATFWUNSAFAttribute::ENonce ) )
       
   367                 {
       
   368                 return EFalse;
       
   369                 }
       
   370             // retry using a nonce from error response
       
   371             return ETrue;
       
   372 
       
   373         case E436UnknownUsername:
       
   374             if ( iSharedSecret )
       
   375                 {
       
   376                 return ETrue;
       
   377                 }
       
   378             // If the username was collected from the user, alert the user.
       
   379             return EFalse;
       
   380                 
       
   381         case E438StaleNonce:
       
   382             if ( iRequest->Attribute( CNATFWUNSAFAttribute::ENonce ) )
       
   383                 {
       
   384                 // retry using a nonce from error response
       
   385                 return ETrue;
       
   386                 }
       
   387             return EFalse;
       
   388         
       
   389         case E487RoleConflict:
       
   390             return EFalse;
       
   391             
       
   392         case E500ServerError:
       
   393             return ETrue;
       
   394 
       
   395         case E600GlobalFailure:
       
   396             return EFalse;
       
   397 
       
   398         case ERetryAfterAddingXorOnly:
       
   399             iAddXorOnly = ETrue;
       
   400             return ETrue;
       
   401 
       
   402         default:
       
   403             return STUNUtils::Is5xxResponse( aError );
       
   404         }
       
   405 
       
   406     }
       
   407 
       
   408 // ---------------------------------------------------------------------------
       
   409 // CSTUNBindingImplementation::IcmpError
       
   410 // ---------------------------------------------------------------------------
       
   411 //
       
   412 void CSTUNBindingImplementation::IcmpError( const TInetAddr& aAddress )
       
   413     {
       
   414     if ( iTransaction && iServerAddress.CmpAddr( aAddress ) )
       
   415         {
       
   416         //Try next address, or terminate with KErrTimedOut.
       
   417         iTransaction->Terminate( KErrTimedOut );
       
   418         }
       
   419     }
       
   420 
       
   421 // ---------------------------------------------------------------------------
       
   422 // CSTUNBindingImplementation::SendRequestL
       
   423 // ---------------------------------------------------------------------------
       
   424 //
       
   425 void CSTUNBindingImplementation::SendRequestL()
       
   426     {
       
   427     iRetransmitInterval = ClientL().RetransmitInterval();
       
   428     iAddFingerprint = EFalse;
       
   429 
       
   430     iState->SendRequestL( *this );
       
   431     }
       
   432 
       
   433 
       
   434 // ---------------------------------------------------------------------------
       
   435 // CSTUNBindingImplementation::SendRequestL
       
   436 // ---------------------------------------------------------------------------
       
   437 //
       
   438 void CSTUNBindingImplementation::SendRequestL( const TInetAddr& aDestAddr,
       
   439                                                TBool aAddFingerprint,
       
   440                                                TUint aRtoValue )
       
   441     {
       
   442     if ( 0 != aRtoValue )
       
   443         {
       
   444         iRetransmitInterval = aRtoValue;
       
   445         }
       
   446 
       
   447     if ( KAFUnspec != aDestAddr.Family() )
       
   448         {
       
   449         iDestAddr.SetAddress( aDestAddr.Address() );
       
   450         iDestAddr.SetPort( aDestAddr.Port() );
       
   451         }
       
   452 
       
   453     iAddFingerprint = aAddFingerprint;
       
   454 
       
   455     iState->SendRequestL( *this );
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------------------------
       
   459 // CSTUNBindingImplementation::StreamId
       
   460 // ---------------------------------------------------------------------------
       
   461 //
       
   462 TUint CSTUNBindingImplementation::StreamId() const
       
   463     {
       
   464     return iStreamId;
       
   465     }
       
   466 
       
   467 // ---------------------------------------------------------------------------
       
   468 // CSTUNBindingImplementation::ConnectionId
       
   469 // ---------------------------------------------------------------------------
       
   470 //
       
   471 TUint CSTUNBindingImplementation::ConnectionId() const
       
   472     {
       
   473     return iConnectionId;
       
   474     }
       
   475 
       
   476 // ---------------------------------------------------------------------------
       
   477 // CSTUNBindingImplementation::CancelRequest
       
   478 // If transaction exists, delete it to stop using the socket.
       
   479 // ---------------------------------------------------------------------------
       
   480 //
       
   481 void CSTUNBindingImplementation::CancelRequest()
       
   482     {
       
   483     if ( AddressResolved() )
       
   484         {
       
   485         ChangeState( *iActive );
       
   486         delete iTransaction;
       
   487         iTransaction = NULL;
       
   488         }
       
   489     else
       
   490         {
       
   491         //The initial request is canceled
       
   492         ChangeState( *iInit );
       
   493         Terminate( KErrCancel );
       
   494         }
       
   495     }
       
   496 
       
   497 // ---------------------------------------------------------------------------
       
   498 // CSTUNBindingImplementation::Socket
       
   499 // ---------------------------------------------------------------------------
       
   500 //
       
   501 const RSocket& CSTUNBindingImplementation::Socket() const
       
   502     {
       
   503     return *iSocket;
       
   504     }
       
   505 
       
   506 // ---------------------------------------------------------------------------
       
   507 // CSTUNBindingImplementation::AddressResolved
       
   508 // The most recent public address is kept also during a refresh.
       
   509 // ---------------------------------------------------------------------------
       
   510 //
       
   511 TBool CSTUNBindingImplementation::AddressResolved() const
       
   512     {
       
   513     return !iPublicAddr.IsUnspecified();
       
   514     }
       
   515 
       
   516 // ---------------------------------------------------------------------------
       
   517 // CSTUNBindingImplementation::PublicAddr
       
   518 // ---------------------------------------------------------------------------
       
   519 //
       
   520 const TInetAddr& CSTUNBindingImplementation::PublicAddr() const
       
   521     {
       
   522     return iPublicAddr;
       
   523     }
       
   524 
       
   525 // ---------------------------------------------------------------------------
       
   526 // CSTUNBindingImplementation::AlternateServerAddr
       
   527 // ---------------------------------------------------------------------------
       
   528 //
       
   529 const TInetAddr& CSTUNBindingImplementation::AlternateServerAddr() const
       
   530     {
       
   531     return iServerAddress;
       
   532     }
       
   533 
       
   534 // ---------------------------------------------------------------------------
       
   535 // CSTUNBindingImplementation::RealmFromResponse
       
   536 // ---------------------------------------------------------------------------
       
   537 //
       
   538 const HBufC8* CSTUNBindingImplementation::RealmFromResponse() const
       
   539     {
       
   540     return iRealmFromResponse;
       
   541     }
       
   542 
       
   543 // ---------------------------------------------------------------------------
       
   544 // CSTUNBindingImplementation::HandleDataL
       
   545 // Must NOT leave, if aData is not a STUN message!
       
   546 // ---------------------------------------------------------------------------
       
   547 //
       
   548 HBufC8* CSTUNBindingImplementation::HandleDataL(
       
   549     const TDesC8& aData, TBool& aConsumed, TInetAddr& aRemoteAddr )
       
   550     {
       
   551     __STUNTURNCLIENT( "CSTUNBindingImplementation::HandleDataL" )
       
   552     aConsumed = EFalse;
       
   553     TInt err( KErrNone );
       
   554     HBufC8* dataPointer = NULL;
       
   555 
       
   556     CNATFWUNSAFMessage* msg = NULL;
       
   557     TRAP( err, msg = DecodeMessageL( aData ) );
       
   558     if ( KErrNoMemory == err )
       
   559         {
       
   560         User::Leave( err );
       
   561         }
       
   562     if ( msg )
       
   563         {
       
   564         CleanupStack::PushL( msg );
       
   565         CNATFWUNSAFRealmAttribute* realm = static_cast<CNATFWUNSAFRealmAttribute*>(
       
   566             msg->Attribute( CNATFWUNSAFAttribute::ERealm ) );
       
   567         if ( realm )
       
   568             {
       
   569             delete iRealmFromResponse;
       
   570             iRealmFromResponse = NULL;
       
   571             const TDesC8& realmValue = ( static_cast<CNATFWUNSAFRealmAttribute*>(
       
   572                 msg->Attribute( CNATFWUNSAFAttribute::ERealm ) )->Value() );
       
   573             iRealmFromResponse = realmValue.AllocL();
       
   574             __STUNTURNCLIENT_STR8( "realm: ", *iRealmFromResponse )
       
   575             }
       
   576 
       
   577         CNATFWUNSAFNonceAttribute* nonce = static_cast<CNATFWUNSAFNonceAttribute*>(
       
   578             msg->Attribute( CNATFWUNSAFAttribute::ENonce ) );
       
   579         if ( nonce )
       
   580             {
       
   581             delete iNonce;
       
   582             iNonce = NULL;
       
   583             const TDesC8& nonceValue = ( static_cast<CNATFWUNSAFNonceAttribute*>(
       
   584             msg->Attribute( CNATFWUNSAFAttribute::ENonce ) )->Value() );
       
   585             iNonce = nonceValue.AllocL();
       
   586             }
       
   587 
       
   588         // if aData contains data indication, decode it (TURN Specific)
       
   589         if ( msg->Type() == CNATFWUNSAFMessage::EDataIndication &&
       
   590              KErrNone == err )
       
   591             {
       
   592             const TDesC8& data = ( static_cast<CNATFWUNSAFDataAttribute*>(
       
   593                 msg->Attribute( CNATFWUNSAFAttribute::EData ) )->Value() );
       
   594 
       
   595             // Remote address is returned through reference
       
   596             CNATFWUNSAFRemoteAddressAttribute* remoteAddress =
       
   597                 static_cast<CNATFWUNSAFRemoteAddressAttribute*>
       
   598                 ( msg->Attribute( CNATFWUNSAFAttribute::ERemoteAddress ) );
       
   599 
       
   600             if( remoteAddress )
       
   601                 {
       
   602                 aRemoteAddr = remoteAddress->Address();
       
   603                 }
       
   604             else
       
   605                 {
       
   606                 remoteAddress = NULL;
       
   607                 }
       
   608 
       
   609             CNATFWUNSAFMessage* msg_unsaf = NULL;
       
   610 
       
   611             dataPointer = data.AllocLC(); // to cleanupstack
       
   612 
       
   613             TRAP( err, msg_unsaf = DecodeMessageL( *dataPointer ) );
       
   614             if ( KErrNoMemory == err )
       
   615                 {
       
   616                 User::Leave( err );
       
   617                 }
       
   618             CleanupStack::PushL( msg_unsaf );
       
   619 
       
   620             if ( iTransaction && iRequest && !err && msg_unsaf )
       
   621                 {
       
   622                 if ( ValidateMsgType( msg_unsaf ) &&
       
   623                      iRequest->TransactionID() == msg_unsaf->TransactionID() )
       
   624                     {
       
   625                     aConsumed = ETrue;
       
   626                     iTransaction->ReceiveL( *msg_unsaf, *dataPointer );
       
   627                     CleanupStack::PopAndDestroy( msg_unsaf );
       
   628                     CleanupStack::PopAndDestroy( dataPointer );
       
   629                     dataPointer = NULL;
       
   630                     }
       
   631                 }
       
   632 
       
   633             if ( dataPointer )
       
   634                 {
       
   635                 // dataPointer is still valid. This means that message was not
       
   636                 // consumed, and data indication is ripped off from it.
       
   637                 // Message can also contain media data.
       
   638                 // Data indication is decapsulated out of that message.
       
   639                 CleanupStack::PopAndDestroy( msg_unsaf );
       
   640                 CleanupStack::Pop( dataPointer );
       
   641                 }
       
   642             }
       
   643 
       
   644         // Data was NOT in encapsulated in data indication, so offer
       
   645         // message to this client.
       
   646         else if ( !err && iTransaction && iRequest )
       
   647             {
       
   648             if ( ValidateMsgType( msg ) &&
       
   649                  iRequest->TransactionID() == msg->TransactionID() )
       
   650                 {
       
   651                 aConsumed = ETrue;
       
   652                 iTransaction->ReceiveL( *msg, aData );
       
   653                 }
       
   654             }
       
   655         else
       
   656             {
       
   657             // PCLint requirement
       
   658             }
       
   659         CleanupStack::PopAndDestroy( msg );
       
   660         }
       
   661     return dataPointer;
       
   662     }
       
   663 
       
   664 // ---------------------------------------------------------------------------
       
   665 // CSTUNBindingImplementation::STUNClient
       
   666 // ---------------------------------------------------------------------------
       
   667 //
       
   668 const CSTUNClient* CSTUNBindingImplementation::STUNClient() const
       
   669     {
       
   670     return iClient ? &iClient->STUNClient() : NULL;
       
   671     }
       
   672 
       
   673 // ---------------------------------------------------------------------------
       
   674 // CSTUNBindingImplementation::GetServerAddressL
       
   675 // ---------------------------------------------------------------------------
       
   676 //
       
   677 void CSTUNBindingImplementation::GetServerAddressL()
       
   678     {
       
   679     __ASSERT_ALWAYS( iServerAddress.IsUnspecified(),
       
   680      User::Leave( KErrAlreadyExists ) );
       
   681     __ASSERT_ALWAYS( ClientL().ObtainServerAddress( iServerAddress ),
       
   682      User::Leave( KErrNotFound ) );
       
   683     }
       
   684 
       
   685 // ---------------------------------------------------------------------------
       
   686 // CSTUNBindingImplementation::GetSharedSecretL
       
   687 // ---------------------------------------------------------------------------
       
   688 //
       
   689 void CSTUNBindingImplementation::GetSharedSecretL()
       
   690     {
       
   691     ClientL().ObtainSharedSecretL( iBinding );
       
   692     }
       
   693 
       
   694 // ---------------------------------------------------------------------------
       
   695 // CSTUNBindingImplementation::Username
       
   696 // ---------------------------------------------------------------------------
       
   697 //
       
   698 const TDesC8& CSTUNBindingImplementation::Username() const
       
   699     {
       
   700     if ( iRequest && iRequest->HasAttribute( CNATFWUNSAFAttribute::EUsername ) )
       
   701         {
       
   702         return static_cast<CNATFWUNSAFUsernameAttribute*>(
       
   703         iRequest->Attribute( CNATFWUNSAFAttribute::EUsername ) )->Value();
       
   704         }
       
   705 
       
   706     return KNullDesC8;
       
   707     }
       
   708 
       
   709 // ---------------------------------------------------------------------------
       
   710 // CSTUNBindingImplementation::DetachClient
       
   711 // ---------------------------------------------------------------------------
       
   712 //
       
   713 void CSTUNBindingImplementation::DetachClient()
       
   714     {
       
   715     iClient = NULL;
       
   716     }
       
   717 
       
   718 // ---------------------------------------------------------------------------
       
   719 // CSTUNBindingImplementation::StoreAddressL
       
   720 // Transaction no longer needed.
       
   721 // ---------------------------------------------------------------------------
       
   722 //
       
   723 void CSTUNBindingImplementation::StoreAddressL(
       
   724     const TInetAddr& aPublicAddress )
       
   725     {
       
   726     iErrorResponseCount = 0;
       
   727     iPublicAddr = aPublicAddress;
       
   728     ClientL().AddressResolvedL( iBinding );
       
   729 
       
   730     FreeRequestData();
       
   731     }
       
   732 
       
   733 // -----------------------------------------------------------------------------
       
   734 // CSTUNBindingImplementation::ChangeState
       
   735 // -----------------------------------------------------------------------------
       
   736 //
       
   737 void CSTUNBindingImplementation::ChangeState(
       
   738     CSTUNBindingState& aNewState )
       
   739     {
       
   740     iState = &aNewState;
       
   741     }
       
   742 
       
   743 // ---------------------------------------------------------------------------
       
   744 // CSTUNBindingImplementation::Terminate
       
   745 // Binding can be re-started with SendRequestL.
       
   746 // ---------------------------------------------------------------------------
       
   747 //
       
   748 void CSTUNBindingImplementation::Terminate( TInt aError )
       
   749     {
       
   750     __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument );
       
   751 
       
   752     NATFWUNSAF_INTLOG( "STUNBinding terminated, reason", aError )
       
   753 
       
   754     TInetAddr emptyAddr;
       
   755     iPublicAddr = emptyAddr;
       
   756     iServerAddress = emptyAddr;
       
   757     iAddXorOnly = EFalse;
       
   758     iErrorResponseCount = 0;
       
   759     FreeRequestData();
       
   760 
       
   761     if ( iState != iInit )
       
   762         {
       
   763         __STUNTURNCLIENT( "Binding terminated" )
       
   764 
       
   765         ChangeState( *iInit );
       
   766         TRAP_IGNORE( ClientL().BindingErrorL( Binding(), aError, ETrue ) )
       
   767         }
       
   768     }
       
   769 
       
   770 // ---------------------------------------------------------------------------
       
   771 // CSTUNBindingImplementation::FreeRequestData
       
   772 // ---------------------------------------------------------------------------
       
   773 //
       
   774 void CSTUNBindingImplementation::FreeRequestData()
       
   775     {
       
   776     delete iTransaction;
       
   777     iTransaction = NULL;
       
   778     delete iUnknownAttr;
       
   779     iUnknownAttr = NULL;
       
   780     delete iRequest;
       
   781     iRequest = NULL;
       
   782     delete iSharedSecret;
       
   783     iSharedSecret = NULL;
       
   784     delete iRealmFromResponse;
       
   785     iRealmFromResponse = NULL;
       
   786     delete iNonce;
       
   787     iNonce = NULL;
       
   788 	iICEAttributes = TICEAttributes();
       
   789 	iAddFingerprint = EFalse;
       
   790     }
       
   791 
       
   792 // ---------------------------------------------------------------------------
       
   793 // CSTUNBindingImplementation::IsWaitingSharedSecret
       
   794 // ---------------------------------------------------------------------------
       
   795 //
       
   796 TBool CSTUNBindingImplementation::IsWaitingSharedSecret() const
       
   797     {
       
   798     return iState == iGetSharedSecret;
       
   799     }
       
   800 
       
   801 // ---------------------------------------------------------------------------
       
   802 // CSTUNBindingImplementation::SharedSecretObtainedL
       
   803 // ---------------------------------------------------------------------------
       
   804 //
       
   805 void CSTUNBindingImplementation::SharedSecretObtainedL(
       
   806     const TDesC8& aUsername, const TDesC8& aPassword )
       
   807     {
       
   808     __STUN_ASSERT_L( ( aUsername.Length() > 0 && aPassword.Length() > 0 ) ||
       
   809      ( aUsername.Length() == 0 && aPassword.Length() == 0 ), KErrArgument );
       
   810 
       
   811     iState->SharedSecretObtainedL( *this, aUsername, aPassword );
       
   812     }
       
   813 
       
   814 // ---------------------------------------------------------------------------
       
   815 // CSTUNBindingImplementation::CreateBindingRequestL
       
   816 // ---------------------------------------------------------------------------
       
   817 //
       
   818 void CSTUNBindingImplementation::CreateBindingRequestL(
       
   819     const TDesC8& aUsername, const TDesC8& aPassword )
       
   820     {
       
   821     delete iRequest;
       
   822     iRequest = NULL;
       
   823 
       
   824     if ( IsSharedSecretRequired() &&
       
   825          ( aUsername.Length() == 0 || aPassword.Length() == 0 ) )
       
   826          {
       
   827          Terminate( KErrAccessDenied );
       
   828          User::Leave( KErrAccessDenied );
       
   829          }
       
   830     iTransactionError = KErrNone;
       
   831 
       
   832     HBufC8* newSharedSecret = aPassword.AllocL();
       
   833     delete iSharedSecret;
       
   834     iSharedSecret = newSharedSecret;
       
   835 
       
   836     TNATFWUNSAFTransactionID transactionID;
       
   837     ClientL().ObtainTransactionIDL( transactionID );
       
   838     iRequest = CNATFWUNSAFBindingRequest::NewL( transactionID );
       
   839 
       
   840     if ( aUsername.Length() > 0 )
       
   841         {
       
   842         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
   843          - Add USERNAME attribute" )
       
   844         iRequest->AddAttributeL( CNATFWUNSAFUsernameAttribute::NewLC( aUsername ) );
       
   845         CleanupStack::Pop(); //CNATFWUNSAFUsernameAttribute
       
   846         }
       
   847 
       
   848     if ( iICEAttributes.iPriority > 0 )
       
   849         {
       
   850         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
   851          - Add PRIORITY attribute" )
       
   852         iRequest->AddAttributeL( CNATFWUNSAFPriorityAttribute::NewLC(
       
   853             iICEAttributes.iPriority ) );
       
   854         CleanupStack::Pop(); // CNATFWUNSAFPriorityAttribute
       
   855         }
       
   856 
       
   857     if ( iICEAttributes.iUseCandidate )
       
   858         {
       
   859         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
   860          - Add USE_CANDIDATE attribute" )
       
   861         iRequest->AddAttributeL( CNATFWUNSAFUseCandidateAttribute::NewLC() );
       
   862         CleanupStack::Pop(); // CNATFWUNSAFUseCandidateAttribute
       
   863         }
       
   864 
       
   865     if ( iICEAttributes.iControlled > 0 )
       
   866         {
       
   867         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
   868          - Add CONTROLLED attribute" )
       
   869         iRequest->AddAttributeL( CNATFWUNSAFIceControlledAttribute::NewLC(
       
   870             iICEAttributes.iControlled ) );
       
   871         CleanupStack::Pop(); // CNATFWUNSAFIceControlledAttribute
       
   872         }
       
   873 
       
   874     if ( iICEAttributes.iControlling > 0 )
       
   875         {
       
   876         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
   877          - Add CONTROLLING attribute" )
       
   878         iRequest->AddAttributeL( CNATFWUNSAFIceControllingAttribute::NewLC(
       
   879             iICEAttributes.iControlling ) );
       
   880         CleanupStack::Pop(); // CNATFWUNSAFIceControllingAttribute
       
   881         }
       
   882 
       
   883     if ( iUseRealmFromResponse )
       
   884         {
       
   885         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
   886          - Add REALM attribute" )
       
   887         // Should only be added if long term credentials used
       
   888         iRequest->AddAttributeL( CNATFWUNSAFRealmAttribute::NewLC(
       
   889             *iRealmFromResponse ) );
       
   890 
       
   891         CleanupStack::Pop(); // CNATFWUNSAFRealmAttribute
       
   892         }
       
   893 
       
   894     if ( iAddXorOnly )
       
   895         {
       
   896         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
   897          - Add XOR_ONLY attribute" )
       
   898         iRequest->AddAttributeL( CNATFWUNSAFXorOnlyAttribute::NewLC() );
       
   899         CleanupStack::Pop(); //CNATFWUNSAFXorOnlyAttribute
       
   900         }
       
   901 
       
   902     if ( iUnknownAttr )
       
   903         {
       
   904         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL - Unknown" )
       
   905         STUNUtils::RemoveUnknownAttributes( *iRequest, *iUnknownAttr );
       
   906         delete iUnknownAttr;
       
   907         iUnknownAttr = NULL;
       
   908         }
       
   909 
       
   910     if ( iNonce )
       
   911         {
       
   912         iRequest->AddAttributeL( CNATFWUNSAFNonceAttribute::NewLC(
       
   913             *iNonce ) );
       
   914         CleanupStack::Pop(); // CNATFWUNSAFNonceAttribute
       
   915         }
       
   916     }
       
   917 
       
   918 // ---------------------------------------------------------------------------
       
   919 // CSTUNBindingImplementation::SendBindingRequestL
       
   920 // ---------------------------------------------------------------------------
       
   921 //
       
   922 void CSTUNBindingImplementation::SendBindingRequestL()
       
   923     {
       
   924     __STUN_ASSERT_L( !iTransaction, KErrAlreadyExists );
       
   925     __STUN_ASSERT_L( iRequest && iSharedSecret,KErrNotFound );
       
   926 
       
   927     __STUNTURNCLIENT( "CSTUNBindingImplementation::SendBindingRequestL" )
       
   928 
       
   929     if ( iSocket )
       
   930         {
       
   931         iTransaction = CSTUNTransaction::NewL( *iRequest,
       
   932                                                iServerAddress,
       
   933                                                *iSharedSecret,
       
   934                                                *iSocket,
       
   935                                                ClientL().TimerProvider(),
       
   936                                                iRetransmitInterval,
       
   937                                                *this,
       
   938                                                KStun,
       
   939                                                ClientL().TransportProtocol() );
       
   940         }
       
   941 
       
   942     else
       
   943         {
       
   944         iTransaction = CSTUNTransaction::NewL( *iRequest,
       
   945                                                iServerAddress,
       
   946                                                *iSharedSecret,
       
   947                                                iStreamId,
       
   948                                                iConnectionId,
       
   949                                                ClientL().TimerProvider(),
       
   950                                                iRetransmitInterval,
       
   951                                                *this,
       
   952                                                KStun,
       
   953                                                *iMux,
       
   954                                                ClientL().TransportProtocol(),
       
   955                                                iAddFingerprint,
       
   956                                                iDestAddr );
       
   957         }
       
   958     }
       
   959 
       
   960 // ---------------------------------------------------------------------------
       
   961 // CSTUNBindingImplementation::WaitBeforeRetrying
       
   962 // ---------------------------------------------------------------------------
       
   963 //
       
   964 void CSTUNBindingImplementation::WaitBeforeRetrying()
       
   965     {
       
   966     StartTimer( STUNUtils::EWaitBeforeRetryDuration );
       
   967     }
       
   968 
       
   969 // ---------------------------------------------------------------------------
       
   970 // CSTUNBindingImplementation::CancelRetransmission
       
   971 // ---------------------------------------------------------------------------
       
   972 //
       
   973 void CSTUNBindingImplementation::CancelRetransmission()
       
   974     {
       
   975     if ( iTransaction )
       
   976         {
       
   977         iTransaction->CancelRetransmission();
       
   978         }
       
   979     }
       
   980 
       
   981 // ---------------------------------------------------------------------------
       
   982 // CSTUNBindingImplementation::SendIndicationL
       
   983 // ---------------------------------------------------------------------------
       
   984 //
       
   985 void CSTUNBindingImplementation::SendIndicationL(
       
   986     const TInetAddr& aRemoteAddr, const TDesC8& /*aData*/, 
       
   987     TBool aAddFingerprint )
       
   988     {
       
   989     __STUNTURNCLIENT( "CSTUNBindingImplementation::SendBindingIndicationL" )
       
   990     
       
   991     HBufC8* username = ClientL().UsernameForIndication().AllocL();
       
   992     CleanupStack::PushL( username );
       
   993     HBufC8* password = ClientL().PasswordForIndication().AllocL();
       
   994     CleanupStack::PushL( password );
       
   995     
       
   996     TNATFWUNSAFTransactionID transactionID;
       
   997     ClientL().ObtainTransactionIDL( transactionID );
       
   998     
       
   999     CNATFWUNSAFMessage* 
       
  1000         indication = CNATFWUNSAFBindingIndication::NewL( transactionID );
       
  1001     CleanupStack::PushL( indication );
       
  1002     
       
  1003     if ( username->Length() > 0 )
       
  1004         {
       
  1005         __STUNTURNCLIENT( "CSTUNBindingImplementation::CreateBindingRequestL\
       
  1006          - Add USERNAME attribute" )
       
  1007         indication->AddAttributeL( CNATFWUNSAFUsernameAttribute::NewLC( *username ) );
       
  1008         CleanupStack::Pop(); //CNATFWUNSAFUsernameAttribute
       
  1009         }
       
  1010 
       
  1011     if ( iUnknownAttr )
       
  1012         {
       
  1013         STUNUtils::RemoveUnknownAttributes( *indication, *iUnknownAttr );
       
  1014         delete iUnknownAttr;
       
  1015         iUnknownAttr = NULL;
       
  1016         }
       
  1017 
       
  1018     iIndicationTx->TransmitL( *indication, aRemoteAddr, *password, 
       
  1019         aAddFingerprint );
       
  1020     
       
  1021     CleanupStack::PopAndDestroy( indication );
       
  1022     CleanupStack::PopAndDestroy( password );
       
  1023     CleanupStack::PopAndDestroy( username );
       
  1024     
       
  1025     __STUNTURNCLIENT( "CSTUNBindingImplementation::SendBindingIndicationL out" )
       
  1026     }
       
  1027 
       
  1028 // ---------------------------------------------------------------------------
       
  1029 // CSTUNBindingImplementation::SetICESpecificAttributes
       
  1030 // ---------------------------------------------------------------------------
       
  1031 //
       
  1032 void CSTUNBindingImplementation::SetICESpecificAttributes(
       
  1033     const TICEAttributes& aAttributes )
       
  1034     {
       
  1035     iICEAttributes = aAttributes;
       
  1036     }
       
  1037 
       
  1038 // ---------------------------------------------------------------------------
       
  1039 // CSTUNBindingImplementation::Binding
       
  1040 // ---------------------------------------------------------------------------
       
  1041 //
       
  1042 const CBinding& CSTUNBindingImplementation::Binding()
       
  1043     {
       
  1044     return iBinding;
       
  1045     }
       
  1046 
       
  1047 // ---------------------------------------------------------------------------
       
  1048 // CSTUNBindingImplementation::IsSharedSecretRequired
       
  1049 // ---------------------------------------------------------------------------
       
  1050 //
       
  1051 TBool CSTUNBindingImplementation::IsSharedSecretRequired() const
       
  1052     {
       
  1053     return iTransactionError == E401Unauthorized ||
       
  1054        iTransactionError == E430StaleCredentials ||
       
  1055        iTransactionError == E431IntegrityCheckFailure ||
       
  1056        iTransactionError == E432MissingUsername ||
       
  1057        iTransactionError == E433UseTLS ||
       
  1058        iTransactionError == E434MissingRealm;
       
  1059     }
       
  1060 
       
  1061 // ---------------------------------------------------------------------------
       
  1062 // CSTUNBindingImplementation::ClientL
       
  1063 // ---------------------------------------------------------------------------
       
  1064 //
       
  1065 MSTUNBindingObserver& CSTUNBindingImplementation::ClientL() const
       
  1066     {
       
  1067     __ASSERT_ALWAYS( iClient, User::Leave( KErrNotFound ) );
       
  1068 
       
  1069     return *iClient;
       
  1070     }
       
  1071 
       
  1072 // ---------------------------------------------------------------------------
       
  1073 // CSTUNBindingImplementation::DecodeMessageL
       
  1074 // ---------------------------------------------------------------------------
       
  1075 //
       
  1076 CNATFWUNSAFMessage*
       
  1077     CSTUNBindingImplementation::DecodeMessageL( const TDesC8& aData ) const
       
  1078     {
       
  1079     CNATFWUNSAFMessageFactory* decoder = CNATFWUNSAFMessageFactory::NewLC();
       
  1080     CNATFWUNSAFMessage* msg = decoder->DecodeL( aData );
       
  1081     CleanupStack::PopAndDestroy( decoder );
       
  1082     return msg;
       
  1083     }
       
  1084 
       
  1085 // ---------------------------------------------------------------------------
       
  1086 // CSTUNBindingImplementation::ValidateMsgType
       
  1087 // ---------------------------------------------------------------------------
       
  1088 //
       
  1089 TBool CSTUNBindingImplementation::ValidateMsgType(
       
  1090     CNATFWUNSAFMessage* aMsg ) const
       
  1091     {
       
  1092     if ( aMsg )
       
  1093         {
       
  1094         return ( aMsg->Type() == CNATFWUNSAFMessage::EBindingResponse ||
       
  1095              aMsg->Type() == CNATFWUNSAFMessage::EBindingErrorResponse );
       
  1096         }
       
  1097     return EFalse;
       
  1098     }
       
  1099