diff -r 7fdc9a71d314 -r 8ad140f3dd41 hti/HtiCommPlugins/HtiBtCommPlugin/HtiBtCommServer/src/HtiBtCommServerSession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hti/HtiCommPlugins/HtiBtCommPlugin/HtiBtCommServer/src/HtiBtCommServerSession.cpp Wed Oct 13 16:17:58 2010 +0300 @@ -0,0 +1,419 @@ +/* +* 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: Implementation of CHtiBtCommServerSession class. This class +* represents the client session in server. +* +*/ + + + +// INCLUDE FILES +#include "HtiBtClientServerCommon.h" +#include "HtiBtCommServerSession.h" +#include "HtiBtCommServer.h" +#include "BtSerialClient.h" +#include "Logger.h" + +#include +#include +#include + +#include // KErrComModuleReset; + +// CONSTANTS + _LIT(KBtComSessPanic, "BtComSessAssrt"); + +const TInt KBtAddressHexStringLength = 12; // 6 bytes +const TInt KIncomingDataBufSize = 32 * 1024; + +//***************************************************************************** +// +// Class CHtiBtCommServerSession +// +//***************************************************************************** + +/*---------------------------------------------------------------------------*/ +CHtiBtCommServerSession::CHtiBtCommServerSession( CHtiBtCommServer* aServer ) + : CSession2() + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: CHtiBtCommServerSession()"))) + + __DECLARE_NAME( _S( "CHtiBtCommServerSession" ) ); + iBtCommServer = aServer; + iReadRequestComplete = ETrue; // ready to accept read request + iWriteRequestComplete = ETrue; + iConnectRequestComplete = ETrue; + iBtCommServer->SessionCreated(this); + } + +/*---------------------------------------------------------------------------*/ +CHtiBtCommServerSession* CHtiBtCommServerSession::NewL( + CHtiBtCommServer* aServer ) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: NewL()"))) + CHtiBtCommServerSession* session = + new (ELeave) CHtiBtCommServerSession( aServer ); + CleanupStack::PushL( session ); + session->ConstructL(); + CleanupStack::Pop( session ); + return session; + } + +/*---------------------------------------------------------------------------*/ + +void CHtiBtCommServerSession::ConstructL() + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ConstructL()"))) + iBtClient = CBtSerialClient::NewL(*this); + iIncomingDataBuf = HBufC8::NewL(KIncomingDataBufSize); + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ConstructL(): Done"))) + } + +/*---------------------------------------------------------------------------*/ +CHtiBtCommServerSession::~CHtiBtCommServerSession() + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ~CHtiBtCommServerSession()"))) + delete iBtClient; + ResetAll(KErrCancel); + delete iIncomingDataBuf; + if ( iBtCommServer ) + { + iBtCommServer->SessionFreed(); + } + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ~CHtiBtCommServerSession(): Done"))) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::ServiceL( const RMessage2& aMessage ) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ServiceL()"))) + + TRAPD( error, DispatchMessageL( aMessage ) ); + if ( error != KErrNone ) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession::ServiceL error %d"), error);) + } + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ServiceL(): Done"))) + } + + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::DispatchMessageL( const RMessage2 &aMessage ) + { + LOGFW( DebugLog( _L( "CHtiBtCommServerSession: DispatchMessageL()" ) ) ) + + switch ( aMessage.Function() ) + { + case EBtCommServerConnect: + { + HandleConnectRequestL( aMessage ); + } + break; + + case EBtCommServerSend: + { + HandleSendRequestL( aMessage ); + } + break; + case EBtCommServerRecv: + { + HandleReadRequestL( aMessage ); + } + break; + + case ECancelBtCommServerRecv: + case ECancelBtCommServerSend: + { + HandleCancelRequestL( aMessage ); + } + break; + + case EGetServicePortNumber: + { + HandlePortNumberRequestL( aMessage ); + } + break; + + default: + { + LOGFW(ErrLog(_L("CHtiBtCommServerSession::DispatchMessageL: Unknown request: %d. Panicing Client"), aMessage.Function());) + PanicClient( EBadRequest ); + User::Panic( KBtComSessPanic, 1 ); + } + break; + } + LOGFW(DebugLog(_L("CHtiBtCommServerSession: DispatchMessageL(): Done"))) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::HandleConnectRequestL( const RMessage2& aMessage ) + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL()"))) + if ( !iConnectRequestComplete ) + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Already connecting"))) + aMessage.Complete( KErrNotReady ); + } + else + { + if ( iBtClient->Connected() ) + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Already connected"))) + aMessage.Complete( KErrNone ); // Already connected. This is not an error? + } + else + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Starting to connect to remote host"))) + iConnectRequest = aMessage; + iConnectRequestComplete = EFalse; + + TInt dataLength = (TUint16)aMessage.GetDesLength( 0 ); //first message slot + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Data length = %d"), dataLength)); + + TInt port = aMessage.Int1(); + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Port = %d"), port)); + + if ( dataLength < 1 ) + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): No address or name - need to ask device"))) + iBtClient->ConnectL(); // Request is completed in ConnectedToServer + } + else if ( dataLength == KBtAddressHexStringLength ) + { + TBuf8 addressBuf8; + aMessage.ReadL( 0, addressBuf8 ); + TBuf addressBuf; + addressBuf.Copy( addressBuf8 ); + TBTDevAddr address; + TInt result = address.SetReadable( addressBuf ); + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): SetReadable result = %d"), result)); + if ( result != KBtAddressHexStringLength ) + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Not valid address - use it as name"))) + iBtClient->ConnectL( addressBuf, port ); + } + else + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Valid address - connect"))) + iBtClient->ConnectL( address, port ); + } + } + else + { + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Using name to connect"))) + TBTDeviceName8 deviceName8; + aMessage.ReadL( 0, deviceName8 ); + TBTDeviceName deviceName; + deviceName.Copy( deviceName8 ); + iBtClient->ConnectL( deviceName, port ); + } + } + } + LOGFW(DebugLog(_L("CHtiBtCommServer:HandleConnectRequestL(): Done"))) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::HandleReadRequestL( const RMessage2& aMessage ) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: HandleReadRequestL()"))) + + if ( !iReadRequestComplete ) + { + LOGFW(WarnLog(_L("CHtiBtCommServerSession: HandleReadRequestL(): Pending request. ret=KErrNotReady"))) + // Two simultaneous read requests are not allowed. + aMessage.Complete(KErrNotReady); + return; + } + + // No data in read buffer. Must wait for new data before completing request + iReadRequest = aMessage; + iReadRequestComplete = EFalse; // Not ready to complete next request + TryCompleteReadRequest(); // if there is something in the readbuffer, + // use it for completion. + + if ( iIncomingDataBuf->Des().Length() == 0 ) + { + // Read some bytes to buffer even before client's request. + iBtClient->ReadAsyncL(); // Issue async request to read more data. + } + + LOGFW(DebugLog(_L("CHtiBtCommServerSession: HandleReadRequestL(): Done"))) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::HandleSendRequestL( const RMessage2& aMessage ) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: HandleSendRequestL()"))) + + TInt dataLength = (TUint16)aMessage.GetDesLength( 0 ); //first message slot + LOGFW( InfoLog( _L( "Framework requested to send data: %d bytes" ), dataLength ) ) + if ( iBtClient->SendBufferMaxSize() < dataLength ) + { + aMessage.Complete(KErrOverflow); + LOGFW(ErrLog(_L("CHtiBtCommServerSession: HandleSendRequestL(): client is giving too big data. Cannot handle."))) + } + else if ( !iWriteRequestComplete ) + { + LOGFW(WarnLog(_L("CHtiBtCommServerSession: HandleSendRequestL(): Pending request. ret=KErrNotReady"))) + // Already pending send request. Two simultaneous send requests not allowed. + aMessage.Complete( KErrNotReady ); + } + else + { + if ( iBtClient->FreeSpaceInSendBuffer() < dataLength ) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: HandleSendRequestL(): Completing send request delayed"))) + // No space in the iBtClient's send buffer. Copy the data to internal + // buffer and wait for iBtClient to send its data out before adding + // data to its send buffer. + delete iSendBuffer; + iSendBuffer = NULL; + iSendBuffer = HBufC8::NewL(dataLength); + TPtr8 ptr = iSendBuffer->Des(); + aMessage.ReadL( 0, ptr ); + iWriteRequestComplete = EFalse; + iWriteRequest = aMessage; + // Wait for callback call AllBufferedDataSent. Complete request there. + } + else + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: HandleSendRequestL(): Completing send request immediately"))) + // All data can be sent immediately, because there is enough space in + // iBtClient's send buffer. + HBufC8* data = HBufC8::NewLC( dataLength ); + TPtr8 ptr = data->Des(); + aMessage.ReadL( 0, ptr ); + iBtClient->SendL( ptr ); + CleanupStack::PopAndDestroy( data ); + aMessage.Complete( KErrNone ); + } + } + LOGFW(DebugLog(_L("CHtiBtCommServerSession: HandleSendRequestL(): Done"))) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::HandleCancelRequestL( const RMessage2& aMessage ) + { + ResetAll( KErrCancel ); + aMessage.Complete( KErrNone ); + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::HandlePortNumberRequestL(const RMessage2& aMessage) + { + TPckgBuf p( iBtClient->ServicePort() ); + TInt err = aMessage.Write( 0, p, 0 ); + aMessage.Complete( err ); + } + +/*---------------------------------------------------------------------------*/ + +void CHtiBtCommServerSession::PanicClient(TInt aPanic) const + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: PanicClient(): %d"), aPanic)) + LOGFW(WarnLog(_L("CHtiBtCommServerSession: PanicClient(): %d. NOT IMPLEMENTED"), aPanic)) + aPanic = aPanic; + // should be done with RMessage2? + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::ResetAll(TInt aCompletionCode) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ResetAll()"))) + if ( !iWriteRequestComplete ) + iWriteRequest.Complete( aCompletionCode ); + if ( !iReadRequestComplete ) + iReadRequest.Complete( aCompletionCode ); + if ( !iConnectRequestComplete ) + iConnectRequest.Complete( aCompletionCode ); // error when making connection + iWriteRequestComplete = ETrue; + iReadRequestComplete = ETrue; + iConnectRequestComplete = ETrue; + delete iIncomingDataBuf; + iIncomingDataBuf = NULL; + delete iSendBuffer; + iSendBuffer = NULL; + iIncomingDataBuf = HBufC8::New(KIncomingDataBufSize); + LOGFW(DebugLog(_L("CHtiBtCommServerSession: ResetAll(): Done"))) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::ConnectedToServer(TInt aError) + { + // Connected to server. Reading has been started. + LOGFW(InfoLog(_L("CHtiBtCommServerSession: ConnectedToServer: connected to remote host"))) + iConnectRequestComplete = ETrue; + iConnectRequest.Complete( aError ); + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::DisconnectedFromServer() + { + LOGFW(InfoLog(_L("CHtiBtCommServerSession: DisconnectedFromServer: disconnected from remote host"))) + ResetAll( KErrDisconnected ); + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::DataFromServer(const TDesC8& aData) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: DataFromServer: %d bytes"), aData.Length())) + TPtr8 ptr = iIncomingDataBuf->Des(); + if ( aData.Length() > ptr.MaxLength() - ptr.Length() ) + PanicClient( KErrUnderflow ); // Client is reading too slowly + + ptr.Append( aData ); + TryCompleteReadRequest(); + LOGFW(DebugLog(_L("CHtiBtCommServerSession: DataFromServer: done"), aData.Length())) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::AllBufferedDataSent() + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: AllBufferedDataSent"))) + if ( !iWriteRequestComplete ) + { + // iBtClient has sent all of its data and is ready to send more. + TPtr8 ptr = iSendBuffer->Des(); + TRAPD( err, iBtClient->SendL( ptr ); ) + iWriteRequest.Complete( err ); + iWriteRequestComplete = ETrue; + delete iSendBuffer; + iSendBuffer = NULL; + } + LOGFW(DebugLog(_L("CHtiBtCommServerSession: AllBufferedDataSent: Done"))) + } + +/*---------------------------------------------------------------------------*/ +void CHtiBtCommServerSession::TryCompleteReadRequest() + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: TryCompleteReadRequest"))) + TPtr8 ptr = iIncomingDataBuf->Des(); + + if ( iReadRequestComplete || ptr.Length() == 0 ) + { + LOGFW(DebugLog(_L("CHtiBtCommServerSession: TryCompleteReadRequest: Nothing to complete"))) + return; // No outstanding client request to complete + } + + TInt dataMaxLength = (TUint16)iReadRequest.GetDesMaxLength(0); //first message slot + TPtrC8 dataToClient = ptr.Left(dataMaxLength); + TRAPD(err, iReadRequest.WriteL(0, dataToClient);) + + ptr.Delete(0, dataToClient.Length()); + iReadRequest.Complete(err); + iReadRequestComplete = ETrue; + LOGFW(DebugLog(_L("CHtiBtCommServerSession: TryCompleteReadRequest: Done"))) + } + +// End of file