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