dbgagents/trkagent/dbgtrccomm/server/dbgtrcsrvsession.cpp
author ravikurupati
Tue, 02 Mar 2010 10:33:16 +0530
changeset 0 c6b0df440bee
permissions -rw-r--r--
Initial contribution of EPL licensed sources

/*
* Copyright (c) 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: 
*
*/

#include "logging.h"
#include "dbgtrcportmgr.h"
#include "ostbaserouter.h"
#include "dbgtrccmdcodes.h"
#include "ostmessage.h"

#include "dbgtrcsrvsession.h"
#include "dbgtrcsrvserver.h"



// Type definitions

// Constants
const TInt KDbgTrcServerTransferBufferExpandSize = 100;
//const TInt KSlot0 = 0;
const TInt KSlot1 = 1;
const TInt KSlot2 = 2;
//const TInt KSlot3 = 3;

// Enumerations

// Classes referenced

// Static functions
//
// Checks for a null'd handle before attempting complete. 
// If handle is null'd then don't complete as this will panic server.
//
void SafeComplete(const RMessagePtr2& aMessage, TInt aCompletionCode)
{
	if(!aMessage.IsNull())
	{
		aMessage.Complete(aCompletionCode);
	}
}


//
// CDbgTrcSrvSession (source)
//

//
// CTrkTcbSrvServer::CDbgTrcSrvSession()
//
// Constructor
//
CDbgTrcSrvSession::CDbgTrcSrvSession(COstBaseRouter* aOstRouter)
: 	iPendingRead(EFalse),
	iPendingWrite(EFalse),
	iPendingReadBufferLength(0),
	iOstRouter(aOstRouter),
	iRecvMessageQueue(1),
	iProtocolIds(1)
{
	LOG_MSG("CDbgTrcSrvSession::CDbgTrcSrvSession");
}

//
// CTrkTcbSrvServer::~CDbgTrcSrvSession()
//
// Destructor
//
CDbgTrcSrvSession::~CDbgTrcSrvSession()
{
	LOG_MSG("CDbgTrcSrvSession::~CDbgTrcSrvSession");
	
	HandleServerDestruction();
	delete iTransferBuffer;
	
	iRecvMessageQueue.ResetAndDestroy();
	iRecvMessageQueue.Close();
	
	iProtocolIds.Reset();
	iProtocolIds.Close();
	
	//get a reference to the server
	CDbgTrcSrvServer* dbgTrcServer = (CDbgTrcSrvServer*)Server();

	//notify the server that the session has been opened
	if (dbgTrcServer != NULL)
		dbgTrcServer->SessionClosed();
}

//
// CTrkTcbSrvServer::ConstructL()
//
// Creates an instance of CDbgTrcSrvSession.
//
void CDbgTrcSrvSession::ConstructL()
{
	LOG_MSG("CDbgTrcSrvSession::ConstructL");
	
	iTransferBuffer = CBufFlat::NewL(KDbgTrcServerTransferBufferExpandSize);
	
	iRecvMessageQueue.Reset();

	iProtocolIds.Reset();
	
}

void CDbgTrcSrvSession::CreateL()
{
	//get a reference to the server
	CDbgTrcSrvServer* dbgTrcServer = (CDbgTrcSrvServer*)Server();
	
	//notify the server that the session has been opened
	if (dbgTrcServer != NULL)
		dbgTrcServer->SessionOpened();
}
//
// CTrkTcbSrvServer::NewL()
//
// Static self construction
//
CDbgTrcSrvSession* CDbgTrcSrvSession::NewL(COstBaseRouter* aOstRouter)
{
	LOG_MSG("CDbgTrcSrvSession::NewL");

	CDbgTrcSrvSession* self = new(ELeave) CDbgTrcSrvSession(aOstRouter);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
}

//
// CTrkTcbSrvServer::HandleServerDestruction()
//
// Called by the server's destructor. We need to be told that the server is
// being destroyed.
//
void CDbgTrcSrvSession::HandleServerDestruction()
{
	LOG_MSG("CDbgTrcSrvSession::HandleServerDestruction");
	
	// disconnect here just in case if the client has not disconnected before shutting down.
	DoDisconnect();
}

//
// CTrkTcbSrvServer::ServiceL()
//
// Services requests from a client.
// Called by the IPC framework whenever a client sends a request to the server.
//
void CDbgTrcSrvSession::ServiceL(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::ServiceL");

	const TInt cmd = aMessage.Function();	
	switch(cmd)
	{
		case EDbgTrcCmdCodeGetAcmConfig:
			CmdGetAcmConfigL(aMessage);
			break;
		case EDbgTrcCmdCodeSetAcmConfig:
			CmdSetAcmConfigL(aMessage);
			break;
		case EDbgTrcCmdCodeOpen:
			CmdOpenCommPortL(aMessage);
			break;
		case EDbgTrcCmdCodeClose:
			CmdCloseCommPort(aMessage);
			break;
		case EDbgTrcCmdCodeRegisterId:
			CmdRegisterProtocol(aMessage);
			break;
		case EDbgTrcCmdCodeRegisterIds:
			CmdRegisterProtocolIdsL(aMessage);
			break;
		case EDbgTrcCmdCodeUnRegisterId:
			CmdUnRegisterProtocol(aMessage);
			break;
		case EDbgTrcCmdCodeUnRegisterIds:
			CmdUnRegisterProtocolIdsL(aMessage);
			break;
		case EDbgTrcCmdCodeReadMsg:
			CmdReadMsgL(aMessage);
			break;
		case EDbgTrcCmdCodeReadCancel:
			CmdReadCancel(aMessage);			
			break;
		case EDbgTrcCmdCodeWriteMsg:
			CmdWriteMsgL(aMessage);
			break;
		case EDbgTrcCmdCodeWriteCancel:
			CmdWriteCancel(aMessage);			
			break;
		case EDbgTrcCmdDisconnect:
			CmdDisconnect(aMessage);
		default:
			aMessage.Panic(KServerIntiatedSessionPanic, EDbgTrcServerInitiatedClientPanicInvalidOperation);
			break;
	}
				
}


//
// CTrkTcbSrvServer::CmdGetAcmConfigL()
//
// Gets the current port configuration 
//
void CDbgTrcSrvSession::CmdGetAcmConfigL(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdGetAcmConfigL");

	const TInt desLength = static_cast<TInt>(aMessage.Int0());

	if (desLength > 0 && desLength == sizeof(TAcmConfigV01))
	{
		TAcmConfig acmConfig;
		iOstRouter->GetPortConfig(acmConfig);
		
		aMessage.WriteL(KSlot1, acmConfig);		
		aMessage.Complete(KErrNone);
	} 
	else
	{
		aMessage.Complete(KErrBadDescriptor);		
	}
}

//
// CTrkTcbSrvServer::CmdSetAcmConfigL()
//
// Sets the port configuration if its not already set
//
void CDbgTrcSrvSession::CmdSetAcmConfigL(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdSetAcmConfigL");

	const TInt desLength = static_cast<TInt>(aMessage.Int0());

	if (desLength > 0 && desLength == sizeof(TAcmConfigV01))
	{
		TAcmConfig acmConfig;
		aMessage.ReadL(KSlot1, acmConfig);
		
		TInt err = iOstRouter->SetPortConfig(acmConfig);		
		
		aMessage.Complete(err);
	} 
	else
	{
		aMessage.Complete(KErrBadDescriptor);
	}
}

//
// CTrkTcbSrvServer::CmdOpenCommPort()
//
// Opens the comm port, if its already opened, 
// just increments the number of active connects and returns true
//
//
void CDbgTrcSrvSession::CmdOpenCommPortL(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdOpenCommPort");

	TInt err = iOstRouter->OpenCommPortL();
	aMessage.Complete(err);
}

//
// CTrkTcbSrvServer::CmdCloseCommPort()
//
// Closes the comm port, the port is actually closed when the
// number of active connections is 0
//
//
void CDbgTrcSrvSession::CmdCloseCommPort(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdCloseCommPort");

	TInt err = iOstRouter->CloseCommPort();
	aMessage.Complete(err);
}

//
// CTrkTcbSrvServer::CmdRegisterProtocol()
//
// Registers the protocol with the id
// This is necessary to be able to read messages
//
//
void CDbgTrcSrvSession::CmdRegisterProtocol(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdRegisterProtocol");

	const TOstProtIds aProtocolId = static_cast<TOstProtIds>(aMessage.Int0());
	
	TBool aNeedHeader = static_cast<TBool>(aMessage.Int1());
	
	iOstRouter->RegisterProtocol(aProtocolId, this, aNeedHeader);
	
	iProtocolIds.Append(aProtocolId);	
	
	aMessage.Complete(KErrNone);
}

//
// CTrkTcbSrvServer::CmdUnRegisterProtocol()
//
// Registers the protocol with the id
// This is necessary to be able to read messages
//
//
void CDbgTrcSrvSession::CmdUnRegisterProtocol(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdUnRegisterProtocol");

	const TOstProtIds aProtocolId = static_cast<TOstProtIds>(aMessage.Int0());
	
	iOstRouter->UnRegisterProtocol(aProtocolId);
	for (TInt i=0; i<iProtocolIds.Count(); i++)
	{
		if (iProtocolIds[i] == aProtocolId)
		{
			iProtocolIds.Remove(i);
			break;
		}
	}
	
	aMessage.Complete(KErrNone);
}

//
// CTrkTcbSrvServer::CmdRegisterProtocolIds()
//
// Registers the protocol with the id
// This is necessary to be able to read messages
//
//
void CDbgTrcSrvSession::CmdRegisterProtocolIdsL(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdRegisterProtocolIdsL");

	TBool aNeedHeader = static_cast<TBool>(aMessage.Int0());
	const TInt numberOfIds = static_cast<TInt>(aMessage.Int1());

	TBuf8<25> protocolIds;
	aMessage.ReadL(KSlot2, protocolIds);
	
	const TUint8* protocolPtr = protocolIds.Ptr();
	for (TInt i=0; i<numberOfIds; i++)
	{
		iOstRouter->RegisterProtocol((TOstProtIds)protocolPtr[i], this, aNeedHeader);
		iProtocolIds.Append((TOstProtIds)protocolPtr[i]);
	}
	
	aMessage.Complete(KErrNone);

}

//
// CTrkTcbSrvServer::CmdUnRegisterProtocol()
//
// Registers the protocol with the id
// This is necessary to be able to read messages
//
//
void CDbgTrcSrvSession::CmdUnRegisterProtocolIdsL(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdUnRegisterProtocolIdsL");

	const TInt numberOfIds = static_cast<TInt>(aMessage.Int0());
	
	TBuf8<25> protocolIds;
	aMessage.ReadL(KSlot1, protocolIds);
	
	const TUint8* protocolPtr = protocolIds.Ptr();
	for (TInt i=0; i<numberOfIds; i++)
	{
		iOstRouter->UnRegisterProtocol((TOstProtIds)protocolPtr[i]);
		for (TInt j=0; j<iProtocolIds.Count(); j++)
		{
			if (iProtocolIds[j] == (TOstProtIds)protocolPtr[i])
			{
				iProtocolIds.Remove(j);
				break;
			}
		}
	}
	
	aMessage.Complete(KErrNone);
}


//
// CTrkTcbSrvServer::CmdReadMsgL()
//
// Gets the data for read file request and calls the session engine read file method.
//
void CDbgTrcSrvSession::CmdReadMsgL(const RMessage2& aMessage)
{		
	LOG_MSG("CDbgTrcSrvSession::CmdReadMsg");

	if (iProtocolIds.Count() <= 0)
	{
		// No protocols are registered, just complete request here.
		aMessage.Complete(KErrAccessDenied);
		return;
	}
	
	if (iRecvMessageQueue.Count() > 0)
	{
		LOG_MSG("Message found in recieve queue");

		iPendingReadBufferLength = static_cast<TUint>(aMessage.Int0());		
		
		COstMessage* ostMsg = iRecvMessageQueue[0];				
		HBufC8* msg = ostMsg->iMsgBuffer;
		
		if (msg->Length() <= iPendingReadBufferLength)
		{
			//write the file data into the client descriptor
			aMessage.WriteL(KSlot1, msg->Des());			
			aMessage.Complete(KErrNone);
			
			// now remove the message from the queue
			SafeDelete(iRecvMessageQueue[0]);			
			iRecvMessageQueue.Remove(0);
		}
		else
		{
			aMessage.Complete(KErrBadDescriptor);
		}
	}
	else
	{
		if (iPendingRead)
		{			
			aMessage.Complete(KErrAlreadyExists);
		}
		else
		{
			iBlockedRead = aMessage;
			iPendingReadBufferLength = static_cast<TUint>(aMessage.Int0());		
			
			iPendingRead = ETrue;
			
			// initiate the read.
			iOstRouter->ReadMessage();
		}
	}
}

void CDbgTrcSrvSession::CmdReadCancel(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdReadCancel");
	
	if (iPendingRead && iBlockedRead.Handle())
	{
		SafeComplete(iBlockedRead, KErrCancel);
		iPendingRead = EFalse;						
	}
	
	// now complete the read cancel request.	
	SafeComplete(aMessage, KErrNone);
}

void CDbgTrcSrvSession::CmdWriteMsgL(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdWriteMsg");

	if (iPendingWrite)
	{
		aMessage.Complete(KErrAlreadyExists);
	}
	else
	{
		const TBool hasHeader = static_cast<TInt>(aMessage.Int0());
		const TInt msgLength = static_cast<TInt>(aMessage.Int1());
	
		if (msgLength > 0)
		{
			if (!hasHeader && iProtocolIds.Count() != 1)
			{
				// For now, if there is no header, then we should have only one protocol id registered by the client.
				// otherwise we don't support writing the message.
				aMessage.Complete(KErrNotSupported);
				return;
			}
			
			HBufC8* msgData = HBufC8::NewLC(msgLength);
			TPtr8 pMsgData(msgData->Des());
			aMessage.ReadL(KSlot2, pMsgData);
			
			iBlockedWrite = aMessage;
			iPendingWrite = ETrue;
			
			if (hasHeader)
				iOstRouter->WriteMessageL(*msgData, this);
			else
				iOstRouter->WriteMessageL(*msgData, this, iProtocolIds[0]);
			//iOstRouter->WriteMessage(*msgData, this);
			

			CleanupStack::PopAndDestroy(msgData);			
		}
		else
		{
			aMessage.Complete(KErrBadDescriptor);
		}		
	}
}

void CDbgTrcSrvSession::CmdWriteCancel(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdWriteCancel");

	// Just complete the pending writes, we don't really try to cancel the actual writes themselves.
	if (iPendingWrite && iBlockedWrite.Handle())
	{
		SafeComplete(iBlockedWrite, KErrCancel);
		iPendingWrite = EFalse;;							
	}
	
	// now complete the write cancel message
	aMessage.Complete(KErrNone);
}

void CDbgTrcSrvSession::CmdDisconnect(const RMessage2& aMessage)
{
	LOG_MSG("CDbgTrcSrvSession::CmdDisconnect");
	
	DoDisconnect();
	aMessage.Complete(KErrNone);
}


void CDbgTrcSrvSession::DoDisconnect()
{
	LOG_MSG("CDbgTrcSrvSession::Disconnect");

	for (TInt i=0; i<iProtocolIds.Count(); i++)
	{
		iOstRouter->UnRegisterProtocol(iProtocolIds[i]);				
	}
	iProtocolIds.Reset();

	if (iPendingRead)
	{
		SafeComplete(iBlockedRead, KErrCancel);
		iPendingRead = EFalse;					
	}
	if (iPendingWrite)
	{
		SafeComplete(iBlockedWrite, KErrCancel);
		iPendingWrite = EFalse;				
	}
}

//
// CTrkTcbSrvServer::CmdShutDownServer()
//
// Stops the active scheduler. This way, server process will run to completion.
//
void CDbgTrcSrvSession::MessageAvailableL(TDesC8& aMsg)
{
	LOG_MSG("CDbgTrcSrvSession::MessageAvailable");

	if (iPendingRead && iBlockedRead.Handle())
	{
		// read is pending, complete it now
		if (aMsg.Length() <= iPendingReadBufferLength)
		{
			LOG_MSG("Completing read request");

			//write the file data into the client descriptor
			TRAPD(err, iBlockedRead.WriteL(KSlot1, aMsg))						
			SafeComplete(iBlockedRead, err);	
			
			LOG_MSG("Completed read request");
				
			iPendingRead = EFalse;
			// the message is completed, return from here
			return;
		}
		else
		{
			LOG_MSG("Bad descriptor unable to complete read request");
			SafeComplete(iBlockedRead, KErrBadDescriptor);
			iPendingRead = EFalse;
		}
	}
	else
	{
		LOG_MSG("Invalid read request handle");
	}
	
	LOG_MSG("Queueing up the message");
	//
	// No pending read, so add the message to the recv queue
	// Right now, there is no limit on the recv queue.
	// Need to check if we need to limit the number of messages to be queued up.
	// 
	COstMessage* ostMessage = COstMessage::NewL(aMsg);
	iRecvMessageQueue.Append(ostMessage);					
}



void CDbgTrcSrvSession::WriteComplete(TInt aErrCode)
{
	LOG_MSG("CDbgTrcSrvSession::WriteComplete");

	if (iPendingWrite && iBlockedWrite.Handle())
	{
		LOG_MSG("Completing write request");

		SafeComplete(iBlockedWrite, aErrCode);
		iPendingWrite = EFalse;
		
		LOG_MSG("Completed write request");
	}
	else
	{
		LOG_MSG("Invalid write message handle");
	}
}