upnp/upnpstack/dlnawebserver/src/upnphttpfiletransferreader.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:  CUpnpHttpFileTransferReader is a class responsible for 
       
    15 *                asynchronous reading data from socket and controlling it
       
    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 "upnphttpfileaccess.h"
       
    26 #include "inet6err.h"
       
    27 
       
    28 
       
    29 
       
    30 
       
    31 // ======== MEMBER FUNCTIONS ========
       
    32 
       
    33 // ---------------------------------------------------------------------------
       
    34 // CUpnpHttpFileTransferReader::NewL
       
    35 // Factory method.
       
    36 // ---------------------------------------------------------------------------
       
    37 //
       
    38 CUpnpHttpFileTransferReader* CUpnpHttpFileTransferReader::NewL( CUpnpTcpSession& aSession,
       
    39                                                 RSocket& aSocket,
       
    40                                                 TThreadPriority aPriority,
       
    41                                                 TInt aReadPortion,
       
    42                                                 TInt aBufferSize)
       
    43     {
       
    44     CUpnpHttpFileTransferReader* self = new ( ELeave ) 
       
    45                             CUpnpHttpFileTransferReader( aSession, aSocket,
       
    46                                               aPriority, aReadPortion, aBufferSize );
       
    47     CleanupStack::PushL( self );
       
    48     self->BaseConstructL();
       
    49     CleanupStack::Pop( self );
       
    50     return self;
       
    51     }
       
    52     
       
    53 // ---------------------------------------------------------------------------
       
    54 // CUpnpHttpFileTransferReader::CUpnpHttpFileTransferReader
       
    55 // C++ constructor.
       
    56 // ---------------------------------------------------------------------------
       
    57 //
       
    58 CUpnpHttpFileTransferReader::CUpnpHttpFileTransferReader( CUpnpTcpSession& aSession,
       
    59                                           RSocket& aSocket,
       
    60                                           TThreadPriority aPriority,
       
    61                                           TInt aReadPortion,
       
    62                                           TInt aBufferSize)
       
    63     :CActive( aPriority ),
       
    64     iSocket( aSocket ),
       
    65     iSession( aSession ),
       
    66     iReceivePtr( NULL, 0, 0 ),
       
    67     iReadBufferSize(aReadPortion),
       
    68     iBufferSize( aBufferSize )
       
    69     {
       
    70     LOGS1( "%i, CUpnpHttpFileTransferReader::CUpnpHttpFileTransferReader", iSession.Id() ); 
       
    71     }
       
    72 
       
    73 // ---------------------------------------------------------------------------
       
    74 // CUpnpHttpFileTransferReader::BaseConstructL
       
    75 // Two-phased constructor
       
    76 // constructor that can leave. Used from derived classes.
       
    77 // ---------------------------------------------------------------------------
       
    78 //
       
    79 void CUpnpHttpFileTransferReader::BaseConstructL()
       
    80     {
       
    81     CActiveScheduler::Add( this );              
       
    82                 
       
    83     iRetryTimer = CUpnpNotifyTimer::NewL( this );
       
    84     iCancelTimer = CUpnpNotifyTimer::NewL( this );        
       
    85     
       
    86     InitiateBufferL();
       
    87     }
       
    88 
       
    89 // ---------------------------------------------------------------------------
       
    90 // CUpnpHttpFileTransferReader::CalculateBufferSize
       
    91 // Finds nearest higher power of 2 for the given size
       
    92 // ---------------------------------------------------------------------------
       
    93 //
       
    94 TInt CUpnpHttpFileTransferReader::CalculateBufferSize( TInt aReadPortion, 
       
    95                                                        TInt aBufferSize )
       
    96     {
       
    97     aBufferSize -= 1;
       
    98     aBufferSize = aBufferSize | (aBufferSize >> 1);
       
    99     aBufferSize = aBufferSize | (aBufferSize >> 2);
       
   100     aBufferSize = aBufferSize | (aBufferSize >> 4);
       
   101     aBufferSize = aBufferSize | (aBufferSize >> 8);
       
   102     aBufferSize = aBufferSize | (aBufferSize >> 16);    
       
   103     aBufferSize += 1;
       
   104 
       
   105     if (aBufferSize <aReadPortion)
       
   106         {        
       
   107         aBufferSize = aReadPortion;
       
   108         }
       
   109     return aBufferSize;
       
   110     }            
       
   111 
       
   112 // ---------------------------------------------------------------------------
       
   113 // CUpnpHttpFileTransferReader::~CUpnpHttpFileTransferReader
       
   114 // Destructor.
       
   115 // ---------------------------------------------------------------------------
       
   116 //
       
   117 CUpnpHttpFileTransferReader::~CUpnpHttpFileTransferReader()
       
   118     {    
       
   119     Cancel();    
       
   120     iCacheBuffer.Close();        
       
   121     delete iRetryTimer;
       
   122     delete iCancelTimer;   
       
   123     }
       
   124     
       
   125 // ---------------------------------------------------------------------------
       
   126 // CUpnpHttpFileTransferReader::Start
       
   127 // Starts reading.
       
   128 // ---------------------------------------------------------------------------
       
   129 //
       
   130 void CUpnpHttpFileTransferReader::StartL()
       
   131     {    
       
   132     LOGS1( "%i, CUpnpHttpFileTransferReader::Start", iSession.Id() );
       
   133     if ( IsActive() )
       
   134         {        
       
   135         return;
       
   136         }
       
   137     
       
   138     if ( RemainingBytes() <= 0 )
       
   139         {
       
   140         HandleOneBufferShortTransferL();
       
   141         }
       
   142     else 
       
   143         {
       
   144         IssueRead();
       
   145         }
       
   146     }    
       
   147     
       
   148 // ---------------------------------------------------------------------------
       
   149 // CUpnpHttpFileTransferReader::HandleOneBufferShortTransferL
       
   150 // ---------------------------------------------------------------------------
       
   151 //    
       
   152 void CUpnpHttpFileTransferReader::HandleOneBufferShortTransferL()
       
   153     {    
       
   154     TInt totalLength = iSession.FileAccess()->TransferTotal();
       
   155     if ( totalLength > 0 && totalLength < iCacheBuffer.Length() )
       
   156         {
       
   157         //cut off malicious bytes exceeding contenth-length
       
   158         iCacheBuffer.SetLength( totalLength );
       
   159         }
       
   160     TInt error = iSession.FileAccess()->SaveL( iCacheBuffer );
       
   161             
       
   162     if ( error != KErrNone )
       
   163         {                
       
   164         iSession.FileTransferReaderErrorL( error );
       
   165         LOGSH( error, "error in HandleOneBufferShortTransferL" );
       
   166         return;
       
   167         }
       
   168     iSession.FileTransferReaderDoneL();
       
   169     Finish();
       
   170     }     
       
   171 
       
   172 // ---------------------------------------------------------------------------
       
   173 // CUpnpHttpFileTransferReader::DoCancel
       
   174 // From class CActive.
       
   175 // Cancels issued reading.
       
   176 // ---------------------------------------------------------------------------
       
   177 //
       
   178 void CUpnpHttpFileTransferReader::DoCancel()
       
   179     {
       
   180     LOGS1( "%i, CUpnpHttpFileTransferReader::DoCancel", iSession.Id() );
       
   181     // Cancel asychronous read request
       
   182     iSocket.CancelRead();
       
   183     }
       
   184     
       
   185 // ---------------------------------------------------------------------------
       
   186 // CUpnpTcpSessionReader::CancelRetry
       
   187 // ---------------------------------------------------------------------------
       
   188 //
       
   189 void CUpnpHttpFileTransferReader::CancelTimers()
       
   190     {
       
   191     iRetryTimer->Cancel();
       
   192     iCancelTimer->Cancel();
       
   193     }       
       
   194     
       
   195 // ---------------------------------------------------------------------------
       
   196 // CUpnpHttpFileTransferReader::RunL
       
   197 // From class CActive.
       
   198 // Function is called as a callback when the issued reading is completed.
       
   199 // ---------------------------------------------------------------------------
       
   200 //
       
   201 void CUpnpHttpFileTransferReader::RunL()
       
   202     {
       
   203     LOGS2( "%i, CUpnpHttpFileTransferReader::RunL(), iStatus %i",
       
   204             iSession.Id(), iStatus.Int() );
       
   205 
       
   206     // Active object request complete handler
       
   207     switch ( iStatus.Int() )
       
   208         {
       
   209         case KErrNone:
       
   210             iRetryErrorCount = 0;
       
   211             iCancelTimer->Cancel();
       
   212 
       
   213             iSession.TimerCancel();
       
   214             iCacheBuffer.SetLength( iCacheBuffer.Length() + iLen() );
       
   215             if ( ( iCacheBuffer.MaxLength() == iCacheBuffer.Length() ) 
       
   216                 || !(RemainingBytes() > 0))
       
   217                 {                
       
   218                 iIsFinished = HandleL();                               
       
   219                 }                                      
       
   220             if ( !iIsFinished )
       
   221                 {
       
   222                 IssueRead();
       
   223                 iSession.StartTimeoutTimer( ETrue );
       
   224                 }
       
   225             else
       
   226                 {                
       
   227                 Finish();
       
   228                 }                                       
       
   229             break;
       
   230          case KErrCancel:
       
   231             if ( iCancelFromTimer ) 
       
   232                 {          
       
   233                 IssueRead();
       
   234                 iCancelFromTimer = EFalse;
       
   235                 }
       
   236             break;            
       
   237         case KErrEof:
       
   238             iSession.TimerCancel();
       
   239             iCacheBuffer.SetLength( iCacheBuffer.Length() + iLen() );
       
   240             iIsFinished = HandleL();                        
       
   241             if ( iIsFinished )
       
   242                 {
       
   243                 iSession.HandleErrorL( iStatus.Int() );
       
   244                 break;
       
   245                 }                       
       
   246         case KErrNoMemory:
       
   247         case KErrNotReady:
       
   248         case KErrInet6AddressExpired:
       
   249             if ( iRetryErrorCount < KMaxRetryErrors )
       
   250                 {
       
   251                 iRetryTimer->Cancel();
       
   252                 iRetryTimer->After( KRetryWaitTime * ++iRetryErrorCount, EFalse );
       
   253                 break;
       
   254                 }
       
   255         default:            
       
   256             iIsFinished = ETrue;
       
   257             iIsActivated = EFalse;
       
   258             if ( iSession.FileAccess() ) 
       
   259                 { 
       
   260                 iSession.FileAccess()->DeleteFile();            
       
   261                 }
       
   262             iSession.HandleErrorL( iStatus.Int() );
       
   263             break;
       
   264         }
       
   265     }
       
   266 
       
   267 // -----------------------------------------------------------------------------
       
   268 // CUpnpTcpSessionWriter::RunError
       
   269 // RunError is called when RunL leaves.
       
   270 // -----------------------------------------------------------------------------
       
   271 //
       
   272 
       
   273 TInt CUpnpHttpFileTransferReader::RunError( TInt /*aError*/ )
       
   274     {  
       
   275     LOGS( "CUpnpHttpFileTransferReader::RunError"); 
       
   276     HandleError();      
       
   277     return KErrNone;
       
   278     }
       
   279 
       
   280 // -----------------------------------------------------------------------------
       
   281 // CUpnpTcpSessionReader::TimerEventL
       
   282 // Retry read
       
   283 // -----------------------------------------------------------------------------
       
   284 //        
       
   285 void CUpnpHttpFileTransferReader::TimerEventL( CUpnpNotifyTimer* aTimer )
       
   286     {
       
   287     if ( aTimer == iCancelTimer )
       
   288         {
       
   289         LOGS( "CUpnpHttpFileTransferReader::TimerEventL, canceltimer");
       
   290         iCancelFromTimer = ETrue;
       
   291         iSocket.CancelRecv();
       
   292         }
       
   293     else if ( aTimer == iRetryTimer )
       
   294         {
       
   295         IssueRead();
       
   296         }
       
   297     }
       
   298 
       
   299 // -----------------------------------------------------------------------------
       
   300 // CUpnpTcpSessionReader::StartCancelTimer
       
   301 // -----------------------------------------------------------------------------
       
   302 //  
       
   303 void CUpnpHttpFileTransferReader::StartCancelTimer()
       
   304     {
       
   305     LOGS( "CUpnpHttpFileTransferReader::StartCancelTimer");
       
   306     TInt timeout = iSession.TimeoutCurrentValue();
       
   307     iCancelTimer->Cancel();
       
   308        
       
   309     timeout = timeout/2 - KTwoSec;
       
   310     if ( timeout <= 0 ) 
       
   311         {
       
   312         timeout = KOneSec;
       
   313         }
       
   314     iCancelTimer->After( timeout, EFalse );
       
   315     iCancelFromTimer = EFalse;
       
   316     }
       
   317    
       
   318 // ---------------------------------------------------------------------------
       
   319 // CUpnpHttpFileTransferReader::IssueRead
       
   320 // Issues reading.
       
   321 // ---------------------------------------------------------------------------
       
   322 //
       
   323 void CUpnpHttpFileTransferReader::IssueRead()
       
   324     {       
       
   325     if ( IsActive() )
       
   326         {
       
   327         LOGS1( "%i, PANIC: CUpnpHttpFileTransferReader::IssueRead!", 
       
   328                 iSession.Id() );
       
   329         User::Panic( _L("CUpnpHttpFileTransferReader is active" ), KErrGeneral );    
       
   330         } 
       
   331                                                
       
   332     if ( iSession.IsConnected() )
       
   333         {          
       
   334         ReadFromSocket();
       
   335         }
       
   336     }
       
   337     
       
   338 // ---------------------------------------------------------------------------
       
   339 // CUpnpHttpFileTransferReader::RemainingBytes
       
   340 // Returns the remaining numbers of bytes to read
       
   341 // ---------------------------------------------------------------------------
       
   342 //
       
   343 TInt CUpnpHttpFileTransferReader::RemainingBytes()
       
   344     {
       
   345     LOGS( "CUpnpHttpFileTransferReader::RemainingBytes()");
       
   346     if ( !iSession.FileAccess() )
       
   347         {        
       
   348         return 0;
       
   349         }    
       
   350     if ( iSession.FileAccess()->TransferTotal() == KErrNotFound ) 
       
   351         {        
       
   352         return ( TcpFinFoundRemainingBytes() );
       
   353         }    
       
   354     return ( iSession.FileAccess()->TransferTotal() - 
       
   355              iSession.FileAccess()->BytesWritten() - iCacheBuffer.Length() );
       
   356     }
       
   357 
       
   358 // ---------------------------------------------------------------------------
       
   359 // CUpnpHttpFileTransferReader::ReadBufferSize
       
   360 // Returns the maximum size of bytes to read for once
       
   361 // ---------------------------------------------------------------------------
       
   362 //
       
   363 TInt CUpnpHttpFileTransferReader::ReadBufferSize()
       
   364     {
       
   365     LOGS( "CUpnpHttpFileTransferReader::ReadBufferSize()");
       
   366     if ( !iSession.FileAccess() )
       
   367         {        
       
   368         return 0;
       
   369         }
       
   370     //checks how much space in the buffer
       
   371     TInt availableSpace = AvailableSpace();
       
   372     
       
   373     //content-length no specified            
       
   374     if( iSession.FileAccess()->TransferTotal() == KErrNotFound )
       
   375         {        
       
   376         return availableSpace;
       
   377         }
       
   378         
       
   379     TInt remainingBytes = RemainingBytes();     
       
   380     //chooses free space in the buffer or the num of remaining bytes to read        
       
   381     return ( availableSpace >= remainingBytes ) ? remainingBytes : availableSpace;    
       
   382     }               
       
   383     
       
   384 // ---------------------------------------------------------------------------
       
   385 // CUpnpHttpFileTransferReader::HandleL
       
   386 // Handles adata in buffer, returns if file transfer has finished
       
   387 // ---------------------------------------------------------------------------
       
   388 //
       
   389 TBool CUpnpHttpFileTransferReader::HandleL()
       
   390     {
       
   391     LOGS( "CUpnpHttpFileTransferReader::HandleL");
       
   392     TInt error = KErrGeneral;    
       
   393     if ( iSession.FileAccess() )
       
   394         {
       
   395         LOGS( "calling iFile->SaveL()");
       
   396         TPtr8 ptr = iCacheBuffer.LeftTPtr( iCacheBuffer.Size() );
       
   397         error = iSession.FileAccess()->SaveL( ptr );
       
   398         iCacheBuffer.SetLength(0);
       
   399         }    
       
   400     if ( error != KErrNone )
       
   401         {                
       
   402         iSession.FileTransferReaderErrorL( error );
       
   403         LOGS( "returning ETrue after FileTransferReaderErrorL" );
       
   404         return ETrue;
       
   405         }
       
   406     else if ( !( RemainingBytes() > 0 ) )
       
   407         {
       
   408         iSession.FileTransferReaderDoneL();
       
   409         LOGS( "returning ETrue FileTransferReaderDoneL");
       
   410         return ETrue;
       
   411         }        
       
   412     LOGS( "returning EFalse"); 
       
   413     return EFalse;
       
   414     }
       
   415 
       
   416 // ---------------------------------------------------------------------------
       
   417 // CUpnpHttpFileTransferReader::Finish
       
   418 // Finishes session
       
   419 // ---------------------------------------------------------------------------
       
   420 //
       
   421 void CUpnpHttpFileTransferReader::Finish()
       
   422     {            
       
   423     iIsActivated = EFalse;
       
   424     iSession.StartClosingSession();        
       
   425     }    
       
   426 
       
   427 // ---------------------------------------------------------------------------
       
   428 // CUpnpHttpFileTransferReader::Reset
       
   429 // Makes reader ready to start reading new content
       
   430 // ---------------------------------------------------------------------------
       
   431 //
       
   432 void CUpnpHttpFileTransferReader::Reset()
       
   433     {    
       
   434     iIsFinished = EFalse;
       
   435     iIsActivated = EFalse;
       
   436     iCacheBuffer.SetLength(0);
       
   437     }
       
   438     
       
   439 // ---------------------------------------------------------------------------
       
   440 // CUpnpHttpFileTransferReader::Activated
       
   441 // Checks if the filetransfer reader is started and in use
       
   442 // ---------------------------------------------------------------------------
       
   443 //
       
   444 TBool CUpnpHttpFileTransferReader::Activated()
       
   445     {    
       
   446     return iIsActivated;
       
   447     } 
       
   448 
       
   449 // ---------------------------------------------------------------------------
       
   450 // CUpnpHttpFileTransferReader::SetActivated
       
   451 // Filetransfer reader taken in use
       
   452 // ---------------------------------------------------------------------------
       
   453 //
       
   454 void CUpnpHttpFileTransferReader::SetActivated( TBool aValue )
       
   455     {    
       
   456     iIsActivated = aValue;
       
   457     }
       
   458         
       
   459 // ---------------------------------------------------------------------------
       
   460 // CUpnpHttpFileTransferReader::ReadFromSocket
       
   461 // Reads data from socket
       
   462 // ---------------------------------------------------------------------------
       
   463 //
       
   464 void CUpnpHttpFileTransferReader::ReadFromSocket()
       
   465     {    
       
   466     Deque();
       
   467     CActiveScheduler::Add(this);
       
   468     
       
   469     TInt len = ReadBufferSize();
       
   470     TPtr8 ptr = iCacheBuffer.RightTPtr( 0 );
       
   471     iReceivePtr.Set( (TUint8*)ptr.Ptr(), len, len );
       
   472     StartCancelTimer();
       
   473     iSocket.RecvOneOrMore( iReceivePtr, 0, iStatus, iLen );   
       
   474     SetActive();
       
   475     }        
       
   476 
       
   477 // ---------------------------------------------------------------------------
       
   478 // CUpnpHttpFileTransferReader::AppendL(const TDesC8& aBeginning)
       
   479 // Appends beginning data to the buffer
       
   480 // ---------------------------------------------------------------------------
       
   481 //
       
   482 void CUpnpHttpFileTransferReader::AppendL( const TDesC8& aBeginning )
       
   483     {    
       
   484     //if no space for this operation, abort it,it shouldn't occur
       
   485     if ( iCacheBuffer.MaxSize() - iCacheBuffer.Length() < aBeginning.Length() )
       
   486         {        
       
   487         User::Leave(KErrAbort);
       
   488         }
       
   489     
       
   490     iCacheBuffer.Append( aBeginning );
       
   491     }
       
   492 
       
   493 // ---------------------------------------------------------------------------
       
   494 // CUpnpHttpFileTransferReader::InitiateBufferL()
       
   495 // Initiates the buffer
       
   496 // ---------------------------------------------------------------------------
       
   497 //
       
   498 void CUpnpHttpFileTransferReader::InitiateBufferL()
       
   499     {    
       
   500     if ( !iSession.FileAccess() )
       
   501         {        
       
   502         User::Leave( KErrGeneral );  
       
   503         }
       
   504     
       
   505     iCacheBuffer.Close();    
       
   506     iCacheBuffer.CreateL( iBufferSize );
       
   507     }
       
   508 
       
   509 // ---------------------------------------------------------------------------
       
   510 // CUpnpHttpFileTransferReader::HandleError
       
   511 // Handles error from RunL
       
   512 // ---------------------------------------------------------------------------
       
   513 //
       
   514 void CUpnpHttpFileTransferReader::HandleError()
       
   515     {
       
   516     if ( iSession.FileAccess() )
       
   517         {
       
   518         iSession.FileAccess()->DeleteFile();        
       
   519         }
       
   520     iIsFinished = ETrue;
       
   521     Finish();        
       
   522     }    
       
   523 
       
   524 // ---------------------------------------------------------------------------
       
   525 // CUpnpHttpFileTransferReader::TcpFinFoundRemainingBytes
       
   526 // Detects end of body when no content length
       
   527 // ---------------------------------------------------------------------------
       
   528 //
       
   529 TInt CUpnpHttpFileTransferReader::TcpFinFoundRemainingBytes()
       
   530     {
       
   531     if ( iStatus.Int() == KErrEof )
       
   532         {
       
   533         //the num of written bytes will be the transfer total
       
   534         iSession.FileAccess()->SetTransferTotal( 
       
   535                                    iSession.FileAccess()->BytesWritten() );
       
   536         return 0;
       
   537         }        
       
   538     else
       
   539         {        
       
   540         return AvailableSpace();        
       
   541         }
       
   542     }  
       
   543        
       
   544 // ---------------------------------------------------------------------------
       
   545 // CUpnpHttpFileTransferReader::AvailableSpace
       
   546 // Returns num of bytes that will still fit into the buffer
       
   547 // ---------------------------------------------------------------------------
       
   548 //
       
   549 TInt CUpnpHttpFileTransferReader::AvailableSpace()
       
   550     {
       
   551     TInt space = (iBufferSize < iCacheBuffer.Length() + iReadBufferSize) ?
       
   552                 iBufferSize - iCacheBuffer.Length(): iReadBufferSize;    
       
   553     return space;        
       
   554     }  
       
   555         
       
   556 //  End of File