upnp/upnpstack/dlnawebserver/src/upnphttpchunkfiletransferreader.cpp
changeset 0 f5a58ecadc66
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 /** @file
       
     2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies  this distribution, and is available 
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  CUpnpHttpChunkFileTransferReader is a class responsible for 
       
    15 *                asynchronous TCP reading and controlling data
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "upnphttpsession.h"
       
    22 #define KLogFile _L("DLNAWebServer.txt")
       
    23 #include "upnpcustomlog.h"
       
    24 #include "upnphttpfiletransferreader.h"
       
    25 #include "upnphttpchunkfiletransferreader.h"
       
    26 #include "upnphttpchunkparser.h"
       
    27 #include "upnphttpfileaccess.h"
       
    28 #include "inet6err.h"
       
    29 
       
    30 // ======== MEMBER FUNCTIONS ========
       
    31 
       
    32 // ---------------------------------------------------------------------------
       
    33 // CUpnpHttpChunkFileTransferReader::NewL
       
    34 // Factory method.
       
    35 // ---------------------------------------------------------------------------
       
    36 //
       
    37 CUpnpHttpChunkFileTransferReader* CUpnpHttpChunkFileTransferReader::NewL( 
       
    38                                                     CUpnpTcpSession& aSession,
       
    39                                                     RSocket& aSocket,
       
    40                                                     TThreadPriority aPriority,
       
    41                                                     TInt aReadPortion,
       
    42                                                     TInt aBufferSize)
       
    43     {
       
    44     CUpnpHttpChunkFileTransferReader* self = new ( ELeave ) 
       
    45                     CUpnpHttpChunkFileTransferReader( aSession, aSocket,
       
    46                                              aPriority, aReadPortion, aBufferSize);
       
    47     CleanupStack::PushL( self );
       
    48     self->ConstructL();
       
    49     CleanupStack::Pop( self );
       
    50     return self;
       
    51     }
       
    52     
       
    53 // ---------------------------------------------------------------------------
       
    54 // CUpnpHttpChunkFileTransferReader::CUpnpHttpChunkFileTransferReader
       
    55 // C++ constructor.
       
    56 // ---------------------------------------------------------------------------
       
    57 //
       
    58 CUpnpHttpChunkFileTransferReader::CUpnpHttpChunkFileTransferReader( CUpnpTcpSession& aSession,
       
    59                                               RSocket& aSocket,
       
    60                                               TThreadPriority aPriority,
       
    61                                               TInt aReadPortion,
       
    62                                               TInt aBufferSize)
       
    63     :CUpnpHttpFileTransferReader( aSession, aSocket,
       
    64                aPriority, aReadPortion, aBufferSize + aReadPortion),
       
    65     iDecoded(0)
       
    66     {        
       
    67     }
       
    68 
       
    69 // ---------------------------------------------------------------------------
       
    70 // CUpnpHttpChunkFileTransferReader::ConstructL
       
    71 // Two-phased constructor
       
    72 // constructor that can leave. Used from derived classes.
       
    73 // ---------------------------------------------------------------------------
       
    74 //
       
    75 void CUpnpHttpChunkFileTransferReader::ConstructL()
       
    76     {   
       
    77     BaseConstructL();
       
    78     
       
    79     iParser = CUpnpHttpChunkParser::NewL();
       
    80     }    
       
    81 // ---------------------------------------------------------------------------
       
    82 // CUpnpHttpChunkFileTransferReader::~CUpnpHttpChunkFileTransferReader
       
    83 // Destructor.
       
    84 // ---------------------------------------------------------------------------
       
    85 //
       
    86 CUpnpHttpChunkFileTransferReader::~CUpnpHttpChunkFileTransferReader()
       
    87     {        
       
    88     delete iParser;    
       
    89     }
       
    90 
       
    91 // ---------------------------------------------------------------------------
       
    92 // CUpnpHttpChunkFileTransferReader::RemainingBytes
       
    93 // Returns the remaining numbers of bytes to read
       
    94 // ---------------------------------------------------------------------------
       
    95 //
       
    96 TInt CUpnpHttpChunkFileTransferReader::RemainingBytes()
       
    97     {
       
    98     if( !iSession.FileAccess() )
       
    99         return KErrNone;
       
   100 
       
   101     return ( iSession.FileAccess()->TransferTotal()-iSession.FileAccess()->BytesWritten() );
       
   102     }
       
   103     
       
   104 // ---------------------------------------------------------------------------
       
   105 // CUpnpHttpFileTransferReader::Start
       
   106 // Starts reading.
       
   107 // ---------------------------------------------------------------------------
       
   108 //    
       
   109 void CUpnpHttpChunkFileTransferReader::StartL()
       
   110     {    
       
   111     LOGS1( "%i, CUpnpHttpFileTransferReader::Start", iSession.Id() );
       
   112     
       
   113     // Initiate a new read from socket into iBuffer
       
   114     if ( !IsActive() )
       
   115     {
       
   116           
       
   117           //checks buffer buffer is not empty   
       
   118          if(iCacheBuffer.Length() > 0) 
       
   119             {
       
   120             //check buffer session should be finished
       
   121             iIsFinished = HandleL();
       
   122             if(iIsFinished)
       
   123                 {
       
   124                 Finish();
       
   125 
       
   126                 if( iSession.FileAccess() )
       
   127                     iSession.FileAccess()->SetChunkCompleted( iIsFinished );
       
   128                 }
       
   129             //if not issue reading
       
   130             else
       
   131                 {
       
   132                 IssueRead();
       
   133                 iSession.StartTimeoutTimer(ETrue);
       
   134                 }
       
   135         
       
   136             }
       
   137         else
       
   138             {
       
   139             IssueRead();
       
   140             }
       
   141         
       
   142     }
       
   143     } 
       
   144 
       
   145 // ---------------------------------------------------------------------------
       
   146 // CUpnpHttpChunkFileTransferReader::ReadBufferSize
       
   147 // Returns the maximum size of bytes to read for once
       
   148 // ---------------------------------------------------------------------------
       
   149 //
       
   150 TInt CUpnpHttpChunkFileTransferReader::ReadBufferSize()
       
   151     {
       
   152     return(AvailableSpace());
       
   153     }
       
   154         
       
   155 // -----------------------------------------------------------------------------
       
   156 // CUpnpHttpChunkParser::Parse
       
   157 // Decoding the chunked-encoded buffer
       
   158 // -----------------------------------------------------------------------------
       
   159 //
       
   160 TInt CUpnpHttpChunkFileTransferReader::Parse( TDes8& aBuffer, TInt& aPos )
       
   161     {    
       
   162     if( aPos >= aBuffer.Length() )
       
   163         {
       
   164         iParser->SetErrorState();
       
   165         return ETrue;
       
   166         }
       
   167     return iParser->Parse( aBuffer, aPos );
       
   168     }
       
   169     
       
   170 // ---------------------------------------------------------------------------
       
   171 // CUpnpHttpChunkFileTransferReader::HandleL
       
   172 // Handles data in buffer, returns if file transfer has finished
       
   173 // ---------------------------------------------------------------------------
       
   174 //
       
   175 TBool CUpnpHttpChunkFileTransferReader::HandleL()
       
   176     {
       
   177     TInt error = KErrGeneral;
       
   178         
       
   179     error = Parse(iCacheBuffer, iDecoded);
       
   180             
       
   181     if( error == KErrNone && iSession.FileAccess() )
       
   182         {
       
   183         if ( iSession.FileAccess()->TransferTotal() == KErrNotFound )
       
   184             {
       
   185             iSession.FileAccess()->SetTransferTotal( 0 );
       
   186             }
       
   187         //parser finished decoding - writing all bytes
       
   188         if ( iParser->IsFinished() )
       
   189             {
       
   190             error = HandleReadDataL( iDecoded );
       
   191             }
       
   192         //buffer almost full - writing a fixed block of decoded data
       
   193         else if ( iBufferSize - iDecoded <= iReadBufferSize )
       
   194             {
       
   195             error = HandleReadDataL( iBufferSize - iReadBufferSize );
       
   196             }
       
   197     }
       
   198     iCacheBuffer.ReAllocL( iBufferSize );
       
   199     
       
   200     if( error != KErrNone )
       
   201         {        
       
   202         iSession.FileTransferReaderErrorL( error );
       
   203         return ETrue;
       
   204         }
       
   205     else if( iParser->IsFinished() )
       
   206         {
       
   207         if ( iSession.FileAccess() )
       
   208             {
       
   209             iSession.FileAccess()->SetChunkCompleted( ETrue );
       
   210             }
       
   211         iSession.FileTransferReaderDoneL();
       
   212         return ETrue;
       
   213         }
       
   214             
       
   215     return EFalse;
       
   216     }
       
   217 
       
   218 // ---------------------------------------------------------------------------
       
   219 // CUpnpHttpChunkFileTransferReader::HandleReadDataL
       
   220 // Handles read data - trims the buffer and save data to file
       
   221 // ---------------------------------------------------------------------------
       
   222 //
       
   223 TInt CUpnpHttpChunkFileTransferReader::HandleReadDataL( TInt aPieceToRead )
       
   224     {        
       
   225     //reads decoded data
       
   226     TPtr8 ptr = iCacheBuffer.LeftTPtr( aPieceToRead );
       
   227     
       
   228     //saves decoded data
       
   229     TInt error = iSession.FileAccess()->SaveL( ptr );
       
   230     iSession.FileAccess()->SetTransferTotal( 
       
   231         iSession.FileAccess()->TransferTotal() + aPieceToRead );
       
   232     
       
   233     //saved data are cut from buffer
       
   234     iCacheBuffer.Delete( 0, aPieceToRead );
       
   235   
       
   236     //position adjusted to the number of still encoded bytes        
       
   237     iDecoded -= aPieceToRead;			
       
   238 
       
   239     return error;
       
   240     }    
       
   241 
       
   242 // ---------------------------------------------------------------------------
       
   243 // CUpnpHttpChunkFileTransferReader::Finish
       
   244 // On finishing the file transfer
       
   245 // ---------------------------------------------------------------------------
       
   246 //
       
   247 void CUpnpHttpChunkFileTransferReader::Finish()
       
   248     {        
       
   249     CUpnpHttpFileTransferReader::Finish();    
       
   250     }    
       
   251 
       
   252 // ---------------------------------------------------------------------------
       
   253 // CUpnpHttpChunkFileTransferReader::RunL
       
   254 // From class CActive.
       
   255 // Function is called as a callback when the issued reading is completed.
       
   256 // ---------------------------------------------------------------------------
       
   257 //
       
   258 void CUpnpHttpChunkFileTransferReader::RunL()
       
   259     {
       
   260     LOGS2( "%i, CUpnpHttpChunkFileTransferReader::RunL(), iStatus %i",
       
   261             iSession.Id(), iStatus.Int() );
       
   262 
       
   263     // Active object request complete handler
       
   264     switch ( iStatus.Int() )
       
   265         {
       
   266         case KErrNone:
       
   267             iRetryErrorCount = 0;
       
   268             iCancelTimer->Cancel();
       
   269  
       
   270            iSession.TimerCancel();
       
   271            iCacheBuffer.SetLength( iCacheBuffer.Length() + iLen() );            
       
   272            iIsFinished = HandleL();                                           
       
   273             
       
   274             if(!iIsFinished)
       
   275                 {
       
   276                 IssueRead();
       
   277                 iSession.StartTimeoutTimer(ETrue);
       
   278                 }
       
   279             else
       
   280                  Finish();                                     
       
   281             break;
       
   282         
       
   283         case KErrCancel:
       
   284             if(iCancelFromTimer) 
       
   285                 {          
       
   286                 IssueRead();
       
   287                 iCancelFromTimer = EFalse;
       
   288                 }
       
   289             break;
       
   290         case KErrEof:
       
   291             iSession.TimerCancel();
       
   292             iCacheBuffer.SetLength( iLen() );                    
       
   293             iIsFinished = HandleL();            
       
   294             
       
   295             if(iIsFinished)
       
   296                 {
       
   297                 iSession.HandleErrorL( iStatus.Int() );
       
   298                 break;
       
   299                 }
       
   300            case KErrNoMemory:
       
   301         case KErrNotReady:
       
   302         case KErrInet6AddressExpired:
       
   303             if( iRetryErrorCount < KMaxRetryErrors )
       
   304                 {
       
   305                 iRetryTimer->Cancel();
       
   306                 iRetryTimer->After( KRetryWaitTime * ++iRetryErrorCount, EFalse );
       
   307                 break;
       
   308                 }         
       
   309             
       
   310         default:            
       
   311             iIsFinished = ETrue;
       
   312             iIsActivated = EFalse;            
       
   313             iSession.HandleErrorL( iStatus.Int() );
       
   314             break;
       
   315         }
       
   316         if( iSession.FileAccess() )
       
   317             iSession.FileAccess()->SetChunkCompleted( iIsFinished );
       
   318     }
       
   319 
       
   320 // -----------------------------------------------------------------------------
       
   321 // CUpnpHttpChunkFileTransferReader::RunError
       
   322 // From CActive.
       
   323 // Invoked when RunL leaves.
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 TInt CUpnpHttpChunkFileTransferReader::RunError( TInt aErr )
       
   327     {
       
   328     LOGS1("CUpnpHttpChunkFileTransferReader::RunError(%d)", aErr);
       
   329     return KErrNone;
       
   330     }
       
   331 
       
   332 // ---------------------------------------------------------------------------
       
   333 // CUpnpHttpChunkFileTransferReader::Reset
       
   334 // Makes reader ready to start reading new content
       
   335 // ---------------------------------------------------------------------------
       
   336 //
       
   337 void CUpnpHttpChunkFileTransferReader::Reset()
       
   338     {    
       
   339     iCacheBuffer.SetLength(0);
       
   340     iDecoded = 0;
       
   341     iParser->Reset();
       
   342     }
       
   343 
       
   344 // ---------------------------------------------------------------------------
       
   345 // CUpnpHttpChunkFileTransferReader::ReadFromSocket
       
   346 // Reads from the socket
       
   347 // ---------------------------------------------------------------------------
       
   348 //
       
   349 void CUpnpHttpChunkFileTransferReader::ReadFromSocket()
       
   350     {    
       
   351     Deque();
       
   352     CActiveScheduler::Add(this);
       
   353     
       
   354     iReceivePtr.Set( (TUint8*)iCacheBuffer.RightTPtr( 0 ).Ptr(), ReadBufferSize(), ReadBufferSize() );
       
   355     StartCancelTimer();
       
   356     iSocket.RecvOneOrMore( iReceivePtr,0,iStatus,iLen);       
       
   357     SetActive();
       
   358     }        
       
   359        
       
   360 //  End of File