diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/secman/pairingserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/secman/pairingserver.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,1214 @@ +// Copyright (c) 2008-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: +// + +/** + @file + @internalComponent +*/ + +#include +#include +#include +#include + +#include "pairingserversecuritypolicy.h" +#include "oobdata.h" +#include "pairingserver.h" + +#include +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_PAIRING_SERVER); +#endif + +#ifdef _DEBUG +PANICCATEGORY("pairingsrv"); +#endif + +// These come after the logging to ensure that debug.h knows we're using the +// bluetooth logger. +#include "physicallinksmanager.h" +#include "ProxySAP.h" + +// +// CPairingServer +// + +CPairingServer* CPairingServer::NewL(COobDataManager& aOobDataManager, CSimplePairingResultList& aSimplePairingResultList, CAuthenticationResultList& aAuthenticationResultList) + { + LOG_STATIC_FUNC + + CPairingServer* self = new(ELeave) CPairingServer(aOobDataManager, aSimplePairingResultList, aAuthenticationResultList); + CleanupStack::PushL(self); + // StartL is where the kernel checks that there isn't already an instance + // of the same server running, so do it before ConstructL. + self->StartL(KPairingServerName); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CPairingServer::~CPairingServer() + { + LOG_FUNC + delete iContainerIndex; + } + +CPairingServer::CPairingServer(COobDataManager& aOobDataManager, CSimplePairingResultList& aSimplePairingResultList, CAuthenticationResultList& aAuthenticationResultList) + : CPolicyServer(CActive::EPriorityStandard, KPairingServerPolicy) + , iOobDataManager(aOobDataManager) + , iSimplePairingResultList(aSimplePairingResultList) + , iAuthenticationResultList(aAuthenticationResultList) + { + LOG_FUNC + } + +void CPairingServer::ConstructL() + { + LOG_FUNC + iContainerIndex = CObjectConIx::NewL(); + } + +// Callback to LinksMgrProtocol to add a pairing session +void CPairingServer::AddSession() + { + LOG_FUNC + if(iSessionCount++ == 0) + { + // While we have clients we need to make sure that the protocol remains alive. + iLinkMgrProtocol->LocalOpen(); + } + } + +// Callback to LinksMgrProtocol to remove a pairing session +void CPairingServer::DropSession() + { + LOG_FUNC + if(--iSessionCount == 0) + { + // There are no longer any clients + iLinkMgrProtocol->LocalClose(); + } + } + +void CPairingServer::SetPhysicalLinksManager(CPhysicalLinksManager& aLinksMan) + { + LOG_FUNC + __ASSERT_DEBUG(!iLinksMan, PANIC(KPairingServerFaultCat, EPairingServerLinkManagerAlreadyProvided)); + iLinksMan = &aLinksMan; + } + +void CPairingServer::ClearPhysicalLinkMgr() + { + LOG_FUNC + iLinksMan = NULL; + } + +// Save a reference to the LinksMgrProtocol +void CPairingServer::SetLinksMgrProtocol(CLinkMgrProtocol& aLinkMgrProtocol) + { + LOG_FUNC + iLinkMgrProtocol = &aLinkMgrProtocol; + } + +// Clear the reference to the LinksMgrProtocol +void CPairingServer::ClearLinksMgrProtocol() + { + LOG_FUNC + iLinkMgrProtocol = NULL; + } + +CSession2* CPairingServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const + { + LOG_FUNC + LOG3(_L("aVersion = (%d, %d, %d)"), aVersion.iMajor, aVersion.iMinor, aVersion.iBuild) + + // Version number check... + TVersion v(KPairingServerMajorVersionNumber, + KPairingServerMinorVersionNumber, + KPairingServerBuildVersionNumber); + if(!User::QueryVersionSupported(v, aVersion)) + { + User::LeaveIfError(KErrNotSupported); + } + + // Ensure that the reference to the LinksMgrProtocol has been receieved + if(!iLinkMgrProtocol) + { + User::Leave(KErrNotReady); + } + // Cast 'this' to allow use in Constructor + CPairingServer* ncThis = const_cast(this); + CPairingSession* sess = CPairingSession::NewL(*ncThis); + return sess; + } + +CObjectCon* CPairingServer::NewContainerL() + { + LOG_FUNC + return iContainerIndex->CreateL(); + } + +void CPairingServer::DeleteContainer(CObjectCon* aContainer) + { + LOG_FUNC + iContainerIndex->Remove(aContainer); + } + +CPhysicalLinksManager& CPairingServer::LinksManL() const + { + LOG_FUNC + if(!iLinksMan) + { + LEAVEL(KErrNotReady); + } + return *iLinksMan; + } + +COobDataManager& CPairingServer::OobDataManager() const + { + LOG_FUNC + return iOobDataManager; + } + +CSimplePairingResultList& CPairingServer::SimplePairingResultList() const + { + LOG_FUNC + return iSimplePairingResultList; + } + +CAuthenticationResultList& CPairingServer::AuthenticationResultList() const + { + LOG_FUNC + return iAuthenticationResultList; + } + +// +// CPairingSession +// + +CPairingSession* CPairingSession::NewL(CPairingServer& aPairingServer) + { + LOG_STATIC_FUNC + CPairingSession* self = new(ELeave) CPairingSession(aPairingServer); + aPairingServer.AddSession(); + return self; + } + +CPairingSession::CPairingSession(CPairingServer& aPairingServer) + : iPairingServer(aPairingServer) + { + LOG_FUNC + } + +CPairingServer& CPairingSession::Server() const + { + LOG_FUNC + return *static_cast(const_cast(CSession2::Server())); + } + +CPairingSession::~CPairingSession() + { + LOG_FUNC + iPairingServer.DropSession(); + delete iSubSessions; // Must be deleted before container to ensure ref counting is correct + Server().DeleteContainer(iContainer); + } + +void CPairingSession::CreateL() + { + LOG_FUNC + iSubSessions = CObjectIx::NewL(); + iContainer = Server().NewContainerL(); + __TEST_INVARIANT; + } + +#ifdef _DEBUG +void CPairingSession::__DbgTestInvariant() const + { + LOG_FUNC + __ASSERT_DEBUG(iContainer->Count() == iSubSessions->ActiveCount(), + PANIC(KPairingServerFaultCat, EPairingServerSessionContainerAndIndexMismatch)); + } +#endif // _DEBUG + +void CPairingSession::ServiceL(const RMessage2& aMessage) + { + LOG_FUNC + LOG1(_L("aMessage.Function() = &d"), aMessage.Function()); +// __TEST_INVARIANT; // Not needed as all major functional exits are checked + TBool handled = DispatchSessMessageL(aMessage); + if(!handled) + { + // if not handled, it must be a subsession request. + DispatchSubSessMessageL(aMessage); + } + __TEST_INVARIANT; + } + +void CPairingSession::ServiceError(const RMessage2& aMessage, TInt aError) + { + LOG_FUNC + LOG1(_L("aError = %d"), aError); + if(aError == KErrBadDescriptor) + { + // If a KErrBadDescriptor is received then the request is bad so punish. + aMessage.Panic(KPairingServerPanicCat, EPairingServerBadDescriptor); + } + else + { + aMessage.Complete(aError); + } + __TEST_INVARIANT; + } + +TBool CPairingSession::DispatchSessMessageL(const RMessage2& aMessage) + { + LOG_FUNC + TBool handled = ETrue; + switch(aMessage.Function()) + { + case EPairingServerCreateOobDataSubSession: + NewOobDataSubSessionL(aMessage); + break; + + case EPairingServerCreateDedicatedBondingSubSession: + NewDedicatedBondingSubSessionL(aMessage); + break; + + case EPairingServerCreateSimplePairingResultSubSession: + NewSimplePairingResultSubSessionL(aMessage); + break; + + case EPairingServerCreateAuthenticationResultSubSession: + NewAuthenticationResultSubSessionL(aMessage); + break; + + case EPairingServerCloseSubSession: + DeleteSubSession(aMessage); + break; + + default: + handled = EFalse; + break; + } + return handled; + } + +void CPairingSession::DispatchSubSessMessageL(const RMessage2& aMessage) + { + LOG_FUNC + CPairingSubSession* ss = SubSessionFromHandle(aMessage.Int3()); + if(!ss) + { + aMessage.Panic(KPairingServerPanicCat, EPairingServerBadSubSessionHandle); + } + else + { + ss->DispatchSubSessMessageL(aMessage); + } + } + +CPairingSubSession* CPairingSession::SubSessionFromHandle(TInt aHandle) + { + LOG_FUNC + LOG1(_L("aHandle = %d"), aHandle); + return static_cast(iSubSessions->At(aHandle)); + } + +void CPairingSession::NewOobDataSubSessionL(const RMessage2& aMessage) + { + LOG_FUNC + COobDataSession* oob = COobDataSession::NewLC(*this, Server().OobDataManager()); + SubSessionConstructL(aMessage, oob); // handles oob on CleanupStack + } + +void CPairingSession::NewDedicatedBondingSubSessionL(const RMessage2& aMessage) + { + LOG_FUNC + CDedicatedBondingSession* ded = CDedicatedBondingSession::NewLC(*this, Server().LinksManL()); + SubSessionConstructL(aMessage, ded); // handles ded on CleanupStack + } + +void CPairingSession::NewSimplePairingResultSubSessionL(const RMessage2& aMessage) + { + LOG_FUNC + CSimplePairingResultSession* sim = CSimplePairingResultSession::NewLC(*this, Server().SimplePairingResultList()); + SubSessionConstructL(aMessage, sim); + } + + +void CPairingSession::NewAuthenticationResultSubSessionL(const RMessage2& aMessage) + { + LOG_FUNC + CAuthenticationResultSession* aut = CAuthenticationResultSession::NewLC(*this, Server().AuthenticationResultList()); + SubSessionConstructL(aMessage, aut); + } + +/** +This function handles the subsession handle binding to the subsession that has been +created. +*/ +void CPairingSession::SubSessionConstructL(const RMessage2& aMessage, CPairingSubSession* aSubSession) + { + LOG_FUNC + // The subsession is on the cleanup stack when this function is called. + TInt subSessionHandleLength = aMessage.GetDesMaxLengthL(3); + if(subSessionHandleLength != sizeof(TInt)) + { + aMessage.Panic(KPairingServerPanicCat, EPairingServerBadDescriptor); + CleanupStack::PopAndDestroy(aSubSession); + } + else + { + iContainer->AddL(aSubSession); + TInt handle = iSubSessions->AddL(aSubSession); + CleanupStack::Pop(aSubSession); // Now lifetime is controlled by the binding CObjectIx + TPckg pckgHandle(handle); + TRAPD(err, aMessage.WriteL(3, pckgHandle)); + if(err != KErrNone) + { + iSubSessions->Remove(handle); + LEAVEL(err); + } + aMessage.Complete(KErrNone); + } + } + +void CPairingSession::DeleteSubSession(const RMessage2& aMessage) + { + LOG_FUNC + TInt handle = aMessage.Int3(); + CPairingSubSession* ss = SubSessionFromHandle(handle); + if(!ss) + { + aMessage.Panic(KPairingServerPanicCat, EPairingServerBadSubSessionHandle); + } + else + { + iSubSessions->Remove(handle); + aMessage.Complete(KErrNone); + } + } + + +// +// CPairingSubSession +// + +CPairingSubSession::CPairingSubSession(CPairingSession& aSession) + : iSession(aSession) + { + LOG_FUNC + } + +CPairingSubSession::~CPairingSubSession() + { + LOG_FUNC + } + +void CPairingSubSession::DispatchSubSessMessageL(const RMessage2& /*aMessage*/) + { + LOG_FUNC + LEAVEL(KErrNotSupported); + } + +void CPairingSubSession::ConstructL() + { + LOG_FUNC + } + +CPairingSession& CPairingSubSession::Session() const + { + LOG_FUNC + return iSession; + } + + +// +// COobDataSession +// + +COobDataSession* COobDataSession::NewLC(CPairingSession& aSession, COobDataManager& aOobDataManager) + { + LOG_STATIC_FUNC + COobDataSession* self = new(ELeave) COobDataSession(aSession, aOobDataManager); + //As its a CObject derived class so we should use CleanupClosePushL + CleanupClosePushL(*self); + self->ConstructL(); + return self; + } + +COobDataSession::COobDataSession(CPairingSession& aSession, COobDataManager& aOobDataManager) + : CPairingSubSession(aSession) + , iOobDataManager(aOobDataManager) + { + LOG_FUNC + } + +COobDataSession::~COobDataSession() + { + LOG_FUNC + TryCancelReadLocalOobData(); + } + +COobDataManager& COobDataSession::OobDataManager() const + { + LOG_FUNC + return iOobDataManager; + } + +void COobDataSession::DispatchSubSessMessageL(const RMessage2& aMessage) + { + LOG_FUNC + switch(aMessage.Function()) + { + case EPairingServerOobDataRefreshLocal: + iOobDataManager.RefreshLocalOobData(); + aMessage.Complete(KErrNone); + break; + case EPairingServerOobDataReadLocal: + ReadLocalOobDataL(aMessage); + break; + case EPairingServerOobDataCancelReadLocal: + CancelReadLocalOobData(aMessage); + break; + case EPairingServerOobDataProvideRemoteParsed: + ProvideParsedRemoteOobDataL(aMessage); + break; + case EPairingServerOobDataProvideRemoteRaw: + ProvideRawRemoteOobDataL(aMessage); + break; + case EPairingServerOobDataClearRemote: + ClearRemoteOobDataL(aMessage); + break; + default: + CPairingSubSession::DispatchSubSessMessageL(aMessage); + break; + } + } + +void COobDataSession::ProvideParsedRemoteOobDataL(const RMessage2& aMessage) + { + LOG_FUNC + + TPckgBuf addrBuf; + if(aMessage.GetDesLengthL(0) != sizeof(TBTDevAddr)) + { + LEAVEL(KErrBadDescriptor); + } + aMessage.ReadL(0, addrBuf); + + TBluetoothSimplePairingHash hash; + if(aMessage.GetDesLengthL(1) != KBluetoothSimplePairingHashSize) + { + LEAVEL(KErrBadDescriptor); + } + aMessage.ReadL(1, hash); + + TBluetoothSimplePairingRandomizer randomizer; + TInt len = aMessage.GetDesLength(2); + if (len < KErrNone) // The randomizer wasn't available (which is fine...) + { + randomizer.FillZ(KBluetoothSimplePairingRandomizerSize); + } + else + { + if(len != KBluetoothSimplePairingRandomizerSize) + { + LEAVEL(KErrBadDescriptor); + } + aMessage.ReadL(2, randomizer); + } + + TOobData oobData(addrBuf(), hash, randomizer); + OobDataManager().ProvideRemoteOobDataL(oobData); + aMessage.Complete(KErrNone); + } + +void COobDataSession::ProvideRawRemoteOobDataL(const RMessage2& aMessage) + { + LOG_FUNC + //Do a quick check to ensure there is at least enough data to get the BT address out. + if(aMessage.GetDesLengthL(0) < KOOBOptionalDataOffset) + User::Leave(KErrUnderflow); + + RBuf8 rawBuf; + rawBuf.CreateL(aMessage.GetDesMaxLengthL(0)); + rawBuf.CleanupClosePushL(); + //Read the optional oob data to rawbuf so it can be parsed to the data block parser + aMessage.ReadL(0, rawBuf, KOOBOptionalDataOffset); + rawBuf.SetMax(); + + //We need to get the address out manually, EIR can't parse the address an no EIR device + //address tag is defined. We are currently ignoring the length and anything other than + //the pairing hash & randomizer. + TBuf8 addrBuf; + aMessage.ReadL(0, addrBuf, KOOBBtAddrOffset); + TBTDevAddr addr(addrBuf); + + //Any remaining data is optional and will be in EIR format so we can use the + //EIR object to parse the data properly. + TExtendedInquiryResponseDataCodec dataBlockParser(rawBuf); + + TPtrC8 hashBuf; + LEAVEIFERRORL(dataBlockParser.GetData(EEirOobSimplePairingHash, hashBuf)); + if(hashBuf.Length() != KBluetoothSimplePairingHashSize) + { + LEAVEL(KErrCorrupt); + } + TBluetoothSimplePairingHash hash(hashBuf); + + TPtrC8 randomizerBuf; + TBluetoothSimplePairingRandomizer randomizer; + TInt err = dataBlockParser.GetData(EEirOobSimplePairingRandomizerR, randomizerBuf); + if(err < KErrNone) // The randomizer wasn't available (which is fine...) + { + randomizer.FillZ(KBluetoothSimplePairingRandomizerSize); + } + else + { + if(randomizerBuf.Length() != KBluetoothSimplePairingRandomizerSize) + { + LEAVEL(KErrCorrupt); + } + randomizer.Copy(randomizerBuf); + } + + // Mark this line as intentional as coverity raises a false positive error that hash + // has not been initalised even though it is set to hashBuf a few lines above. + // coverity[uninit_use_in_call] + TOobData oobData(addr, hash, randomizer); + OobDataManager().ProvideRemoteOobDataL(oobData); + + CleanupStack::PopAndDestroy(&rawBuf); // finished with the backing buffer + + aMessage.Complete(KErrNone); + } + +void COobDataSession::ClearRemoteOobDataL(const RMessage2& aMessage) + { + LOG_FUNC + TPckgBuf addrBuf; + if(aMessage.GetDesLengthL(0) != sizeof(TBTDevAddr)) + { + LEAVEL(KErrBadDescriptor); + } + aMessage.ReadL(0, addrBuf); + + OobDataManager().ClearRemoteOobData(addrBuf()); + aMessage.Complete(KErrNone); + } + +void COobDataSession::ReadLocalOobDataL(const RMessage2& aMessage) + { + LOG_FUNC + if(iReadLocalOobDataMsg.Handle()) + { + aMessage.Panic(KPairingServerPanicCat, EPairingServerReadLocalOobDataOutstanding); + return; + } + iReadLocalOobDataMsg = aMessage; // Remember which request to complete. + OobDataManager().ReadLocalOobData(*this); + } + +void COobDataSession::CancelReadLocalOobData(const RMessage2& aMessage) + { + LOG_FUNC + TryCancelReadLocalOobData(); + aMessage.Complete(KErrNone); + } + +void COobDataSession::TryCancelReadLocalOobData() + { + LOG_FUNC + if(iReadLocalOobDataMsg.Handle()) + { + OobDataManager().CancelReadLocalOobData(*this); + } + } + + +void COobDataSession::XoldoLocalOobDataRetrieved(TInt aResult, const TBluetoothSimplePairingHash& aHash, const TBluetoothSimplePairingRandomizer& aRandomizer) + { + LOG_FUNC + __ASSERT_DEBUG(iReadLocalOobDataMsg.Handle(), + PANIC(KPairingServerFaultCat, EPairingServerNoMessageForObserverCompletion)); + + TInt err = aResult; + if(err == KErrNone) + { + TRAP(err, LocalOobDataRetrievedL(aHash, aRandomizer)); + } + if(err == KErrBadDescriptor) + { + iReadLocalOobDataMsg.Panic(KPairingServerPanicCat, EPairingServerBadDescriptor); + } + else + { + iReadLocalOobDataMsg.Complete(err); + } + } + +void COobDataSession::LocalOobDataRetrievedL(const TBluetoothSimplePairingHash& aHash, const TBluetoothSimplePairingRandomizer& aRandomizer) + { + LOG_FUNC + iReadLocalOobDataMsg.WriteL(0, aHash); + iReadLocalOobDataMsg.WriteL(1, aRandomizer); + } + + +// +// CDedicatedBondingSession +// + +CDedicatedBondingSession* CDedicatedBondingSession::NewLC(CPairingSession& aSession, CPhysicalLinksManager& aPhysicalLinksManager) + { + LOG_STATIC_FUNC + CDedicatedBondingSession* self = new(ELeave) CDedicatedBondingSession(aSession, aPhysicalLinksManager); + //As its a CObject derived class so we should use CleanupClosePushL + CleanupClosePushL(*self); + self->ConstructL(); + return self; + } + +CDedicatedBondingSession::CDedicatedBondingSession(CPairingSession& aSession, CPhysicalLinksManager& aPhysicalLinksManager) + : CPairingSubSession(aSession) + , iPhysicalLinksManager(aPhysicalLinksManager) + { + LOG_FUNC + } + +void CDedicatedBondingSession::ConstructL() + { + LOG_FUNC + CPairingSubSession::ConstructL(); + TCallBack cb(CDedicatedBondingSession::StaticShutdown, this); + iAsyncShutdown = new(ELeave) CAsyncCallBack(cb, CActive::EPriorityStandard); + } + +CDedicatedBondingSession::~CDedicatedBondingSession() + { + LOG_FUNC + iPhysicalLinksManager.SecMan().CancelRequest(*this); + delete iProxySap; + if(iStartBondingMsg.Handle()) + { + iStartBondingMsg.Complete(KErrCancel); + } + delete iAsyncShutdown; + } + +void CDedicatedBondingSession::DispatchSubSessMessageL(const RMessage2& aMessage) + { + LOG_FUNC + switch(aMessage.Function()) + { + case EPairingServerStartDedicatedBond: + StartBondingL(aMessage); + break; + default: + CPairingSubSession::DispatchSubSessMessageL(aMessage); + break; + } + } + +void CDedicatedBondingSession::Complete(TInt aError) + { + LOG_FUNC + iState = EShutdown; + iAsyncShutdown->CallBack(); + iStartBondingMsg.Complete(aError); + } + +TInt CDedicatedBondingSession::StaticShutdown(TAny* aDedBond) + { + LOG_STATIC_FUNC + reinterpret_cast(aDedBond)->Shutdown(); + return KErrNone; + } + +void CDedicatedBondingSession::Shutdown() + { + LOG_FUNC + __ASSERT_DEBUG(iState == EShutdown, PANIC(KPairingServerFaultCat, EPairingServerBadShutdownState)); + iState = EInvalid; + iProxySap->Shutdown(CServProviderBase::ENormal); + } + +void CDedicatedBondingSession::StartBondingL(const RMessage2& aMessage) + { + LOG_FUNC + + if(!iStartBondingMsg.IsNull() || iState != EInvalid) + { + aMessage.Panic(KPairingServerPanicCat, EPairingServerDedicatedBondAlreadyInProgress); + return; + } + + TPckgBuf addrBuf; + TInt addrLen = aMessage.GetDesLengthL(0); + if(addrLen != sizeof(TBTDevAddr)) + { + // If the length is correct then the address has been packaged incorrect for the + // IPC operation. + LEAVEL(KErrBadDescriptor); + } + aMessage.ReadL(0, addrBuf); + + iStartBondingMsg = aMessage; + CleanupStack::PushL(TCleanupItem(CleanupStartMessage, this)); + + TBTSockAddr addr; + addr.SetBTAddr(addrBuf()); + iProxySap = CBTProxySAP::NewL(iPhysicalLinksManager, NULL); + + CleanupStack::Pop(this); // the start message cleaner + + iState = EInitialConnectionPending; + iProxySap->SetNotify(this); + iProxySap->SetRemName(addr); + iProxySap->ActiveOpen(); + } + +void CDedicatedBondingSession::CleanupStartMessage(TAny* aPtr) + { + LOG_STATIC_FUNC + CDedicatedBondingSession* session = reinterpret_cast(aPtr); + session->iStartBondingMsg = RMessage2(); // blat the old one + } + +void CDedicatedBondingSession::DoAccessRequestL() + { + LOG_FUNC + TBTServiceSecurity security; + security.SetAuthentication(EMitmDesired); + security.SetUid(KBluetoothDedicatedBondingUid); + + iPhysicalLinksManager.SecMan().AccessRequestL(security, NULL, iProxySap->RemoteAddress(), EDedicatedBonding, *this); + } + +void CDedicatedBondingSession::AccessRequestComplete(TInt aResult) + { + LOG_FUNC + TInt err = aResult; + TBool completed = EFalse; + TBTSockAddr addr; + switch (iState) + { + case EZombie: + // Ready for a retry. + if(aResult == EBTSecManAccessDeferred) + { + iState = EFinalConnectionPending; + addr.SetBTAddr(iProxySap->RemoteAddress()); + iProxySap->SetRemName(addr); // triggers finding a link again. + iProxySap->ActiveOpen(); + break; + } + // else not deferred so complete now.... + // fall-through... + case EInitialConnection: + ASSERT_DEBUG(aResult != EBTSecManAccessDeferred); // Should have been disconnected if we receive + // this - I don't expect this to happen. + // fall-through... + case EFinalConnection: + completed = ETrue; // in the final connection any complete is errored. + if(aResult == EBTSecManAccessDenied) + { + err = KErrAccessDenied; + } + break; + default: + LOG1(_L("Unexpected Access Request Complete in state %d"), iState); + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedAccessCallback)); + break; + } + + if (completed) + { + Complete(err); + } + } + +void CDedicatedBondingSession::NewData(TUint /*aCount*/) + { + LOG_FUNC + // We aren't using a raw conduit + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + } + +void CDedicatedBondingSession::CanSend() + { + LOG_FUNC + // We aren't using a raw conduit + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + } + +void CDedicatedBondingSession::ConnectCompleteL() + { + LOG_FUNC + switch(iState) + { + case EInitialConnectionPending: + iState = EInitialConnection; + DoAccessRequestL(); + break; + case EFinalConnectionPending: + iState = EFinalConnection; + DoAccessRequestL(); + break; + case EInitialConnection: + case EFinalConnection: + // Apparently multiple connect completes are allowed by CSocket + break; + default: + LOG1(_L("Unexpected Connect Complete in state %d"), iState); + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + break; + } + } + +void CDedicatedBondingSession::ConnectComplete() + { + LOG_FUNC + TRAPD(err, ConnectCompleteL()); + if(err != KErrNone) + { + Error(err); + } + } + +void CDedicatedBondingSession::ConnectComplete(const TDesC8& /*aConnectData*/) + { + LOG_FUNC + ConnectComplete(); // Connection data isn't useful for us. + } + +void CDedicatedBondingSession::ConnectComplete(CServProviderBase& /*aSSP*/) + { + LOG_FUNC + // ProxySAPs aren't used for passive connections. + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + } + +void CDedicatedBondingSession::ConnectComplete(CServProviderBase& /*aSSP*/, const TDesC8& /*aConnectData*/) + { + LOG_FUNC + // ProxySAPs aren't used for passive connections. + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + } + +void CDedicatedBondingSession::CanClose(TDelete aDelete) + { + LOG_FUNC + if (aDelete == EDelete) + { + delete iProxySap; iProxySap = NULL; + } + } + +void CDedicatedBondingSession::CanClose(const TDesC8& /*aDisconnectData*/, TDelete aDelete) + { + LOG_FUNC + CanClose(aDelete); + } + +void CDedicatedBondingSession::Error(TInt aError, TUint /*anOperationMask*/) + { + LOG_FUNC + Complete(aError); + } + +void CDedicatedBondingSession::Disconnect() + { + LOG_FUNC + switch (iState) + { + case EInitialConnection: + // enter the zombie state and wait for the access requester to complete. + iState = EZombie; + break; + case EFinalConnection: + Error(KErrDisconnected); + break; + case EShutdown: + // Already closing down. + break; + default: + LOG1(_L("Unexpected Disconnect in state %d"), iState); + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + break; + } + } + +void CDedicatedBondingSession::Disconnect(TDesC8& /*aDisconnectData*/) + { + LOG_FUNC + Disconnect(); + } + +void CDedicatedBondingSession::IoctlComplete(TDesC8* /*aBuf*/) + { + LOG_FUNC + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + } + +void CDedicatedBondingSession::NoBearer(const TDesC8& /*aConnectionParams*/) + { + LOG_FUNC + // No idea what this is for and proxy sap never calls it... so as far as I'm concerned it's + // unexpected. + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + } + +void CDedicatedBondingSession::Bearer(const TDesC8& /*aConnectionInfo*/) + { + LOG_FUNC + // No idea what this is for and proxy sap never calls it... so as far as I'm concerned it's + // unexpected. + __ASSERT_DEBUG(EFalse, PANIC(KPairingServerFaultCat, EPairingServerUnexpectedSocketCallback)); + } + + +// +// CSimplePairingResultSession +// + +CSimplePairingResultSession* CSimplePairingResultSession::NewLC(CPairingSession& aSession, CSimplePairingResultList& aResultList) + { + LOG_STATIC_FUNC + CSimplePairingResultSession* self = new(ELeave) CSimplePairingResultSession(aSession, aResultList); + //As its a CObject derived class so we should use CleanupClosePushL + CleanupClosePushL(*self); + self->ConstructL(); + return self; + } + +CSimplePairingResultSession::CSimplePairingResultSession(CPairingSession& aSession, CSimplePairingResultList& aResultList) + : CPairingSubSession(aSession) + , iResultList(aResultList) + { + LOG_FUNC + } + +void CSimplePairingResultSession::ConstructL() + { + LOG_FUNC + CPairingSubSession::ConstructL(); + iResultList.RegisterObserverL(*this); + } + +CSimplePairingResultSession::~CSimplePairingResultSession() + { + LOG_FUNC + iResultList.ReleaseObserver(*this); + if(!iResultMsg.IsNull()) + { + iResultMsg.Complete(KErrCancel); + } + } + +void CSimplePairingResultSession::DispatchSubSessMessageL(const RMessage2& aMessage) + { + LOG_FUNC + switch(aMessage.Function()) + { + case EPairingServerSimplePairingResult: + SimplePairingResultL(aMessage); + break; + case EPairingServerCancelSimplePairingResult: + CancelSimplePairingResult(aMessage); + break; + default: + CPairingSubSession::DispatchSubSessMessageL(aMessage); + break; + } + } + +void CSimplePairingResultSession::SimplePairingResultL(const RMessage2& aMessage) + { + LOG_FUNC + + TPckgBuf addrBuf; + if(aMessage.GetDesMaxLengthL(0) != sizeof(TBTDevAddr)) + { + LEAVEL(KErrBadDescriptor); + } + + if(!iResultMsg.IsNull()) + { + LEAVEL(KErrInUse); + } + + iResultMsg = aMessage; + iResultList.ReturnResult(); + } + +void CSimplePairingResultSession::CancelSimplePairingResult(const RMessage2& aMessage) + { + LOG_FUNC + if(!iResultMsg.IsNull()) + { + iResultList.CancelReturn(); + iResultMsg.Complete(KErrCancel); + } + aMessage.Complete(KErrNone); + } + +TInt CSimplePairingResultSession::MbsroResult(const TBTDevAddr& aDevAddr, TInt aResult) + { + LOG_FUNC + __ASSERT_DEBUG(iResultMsg.Handle(), + PANIC(KPairingServerFaultCat, EPairingServerNoMessageForObserverCompletion)); + + TRAPD(err, ReturnResultL(aDevAddr)); + if(err == KErrBadDescriptor) + { + iResultMsg.Panic(KPairingServerPanicCat, EPairingServerBadDescriptor); + } + else if(err != KErrNone) + { + iResultMsg.Complete(err); + } + else + { + iResultMsg.Complete(aResult); + } + return err; + } + +void CSimplePairingResultSession::ReturnResultL(const TBTDevAddr& aDevAddr) + { + LOG_FUNC + TPckg pckg(aDevAddr); + iResultMsg.WriteL(0, pckg); + } + + +// +// CAuthenticationResultSession +// + +CAuthenticationResultSession* CAuthenticationResultSession::NewLC(CPairingSession& aSession, CAuthenticationResultList& aResultList) + { + LOG_STATIC_FUNC + CAuthenticationResultSession* self = new(ELeave) CAuthenticationResultSession(aSession, aResultList); + //As its a CObject derived class so we should use CleanupClosePushL + CleanupClosePushL(*self); + self->ConstructL(); + return self; + } + +CAuthenticationResultSession::CAuthenticationResultSession(CPairingSession& aSession, CAuthenticationResultList& aResultList) + : CPairingSubSession(aSession) + , iResultList(aResultList) + { + LOG_FUNC + } + +void CAuthenticationResultSession::ConstructL() + { + LOG_FUNC + CPairingSubSession::ConstructL(); + iResultList.RegisterObserverL(*this); + } + +CAuthenticationResultSession::~CAuthenticationResultSession() + { + LOG_FUNC + iResultList.ReleaseObserver(*this); + if(!iResultMsg.IsNull()) + { + iResultMsg.Complete(KErrCancel); + } + } + +void CAuthenticationResultSession::DispatchSubSessMessageL(const RMessage2& aMessage) + { + LOG_FUNC + switch(aMessage.Function()) + { + case EPairingServerAuthenticationResult: + AuthenticationResultL(aMessage); + break; + case EPairingServerCancelAuthenticationResult: + CancelAuthenticationResult(aMessage); + break; + default: + CPairingSubSession::DispatchSubSessMessageL(aMessage); + break; + } + } + +void CAuthenticationResultSession::AuthenticationResultL(const RMessage2& aMessage) + { + LOG_FUNC + + TPckgBuf addrBuf; + if(aMessage.GetDesMaxLengthL(0) != sizeof(TBTDevAddr)) + { + LEAVEL(KErrBadDescriptor); + } + + if(!iResultMsg.IsNull()) + { + LEAVEL(KErrInUse); + } + + iResultMsg = aMessage; + iResultList.ReturnResult(); + } + +void CAuthenticationResultSession::CancelAuthenticationResult(const RMessage2& aMessage) + { + LOG_FUNC + if(!iResultMsg.IsNull()) + { + iResultList.CancelReturn(); + iResultMsg.Complete(KErrCancel); + } + aMessage.Complete(KErrNone); + } + +TInt CAuthenticationResultSession::MbsroResult(const TBTDevAddr& aDevAddr, TInt aResult) + { + LOG_FUNC + __ASSERT_DEBUG(iResultMsg.Handle(), + PANIC(KPairingServerFaultCat, EPairingServerNoMessageForObserverCompletion)); + + TRAPD(err, ReturnResultL(aDevAddr)); + if(err == KErrBadDescriptor) + { + iResultMsg.Panic(KPairingServerPanicCat, EPairingServerBadDescriptor); + } + else if(err != KErrNone) + { + iResultMsg.Complete(err); + } + else + { + iResultMsg.Complete(aResult); + } + return err; + } + +void CAuthenticationResultSession::ReturnResultL(const TBTDevAddr& aDevAddr) + { + LOG_FUNC + TPckg pckg(aDevAddr); + iResultMsg.WriteL(0, pckg); + } + +