--- /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 <bt_sock.h>
+#include <btextnotifiers.h> // Needed to check the NOTIFIERS_SUPPORT_PASSKEY_MIN_LENGTH flag
+#include <btengdiscovery.h>
+#include <btengconstants.h>
+#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