testconns/statapi/device/source/statapi/src/stat_packetisation.cpp
changeset 4 b8d1455fddc0
equal deleted inserted replaced
2:73b88125830c 4:b8d1455fddc0
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20  /**************************************************************************************
       
    21  *
       
    22  * Packetisation transport for STAT -- for packet based network layers
       
    23  *
       
    24  *************************************************************************************/
       
    25 #include <e32std.h>
       
    26 #include <e32base.h>
       
    27 
       
    28 /**************************************************************************************
       
    29  *
       
    30  * Local Includes
       
    31  *
       
    32  *************************************************************************************/
       
    33 #include "assert.h"
       
    34 #include "stat.h"
       
    35 #include "stat_packetisation.h"
       
    36 #include "dataconsumer_memory.h"
       
    37 #include "dataconsumer_file.h"
       
    38 
       
    39 /*************************************************************************
       
    40  *
       
    41  * Definitions
       
    42  *
       
    43  *************************************************************************/
       
    44 #define KMinDataSize		64
       
    45 #define KMinPacketSize		KHeaderSize + KMinDataSize
       
    46 
       
    47  /**************************************************************************************
       
    48  *
       
    49  * CStatTransportPacketisation - Construction
       
    50  *
       
    51  *************************************************************************************/
       
    52 CStatTransportPacketisation *CStatTransportPacketisation::NewL( MNotifyStatEngine *aStatEngine, MStatNetwork *aStatNetwork, TUint aPacketSize )
       
    53 {
       
    54     CStatTransportPacketisation *self = new (ELeave) CStatTransportPacketisation();
       
    55     CleanupStack::PushL(self);
       
    56 	self->ConstructL( aStatEngine, aStatNetwork, aPacketSize );
       
    57 	CleanupStack::Pop();
       
    58     return self;
       
    59 }
       
    60 
       
    61 CStatTransportPacketisation::CStatTransportPacketisation() :
       
    62 	iDataSupplier( NULL )
       
    63 {
       
    64 }
       
    65 
       
    66 void CStatTransportPacketisation::ConstructL( MNotifyStatEngine *aStatEngine, MStatNetwork *aStatNetwork, TUint aPacketSize )
       
    67 {
       
    68 	// check params
       
    69 	asserte( aStatEngine != NULL );
       
    70 	asserte( aStatNetwork != NULL );
       
    71 	asserte( aPacketSize >= KMinPacketSize );
       
    72 
       
    73 	// setup general members
       
    74 	iStatEngine = aStatEngine;
       
    75 	iStatNetwork = aStatNetwork;
       
    76 	iTransportStatus = EIdle;
       
    77 	iSendStatus = ESendIdle;
       
    78 	iRecvStatus = EReceiveIdle;
       
    79 	iDataPacketSize = aPacketSize;
       
    80 
       
    81 	// setup send buffer members
       
    82 	iSendFragment = NULL;
       
    83 	iSendCommand = 0;
       
    84 	iSendDataLength = 0;
       
    85 	iSendDataWritten = 0;
       
    86 	iSendDataAcknowledged = 0;
       
    87 
       
    88 	// setup recv buffer members
       
    89 	iRecvCommand = 0;
       
    90 	iRecvDataLength = 0;
       
    91 	iRecvDataReceived = 0;
       
    92 }
       
    93 
       
    94 CStatTransportPacketisation::~CStatTransportPacketisation()
       
    95 {
       
    96 	if( iSendFragment != NULL )
       
    97 		{
       
    98 		delete iSendFragment;
       
    99 		iSendFragment = NULL;
       
   100 		}
       
   101 	if( iDataConsumer )
       
   102 		{
       
   103 		iDataConsumer->Delete( );
       
   104 		iDataConsumer = NULL;
       
   105 		}
       
   106 }
       
   107 
       
   108 /**************************************************************************************
       
   109  *
       
   110  * CStatTransportPacketisation - MStatApiTransport - all calls except for send are 
       
   111  * passed straight through to the network layer (a flag is recorded for receive as
       
   112  * well). See the STAT design spec doc for the packetisation protocol.
       
   113  *
       
   114  *************************************************************************************/
       
   115 TInt CStatTransportPacketisation::InitialiseL( void )
       
   116 {
       
   117 	return iStatNetwork->InitialiseL( this );
       
   118 }
       
   119 
       
   120 TInt CStatTransportPacketisation::ConnectL( TDesC *aRemoteHost )
       
   121 {
       
   122 	return iStatNetwork->ConnectL( aRemoteHost );
       
   123 }
       
   124 
       
   125 TInt CStatTransportPacketisation::RequestReceive( void )
       
   126 {
       
   127 	// set the state and wait for the header
       
   128 	iTransportStatus = EReceivePending;
       
   129 	iRecvStatus = EReceivingInitialHeader;
       
   130 	return iStatNetwork->RequestReceive( KHeaderSize );
       
   131 }
       
   132 
       
   133 TInt CStatTransportPacketisation::Disconnect( void )
       
   134 {
       
   135 	return iStatNetwork->Disconnect();
       
   136 }
       
   137 
       
   138 TInt CStatTransportPacketisation::Release( void )
       
   139 {
       
   140 	return iStatNetwork->Release();
       
   141 }
       
   142 
       
   143 TText8 *CStatTransportPacketisation::Error( void )
       
   144 {
       
   145 	return iStatNetwork->Error();
       
   146 }
       
   147 
       
   148 
       
   149 TInt CStatTransportPacketisation::RequestSend( const TUint aCommand, MDataSupplier *const aDataSupplier)
       
   150 	{
       
   151 	TInt err = KErrNone;
       
   152 
       
   153 	// make sure a packet can fit the header and at least some data -- otherwise it's useless
       
   154 	asserte( iDataPacketSize >= KMinPacketSize );
       
   155 
       
   156 	// check the state is as expected
       
   157 	asserte( iTransportStatus == EIdle );
       
   158 	asserte( iSendStatus == ESendIdle );
       
   159 
       
   160 	// Take a copy of the pointer to the data supplier.
       
   161 	iDataSupplier = aDataSupplier;
       
   162 
       
   163 	// save the command and its data
       
   164 	iSendCommand = aCommand;
       
   165 	iSendDataLength = 0;
       
   166 	if(iDataSupplier)
       
   167 		{
       
   168 		TInt dataLength = 0;
       
   169 		err = iDataSupplier->GetTotalSize( dataLength );
       
   170 
       
   171 		if( err == KErrNone )
       
   172 			{
       
   173 				iSendDataLength = static_cast<TUint>(dataLength);
       
   174 			}
       
   175 		}
       
   176 	iSendDataWritten = 0;
       
   177 
       
   178 	if( err == KErrNone )
       
   179 	{
       
   180 		// create and send the initial header
       
   181 		SendHeaderPacket( iSendCommand, iSendDataLength );
       
   182 		err = KSTErrAsynchronous;
       
   183 	}
       
   184 
       
   185 	return (err);
       
   186 }
       
   187 
       
   188 
       
   189 
       
   190 /**************************************************************************************
       
   191  *
       
   192  * CStatTransportPacketisation - MNotifyStatTransport - all events except HandleSend
       
   193  * and HandleReceive are sent straight through to the engine.  
       
   194  *
       
   195  *************************************************************************************/
       
   196 void CStatTransportPacketisation::HandleInitialise( TInt aResult )
       
   197 {
       
   198 	iStatEngine->HandleInitialise( aResult );
       
   199 }
       
   200 
       
   201 void CStatTransportPacketisation::HandleConnect( TInt aResult )
       
   202 {
       
   203 	iStatEngine->HandleConnect( aResult );
       
   204 }
       
   205 
       
   206 void CStatTransportPacketisation::HandleDisconnect( TInt aResult )
       
   207 {
       
   208 	iStatEngine->HandleDisconnect( aResult );
       
   209 }
       
   210 
       
   211 void CStatTransportPacketisation::HandleRelease( TInt aResult )
       
   212 {
       
   213 	iStatEngine->HandleRelease( aResult );
       
   214 }
       
   215 
       
   216 void CStatTransportPacketisation::HandleError( TInt aError, void *aErrorData )
       
   217 {
       
   218 	iStatEngine->HandleError( aError, aErrorData );
       
   219 }
       
   220 
       
   221 void CStatTransportPacketisation::HandleInfo( const TDesC *aInfo )
       
   222 {
       
   223 	iStatEngine->HandleInfo( aInfo );
       
   224 }
       
   225 
       
   226 /**************************************************************************************
       
   227  *
       
   228  * CStatTransportPacketisation - HandleSend
       
   229  *
       
   230  *************************************************************************************/
       
   231 void CStatTransportPacketisation::HandleSend( TInt aResult )
       
   232 {
       
   233 	TUint remainingBytes, packetSize, err;
       
   234 	
       
   235 	// handle each state
       
   236 	switch( iSendStatus ) {
       
   237 
       
   238 	case ESendingInitialHeader:
       
   239 
       
   240 		// wait for an acknowledgement for the header
       
   241 		iTransportStatus = EReceivePending;
       
   242 		iRecvStatus = EReceivingFragmentAck;
       
   243 		iSendStatus = ESendIdle;
       
   244 		err = iStatNetwork->RequestReceive( KHeaderSize );
       
   245 		asserte( err == KSTErrAsynchronous );                   
       
   246 		break;
       
   247 
       
   248 	case ESendingFragmentHeader:
       
   249 
       
   250 		// if there is data left to send then send it -- otherwise we have completed a send
       
   251 		if( iSendDataWritten == iSendDataLength ) {
       
   252 			NotifyEngineSend( aResult );
       
   253 		} else {
       
   254 			remainingBytes = iSendDataLength - iSendDataWritten;
       
   255 			packetSize = ((remainingBytes < iDataPacketSize) ? remainingBytes : iDataPacketSize);
       
   256 
       
   257 			asserte( packetSize <= iDataPacketSize );
       
   258 
       
   259 			iSendFragment = HBufC8::NewMax(packetSize);
       
   260 			if(iSendFragment)
       
   261 			{
       
   262 				TInt dataCopied = 0;
       
   263 				iDataSupplier->GetData( *iSendFragment, packetSize, dataCopied );
       
   264 
       
   265 				// When we do the sending the data we send
       
   266 				// is of size 'bufferSize' but we must only
       
   267 				// add 'packetSize' to the running total of
       
   268 				// data written.
       
   269 				iTransportStatus = ESendPending;
       
   270 				iSendStatus = ESendingFragmentData;
       
   271 				iSendDataWritten += packetSize;
       
   272 				err = iStatNetwork->RequestSend( iSendFragment, packetSize );
       
   273 				asserte( err == KSTErrAsynchronous );
       
   274 			}
       
   275 		}
       
   276 		break;
       
   277 
       
   278 	case ESendingFragmentData:
       
   279 
       
   280 		// if we have just sent some data then free the buffer
       
   281 		asserte( iSendFragment != NULL );
       
   282 		delete iSendFragment;
       
   283 		iSendFragment = NULL;
       
   284 
       
   285 		// if we are not packetising data then we have completed the send otherwise we are 
       
   286 		// packetising data then the remote host will send an acknowledgement
       
   287 		if( iSendDataLength <= iDataPacketSize ) {
       
   288 			NotifyEngineSend( aResult );
       
   289 		} else {
       
   290 			iTransportStatus = EReceivePending;
       
   291 			iRecvStatus = EReceivingFragmentAck;
       
   292 			iSendStatus = ESendIdle;
       
   293 			err = iStatNetwork->RequestReceive( KHeaderSize );
       
   294 			asserte( err == KSTErrAsynchronous );
       
   295 		}
       
   296 		break;
       
   297 		
       
   298 	case ESendingFragmentAck:
       
   299 
       
   300 		// if we have just sent a fragment ack then wait for the next fragment header
       
   301 		iTransportStatus = EReceivePending;
       
   302 		iRecvStatus = EReceivingFragmentHeader;
       
   303 		iSendStatus = ESendIdle;
       
   304 		err = iStatNetwork->RequestReceive( KHeaderSize );
       
   305 		asserte( err == KSTErrAsynchronous );
       
   306 		break;
       
   307 
       
   308 	case ESendIdle:
       
   309 		;
       
   310 		break;
       
   311 	}
       
   312 }
       
   313 
       
   314 /**************************************************************************************
       
   315  *
       
   316  * CStatTransportPacketisation - HandleReceive
       
   317  *
       
   318  *************************************************************************************/
       
   319 void CStatTransportPacketisation::HandleReceive( TInt aResult, TDesC8 *aData, TUint aDataLength )
       
   320 {
       
   321 	TUint *pData, packetSize, remainingBytes, recvCommand, recvLength = 0;
       
   322 	TInt err;
       
   323 
       
   324 	
       
   325 	
       
   326 	// make sure that we thought we were waiting to receive
       
   327 	asserte( aResult == KErrNone );
       
   328 	asserte( iTransportStatus == EReceivePending );
       
   329 	asserte( iRecvStatus != EReceiveIdle );
       
   330 	
       
   331 	
       
   332 	// Handle a special case where we receive a modem query
       
   333 	// from the (Windows) system.  There is a chance that we
       
   334 	// will recieve a series of modem query strings of three
       
   335 	// lots of 'AT'.  When that happens we need to ignore it.
       
   336 	// Usually we use the 'L' macro and let the preprocessor
       
   337 	// sort out the length of the character but we have to
       
   338 	// force it here because in a UNICODE build the serial
       
   339 	// port still delivers 8 bit characters.
       
   340 	static const TInt modemQueryLength = 8;
       
   341 	static const TLitC8<modemQueryLength + 1> modemQuery = { modemQueryLength, "AT\rAT\rAT" };
       
   342 
       
   343 	if( (static_cast<TInt>(aDataLength) == modemQueryLength) && 
       
   344 			(0 == aData->Compare(modemQuery.operator const TDesC8&()) ))
       
   345 	{
       
   346 		return;
       
   347 	}
       
   348 	// End special case of modem query.
       
   349 	
       
   350 	// STEP 1: process the incoming message
       
   351 	switch( iRecvStatus ) {
       
   352 
       
   353 	case EReceivingInitialHeader:
       
   354 
       
   355 		// extract the header info and setup the local receive state 
       
   356 		pData = (TUint*)aData->Ptr();
       
   357 		iRecvCommand = iStatNetwork->NtoHl( pData[0] );
       
   358 		iRecvDataLength = iStatNetwork->NtoHl( pData[1] );
       
   359 
       
   360 		// if this is a resync then abort the connection
       
   361 		if( iRecvCommand == RESYNC_ID ) {
       
   362 			iStatEngine->HandleError( KSTErrResyncCommand, (void*)0 );
       
   363 			iSendStatus = ESendIdle;
       
   364 			iRecvStatus = EReceiveIdle;
       
   365 			iTransportStatus = EIdle;
       
   366 			return;
       
   367 		}
       
   368 
       
   369 		// allocate the data buffers 
       
   370 		asserte( iRecvDataReceived == 0 );
       
   371 		if( iRecvDataLength > 0 )
       
   372 			{
       
   373 			// Determine if we use a memory receive buffer
       
   374 			// or a temporary file.  Purely arbitary size.
       
   375 			static const unsigned int maxSizeOfMemoryConsumer = (1024 * 4);
       
   376 
       
   377 			if( iRecvDataLength < maxSizeOfMemoryConsumer )
       
   378 				{
       
   379 				iDataConsumer = CDataConsumerMemory::NewL( );
       
   380 				}
       
   381 			else
       
   382 				{
       
   383 				iDataConsumer = CDataConsumerFile::NewL( );
       
   384 				}
       
   385 			}
       
   386 
       
   387 		// If the data length is greater that iDataPacketSize then the desktop will
       
   388 		// packetise the data into fragments each with a header. If the data is not
       
   389 		// packetised then the initial header is equivalent to a fragment header.
       
   390 		if( iRecvDataLength <= iDataPacketSize ) {
       
   391 			iRecvStatus = EReceivingFragmentHeader;
       
   392 			recvCommand = iRecvCommand;
       
   393 			recvLength = iRecvDataLength;
       
   394 		}
       
   395 		break;
       
   396 
       
   397 	case EReceivingFragmentHeader:
       
   398 		
       
   399 		// check that this is a fragment header as expected
       
   400 		asserte( aDataLength == KHeaderSize );
       
   401 		pData = (TUint*)aData->Ptr();
       
   402 		recvCommand = iStatNetwork->NtoHl( pData[0] );
       
   403 		recvLength = iStatNetwork->NtoHl( pData[1] );
       
   404 
       
   405 		// if this is not the expected command (e.g. a resync) then throw an error 
       
   406 		if( (recvCommand != iRecvCommand) ) {
       
   407 			iStatEngine->HandleError( KSTErrUnexpectedFragmentCommand, (void*)recvCommand );
       
   408 			iSendStatus = ESendIdle;
       
   409 			iRecvStatus = EReceiveIdle;
       
   410 			iTransportStatus = EIdle;
       
   411 			return;
       
   412 		}
       
   413 		break;
       
   414 
       
   415 	case EReceivingData:
       
   416 		{
       
   417 		// received data is placed into the receive buffer
       
   418 		asserte( (iRecvDataReceived + aDataLength) <= iRecvDataLength );
       
   419 		iDataConsumer->AddData( *aData );
       
   420 		iRecvDataReceived += aDataLength;
       
   421 		break;
       
   422 		}
       
   423 	case EReceivingFragmentAck:
       
   424 		
       
   425 		// check that this is a fragment ack as expected
       
   426 		asserte( aDataLength == KHeaderSize );
       
   427 		pData = (TUint*)aData->Ptr();
       
   428 		recvCommand = iStatNetwork->NtoHl( pData[0] );
       
   429 		recvLength = iStatNetwork->NtoHl( pData[1] );
       
   430 
       
   431 		// if this is not the expected command (e.g. a resync) then throw an error 
       
   432 		if( (recvCommand != iSendCommand) ) {
       
   433 			iStatEngine->HandleError( KSTErrUnexpectedFragmentCommand, (void*)recvCommand );
       
   434 			iSendStatus = ESendIdle;
       
   435 			iRecvStatus = EReceiveIdle;
       
   436 			iTransportStatus = EIdle;
       
   437 			return;
       
   438 		}
       
   439 		asserte( recvLength == 0 );
       
   440 
       
   441 		// update the number of bytes acknowledged
       
   442 		iSendDataAcknowledged = iSendDataWritten;
       
   443 		break;
       
   444 
       
   445 	case EReceiveIdle:
       
   446 		;
       
   447 		break;
       
   448 	}
       
   449 
       
   450 	// STEP 2: decide what to do next
       
   451 	switch( iRecvStatus ) {
       
   452 
       
   453 	case EReceivingInitialHeader:
       
   454 
       
   455 		// send an acknowledgement for the initial header
       
   456 		SendAckPacket( iRecvCommand );
       
   457 		break;
       
   458 
       
   459 	case EReceivingFragmentHeader:
       
   460 
       
   461 		// if there is more data then wait for it -- otherwise the receive is complete
       
   462 		if( recvLength > 0 ) {
       
   463 			iTransportStatus = EReceivePending;
       
   464 			iRecvStatus = EReceivingData;
       
   465 			err = iStatNetwork->RequestReceive( recvLength );	
       
   466 			asserte( err == KSTErrAsynchronous );
       
   467 		} else {
       
   468 			NotifyEngineReceive( aResult );
       
   469 		}
       
   470 		break;
       
   471 
       
   472 	case EReceivingData:
       
   473 
       
   474 		// If we have received some packetised data then we have to acknowledge it. Otherwise
       
   475 		// we have completed a receive and should notify the engine and clean up.
       
   476 		if( iRecvDataLength > iDataPacketSize)
       
   477 			SendAckPacket( iRecvCommand );
       
   478 		else
       
   479 			NotifyEngineReceive( aResult );
       
   480 		break;
       
   481 
       
   482 	case EReceivingFragmentAck:
       
   483 
       
   484 		// if the desktop has just acknowledged a fragment then we send the next fragment header,
       
   485 		// even if there are no more bytes to send.	
       
   486 		remainingBytes = iSendDataLength - iSendDataWritten;
       
   487 		packetSize = ((remainingBytes < iDataPacketSize) ? remainingBytes : iDataPacketSize);
       
   488 		SendHeaderPacket( iSendCommand, packetSize );
       
   489 		break;
       
   490 
       
   491 	case EReceiveIdle:
       
   492 		;
       
   493 		break;
       
   494 	}
       
   495 }
       
   496 
       
   497 /**************************************************************************************
       
   498  *
       
   499  * Helper functions
       
   500  *
       
   501  *************************************************************************************/
       
   502 void CStatTransportPacketisation::SendHeaderPacket( TUint aCommand, TUint aDataLength )
       
   503 {
       
   504 	TUint err;
       
   505 
       
   506 	// construct the header in iSendHeader
       
   507 	BuildHeader( aCommand, aDataLength );
       
   508 
       
   509 	// set the state
       
   510 	iTransportStatus = ESendPending;
       
   511 	iRecvStatus = EReceiveIdle;
       
   512 	iSendStatus = ((aDataLength > iDataPacketSize) ? ESendingInitialHeader : ESendingFragmentHeader);
       
   513 
       
   514 	// send it
       
   515 	err = iStatNetwork->RequestSend( &iSendHeader, KHeaderSize );
       
   516 	asserte( err == KSTErrAsynchronous );
       
   517 }
       
   518 
       
   519 void CStatTransportPacketisation::SendAckPacket( TUint aCommand )
       
   520 {
       
   521 	TUint err;
       
   522 
       
   523 	// construct the header in iSendHeader
       
   524 	BuildHeader( aCommand, 0 );
       
   525 
       
   526 	// set the state
       
   527 	iTransportStatus = ESendPending;
       
   528 	iRecvStatus = EReceiveIdle;
       
   529 	iSendStatus = ESendingFragmentAck;
       
   530 
       
   531 	// send it
       
   532 	err = iStatNetwork->RequestSend( &iSendHeader, KHeaderSize );
       
   533 	asserte( err == KSTErrAsynchronous );
       
   534 }
       
   535 
       
   536 void CStatTransportPacketisation::BuildHeader( TUint aCommand, TUint aDataLength )
       
   537 {
       
   538 	TInt nbCommand, nbLength;
       
   539 	TUint *buff;
       
   540 
       
   541 	// create the header
       
   542 	nbCommand = iStatNetwork->HtoNl( aCommand );
       
   543 	nbLength = iStatNetwork->HtoNl( aDataLength );
       
   544 	iSendHeader.SetLength( 0 );
       
   545 	buff = (TUint*)iSendHeader.Ptr();
       
   546 	buff[0] = nbCommand;
       
   547 	buff[1] = nbLength;
       
   548 	iSendHeader.SetLength( KHeaderSize );
       
   549 }
       
   550 
       
   551 void CStatTransportPacketisation::NotifyEngineSend( TUint aResult )
       
   552 {
       
   553 	// check the state is as expected
       
   554 	asserte( iSendDataWritten == iSendDataLength );
       
   555 	asserte( (iSendDataLength <= iDataPacketSize) || (iSendDataAcknowledged == iSendDataLength) );
       
   556 	
       
   557 	// clear the state
       
   558 	iSendCommand = 0;
       
   559 	iSendDataLength = 0;
       
   560 	iSendDataWritten = 0;
       
   561 	iSendDataAcknowledged = 0;
       
   562 
       
   563 	iTransportStatus = EIdle;
       
   564 	iSendStatus = ESendIdle;
       
   565 
       
   566 	// notify the engine
       
   567 	iStatEngine->HandleSend( aResult );
       
   568 }
       
   569 
       
   570 void CStatTransportPacketisation::NotifyEngineReceive( TUint aResult )
       
   571 {
       
   572 	// check the state is as expected
       
   573 	asserte( iRecvDataLength == iRecvDataReceived || iRecvDataLength==(unsigned long)-1);
       
   574 	asserte( (iRecvDataLength == 0) || (iDataConsumer != NULL) );
       
   575 	
       
   576 	// clear the send state (allows sending from the receive handler) but don't clear
       
   577 	// the recvstatus since the buffers are still in use. This could be solved by 
       
   578 	// creating multiple buffers but there is no need now and this would be slow
       
   579 	iTransportStatus = EIdle;
       
   580 	iSendStatus = ESendIdle;
       
   581 
       
   582 	// notify the engine 
       
   583 	iStatEngine->HandleReceive( aResult, iRecvCommand, iDataConsumer );
       
   584 
       
   585 	// clear the status state
       
   586 	iRecvStatus = EReceiveIdle;
       
   587 
       
   588 	// clear the recv buffer state
       
   589 	iRecvCommand = 0;
       
   590 	iRecvDataLength = 0;
       
   591 	iRecvDataReceived = 0;
       
   592 	iRecvDataAcknowledged = 0;
       
   593 
       
   594 	if(iDataConsumer)
       
   595 		{
       
   596 		iDataConsumer->Delete( );
       
   597 		iDataConsumer = NULL;
       
   598 		}
       
   599 }
       
   600