upnp/upnpstack/dlnawebserver/src/upnphttpfiletransferwriter.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:  CUpnpHttpFileTransferWriter is a class responsible for 
       
    15 *                   asynchronous writing to a socket owned by CUpnpTcpSession.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "upnptcpsession.h"
       
    22 #include "upnphttpfiletransferwriter.h"
       
    23 #include "upnphttpfileaccess.h"
       
    24 #define KLogFile _L("DLNAWebServer.txt")
       
    25 #include "upnpcustomlog.h"
       
    26 
       
    27 
       
    28 // ======== MEMBER FUNCTIONS ========
       
    29 
       
    30 // ---------------------------------------------------------------------------
       
    31 // CUpnpHttpFileTransferWriter::NewL
       
    32 // Factory method.
       
    33 // ---------------------------------------------------------------------------
       
    34 //
       
    35 CUpnpHttpFileTransferWriter* CUpnpHttpFileTransferWriter::NewL( CUpnpTcpSession& aSession,
       
    36                                                     RSocket& aSocket,
       
    37                                                     TThreadPriority aPriority,
       
    38                                                     TInt aWriteSize )
       
    39     {
       
    40     CUpnpHttpFileTransferWriter* self = new ( ELeave ) 
       
    41             CUpnpHttpFileTransferWriter( aSession, aSocket, aPriority, aWriteSize );
       
    42     CleanupStack::PushL( self );
       
    43     self->ConstructL();
       
    44     CleanupStack::Pop( self );
       
    45     return self;
       
    46     }
       
    47     
       
    48 // ---------------------------------------------------------------------------
       
    49 // CUpnpHttpFileTransferWriter::CUpnpHttpFileTransferWriter
       
    50 // C++ constructor.
       
    51 // ---------------------------------------------------------------------------
       
    52 //
       
    53 CUpnpHttpFileTransferWriter::CUpnpHttpFileTransferWriter( CUpnpTcpSession& aSession,
       
    54                                               RSocket& aSocket, 
       
    55                                               TThreadPriority aPriority,
       
    56                                               TInt aWriteSize )
       
    57     :CActive( aPriority ),
       
    58     iSocket( aSocket ),
       
    59     iSession( aSession ),
       
    60     iState(EUnknown),
       
    61     iSendPointer(NULL,0),
       
    62     iWriteSize(aWriteSize)
       
    63     {
       
    64     LOGS1( "%i, CUpnpHttpFileTransferWriter::CUpnpHttpFileTransferWriter", iSession.Id() );
       
    65     // No implementation required
       
    66     }
       
    67 
       
    68 // ---------------------------------------------------------------------------
       
    69 // CUpnpTcpSessionReader::ConstructL
       
    70 // Two-phased constructor
       
    71 // constructor that can leave. Used from derived classes.
       
    72 // ---------------------------------------------------------------------------
       
    73 //
       
    74 void CUpnpHttpFileTransferWriter::ConstructL()
       
    75     {
       
    76     CActiveScheduler::Add( this );   
       
    77     iRetryWrite = CUpnpRetryWrite::NewL( iSession, iSocket, this, (TThreadPriority)Priority() );
       
    78     
       
    79     iSendBuffer.CreateL( iWriteSize );
       
    80     }
       
    81     
       
    82 // ---------------------------------------------------------------------------
       
    83 // CUpnpTcpSessionReader::~CUpnpTcpSessionReader
       
    84 // Destructor.
       
    85 // ---------------------------------------------------------------------------
       
    86 //
       
    87 CUpnpHttpFileTransferWriter::~CUpnpHttpFileTransferWriter()
       
    88     {    
       
    89     Cancel();    
       
    90     
       
    91     iSendBuffer.Close();
       
    92     
       
    93     delete iRetryWrite;
       
    94     }
       
    95  
       
    96 // ---------------------------------------------------------------------------
       
    97 // CUpnpHttpFileTransferWriter::DoCancel
       
    98 // From class CActive
       
    99 // Cancels issued writing request.
       
   100 // ---------------------------------------------------------------------------
       
   101 //
       
   102 void CUpnpHttpFileTransferWriter::DoCancel()
       
   103     {
       
   104     LOGS1( "%i, CUpnpHttpFileTransferWriter::DoCancel", iSession.Id() );
       
   105     
       
   106 	iState = ECancelled;
       
   107     }
       
   108     
       
   109 // ---------------------------------------------------------------------------
       
   110 // CUpnpHttpFileTransferWriter::RunL
       
   111 // From class CActive
       
   112 // Function called when issued writing is completed. Function checks if there
       
   113 // are any write requests left to send and if there are then it issues writing.
       
   114 // If queue is empty then function informs upper layer that writing is completed.
       
   115 // ---------------------------------------------------------------------------
       
   116 //
       
   117 void CUpnpHttpFileTransferWriter::RunL()
       
   118     {
       
   119     LOGS2( "%i, CUpnpHttpFileTransferWriter::RunL(), iStatus %i", 
       
   120     		iSession.Id() , iStatus.Int() );
       
   121     
       
   122     // Active object request complete handler
       
   123     if ( iStatus == KErrNone )
       
   124         {
       
   125         switch( iState )
       
   126             {
       
   127             // Character has been written to socket
       
   128             case EHeaders:
       
   129             	//100-continue not expected
       
   130             	if(!iSession.FileAccess())
       
   131             		{
       
   132             		Cancel();
       
   133             		break;
       
   134             		}
       
   135             	else 
       
   136             		{
       
   137             		iState = EContent;            		
       
   138             		}
       
   139             case EContent:            	
       
   140             	SendNextPortionL();            
       
   141                 
       
   142                 break;
       
   143             case EFinished:                    	    	
       
   144             	iSession.FileTransferWriterDoneL();
       
   145 
       
   146             	iSession.StartTimeoutTimer(EFalse);            	                      	
       
   147 				FinishL();
       
   148             	//export finished
       
   149             	break;    
       
   150             
       
   151             default:                
       
   152                 break;
       
   153             };
       
   154         }
       
   155     else
       
   156         {
       
   157            if( (iState == EHeaders || iState == EContent || iState == EFinished) &&
       
   158               (iStatus.Int() == KErrNoMemory || iStatus.Int() == KErrNotReady ) )
       
   159            {
       
   160 				iRetryWrite->IssueWriteRetry();
       
   161     	   }
       
   162 		   else
       
   163 	       {
       
   164 				// Error: pass it up to session
       
   165 				iSession.HandleErrorL( iStatus.Int() );
       
   166 				iState = ECancelled;
       
   167 			}
       
   168         }
       
   169     }
       
   170 
       
   171 // -----------------------------------------------------------------------------
       
   172 // CUpnpHttpFileTransferWriter::RunError
       
   173 // RunError is called when RunL leaves.
       
   174 // -----------------------------------------------------------------------------
       
   175 //
       
   176 TInt CUpnpHttpFileTransferWriter::RunError( TInt aError )
       
   177     {
       
   178     LOGS2( "%i, CUpnpHttpFileTransferWriter::RunError %d"
       
   179     		, iSession.Id() , aError);
       
   180     
       
   181     iState = EFinished;        
       
   182                 
       
   183     TRAP_IGNORE( HandleErrorL() );
       
   184     iSession.StartClosingSession();
       
   185     
       
   186     return KErrNone;
       
   187     }
       
   188 
       
   189 // ---------------------------------------------------------------------------
       
   190 // CUpnpHttpFileTransferWriter::SendNextWriteRequestL
       
   191 // Function checks if there are any write requests left and if there are then
       
   192 // issues writing and removes this request from queue.
       
   193 // ---------------------------------------------------------------------------
       
   194 //
       
   195 void CUpnpHttpFileTransferWriter::SendNextPortionL()
       
   196     {
       
   197     LOGS2( "%i, CUpnpHttpFileTransferWriter::SendNextPortionL(), iState %i",
       
   198     		iSession.Id() , iState );
       
   199 	
       
   200 	if( iSession.FileAccess() )
       
   201 		{
       
   202 		if( iState == EContent )    	
       
   203 	    	if( !IsActive() )
       
   204 	    		{      	
       
   205 		    	iSendPointer.Set( (TUint8*)iSendBuffer.Ptr(),0,iSendBuffer.MaxLength() );
       
   206 		        if( iSession.FileAccess()->GetL(iSendPointer,iSendBuffer.MaxLength()) )
       
   207 		        	{
       
   208 		        	iState = EFinished;     		
       
   209 		        	}
       
   210 		        
       
   211 				
       
   212 				iSession.TimerCancel();        
       
   213 		        WriteToSocket();
       
   214 		        iSession.StartTimeoutTimer(ETrue);	       
       
   215 		        
       
   216 	    		}
       
   217 		}
       
   218 	else
       
   219 		{
       
   220 		Cancel();
       
   221 		}
       
   222   
       
   223     }  
       
   224 
       
   225 // ---------------------------------------------------------------------------
       
   226 // CUpnpHttpFileTransferWriter::StartL
       
   227 // Passes control to the reader
       
   228 // ---------------------------------------------------------------------------
       
   229 //
       
   230 void CUpnpHttpFileTransferWriter::StartL()
       
   231     {
       
   232     iWaiting = EFalse;    
       
   233 	switch(iState)
       
   234 		{
       
   235 			case EUnknown:			
       
   236 				
       
   237 				iState = EHeaders;
       
   238 				SendHeadersL();
       
   239 				break;
       
   240 			case EHeaders:
       
   241 				
       
   242 				if(iSession.FileAccess()->HeadersSent())
       
   243 					{
       
   244 					iState = EContent;				
       
   245 					SendNextPortionL();
       
   246 					}
       
   247 				else
       
   248 					SendHeadersL();
       
   249 				break;
       
   250 				
       
   251 			default:
       
   252 				break;
       
   253 		}
       
   254     }
       
   255 
       
   256 // ---------------------------------------------------------------------------
       
   257 // CUpnpHttpFileTransferWriter::StartL
       
   258 // Sends the HTTP headers of the content
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CUpnpHttpFileTransferWriter::SendHeadersL()
       
   262     {
       
   263     if(iState == EHeaders)
       
   264     	if( iSession.FileAccess() )
       
   265     		if(!IsActive())
       
   266     			{ 
       
   267     			//in case session not connected,waiting...
       
   268     			if(!iSession.IsConnected())
       
   269 					{
       
   270 					iWaiting = ETrue;
       
   271 					return;
       
   272 					}   			
       
   273 				iSendBuffer.Zero();
       
   274 				
       
   275 				if ( ( iSession.FileAccess()->GetHeaders().Length() -
       
   276 				       iSession.FileAccess()->TransferredBytes()) <= 
       
   277 		               iSendBuffer.MaxLength() )
       
   278 					{
       
   279 					TPtrC8 headerPointer;
       
   280 					headerPointer.Set(iSession.FileAccess()->GetHeaders());
       
   281 					headerPointer.Set( headerPointer.Right( 
       
   282 		            iSession.FileAccess()->GetHeaders().Length()-
       
   283 		                iSession.FileAccess()->TransferredBytes()) );
       
   284 				
       
   285 					iSendBuffer.Append( headerPointer );			
       
   286 					iSession.FileAccess()->SetHeadersSent();
       
   287 
       
   288                     // Adding file content to the header
       
   289                     TInt length = iSendBuffer.MaxLength()-iSendBuffer.Length();
       
   290                     						
       
   291                     HBufC8* tmpBuffer = HBufC8::NewLC(length);
       
   292 					
       
   293                     iSendPointer.Set(tmpBuffer->Des());
       
   294                     if( iSession.FileAccess()->GetL(iSendPointer,length) )
       
   295                         {
       
   296                         iState = EFinished;
       
   297                         }
       
   298                     iSendBuffer.Append(iSendPointer);
       
   299                     CleanupStack::PopAndDestroy( tmpBuffer );
       
   300 					}
       
   301 				else
       
   302 					{
       
   303 					TPtrC8 headerPointer;
       
   304 					headerPointer.Set( iSession.FileAccess()->GetHeaders() );
       
   305 					headerPointer.Set( headerPointer.Right( 
       
   306 		            iSession.FileAccess()->GetHeaders().Length() -
       
   307 		                iSession.FileAccess()->TransferredBytes() ) );
       
   308 					headerPointer.Set( headerPointer.Left( 
       
   309 		                iSendBuffer.Length() ) );
       
   310 					
       
   311 					iSendBuffer.Append( headerPointer );				
       
   312 					iSession.FileAccess()->SetPosOfHeader( 
       
   313 					    iSession.FileAccess()->TransferredBytes() + headerPointer.Length() );							
       
   314 					}
       
   315 		    	
       
   316 		    	iSendPointer.Set((TUint8*)iSendBuffer.Ptr(),iSendBuffer.Length(),iSendBuffer.MaxLength());
       
   317     	   		
       
   318     	   		iSession.TimerCancel();        
       
   319 	        	WriteToSocket();
       
   320 	        	iSession.StartTimeoutTimer(ETrue);
       
   321 	        	
       
   322 	        	if(!iHttpPostStarted)
       
   323 	        		{
       
   324 	        		iSession.NotifyUpperLayersOnPostL();
       
   325 	        		iHttpPostStarted = ETrue;
       
   326 	        		}
       
   327 	        		
       
   328     			}
       
   329     }          
       
   330 
       
   331 // ---------------------------------------------------------------------------
       
   332 // CUpnpHttpFileTransferWriter::Reset
       
   333 // Resets the state of the writer
       
   334 // ---------------------------------------------------------------------------
       
   335 //
       
   336 void CUpnpHttpFileTransferWriter::Reset()
       
   337     {
       
   338     iState = EUnknown;  
       
   339     iHttpPostStarted = ETrue;  
       
   340     }
       
   341 
       
   342 // ---------------------------------------------------------------------------
       
   343 // CUpnpHttpFileTransferWriter::WriteToSocket
       
   344 // Writes data to socket
       
   345 // ---------------------------------------------------------------------------
       
   346 //
       
   347 void CUpnpHttpFileTransferWriter::WriteToSocket()
       
   348     {
       
   349 	Deque();
       
   350 	CActiveScheduler::Add(this);  
       
   351 
       
   352 	iSocket.Write(iSendPointer,iStatus);
       
   353 	SetActive();
       
   354     }
       
   355 
       
   356 // ---------------------------------------------------------------------------
       
   357 // CUpnpHttpFileTransferWriter::IsWaiting
       
   358 // Checks if file transfer writer is in use
       
   359 // ---------------------------------------------------------------------------
       
   360 //
       
   361 TBool CUpnpHttpFileTransferWriter::IsWaiting()
       
   362     {
       
   363 	return iWaiting;
       
   364     }
       
   365 
       
   366 // ---------------------------------------------------------------------------
       
   367 // CUpnpHttpFileTransferWriter::IsActivated
       
   368 // Writes data to socket
       
   369 // ---------------------------------------------------------------------------
       
   370 //
       
   371 TBool CUpnpHttpFileTransferWriter::IsActivated()
       
   372     {
       
   373 	return (!iWaiting && iState!=EUnknown);
       
   374     } 
       
   375 
       
   376 // ---------------------------------------------------------------------------
       
   377 // CUpnpHttpFileTransferWriter::IsRetrying
       
   378 // if waiting to retry writing to a socket
       
   379 // ---------------------------------------------------------------------------
       
   380 //
       
   381 TBool CUpnpHttpFileTransferWriter::IsRetrying()
       
   382     {
       
   383 	return (iRetryWrite->IsStarted());
       
   384     }
       
   385     
       
   386 // ---------------------------------------------------------------------------
       
   387 // CUpnpHttpFileTransferWriter::IsCancelled
       
   388 // Checks if transfer is cancelled
       
   389 // ---------------------------------------------------------------------------
       
   390 //
       
   391 TBool CUpnpHttpFileTransferWriter::IsCancelled()
       
   392     {
       
   393 	return (iState== ECancelled);
       
   394     }        
       
   395 // ---------------------------------------------------------------------------
       
   396 // CUpnpHttpFileTransferWriter::FinishL
       
   397 // Finishes download
       
   398 // ---------------------------------------------------------------------------
       
   399 //
       
   400 void CUpnpHttpFileTransferWriter::FinishL()
       
   401     {
       
   402 	iSession.FileTransferWriterHandleMoreL();
       
   403     }    
       
   404     
       
   405 // ---------------------------------------------------------------------------
       
   406 // CUpnpHttpFileTransferWriter::HandleErrorL
       
   407 // Handles RunL error
       
   408 // ---------------------------------------------------------------------------
       
   409 //
       
   410 void CUpnpHttpFileTransferWriter::HandleErrorL()
       
   411     {
       
   412     iSession.FileTransferWriterDoneL(); // 200ok to upper layers + delete iFileServe    
       
   413     FinishL();                          // serving uotstanding requests  
       
   414     }
       
   415         
       
   416 // ---------------------------------------------------------------------------
       
   417 // CUpnpHttpFileTransferWriter::SetPostNotify
       
   418 // Post notify will be sent
       
   419 // ---------------------------------------------------------------------------
       
   420 //
       
   421 void CUpnpHttpFileTransferWriter::SetPostNotify()
       
   422     {
       
   423 	iHttpPostStarted = EFalse;
       
   424     }    
       
   425         
       
   426 // ---------------------------------------------------------------------------
       
   427 // CUpnpHttpFileTransferWriter::RetryWriteFailL
       
   428 // 
       
   429 // ---------------------------------------------------------------------------
       
   430 //    
       
   431 void CUpnpHttpFileTransferWriter::RetryWriteFailL( TInt aError )
       
   432 	{
       
   433 	// Error: pass it up to session
       
   434 	iSession.HandleErrorL( aError );
       
   435     iState = ECancelled;
       
   436 	}
       
   437 
       
   438 // ---------------------------------------------------------------------------
       
   439 // CUpnpHttpFileTransferWriter::RetryWriteSucceed
       
   440 // 
       
   441 // ---------------------------------------------------------------------------
       
   442 // 
       
   443 void CUpnpHttpFileTransferWriter::RetryWriteSucceed()
       
   444 	{
       
   445 	WriteToSocket();
       
   446 	}
       
   447     
       
   448 //  End of File