dvrengine/CommonRecordingEngine/src/CCRRTSPCommand.cpp
branchRCL_3
changeset 23 13a33d82ad98
parent 0 822a42b6c3f1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/src/CCRRTSPCommand.cpp	Wed Sep 01 12:20:37 2010 +0100
@@ -0,0 +1,761 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:    RTSP command parser and producer*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "CCRRtspCommand.h"
+#include "CCRSock.h"
+#include <imcvcodc.h>
+#include <Hash.h>
+#include "videoserviceutilsLogger.h"
+
+// CONSTANTS
+const TReal KRealZero( 0.0 ); 
+const TReal KRealMinusOne( -1.0 ); 
+// Length of a digest hash before converting to hex.
+const TInt KCRRawHashLength( 16 );
+// Length of a digest hash when represented in hex
+const TInt KCRHashLength( 32 );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCRRtspCommand* CCRRtspCommand::NewL()
+    {
+    CCRRtspCommand* self = new( ELeave ) CCRRtspCommand();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::CCRRtspCommand
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CCRRtspCommand::CCRRtspCommand()
+  : iCommand( ERTSPCommandNOCOMMAND )
+    {  
+    // None
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::ConstructL()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::~CCRRtspCommand
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CCRRtspCommand::~CCRRtspCommand()
+    {
+    LOG( "CCRRtspCommand::~CCRRtspCommand" );
+    
+    // iRtspText is deleted in base class destructor
+    delete iAuthHeader;
+    delete iMD5Calculator;
+    delete iUserAgent;
+    delete iWapProfile;
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::TryParseL
+// 
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::TryParseL( const TDesC8 &aString ) 
+    {
+    // try to find out if end of the command has been received
+    // "RTSP/1.0 XXX\r\n\r\n" at least..
+    const TInt KDVRMinCommandLen( 14 ); 
+    TInt replyEndOffSet( ( aString.Length() < KDVRMinCommandLen )?
+                           KDVRMinCommandLen: aString.Find( KCR2NewLines() ) ); 
+    if ( replyEndOffSet == KErrNotFound )
+        {
+        // need to have more, do nothing yet
+        LOG( "CCRRtspCommand::TryParseL() out because response not complete" );
+        User::Leave( KErrUnderflow ); 
+        }
+
+    // copy the stuff into local variable:      
+    delete iRtspText; iRtspText = NULL; 
+    iRtspText = aString.AllocL(); 
+    iCommand = ERTSPCommandNOCOMMAND;
+
+    // try each command in order: 
+    if ( iRtspText->Find( KCROPTIONS() ) == 0 )
+        {
+        // it was OPTIONS command
+        LOG( "CCRRtspCommand::TryParseL() -> OPTIONS" );
+        iCommand = ERTSPCommandOPTIONS;
+        }
+    else if ( iRtspText->Find( KCRDESCRIBE() ) == 0 )
+        {
+        LOG( "CCRRtspCommand::TryParseL() -> DESCRIBE" );
+        iCommand = ERTSPCommandDESCRIBE;
+        }  
+    else if ( iRtspText->Find( KCRTEARDOWN() ) == 0 )
+        {
+        LOG( "CCRRtspCommand::TryParseL() -> TEARDOWN" );
+        iCommand = ERTSPCommandTEARDOWN;        
+        }                   
+    else if ( iRtspText->Find( KCRPAUSE() ) == 0 )
+        {
+        LOG( "CCRRtspCommand::TryParseL() -> PAUSE" );
+        iCommand = ERTSPCommandPAUSE;       
+        }                                       
+    else if ( iRtspText->Find( KCRSETUP() ) == 0 )
+        {
+        LOG( "CCRRtspCommand::TryParseL() -> SETUP" );
+        iCommand = ERTSPCommandSETUP;       
+        }
+    else if ( iRtspText->Find( KCRPLAY() ) == 0 )
+        {
+        LOG( "CCRRtspCommand::TryParseL() -> PLAY" );
+        iCommand = ERTSPCommandPLAY;        
+        }  
+    else
+        {
+        User::Leave( KErrNotSupported ); 
+        }
+
+    // then find CSeq
+    FindCSeqL();    
+    // then find session id
+    FindSessionIdL(); 
+    // then find possible content. for commands it is usually not there
+    FindContentL(); 
+    // find URL
+    FindURLL(); 
+    // find possible transport method
+    // IMPORTANT: should be done before parsing client port
+    FindTransport();
+    // find possible client port
+    FindClientPorts();
+    // find possible range-header
+    ParseRange();
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::FindURLL
+// in rtsp the URL is between first and second whitespace.
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::FindURLL( void ) 
+    {
+#ifdef _DEBUG   
+    _LIT( KPanicStr, "RTSPCommon" ); 
+    __ASSERT_DEBUG( iRtspText, 
+                    User::Panic( KPanicStr, KErrBadHandle ) );
+#endif                    
+    
+    iURL.Set( NULL, 0 );
+    TInt spaceOffset( iRtspText->Locate( ' ' ) ); 
+    if ( spaceOffset < 0 ) 
+        {
+        User::Leave( KErrNotSupported ); 
+        }
+        
+    TPtrC8 beginningFromUrl( iRtspText->Right( iRtspText->Length() - 
+                                             ( spaceOffset + 1 ) ) ) ;      
+    spaceOffset = beginningFromUrl.Locate( ' ' ); 
+    if ( spaceOffset < 0 ) 
+        {
+        User::Leave( KErrNotSupported ); 
+        }
+    
+    iURL.Set( beginningFromUrl.Left( spaceOffset ) ); 
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::URL
+//
+// method that returns URL
+// -----------------------------------------------------------------------------
+//  
+TInt CCRRtspCommand::URL( TPtrC8& aURL ) 
+    {
+    if ( iURL.Ptr() != NULL )   
+        {
+        aURL.Set ( iURL ); 
+        return KErrNone;
+        }
+
+    return KErrNotFound; 
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetURL
+//
+// -----------------------------------------------------------------------------
+//  
+void CCRRtspCommand::SetURL ( const TDesC8& aURL ) 
+    {
+    iURL.Set ( aURL ); 
+    }
+    
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetAuthentication
+//
+// -----------------------------------------------------------------------------
+//  
+void CCRRtspCommand::SetAuthentication( TBool aAuth ) 
+    {
+    iAuthenticationNeeded = aAuth;
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetUserAgentL
+//
+// -----------------------------------------------------------------------------
+//  
+void CCRRtspCommand::SetUserAgentL( const TDesC8& aUserAgent )
+    {
+    delete iUserAgent; iUserAgent = NULL;
+    iUserAgent = aUserAgent.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetBandwidth
+//
+// -----------------------------------------------------------------------------
+//  
+void CCRRtspCommand::SetBandwidth( TInt aBandwidth )
+    {
+    iBandwidth = aBandwidth;
+    iBandwidthAvailable = ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetWapProfileL
+//
+// -----------------------------------------------------------------------------
+//  
+void CCRRtspCommand::SetWapProfileL( const TDesC8& aWapProfile )
+    {
+    delete iWapProfile; iWapProfile = NULL;
+    iWapProfile = aWapProfile.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetCommand
+//
+// -----------------------------------------------------------------------------
+//  
+void CCRRtspCommand::SetCommand( TCommand aCommand ) 
+    {
+    iCommand = aCommand; 
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::Command
+//
+// -----------------------------------------------------------------------------
+//  
+CCRRtspCommand::TCommand CCRRtspCommand::Command( void ) const 
+    {
+    return iCommand;    
+    }       
+            
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::ProduceL
+//
+// -----------------------------------------------------------------------------
+//  
+TPtrC8& CCRRtspCommand::ProduceL( void ) 
+    {
+    // First common part for all commands, except actual command
+    delete iRtspText; iRtspText = NULL;
+    iRtspText = HBufC8::NewL( KMaxName );
+    iRtspText->Des().Zero();
+    
+    switch ( iCommand )
+        {
+        case ERTSPCommandOPTIONS:
+            AppendL( iRtspText, KCROPTIONS ); 
+            break;
+        
+        case ERTSPCommandDESCRIBE:
+            AppendL( iRtspText, KCRDESCRIBE ); 
+            break;
+        
+        case ERTSPCommandTEARDOWN:     
+            AppendL( iRtspText, KCRTEARDOWN ); 
+            break;
+        
+        case ERTSPCommandPAUSE:
+            AppendL( iRtspText, KCRPAUSE ); 
+            break;
+        
+        case ERTSPCommandSETUP:        
+            AppendL( iRtspText, KCRSETUP ); 
+            break;
+        
+        case ERTSPCommandPLAY : 
+            AppendL( iRtspText, KCRPLAY ); 
+            break;
+        
+        default:
+            User::Leave( KErrNotSupported ); 
+            break;
+        }
+    
+    AppendL( iRtspText, iURL ); 
+    AppendL( iRtspText, KCRSpace ); 
+    AppendL( iRtspText, KCRRTSP10 ); 
+    AppendL( iRtspText, KCRNewLine ); 
+    AppendL( iRtspText, KCRCSeq ); 
+    AppendNumL( iRtspText, iCSeq );
+    AppendL( iRtspText, KCRNewLine );
+
+    if ( iUserAgent )
+        {
+        TPtrC8 useragent( iUserAgent->Des() );
+        AppendFormatL( iRtspText, KCRRTSPUserAgentHeader, &useragent );
+        }
+
+    // then variable tail depending on command
+    switch ( iCommand )
+        {
+        case ERTSPCommandOPTIONS:
+            if ( iSessionId.Ptr() != NULL ) 
+                {
+                AppendL( iRtspText, KCRSessionStr() ); 
+                AppendL( iRtspText, iSessionId ); // now only session number
+                AppendL( iRtspText, KCRNewLine );                
+                }
+            break;
+        
+        case ERTSPCommandDESCRIBE:
+            {
+            AppendL( iRtspText, KCRAcceptSDP );
+            if ( iWapProfile )
+                {
+                TPtrC8 profile = iWapProfile->Des();
+                AppendFormatL( iRtspText, KCRRTSPXWapProfile, &profile );
+                }
+            if ( iBandwidthAvailable )
+                {
+                AppendFormatL( iRtspText, KCRRTSPBandwidth, iBandwidth );
+                }
+            }
+            break;
+        
+        case ERTSPCommandTEARDOWN:     
+            if ( iSessionId.Ptr() != NULL ) 
+                {
+                AppendL( iRtspText, KCRSessionStr() ); 
+                AppendL( iRtspText, iSessionId ); // now only session number
+                AppendL( iRtspText, KCRNewLine );                
+                }
+            break;
+
+        case ERTSPCommandPAUSE:        
+            if ( iSessionId.Ptr() != NULL ) 
+                {
+                AppendL( iRtspText, KCRSessionStr() ); 
+                AppendL( iRtspText, iSessionId ); // now only session number
+                AppendL( iRtspText, KCRNewLine );                
+                }
+            break;
+
+        case ERTSPCommandSETUP:        
+            {
+            // build transport header according to chosen method
+            switch ( iTransport )
+                {
+                case ERTPOverUDP:
+                    AppendFormatL( iRtspText, KCRTransportHeaderUDP,
+                                   iClientPort, iClientPort + 1 );
+                    break;
+                case ERTPOverTCP:
+                    AppendFormatL( iRtspText, KCRTransportHeaderTCP,
+                                   iClientPort, iClientPort + 1 );
+                    break;
+                
+                case ERTPOverMulticast:
+                    AppendL( iRtspText, KCRTransportHeaderMulticast );
+                    break;
+                }
+
+            // Session: 5273458854096827704         
+            if ( iSessionId.Ptr() != NULL ) 
+                {
+                AppendL( iRtspText, KCRSessionStr ); 
+                AppendL( iRtspText, iSessionId ); // now only session number
+                AppendL( iRtspText, KCRNewLine ); 
+                }
+            if ( iWapProfile )
+                {
+                TPtrC8 profile( iWapProfile->Des() );
+                AppendFormatL( iRtspText, KCRRTSPXWapProfile, &profile );
+                }
+            }
+            break;
+            
+        case ERTSPCommandPLAY: 
+            {
+            if ( !( iLowerRange == KRealZero && iUpperRange == KRealMinusOne ) )
+                {
+                // Range was something else than 0,-1
+                TBuf8<KMaxName> buf( KCRRangeHeader );
+                TRealFormat format( 10, 3 ); 
+                format.iTriLen = 0; 
+                format.iPoint = '.';
+                buf.AppendNum( iLowerRange, format );
+                buf.Append( '-' ); 
+                if ( iUpperRange > KRealZero )
+                    {
+                    buf.AppendNum( iUpperRange, format );
+                    }
+                
+                buf.Append( KCRNewLine );
+                AppendL( iRtspText, buf );
+                }
+            if ( iSessionId.Ptr() != NULL ) 
+                {
+                AppendL( iRtspText, KCRSessionStr() ); 
+                AppendL( iRtspText, iSessionId ); // now only session number
+                AppendL( iRtspText, KCRNewLine ); 
+                }
+            }
+            break;
+
+        default:
+            User::Leave( KErrNotSupported ); 
+            break;
+        }           
+    
+    if ( iAuthenticationNeeded )
+        {
+        TBool useDigest( EFalse );
+        
+        if ( iAuthType && ( iAuthType->FindC( KCRAuthDigest ) != KErrNotFound ) )
+            {
+            useDigest = ETrue;
+            }
+        
+        switch ( iCommand )
+            {
+            case ERTSPCommandOPTIONS :
+                useDigest ? CalculateDigestResponseL( KCROPTIONSNoSpace ) :
+                            CalculateBasicResponseL( KCROPTIONSNoSpace );
+                
+                if ( iAuthHeader ) 
+                    {
+                    AppendL( iRtspText, iAuthHeader->Des() );
+                    }
+                break;
+            
+            case ERTSPCommandDESCRIBE :
+                useDigest ? CalculateDigestResponseL( KCRDESCRIBENoSpace ) :
+                            CalculateBasicResponseL( KCRDESCRIBENoSpace );  
+               
+                if ( iAuthHeader ) 
+                    {
+                    AppendL( iRtspText, iAuthHeader->Des() );
+                    }
+                break;
+            
+            case ERTSPCommandTEARDOWN :     
+                useDigest ? CalculateDigestResponseL( KCRTEARDOWNNoSpace ) :
+                            CalculateBasicResponseL( KCRTEARDOWNNoSpace );
+                
+                if ( iAuthHeader ) 
+                    {               
+                    AppendL( iRtspText, iAuthHeader->Des() );
+                    }
+                break;
+            
+            case ERTSPCommandPAUSE :        
+                useDigest ? CalculateDigestResponseL( KCRPAUSENoSpace ) :
+                            CalculateBasicResponseL( KCRPAUSENoSpace );
+                
+                if ( iAuthHeader ) 
+                    {           
+                    AppendL( iRtspText, iAuthHeader->Des() );
+                    }
+                break;
+            
+            case ERTSPCommandSETUP :        
+                useDigest ? CalculateDigestResponseL( KCRSETUPNoSpace ) :
+                            CalculateBasicResponseL( KCRSETUPNoSpace );
+                
+                if ( iAuthHeader ) 
+                    {
+                    AppendL( iRtspText, iAuthHeader->Des() );
+                    }
+                break;
+            
+            case ERTSPCommandPLAY :  
+                useDigest ? CalculateDigestResponseL( KCRPLAYNoSpace ) :
+                            CalculateBasicResponseL( KCRPLAYNoSpace );
+                
+                if ( iAuthHeader ) 
+                    {           
+                    AppendL( iRtspText, iAuthHeader->Des() );
+                    }
+                break;
+            
+            default:
+                User::Leave( KErrNotSupported ); 
+                break;
+            }       
+        }
+        
+    AppendL( iRtspText, KCRNewLine ); 
+    iProductDescriptor.Set( *iRtspText );
+    return iProductDescriptor;
+    }   
+    
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::AppendL
+//
+// -----------------------------------------------------------------------------
+//      
+void CCRRtspCommand::AppendL( HBufC8*& aBuffer, const TDesC8& aStr )
+    {
+    TPtr8 ptr( aBuffer->Des() );
+    if ( ( ptr.Length() + aStr.Length() ) >= ptr.MaxLength() )
+        {
+        const TInt newLength( ptr.Length() + aStr.Length() + KMaxName );
+        aBuffer = aBuffer->ReAllocL( newLength );
+        ptr.Set( aBuffer->Des() );
+        }
+    
+    ptr.Append( aStr );
+    }
+    
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::AppendNumL
+//
+// -----------------------------------------------------------------------------
+//      
+void CCRRtspCommand::AppendNumL( HBufC8*& aBuffer, const TInt aNum )
+    {
+    TPtr8 ptr( aBuffer->Des() );
+    if ( ( ptr.Length() + KMaxInfoName ) >= ptr.MaxLength() )
+        {
+        const TInt newLength( ptr.Length() + KMaxInfoName + KMaxName );
+        aBuffer = aBuffer->ReAllocL( newLength );
+        ptr.Set( aBuffer->Des() );
+        }
+    
+    ptr.AppendNum( aNum );
+    }
+    
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::AppendFormatL
+//
+// -----------------------------------------------------------------------------
+//      
+void CCRRtspCommand::AppendFormatL(
+    HBufC8*& aBuffer,
+    TRefByValue<const TDesC8> aFmt, ... )
+    {
+    VA_LIST list;
+    VA_START( list, aFmt );
+    HBufC8* buf = HBufC8::NewLC( KMaxDataSize );
+    buf->Des().FormatList( aFmt, list );
+    VA_END( list );
+
+    TPtr8 ptr( aBuffer->Des() );
+    if ( ( ptr.Length() + buf->Length() ) >= ptr.MaxLength() )
+        {
+        const TInt newLength( ptr.Length() + buf->Length() + KMaxName );
+        aBuffer = aBuffer->ReAllocL( newLength );
+        ptr.Set( aBuffer->Des() );
+        }
+    
+    ptr.Append( *buf );
+    CleanupStack::PopAndDestroy( buf );
+    }
+    
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::Hash
+// Calculates hash value ( from S60 HttpFilters )
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::HashL( const TDesC8& aMessage, TDes8& aHash )
+    {
+    LOG( "CCRRtspCommand::HashL() in" );
+    // check if md5 calculator is already constructed
+    if ( !iMD5Calculator )
+        { 
+        iMD5Calculator = CMD5::NewL();
+        }
+    // Calculate the 128 bit (16 byte) hash
+    iMD5Calculator->Reset();
+    TPtrC8 hash = iMD5Calculator->Hash( aMessage );
+    
+    // Now print it as a 32 byte hex number
+    aHash.Zero();
+    _LIT8( formatStr, "%02x" );
+    TBuf8<2> scratch;
+    for ( TInt i( 0 ); i < KCRRawHashLength; i++ )
+        {
+        scratch.Zero();
+        scratch.Format( formatStr, hash[i] );
+        aHash.Append( scratch );
+        }
+    
+    LOG( "CCRRtspCommand::HashL() out" );
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::CalculateBasicResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::CalculateBasicResponseL( const TDesC8& /*aMethod*/ )
+    {
+    LOG( "CCRRtspCommand::CalculateBasicResponseL() in" );
+    
+    if ( !( iUserName && iPassword  ) )
+        {
+        LOG( "CCRRtspCommand::CalculateBasicResponseL() out, username or password not set" );
+        delete iAuthHeader; 
+        iAuthHeader = NULL;
+        return; // no can do
+        }
+    
+    HBufC8* plainData = HBufC8::NewL( iUserName->Length() + 1 + // ':'
+                                      iPassword->Length() );
+    
+    CleanupStack::PushL( plainData );
+    
+    plainData->Des().Append( *iUserName );
+    plainData->Des().Append( ':' );
+    plainData->Des().Append( *iPassword );
+    
+    // Max size = ((Bytes + 3 - (Bytes MOD 3)) /3) x 4 
+    TInt base64MaxSize = ( ( plainData->Length() + 3 - 
+            ( plainData->Length() % 3 ) ) / 3 ) * 4;
+    
+    HBufC8* encodedData = HBufC8::NewL( base64MaxSize );
+    TPtr8 dataPrt( encodedData->Des() );   
+    CleanupStack::PushL( encodedData );
+    
+    TImCodecB64 b64enc;
+    b64enc.Initialise();
+    b64enc.Encode( *plainData, dataPrt );
+    
+    delete iAuthHeader; 
+    iAuthHeader = NULL;
+    iAuthHeader = HBufC8::NewL( KCRAuthorizationBasicHeader().Length() + encodedData->Length() );           
+    iAuthHeader->Des().Format( KCRAuthorizationBasicHeader, encodedData );
+    
+    CleanupStack::PopAndDestroy( encodedData );
+    CleanupStack::PopAndDestroy( plainData );
+    
+    LOG( "CCRRtspCommand::CalculateBasicResponseL() out" );
+    }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::CalculateDigestResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::CalculateDigestResponseL( const TDesC8& aMethod )
+    {
+    LOG( "CCRRtspCommand::CalculateDigestResponseL() in" );
+
+    if ( !( iUserName && iPassword && iNonce && iOpaque && iRealm && iUri ) )
+        {
+        LOG( "CCRRtspCommand::CalculateDigestResponseL() out, username or password not set" );
+        delete iAuthHeader; iAuthHeader = NULL;
+        return; // no can do
+        }
+
+    TBuf8<KCRHashLength> hash1;
+    TBuf8<KCRHashLength> hash2;
+    TBuf8<KCRHashLength> finalHash;
+
+    // calculate the hash1 using "username:realm:password"
+    HBufC8* hashPtr = HBufC8::NewL ( iUserName->Length() + 1 +  // ':'
+                                     iRealm->Length() + 1 +      // ':' 
+                                     iPassword->Length() );
+    hashPtr->Des().Append( *iUserName );
+    hashPtr->Des().Append( ':' );
+    hashPtr->Des().Append( *iRealm );
+    hashPtr->Des().Append( ':' );
+    hashPtr->Des().Append( *iPassword );
+    
+    HashL( *hashPtr, hash1 );
+    delete hashPtr; hashPtr = NULL;
+
+    // calculate hash2 using "Method:uri"
+    HBufC8* hashPtr2 = HBufC8::NewL(aMethod.Length() + 1 + iUri->Length() );
+    hashPtr2->Des().Append( aMethod );
+    hashPtr2->Des().Append( ':' );
+    hashPtr2->Des().Append( *iUri );
+    
+    HashL( *hashPtr2, hash2 );
+    delete hashPtr2; hashPtr2 = NULL;
+
+    // calculate finalHash to be sent to remote server using
+    // hash1 + ":" + nonce + ":" + hash2
+    HBufC8* hashPtr3 = HBufC8::NewL( hash1.Length() + 1 + // ':'
+                                     iNonce->Length() + 1 + // ':'
+                                     hash2.Length() );
+    hashPtr3->Des().Append( hash1 );
+    hashPtr3->Des().Append( ':' );
+    hashPtr3->Des().Append( *iNonce );
+    hashPtr3->Des().Append( ':' );
+    hashPtr3->Des().Append( hash2 );
+
+    HashL( *hashPtr3, finalHash );
+    delete hashPtr3; hashPtr3 = NULL;
+
+    // generate the authentication header 
+    if ( iOpaque->Length()  ) 
+        {
+        delete iAuthHeader; iAuthHeader = NULL;
+        iAuthHeader = HBufC8::NewL( KCRAuthorizationHeader().Length() + 
+            iUserName->Length() + iRealm->Length() + iNonce->Length() +
+            iUri->Length() + finalHash.Length() + iOpaque->Length() );
+        
+        iAuthHeader->Des().Format( KCRAuthorizationHeader, iUserName,
+            iRealm, iNonce, iUri, &finalHash, iOpaque );
+        }
+    else
+        {
+        delete iAuthHeader; iAuthHeader = NULL;
+        iAuthHeader = HBufC8::NewL( KCRAuthorizationHeaderNoOpaque().Length() +
+            iUserName->Length() + iRealm->Length() + iNonce->Length() +
+            iUri->Length() + finalHash.Length() );
+                                    
+        iAuthHeader->Des().Format( KCRAuthorizationHeaderNoOpaque, iUserName,
+            iRealm, iNonce, iUri, &finalHash );
+        }
+
+    LOG( "CCRRtspCommand::CalculateDigestResponseL() out" );   
+    }
+
+//  End of File