connection monitor

pull/6188/head
paul-szczepanek-arm 2018-02-19 15:32:07 +00:00
parent 2f1e211da1
commit d9156a28e2
7 changed files with 198 additions and 54 deletions

View File

@ -0,0 +1,62 @@
/* mbed Microcontroller Library
* Copyright (c) 2017-2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_BLE_CONNECTION_EVENT_MONITOR
#define MBED_BLE_CONNECTION_EVENT_MONITOR
#include <algorithm>
#include "ble/BLE.h"
#include "ble/BLEProtocol.h"
#include "ble/Gap.h"
#include "ble/pal/PalGap.h"
#include "ble/pal/GapEvents.h"
#include "ble/pal/GapTypes.h"
#include "ble/BLETypes.h"
#include "ble/pal/GenericAccessService.h"
#include "ble/pal/EventQueue.h"
namespace ble {
class ConnectionEventHandler {
virtual void on_connected(
connection_handle_t connection,
Gap::Role_t role,
BLEProtocol::AddressType_t peer_address_type,
const BLEProtocol::AddressBytes_t peer_address,
BLEProtocol::AddressType_t local_address_type,
const BLEProtocol::AddressBytes_t local_address,
const Gap::ConnectionParams_t *connection_params
) = 0;
void on_disconnected(
connection_handle_t connection,
Gap::DisconnectionReason_t reason
) = 0;
};
class ConnectionEventMonitor {
/**
* Register a handler for connection events to be used internally and serviced first.
*
* @param[in] connection_event_handler Event handler being registered.
*/
void set_connection_event_handler(ConnectionEventHandler *connection_event_handler) = 0;
}
}
#endif /* MBED_BLE_CONNECTION_EVENT_MONITOR */

View File

@ -2281,7 +2281,7 @@ public:
* @param[in] ownAddr Address this device uses for this connection. * @param[in] ownAddr Address this device uses for this connection.
* @param[in] connectionParams Parameters of the connection. * @param[in] connectionParams Parameters of the connection.
*/ */
void processConnectionEvent( virtual void processConnectionEvent(
Handle_t handle, Handle_t handle,
Role_t role, Role_t role,
BLEProtocol::AddressType_t peerAddrType, BLEProtocol::AddressType_t peerAddrType,
@ -2304,6 +2304,7 @@ public:
ownAddr, ownAddr,
connectionParams connectionParams
); );
connectionCallChain.call(&callbackParams); connectionCallChain.call(&callbackParams);
} }
@ -2316,7 +2317,7 @@ public:
* @param[in] handle Handle of the terminated connection. * @param[in] handle Handle of the terminated connection.
* @param[in] reason Reason of the disconnection. * @param[in] reason Reason of the disconnection.
*/ */
void processDisconnectionEvent(Handle_t handle, DisconnectionReason_t reason) virtual void processDisconnectionEvent(Handle_t handle, DisconnectionReason_t reason)
{ {
/* Update Gap state */ /* Update Gap state */
--connectionCount; --connectionCount;
@ -2447,6 +2448,13 @@ protected:
*/ */
DisconnectionEventCallbackChain_t disconnectionCallChain; DisconnectionEventCallbackChain_t disconnectionCallChain;
/**
* Register a callback handling connection events to be used internally and serviced first.
*
* @param[in] callback Event handler being registered.
*/
virtual void onConnectionPrivate(ConnectionEventCallback_t callback) { }
private: private:
/** /**
* Callchain containing all registered callback handlers for shutdown * Callchain containing all registered callback handlers for shutdown

View File

@ -28,12 +28,12 @@
#include "ble/BLETypes.h" #include "ble/BLETypes.h"
#include "ble/pal/GenericAccessService.h" #include "ble/pal/GenericAccessService.h"
#include "ble/pal/EventQueue.h" #include "ble/pal/EventQueue.h"
#include "ble/ConnectionEventMonitor.h"
#include "drivers/Timeout.h" #include "drivers/Timeout.h"
namespace ble { namespace ble {
namespace generic { namespace generic {
/** /**
* Generic implementation of the Gap class. * Generic implementation of the Gap class.
* It requires a pal::Gap and a pal::GenericAccessService injected at * It requires a pal::Gap and a pal::GenericAccessService injected at
@ -41,7 +41,8 @@ namespace generic {
* *
* @attention: Not part of the public interface of BLE API. * @attention: Not part of the public interface of BLE API.
*/ */
class GenericGap : public ::Gap { class GenericGap : public ::Gap,
public ConnectionEventMonitor {
public: public:
/** /**
@ -250,6 +251,27 @@ public:
*/ */
virtual ble_error_t reset(void); virtual ble_error_t reset(void);
/**
* @copydoc ::Gap::processConnectionEvent
*/
virtual void processConnectionEvent(
Handle_t handle,
Role_t role,
BLEProtocol::AddressType_t peerAddrType,
const BLEProtocol::AddressBytes_t peerAddr,
BLEProtocol::AddressType_t ownAddrType,
const BLEProtocol::AddressBytes_t ownAddr,
const ConnectionParams_t *connectionParams
);
/**
* @copydoc ::Gap::processDisconnectionEvent
*/
virtual void processDisconnectionEvent(
Handle_t handle,
DisconnectionReason_t reason
);
private: private:
void on_scan_timeout(); void on_scan_timeout();
@ -279,6 +301,9 @@ private:
bool initialize_whitelist() const; bool initialize_whitelist() const;
/** implements ConnectionEventMonitor */
void set_connection_event_handler(ConnectionEventHandler *_connection_event_handler);
pal::EventQueue& _event_queue; pal::EventQueue& _event_queue;
pal::Gap &_pal_gap; pal::Gap &_pal_gap;
pal::GenericAccessService &_gap_service; pal::GenericAccessService &_gap_service;
@ -290,6 +315,7 @@ private:
mutable Whitelist_t _whitelist; mutable Whitelist_t _whitelist;
mbed::Timeout _advertising_timeout; mbed::Timeout _advertising_timeout;
mbed::Timeout _scan_timeout; mbed::Timeout _scan_timeout;
ConnectionEventHandler *_connection_event_handler;
}; };
} }

View File

@ -22,6 +22,7 @@
#include "ble/generic/GenericSecurityDb.h" #include "ble/generic/GenericSecurityDb.h"
#include "Callback.h" #include "Callback.h"
#include "ble/Gap.h" #include "ble/Gap.h"
#include "ble/generic/GenericGap.h"
#include "ble/pal/PalSecurityManager.h" #include "ble/pal/PalSecurityManager.h"
namespace ble { namespace ble {
@ -37,7 +38,8 @@ typedef SecurityManager::SecurityIOCapabilities_t SecurityIOCapabilities_t;
class GenericSecurityManagerEventHandler; class GenericSecurityManagerEventHandler;
class GenericSecurityManager : public SecurityManager, class GenericSecurityManager : public SecurityManager,
public pal::SecurityManagerEventHandler { public pal::SecurityManagerEventHandler,
public ConnectionEventHandler {
public: public:
/* implements SecurityManager */ /* implements SecurityManager */
@ -232,7 +234,7 @@ public:
GenericSecurityManager( GenericSecurityManager(
ble::pal::SecurityManager &palImpl, ble::pal::SecurityManager &palImpl,
GenericSecurityDb &dbImpl, GenericSecurityDb &dbImpl,
Gap &gapImpl GenericGap &gapImpl
) : _pal(palImpl), ) : _pal(palImpl),
_db(dbImpl), _db(dbImpl),
_gap(gapImpl), _gap(gapImpl),
@ -374,17 +376,6 @@ private:
bool enable = true bool enable = true
); );
/**
* Inform the security manager that a device has been disconnected and its
* entry can be put in NVM storage. Called by GAP.
*
* @param[in] connectionHandle Handle to identify the connection.
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
void on_disconnected(
connection_handle_t connection
);
/** /**
* Inform the Security manager of a new connection. This will create * Inform the Security manager of a new connection. This will create
* or retrieve an existing security manager entry for the connected device. * or retrieve an existing security manager entry for the connected device.
@ -398,10 +389,24 @@ private:
*/ */
void on_connected( void on_connected(
connection_handle_t connection, connection_handle_t connection,
bool is_master, Gap::Role_t role,
BLEProtocol::AddressType_t peer_address_type, BLEProtocol::AddressType_t peer_address_type,
const address_t &peer_address, const BLEProtocol::AddressBytes_t peer_address,
const address_t &local_address BLEProtocol::AddressType_t local_address_type,
const BLEProtocol::AddressBytes_t local_address,
const Gap::ConnectionParams_t *connection_params
);
/**
* Inform the security manager that a device has been disconnected and its
* entry can be put in NVM storage. Called by GAP.
*
* @param[in] connectionHandle Handle to identify the connection.
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
void on_disconnected(
connection_handle_t connection,
Gap::DisconnectionReason_t reason
); );
/** /**
@ -425,7 +430,7 @@ private:
private: private:
ble::pal::SecurityManager &_pal; ble::pal::SecurityManager &_pal;
GenericSecurityDb &_db; GenericSecurityDb &_db;
Gap &_gap; GenericGap &_gap;
AuthenticationMask _default_authentication; AuthenticationMask _default_authentication;
KeyDistribution _default_key_distribution; KeyDistribution _default_key_distribution;

View File

@ -382,7 +382,8 @@ GenericGap::GenericGap(
_advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER),
_whitelist(), _whitelist(),
_advertising_timeout(), _advertising_timeout(),
_scan_timeout() _scan_timeout(),
_connection_event_handler(NULL)
{ {
_pal_gap.when_gap_event_received( _pal_gap.when_gap_event_received(
mbed::callback(this, &GenericGap::on_gap_event_received) mbed::callback(this, &GenericGap::on_gap_event_received)
@ -896,6 +897,55 @@ ble_error_t GenericGap::reset(void)
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
void GenericGap::processConnectionEvent(
Handle_t handle,
Role_t role,
BLEProtocol::AddressType_t peerAddrType,
const BLEProtocol::AddressBytes_t peerAddr,
BLEProtocol::AddressType_t ownAddrType,
const BLEProtocol::AddressBytes_t ownAddr,
const ConnectionParams_t *connectionParams
) {
if (_connection_event_handler) {
_connection_event_handler->on_connected(
handle,
role,
peerAddrType,
peerAddr,
ownAddrType,
ownAddr,
connectionParams
);
}
::Gap::processConnectionEvent(
handle,
role,
peerAddrType,
peerAddr,
ownAddrType,
ownAddr,
connectionParams
);
}
void GenericGap::processDisconnectionEvent(
Handle_t handle,
DisconnectionReason_t reason
) {
if (_connection_event_handler) {
_connection_event_handler->on_disconnected(
handle,
reason
);
}
::Gap::processDisconnectionEvent(
handle,
reason
);
}
void GenericGap::on_scan_timeout() void GenericGap::on_scan_timeout()
{ {
_event_queue.post(mbed::callback(this, &GenericGap::process_scan_timeout)); _event_queue.post(mbed::callback(this, &GenericGap::process_scan_timeout));
@ -1087,5 +1137,10 @@ bool GenericGap::initialize_whitelist() const
return true; return true;
} }
void GenericGap::set_connection_event_handler(ConnectionEventHandler *connection_event_handler)
{
_connection_event_handler = connection_event_handler;
}
} // namespace generic } // namespace generic
} // namespace ble } // namespace ble

View File

@ -55,8 +55,7 @@ ble_error_t GenericSecurityManager::init(
init_signing(); init_signing();
} }
_gap.onConnection(this, &GenericSecurityManager::connection_callback); _gap.set_connection_event_handler(this);
_gap.onDisconnection(this, &GenericSecurityManager::disconnection_callback);
_pal.generate_public_key(); _pal.generate_public_key();
@ -727,27 +726,20 @@ void GenericSecurityManager::set_mitm_performed(connection_handle_t connection,
} }
} }
void GenericSecurityManager::on_disconnected(connection_handle_t connection) {
SecurityEntry_t *entry = _db.get_entry(connection);
if (!entry) {
return;
}
entry->connected = false;
_db.sync();
}
void GenericSecurityManager::on_connected( void GenericSecurityManager::on_connected(
connection_handle_t connection, connection_handle_t connection,
bool is_master, Gap::Role_t role,
BLEProtocol::AddressType_t peer_address_type, BLEProtocol::AddressType_t peer_address_type,
const address_t &peer_address, const BLEProtocol::AddressBytes_t peer_address,
const address_t &local_address BLEProtocol::AddressType_t local_address_type,
const BLEProtocol::AddressBytes_t local_address,
const Gap::ConnectionParams_t *connection_params
) { ) {
SecurityEntry_t *entry = _db.connect_entry( SecurityEntry_t *entry = _db.connect_entry(
connection, connection,
peer_address_type, peer_address_type,
peer_address, address_t(peer_address),
local_address address_t(local_address)
); );
if (!entry) { if (!entry) {
@ -756,26 +748,21 @@ void GenericSecurityManager::on_connected(
entry->reset(); entry->reset();
entry->is_master = is_master; entry->is_master = (role == Gap::CENTRAL);
entry->handle = connection; entry->handle = connection;
entry->connected = true; entry->connected = true;
} }
void GenericSecurityManager::connection_callback( void GenericSecurityManager::on_disconnected(
const Gap::ConnectionCallbackParams_t* params connection_handle_t connection,
Gap::DisconnectionReason_t reason
) { ) {
on_connected( SecurityEntry_t *entry = _db.get_entry(connection);
params->handle, if (!entry) {
(params->role == Gap::CENTRAL), return;
params->peerAddrType, }
address_t(params->peerAddr), entry->connected = false;
address_t(params->ownAddr) _db.sync();
);
}
void GenericSecurityManager::disconnection_callback(
const Gap::DisconnectionCallbackParams_t* params
) {
on_disconnected(params->handle);
} }
/* Implements ble::pal::SecurityManagerEventHandler */ /* Implements ble::pal::SecurityManagerEventHandler */

View File

@ -21,6 +21,7 @@
#include "ble/generic/GenericSecurityManager.h" #include "ble/generic/GenericSecurityManager.h"
#include "ble/generic/GenericSecurityDb.h" #include "ble/generic/GenericSecurityDb.h"
#include "ble/generic/GenericGap.h"
#include "ble/pal/PalSecurityManager.h" #include "ble/pal/PalSecurityManager.h"
#include "CordioPalSecurityManager.h" #include "CordioPalSecurityManager.h"
#include "CordioGap.h" #include "CordioGap.h"
@ -45,7 +46,7 @@ public:
SecurityManager( SecurityManager(
pal::SecurityManager &palImpl, pal::SecurityManager &palImpl,
generic::GenericSecurityDb &dbImpl, generic::GenericSecurityDb &dbImpl,
Gap &gapImpl generic::GenericGap &gapImpl
) : generic::GenericSecurityManager(palImpl, dbImpl, gapImpl) { ) : generic::GenericSecurityManager(palImpl, dbImpl, gapImpl) {
/* empty */ /* empty */
} }