mtptransports/mtpptpiptransport/ptpipplugin/src/cptpipsockhandlerbase.cpp
changeset 0 d0791faffa3f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtptransports/mtpptpiptransport/ptpipplugin/src/cptpipsockhandlerbase.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,1008 @@
+// Copyright (c) 2008-2009 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:
+// cptpipsockethandler.cpp
+// 
+//
+
+/**
+ @internalComponent
+*/
+
+#include "cptpipsockhandlerbase.h"
+#include "cptpipconnection.h"
+#include "ptpippanic.h"
+
+const TUint32 KPTPIPHeaderSize = 8;
+const TUint KMaxPacketSixe   = 16;
+const TUint64 KMaxPTPIPPacketSize = 0x18FF4; // 100 KB - 12
+
+//#define MTP_DEBUG_FLOG_HEX_DUMP
+
+#define UNUSED_VAR(a) (a)=(a)
+
+/**
+Constructor 
+*/
+CPTPIPSocketHandlerBase::CPTPIPSocketHandlerBase(CPTPIPConnection& aConnection, TPriority priority ) : 
+						CActive(priority),
+						iChunkStatus(0),
+						iSendChunkData(NULL, 0),
+						iSendData(NULL, 0),
+						iReceiveChunkData(NULL, 0),
+						iPTPPacketLength(0),
+						iState(EIdle),
+						iPacketBuffer(NULL),
+						iPacketSizeMax(NULL),
+						iReceiveData(NULL, 0),
+						iIsFirstChunk(EFalse),
+						iPTPPacketLengthReceived(0),
+						iReceiveDataCommit(EFalse),
+						iSendHeaderData(NULL, 0),
+						iPTPIPDataHeader(NULL),
+						iConnection(aConnection),
+						iReceiveDataSink(NULL),
+						iSendDataSource(NULL),
+						iCurrentChunkData(NULL,0,0)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+
+
+/**
+Second phase constructor.
+*/
+#ifdef __FLOG_ACTIVE    
+void CPTPIPSocketHandlerBase::ConstructL(const TDesC8& aComponentName)
+#else
+void CPTPIPSocketHandlerBase::ConstructL()
+#endif
+    {
+    __FLOG_OPEN(KMTPSubsystem, aComponentName);
+    __FLOG(_L8("CSocketHandler::ConstructL - Entry"));
+    iPacketSizeMax = KMaxPacketSixe; 
+    iPacketBuffer.ReAllocL(iPacketSizeMax);
+    iPTPIPDataHeader = CPTPIPDataContainer::NewL();
+    __FLOG(_L8("CSocketHandler::ConstructL - Exit"));
+    }
+  
+ /**
+ Destructor
+ */  
+ CPTPIPSocketHandlerBase::~CPTPIPSocketHandlerBase()
+ {
+    __FLOG(_L8("CSocketHandler::~CSocketHandler - Entry"));
+    Cancel();
+    iPacketBuffer.Close();
+    iSocket.Close();
+    delete iPTPIPDataHeader;
+    __FLOG(_L8("CSocketHandler::~CSocketHandler - Exit"));
+    __FLOG_CLOSE;
+ }
+
+
+//
+// CActive Functions
+//
+
+/**
+ This will be called after every chunk is sent or received over the socket. 
+*/
+void CPTPIPSocketHandlerBase::RunL()
+	{
+	__FLOG(_L8("RunL - Entry"));
+    __FLOG_VA((_L8("Current State is 0x%08X, and status is %d"), iState, iStatus.Int()));	
+    
+	switch ( DataStreamDirection() )
+		{
+	case EReceivingState:
+	
+        __FLOG_VA((_L8("Receive data completion status = %d"), iStatus.Int()));
+        if (iState == EReceiveFastInProgress)
+        	{
+        	InitiateFirstChunkReceiveL(); 
+        	}
+        
+        else if (iStatus != KErrNone)
+            {
+            // Abnormal completion.
+            __FLOG_VA((_L8("PTPIP Error: Receive data completed with error = %d"), iStatus.Int()));
+            SetState(EReceiveComplete);
+            }
+        else if (iState != EReceiveComplete)
+            {
+	        // Update the chunk data length. We use the iReceiveData variable with the socket 
+	        // so only its length gets updated on receive. 
+	        
+	        // However during remaining processing we use iReceiveChunkData, so update its len.
+            iReceiveChunkData.SetLength(iReceiveChunkData.Length() + iReceiveData.Length());
+            if (iIsFirstChunk)
+	            {
+	            // process the first chunk.
+	            ProcessFirstReceivedChunkL();  
+	            }
+	        else
+		        {
+		        ResumeReceiveDataStreamL(); 
+		        }
+            }
+            
+        if (iState == EReceiveComplete)
+            {             
+            // Save the pointer to the last populated location on the current chunk            
+            iCurrentChunkData.Set(iReceiveChunkData);             
+            // Reset the receive data stream and notify the connection.
+            MMTPType& data(*iReceiveDataSink);
+            ResetReceiveDataStream();
+            TRAPD(err, ReceiveDataCompleteL(iStatus.Int(), data));
+            if (err != KErrNone)
+            	{
+            	__FLOG_VA((_L8("Framework threw an error from ReceiveDataCompleteL = %d"), err)); 
+            	ReceiveDataCompleteL(err, data);
+            	}
+            }
+        break;
+        
+	case ESendingState:
+		// Special case for handling the sending of init ack, handled in the derived class.
+		if (HandleInitAck())
+			{
+			ResetSendDataStream();
+			break;
+			}
+
+        __FLOG_VA((_L8("Send data stream completion status = %d"), iStatus.Int())); 
+        if (iStatus != KErrNone)
+            {
+            // Abnormal completion.
+            SetState(ESendComplete);
+            }
+		else
+			{
+            ProcessSendDataL(); 
+            }
+         if (iState == ESendComplete)
+            {
+            // Reset the send data stream and notify the connection.
+            const MMTPType& data(*iSendDataSource);
+            ResetSendDataStream();
+            TRAPD(err, SendDataCompleteL(iStatus.Int(), data));
+            if (err != KErrNone)
+            	{
+            	__FLOG_VA((_L8("Framework threw an error from SendDataCompleteL = %d"), err)); 
+            	SendDataCompleteL(err, data);
+            	}
+            }
+        break;
+        
+	case ESendDataState:
+		if (iStatus != KErrNone)
+            {
+            // Abnormal completion.
+            SetState(ESendDataComplete);
+            }
+ 		else if (iState == ESendingDataHeader)
+			{
+			SetState(ESendingDataPacket);	
+			}
+		else if (iState == ESendingDataPacket)
+			{
+			SetState(ESendingDataHeader);		
+			}
+		else if (iState == ESendDataPacketCompleting)
+			{
+			SetState(ESendDataComplete);	
+			}
+		
+		if (iState == ESendDataComplete || iState == ESendDataCancelled)
+            {
+            // Reset the send data stream and notify the connection.
+            const MMTPType& data(*iSendDataSource);
+            ResetSendDataStream();
+            SendDataCompleteL(iStatus.Int(), data);
+            }
+   		else
+	        {
+	        CreateAndSendDataPacketsL();	
+	        }
+		break;
+		
+	default:
+		
+		__FLOG_VA((_L8("PTPIP ERROR: Invalid state of the sockethandler: RunL should not be called with 0x%08X state"), iState));	
+        Panic(EPTPIPBadState);
+		break;
+		
+		}// switch
+		
+    __FLOG_VA((_L8("IsActive = %d"), IsActive()));
+	__FLOG(_L8("RunL - Exit"));
+	}
+
+/**
+Tell the Asynchronous Service provider to cancel all outstanding operations. 
+*/
+void CPTPIPSocketHandlerBase::DoCancel()
+	{
+	__FLOG(_L8("DoCancel - Entry"));
+    switch (iState & EStateDirection)
+        {
+    case EReceivingState:
+        __FLOG(_L8("Cancelling receive on the socket"));
+        iSocket.CancelRecv();
+        ResetReceiveDataStream();
+        break;
+
+    case ESendingState:    
+        __FLOG(_L8("Cancelling send on the socket"));
+        iSocket.CancelSend();
+        ResetSendDataStream();
+        break;
+        
+    case ESendDataState:
+	    __FLOG(_L8("Cancelling send on the socket"));
+	    iSocket.CancelSend();
+	    ResetSendDataStream();
+	    break;
+	    
+    default:
+        break;
+		}
+	__FLOG(_L8("DoCancel - Exit"));
+	}
+
+/**
+This is invoked when a panic occurs during RunL. 
+To handle this , all operations are cancelled, and if we were processing
+a send or recv operation, we complete it with the error code. 
+@param - The error code with which RunL left
+*/
+TInt CPTPIPSocketHandlerBase::RunError(TInt aError)
+	{
+	__FLOG(_L8("RunError - Entry"));
+    __FLOG_VA((_L8("Error reported is  %d and state is 0x%08X, and status is %d"), aError, iState, iStatus.Int()));
+ 
+    // Cancel any outstanding request.
+    Cancel();  
+    
+    // Notify the protocol layer of the error.
+    TInt32 streamDirection = DataStreamDirection();
+    if (streamDirection == EReceivingState)
+	    {
+		__FLOG(_L8("Error in EReceivingState"));            
+        // Notify the connection and reset the receive data stream.
+        MMTPType& data(*iReceiveDataSink);
+        ResetReceiveDataStream();
+        TRAPD(err, ReceiveDataCompleteL(aError, data));
+        UNUSED_VAR(err);
+	    }
+	else if (streamDirection == ESendingState || (streamDirection == ESendDataState))
+		{
+		__FLOG(_L8("Error in ESendingState"));
+        // Notify the connection and reset the send data stream.
+        const MMTPType& data(*iSendDataSource);
+        ResetSendDataStream();
+        TRAPD(err, SendDataCompleteL(aError, data));
+        UNUSED_VAR(err);
+		}
+    // We are neither in sending nor receiving state, the error in RunL
+    // must have originated from the MTP framework, tell the connection 
+    // to stop.
+	else 
+		{
+		Connection().HandleError(aError);
+		}
+ 
+	__FLOG(_L8("RunError - Exit"));
+	return KErrNone;
+	}
+	
+//
+// Send Data Functions
+//
+
+/**
+This sends the data over the socket. The buffer is provided by the MTP fw.
+@param aData - The data buffer to be sent
+@param aTransactionId - The id of the current onging transaction. This is needed 
+ in case the data in R to I phase has to be split into multiple PTPIP data packets
+ In such a case the PTPIP Data packet header needs to be created which contains the tran id. 
+*/
+void CPTPIPSocketHandlerBase::SendDataL(const MMTPType& aData, TUint32 aTransactionId )
+	{
+	__FLOG(_L8("SendDataL - Entry"));
+    iSendDataSource = &aData;
+	TUint64 size = iSendDataSource->Size();
+    __FLOG_VA((_L8("Size of total data to be sent = %ld bytes"), size));
+	
+	// if the data is less than KMaxPTPIPPacketSize then it can be sent in a shot, 
+	// Currently the ptp ip packet has the end data packet already, so it can be sent directly. 
+	if ( size < KMaxPTPIPPacketSize)
+		{
+		__FLOG(_L8("Size of data is less than KMaxPTPIPPacketSize, sending as one ptpip packet."));
+	    SetState(ESendInitialising);
+		ProcessSendDataL();
+		}
+		
+	// if the data is greater than KMaxPTPIPPacketSize then it needs to be split into 
+	// multiple packets. The PTPIP header will be locally created , and sent
+	// and then one chunk will be sent as one PTPIP packet.
+	else 
+		{
+		__FLOG(_L8("Size of data is more than KMaxPTPIPPacketSize, sending as multiple ptpip packets."));
+		iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::ETransactionId, aTransactionId);
+		iPTPIPDataHeader->SetPayloadL(NULL);
+		
+		// We can ignore this header, since we create our own while sending each packet.
+		iChunkStatus = iSendDataSource->FirstReadChunk(iSendChunkData);
+        
+		SetState(ESendingDataHeader);
+		CreateAndSendDataPacketsL();
+		}
+	
+	__FLOG(_L8("SendDataL - Exit"));
+	}
+
+/**
+Using the same algo as the USB send, to buffer into a local buffer, and sending 
+only when buffer exceeds the max socket send size, or all chunks have been buffered. 
+*/
+void CPTPIPSocketHandlerBase::ProcessSendDataL()
+	{
+	__FLOG(_L8("ProcessSendDataL - Entry"));	
+	
+    iSendData.Set(KNullDesC8);
+
+    TUint chunkAvailableLen(iSendChunkData.Length());
+    if (!chunkAvailableLen)
+        {    
+        // Fetch the next read data chunk. 
+        switch (iState)
+            {
+        case ESendInitialising:
+            __FLOG(_L8("Fetching first read data chunk"));
+            iChunkStatus = iSendDataSource->FirstReadChunk(iSendChunkData);
+            iPacketBuffer.Zero();
+            break;
+            
+        case ESendInProgress:
+            __FLOG(_L8("Fetching next read data chunk"));
+            iChunkStatus = iSendDataSource->NextReadChunk(iSendChunkData);
+            break;
+            
+        case ESendCompleting:
+            break;            
+           
+        case EIdle:
+        default:
+            __FLOG(_L8("Invalid send data stream state"));
+            Panic(EPTPIPBadState);
+            break;
+            }
+        
+        // Fetch the new chunk data size available.
+        chunkAvailableLen = iSendChunkData.Length();
+        
+        // Update data stream state.
+        switch (iChunkStatus)
+            {
+        case KErrNone:
+            SetState(ESendInProgress);
+            break;
+            
+        case KMTPChunkSequenceCompletion:
+            if (iState == ESendCompleting)
+                {
+                SetState(ESendComplete);
+                }
+            else
+                {
+                SetState(ESendCompleting);
+                }
+            break;
+            
+          case KErrNotFound:// CMTPTypeFile returns this when it has zero length
+        	if( 0 == iSendChunkData.Length() )
+        		{
+                if (iState == ESendCompleting)
+                {
+                SetState(ESendComplete);
+                }
+            else
+                {
+                SetState(ESendCompleting);
+                }
+                }  
+                break;
+        default:
+            User::Leave(iChunkStatus);
+            break;
+            }          
+        }
+    __FLOG_VA((_L8("Chunk status = %d"), iChunkStatus));
+    
+    // Process the buffered residual and/or available chunk data.
+    TUint bufferedLen(iPacketBuffer.Length());
+    TUint chunkIntegralLen((chunkAvailableLen / iPacketSizeMax) * iPacketSizeMax);
+    TUint chunkResidualLen(chunkAvailableLen % iPacketSizeMax);
+    __FLOG_VA((_L8("Buffered residual data = %d bytes"), bufferedLen));
+    __FLOG_VA((_L8("Chunk data available = %d bytes"), chunkAvailableLen));
+    __FLOG_VA((_L8("Chunk data packet integral portion = %d bytes"), chunkIntegralLen));
+    __FLOG_VA((_L8("Chunk data packet residual portion = %d bytes"), chunkResidualLen));
+    
+    if (bufferedLen)
+        {
+        // Data is buffered in the packet buffer. Fill the available packet buffer space.
+        if (chunkAvailableLen)
+            {
+            // Fill the packet buffer.
+            TUint consumedLen(0);
+            TUint unconsumedLen(0);
+            TUint capacity(iPacketBuffer.MaxLength() - iPacketBuffer.Length());
+            if (chunkAvailableLen > capacity)
+                {
+                consumedLen     = capacity;
+                unconsumedLen   = (chunkAvailableLen - consumedLen);              
+                }
+            else
+                {
+                consumedLen = chunkAvailableLen;
+                }
+            __FLOG_VA((_L8("Buffering %d bytes"), consumedLen));
+            iPacketBuffer.Append(iSendChunkData.Left(consumedLen));
+            
+            // Update the available chunk data to reflect only the unconsumed portion.
+            __FLOG_VA((_L8("Residual chunk data = %d bytes"), unconsumedLen));
+            if (unconsumedLen)
+                {
+                iSendChunkData.Set(iSendChunkData.Right(unconsumedLen));
+                }
+            else
+                {
+                iSendChunkData.Set(NULL, 0);                    
+                }
+            }
+        
+        // Send the packet buffer when full.
+        if ((iState == ESendCompleting) || (iPacketBuffer.Size() == iPacketBuffer.MaxSize()))
+            {
+            iSendData.Set(iPacketBuffer);
+            iPacketBuffer.Zero();
+            }
+       
+        }
+    else if (iState == ESendInProgress)
+        {
+        // Send the chunk data packet integral portion.
+        if (chunkIntegralLen)
+            {
+            iSendData.Set(iSendChunkData.Left(chunkIntegralLen));   
+            }
+    
+        // Buffer the chunk data packet residual portion.
+        if (chunkResidualLen)
+            {
+            __FLOG_VA((_L8("Buffering %d bytes"), chunkResidualLen));
+            iPacketBuffer.Append(iSendChunkData.Right(chunkResidualLen));  
+            }
+            
+        // All data has been consumed and/or buffered.
+        iSendChunkData.Set(NULL, 0);
+        }
+    else if (iState == ESendCompleting)
+        {
+        // Send all available chunk data.
+        iSendData.Set(iSendChunkData);
+            
+        // All data has been consumed.
+        iSendChunkData.Set(NULL, 0);
+        }
+
+    // Send the available data or reschedule to process the next chunk.
+    TUint sendBytes(iSendData.Length());
+    if (sendBytes)
+        {
+        __FLOG_VA((_L8("Send data length = %d bytes"), iSendData.Length()));
+#ifdef MTP_DEBUG_FLOG_HEX_DUMP 
+        __FLOG_HEXDUMP((iSendData, _L8("Sending data on socket ")));
+#endif
+        iSocket.Send(iSendData, 0, iStatus);
+        SetActive(); 
+        __FLOG(_L8("Request issued"));
+        }
+    else if (iState != ESendComplete)
+        {    
+        iStatus = KRequestPending;
+		CompleteSelf(KErrNone);      
+		}
+
+    __FLOG_VA((_L8("CSocketHandler state on exit = 0x%08X"), iState));
+	__FLOG(_L8("ProcessSendDataL - Exit"));
+	}
+
+
+	
+/**
+first the data header will be sent, 
+next the packet will be sent. 
+
+in case this is the last chunk, then the data header will have the last data 
+*/
+	
+void CPTPIPSocketHandlerBase::CreateAndSendDataPacketsL()	
+	{
+	__FLOG(_L8("CreateAndSendDataPacketsL - Entry"));
+	
+	// Create the data header and prepare to send it.
+	if (iState == ESendingDataHeader)
+		{
+		// if we've received a Cancel, then don't send further packets and return to the connection. 
+		if (iCancelReceived)
+			{
+			iState = ESendDataCancelled;
+			CompleteSelf(KErrNone);
+			__FLOG(_L8("Sending the PTPIP data "));
+			return;
+			}
+		else 
+			{
+			iChunkStatus = iSendDataSource->NextReadChunk(iSendChunkData);
+			TInt32 size = iPTPIPDataHeader->Size() + iSendChunkData.Size();
+			iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::EPacketLength, size);
+	   		__FLOG_VA((_L8("Size of ptpip packet data to be sent = %d bytes"), size));
+	
+			switch (iChunkStatus)
+		        {
+		    case KErrNone:
+		        iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::EPacketType, EPTPIPPacketTypeData);
+		        break;
+		        
+		    case KMTPChunkSequenceCompletion:
+		    	iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::EPacketType, EPTPIPPacketTypeEndData);
+		        break;
+		        
+		    default:
+		    	__FLOG(_L8("PTPIP Error :chunkStatus returned an error"));
+		        User::Leave(iChunkStatus);
+		        break;
+		        } 
+			// Set the iSendData to point to the ptpip header. 
+			TInt ret = iPTPIPDataHeader->FirstReadChunk(iSendData);
+			}
+ 		}
+	
+	// Set the iSendData to point to the actual data chunk. 
+	else if (iState == ESendingDataPacket)
+		{
+		iSendData.Set(iSendChunkData);
+    	__FLOG(_L8("Sending the PTPIP data "));
+		// if this is the last packet then set state. 	
+		if (iChunkStatus == KMTPChunkSequenceCompletion)
+			SetState(ESendDataPacketCompleting);
+		}
+	// We exited due to an error condition, 
+	else 
+		{
+        Panic(EPTPIPBadState);
+		}
+		
+    __FLOG_VA((_L8("Send data length = %d bytes"), iSendData.Length()));
+#ifdef MTP_DEBUG_FLOG_HEX_DUMP 
+    __FLOG_HEXDUMP((iSendData, _L8("Sending data on socket ")));
+#endif
+    iSocket.Send(iSendData, 0, iStatus);
+    SetActive();
+    __FLOG(_L8("Request issued"));
+	__FLOG(_L8("CreateAndSendDataPacketsL - Exit"));
+	}
+	
+	
+	
+/**
+Signals tthe data transfer controller that an asynchronous data send sequence 
+has completed.
+@leave One of the system wide error codes, if a processing failure occurs.
+@panic EPTPIPNotSupported In debug builds only, if the derived class has not fully 
+implemented the send data path.
+*/
+void CPTPIPSocketHandlerBase::SendDataCompleteL(TInt /*aError*/, const MMTPType& /*aSource*/)
+    {
+    __FLOG(_L8("CSocketHandler::SendDataCompleteL - Entry"));
+    __DEBUG_ONLY(Panic(EPTPIPNotSupported));
+    __FLOG(_L8("CSocketHandler::SendDataCompleteL - Exit"));
+    }	
+
+/**
+Forces the completion of a transfer in progress. 
+
+@param aReason error code describing the reason for cancelling.
+@leave Any of the system wide error codes.
+*/
+void CPTPIPSocketHandlerBase::CancelSendL(TInt aReason)
+	{
+	__FLOG(_L8("CSocketHandler::CancelSendL - Entry"));
+    
+	if ( (DataStreamDirection() == ESendingState) || (DataStreamDirection() == ESendDataState))
+		{
+		__FLOG(_L8("Cancel in ESendingState"));
+		// Cancel any outstanding request.
+		Cancel();
+		ResetSendDataStream();
+		SendDataCompleteL(aReason, *iSendDataSource);
+		}
+		
+	__FLOG(_L8("CSocketHandler::CancelSendL - Exit"));
+	}
+
+	
+//
+// Receive Data Functions
+//
+
+/**
+This receives the data over the socket. The data may be event or command data. 
+The buffer is provided by the fw in case its a data in.
+@param aSink The buffer into which the data from initiator will be received. 
+*/
+void CPTPIPSocketHandlerBase::ReceiveDataL(MMTPType& aSink)
+	{
+	__FLOG(_L8("ReceiveDataL - Entry"));
+	
+	// Set the state 
+	SetState(EReceiveInProgress);
+	
+	// The memory has come from the conection. In case it was a command receive
+	// then the connection itself had put the memory for the payload 
+	// from its members, 
+	// in case it was a data receive , then the payload buffer was provided by
+	// the framework. 
+	
+    iReceiveDataSink    = &aSink;
+    iReceiveDataCommit  = iReceiveDataSink->CommitRequired();
+    
+    InitiateFirstChunkReceiveL(); 
+	__FLOG(_L8("ReceiveDataL - Exit"));
+	}
+
+/**
+Reads the first chunk. Then validates what was read and adjusts the buffer accordingly. 
+*/
+void CPTPIPSocketHandlerBase::InitiateFirstChunkReceiveL()
+	{
+	__FLOG(_L8("InitiateFirstChunkReceiveL - Entry"));
+	
+	// sink refers to the buffer from connection.
+	// Now the ptr iReceiveChunkData is set to it first chunk.
+	iChunkStatus = iReceiveDataSink->FirstWriteChunk(iReceiveChunkData);
+	
+	// The first chunk is going to be read.
+	iIsFirstChunk = ETrue;
+    __FLOG_VA((_L8("Receive chunk capacity = %d bytes, length = %d bytes"), iReceiveChunkData.MaxLength(), iReceiveChunkData.Length()));
+    __FLOG_VA((_L8("Chunk status = %d"), iChunkStatus)); 
+
+	iReceiveData.Set(iReceiveChunkData);
+	
+	// start the timer. 
+	
+	// Make the async request to read on the socket and set ourselves active.
+	// once data is read on the socket, the iStatus will be changed by the comms framework. 
+ 	iSocket.Recv(iReceiveData, 0, iStatus);
+#ifdef MTP_DEBUG_FLOG_HEX_DUMP 
+    __FLOG_HEXDUMP((iReceiveData, _L8("Received data on socket ")));
+#endif
+
+    SetActive();
+    __FLOG(_L8("Request issued"));
+	__FLOG(_L8("InitiateFirstChunkReceiveL - Exit"));
+	}
+
+/**
+The first chunk received will have the length of the data and the ptpip packet type.
+Validate the ptp packet type, and set the correct packet type in the generic container.
+Set the state to complete or read further depending on the size.
+*/
+void CPTPIPSocketHandlerBase::ProcessFirstReceivedChunkL()
+	{
+	__FLOG(_L8("ProcessFirstReceivedChunkL - Entry"));
+    iIsFirstChunk = EFalse;
+    // Reset the data counter, This will be filled in later in the ResumeReceiveDataStreamL.
+    iPTPPacketLengthReceived = 0; 
+    iType = EPTPIPPacketTypeUndefined;
+    
+    // Parse and get the packet type, and packet length into type and iPTPPacketLength.
+    // This will also validate that the correct payload is set to get the remaining data. 
+    iType = ParsePTPIPHeaderL();
+	
+	// If the PTPIP type is not one of the standard expected types, 
+	// or not expected in the current transaction phase then we stop further receiving
+	// This current RunL will 
+	if (EPTPIPPacketTypeUndefined == iType ) 
+		{
+		__FLOG(_L8("PTPIP ERROR: Unexpected value in the type field of PTPIP header, appears corrupt"));
+		SetState(EReceiveComplete);
+		iStatus = KErrCorrupt;
+		}
+	
+	// If there is nothing to receive after the header, possible for probe packet.
+	else if (KPTPIPHeaderSize == iPTPPacketLength )
+		{
+		SetState(EReceiveComplete);
+		}
+	   
+    if (iState == EReceiveComplete)
+		{
+#ifdef MTP_DEBUG_FLOG_HEX_DUMP 
+        __FLOG_HEXDUMP((iReceiveChunkData, _L8("Received data ")));
+#endif
+
+		// Commit the received data if required.
+        if (iReceiveDataCommit)
+		    {
+		 	__FLOG(_L8("Commiting write data chunk"));
+	        iReceiveDataSink->CommitChunkL(iReceiveChunkData);       
+		    }
+		}
+	else
+		{
+		ResumeReceiveDataStreamL();
+		}
+
+	__FLOG(_L8("ProcessFirstReceivedChunkL - Exit"));
+	}
+
+
+
+/**
+Called after the first chunk has been received and we are expecting more packets. 
+This will be called repeatedly until all the packets have been received.
+*/
+void CPTPIPSocketHandlerBase::ResumeReceiveDataStreamL()
+	{
+	__FLOG(_L8("ResumeReceiveDataStreamL - Entry"));
+	TBool endStream(EFalse);
+	MMTPType *needCommit = NULL;
+		
+    // Process the received chunk (if any).
+   	iPTPPacketLengthReceived += iReceiveData.Length();
+   	__FLOG_VA((_L8("Data received = iPTPPacketLengthReceived = %d bytes, Data expected = iPTPPacketLength = %d"), iPTPPacketLengthReceived, iPTPPacketLength));
+   	
+	if (iPTPPacketLengthReceived == iPTPPacketLength)
+	   	{
+	   	SetState(EReceiveComplete);
+	   	endStream = ETrue;
+	   	
+	   	//if type  is data then end stream is not true
+	   	if (iType == EPTPIPPacketTypeData)
+	   	endStream = EFalse;
+	   	}
+
+    __FLOG_VA((_L8("Received = %d bytes, write data chunk capacity = %d bytes"), iReceiveChunkData.Length(), iReceiveChunkData.MaxLength()));		   
+#ifdef MTP_DEBUG_FLOG_HEX_DUMP 
+    __FLOG_HEXDUMP((iReceiveChunkData, _L8("Received data ")));
+#endif
+
+
+    // Commit the received data if required.
+	if (iReceiveDataCommit)
+         {
+         // if the chunk has been read completely.
+         // or if the end of stream has been reached. 
+         if (iReceiveChunkData.Length() == iReceiveChunkData.MaxLength()
+         	|| endStream )
+        	 {
+        	 needCommit = iReceiveDataSink->CommitChunkL(iReceiveChunkData);
+        	 }   
+         
+         
+         } 
+
+    // Fetch the next read data chunk.  
+    switch (iState)
+        {
+    case EReceiveInProgress:
+   	
+	// If we're in the middle of receiving a ptp data packet, 
+	// then at this stage we might have already used some of this chunk. 
+	// so reset its length to previously saved value
+    if (iUseOffset)
+		
+		{		
+		iUseOffset = EFalse;	
+		iReceiveChunkData.Set(iCurrentChunkData);
+		iChunkStatus = KErrNone;		
+		}
+    
+    	// get the next chunk only if this chunk has been read completely. 
+    	if (iReceiveChunkData.Length() == iReceiveChunkData.MaxLength())
+    		{
+    		
+    		iChunkStatus = iReceiveDataSink->NextWriteChunk(iReceiveChunkData);
+    		
+    		}
+    	__FLOG_VA((_L8("iReceiveChunkData pointer address is %08x"), iReceiveChunkData.Ptr()));
+	    break;
+        
+    case EReceiveComplete:
+        __FLOG(_L8("Write data chunk sequence complet"));
+        break;
+                  
+    case EIdle:
+    default:
+        __FLOG(_L8("Invalid stream state"));
+        Panic(EPTPIPBadState);
+        break;
+        }
+        
+    __FLOG_VA((_L8("Chunk status = %d"), iChunkStatus)); 
+        
+        
+    // If necessary, process the next chunk. 
+    if (iState != EReceiveComplete)
+        {
+        __FLOG_VA((_L8("Receive chunk capacity = %d bytes, length = %d bytes"), iReceiveChunkData.MaxLength(), iReceiveChunkData.Length()));
+        __FLOG_VA((_L8("iReceiveChunkData pointer address is %08x"), iReceiveChunkData.Ptr()));
+        
+        
+	        // When we reach the end of receiving a PTPIP packet, it is possible that our PTPIP chunk
+	        // length is greater than the actual data that is expected. 
+	        // eg when parameters 1to 5 are not set in a PTPIP request. In this case 
+	        // we need to read the remaining length which will be less than the max length of the chunk.
+	        TUint32 remainingLen = iPTPPacketLength - iPTPPacketLengthReceived;
+	        if (remainingLen < (iReceiveChunkData.MaxLength() - iReceiveChunkData.Length()))
+	        	{
+	        	iReceiveData.Set(const_cast<TUint8*>(iReceiveChunkData.Ptr() + iReceiveChunkData.Length()), 
+	        	                 0,
+	        					remainingLen); 
+	        	}
+	        else
+	        	{
+	        	iReceiveData.Set(const_cast<TUint8*>(iReceiveChunkData.Ptr() + iReceiveChunkData.Length()), 
+	        					0, 
+	        					iReceiveChunkData.MaxLength() - iReceiveChunkData.Length());
+	        	}        	
+	       
+        	
+        	
+	        __FLOG_VA((_L8("Length read this time is= %d"), iReceiveData.MaxLength()));
+        	
+        
+ 		iSocket.Recv(iReceiveData, 0, iStatus);
+#ifdef MTP_DEBUG_FLOG_HEX_DUMP 
+    __FLOG_HEXDUMP((iReceiveData, _L8("Received data on socket ")));
+#endif 		
+        SetActive();
+        __FLOG(_L8("Request issued"));
+        }
+        if(needCommit != NULL)
+            {
+            TPtr8 tmp(NULL, 0, 0);
+            needCommit->CommitChunkL(tmp);
+            }
+ 	__FLOG(_L8("ResumeReceiveDataStreamL - Exit"));
+	}
+
+/**
+Signals the data transfer controller that an asynchronous data receive sequence 
+has completed.
+@leave One of the system wide error codes, if a processing failure occurs.
+@panic EPTPIPNotSupported In debug builds only, if the derived class has not fully 
+implemented the receive data path.
+*/
+void CPTPIPSocketHandlerBase::ReceiveDataCompleteL(TInt /*aError*/, MMTPType& /*aSink*/)
+    {
+    __FLOG(_L8("CSocketHandler::ReceiveDataCompleteL - Entry"));
+    __DEBUG_ONLY(Panic(EPTPIPNotSupported));
+    __FLOG(_L8("CSocketHandler::ReceiveDataCompleteL - Exit"));
+    }
+
+/**
+Forces the completion of a transfer in progress. 
+
+@param aReason error code describing the reason for cancelling.
+@leave Any of the system wide error codes.
+*/
+void CPTPIPSocketHandlerBase::CancelReceiveL(TInt aReason)
+	{
+	__FLOG(_L8("CSocketHandler::CancelReceiveL - Entry"));
+     
+    if (DataStreamDirection() == EReceivingState)
+	    {
+		__FLOG(_L8("Cancel in EReceivingState"));            
+	    // Cancel any outstanding request.
+    	Cancel();  
+
+        // Notify the connection and reset the receive data stream.
+		ResetReceiveDataStream();
+        ReceiveDataCompleteL(aReason, *iReceiveDataSink);
+	    }
+	    
+    __FLOG(_L8("CSocketHandler::CancelReceiveL - Exit"));	
+	}
+
+//
+// Getters , Setters and other helper functions
+//
+
+CPTPIPConnection& CPTPIPSocketHandlerBase::Connection()
+	{
+	return iConnection;
+	}
+
+RSocket& CPTPIPSocketHandlerBase::Socket()
+	{
+	return iSocket;	
+	}
+
+
+void CPTPIPSocketHandlerBase::ResetSendDataStream()
+    {
+	__FLOG(_L8("CSocketHandler::ResetSendDataStream - Entry"));
+    iSendChunkData.Set(NULL, 0);
+    iSendData.Set(NULL, 0);
+    iSendDataSource = NULL;
+    iCancelReceived = EFalse;
+    SetState(EIdle);
+	__FLOG(_L8("CSocketHandler::ResetSendDataStream - Exit"));
+    }
+    
+void CPTPIPSocketHandlerBase::ResetReceiveDataStream()
+    {
+	__FLOG(_L8("CSocketHandler::ResetReceiveDataStream - Entry"));
+    iReceiveChunkData.Set(NULL, 0, 0);
+    iReceiveData.Set(NULL, 0, 0);
+    iReceiveDataSink = NULL;
+    iCancelReceived = EFalse;
+    SetState(EIdle);
+	__FLOG(_L8("CSocketHandler::ResetReceiveDataStream - Exit"));
+    }
+
+    
+void CPTPIPSocketHandlerBase::SetState(TSocketState aState)
+	{
+	__FLOG(_L8("SetState - Entry"));
+	iState = aState;
+	__FLOG_VA((_L8(" state = 0x%08X"), iState));
+	__FLOG(_L8("SetState - Exit"));
+	}
+	
+void CPTPIPSocketHandlerBase::CompleteSelf(TInt aCompletionCode)
+     {
+     SetActive();
+     TRequestStatus* stat = &iStatus;
+     User::RequestComplete(stat, aCompletionCode);
+     }	
+
+/**
+Provides the current data stream direction, sending or receiving
+*/
+TInt32 CPTPIPSocketHandlerBase::DataStreamDirection() const
+    {
+    return (iState & EStateDirection);
+    }
+    
+void CPTPIPSocketHandlerBase::SetSocket(RSocket& aSocket)
+	{
+	iSocket = aSocket;	
+	}
+
+/**
+Ignore any errors in setting the socket options
+*/
+void CPTPIPSocketHandlerBase::SetSocketOptions()
+	{
+	TInt error=iSocket.SetOpt(KSoTcpKeepAlive,KSolInetTcp,1);
+	__FLOG_VA((_L8(" setting the keep alive option returned = %d"), error));
+	error=iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1);
+	__FLOG_VA((_L8(" setting the no delay to disable Nagle's algo returned %d"), error));
+	}