upnp/upnpstack/dlnawebserver/src/upnphttpchunkfiletransferreader.cpp
changeset 0 f5a58ecadc66
--- /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