diff -r 000000000000 -r f5a58ecadc66 upnp/upnpstack/dlnawebserver/src/upnphttpfiletransferwriter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnp/upnpstack/dlnawebserver/src/upnphttpfiletransferwriter.cpp Tue Feb 02 01:12:20 2010 +0200 @@ -0,0 +1,448 @@ +/** @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: CUpnpHttpFileTransferWriter is a class responsible for +* asynchronous writing to a socket owned by CUpnpTcpSession. +* +*/ + + + +#include "upnptcpsession.h" +#include "upnphttpfiletransferwriter.h" +#include "upnphttpfileaccess.h" +#define KLogFile _L("DLNAWebServer.txt") +#include "upnpcustomlog.h" + + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::NewL +// Factory method. +// --------------------------------------------------------------------------- +// +CUpnpHttpFileTransferWriter* CUpnpHttpFileTransferWriter::NewL( CUpnpTcpSession& aSession, + RSocket& aSocket, + TThreadPriority aPriority, + TInt aWriteSize ) + { + CUpnpHttpFileTransferWriter* self = new ( ELeave ) + CUpnpHttpFileTransferWriter( aSession, aSocket, aPriority, aWriteSize ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::CUpnpHttpFileTransferWriter +// C++ constructor. +// --------------------------------------------------------------------------- +// +CUpnpHttpFileTransferWriter::CUpnpHttpFileTransferWriter( CUpnpTcpSession& aSession, + RSocket& aSocket, + TThreadPriority aPriority, + TInt aWriteSize ) + :CActive( aPriority ), + iSocket( aSocket ), + iSession( aSession ), + iState(EUnknown), + iSendPointer(NULL,0), + iWriteSize(aWriteSize) + { + LOGS1( "%i, CUpnpHttpFileTransferWriter::CUpnpHttpFileTransferWriter", iSession.Id() ); + // No implementation required + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::ConstructL +// Two-phased constructor +// constructor that can leave. Used from derived classes. +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::ConstructL() + { + CActiveScheduler::Add( this ); + iRetryWrite = CUpnpRetryWrite::NewL( iSession, iSocket, this, (TThreadPriority)Priority() ); + + iSendBuffer.CreateL( iWriteSize ); + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::~CUpnpTcpSessionReader +// Destructor. +// --------------------------------------------------------------------------- +// +CUpnpHttpFileTransferWriter::~CUpnpHttpFileTransferWriter() + { + Cancel(); + + iSendBuffer.Close(); + + delete iRetryWrite; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::DoCancel +// From class CActive +// Cancels issued writing request. +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::DoCancel() + { + LOGS1( "%i, CUpnpHttpFileTransferWriter::DoCancel", iSession.Id() ); + + iState = ECancelled; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::RunL +// From class CActive +// Function called when issued writing is completed. Function checks if there +// are any write requests left to send and if there are then it issues writing. +// If queue is empty then function informs upper layer that writing is completed. +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::RunL() + { + LOGS2( "%i, CUpnpHttpFileTransferWriter::RunL(), iStatus %i", + iSession.Id() , iStatus.Int() ); + + // Active object request complete handler + if ( iStatus == KErrNone ) + { + switch( iState ) + { + // Character has been written to socket + case EHeaders: + //100-continue not expected + if(!iSession.FileAccess()) + { + Cancel(); + break; + } + else + { + iState = EContent; + } + case EContent: + SendNextPortionL(); + + break; + case EFinished: + iSession.FileTransferWriterDoneL(); + + iSession.StartTimeoutTimer(EFalse); + FinishL(); + //export finished + break; + + default: + break; + }; + } + else + { + if( (iState == EHeaders || iState == EContent || iState == EFinished) && + (iStatus.Int() == KErrNoMemory || iStatus.Int() == KErrNotReady ) ) + { + iRetryWrite->IssueWriteRetry(); + } + else + { + // Error: pass it up to session + iSession.HandleErrorL( iStatus.Int() ); + iState = ECancelled; + } + } + } + +// ----------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::RunError +// RunError is called when RunL leaves. +// ----------------------------------------------------------------------------- +// +TInt CUpnpHttpFileTransferWriter::RunError( TInt aError ) + { + LOGS2( "%i, CUpnpHttpFileTransferWriter::RunError %d" + , iSession.Id() , aError); + + iState = EFinished; + + TRAP_IGNORE( HandleErrorL() ); + iSession.StartClosingSession(); + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::SendNextWriteRequestL +// Function checks if there are any write requests left and if there are then +// issues writing and removes this request from queue. +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::SendNextPortionL() + { + LOGS2( "%i, CUpnpHttpFileTransferWriter::SendNextPortionL(), iState %i", + iSession.Id() , iState ); + + if( iSession.FileAccess() ) + { + if( iState == EContent ) + if( !IsActive() ) + { + iSendPointer.Set( (TUint8*)iSendBuffer.Ptr(),0,iSendBuffer.MaxLength() ); + if( iSession.FileAccess()->GetL(iSendPointer,iSendBuffer.MaxLength()) ) + { + iState = EFinished; + } + + + iSession.TimerCancel(); + WriteToSocket(); + iSession.StartTimeoutTimer(ETrue); + + } + } + else + { + Cancel(); + } + + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::StartL +// Passes control to the reader +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::StartL() + { + iWaiting = EFalse; + switch(iState) + { + case EUnknown: + + iState = EHeaders; + SendHeadersL(); + break; + case EHeaders: + + if(iSession.FileAccess()->HeadersSent()) + { + iState = EContent; + SendNextPortionL(); + } + else + SendHeadersL(); + break; + + default: + break; + } + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::StartL +// Sends the HTTP headers of the content +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::SendHeadersL() + { + if(iState == EHeaders) + if( iSession.FileAccess() ) + if(!IsActive()) + { + //in case session not connected,waiting... + if(!iSession.IsConnected()) + { + iWaiting = ETrue; + return; + } + iSendBuffer.Zero(); + + if ( ( iSession.FileAccess()->GetHeaders().Length() - + iSession.FileAccess()->TransferredBytes()) <= + iSendBuffer.MaxLength() ) + { + TPtrC8 headerPointer; + headerPointer.Set(iSession.FileAccess()->GetHeaders()); + headerPointer.Set( headerPointer.Right( + iSession.FileAccess()->GetHeaders().Length()- + iSession.FileAccess()->TransferredBytes()) ); + + iSendBuffer.Append( headerPointer ); + iSession.FileAccess()->SetHeadersSent(); + + // Adding file content to the header + TInt length = iSendBuffer.MaxLength()-iSendBuffer.Length(); + + HBufC8* tmpBuffer = HBufC8::NewLC(length); + + iSendPointer.Set(tmpBuffer->Des()); + if( iSession.FileAccess()->GetL(iSendPointer,length) ) + { + iState = EFinished; + } + iSendBuffer.Append(iSendPointer); + CleanupStack::PopAndDestroy( tmpBuffer ); + } + else + { + TPtrC8 headerPointer; + headerPointer.Set( iSession.FileAccess()->GetHeaders() ); + headerPointer.Set( headerPointer.Right( + iSession.FileAccess()->GetHeaders().Length() - + iSession.FileAccess()->TransferredBytes() ) ); + headerPointer.Set( headerPointer.Left( + iSendBuffer.Length() ) ); + + iSendBuffer.Append( headerPointer ); + iSession.FileAccess()->SetPosOfHeader( + iSession.FileAccess()->TransferredBytes() + headerPointer.Length() ); + } + + iSendPointer.Set((TUint8*)iSendBuffer.Ptr(),iSendBuffer.Length(),iSendBuffer.MaxLength()); + + iSession.TimerCancel(); + WriteToSocket(); + iSession.StartTimeoutTimer(ETrue); + + if(!iHttpPostStarted) + { + iSession.NotifyUpperLayersOnPostL(); + iHttpPostStarted = ETrue; + } + + } + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::Reset +// Resets the state of the writer +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::Reset() + { + iState = EUnknown; + iHttpPostStarted = ETrue; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::WriteToSocket +// Writes data to socket +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::WriteToSocket() + { + Deque(); + CActiveScheduler::Add(this); + + iSocket.Write(iSendPointer,iStatus); + SetActive(); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::IsWaiting +// Checks if file transfer writer is in use +// --------------------------------------------------------------------------- +// +TBool CUpnpHttpFileTransferWriter::IsWaiting() + { + return iWaiting; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::IsActivated +// Writes data to socket +// --------------------------------------------------------------------------- +// +TBool CUpnpHttpFileTransferWriter::IsActivated() + { + return (!iWaiting && iState!=EUnknown); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::IsRetrying +// if waiting to retry writing to a socket +// --------------------------------------------------------------------------- +// +TBool CUpnpHttpFileTransferWriter::IsRetrying() + { + return (iRetryWrite->IsStarted()); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::IsCancelled +// Checks if transfer is cancelled +// --------------------------------------------------------------------------- +// +TBool CUpnpHttpFileTransferWriter::IsCancelled() + { + return (iState== ECancelled); + } +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::FinishL +// Finishes download +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::FinishL() + { + iSession.FileTransferWriterHandleMoreL(); + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::HandleErrorL +// Handles RunL error +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::HandleErrorL() + { + iSession.FileTransferWriterDoneL(); // 200ok to upper layers + delete iFileServe + FinishL(); // serving uotstanding requests + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::SetPostNotify +// Post notify will be sent +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::SetPostNotify() + { + iHttpPostStarted = EFalse; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::RetryWriteFailL +// +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::RetryWriteFailL( TInt aError ) + { + // Error: pass it up to session + iSession.HandleErrorL( aError ); + iState = ECancelled; + } + +// --------------------------------------------------------------------------- +// CUpnpHttpFileTransferWriter::RetryWriteSucceed +// +// --------------------------------------------------------------------------- +// +void CUpnpHttpFileTransferWriter::RetryWriteSucceed() + { + WriteToSocket(); + } + +// End of File