diff -r 000000000000 -r f63038272f30 bluetoothengine/btsap/src/BTSapSocketHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothengine/btsap/src/BTSapSocketHandler.cpp Mon Jan 18 20:28:57 2010 +0200 @@ -0,0 +1,336 @@ +/* +* Copyright (c) 2004-2008 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: +* This class handles data exchange between BTSap server and client +* +*/ + + +// INCLUDE FILES +#include +#include // Needed to check the NOTIFIERS_SUPPORT_PASSKEY_MIN_LENGTH flag +#include +#include +#include "BTSapSocketHandler.h" +#include "BTSapServerState.h" +#include "BTSapSecurityHandler.h" +#include "debug.h" + +// Old versions of RAN always try to connect to the same channel after pairing +// To solve this problem, we try to use always the same channel +const TUint KBTSapProposedChannel = 21; // 21 is big enough and my lucky number ;) +const TInt KListenQueSize = 1; + +CBTSapSocketHandler::CBTSapSocketHandler(CBTSapServerState& aServerState, CBTSapRequestHandler& aRequestHandler) + : CActive(CActive::EPriorityHigh), + iServerState(aServerState), + iChannel(0), + iStateListen(iSockServ, iSocket, iListener, iChannel), + iStateRecv(iSocket, aRequestHandler, &iSniffHandler), + iStateSend(iSocket), + iStateCheckSecurity(iSocket, iSecurityHandler), + iCurrentState(EBTSapSocketStateListen), + iNextState(EBTSapSocketStateRecv) + { + iStateArray.Append(&iStateListen); + iStateArray.Append(&iStateRecv); + iStateArray.Append(&iStateSend); + iStateArray.Append(&iStateCheckSecurity); + + CActiveScheduler::Add(this); + } + +// Destructor. +CBTSapSocketHandler::~CBTSapSocketHandler() + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] ~CBTSapSocketHandler"))); + + Cancel(); + iStateArray.Close(); + + TRAPD(err, UnregisterBTSapServiceL()); + if(err != KErrNone) + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_ERROR, BTSapPrintTrace(_L("[BTSap] ~CBTSapSocketHandler - Couldn't unregister SAP Service!!!"))); + } + + delete iSecurityHandler; + iSocket.Close(); + iListener.Close(); + iSockServ.Close(); + delete iBtDiscovery; + delete iSniffHandler; + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::NewL() +// --------------------------------------------------------- +// +CBTSapSocketHandler* CBTSapSocketHandler::NewL(CBTSapServerState& aServerState, CBTSapRequestHandler& aRequestHandler) + { + CBTSapSocketHandler* self = new (ELeave) CBTSapSocketHandler(aServerState, aRequestHandler); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::ConstructL +// --------------------------------------------------------- +// +void CBTSapSocketHandler::ConstructL() + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: ConstructL"))); + + RegisterBTSapServiceL(); + + iSecurityHandler = CBTSapSecurityHandler::NewL(); + // Now create the Sniff Handler + iSniffHandler = CBTSapSniffHandler::NewL(iSocket, iSockServ); + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::DoCancel +// --------------------------------------------------------- +// +void CBTSapSocketHandler::DoCancel() + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: DoCancel"))); + iStateArray[iCurrentState]->Cancel(); + } + +// --------------------------------------------------------- +// RunL +// --------------------------------------------------------- +// +void CBTSapSocketHandler::RunL() + { + TInt status = iStatus.Int(); + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: RunL: %d"), status)); + TBool disconnecting = EFalse; + + if (iNextState == EBTSapSocketStateListen) + { + // In case we are here, we are disconnecting existing connection + disconnecting = ETrue; + } + + if (status >= KErrNone) + { + TBTSapSocketState nextState = iStateArray[iCurrentState]->Complete(status); + + if (iCurrentState == EBTSapSocketStateListen) + { + // The remote side has created SAP connection + // In order to save RAM, the SAP states are not created until here + iServerState.CreateStatesL(); + } + + if (iNextState == EBTSapSocketStateRecv) + { + iNextState = nextState; + } + + ChangeState(); + } + else + { + // BT link loss or other socket errors + iCurrentState = EBTSapSocketStateRecvWrong; + iServerState.ChangeState(EStateNotConnected); + } + + if (disconnecting) + { + // Disconnect has been completed, notify caller + iServerState.DisconnectCompleteL(status); + } + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::Listen +// --------------------------------------------------------- +void CBTSapSocketHandler::Listen() + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: Listen"))); + + iNextState = EBTSapSocketStateListen; + + if (iCurrentState != EBTSapSocketStateSend) + { + Cancel(); + ChangeState(); + } + + // In order to save RAM, release the SAP states here and create + // them when the connection has been created. + TRAP_IGNORE( iServerState.ReleaseStatesL() ); + + // Make sure the sniffer is disabled when we're listening for an incoming connection + iSniffHandler->Disable(); + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::Send +// --------------------------------------------------------- +void CBTSapSocketHandler::Send(const TDes8& aResponseData) + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: Send"))); + + if (iCurrentState == EBTSapSocketStateRecv || + iCurrentState == EBTSapSocketStateSend) + { + iStateSend.SetResponseData(aResponseData); + iNextState = EBTSapSocketStateSend; + + if (iCurrentState == EBTSapSocketStateRecv) + { + Cancel(); + ChangeState(); + } + } + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::GetRemoteBTAddress +// --------------------------------------------------------- +TInt CBTSapSocketHandler::GetRemoteBTAddress(TBTDevAddr& aBTDevAddr) + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: GetRemoteBTAddress >>"))); + TInt retVal = KErrDisconnected; + + if (iCurrentState == EBTSapSocketStateRecv || + iCurrentState == EBTSapSocketStateSend) + { + TBTSockAddr addr; + iSocket.RemoteName(addr); + aBTDevAddr = addr.BTAddr(); + retVal = KErrNone; + } + + BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: GetRemoteBTAddress: %d"), retVal)); + return retVal; + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::IsSapConnected +// --------------------------------------------------------- +TBool CBTSapSocketHandler::IsSapConnected() + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler::IsSapConnected"))); + return (iCurrentState != EBTSapSocketStateListen); + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::ChangeState +// --------------------------------------------------------- +void CBTSapSocketHandler::ChangeState() + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: ChangeState: %d"), iNextState)); + + iCurrentState = iNextState; + iNextState = EBTSapSocketStateRecv; + iStateArray[iCurrentState]->Enter(iStatus); + SetActive(); + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::RegisterBTSapServiceL +// --------------------------------------------------------- +void CBTSapSocketHandler::RegisterBTSapServiceL() + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler::RegisterBTSapServiceL"))); + + User::LeaveIfError(iSockServ.Connect()); + TProtocolDesc pInfo; + iBtDiscovery = CBTEngDiscovery::NewL(); + TInt err = KErrNone; + + // Old version of RAN always use the same channel, so try to get a fixed one + iChannel = KBTSapProposedChannel; + + User::LeaveIfError(iSockServ.FindProtocol(TProtocolName(KRFCOMMDesC), pInfo)); // Or other protocol + User::LeaveIfError(iListener.Open( iSockServ, pInfo.iAddrFamily, pInfo.iSockType, pInfo.iProtocol)); + + TRfcommSockAddr addr; + TBTServiceSecurity sec; + + sec.SetAuthentication( EMitmRequired ); + sec.SetAuthorisation(ETrue); + sec.SetEncryption(ETrue); + sec.SetPasskeyMinLength(KRequiredPassKeyLen); + addr.SetSecurity(sec); + addr.SetPort(iChannel); + + // On return, _should_ contain a free RFCOMM port + err = iListener.Bind(addr); + + if(err) + { + TInt freeChnl; + err = iListener.GetOpt(KRFCOMMGetAvailableServerChannel, KSolBtRFCOMM, freeChnl); + if (err == KErrNone) + { + err = iListener.SetLocalPort(freeChnl); + iChannel = freeChnl; + } + } + if(err) + { + // Try to bind using KRfcommPassiveAutoBind + iChannel = KRfcommPassiveAutoBind; + addr.SetPort(iChannel); + err = iListener.Bind(addr); + } + + if (!err) + { + // Update with the actual value + iChannel = iListener.LocalPort(); + + // Set the socket to listening + User::LeaveIfError(iListener.Listen(KListenQueSize)); + } + else + { + BTSAP_TRACE_OPT(KBTSAP_TRACE_ERROR, BTSapPrintTrace(_L("[BTSap] CBTSapSocketHandler: RegisterBTSapServiceL: Couldn't register dynamic channel!!! (err = %d)"), err)); + User::Leave( err ); + } + + // register BTSap service profile + TUUID uuid(EBTProfileSAP); + User::LeaveIfError( iBtDiscovery->RegisterSdpRecord(uuid, iChannel, iSdpHandle) ); + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::UnregisterBTSapServiceL +// --------------------------------------------------------- +void CBTSapSocketHandler::UnregisterBTSapServiceL() + { + if(iSdpHandle) + { + User::LeaveIfError(iBtDiscovery->DeleteSdpRecord(iSdpHandle)); + } + } + +// --------------------------------------------------------- +// CBTSapSocketHandler::TState::TState +// --------------------------------------------------------- +CBTSapSocketHandler::TState::TState(RSocket& aSocket) + : iSocket(aSocket) + { + } + +// End of File