diff --git a/src/NimBLEAddress.cpp b/src/NimBLEAddress.cpp index af7956b3..6a91de1c 100644 --- a/src/NimBLEAddress.cpp +++ b/src/NimBLEAddress.cpp @@ -14,148 +14,151 @@ #include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) -#include +# include "NimBLEAddress.h" +# include "NimBLELog.h" -#include "NimBLEAddress.h" -#include "NimBLEUtils.h" -#include "NimBLELog.h" +# include static const char* LOG_TAG = "NimBLEAddress"; /************************************************* * NOTE: NimBLE address bytes are in INVERSE ORDER! - * We will accomodate that fact in these methods. -*************************************************/ + * We will accommodate that fact in these methods. + *************************************************/ /** * @brief Create an address from the native NimBLE representation. * @param [in] address The native NimBLE address. */ -NimBLEAddress::NimBLEAddress(ble_addr_t address) { - memcpy(m_address, address.val, 6); - m_addrType = address.type; -} // NimBLEAddress - +NimBLEAddress::NimBLEAddress(ble_addr_t address) : ble_addr_t{address} {} /** - * @brief Create a blank address, i.e. 00:00:00:00:00:00, type 0. - */ -NimBLEAddress::NimBLEAddress() { - NimBLEAddress(""); -} // NimBLEAddress - - -/** - * @brief Create an address from a hex string + * @brief Create an address from a hex string. * * A hex string is of the format: * ``` * 00:00:00:00:00:00 * ``` * which is 17 characters in length. - * - * @param [in] stringAddress The hex string representation of the address. + * @param [in] addr The hex string representation of the address. * @param [in] type The type of the address. */ -NimBLEAddress::NimBLEAddress(const std::string &stringAddress, uint8_t type) { - m_addrType = type; - - if (stringAddress.length() == 0) { - memset(m_address, 0, 6); - return; - } +NimBLEAddress::NimBLEAddress(const std::string& addr, uint8_t type) { + this->type = type; - if (stringAddress.length() == 6) { - std::reverse_copy(stringAddress.data(), stringAddress.data() + 6, m_address); + if (addr.length() == BLE_DEV_ADDR_LEN) { + std::reverse_copy(addr.data(), addr.data() + BLE_DEV_ADDR_LEN, this->val); return; } - if (stringAddress.length() != 17) { - memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address - NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str()); + if (addr.length() == 17) { + std::string mac{addr}; + mac.erase(std::remove(mac.begin(), mac.end(), ':'), mac.end()); + uint64_t address = std::stoul(mac, nullptr, 16); + memcpy(this->val, &address, sizeof this->val); return; } - int data[6]; - if(sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[5], &data[4], &data[3], &data[2], &data[1], &data[0]) != 6) { - memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address - NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str()); - } - for(size_t index = 0; index < sizeof m_address; index++) { - m_address[index] = data[index]; - } + *this = NimBLEAddress{}; + NIMBLE_LOGE(LOG_TAG, "Invalid address '%s'", addr.c_str()); } // NimBLEAddress - /** * @brief Constructor for compatibility with bluedroid esp library using native ESP representation. * @param [in] address A uint8_t[6] or esp_bd_addr_t containing the address. * @param [in] type The type of the address. */ -NimBLEAddress::NimBLEAddress(uint8_t address[6], uint8_t type) { - std::reverse_copy(address, address + sizeof m_address, m_address); - m_addrType = type; +NimBLEAddress::NimBLEAddress(const uint8_t address[BLE_DEV_ADDR_LEN], uint8_t type) { + std::reverse_copy(address, address + BLE_DEV_ADDR_LEN, this->val); + this->type = type; } // NimBLEAddress - /** * @brief Constructor for address using a hex value.\n * Use the same byte order, so use 0xa4c1385def16 for "a4:c1:38:5d:ef:16" * @param [in] address uint64_t containing the address. * @param [in] type The type of the address. */ -NimBLEAddress::NimBLEAddress(const uint64_t &address, uint8_t type) { - memcpy(m_address, &address, sizeof m_address); - m_addrType = type; +NimBLEAddress::NimBLEAddress(const uint64_t& address, uint8_t type) { + memcpy(this->val, &address, sizeof this->val); + this->type = type; } // NimBLEAddress - /** * @brief Determine if this address equals another. * @param [in] otherAddress The other address to compare against. * @return True if the addresses are equal. */ -bool NimBLEAddress::equals(const NimBLEAddress &otherAddress) const { +bool NimBLEAddress::equals(const NimBLEAddress& otherAddress) const { return *this == otherAddress; } // equals - /** - * @brief Get the native representation of the address. - * @return a pointer to the uint8_t[6] array of the address. + * @brief Get the NimBLE base struct of the address. + * @return A read only reference to the NimBLE base struct of the address. */ -const uint8_t *NimBLEAddress::getNative() const { - return m_address; -} // getNative - +const ble_addr_t* NimBLEAddress::getBase() const { + return reinterpret_cast(this); +} // getBase /** * @brief Get the address type. * @return The address type. */ uint8_t NimBLEAddress::getType() const { - return m_addrType; + return this->type; } // getType +/** + * @brief Get the address value. + * @return A read only reference to the address value. + */ +const uint8_t* NimBLEAddress::getVal() const { + return this->val; +} // getVal /** * @brief Determine if this address is a Resolvable Private Address. * @return True if the address is a RPA. */ bool NimBLEAddress::isRpa() const { - return (m_addrType && ((m_address[5] & 0xc0) == 0x40)); + return BLE_ADDR_IS_RPA(this); } // isRpa +/** + * @brief Determine if this address is a Non-Resolvable Private Address. + * @return True if the address is a NRPA. + */ +bool NimBLEAddress::isNrpa() const { + return BLE_ADDR_IS_NRPA(this); +} // isNrpa + +/** + * @brief Determine if this address is a Static Address. + * @return True if the address is a Static Address. + */ +bool NimBLEAddress::isStatic() const { + return BLE_ADDR_IS_STATIC(this); +} // isStatic + +/** + * @brief Determine if this address is a Public Address. + * @return True if the address is a Public Address. + */ +bool NimBLEAddress::isPublic() const { + return this->type == BLE_ADDR_PUBLIC; +} // isPublic + +/** + * @brief Determine if this address is a NULL Address. + * @return True if the address is a NULL Address. + */ +bool NimBLEAddress::isNull() const { + return *this == NimBLEAddress{}; +} // isNull /** * @brief Convert a BLE address to a string. - * - * A string representation of an address is in the format: - * - * ``` - * xx:xx:xx:xx:xx:xx - * ``` - * * @return The string representation of the address. * @deprecated Use std::string() operator instead. */ @@ -163,43 +166,57 @@ std::string NimBLEAddress::toString() const { return std::string(*this); } // toString +/** + * @brief Reverse the byte order of the address. + * @return A reference to this address. + */ +const NimBLEAddress& NimBLEAddress::reverseByteOrder() { + std::reverse(this->val, this->val + BLE_DEV_ADDR_LEN); + return *this; +} // reverseByteOrder /** * @brief Convenience operator to check if this address is equal to another. */ -bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const { - return memcmp(rhs.m_address, m_address, sizeof m_address) == 0; -} // operator == +bool NimBLEAddress::operator==(const NimBLEAddress& rhs) const { + if (this->type != rhs.type) { + return false; + } + return memcmp(rhs.val, this->val, sizeof this->val) == 0; +} // operator == /** * @brief Convenience operator to check if this address is not equal to another. */ -bool NimBLEAddress::operator !=(const NimBLEAddress & rhs) const { +bool NimBLEAddress::operator!=(const NimBLEAddress& rhs) const { return !this->operator==(rhs); } // operator != - /** - * @brief Convienience operator to convert this address to string representation. - * @details This allows passing NimBLEAddress to functions - * that accept std::string and/or or it's methods as a parameter. + * @brief Convenience operator to convert this address to string representation. + * @details This allows passing NimBLEAddress to functions that accept std::string and/or it's methods as a parameter. */ NimBLEAddress::operator std::string() const { char buffer[18]; - snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x", - m_address[5], m_address[4], m_address[3], - m_address[2], m_address[1], m_address[0]); - return std::string(buffer); + snprintf(buffer, + sizeof(buffer), + "%02x:%02x:%02x:%02x:%02x:%02x", + this->val[5], + this->val[4], + this->val[3], + this->val[2], + this->val[1], + this->val[0]); + return std::string{buffer}; } // operator std::string - /** * @brief Convenience operator to convert the native address representation to uint_64. */ NimBLEAddress::operator uint64_t() const { uint64_t address = 0; - memcpy(&address, m_address, sizeof m_address); + memcpy(&address, this->val, sizeof this->val); return address; } // operator uint64_t diff --git a/src/NimBLEAddress.h b/src/NimBLEAddress.h index 8a55b3eb..ff649475 100644 --- a/src/NimBLEAddress.h +++ b/src/NimBLEAddress.h @@ -12,52 +12,56 @@ * Author: kolban */ -#ifndef COMPONENTS_NIMBLEADDRESS_H_ -#define COMPONENTS_NIMBLEADDRESS_H_ +#ifndef NIMBLE_CPP_ADDRESS_H_ +#define NIMBLE_CPP_ADDRESS_H_ #include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) -#if defined(CONFIG_NIMBLE_CPP_IDF) -#include "nimble/ble.h" -#else -#include "nimble/nimble/include/nimble/ble.h" -#endif +# if defined(CONFIG_NIMBLE_CPP_IDF) +# include "nimble/ble.h" +# else +# include "nimble/nimble/include/nimble/ble.h" +# endif /**** FIX COMPILATION ****/ -#undef min -#undef max +# undef min +# undef max /**************************/ -#include -#include +# include /** * @brief A %BLE device address. * * Every %BLE device has a unique address which can be used to identify it and form connections. */ -class NimBLEAddress { -public: - NimBLEAddress(); - NimBLEAddress(ble_addr_t address); - NimBLEAddress(uint8_t address[6], uint8_t type = BLE_ADDR_PUBLIC); - NimBLEAddress(const std::string &stringAddress, uint8_t type = BLE_ADDR_PUBLIC); - NimBLEAddress(const uint64_t &address, uint8_t type = BLE_ADDR_PUBLIC); - bool isRpa() const; - bool equals(const NimBLEAddress &otherAddress) const; - const uint8_t* getNative() const; - std::string toString() const; - uint8_t getType() const; +class NimBLEAddress : private ble_addr_t { + public: + /** + * @brief Create a blank address, i.e. 00:00:00:00:00:00, type 0. + */ + NimBLEAddress() = default; + NimBLEAddress(const ble_addr_t address); + NimBLEAddress(const uint8_t address[BLE_DEV_ADDR_LEN], uint8_t type = BLE_ADDR_PUBLIC); + NimBLEAddress(const std::string& stringAddress, uint8_t type = BLE_ADDR_PUBLIC); + NimBLEAddress(const uint64_t& address, uint8_t type = BLE_ADDR_PUBLIC); - bool operator ==(const NimBLEAddress & rhs) const; - bool operator !=(const NimBLEAddress & rhs) const; - operator std::string() const; - operator uint64_t() const; - -private: - uint8_t m_address[6]; - uint8_t m_addrType; + bool isRpa() const; + bool isNrpa() const; + bool isStatic() const; + bool isPublic() const; + bool isNull() const; + bool equals(const NimBLEAddress& otherAddress) const; + const ble_addr_t* getBase() const; + std::string toString() const; + uint8_t getType() const; + const uint8_t* getVal() const; + const NimBLEAddress& reverseByteOrder(); + bool operator==(const NimBLEAddress& rhs) const; + bool operator!=(const NimBLEAddress& rhs) const; + operator std::string() const; + operator uint64_t() const; }; #endif /* CONFIG_BT_ENABLED */ -#endif /* COMPONENTS_NIMBLEADDRESS_H_ */ +#endif /* NIMBLE_CPP_ADDRESS_H_ */ diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index bdc1358e..fba6f5d7 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -302,7 +302,7 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) { } } - return NimBLEAddress(""); + return NimBLEAddress{}; } diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index 7869fb54..50d3f70c 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -162,7 +162,7 @@ class NimBLEAdvertisedDevice { uint8_t findAdvField(uint8_t type, uint8_t index = 0, size_t * data_loc = nullptr); size_t findServiceData(uint8_t index, uint8_t* bytes); - NimBLEAddress m_address = NimBLEAddress(""); + NimBLEAddress m_address; uint8_t m_advType; int m_rssi; time_t m_timestamp; diff --git a/src/NimBLEAdvertising.cpp b/src/NimBLEAdvertising.cpp index 1a4772e6..cc044221 100644 --- a/src/NimBLEAdvertising.cpp +++ b/src/NimBLEAdvertising.cpp @@ -643,15 +643,9 @@ bool NimBLEAdvertising::start(uint32_t duration, advCompleteCB_t advCompleteCB, m_advDataSet = true; } - ble_addr_t peerAddr; - if (dirAddr != nullptr) { - memcpy(&peerAddr.val, dirAddr->getNative(), 6); - peerAddr.type = dirAddr->getType(); - } - #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, - (dirAddr != nullptr) ? &peerAddr : NULL, + (dirAddr != nullptr) ? dirAddr->getBase() : NULL, duration, &m_advParams, (pServer != nullptr) ? NimBLEServer::handleGapEvent : diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index e49827f4..4f78452b 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -199,16 +199,14 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttributes) return false; } - ble_addr_t peerAddr_t; - memcpy(&peerAddr_t.val, address.getNative(),6); - peerAddr_t.type = address.getType(); - if(ble_gap_conn_find_by_addr(&peerAddr_t, NULL) == 0) { + const ble_addr_t* peerAddr = address.getBase(); + if(ble_gap_conn_find_by_addr(peerAddr, NULL) == 0) { NIMBLE_LOGE(LOG_TAG, "A connection to %s already exists", address.toString().c_str()); return false; } - if(address == NimBLEAddress("")) { + if(address.isNull()) { NIMBLE_LOGE(LOG_TAG, "Invalid peer address;(NULL)"); return false; } else { @@ -227,7 +225,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttributes) do { #if CONFIG_BT_NIMBLE_EXT_ADV rc = ble_gap_ext_connect(NimBLEDevice::m_own_addr_type, - &peerAddr_t, + peerAddr, m_connectTimeout, m_phyMask, &m_pConnParams, @@ -237,7 +235,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttributes) this); #else - rc = ble_gap_connect(NimBLEDevice::m_own_addr_type, &peerAddr_t, + rc = ble_gap_connect(NimBLEDevice::m_own_addr_type, peerAddr, m_connectTimeout, &m_pConnParams, NimBLEClient::handleGapEvent, this); #endif @@ -557,7 +555,7 @@ uint16_t NimBLEClient::getConnId() { void NimBLEClient::clearConnection() { m_conn_id = BLE_HS_CONN_HANDLE_NONE; m_connEstablished = false; - m_peerAddress = NimBLEAddress(); + m_peerAddress = NimBLEAddress{}; } // clearConnection /** diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index 9ae964cd..c873b8a7 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -56,6 +56,8 @@ #include "NimBLELog.h" +#include + static const char* LOG_TAG = "NimBLEDevice"; /** @@ -456,7 +458,7 @@ int NimBLEDevice::getPower() { */ /* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() { - ble_addr_t addr = {BLE_ADDR_PUBLIC, 0}; + ble_addr_t addr{}; if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) { NIMBLE_LOGD(LOG_TAG, "Public address not found, checking random"); @@ -599,16 +601,7 @@ bool NimBLEDevice::deleteAllBonds() { */ /*STATIC*/ bool NimBLEDevice::deleteBond(const NimBLEAddress &address) { - ble_addr_t delAddr; - memcpy(&delAddr.val, address.getNative(),6); - delAddr.type = address.getType(); - - int rc = ble_gap_unpair(&delAddr); - if (rc != 0) { - return false; - } - - return true; + return ble_gap_unpair(address.getBase()) == 0; } @@ -685,26 +678,14 @@ bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) { */ /*STATIC*/ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) { - if (NimBLEDevice::onWhiteList(address)) { - return true; - } - - m_whiteList.push_back(address); - std::vector wlVec; - wlVec.reserve(m_whiteList.size()); - - for (auto &it : m_whiteList) { - ble_addr_t wlAddr; - memcpy(&wlAddr.val, it.getNative(), 6); - wlAddr.type = it.getType(); - wlVec.push_back(wlAddr); - } - - int rc = ble_gap_wl_set(&wlVec[0], wlVec.size()); - if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc); - m_whiteList.pop_back(); - return false; + if (!NimBLEDevice::onWhiteList(address)) { + m_whiteList.push_back(address); + int rc = ble_gap_wl_set(reinterpret_cast(&m_whiteList[0]), m_whiteList.size()); + if (rc != 0) { + NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc); + m_whiteList.pop_back(); + return false; + } } return true; @@ -718,33 +699,14 @@ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) { */ /*STATIC*/ bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) { - if (!NimBLEDevice::onWhiteList(address)) { - return true; - } - - std::vector wlVec; - wlVec.reserve(m_whiteList.size()); - - for (auto &it : m_whiteList) { - if (it != address) { - ble_addr_t wlAddr; - memcpy(&wlAddr.val, it.getNative(), 6); - wlAddr.type = it.getType(); - wlVec.push_back(wlAddr); - } - } - - int rc = ble_gap_wl_set(&wlVec[0], wlVec.size()); - if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "Failed removing from whitelist rc=%d", rc); - return false; - } - - // Don't remove from the list unless NimBLE returned success - for (auto it = m_whiteList.begin(); it < m_whiteList.end(); ++it) { - if ((*it) == address) { - m_whiteList.erase(it); - break; + auto it = std::find(m_whiteList.begin(), m_whiteList.end(), address); + if (it != m_whiteList.end()) { + m_whiteList.erase(it); + int rc = ble_gap_wl_set(reinterpret_cast(&m_whiteList[0]), m_whiteList.size()); + if (rc != 0) { + m_whiteList.push_back(address); + NIMBLE_LOGE(LOG_TAG, "Failed removing from whitelist rc=%d", rc); + return false; } } diff --git a/src/NimBLEDevice.h b/src/NimBLEDevice.h index 64bd4ed3..f6a11b58 100644 --- a/src/NimBLEDevice.h +++ b/src/NimBLEDevice.h @@ -161,7 +161,7 @@ class NimBLEDevice { #endif #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) - static NimBLEClient* createClient(NimBLEAddress peerAddress = NimBLEAddress("")); + static NimBLEClient* createClient(NimBLEAddress peerAddress = NimBLEAddress{}); static bool deleteClient(NimBLEClient* pClient); static NimBLEClient* getClientByID(uint16_t conn_id); static NimBLEClient* getClientByPeerAddress(const NimBLEAddress &peer_addr); diff --git a/src/NimBLEExtAdvertising.cpp b/src/NimBLEExtAdvertising.cpp index 67d8a586..866e452c 100644 --- a/src/NimBLEExtAdvertising.cpp +++ b/src/NimBLEExtAdvertising.cpp @@ -100,12 +100,8 @@ bool NimBLEExtAdvertising::setInstanceData(uint8_t inst_id, NimBLEExtAdvertiseme if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "Invalid advertisement data: rc = %d", rc); } else { - if (adv.m_advAddress != NimBLEAddress("")) { - ble_addr_t addr; - memcpy(&addr.val, adv.m_advAddress.getNative(), 6); - // Custom advertising address must be random. - addr.type = BLE_OWN_ADDR_RANDOM; - rc = ble_gap_ext_adv_set_addr(inst_id, &addr); + if (!adv.m_advAddress.isNull()) { + rc = ble_gap_ext_adv_set_addr(inst_id, adv.m_advAddress.getBase()); } if (rc != 0) { @@ -388,7 +384,7 @@ void NimBLEExtAdvertisingCallbacks::onScanRequest(NimBLEExtAdvertising *pAdv, * * BLE_HCI_LE_PHY_CODED */ NimBLEExtAdvertisement::NimBLEExtAdvertisement(uint8_t priPhy, uint8_t secPhy) -: m_advAddress("") +: m_advAddress{} { memset (&m_params, 0, sizeof(m_params)); m_params.own_addr_type = NimBLEDevice::m_own_addr_type; @@ -493,10 +489,7 @@ void NimBLEExtAdvertisement::setScanFilter(bool scanRequestWhitelistOnly, bool c * @param [in] addr The address of the peer to direct the advertisements. */ void NimBLEExtAdvertisement::setDirectedPeer(const NimBLEAddress & addr) { - ble_addr_t peerAddr; - memcpy(&peerAddr.val, addr.getNative(), 6); - peerAddr.type = addr.getType(); - m_params.peer = peerAddr; + m_params.peer = *addr.getBase(); } // setDirectedPeer diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 15f933c3..4c5f84ef 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -28,6 +28,7 @@ #endif #include +#include #define NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB 0 #define NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB 1 @@ -324,12 +325,8 @@ NimBLEConnInfo NimBLEServer::getPeerInfo(size_t index) { * @param [in] address The address of the peer. */ NimBLEConnInfo NimBLEServer::getPeerInfo(const NimBLEAddress& address) { - ble_addr_t peerAddr; - memcpy(&peerAddr.val, address.getNative(),6); - peerAddr.type = address.getType(); - NimBLEConnInfo peerInfo; - int rc = ble_gap_conn_find_by_addr(&peerAddr, &peerInfo.m_desc); + int rc = ble_gap_conn_find_by_addr(address.getBase(), &peerInfo.m_desc); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "Peer info not found"); }