BLE Generic: Handle peer address type backward compatibility.

pull/6932/head
Vincent Coubard 2018-05-21 13:29:06 +01:00
parent cc286fe84c
commit bdad5d6496
2 changed files with 178 additions and 117 deletions

View File

@ -113,6 +113,16 @@ public:
*/
virtual ble_error_t stopScan();
/**
* @see Gap::connect
*/
virtual ble_error_t connect(
const BLEProtocol::AddressBytes_t peerAddr,
PeerAddressType_t peerAddrType,
const ConnectionParams_t *connectionParams,
const GapScanningParams *scanParams
);
/**
* @see Gap::connect
*/
@ -295,11 +305,13 @@ public:
void processConnectionEvent(
Handle_t handle,
Role_t role,
BLEProtocol::AddressType_t peerAddrType,
peer_address_type_t peerAddrType,
const BLEProtocol::AddressBytes_t peerAddr,
BLEProtocol::AddressType_t ownAddrType,
const BLEProtocol::AddressBytes_t ownAddr,
const ConnectionParams_t *connectionParams
const ConnectionParams_t *connectionParams,
const uint8_t *peerResolvableAddr,
const uint8_t *localResolvableAddr
);
/**

View File

@ -31,6 +31,10 @@
namespace ble {
namespace generic {
using pal::connection_peer_address_type_t;
typedef BLEProtocol::AddressType_t LegacyAddressType_t;
typedef BLEProtocol::AddressType LegacyAddressType;
namespace {
// Constants
@ -353,7 +357,7 @@ static bool is_in_whitelist(
/*
* Convert a BLEProtocol::AddressType_t into a pal::whitelist_address_type_t.
*/
static pal::whitelist_address_type_t to_device_address_type(
static pal::whitelist_address_type_t to_whitelist_address_type(
BLEProtocol::AddressType_t address_type
) {
return (address_type == BLEProtocol::AddressType::PUBLIC) ?
@ -361,6 +365,18 @@ static pal::whitelist_address_type_t to_device_address_type(
pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS;
}
/*
* Convert a BLEProtocol::AddressType_t into a pal::peer_address_type
*/
static peer_address_type_t to_peer_address_type(
LegacyAddressType_t address_type
) {
return (address_type == LegacyAddressType::PUBLIC) ?
peer_address_type_t::PUBLIC :
peer_address_type_t::RANDOM;
}
/*
* Return true if the advertising parameters are valid.
*/
@ -388,7 +404,7 @@ GenericGap::GenericGap(
_pal_gap(pal_gap),
_gap_service(generic_access_service),
_pal_sm(pal_sm),
_address_type(BLEProtocol::AddressType::PUBLIC),
_address_type(LegacyAddressType::PUBLIC),
_initiator_policy_mode(pal::initiator_policy_t::NO_FILTER),
_scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER),
_advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER),
@ -414,16 +430,16 @@ GenericGap::~GenericGap()
}
ble_error_t GenericGap::setAddress(
BLEProtocol::AddressType_t type,
const BLEProtocol::AddressBytes_t address
LegacyAddressType_t type,
const Address_t address
) {
switch (type) {
case BLEProtocol::AddressType::PUBLIC:
case LegacyAddressType::PUBLIC:
// The public address cannot be set, just set the type to public
_address_type = type;
return BLE_ERROR_NONE;
case BLEProtocol::AddressType::RANDOM_STATIC: {
case LegacyAddressType::RANDOM_STATIC: {
if (is_random_static_address(address) == false) {
return BLE_ERROR_INVALID_PARAM;
}
@ -441,8 +457,8 @@ ble_error_t GenericGap::setAddress(
return BLE_ERROR_NONE;
}
case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE:
case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE:
case LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE:
case LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE:
// Note: it is not allowed to set directly these addresses
// privacy management handled it for users.
return BLE_ERROR_INVALID_PARAM;
@ -453,13 +469,13 @@ ble_error_t GenericGap::setAddress(
}
ble_error_t GenericGap::getAddress(
BLEProtocol::AddressType_t *type,
BLEProtocol::AddressBytes_t address
LegacyAddressType_t *type,
Address_t address
) {
*type = _address_type;
ble::address_t address_value;
if (_address_type == BLEProtocol::AddressType::PUBLIC) {
if (_address_type == LegacyAddressType::PUBLIC) {
address_value = _pal_gap.get_device_address();
} else {
address_value = _pal_gap.get_random_address();
@ -514,10 +530,10 @@ ble_error_t GenericGap::stopScan()
}
ble_error_t GenericGap::connect(
const BLEProtocol::AddressBytes_t peerAddr,
BLEProtocol::AddressType_t peerAddrType,
const ConnectionParams_t* connectionParams,
const GapScanningParams* scanParams
const Address_t peerAddr,
PeerAddressType_t peerAddrType,
const ConnectionParams_t *connectionParams,
const GapScanningParams *scanParams
) {
if (connectionParams == NULL) {
connectionParams = &default_connection_params;
@ -535,8 +551,6 @@ ble_error_t GenericGap::connect(
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
// TODO fix upper layer API, address type factorization is incorrect.
// Force scan stop before initiating the scan used for connection
stopScan();
@ -544,7 +558,7 @@ ble_error_t GenericGap::connect(
scanParams->getInterval(),
scanParams->getWindow(),
_initiator_policy_mode,
(pal::connection_peer_address_type_t::type) peerAddrType,
(pal::connection_peer_address_type_t::type) peerAddrType.value(),
ble::address_t(peerAddr),
get_own_address_type(CENTRAL_CONNECTION /* requires resolvable address */),
connectionParams->minConnectionInterval,
@ -556,6 +570,21 @@ ble_error_t GenericGap::connect(
);
}
ble_error_t GenericGap::connect(
const Address_t peerAddr,
LegacyAddressType_t peerAddrType,
const ConnectionParams_t* connectionParams,
const GapScanningParams* scanParams
) {
return connect(
peerAddr,
to_peer_address_type(peerAddrType),
connectionParams,
scanParams
);
}
ble_error_t GenericGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason)
{
if (is_disconnection_reason_valid(reason) == false) {
@ -706,7 +735,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist)
if (is_in_whitelist(device, whitelist) == false) {
ble_error_t err = _pal_gap.remove_device_from_whitelist(
to_device_address_type(device.type),
to_whitelist_address_type(device.type),
device.address
);
@ -717,7 +746,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist)
if (is_in_whitelist(device, whitelist) == false) {
_pal_gap.add_device_to_whitelist(
to_device_address_type(device.type),
to_whitelist_address_type(device.type),
device.address
);
}
@ -733,7 +762,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist)
if (is_in_whitelist(device, _whitelist) == false) {
ble_error_t err = _pal_gap.add_device_to_whitelist(
to_device_address_type(device.type),
to_whitelist_address_type(device.type),
device.address
);
@ -745,7 +774,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist)
if (is_in_whitelist(device, _whitelist) == false) {
_pal_gap.remove_device_from_whitelist(
to_device_address_type(device.type),
to_whitelist_address_type(device.type),
device.address
);
}
@ -757,7 +786,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist)
if (is_in_whitelist(device, whitelist) == false) {
_pal_gap.add_device_to_whitelist(
to_device_address_type(device.type),
to_whitelist_address_type(device.type),
device.address
);
}
@ -961,9 +990,11 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params)
// We can only use non resolvable addresses if the device is non connectable
AddressUseType_t address_use_type =
((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)
|| (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED))
? PERIPHERAL_NON_CONNECTABLE : PERIPHERAL_CONNECTABLE;
((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) ||
(params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) ?
PERIPHERAL_NON_CONNECTABLE :
PERIPHERAL_CONNECTABLE;
pal::own_address_type_t own_address_type = get_own_address_type(address_use_type);
if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS))
@ -1024,11 +1055,13 @@ ble_error_t GenericGap::reset(void)
void GenericGap::processConnectionEvent(
Handle_t handle,
Role_t role,
BLEProtocol::AddressType_t peerAddrType,
PeerAddressType_t peerAddrType,
const BLEProtocol::AddressBytes_t peerAddr,
BLEProtocol::AddressType_t ownAddrType,
const BLEProtocol::AddressBytes_t ownAddr,
const ConnectionParams_t *connectionParams
const ConnectionParams_t *connectionParams,
const uint8_t *peerResolvableAddr,
const uint8_t *localResolvableAddr
) {
if (_connection_event_handler) {
_connection_event_handler->on_connected(
@ -1049,7 +1082,9 @@ void GenericGap::processConnectionEvent(
peerAddr,
ownAddrType,
ownAddr,
connectionParams
connectionParams,
peerResolvableAddr,
localResolvableAddr
);
}
@ -1140,15 +1175,20 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e)
pal::GapAdvertisingReportEvent::advertising_t advertising = e[i];
// Check if the address hasn't been resolved
if(_privacy_enabled && _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER)
{
if(advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS)
{
if(_privacy_enabled &&
_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER &&
advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS &&
is_random_private_resolvable_address(advertising.address.data())
) {
// Filter it out
continue;
}
return;
}
// note 1-to-1 conversion between connection_peer_address_type_t and
// peer_address_type_t
peer_address_type_t peer_address_type =
static_cast<peer_address_type_t::type>(advertising.address_type.value());
processAdvertisementReport(
advertising.address.data(),
advertising.rssi,
@ -1156,96 +1196,105 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e)
(GapAdvertisingParams::AdvertisingType_t) advertising.type.value(),
advertising.data.size(),
advertising.data.data(),
(BLEProtocol::AddressType_t) advertising.address_type.value()
peer_address_type
);
}
}
void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e)
{
// TODO: deprecate ownAddrType and ownAddr, those are not specified
// from the Bluetooth perspective
if (e.status == pal::hci_error_code_t::SUCCESS) {
bool needs_pairing = false;
bool needs_authentication = false;
if(_privacy_enabled && (e.role.value() == e.role.SLAVE)) {
// Apply privacy policy if in peripheral mode for non-resolved addresses
RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE);
ble_error_t ret = getRandomAddressType(e.peer_address.data(), &random_address_type);
if((ret != BLE_ERROR_NONE)
|| (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE))
{
switch(_peripheral_privacy_configuration.resolution_strategy)
{
case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS:
// Reject connection request - the user will get notified through a callback
_pal_gap.disconnect(e.connection_handle, pal::disconnection_reason_t::AUTHENTICATION_FAILLURE);
return;
case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE:
needs_pairing = true;
break;
case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE:
needs_authentication = true;
break;
default:
break;
}
}
}
if (e.role.value() == e.role.SLAVE) {
_advertising_timeout.detach();
_pal_gap.advertising_enable(false);
// Stop address rotation if required
set_random_address_rotation(false);
}
// using these parameters if stupid, there is no range for the
// connection interval when the connection is established
ConnectionParams_t connection_params = {
/* minConnectionInterval */ e.connection_interval,
/* maxConnectionInterval */ e.connection_interval,
e.connection_latency,
e.supervision_timeout
};
ble::address_t address;
if (_address_type == BLEProtocol::AddressType::PUBLIC) {
address = _pal_gap.get_device_address();
} else {
address = _pal_gap.get_random_address();
}
processConnectionEvent(
e.connection_handle,
e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL,
(BLEProtocol::AddressType_t) e.peer_address_type.value(),
e.peer_address.data(),
_address_type,
address.data(),
&connection_params
);
// Now starts pairing or authentication procedures if required
if(needs_pairing) {
SecurityManager &sm = createBLEInstance()->getSecurityManager();
// Request authentication to start pairing procedure
sm.requestAuthentication(e.connection_handle);
}
else if(needs_authentication) {
// TODO: GAP Authentication != Security Manager authentication
// Needs to be implemented
}
} else {
if (e.status != pal::hci_error_code_t::SUCCESS) {
// for now notify user that the connection failled by issuing a timeout
// event
// TODO: Define events in case of connection faillure
processTimeoutEvent(Gap::TIMEOUT_SRC_CONN);
return;
}
bool needs_pairing = false;
bool needs_authentication = false;
if (_privacy_enabled &&
e.role.value() == e.role.SLAVE &&
e.peer_address_type == peer_address_type_t::RANDOM
) {
// Apply privacy policy if in peripheral mode for non-resolved addresses
RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE);
ble_error_t err = getRandomAddressType(e.peer_address.data(), &random_address_type);
if (err) {
// FIXME: return for now; needs to report the error ?
return;
}
if (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE) {
switch(_peripheral_privacy_configuration.resolution_strategy) {
case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS:
// Reject connection request - the user will get notified through a callback
_pal_gap.disconnect(
e.connection_handle,
pal::disconnection_reason_t::AUTHENTICATION_FAILLURE
);
return;
case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE:
needs_pairing = true;
break;
case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE:
needs_authentication = true;
break;
default:
break;
}
}
}
if (e.role.value() == e.role.SLAVE) {
_advertising_timeout.detach();
_pal_gap.advertising_enable(false);
// Stop address rotation if required
set_random_address_rotation(false);
}
// using these parameters if stupid, there is no range for the
// connection interval when the connection is established
ConnectionParams_t connection_params = {
/* minConnectionInterval */ e.connection_interval,
/* maxConnectionInterval */ e.connection_interval,
e.connection_latency,
e.supervision_timeout
};
ble::address_t address;
if (_address_type == LegacyAddressType::PUBLIC) {
address = _pal_gap.get_device_address();
} else {
address = _pal_gap.get_random_address();
}
processConnectionEvent(
e.connection_handle,
e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL,
e.peer_address_type,
e.peer_address.data(),
_address_type,
address.data(),
&connection_params,
e.local_resolvable_private_address.data(),
e.peer_resolvable_private_address.data()
);
// Now starts pairing or authentication procedures if required
if(needs_pairing) {
SecurityManager &sm = createBLEInstance()->getSecurityManager();
// Request authentication to start pairing procedure
sm.requestAuthentication(e.connection_handle);
} else if(needs_authentication) {
// TODO: GAP Authentication != Security Manager authentication
// Needs to be implemented
}
}
@ -1431,7 +1480,7 @@ void GenericGap::update_random_address()
return;
}
_address_type = BLEProtocol::AddressType::RANDOM;
_address_type = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE;
_address = address;
}