diff -r 798ee5f1972c -r 826cea16efd9 dvrengine/CommonRecordingEngine/src/CCRRTSPCommand.cpp --- a/dvrengine/CommonRecordingEngine/src/CCRRTSPCommand.cpp Thu Aug 19 10:54:18 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,761 +0,0 @@ -/* -* 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 -#include -#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 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 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 hash1; - TBuf8 hash2; - TBuf8 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