testexecfw/statsrv/device/source/statapi/src/stat_tcpip.cpp
changeset 0 3e07fef1e154
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testexecfw/statsrv/device/source/statapi/src/stat_tcpip.cpp	Mon Mar 08 15:03:44 2010 +0800
@@ -0,0 +1,370 @@
+/*
+* Copyright (c) 2005-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: 
+*
+*/
+
+
+
+/********************************************************************************
+ *
+ * System Includes
+ *
+ *******************************************************************************/
+#include <es_sock.h>
+#include <in_sock.h>
+
+/********************************************************************************
+ *
+ * Local Includes
+ *
+ *******************************************************************************/
+#include "assert.h"
+#include "ntoh.h"
+#include "stat_tcpip.h"
+#include "../../../../common/inc/SerialPacketSize.h"
+
+/********************************************************************************
+ *
+ * Macro functions
+ *
+ ********************************************************************************/
+
+/********************************************************************************
+ *
+ * CStatTransportTCPIP -- Constructor
+ *
+ *******************************************************************************/
+CStatTransportTCPIP *CStatTransportTCPIP::NewL( void )
+{
+	CStatTransportTCPIP *self = new (ELeave) CStatTransportTCPIP();
+    CleanupStack::PushL(self);
+	self->ConstructL( );
+	CleanupStack::Pop();
+    return self;
+}
+
+CStatTransportTCPIP::CStatTransportTCPIP() : CActive(EPriorityStandard)
+{
+}
+
+void CStatTransportTCPIP::ConstructL( void )
+{
+	// add this to active scheduler
+	CActiveScheduler::Add(this); 
+
+	// initialise all params	
+
+	iBufferPtr = NULL;
+	iTransport = NULL;
+	iTransportStatus = EIdle;
+	iRWStatus = ENoRW;
+
+	iMaxPacketSize = KMaxTCPIPPacketSize;
+	
+	iBuffer = HBufC8::New( iMaxPacketSize );
+	
+}
+
+CStatTransportTCPIP::~CStatTransportTCPIP()
+{
+	// this will call cancel and remove the active object -- this will call cancel
+	Deque(); 
+
+	// cleanup the sockets
+	switch( iTransportStatus ) {
+
+	case EIdle:
+	case EInitialised:
+	case EDisconnected:
+	case EError:
+		break;
+
+	case EConnected:
+		iDataSocket.Shutdown( RSocket::EImmediate, iStatus );
+		/* fall through */
+
+	case EConnecting:
+		iDataSocket.Close();
+		iListenSocket.Shutdown( RSocket::EImmediate, iStatus );
+		iListenSocket.Close();
+		iSocketServ.Close();
+		break;
+
+	case EDisconnectingData:
+	case EDisconnectingListen:
+		;
+		break;
+	}
+
+	if( iBuffer )
+		{
+			delete iBuffer;
+			iBuffer = NULL;
+		}
+
+	if( iBufferPtr )
+		{
+			delete iBufferPtr;
+			iBufferPtr = NULL;
+		}
+}
+
+/********************************************************************************
+ *
+ * CStatTransportTCPIP -- MStatApiTransport
+ *
+ *******************************************************************************/
+TInt CStatTransportTCPIP::InitialiseL( MNotifyStatTransport *aTransport )
+{
+	// save the transport interface
+	iTransport = aTransport;
+
+	// everything here is done in connect
+	iTransportStatus = EInitialised;
+	return KSTErrSuccess;
+}
+
+TInt CStatTransportTCPIP::Release( void )
+{
+	// release has nothing to do
+	asserte( (iTransportStatus == EDisconnected) || (iTransportStatus == EInitialised) );
+	iTransportStatus = EIdle;
+	return KSTErrSuccess;
+}
+
+TInt CStatTransportTCPIP::ConnectL( TDesC* /*aRemoteHost*/ )
+{
+	// make sure we are in the correct state
+	asserte( iTransportStatus == EInitialised );
+
+	// connect to the socket server, create a socket, bind, listen, accept
+	User::LeaveIfError( iSocketServ.Connect() );
+	User::LeaveIfError( iListenSocket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp) );
+	User::LeaveIfError( iListenSocket.SetLocalPort( KLittleStatPort) );
+	User::LeaveIfError( iListenSocket.Listen(KLittleStatListenQueue) );
+
+	// create a blank socket which is used as the data socket
+	User::LeaveIfError( iDataSocket.Open(iSocketServ) );
+
+	// everything should now be set up, we just wait for a stat connection
+	asserte( !IsActive() );
+	iListenSocket.Accept( iDataSocket, iStatus );
+	SetActive();
+	iTransportStatus = EConnecting;
+
+	// tell the client to wait for an asynchronous response
+	return KSTErrAsynchronous;
+}
+
+TInt CStatTransportTCPIP::Disconnect( void )
+{
+	// must be connected 
+	asserte( (iTransportStatus == EInitialised) || 
+			(iTransportStatus == EConnected)   || 
+			(iTransportStatus == EConnecting)  ||
+			(iTransportStatus == EDisconnectingData) ||
+			(iTransportStatus == EDisconnectingListen) );
+
+	// cancel any pending ops 
+	Cancel();
+
+	// clean up the sockets depending on the state
+	switch( iTransportStatus ) {
+
+	case EConnected:
+		iDataSocket.Shutdown( RSocket::ENormal, iStatus );
+		SetActive();
+		iTransportStatus = EDisconnectingData;
+		return KSTErrAsynchronous;
+
+	case EConnecting:
+	case EDisconnectingData:
+		iDataSocket.Close();
+		iListenSocket.Shutdown( RSocket::ENormal, iStatus );
+		SetActive();
+		iTransportStatus = EDisconnectingListen;
+		return KSTErrAsynchronous;
+
+	case EInitialised:
+	case EDisconnectingListen:
+		// initialised may mean that ConnectL threw an error -- so close the resources
+		iDataSocket.Close();
+		iListenSocket.Close();
+		iSocketServ.Close();
+		return KSTErrSuccess;
+
+	default:
+		;
+	}
+	return KSTErrSuccess;
+}
+
+TInt CStatTransportTCPIP::RequestSend( TDesC8 *aData, const TUint /*aDataLength*/ )
+{
+
+	// make sure the state is correct
+	asserte( iTransportStatus == EConnected );
+	asserte( iRWStatus == ENoRW );
+	iRWStatus = EWritePending;
+	
+	iDataSocket.Write( *aData, iStatus );
+	SetActive();
+	
+	// tell the caller to wait for an asynchronous response
+	return KSTErrAsynchronous;
+
+
+}
+
+TInt CStatTransportTCPIP::RequestReceive( TUint aByteCount )
+{
+
+	// ensure that there are no reads in progress
+	asserte( iTransportStatus == EConnected );
+	asserte( !IsActive() );
+	asserte( iRWStatus == ENoRW );
+	iRWStatus = EReadPending;
+
+	asserte( aByteCount <= static_cast<TUint>(iMaxPacketSize) );
+	asserte( !IsActive() );
+	
+	if(!iBufferPtr)
+		{
+		iBufferPtr = new TPtr8(const_cast<unsigned char*>(iBuffer->Ptr( )),aByteCount);	
+		}
+	else
+		if(iBufferPtr->MaxLength()!=aByteCount)
+			{
+			delete iBufferPtr;
+			iBufferPtr = new TPtr8(const_cast<unsigned char*>(iBuffer->Ptr( )),aByteCount);
+			}
+	
+	iDataSocket.Read( *iBufferPtr, iStatus );
+	SetActive();
+
+	// return to the caller
+	return KSTErrAsynchronous;
+	
+}
+
+TText8 *CStatTransportTCPIP::Error( void )
+{
+	return NULL;
+}
+
+TInt CStatTransportTCPIP::GetPacketSize()
+{
+	// The packet size is configured when we initialise the port.
+	return iMaxPacketSize;
+}
+
+/********************************************************************************
+ *
+ * CStatTransportTCPIP -- Active Object
+ *
+ *******************************************************************************/
+void CStatTransportTCPIP::RunL( void )
+{
+	// if there was an error during connectiong then tell the engine this
+	if( (iTransportStatus == EConnecting) && (iStatus != KErrNone) ) {
+		iTransport->HandleError( KSTErrConnectFailure, (void*)iStatus.Int() );
+		return;
+	}
+
+	//reconnect without restarting STAT
+	if(iStatus != KErrNone)
+		{
+		//if no error due to end of socket connection
+		if(iStatus != KErrDisconnected && iStatus != KErrEof)
+			{
+			_LIT(KFormat,"Error during TCPIP: %d\n");
+			TBuf<50> lBuf;
+			lBuf.Format(KFormat,iStatus.Int());
+			iTransport->HandleInfo(&lBuf);	
+			}
+		
+		// close and reopen the socket
+		iDataSocket.Close();  
+		iDataSocket.Open(iSocketServ);
+
+		// wait for a new connection
+		iTransportStatus = EConnecting;
+		iRWStatus = ENoRW;
+		iListenSocket.Accept( iDataSocket, iStatus );
+		SetActive();
+		return;
+		}
+
+	// handle connection response 
+	if( iTransportStatus == EConnecting ) {
+		asserte( iStatus == KErrNone );
+		iTransportStatus = EConnected;
+		iTransport->HandleConnect( KErrNone );
+		return;
+	}
+
+	// handle shutdown data socket
+	if( iTransportStatus == EDisconnectingData ) {
+		iDataSocket.Close();
+		iListenSocket.Shutdown( RSocket::ENormal, iStatus );
+		SetActive();
+		iTransportStatus = EDisconnectingListen;
+		return;
+	}
+
+	// handle shutdown listen
+	if( iTransportStatus == EDisconnectingListen ) {
+		iListenSocket.Close();
+		iTransportStatus = EDisconnected;
+		iSocketServ.Close();
+		iTransport->HandleDisconnect( KErrNone );
+		return;
+	}
+
+	// if we are writing then notify of the write
+	if( iRWStatus == EWritePending ) {
+		iRWStatus = ENoRW;
+		iTransport->HandleSend( KErrNone );
+		return;
+	}
+
+	// if we are reading then notify of the read
+	if( iRWStatus == EReadPending ) {
+		iRWStatus = ENoRW;
+		iTransport->HandleReceive( KErrNone, iBufferPtr, iBufferPtr->Length( ) );
+		return;
+	}
+}
+
+void CStatTransportTCPIP::DoCancel( void )
+{
+	if( iTransportStatus == EConnecting )
+		{
+		iListenSocket.CancelAccept();
+		}
+
+	if( iRWStatus == EReadPending )
+		{
+		iDataSocket.CancelRead();
+		}
+
+	if( iRWStatus == EWritePending )
+		{
+		iDataSocket.CancelWrite();
+		}
+
+	iRWStatus = ENoRW;
+}
+