--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btnotif/btnotifsrv/src/btnotifconnectiontracker.cpp Fri May 14 16:01:46 2010 +0300
@@ -0,0 +1,721 @@
+/*
+* ============================================================================
+* Name : btnotifconnectiontracker.cpp
+* Part of : bluetoothengine / btnotif
+* Description : Bluetooth connection tracker and manager.
+*
+* Copyright © 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:
+* Nokia Corporation
+* ============================================================================
+* Template version: 4.1
+*/
+
+#include "btnotifconnectiontracker.h"
+#include <btextnotifiers.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <btextnotifierspartner.h>
+#endif
+
+#include "btnotifconnection.h"
+#include "btnotifsession.h"
+#include "btnotifclientserver.h"
+#include "bluetoothtrace.h"
+
+/** Id for the link key watcher active object. */
+const TInt KLinkCountWatcher = 30;
+/** Id for the pairing result watcher active object. */
+const TInt KSspResultWatcher = 31;
+/** Id for the registry watcher active object (TEMP!). */
+const TInt KRegistryWatcher = 41;
+/** Time window for determining if there are too many requests. */
+#ifndef __WINS__
+#define KDENYTHRESHOLD TTimeIntervalSeconds(3)
+#else //__WINS__
+#define KDENYTHRESHOLD TTimeIntervalSeconds(5)
+#endif //__WINS__
+
+
+// ======== LOCAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Checks if the notifier is one launched by the security manager of the
+// protocol stack. These notifiers need to be served unless really not possible.
+// ---------------------------------------------------------------------------
+//
+TBool IsStackSecmanNotifier( TInt aUid )
+ {
+ TBool result = EFalse;
+ if( aUid == KBTManAuthNotifierUid.iUid || aUid == KBTManPinNotifierUid.iUid ||
+ aUid == KBTPinCodeEntryNotifierUid.iUid || aUid == KBTNumericComparisonNotifierUid.iUid ||
+ aUid == KBTPasskeyDisplayNotifierUid.iUid )
+ {
+ result = ETrue;
+ }
+ return result;
+ }
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor
+// ---------------------------------------------------------------------------
+//
+CBTNotifConnectionTracker::CBTNotifConnectionTracker( CBTNotifServer* aServer )
+: iServer( aServer )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd-phase constructor
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::ConstructL()
+ {
+ BOstraceFunctionEntry0( DUMMY_DEVLIST );
+ // Start watching the number of baseband links.
+ TInt err = iLinkCount.Attach( KPropertyUidBluetoothCategory,
+ KPropertyKeyBluetoothGetPHYCount );
+ // There is not much point to continue if we can't attach to
+ // the link count key.
+ User::LeaveIfError( err );
+ iLinkCountActive = CBtSimpleActive::NewL( *this, KLinkCountWatcher );
+ iLinkCount.Subscribe( iLinkCountActive->RequestStatus() );
+ iLinkCountActive->GoActive();
+ // Open a handle to the registry server
+ User::LeaveIfError( iBTRegistrySession.Connect() );
+ // Open a handle to the socket server
+ User::LeaveIfError( iSockServ.Connect() );
+ iPairingServ = new( ELeave ) RBluetoothPairingServer();
+ if( iPairingServ->Connect() )
+ {
+ // Delete in case of error - there is no good other way to keep track.
+ delete iPairingServ;
+ iPairingServ = NULL;
+ }
+ else
+ {
+ iSspResultActive = CBtSimpleActive::NewL( *this, KSspResultWatcher );
+ User::LeaveIfError( iSspResultSession.Open( *iPairingServ ) );
+ iSspResultSession.SimplePairingResult( iSspResultAddr, iSspResultActive->RequestStatus() );
+ iSspResultActive->GoActive();
+ }
+ iConnMan = CBTEngConnMan::NewL( this );
+ iPhyLinks = CBluetoothPhysicalLinks::NewL( *this, iSockServ );
+// ToDo: remove this when registry notifications API is available!!
+ err = iRegistryChange.Attach( KPropertyUidBluetoothCategory, KPropertyKeyBluetoothRegistryTableChange );
+ User::LeaveIfError( err );
+ iRegistryActive = CBtSimpleActive::NewL( *this, KRegistryWatcher );
+ iRegistryChange.Subscribe( iRegistryActive->RequestStatus() );
+ iRegistryActive->GoActive();
+// End ToDo
+ BOstraceFunctionExit0( DUMMY_DEVLIST );
+ }
+
+
+// ---------------------------------------------------------------------------
+// NewL.
+// ---------------------------------------------------------------------------
+//
+CBTNotifConnectionTracker* CBTNotifConnectionTracker::NewL( CBTNotifServer* aServer )
+ {
+ CBTNotifConnectionTracker* self = new( ELeave ) CBTNotifConnectionTracker( aServer );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CBTNotifConnectionTracker::~CBTNotifConnectionTracker()
+ {
+ BOstraceFunctionEntry0( DUMMY_DEVLIST );
+ iConnArray.ResetAndDestroy();
+ iConnArray.Close();
+ iDeniedRequests.Close();
+ delete iLinkCountActive;
+ iLinkCount.Close();
+
+ delete iConnMan;
+ delete iPhyLinks;
+ iSockServ.Close();
+ delete iSspResultActive;
+ iSspResultSession.Close();
+ if( iPairingServ )
+ {
+ iPairingServ->Close();
+ delete iPairingServ;
+ }
+ delete iRegistryActive;
+ iRegistryChange.Close();
+ iBTRegistrySession.Close();
+ BOstraceFunctionExit0( DUMMY_DEVLIST );
+ }
+
+// ---------------------------------------------------------------------------
+// Process a client message related to notifiers.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::DispatchNotifierMessageL( const RMessage2& aMessage )
+ {
+ BOstraceFunctionEntryExt ( DUMMY_LIST, this, aMessage.Function() );
+ TInt opcode = aMessage.Function();
+ TInt uid = aMessage.Int0();
+ const RMessage2* message = &aMessage;
+ // Use a pointer to the original message, so that we don't duplicate it.
+ // Then we avoid any bookkeeping for keeping them in sync.
+ if( opcode == EBTNotifCancelNotifier )
+ {
+ // We only accept a cancel message from the same session as the original
+ // request (this is enforced by the RNotifier backend). So we use the
+ // session of the cancel request (if this would change, the same way as
+ // for updates can be followed).
+ // We need to find the original request to identify the handler of the
+ // connection; the uid points to the original request.
+ message = ( (CBTNotifSession *) aMessage.Session() )->FindMessageFromUid( uid );
+ }
+ else if( opcode == EBTNotifUpdateNotifier )
+ {
+ // We accept a update messages from any client, although in practice,
+ // they will all come from the same session (through RNotifier).
+ // We need to find the original request to identify the handler of the
+ // connection (the uid points to the original request). Through the
+ // server, we get it from any session.
+ message = iServer->FindMessageFromUid( uid );
+ }
+ if( !message )
+ {
+ // It's hard to continue if we don't know where to route the message.
+ User::Leave( KErrDisconnected );
+ }
+ TBuf8<0x250> paramsBuf; // Size needs to be long enough to read all possible parameter sizes.
+ CBTNotifConnection* connection = FindConnectionFromMessageL( opcode, *message, paramsBuf );
+ if( !connection )
+ {
+ User::Leave( KErrDisconnected );
+ }
+ switch( opcode )
+ {
+ case EBTNotifStartSyncNotifier:
+ case EBTNotifStartAsyncNotifier:
+ connection->HandleNotifierRequestL( paramsBuf, aMessage );
+ break;
+ case EBTNotifUpdateNotifier:
+ connection->HandleNotifierUpdateL( paramsBuf, aMessage );
+ break;
+ case EBTNotifCancelNotifier:
+ // Complete the cancel message already here, so that the caller can
+ // continue, and the next operation can close sessions with the caller.
+ aMessage.Complete( KErrNone );
+ connection->CancelNotifierRequestL( *message );
+ break;
+ default:
+ break;
+ }
+ BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle a request related to pairing.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::HandleBondingRequestL( const RMessage2& aMessage )
+ {
+ BOstraceFunctionEntryExt ( DUMMY_LIST, this, aMessage.Function() );
+ // Bonding is an infrequently occurring operation, so we don't waste memory
+ // to keep a copy of the parameters. Instead we read them again when needed.
+ TPckgBuf<TBTDevAddr> addrBuf;
+ TInt opcode = aMessage.Function();
+ if( opcode == EBTEngPairDevice )
+ {
+ aMessage.ReadL( EBTNotifSrvParamSlot, addrBuf );
+ }
+ else if( opcode == EBTEngCancelPairDevice )
+ {
+ const RMessage2* message =
+ ( (CBTNotifSession *) aMessage.Session() )->FindMessageFromUid( EBTEngPairDevice );
+ message->ReadL( EBTNotifSrvParamSlot, addrBuf );
+ }
+ BtTraceBtAddr1( TRACE_DEBUG, DUMMY_LIST, "CBTNotifConnectionTracker::HandleBondingRequestL() addr=", addrBuf() );
+ TInt err = KErrNotFound;
+ CBTNotifConnection* connection = FindConnectionHandler( addrBuf() );
+ if( opcode == EBTEngPairDevice )
+ {
+ if( !connection )
+ {
+ // Create a connection first, then tell it to bond.
+ err = iPhyLinks->CreateConnection( addrBuf() );
+ connection = CBTNotifConnection::NewLC( addrBuf(), this );
+ iConnArray.AppendL( connection );
+ CleanupStack::Pop( connection );
+ }
+ else
+ {
+ // There is an existing connection. Care must be taken, the connection
+ // _should_ be disconnect first if this device is already paired, so that
+ // we are sure that we don't mix up the state of the connection.
+ RBTPhysicalLinkAdapter link;
+ err = link.Open( iSockServ, addrBuf() );
+ TUint32 linkState = 0;
+ if( !err )
+ {
+ err = link.PhysicalLinkState( linkState );
+ }
+ if( !err && linkState & ( ENotifyAuthenticationComplete | ENotifyEncryptionChangeOn ) )
+ {
+ // For now, we just reject the request.
+ err = KErrAlreadyExists;
+ }
+ link.Close();
+ }
+ if( !err )
+ {
+ // Start bonding immediately so that the connection object is in the right state.
+ connection->StartBondingL( aMessage );
+ }
+ }
+ else if( opcode == EBTEngCancelPairDevice && connection )
+ {
+ connection->CancelBondingL();
+ err = KErrNone;
+ aMessage.Complete( err );
+ }
+ // KErrNotFound is returned for a request to cancel pairing that has no connection.
+ if( err )
+ {
+ aMessage.Complete( err );
+ }
+ BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle a change in the number of connections.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::HandleLinkCountChangeL()
+ {
+ BOstraceFunctionEntry0( DUMMY_DEVLIST );
+ TInt linkCount = 0;
+ User::LeaveIfError( iLinkCount.Get( linkCount ) );
+ if( linkCount )
+ {
+ RBTDevAddrArray links;
+ CleanupClosePushL( links );
+ User::LeaveIfError( iPhyLinks->Enumerate( links, 10 ) );
+ __ASSERT_ALWAYS( links.Count(), PanicServer( EBTNotifPanicBadState ) );
+ for( TInt i = iConnArray.Count() -1; i >= 0 ; i-- )
+ {
+ // Loop backwards, as we may remove entries from the array.
+
+ // First check the existing connections, and
+ // remove disconnected links
+ TBTDevAddr addr = iConnArray[i]->Address();
+ TInt pos = links.Find( addr );
+ if( pos > KErrNotFound )
+ {
+ // The link we know is still connected,
+ // remove the watceher from the array.
+ links.Remove( pos );
+ // ToDo: see comment below!
+ }
+ else if( iConnArray[i]->CurrentOperation() == CBTNotifConnection::EIdle )
+ {
+ // This link is no more connected and idle, remove.
+ CBTNotifConnection* connection = iConnArray[i];
+ iConnArray.Remove( i ); // Does not delete the object.
+ delete connection;
+ }
+ // else we wait for the link to complete its operations.
+ }
+ // Now we have an array with only the new connections.
+ // Add new watchers.
+ for( TInt i = 0; i < links.Count(); i++ )
+ {
+ CBTNotifConnection* connection = CBTNotifConnection::NewLC( links[i], this );
+ iConnArray.AppendL( connection );
+ CleanupStack::Pop( connection );
+ }
+ // Close the links RBTDevAddrArray, needed before going out of scope.
+ CleanupStack::PopAndDestroy();
+ }
+ else
+ {
+ for( TInt i = iConnArray.Count() -1; i >= 0 ; i-- )
+ {
+ if( iConnArray[i]->CurrentOperation() == CBTNotifConnection::EIdle )
+ {
+ // This link is now idle, so we can remove it safely.
+ CBTNotifConnection* connection = iConnArray[i];
+ iConnArray.Remove( i ); // Does not delete the object.
+ delete connection;
+ }
+ }
+ if( !iConnArray.Count() )
+ {
+ // The array is idle, clean up the array resources.
+ iConnArray.Reset();
+ }
+ }
+ BOstraceFunctionExit0( DUMMY_DEVLIST );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Check if this device has been denied a connection already before.
+// Also check if a previous connection attempt has just been rejected.
+// ---------------------------------------------------------------------------
+//
+TBool CBTNotifConnectionTracker::UpdateBlockingHistoryL( const CBTDevice* aDevice,
+ TBool aAccepted )
+ {
+ BOstraceFunctionEntry0( DUMMY_DEVLIST );
+ __ASSERT_ALWAYS( aDevice, PanicServer( EBTNotifPanicBadArgument ) );
+ // Check the time since the previous event.
+ TBool result = RecordConnectionAttempts( aAccepted );
+ TInt pos = iDeniedRequests.Find( aDevice->BDAddr() );
+ if( !aAccepted )
+ {
+ if( pos == KErrNotFound )
+ {
+ // The user denied the request from a new device, record the device address.
+ if( aDevice->IsValidPaired() && aDevice->IsPaired() )
+ //[MCL]: && iDevice->LinkKeyType() != ELinkKeyUnauthenticatedUpgradable )
+ {
+ // Paired devices are allowed one time rejection without a prompt for blocking.
+ result = EFalse;
+ }
+ iDeniedRequests.AppendL( aDevice->BDAddr() );
+ }
+ // Nothing needed here if the address is already in the array.
+ }
+ else if( pos > KErrNotFound )
+ {
+ // The user accepted a request, and it was from a device he/she
+ // previously rejected. Clear the history for this device from the array.
+ iDeniedRequests.Remove( pos );
+ }
+ BOstraceFunctionExit0( DUMMY_DEVLIST );
+ return result;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class MBluetoothPhysicalLinksNotifier.
+// Handle baseband connection completion.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::HandleCreateConnectionCompleteL( TInt aErr )
+ {
+ BOstraceFunctionEntryExt ( DUMMY_LIST, this, aErr );
+ // We only connect links for starting outgoing bonding.
+ const RMessage2* message = iServer->FindMessageFromUid( (TInt) EBTEngPairDevice );
+ if( message )
+ {
+ TPckgBuf<TBTDevAddr> addrBuf;
+ message->ReadL( EBTNotifSrvParamSlot, addrBuf );
+ CBTNotifConnection* connection = FindConnectionHandler( addrBuf() );
+ __ASSERT_ALWAYS( connection, PanicServer( EBTNotifPanicBadState ) );
+ if( !aErr && connection->CurrentOperation() == CBTNotifConnection::EIdle )
+ {
+ TRAP( aErr, connection->StartBondingL( *message ) );
+ }
+ if( aErr && connection->CurrentOperation() == CBTNotifConnection::EBonding )
+ {
+ connection->PairingResult( aErr ); // Launch error note
+ }
+ }
+ BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class MBluetoothPhysicalLinksNotifier.
+// Handle baseband disconnection.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::HandleDisconnectCompleteL( TInt aErr )
+ {
+ BOstraceFunctionEntry0( DUMMY_DEVLIST );
+ // We only disconnect links for starting outgoing bonding.
+ const RMessage2* message = iServer->FindMessageFromUid( (TInt) EBTEngPairDevice );
+ if( message )
+ {
+ TPckgBuf<TBTDevAddr> addrBuf;
+ message->ReadL( EBTNotifSrvParamSlot, addrBuf );
+ if( !aErr )
+ {
+ aErr = iPhyLinks->CreateConnection( addrBuf() );
+ }
+ if( aErr )
+ {
+ iServer->CompleteMessage( message->Handle(), aErr, KNullDesC8 );
+ CBTNotifConnection* connection = FindConnectionHandler( addrBuf() );
+ __ASSERT_ALWAYS( connection, PanicServer( EBTNotifPanicBadState ) );
+ connection->PairingResult( aErr ); // Launch error note
+ }
+ }
+ BOstraceFunctionExit0( DUMMY_DEVLIST );
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class MBluetoothPhysicalLinksNotifier.
+// Handle disconnection of all links.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::HandleDisconnectAllCompleteL( TInt aErr )
+ {
+ (void) aErr;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTEngConnObserver.
+// Handle service-level connection completion.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::ConnectComplete( TBTDevAddr& aAddr,
+ TInt aErr, RBTDevAddrArray* aConflicts )
+ {
+ (void) aAddr;
+ (void) aErr;
+ (void) aConflicts;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTEngConnObserver.
+// Handle service-level disconnection.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::DisconnectComplete( TBTDevAddr& aAddr, TInt aErr )
+ {
+ (void) aAddr;
+ (void) aErr;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class MBtSimpleActiveObserver.
+// Handle the active object completion.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::RequestCompletedL( CBtSimpleActive* aActive,
+ TInt aStatus )
+ {
+ BOstraceFunctionEntryExt ( DUMMY_LIST, this, aActive->RequestId() );
+ BOstraceExt2( TRACE_DEBUG, DUMMY_DEVLIST,
+ "CBTNotifConnectionTracker::MBAORequestCompletedL() requestid=%d status=%d",
+ aActive->RequestId(), aStatus);
+ if( aActive->RequestId() == KLinkCountWatcher )
+ {
+ iLinkCount.Subscribe( aActive->RequestStatus() );
+ aActive->GoActive();
+ if( !aStatus )
+ {
+ // HandleLinkCountChangeL();
+ }
+ }
+// ToDo: remove this when registry notifications API is available!!
+ else if( aActive->RequestId() == KRegistryWatcher )
+ {
+ // BTRegistry notifies of a change. Check which one.
+ iRegistryChange.Subscribe( aActive->RequestStatus() );
+ aActive->GoActive();
+ TInt tableChanged = 0;
+ if( !aStatus && !iRegistryChange.Get( tableChanged ) &&
+ tableChanged == KRegistryChangeRemoteTable )
+ {
+ // A record for a remote device has changed. Tell all
+ // connections to update their record.
+ for( TInt i = 0; i < iConnArray.Count(); i++ )
+ {
+ // Reuse the functionality in the connection
+ if( iConnArray[i]->CurrentOperation() < CBTNotifConnection::EReadingRegistry )
+ {
+ iConnArray[i]->RequestCompletedL( aActive, aStatus );
+ }
+ }
+ }
+ }
+// End ToDo
+ else if( aActive->RequestId() == KSspResultWatcher )
+ {
+ iSspResultSession.SimplePairingResult( iSspResultAddr, iSspResultActive->RequestStatus() );
+ iSspResultActive->GoActive();
+ CBTNotifConnection* connection = FindConnectionHandler( iSspResultAddr );
+ // ToDo: how to handle a result of a link that already disconnected?
+ if( connection )
+ {
+ connection->PairingResult( aStatus );
+ }
+ }
+ BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class MBtSimpleActiveObserver.
+// Cancel and clean up all requests related to the active object.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::CancelRequest( TInt aRequestId )
+ {
+ BOstraceFunctionEntry0( DUMMY_DEVLIST );
+ if( aRequestId == KLinkCountWatcher )
+ {
+ iLinkCount.Cancel();
+ }
+ else if( aRequestId == KSspResultWatcher )
+ {
+ iSspResultSession.CancelSimplePairingResult();
+ }
+ else if ( aRequestId == KRegistryWatcher )
+ {
+ iRegistryChange.Cancel();
+ }
+ BOstraceFunctionExit0( DUMMY_DEVLIST );
+ }
+
+// ---------------------------------------------------------------------------
+// From class MBtSimpleActiveObserver.
+//
+// ---------------------------------------------------------------------------
+//
+void CBTNotifConnectionTracker::HandleError( CBtSimpleActive* aActive,
+ TInt aError )
+ {
+ (void) aActive;
+ (void) aError;
+ }
+
+// ---------------------------------------------------------------------------
+// Parse the details from a client message and find the associated handler.
+// ---------------------------------------------------------------------------
+//
+CBTNotifConnection* CBTNotifConnectionTracker::FindConnectionFromMessageL(
+ TInt aOpcode, const RMessage2& aMessage, TDes8& aBuffer )
+ {
+ BOstraceFunctionEntry1( DUMMY_DEVLIST, this );
+ TInt uid = aMessage.Int0();
+ aMessage.ReadL( EBTNotifSrvParamSlot, aBuffer );
+ TBTDevAddr addr = ParseAddressL( uid, aBuffer );
+ // If this is a
+ CBTNotifConnection* connection = FindConnectionHandler( addr );
+ if( !connection && IsStackSecmanNotifier( uid ) &&
+ ( aOpcode == EBTNotifStartAsyncNotifier || aOpcode == EBTNotifStartSyncNotifier ) )
+ {
+ // A notifier from stack. This happens if e.g. the pairing
+ // request comes in before the link count changes (like security
+ // mode 3). Create the handler and queue the request.
+ // And note that
+ connection = CBTNotifConnection::NewLC( addr, this );
+ iConnArray.AppendL( connection );
+ CleanupStack::Pop( connection );
+ }
+ BOstraceFunctionExitExt( DUMMY_DEVLIST, this, connection );
+ return connection;
+ }
+
+
+// ---------------------------------------------------------------------------
+// read the address from a client message.
+// ---------------------------------------------------------------------------
+//
+TBTDevAddr CBTNotifConnectionTracker::ParseAddressL( TInt aUid,
+ const TDesC8& aParamsBuf ) const
+ {
+ BOstraceFunctionEntry1( DUMMY_DEVLIST, this );
+ TBTDevAddr addr;
+ if( IsStackSecmanNotifier( aUid ) )
+ {
+ // For all these, the address is the first data member,
+ // so can be read using the TBTNotifierParams data structure.
+ TBTNotifierParams params;
+ TPckgC<TBTNotifierParams> paramsPckg( params );
+ paramsPckg.Set( aParamsBuf );
+ addr = paramsPckg().iBDAddr;
+ }
+ //else if( ) other notifier types
+ BOstraceFunctionExitExt( DUMMY_DEVLIST, this, &addr );
+ return addr;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Find a specific connection.
+// ---------------------------------------------------------------------------
+//
+CBTNotifConnection* CBTNotifConnectionTracker::FindConnectionHandler(
+ const TBTDevAddr& aAddr ) const
+ {
+ BOstraceFunctionEntry1( DUMMY_DEVLIST, this );
+ CBTNotifConnection* conn = NULL;
+ if( aAddr != TBTDevAddr() )
+ {
+ // This may be replaced by RArray::Find with appropriate key
+ for( TInt i = 0; i < iConnArray.Count(); i++ )
+ {
+ if( iConnArray[i]->Address() == aAddr )
+ {
+ conn = iConnArray[i];
+ break;
+ }
+ }
+ }
+ BOstraceFunctionExitExt( DUMMY_DEVLIST, this, conn );
+ return conn;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Record and check the time between connection attempts.
+// ---------------------------------------------------------------------------
+//
+TBool CBTNotifConnectionTracker::RecordConnectionAttempts( TBool aAccepted )
+ {
+ BOstraceFunctionEntry1( DUMMY_DEVLIST, this );
+ TBool result = ETrue;
+ TTime now( 0 );
+ if( !aAccepted )
+ {
+ now.UniversalTime();
+ if( iLastReject )
+ {
+ // Check the time between denied connections, that it does not go too fast.
+ TTimeIntervalSeconds prev( 0 );
+ if( !now.SecondsFrom( TTime( iLastReject ), prev ) )
+ {
+ if( prev <= KDENYTHRESHOLD )
+ {
+ // We are getting the requests too fast. Present the user with
+ // an option to turn BT off.
+ //iServer->SettingsTracker()->SetPower( EFalse );
+ result = EFalse;
+ }
+ }
+ }
+ }
+ // Record the current timestamp.
+ // It is reset in case the user accepted the request.
+ iLastReject = now.Int64();
+ BOstraceFunctionExitExt( DUMMY_DEVLIST, this, result );
+ return result;
+ }