diff -r 000000000000 -r f5a58ecadc66 upnp/upnpstack/dlnawebserver/src/upnphttpchunkfiletransferreader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnp/upnpstack/dlnawebserver/src/upnphttpchunkfiletransferreader.cpp Tue Feb 02 01:12:20 2010 +0200 @@ -0,0 +1,360 @@ +/** @file +* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: CUpnpHttpChunkFileTransferReader is a class responsible for +* asynchronous TCP reading and controlling data +* +*/ + + + +#include "upnphttpsession.h" +#define KLogFile _L("DLNAWebServer.txt") +#include "upnpcustomlog.h" +#include "upnphttpfiletransferreader.h" +#include "upnphttpchunkfiletransferreader.h" +#include "upnphttpchunkparser.h" +#include "upnphttpfileaccess.h" +#include "inet6err.h" + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::NewL +// Factory method. +// --------------------------------------------------------------------------- +// +CUpnpHttpChunkFileTransferReader* CUpnpHttpChunkFileTransferReader::NewL( + CUpnpTcpSession& aSession, + RSocket& aSocket, + TThreadPriority aPriority, + TInt aReadPortion, + TInt aBufferSize) + { + CUpnpHttpChunkFileTransferReader* self = new ( ELeave ) + CUpnpHttpChunkFileTransferReader( aSession, aSocket, + aPriority, aReadPortion, aBufferSize); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::CUpnpHttpChunkFileTransferReader +// C++ constructor. +// --------------------------------------------------------------------------- +// +CUpnpHttpChunkFileTransferReader::CUpnpHttpChunkFileTransferReader( CUpnpTcpSession& aSession, + RSocket& aSocket, + TThreadPriority aPriority, + TInt aReadPortion, + TInt aBufferSize) + :CUpnpHttpFileTransferReader( aSession, aSocket, + aPriority, aReadPortion, aBufferSize + aReadPortion), + iDecoded(0) + { + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::ConstructL +// Two-phased constructor +// constructor that can leave. Used from derived classes. +// --------------------------------------------------------------------------- +// +void CUpnpHttpChunkFileTransferReader::ConstructL() + { + BaseConstructL(); + + iParser = CUpnpHttpChunkParser::NewL(); + } +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::~CUpnpHttpChunkFileTransferReader +// Destructor. +// --------------------------------------------------------------------------- +// +CUpnpHttpChunkFileTransferReader::~CUpnpHttpChunkFileTransferReader() + { + delete iParser; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::RemainingBytes +// Returns the remaining numbers of bytes to read +// --------------------------------------------------------------------------- +// +TInt CUpnpHttpChunkFileTransferReader::RemainingBytes() + { + if( !iSession.FileAccess() ) + return KErrNone; + + return ( iSession.FileAccess()->TransferTotal()-iSession.FileAccess()->BytesWritten() ); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferReader::Start +// Starts reading. +// --------------------------------------------------------------------------- +// +void CUpnpHttpChunkFileTransferReader::StartL() + { + LOGS1( "%i, CUpnpHttpFileTransferReader::Start", iSession.Id() ); + + // Initiate a new read from socket into iBuffer + if ( !IsActive() ) + { + + //checks buffer buffer is not empty + if(iCacheBuffer.Length() > 0) + { + //check buffer session should be finished + iIsFinished = HandleL(); + if(iIsFinished) + { + Finish(); + + if( iSession.FileAccess() ) + iSession.FileAccess()->SetChunkCompleted( iIsFinished ); + } + //if not issue reading + else + { + IssueRead(); + iSession.StartTimeoutTimer(ETrue); + } + + } + else + { + IssueRead(); + } + + } + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::ReadBufferSize +// Returns the maximum size of bytes to read for once +// --------------------------------------------------------------------------- +// +TInt CUpnpHttpChunkFileTransferReader::ReadBufferSize() + { + return(AvailableSpace()); + } + +// ----------------------------------------------------------------------------- +// CUpnpHttpChunkParser::Parse +// Decoding the chunked-encoded buffer +// ----------------------------------------------------------------------------- +// +TInt CUpnpHttpChunkFileTransferReader::Parse( TDes8& aBuffer, TInt& aPos ) + { + if( aPos >= aBuffer.Length() ) + { + iParser->SetErrorState(); + return ETrue; + } + return iParser->Parse( aBuffer, aPos ); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::HandleL +// Handles data in buffer, returns if file transfer has finished +// --------------------------------------------------------------------------- +// +TBool CUpnpHttpChunkFileTransferReader::HandleL() + { + TInt error = KErrGeneral; + + error = Parse(iCacheBuffer, iDecoded); + + if( error == KErrNone && iSession.FileAccess() ) + { + if ( iSession.FileAccess()->TransferTotal() == KErrNotFound ) + { + iSession.FileAccess()->SetTransferTotal( 0 ); + } + //parser finished decoding - writing all bytes + if ( iParser->IsFinished() ) + { + error = HandleReadDataL( iDecoded ); + } + //buffer almost full - writing a fixed block of decoded data + else if ( iBufferSize - iDecoded <= iReadBufferSize ) + { + error = HandleReadDataL( iBufferSize - iReadBufferSize ); + } + } + iCacheBuffer.ReAllocL( iBufferSize ); + + if( error != KErrNone ) + { + iSession.FileTransferReaderErrorL( error ); + return ETrue; + } + else if( iParser->IsFinished() ) + { + if ( iSession.FileAccess() ) + { + iSession.FileAccess()->SetChunkCompleted( ETrue ); + } + iSession.FileTransferReaderDoneL(); + return ETrue; + } + + return EFalse; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::HandleReadDataL +// Handles read data - trims the buffer and save data to file +// --------------------------------------------------------------------------- +// +TInt CUpnpHttpChunkFileTransferReader::HandleReadDataL( TInt aPieceToRead ) + { + //reads decoded data + TPtr8 ptr = iCacheBuffer.LeftTPtr( aPieceToRead ); + + //saves decoded data + TInt error = iSession.FileAccess()->SaveL( ptr ); + iSession.FileAccess()->SetTransferTotal( + iSession.FileAccess()->TransferTotal() + aPieceToRead ); + + //saved data are cut from buffer + iCacheBuffer.Delete( 0, aPieceToRead ); + + //position adjusted to the number of still encoded bytes + iDecoded -= aPieceToRead; + + return error; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::Finish +// On finishing the file transfer +// --------------------------------------------------------------------------- +// +void CUpnpHttpChunkFileTransferReader::Finish() + { + CUpnpHttpFileTransferReader::Finish(); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::RunL +// From class CActive. +// Function is called as a callback when the issued reading is completed. +// --------------------------------------------------------------------------- +// +void CUpnpHttpChunkFileTransferReader::RunL() + { + LOGS2( "%i, CUpnpHttpChunkFileTransferReader::RunL(), iStatus %i", + iSession.Id(), iStatus.Int() ); + + // Active object request complete handler + switch ( iStatus.Int() ) + { + case KErrNone: + iRetryErrorCount = 0; + iCancelTimer->Cancel(); + + iSession.TimerCancel(); + iCacheBuffer.SetLength( iCacheBuffer.Length() + iLen() ); + iIsFinished = HandleL(); + + if(!iIsFinished) + { + IssueRead(); + iSession.StartTimeoutTimer(ETrue); + } + else + Finish(); + break; + + case KErrCancel: + if(iCancelFromTimer) + { + IssueRead(); + iCancelFromTimer = EFalse; + } + break; + case KErrEof: + iSession.TimerCancel(); + iCacheBuffer.SetLength( iLen() ); + iIsFinished = HandleL(); + + if(iIsFinished) + { + iSession.HandleErrorL( iStatus.Int() ); + break; + } + case KErrNoMemory: + case KErrNotReady: + case KErrInet6AddressExpired: + if( iRetryErrorCount < KMaxRetryErrors ) + { + iRetryTimer->Cancel(); + iRetryTimer->After( KRetryWaitTime * ++iRetryErrorCount, EFalse ); + break; + } + + default: + iIsFinished = ETrue; + iIsActivated = EFalse; + iSession.HandleErrorL( iStatus.Int() ); + break; + } + if( iSession.FileAccess() ) + iSession.FileAccess()->SetChunkCompleted( iIsFinished ); + } + +// ----------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::RunError +// From CActive. +// Invoked when RunL leaves. +// ----------------------------------------------------------------------------- +// +TInt CUpnpHttpChunkFileTransferReader::RunError( TInt aErr ) + { + LOGS1("CUpnpHttpChunkFileTransferReader::RunError(%d)", aErr); + return KErrNone; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::Reset +// Makes reader ready to start reading new content +// --------------------------------------------------------------------------- +// +void CUpnpHttpChunkFileTransferReader::Reset() + { + iCacheBuffer.SetLength(0); + iDecoded = 0; + iParser->Reset(); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpChunkFileTransferReader::ReadFromSocket +// Reads from the socket +// --------------------------------------------------------------------------- +// +void CUpnpHttpChunkFileTransferReader::ReadFromSocket() + { + Deque(); + CActiveScheduler::Add(this); + + iReceivePtr.Set( (TUint8*)iCacheBuffer.RightTPtr( 0 ).Ptr(), ReadBufferSize(), ReadBufferSize() ); + StartCancelTimer(); + iSocket.RecvOneOrMore( iReceivePtr,0,iStatus,iLen); + SetActive(); + } + +// End of File