mtptransports/mtpptpiptransport/ptpipplugin/src/cptpipsockhandlerbase.cpp
changeset 0 d0791faffa3f
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // cptpipsockethandler.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @internalComponent
       
    20 */
       
    21 
       
    22 #include "cptpipsockhandlerbase.h"
       
    23 #include "cptpipconnection.h"
       
    24 #include "ptpippanic.h"
       
    25 
       
    26 const TUint32 KPTPIPHeaderSize = 8;
       
    27 const TUint KMaxPacketSixe   = 16;
       
    28 const TUint64 KMaxPTPIPPacketSize = 0x18FF4; // 100 KB - 12
       
    29 
       
    30 //#define MTP_DEBUG_FLOG_HEX_DUMP
       
    31 
       
    32 #define UNUSED_VAR(a) (a)=(a)
       
    33 
       
    34 /**
       
    35 Constructor 
       
    36 */
       
    37 CPTPIPSocketHandlerBase::CPTPIPSocketHandlerBase(CPTPIPConnection& aConnection, TPriority priority ) : 
       
    38 						CActive(priority),
       
    39 						iChunkStatus(0),
       
    40 						iSendChunkData(NULL, 0),
       
    41 						iSendData(NULL, 0),
       
    42 						iReceiveChunkData(NULL, 0),
       
    43 						iPTPPacketLength(0),
       
    44 						iState(EIdle),
       
    45 						iPacketBuffer(NULL),
       
    46 						iPacketSizeMax(NULL),
       
    47 						iReceiveData(NULL, 0),
       
    48 						iIsFirstChunk(EFalse),
       
    49 						iPTPPacketLengthReceived(0),
       
    50 						iReceiveDataCommit(EFalse),
       
    51 						iSendHeaderData(NULL, 0),
       
    52 						iPTPIPDataHeader(NULL),
       
    53 						iConnection(aConnection),
       
    54 						iReceiveDataSink(NULL),
       
    55 						iSendDataSource(NULL),
       
    56 						iCurrentChunkData(NULL,0,0)
       
    57 	{
       
    58 	CActiveScheduler::Add(this);
       
    59 	}
       
    60 
       
    61 
       
    62 
       
    63 /**
       
    64 Second phase constructor.
       
    65 */
       
    66 #ifdef __FLOG_ACTIVE    
       
    67 void CPTPIPSocketHandlerBase::ConstructL(const TDesC8& aComponentName)
       
    68 #else
       
    69 void CPTPIPSocketHandlerBase::ConstructL()
       
    70 #endif
       
    71     {
       
    72     __FLOG_OPEN(KMTPSubsystem, aComponentName);
       
    73     __FLOG(_L8("CSocketHandler::ConstructL - Entry"));
       
    74     iPacketSizeMax = KMaxPacketSixe; 
       
    75     iPacketBuffer.ReAllocL(iPacketSizeMax);
       
    76     iPTPIPDataHeader = CPTPIPDataContainer::NewL();
       
    77     __FLOG(_L8("CSocketHandler::ConstructL - Exit"));
       
    78     }
       
    79   
       
    80  /**
       
    81  Destructor
       
    82  */  
       
    83  CPTPIPSocketHandlerBase::~CPTPIPSocketHandlerBase()
       
    84  {
       
    85     __FLOG(_L8("CSocketHandler::~CSocketHandler - Entry"));
       
    86     Cancel();
       
    87     iPacketBuffer.Close();
       
    88     iSocket.Close();
       
    89     delete iPTPIPDataHeader;
       
    90     __FLOG(_L8("CSocketHandler::~CSocketHandler - Exit"));
       
    91     __FLOG_CLOSE;
       
    92  }
       
    93 
       
    94 
       
    95 //
       
    96 // CActive Functions
       
    97 //
       
    98 
       
    99 /**
       
   100  This will be called after every chunk is sent or received over the socket. 
       
   101 */
       
   102 void CPTPIPSocketHandlerBase::RunL()
       
   103 	{
       
   104 	__FLOG(_L8("RunL - Entry"));
       
   105     __FLOG_VA((_L8("Current State is 0x%08X, and status is %d"), iState, iStatus.Int()));	
       
   106     
       
   107 	switch ( DataStreamDirection() )
       
   108 		{
       
   109 	case EReceivingState:
       
   110 	
       
   111         __FLOG_VA((_L8("Receive data completion status = %d"), iStatus.Int()));
       
   112         if (iState == EReceiveFastInProgress)
       
   113         	{
       
   114         	InitiateFirstChunkReceiveL(); 
       
   115         	}
       
   116         
       
   117         else if (iStatus != KErrNone)
       
   118             {
       
   119             // Abnormal completion.
       
   120             __FLOG_VA((_L8("PTPIP Error: Receive data completed with error = %d"), iStatus.Int()));
       
   121             SetState(EReceiveComplete);
       
   122             }
       
   123         else if (iState != EReceiveComplete)
       
   124             {
       
   125 	        // Update the chunk data length. We use the iReceiveData variable with the socket 
       
   126 	        // so only its length gets updated on receive. 
       
   127 	        
       
   128 	        // However during remaining processing we use iReceiveChunkData, so update its len.
       
   129             iReceiveChunkData.SetLength(iReceiveChunkData.Length() + iReceiveData.Length());
       
   130             if (iIsFirstChunk)
       
   131 	            {
       
   132 	            // process the first chunk.
       
   133 	            ProcessFirstReceivedChunkL();  
       
   134 	            }
       
   135 	        else
       
   136 		        {
       
   137 		        ResumeReceiveDataStreamL(); 
       
   138 		        }
       
   139             }
       
   140             
       
   141         if (iState == EReceiveComplete)
       
   142             {             
       
   143             // Save the pointer to the last populated location on the current chunk            
       
   144             iCurrentChunkData.Set(iReceiveChunkData);             
       
   145             // Reset the receive data stream and notify the connection.
       
   146             MMTPType& data(*iReceiveDataSink);
       
   147             ResetReceiveDataStream();
       
   148             TRAPD(err, ReceiveDataCompleteL(iStatus.Int(), data));
       
   149             if (err != KErrNone)
       
   150             	{
       
   151             	__FLOG_VA((_L8("Framework threw an error from ReceiveDataCompleteL = %d"), err)); 
       
   152             	ReceiveDataCompleteL(err, data);
       
   153             	}
       
   154             }
       
   155         break;
       
   156         
       
   157 	case ESendingState:
       
   158 		// Special case for handling the sending of init ack, handled in the derived class.
       
   159 		if (HandleInitAck())
       
   160 			{
       
   161 			ResetSendDataStream();
       
   162 			break;
       
   163 			}
       
   164 
       
   165         __FLOG_VA((_L8("Send data stream completion status = %d"), iStatus.Int())); 
       
   166         if (iStatus != KErrNone)
       
   167             {
       
   168             // Abnormal completion.
       
   169             SetState(ESendComplete);
       
   170             }
       
   171 		else
       
   172 			{
       
   173             ProcessSendDataL(); 
       
   174             }
       
   175          if (iState == ESendComplete)
       
   176             {
       
   177             // Reset the send data stream and notify the connection.
       
   178             const MMTPType& data(*iSendDataSource);
       
   179             ResetSendDataStream();
       
   180             TRAPD(err, SendDataCompleteL(iStatus.Int(), data));
       
   181             if (err != KErrNone)
       
   182             	{
       
   183             	__FLOG_VA((_L8("Framework threw an error from SendDataCompleteL = %d"), err)); 
       
   184             	SendDataCompleteL(err, data);
       
   185             	}
       
   186             }
       
   187         break;
       
   188         
       
   189 	case ESendDataState:
       
   190 		if (iStatus != KErrNone)
       
   191             {
       
   192             // Abnormal completion.
       
   193             SetState(ESendDataComplete);
       
   194             }
       
   195  		else if (iState == ESendingDataHeader)
       
   196 			{
       
   197 			SetState(ESendingDataPacket);	
       
   198 			}
       
   199 		else if (iState == ESendingDataPacket)
       
   200 			{
       
   201 			SetState(ESendingDataHeader);		
       
   202 			}
       
   203 		else if (iState == ESendDataPacketCompleting)
       
   204 			{
       
   205 			SetState(ESendDataComplete);	
       
   206 			}
       
   207 		
       
   208 		if (iState == ESendDataComplete || iState == ESendDataCancelled)
       
   209             {
       
   210             // Reset the send data stream and notify the connection.
       
   211             const MMTPType& data(*iSendDataSource);
       
   212             ResetSendDataStream();
       
   213             SendDataCompleteL(iStatus.Int(), data);
       
   214             }
       
   215    		else
       
   216 	        {
       
   217 	        CreateAndSendDataPacketsL();	
       
   218 	        }
       
   219 		break;
       
   220 		
       
   221 	default:
       
   222 		
       
   223 		__FLOG_VA((_L8("PTPIP ERROR: Invalid state of the sockethandler: RunL should not be called with 0x%08X state"), iState));	
       
   224         Panic(EPTPIPBadState);
       
   225 		break;
       
   226 		
       
   227 		}// switch
       
   228 		
       
   229     __FLOG_VA((_L8("IsActive = %d"), IsActive()));
       
   230 	__FLOG(_L8("RunL - Exit"));
       
   231 	}
       
   232 
       
   233 /**
       
   234 Tell the Asynchronous Service provider to cancel all outstanding operations. 
       
   235 */
       
   236 void CPTPIPSocketHandlerBase::DoCancel()
       
   237 	{
       
   238 	__FLOG(_L8("DoCancel - Entry"));
       
   239     switch (iState & EStateDirection)
       
   240         {
       
   241     case EReceivingState:
       
   242         __FLOG(_L8("Cancelling receive on the socket"));
       
   243         iSocket.CancelRecv();
       
   244         ResetReceiveDataStream();
       
   245         break;
       
   246 
       
   247     case ESendingState:    
       
   248         __FLOG(_L8("Cancelling send on the socket"));
       
   249         iSocket.CancelSend();
       
   250         ResetSendDataStream();
       
   251         break;
       
   252         
       
   253     case ESendDataState:
       
   254 	    __FLOG(_L8("Cancelling send on the socket"));
       
   255 	    iSocket.CancelSend();
       
   256 	    ResetSendDataStream();
       
   257 	    break;
       
   258 	    
       
   259     default:
       
   260         break;
       
   261 		}
       
   262 	__FLOG(_L8("DoCancel - Exit"));
       
   263 	}
       
   264 
       
   265 /**
       
   266 This is invoked when a panic occurs during RunL. 
       
   267 To handle this , all operations are cancelled, and if we were processing
       
   268 a send or recv operation, we complete it with the error code. 
       
   269 @param - The error code with which RunL left
       
   270 */
       
   271 TInt CPTPIPSocketHandlerBase::RunError(TInt aError)
       
   272 	{
       
   273 	__FLOG(_L8("RunError - Entry"));
       
   274     __FLOG_VA((_L8("Error reported is  %d and state is 0x%08X, and status is %d"), aError, iState, iStatus.Int()));
       
   275  
       
   276     // Cancel any outstanding request.
       
   277     Cancel();  
       
   278     
       
   279     // Notify the protocol layer of the error.
       
   280     TInt32 streamDirection = DataStreamDirection();
       
   281     if (streamDirection == EReceivingState)
       
   282 	    {
       
   283 		__FLOG(_L8("Error in EReceivingState"));            
       
   284         // Notify the connection and reset the receive data stream.
       
   285         MMTPType& data(*iReceiveDataSink);
       
   286         ResetReceiveDataStream();
       
   287         TRAPD(err, ReceiveDataCompleteL(aError, data));
       
   288         UNUSED_VAR(err);
       
   289 	    }
       
   290 	else if (streamDirection == ESendingState || (streamDirection == ESendDataState))
       
   291 		{
       
   292 		__FLOG(_L8("Error in ESendingState"));
       
   293         // Notify the connection and reset the send data stream.
       
   294         const MMTPType& data(*iSendDataSource);
       
   295         ResetSendDataStream();
       
   296         TRAPD(err, SendDataCompleteL(aError, data));
       
   297         UNUSED_VAR(err);
       
   298 		}
       
   299     // We are neither in sending nor receiving state, the error in RunL
       
   300     // must have originated from the MTP framework, tell the connection 
       
   301     // to stop.
       
   302 	else 
       
   303 		{
       
   304 		Connection().HandleError(aError);
       
   305 		}
       
   306  
       
   307 	__FLOG(_L8("RunError - Exit"));
       
   308 	return KErrNone;
       
   309 	}
       
   310 	
       
   311 //
       
   312 // Send Data Functions
       
   313 //
       
   314 
       
   315 /**
       
   316 This sends the data over the socket. The buffer is provided by the MTP fw.
       
   317 @param aData - The data buffer to be sent
       
   318 @param aTransactionId - The id of the current onging transaction. This is needed 
       
   319  in case the data in R to I phase has to be split into multiple PTPIP data packets
       
   320  In such a case the PTPIP Data packet header needs to be created which contains the tran id. 
       
   321 */
       
   322 void CPTPIPSocketHandlerBase::SendDataL(const MMTPType& aData, TUint32 aTransactionId )
       
   323 	{
       
   324 	__FLOG(_L8("SendDataL - Entry"));
       
   325     iSendDataSource = &aData;
       
   326 	TUint64 size = iSendDataSource->Size();
       
   327     __FLOG_VA((_L8("Size of total data to be sent = %ld bytes"), size));
       
   328 	
       
   329 	// if the data is less than KMaxPTPIPPacketSize then it can be sent in a shot, 
       
   330 	// Currently the ptp ip packet has the end data packet already, so it can be sent directly. 
       
   331 	if ( size < KMaxPTPIPPacketSize)
       
   332 		{
       
   333 		__FLOG(_L8("Size of data is less than KMaxPTPIPPacketSize, sending as one ptpip packet."));
       
   334 	    SetState(ESendInitialising);
       
   335 		ProcessSendDataL();
       
   336 		}
       
   337 		
       
   338 	// if the data is greater than KMaxPTPIPPacketSize then it needs to be split into 
       
   339 	// multiple packets. The PTPIP header will be locally created , and sent
       
   340 	// and then one chunk will be sent as one PTPIP packet.
       
   341 	else 
       
   342 		{
       
   343 		__FLOG(_L8("Size of data is more than KMaxPTPIPPacketSize, sending as multiple ptpip packets."));
       
   344 		iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::ETransactionId, aTransactionId);
       
   345 		iPTPIPDataHeader->SetPayloadL(NULL);
       
   346 		
       
   347 		// We can ignore this header, since we create our own while sending each packet.
       
   348 		iChunkStatus = iSendDataSource->FirstReadChunk(iSendChunkData);
       
   349         
       
   350 		SetState(ESendingDataHeader);
       
   351 		CreateAndSendDataPacketsL();
       
   352 		}
       
   353 	
       
   354 	__FLOG(_L8("SendDataL - Exit"));
       
   355 	}
       
   356 
       
   357 /**
       
   358 Using the same algo as the USB send, to buffer into a local buffer, and sending 
       
   359 only when buffer exceeds the max socket send size, or all chunks have been buffered. 
       
   360 */
       
   361 void CPTPIPSocketHandlerBase::ProcessSendDataL()
       
   362 	{
       
   363 	__FLOG(_L8("ProcessSendDataL - Entry"));	
       
   364 	
       
   365     iSendData.Set(KNullDesC8);
       
   366 
       
   367     TUint chunkAvailableLen(iSendChunkData.Length());
       
   368     if (!chunkAvailableLen)
       
   369         {    
       
   370         // Fetch the next read data chunk. 
       
   371         switch (iState)
       
   372             {
       
   373         case ESendInitialising:
       
   374             __FLOG(_L8("Fetching first read data chunk"));
       
   375             iChunkStatus = iSendDataSource->FirstReadChunk(iSendChunkData);
       
   376             iPacketBuffer.Zero();
       
   377             break;
       
   378             
       
   379         case ESendInProgress:
       
   380             __FLOG(_L8("Fetching next read data chunk"));
       
   381             iChunkStatus = iSendDataSource->NextReadChunk(iSendChunkData);
       
   382             break;
       
   383             
       
   384         case ESendCompleting:
       
   385             break;            
       
   386            
       
   387         case EIdle:
       
   388         default:
       
   389             __FLOG(_L8("Invalid send data stream state"));
       
   390             Panic(EPTPIPBadState);
       
   391             break;
       
   392             }
       
   393         
       
   394         // Fetch the new chunk data size available.
       
   395         chunkAvailableLen = iSendChunkData.Length();
       
   396         
       
   397         // Update data stream state.
       
   398         switch (iChunkStatus)
       
   399             {
       
   400         case KErrNone:
       
   401             SetState(ESendInProgress);
       
   402             break;
       
   403             
       
   404         case KMTPChunkSequenceCompletion:
       
   405             if (iState == ESendCompleting)
       
   406                 {
       
   407                 SetState(ESendComplete);
       
   408                 }
       
   409             else
       
   410                 {
       
   411                 SetState(ESendCompleting);
       
   412                 }
       
   413             break;
       
   414             
       
   415           case KErrNotFound:// CMTPTypeFile returns this when it has zero length
       
   416         	if( 0 == iSendChunkData.Length() )
       
   417         		{
       
   418                 if (iState == ESendCompleting)
       
   419                 {
       
   420                 SetState(ESendComplete);
       
   421                 }
       
   422             else
       
   423                 {
       
   424                 SetState(ESendCompleting);
       
   425                 }
       
   426                 }  
       
   427                 break;
       
   428         default:
       
   429             User::Leave(iChunkStatus);
       
   430             break;
       
   431             }          
       
   432         }
       
   433     __FLOG_VA((_L8("Chunk status = %d"), iChunkStatus));
       
   434     
       
   435     // Process the buffered residual and/or available chunk data.
       
   436     TUint bufferedLen(iPacketBuffer.Length());
       
   437     TUint chunkIntegralLen((chunkAvailableLen / iPacketSizeMax) * iPacketSizeMax);
       
   438     TUint chunkResidualLen(chunkAvailableLen % iPacketSizeMax);
       
   439     __FLOG_VA((_L8("Buffered residual data = %d bytes"), bufferedLen));
       
   440     __FLOG_VA((_L8("Chunk data available = %d bytes"), chunkAvailableLen));
       
   441     __FLOG_VA((_L8("Chunk data packet integral portion = %d bytes"), chunkIntegralLen));
       
   442     __FLOG_VA((_L8("Chunk data packet residual portion = %d bytes"), chunkResidualLen));
       
   443     
       
   444     if (bufferedLen)
       
   445         {
       
   446         // Data is buffered in the packet buffer. Fill the available packet buffer space.
       
   447         if (chunkAvailableLen)
       
   448             {
       
   449             // Fill the packet buffer.
       
   450             TUint consumedLen(0);
       
   451             TUint unconsumedLen(0);
       
   452             TUint capacity(iPacketBuffer.MaxLength() - iPacketBuffer.Length());
       
   453             if (chunkAvailableLen > capacity)
       
   454                 {
       
   455                 consumedLen     = capacity;
       
   456                 unconsumedLen   = (chunkAvailableLen - consumedLen);              
       
   457                 }
       
   458             else
       
   459                 {
       
   460                 consumedLen = chunkAvailableLen;
       
   461                 }
       
   462             __FLOG_VA((_L8("Buffering %d bytes"), consumedLen));
       
   463             iPacketBuffer.Append(iSendChunkData.Left(consumedLen));
       
   464             
       
   465             // Update the available chunk data to reflect only the unconsumed portion.
       
   466             __FLOG_VA((_L8("Residual chunk data = %d bytes"), unconsumedLen));
       
   467             if (unconsumedLen)
       
   468                 {
       
   469                 iSendChunkData.Set(iSendChunkData.Right(unconsumedLen));
       
   470                 }
       
   471             else
       
   472                 {
       
   473                 iSendChunkData.Set(NULL, 0);                    
       
   474                 }
       
   475             }
       
   476         
       
   477         // Send the packet buffer when full.
       
   478         if ((iState == ESendCompleting) || (iPacketBuffer.Size() == iPacketBuffer.MaxSize()))
       
   479             {
       
   480             iSendData.Set(iPacketBuffer);
       
   481             iPacketBuffer.Zero();
       
   482             }
       
   483        
       
   484         }
       
   485     else if (iState == ESendInProgress)
       
   486         {
       
   487         // Send the chunk data packet integral portion.
       
   488         if (chunkIntegralLen)
       
   489             {
       
   490             iSendData.Set(iSendChunkData.Left(chunkIntegralLen));   
       
   491             }
       
   492     
       
   493         // Buffer the chunk data packet residual portion.
       
   494         if (chunkResidualLen)
       
   495             {
       
   496             __FLOG_VA((_L8("Buffering %d bytes"), chunkResidualLen));
       
   497             iPacketBuffer.Append(iSendChunkData.Right(chunkResidualLen));  
       
   498             }
       
   499             
       
   500         // All data has been consumed and/or buffered.
       
   501         iSendChunkData.Set(NULL, 0);
       
   502         }
       
   503     else if (iState == ESendCompleting)
       
   504         {
       
   505         // Send all available chunk data.
       
   506         iSendData.Set(iSendChunkData);
       
   507             
       
   508         // All data has been consumed.
       
   509         iSendChunkData.Set(NULL, 0);
       
   510         }
       
   511 
       
   512     // Send the available data or reschedule to process the next chunk.
       
   513     TUint sendBytes(iSendData.Length());
       
   514     if (sendBytes)
       
   515         {
       
   516         __FLOG_VA((_L8("Send data length = %d bytes"), iSendData.Length()));
       
   517 #ifdef MTP_DEBUG_FLOG_HEX_DUMP 
       
   518         __FLOG_HEXDUMP((iSendData, _L8("Sending data on socket ")));
       
   519 #endif
       
   520         iSocket.Send(iSendData, 0, iStatus);
       
   521         SetActive(); 
       
   522         __FLOG(_L8("Request issued"));
       
   523         }
       
   524     else if (iState != ESendComplete)
       
   525         {    
       
   526         iStatus = KRequestPending;
       
   527 		CompleteSelf(KErrNone);      
       
   528 		}
       
   529 
       
   530     __FLOG_VA((_L8("CSocketHandler state on exit = 0x%08X"), iState));
       
   531 	__FLOG(_L8("ProcessSendDataL - Exit"));
       
   532 	}
       
   533 
       
   534 
       
   535 	
       
   536 /**
       
   537 first the data header will be sent, 
       
   538 next the packet will be sent. 
       
   539 
       
   540 in case this is the last chunk, then the data header will have the last data 
       
   541 */
       
   542 	
       
   543 void CPTPIPSocketHandlerBase::CreateAndSendDataPacketsL()	
       
   544 	{
       
   545 	__FLOG(_L8("CreateAndSendDataPacketsL - Entry"));
       
   546 	
       
   547 	// Create the data header and prepare to send it.
       
   548 	if (iState == ESendingDataHeader)
       
   549 		{
       
   550 		// if we've received a Cancel, then don't send further packets and return to the connection. 
       
   551 		if (iCancelReceived)
       
   552 			{
       
   553 			iState = ESendDataCancelled;
       
   554 			CompleteSelf(KErrNone);
       
   555 			__FLOG(_L8("Sending the PTPIP data "));
       
   556 			return;
       
   557 			}
       
   558 		else 
       
   559 			{
       
   560 			iChunkStatus = iSendDataSource->NextReadChunk(iSendChunkData);
       
   561 			TInt32 size = iPTPIPDataHeader->Size() + iSendChunkData.Size();
       
   562 			iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::EPacketLength, size);
       
   563 	   		__FLOG_VA((_L8("Size of ptpip packet data to be sent = %d bytes"), size));
       
   564 	
       
   565 			switch (iChunkStatus)
       
   566 		        {
       
   567 		    case KErrNone:
       
   568 		        iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::EPacketType, EPTPIPPacketTypeData);
       
   569 		        break;
       
   570 		        
       
   571 		    case KMTPChunkSequenceCompletion:
       
   572 		    	iPTPIPDataHeader->SetUint32L(CPTPIPDataContainer::EPacketType, EPTPIPPacketTypeEndData);
       
   573 		        break;
       
   574 		        
       
   575 		    default:
       
   576 		    	__FLOG(_L8("PTPIP Error :chunkStatus returned an error"));
       
   577 		        User::Leave(iChunkStatus);
       
   578 		        break;
       
   579 		        } 
       
   580 			// Set the iSendData to point to the ptpip header. 
       
   581 			TInt ret = iPTPIPDataHeader->FirstReadChunk(iSendData);
       
   582 			}
       
   583  		}
       
   584 	
       
   585 	// Set the iSendData to point to the actual data chunk. 
       
   586 	else if (iState == ESendingDataPacket)
       
   587 		{
       
   588 		iSendData.Set(iSendChunkData);
       
   589     	__FLOG(_L8("Sending the PTPIP data "));
       
   590 		// if this is the last packet then set state. 	
       
   591 		if (iChunkStatus == KMTPChunkSequenceCompletion)
       
   592 			SetState(ESendDataPacketCompleting);
       
   593 		}
       
   594 	// We exited due to an error condition, 
       
   595 	else 
       
   596 		{
       
   597         Panic(EPTPIPBadState);
       
   598 		}
       
   599 		
       
   600     __FLOG_VA((_L8("Send data length = %d bytes"), iSendData.Length()));
       
   601 #ifdef MTP_DEBUG_FLOG_HEX_DUMP 
       
   602     __FLOG_HEXDUMP((iSendData, _L8("Sending data on socket ")));
       
   603 #endif
       
   604     iSocket.Send(iSendData, 0, iStatus);
       
   605     SetActive();
       
   606     __FLOG(_L8("Request issued"));
       
   607 	__FLOG(_L8("CreateAndSendDataPacketsL - Exit"));
       
   608 	}
       
   609 	
       
   610 	
       
   611 	
       
   612 /**
       
   613 Signals tthe data transfer controller that an asynchronous data send sequence 
       
   614 has completed.
       
   615 @leave One of the system wide error codes, if a processing failure occurs.
       
   616 @panic EPTPIPNotSupported In debug builds only, if the derived class has not fully 
       
   617 implemented the send data path.
       
   618 */
       
   619 void CPTPIPSocketHandlerBase::SendDataCompleteL(TInt /*aError*/, const MMTPType& /*aSource*/)
       
   620     {
       
   621     __FLOG(_L8("CSocketHandler::SendDataCompleteL - Entry"));
       
   622     __DEBUG_ONLY(Panic(EPTPIPNotSupported));
       
   623     __FLOG(_L8("CSocketHandler::SendDataCompleteL - Exit"));
       
   624     }	
       
   625 
       
   626 /**
       
   627 Forces the completion of a transfer in progress. 
       
   628 
       
   629 @param aReason error code describing the reason for cancelling.
       
   630 @leave Any of the system wide error codes.
       
   631 */
       
   632 void CPTPIPSocketHandlerBase::CancelSendL(TInt aReason)
       
   633 	{
       
   634 	__FLOG(_L8("CSocketHandler::CancelSendL - Entry"));
       
   635     
       
   636 	if ( (DataStreamDirection() == ESendingState) || (DataStreamDirection() == ESendDataState))
       
   637 		{
       
   638 		__FLOG(_L8("Cancel in ESendingState"));
       
   639 		// Cancel any outstanding request.
       
   640 		Cancel();
       
   641 		ResetSendDataStream();
       
   642 		SendDataCompleteL(aReason, *iSendDataSource);
       
   643 		}
       
   644 		
       
   645 	__FLOG(_L8("CSocketHandler::CancelSendL - Exit"));
       
   646 	}
       
   647 
       
   648 	
       
   649 //
       
   650 // Receive Data Functions
       
   651 //
       
   652 
       
   653 /**
       
   654 This receives the data over the socket. The data may be event or command data. 
       
   655 The buffer is provided by the fw in case its a data in.
       
   656 @param aSink The buffer into which the data from initiator will be received. 
       
   657 */
       
   658 void CPTPIPSocketHandlerBase::ReceiveDataL(MMTPType& aSink)
       
   659 	{
       
   660 	__FLOG(_L8("ReceiveDataL - Entry"));
       
   661 	
       
   662 	// Set the state 
       
   663 	SetState(EReceiveInProgress);
       
   664 	
       
   665 	// The memory has come from the conection. In case it was a command receive
       
   666 	// then the connection itself had put the memory for the payload 
       
   667 	// from its members, 
       
   668 	// in case it was a data receive , then the payload buffer was provided by
       
   669 	// the framework. 
       
   670 	
       
   671     iReceiveDataSink    = &aSink;
       
   672     iReceiveDataCommit  = iReceiveDataSink->CommitRequired();
       
   673     
       
   674     InitiateFirstChunkReceiveL(); 
       
   675 	__FLOG(_L8("ReceiveDataL - Exit"));
       
   676 	}
       
   677 
       
   678 /**
       
   679 Reads the first chunk. Then validates what was read and adjusts the buffer accordingly. 
       
   680 */
       
   681 void CPTPIPSocketHandlerBase::InitiateFirstChunkReceiveL()
       
   682 	{
       
   683 	__FLOG(_L8("InitiateFirstChunkReceiveL - Entry"));
       
   684 	
       
   685 	// sink refers to the buffer from connection.
       
   686 	// Now the ptr iReceiveChunkData is set to it first chunk.
       
   687 	iChunkStatus = iReceiveDataSink->FirstWriteChunk(iReceiveChunkData);
       
   688 	
       
   689 	// The first chunk is going to be read.
       
   690 	iIsFirstChunk = ETrue;
       
   691     __FLOG_VA((_L8("Receive chunk capacity = %d bytes, length = %d bytes"), iReceiveChunkData.MaxLength(), iReceiveChunkData.Length()));
       
   692     __FLOG_VA((_L8("Chunk status = %d"), iChunkStatus)); 
       
   693 
       
   694 	iReceiveData.Set(iReceiveChunkData);
       
   695 	
       
   696 	// start the timer. 
       
   697 	
       
   698 	// Make the async request to read on the socket and set ourselves active.
       
   699 	// once data is read on the socket, the iStatus will be changed by the comms framework. 
       
   700  	iSocket.Recv(iReceiveData, 0, iStatus);
       
   701 #ifdef MTP_DEBUG_FLOG_HEX_DUMP 
       
   702     __FLOG_HEXDUMP((iReceiveData, _L8("Received data on socket ")));
       
   703 #endif
       
   704 
       
   705     SetActive();
       
   706     __FLOG(_L8("Request issued"));
       
   707 	__FLOG(_L8("InitiateFirstChunkReceiveL - Exit"));
       
   708 	}
       
   709 
       
   710 /**
       
   711 The first chunk received will have the length of the data and the ptpip packet type.
       
   712 Validate the ptp packet type, and set the correct packet type in the generic container.
       
   713 Set the state to complete or read further depending on the size.
       
   714 */
       
   715 void CPTPIPSocketHandlerBase::ProcessFirstReceivedChunkL()
       
   716 	{
       
   717 	__FLOG(_L8("ProcessFirstReceivedChunkL - Entry"));
       
   718     iIsFirstChunk = EFalse;
       
   719     // Reset the data counter, This will be filled in later in the ResumeReceiveDataStreamL.
       
   720     iPTPPacketLengthReceived = 0; 
       
   721     iType = EPTPIPPacketTypeUndefined;
       
   722     
       
   723     // Parse and get the packet type, and packet length into type and iPTPPacketLength.
       
   724     // This will also validate that the correct payload is set to get the remaining data. 
       
   725     iType = ParsePTPIPHeaderL();
       
   726 	
       
   727 	// If the PTPIP type is not one of the standard expected types, 
       
   728 	// or not expected in the current transaction phase then we stop further receiving
       
   729 	// This current RunL will 
       
   730 	if (EPTPIPPacketTypeUndefined == iType ) 
       
   731 		{
       
   732 		__FLOG(_L8("PTPIP ERROR: Unexpected value in the type field of PTPIP header, appears corrupt"));
       
   733 		SetState(EReceiveComplete);
       
   734 		iStatus = KErrCorrupt;
       
   735 		}
       
   736 	
       
   737 	// If there is nothing to receive after the header, possible for probe packet.
       
   738 	else if (KPTPIPHeaderSize == iPTPPacketLength )
       
   739 		{
       
   740 		SetState(EReceiveComplete);
       
   741 		}
       
   742 	   
       
   743     if (iState == EReceiveComplete)
       
   744 		{
       
   745 #ifdef MTP_DEBUG_FLOG_HEX_DUMP 
       
   746         __FLOG_HEXDUMP((iReceiveChunkData, _L8("Received data ")));
       
   747 #endif
       
   748 
       
   749 		// Commit the received data if required.
       
   750         if (iReceiveDataCommit)
       
   751 		    {
       
   752 		 	__FLOG(_L8("Commiting write data chunk"));
       
   753 	        iReceiveDataSink->CommitChunkL(iReceiveChunkData);       
       
   754 		    }
       
   755 		}
       
   756 	else
       
   757 		{
       
   758 		ResumeReceiveDataStreamL();
       
   759 		}
       
   760 
       
   761 	__FLOG(_L8("ProcessFirstReceivedChunkL - Exit"));
       
   762 	}
       
   763 
       
   764 
       
   765 
       
   766 /**
       
   767 Called after the first chunk has been received and we are expecting more packets. 
       
   768 This will be called repeatedly until all the packets have been received.
       
   769 */
       
   770 void CPTPIPSocketHandlerBase::ResumeReceiveDataStreamL()
       
   771 	{
       
   772 	__FLOG(_L8("ResumeReceiveDataStreamL - Entry"));
       
   773 	TBool endStream(EFalse);
       
   774 	MMTPType *needCommit = NULL;
       
   775 		
       
   776     // Process the received chunk (if any).
       
   777    	iPTPPacketLengthReceived += iReceiveData.Length();
       
   778    	__FLOG_VA((_L8("Data received = iPTPPacketLengthReceived = %d bytes, Data expected = iPTPPacketLength = %d"), iPTPPacketLengthReceived, iPTPPacketLength));
       
   779    	
       
   780 	if (iPTPPacketLengthReceived == iPTPPacketLength)
       
   781 	   	{
       
   782 	   	SetState(EReceiveComplete);
       
   783 	   	endStream = ETrue;
       
   784 	   	
       
   785 	   	//if type  is data then end stream is not true
       
   786 	   	if (iType == EPTPIPPacketTypeData)
       
   787 	   	endStream = EFalse;
       
   788 	   	}
       
   789 
       
   790     __FLOG_VA((_L8("Received = %d bytes, write data chunk capacity = %d bytes"), iReceiveChunkData.Length(), iReceiveChunkData.MaxLength()));		   
       
   791 #ifdef MTP_DEBUG_FLOG_HEX_DUMP 
       
   792     __FLOG_HEXDUMP((iReceiveChunkData, _L8("Received data ")));
       
   793 #endif
       
   794 
       
   795 
       
   796     // Commit the received data if required.
       
   797 	if (iReceiveDataCommit)
       
   798          {
       
   799          // if the chunk has been read completely.
       
   800          // or if the end of stream has been reached. 
       
   801          if (iReceiveChunkData.Length() == iReceiveChunkData.MaxLength()
       
   802          	|| endStream )
       
   803         	 {
       
   804         	 needCommit = iReceiveDataSink->CommitChunkL(iReceiveChunkData);
       
   805         	 }   
       
   806          
       
   807          
       
   808          } 
       
   809 
       
   810     // Fetch the next read data chunk.  
       
   811     switch (iState)
       
   812         {
       
   813     case EReceiveInProgress:
       
   814    	
       
   815 	// If we're in the middle of receiving a ptp data packet, 
       
   816 	// then at this stage we might have already used some of this chunk. 
       
   817 	// so reset its length to previously saved value
       
   818     if (iUseOffset)
       
   819 		
       
   820 		{		
       
   821 		iUseOffset = EFalse;	
       
   822 		iReceiveChunkData.Set(iCurrentChunkData);
       
   823 		iChunkStatus = KErrNone;		
       
   824 		}
       
   825     
       
   826     	// get the next chunk only if this chunk has been read completely. 
       
   827     	if (iReceiveChunkData.Length() == iReceiveChunkData.MaxLength())
       
   828     		{
       
   829     		
       
   830     		iChunkStatus = iReceiveDataSink->NextWriteChunk(iReceiveChunkData);
       
   831     		
       
   832     		}
       
   833     	__FLOG_VA((_L8("iReceiveChunkData pointer address is %08x"), iReceiveChunkData.Ptr()));
       
   834 	    break;
       
   835         
       
   836     case EReceiveComplete:
       
   837         __FLOG(_L8("Write data chunk sequence complet"));
       
   838         break;
       
   839                   
       
   840     case EIdle:
       
   841     default:
       
   842         __FLOG(_L8("Invalid stream state"));
       
   843         Panic(EPTPIPBadState);
       
   844         break;
       
   845         }
       
   846         
       
   847     __FLOG_VA((_L8("Chunk status = %d"), iChunkStatus)); 
       
   848         
       
   849         
       
   850     // If necessary, process the next chunk. 
       
   851     if (iState != EReceiveComplete)
       
   852         {
       
   853         __FLOG_VA((_L8("Receive chunk capacity = %d bytes, length = %d bytes"), iReceiveChunkData.MaxLength(), iReceiveChunkData.Length()));
       
   854         __FLOG_VA((_L8("iReceiveChunkData pointer address is %08x"), iReceiveChunkData.Ptr()));
       
   855         
       
   856         
       
   857 	        // When we reach the end of receiving a PTPIP packet, it is possible that our PTPIP chunk
       
   858 	        // length is greater than the actual data that is expected. 
       
   859 	        // eg when parameters 1to 5 are not set in a PTPIP request. In this case 
       
   860 	        // we need to read the remaining length which will be less than the max length of the chunk.
       
   861 	        TUint32 remainingLen = iPTPPacketLength - iPTPPacketLengthReceived;
       
   862 	        if (remainingLen < (iReceiveChunkData.MaxLength() - iReceiveChunkData.Length()))
       
   863 	        	{
       
   864 	        	iReceiveData.Set(const_cast<TUint8*>(iReceiveChunkData.Ptr() + iReceiveChunkData.Length()), 
       
   865 	        	                 0,
       
   866 	        					remainingLen); 
       
   867 	        	}
       
   868 	        else
       
   869 	        	{
       
   870 	        	iReceiveData.Set(const_cast<TUint8*>(iReceiveChunkData.Ptr() + iReceiveChunkData.Length()), 
       
   871 	        					0, 
       
   872 	        					iReceiveChunkData.MaxLength() - iReceiveChunkData.Length());
       
   873 	        	}        	
       
   874 	       
       
   875         	
       
   876         	
       
   877 	        __FLOG_VA((_L8("Length read this time is= %d"), iReceiveData.MaxLength()));
       
   878         	
       
   879         
       
   880  		iSocket.Recv(iReceiveData, 0, iStatus);
       
   881 #ifdef MTP_DEBUG_FLOG_HEX_DUMP 
       
   882     __FLOG_HEXDUMP((iReceiveData, _L8("Received data on socket ")));
       
   883 #endif 		
       
   884         SetActive();
       
   885         __FLOG(_L8("Request issued"));
       
   886         }
       
   887         if(needCommit != NULL)
       
   888             {
       
   889             TPtr8 tmp(NULL, 0, 0);
       
   890             needCommit->CommitChunkL(tmp);
       
   891             }
       
   892  	__FLOG(_L8("ResumeReceiveDataStreamL - Exit"));
       
   893 	}
       
   894 
       
   895 /**
       
   896 Signals the data transfer controller that an asynchronous data receive sequence 
       
   897 has completed.
       
   898 @leave One of the system wide error codes, if a processing failure occurs.
       
   899 @panic EPTPIPNotSupported In debug builds only, if the derived class has not fully 
       
   900 implemented the receive data path.
       
   901 */
       
   902 void CPTPIPSocketHandlerBase::ReceiveDataCompleteL(TInt /*aError*/, MMTPType& /*aSink*/)
       
   903     {
       
   904     __FLOG(_L8("CSocketHandler::ReceiveDataCompleteL - Entry"));
       
   905     __DEBUG_ONLY(Panic(EPTPIPNotSupported));
       
   906     __FLOG(_L8("CSocketHandler::ReceiveDataCompleteL - Exit"));
       
   907     }
       
   908 
       
   909 /**
       
   910 Forces the completion of a transfer in progress. 
       
   911 
       
   912 @param aReason error code describing the reason for cancelling.
       
   913 @leave Any of the system wide error codes.
       
   914 */
       
   915 void CPTPIPSocketHandlerBase::CancelReceiveL(TInt aReason)
       
   916 	{
       
   917 	__FLOG(_L8("CSocketHandler::CancelReceiveL - Entry"));
       
   918      
       
   919     if (DataStreamDirection() == EReceivingState)
       
   920 	    {
       
   921 		__FLOG(_L8("Cancel in EReceivingState"));            
       
   922 	    // Cancel any outstanding request.
       
   923     	Cancel();  
       
   924 
       
   925         // Notify the connection and reset the receive data stream.
       
   926 		ResetReceiveDataStream();
       
   927         ReceiveDataCompleteL(aReason, *iReceiveDataSink);
       
   928 	    }
       
   929 	    
       
   930     __FLOG(_L8("CSocketHandler::CancelReceiveL - Exit"));	
       
   931 	}
       
   932 
       
   933 //
       
   934 // Getters , Setters and other helper functions
       
   935 //
       
   936 
       
   937 CPTPIPConnection& CPTPIPSocketHandlerBase::Connection()
       
   938 	{
       
   939 	return iConnection;
       
   940 	}
       
   941 
       
   942 RSocket& CPTPIPSocketHandlerBase::Socket()
       
   943 	{
       
   944 	return iSocket;	
       
   945 	}
       
   946 
       
   947 
       
   948 void CPTPIPSocketHandlerBase::ResetSendDataStream()
       
   949     {
       
   950 	__FLOG(_L8("CSocketHandler::ResetSendDataStream - Entry"));
       
   951     iSendChunkData.Set(NULL, 0);
       
   952     iSendData.Set(NULL, 0);
       
   953     iSendDataSource = NULL;
       
   954     iCancelReceived = EFalse;
       
   955     SetState(EIdle);
       
   956 	__FLOG(_L8("CSocketHandler::ResetSendDataStream - Exit"));
       
   957     }
       
   958     
       
   959 void CPTPIPSocketHandlerBase::ResetReceiveDataStream()
       
   960     {
       
   961 	__FLOG(_L8("CSocketHandler::ResetReceiveDataStream - Entry"));
       
   962     iReceiveChunkData.Set(NULL, 0, 0);
       
   963     iReceiveData.Set(NULL, 0, 0);
       
   964     iReceiveDataSink = NULL;
       
   965     iCancelReceived = EFalse;
       
   966     SetState(EIdle);
       
   967 	__FLOG(_L8("CSocketHandler::ResetReceiveDataStream - Exit"));
       
   968     }
       
   969 
       
   970     
       
   971 void CPTPIPSocketHandlerBase::SetState(TSocketState aState)
       
   972 	{
       
   973 	__FLOG(_L8("SetState - Entry"));
       
   974 	iState = aState;
       
   975 	__FLOG_VA((_L8(" state = 0x%08X"), iState));
       
   976 	__FLOG(_L8("SetState - Exit"));
       
   977 	}
       
   978 	
       
   979 void CPTPIPSocketHandlerBase::CompleteSelf(TInt aCompletionCode)
       
   980      {
       
   981      SetActive();
       
   982      TRequestStatus* stat = &iStatus;
       
   983      User::RequestComplete(stat, aCompletionCode);
       
   984      }	
       
   985 
       
   986 /**
       
   987 Provides the current data stream direction, sending or receiving
       
   988 */
       
   989 TInt32 CPTPIPSocketHandlerBase::DataStreamDirection() const
       
   990     {
       
   991     return (iState & EStateDirection);
       
   992     }
       
   993     
       
   994 void CPTPIPSocketHandlerBase::SetSocket(RSocket& aSocket)
       
   995 	{
       
   996 	iSocket = aSocket;	
       
   997 	}
       
   998 
       
   999 /**
       
  1000 Ignore any errors in setting the socket options
       
  1001 */
       
  1002 void CPTPIPSocketHandlerBase::SetSocketOptions()
       
  1003 	{
       
  1004 	TInt error=iSocket.SetOpt(KSoTcpKeepAlive,KSolInetTcp,1);
       
  1005 	__FLOG_VA((_L8(" setting the keep alive option returned = %d"), error));
       
  1006 	error=iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1);
       
  1007 	__FLOG_VA((_L8(" setting the no delay to disable Nagle's algo returned %d"), error));
       
  1008 	}