diff options
author | Sven Gothel <[email protected]> | 2022-11-27 12:52:58 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2022-11-27 12:52:58 +0100 |
commit | cc49c8bf94b5b9b557cb2caf7b379df0660604af (patch) | |
tree | c162540a52b27442720a70622c79dbc3ce79733f | |
parent | afe939ca46e6a1517e0f3b326f2f23be2e616c9a (diff) |
AttPDUMsg*, SMPPDUMsg*: Place check_range() to final type, avoid vtable-mess; Have all msg creation ctor check range.
-rw-r--r-- | api/direct_bt/ATTPDUTypes.hpp | 213 | ||||
-rw-r--r-- | api/direct_bt/SMPTypes.hpp | 104 |
2 files changed, 209 insertions, 108 deletions
diff --git a/api/direct_bt/ATTPDUTypes.hpp b/api/direct_bt/ATTPDUTypes.hpp index 12650f8d..1c7e36ed 100644 --- a/api/direct_bt/ATTPDUTypes.hpp +++ b/api/direct_bt/ATTPDUTypes.hpp @@ -27,6 +27,7 @@ #define ATT_PDU_TYPES_HPP_ #include <cstring> +#include <exception> #include <string> #include <memory> #include <cstdint> @@ -493,6 +494,10 @@ namespace direct_bt { } protected: + void check_range() { + pdu.check_range(0, getPDUMinSize(), E_FILE_LINE); + } + void checkOpcode(const Opcode expected) const { const Opcode has = getOpcode(); @@ -539,9 +544,7 @@ namespace direct_bt { AttPDUMsg(const uint8_t* source, const jau::nsize_t size) : pdu(source, std::max<jau::nsize_t>(1, size), jau::endian::little), ts_creation(jau::getCurrentMilliseconds()) - { - pdu.check_range(0, getPDUMinSize()); - } + { } /** Persistent memory, w/ ownership ..*/ AttPDUMsg(const Opcode opc, const jau::nsize_t size) @@ -549,7 +552,6 @@ namespace direct_bt { ts_creation(jau::getCurrentMilliseconds()) { pdu.put_uint8_nc(0, number(opc)); - pdu.check_range(0, getPDUMinSize()); } AttPDUMsg(const AttPDUMsg &o) = default; // POctets copy-ctor may throw @@ -557,7 +559,7 @@ namespace direct_bt { AttPDUMsg& operator=(const AttPDUMsg &o) noexcept = delete; // const ts_creation AttPDUMsg& operator=(AttPDUMsg &&o) noexcept = delete; // const ts_creation - virtual ~AttPDUMsg() noexcept {} + virtual ~AttPDUMsg() noexcept = default; /** ATT PDU Format Vol 3, Part F 3.3.1 */ constexpr Opcode getOpcode() const noexcept { return static_cast<Opcode>(pdu.get_uint8_nc(0)); } @@ -677,10 +679,11 @@ namespace direct_bt { * ATT_PDU_UNDEFINED * </p> */ - class AttPDUUndefined : public AttPDUMsg + class AttPDUUndefined final : public AttPDUMsg { public: AttPDUUndefined(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::PDU_UNDEFINED); } @@ -696,7 +699,7 @@ namespace direct_bt { * * Used to send a error reply for any request. */ - class AttErrorRsp : public AttPDUMsg + class AttErrorRsp final : public AttPDUMsg { public: enum class ErrorCode : uint8_t { @@ -728,18 +731,19 @@ namespace direct_bt { static std::string getErrorCodeString(const ErrorCode errorCode) noexcept; AttErrorRsp(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::ERROR_RSP); } AttErrorRsp(const ErrorCode error_code, const Opcode cause_opc, const uint16_t cause_handle) : AttPDUMsg(Opcode::ERROR_RSP, 1+1+2+1) { - pdu.put_uint8_nc(1, AttPDUMsg::number(cause_opc)); - pdu.put_uint16_nc(2, cause_handle); - pdu.put_uint8_nc(4, number(error_code)); + pdu.put_uint8(1, AttPDUMsg::number(cause_opc)); + pdu.put_uint16(2, cause_handle); + pdu.put_uint8(4, number(error_code)); + check_range(); } - /** opcode + reqOpcodeCause + handleCause + errorCode */ constexpr_cxx20 jau::nsize_t getPDUValueOffset() const noexcept override { return 1 + 1 + 2 + 1; } @@ -770,19 +774,21 @@ namespace direct_bt { * Used for * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.3.1 Exchange MTU (Server configuration) */ - class AttExchangeMTU : public AttPDUMsg + class AttExchangeMTU final : public AttPDUMsg { public: AttExchangeMTU(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::EXCHANGE_MTU_RSP, Opcode::EXCHANGE_MTU_REQ); } AttExchangeMTU(const ReqRespType type, const uint16_t mtuSize) : AttPDUMsg(is_request(type) ? Opcode::EXCHANGE_MTU_REQ : Opcode::EXCHANGE_MTU_RSP, 1+2) { - pdu.put_uint16_nc(1, mtuSize); + pdu.put_uint16(1, mtuSize); + check_range(); } /** opcode + mtu-size */ @@ -807,19 +813,21 @@ namespace direct_bt { * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.1 Read Characteristic Value * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.12.1 Read Characteristic Descriptors */ - class AttReadReq : public AttPDUMsg + class AttReadReq final : public AttPDUMsg { public: AttReadReq(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::READ_REQ); } AttReadReq(const uint16_t handle) : AttPDUMsg(Opcode::READ_REQ, getPDUValueOffset()) { - pdu.put_uint16_nc(1, handle); + pdu.put_uint16(1, handle); + check_range(); } /** opcode + handle */ @@ -844,20 +852,22 @@ namespace direct_bt { * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.3 Read Long Characteristic Value * - For any follow up request, which previous request reply couldn't fit in ATT_MTU */ - class AttReadBlobReq : public AttPDUMsg + class AttReadBlobReq final : public AttPDUMsg { public: AttReadBlobReq(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::READ_BLOB_REQ); } AttReadBlobReq(const uint16_t handle, const uint16_t value_offset) : AttPDUMsg(Opcode::READ_BLOB_REQ, getPDUValueOffset()) { - pdu.put_uint16_nc(1, handle); - pdu.put_uint16_nc(3, value_offset); + pdu.put_uint16(1, handle); + pdu.put_uint16(3, value_offset); + check_range(); } /** opcode + handle + value_offset */ @@ -891,7 +901,7 @@ namespace direct_bt { * If expected value size exceeds getValueSize(), continue with ATT_READ_BLOB_REQ (3.4.4.5), * see shallReadBlobReq(..) */ - class AttReadNRsp : public AttPDUMsg + class AttReadNRsp final : public AttPDUMsg { private: const jau::TOctetSlice view; @@ -903,6 +913,7 @@ namespace direct_bt { : AttPDUMsg(source, length), view(pdu, getPDUValueOffset(), getPDUValueSize()) { + check_range(); checkOpcode(Opcode::READ_RSP, Opcode::READ_BLOB_RSP); } @@ -914,7 +925,8 @@ namespace direct_bt { throw AttValueException(getName()+": Invalid value offset "+std::to_string(value_offset)+ " > value-size "+std::to_string(value.size()), E_FILE_LINE); } - pdu.put_bytes_nc(getPDUValueOffset(), value.get_ptr()+value_offset, value.size()-value_offset); + pdu.put_bytes(getPDUValueOffset(), value.get_ptr()+value_offset, value.size()-value_offset); + check_range(); } /** opcode */ @@ -944,7 +956,7 @@ namespace direct_bt { * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.3 Write Characteristic Value * - BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration */ - class AttWriteReq : public AttPDUMsg + class AttWriteReq final : public AttPDUMsg { private: const jau::TOctetSlice view; @@ -956,6 +968,7 @@ namespace direct_bt { : AttPDUMsg(source, length), view(pdu, getPDUValueOffset(), getPDUValueSize()) { + check_range(); checkOpcode(Opcode::WRITE_REQ); } @@ -963,8 +976,9 @@ namespace direct_bt { : AttPDUMsg(Opcode::WRITE_REQ, getPDUValueOffset()+value.size()), view(pdu, getPDUValueOffset(), getPDUValueSize()) { - pdu.put_uint16_nc(1, handle); - pdu.put_bytes_nc(getPDUValueOffset(), value.get_ptr(), value.size()); + pdu.put_uint16(1, handle); + pdu.put_bytes(getPDUValueOffset(), value.get_ptr(), value.size()); + check_range(); } /** opcode + handle */ @@ -992,17 +1006,21 @@ namespace direct_bt { * Used for: * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.3 Write Characteristic Value */ - class AttWriteRsp : public AttPDUMsg + class AttWriteRsp final : public AttPDUMsg { public: AttWriteRsp(const uint8_t* source, const jau::nsize_t length) - : AttPDUMsg(source, length) { + : AttPDUMsg(source, length) + { + check_range(); checkOpcode(Opcode::WRITE_RSP); } AttWriteRsp() : AttPDUMsg(Opcode::WRITE_RSP, 1) - { } + { + check_range(); + } /** opcode */ constexpr_cxx20 jau::nsize_t getPDUValueOffset() const noexcept override { return 1; } @@ -1021,7 +1039,7 @@ namespace direct_bt { * Used for: * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.1 Write Characteristic Value without Response */ - class AttWriteCmd : public AttPDUMsg + class AttWriteCmd final : public AttPDUMsg { private: const jau::TOctetSlice view; @@ -1033,6 +1051,7 @@ namespace direct_bt { : AttPDUMsg(source, length), view(pdu, getPDUValueOffset(), getPDUValueSize()) { + check_range(); checkOpcode(Opcode::WRITE_CMD); } @@ -1040,8 +1059,9 @@ namespace direct_bt { : AttPDUMsg(Opcode::WRITE_CMD, getPDUValueOffset()+value.size()), view(pdu, getPDUValueOffset(), getPDUValueSize()) { - pdu.put_uint16_nc(1, handle); - pdu.put_bytes_nc(getPDUValueOffset(), value.get_ptr(), value.size()); + pdu.put_uint16(1, handle); + pdu.put_bytes(getPDUValueOffset(), value.get_ptr(), value.size()); + check_range(); } /** opcode + handle */ @@ -1070,7 +1090,7 @@ namespace direct_bt { * Used for: * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.4 Write Long Characteristic Values */ - class AttPrepWrite : public AttPDUMsg + class AttPrepWrite final : public AttPDUMsg { private: const jau::TOctetSlice view; @@ -1082,6 +1102,7 @@ namespace direct_bt { : AttPDUMsg(source, length), view(pdu, getPDUValueOffset(), getPDUValueSize()) { + check_range(); checkOpcode(Opcode::PREPARE_WRITE_REQ, Opcode::PREPARE_WRITE_RSP); } @@ -1089,27 +1110,30 @@ namespace direct_bt { : AttPDUMsg(isReq ? Opcode::PREPARE_WRITE_REQ : Opcode::PREPARE_WRITE_RSP, getPDUValueOffset()+value.size()), view(pdu, getPDUValueOffset(), getPDUValueSize()) { - pdu.put_uint16_nc(1, handle); - pdu.put_uint16_nc(3, value_offset); - pdu.put_bytes_nc(getPDUValueOffset(), value.get_ptr(), value.size()); + pdu.put_uint16(1, handle); + pdu.put_uint16(3, value_offset); + pdu.put_bytes(getPDUValueOffset(), value.get_ptr(), value.size()); + check_range(); } AttPrepWrite(const bool isReq, const AttPrepWrite& other) : AttPDUMsg(isReq ? Opcode::PREPARE_WRITE_REQ : Opcode::PREPARE_WRITE_RSP, getPDUValueOffset()+other.getValue().size()), view(pdu, getPDUValueOffset(), getPDUValueSize()) { - pdu.put_uint16_nc(1, other.getHandle()); - pdu.put_uint16_nc(3, other.getValueOffset()); - pdu.put_bytes_nc(getPDUValueOffset(), other.getValue().get_ptr_nc(0), other.getValue().size()); + pdu.put_uint16(1, other.getHandle()); + pdu.put_uint16(3, other.getValueOffset()); + pdu.put_bytes(getPDUValueOffset(), other.getValue().get_ptr_nc(0), other.getValue().size()); + check_range(); } AttPrepWrite(const AttPrepWrite& other) : AttPDUMsg(other.getOpcode(), getPDUValueOffset()+other.getValue().size()), view(pdu, getPDUValueOffset(), getPDUValueSize()) { - pdu.put_uint16_nc(1, other.getHandle()); - pdu.put_uint16_nc(3, other.getValueOffset()); - pdu.put_bytes_nc(getPDUValueOffset(), other.getValue().get_ptr_nc(0), other.getValue().size()); + pdu.put_uint16(1, other.getHandle()); + pdu.put_uint16(3, other.getValueOffset()); + pdu.put_bytes(getPDUValueOffset(), other.getValue().get_ptr_nc(0), other.getValue().size()); + check_range(); } /** opcode + handle + value_offset */ @@ -1139,18 +1163,21 @@ namespace direct_bt { * Used for: * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.4 Write Long Characteristic Values */ - class AttExeWriteReq : public AttPDUMsg + class AttExeWriteReq final : public AttPDUMsg { public: AttExeWriteReq(const uint8_t* source, const jau::nsize_t length) - : AttPDUMsg(source, length) { + : AttPDUMsg(source, length) + { + check_range(); checkOpcode(Opcode::EXECUTE_WRITE_REQ); } AttExeWriteReq(const uint8_t flags) : AttPDUMsg(Opcode::EXECUTE_WRITE_REQ, 1+1) { - pdu.put_uint8_nc(1, flags); + pdu.put_uint8(1, flags); + check_range(); } /** opcode */ @@ -1169,17 +1196,21 @@ namespace direct_bt { * Used for: * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.4 Write Long Characteristic Values */ - class AttExeWriteRsp : public AttPDUMsg + class AttExeWriteRsp final : public AttPDUMsg { public: AttExeWriteRsp(const uint8_t* source, const jau::nsize_t length) - : AttPDUMsg(source, length) { + : AttPDUMsg(source, length) + { + check_range(); checkOpcode(Opcode::EXECUTE_WRITE_RSP); } AttExeWriteRsp() : AttPDUMsg(Opcode::EXECUTE_WRITE_RSP, 1) - { } + { + check_range(); + } /** opcode */ constexpr_cxx20 jau::nsize_t getPDUValueOffset() const noexcept override { return 1; } @@ -1205,7 +1236,7 @@ namespace direct_bt { * Send by server to notify or indicate an ATT value (at any time). * </p> */ - class AttHandleValueRcv : public AttPDUMsg + class AttHandleValueRcv final : public AttPDUMsg { private: const jau::TOctetSlice view; @@ -1217,6 +1248,7 @@ namespace direct_bt { : AttPDUMsg(source, length), view(pdu, getPDUValueOffset(), getPDUValueSize()) { + check_range(); checkOpcode(Opcode::HANDLE_VALUE_NTF, Opcode::HANDLE_VALUE_IND); } @@ -1224,8 +1256,9 @@ namespace direct_bt { : AttPDUMsg(isNotify ? Opcode::HANDLE_VALUE_NTF : Opcode::HANDLE_VALUE_IND, getPDUValueOffset()+std::min(mtu-pdu_value_offset, value.size())), view(pdu, getPDUValueOffset(), getPDUValueSize()) { - pdu.put_uint16_nc(1, handle); - pdu.put_bytes_nc(getPDUValueOffset(), value.get_ptr(), std::min(mtu-pdu_value_offset, value.size())); + pdu.put_uint16(1, handle); + pdu.put_bytes(getPDUValueOffset(), value.get_ptr(), std::min(mtu-pdu_value_offset, value.size())); + check_range(); } /** opcode + handle */ @@ -1265,18 +1298,20 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 4.11 Characteristic Value Indications * </p> */ - class AttHandleValueCfm : public AttPDUMsg + class AttHandleValueCfm final : public AttPDUMsg { public: AttHandleValueCfm(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::HANDLE_VALUE_CFM); } AttHandleValueCfm() : AttPDUMsg(Opcode::HANDLE_VALUE_CFM, 1) - { + { + check_range(); } /** opcode */ @@ -1319,7 +1354,7 @@ namespace direct_bt { } public: - virtual ~AttElementList() noexcept override {} + ~AttElementList() noexcept override = default; /** Total size of one element */ virtual jau::nsize_t getElementSize() const = 0; @@ -1404,7 +1439,7 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.1 Characteristic Declaration Attribute Value * </p> */ - class AttReadByNTypeReq : public AttPDUMsg + class AttReadByNTypeReq final : public AttPDUMsg { private: jau::uuid_t::TypeSize getUUIFormat() const { @@ -1415,6 +1450,7 @@ namespace direct_bt { AttReadByNTypeReq(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::READ_BY_GROUP_TYPE_REQ, Opcode::READ_BY_TYPE_REQ); } @@ -1424,9 +1460,10 @@ namespace direct_bt { if( uuid.getTypeSize() != jau::uuid_t::TypeSize::UUID16_SZ && uuid.getTypeSize()!= jau::uuid_t::TypeSize::UUID128_SZ ) { throw jau::IllegalArgumentException("Only UUID16 and UUID128 allowed: "+uuid.toString(), E_FILE_LINE); } - pdu.put_uint16_nc(1, startHandle); - pdu.put_uint16_nc(3, endHandle); - pdu.put_uuid_nc(5, uuid); + pdu.put_uint16(1, startHandle); + pdu.put_uint16(3, endHandle); + pdu.put_uuid(5, uuid); + check_range(); } /** opcode + handle-start + handle-end */ @@ -1471,7 +1508,7 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.1 Characteristic Declaration Attribute Value * </p> */ - class AttReadByTypeRsp : public AttElementList + class AttReadByTypeRsp final : public AttElementList { public: /** @@ -1500,6 +1537,7 @@ namespace direct_bt { AttReadByTypeRsp(const uint8_t* source, const jau::nsize_t length) : AttElementList(source, length) { + check_range(); checkOpcode(Opcode::READ_BY_TYPE_RSP); if( getPDUValueSize() % getElementSize() != 0 ) { @@ -1545,7 +1583,8 @@ namespace direct_bt { AttReadByTypeRsp(const jau::nsize_t total_length) : AttElementList(Opcode::READ_BY_TYPE_RSP, total_length) { - pdu.put_uint8_nc(1, 2 + 1 + 2 + 2); // dummy element_size: handle + property + handle + uuid + pdu.put_uint8(1, 2 + 1 + 2 + 2); // dummy element_size: handle + property + handle + uuid + check_range(); } Element getElement(const jau::nsize_t elementIdx) const { @@ -1591,7 +1630,7 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 4.4.1 Discover All Primary Services * </p> */ - class AttReadByGroupTypeRsp : public AttElementList + class AttReadByGroupTypeRsp final : public AttElementList { public: /** @@ -1617,6 +1656,7 @@ namespace direct_bt { AttReadByGroupTypeRsp(const uint8_t* source, const jau::nsize_t length) : AttElementList(source, length) { + check_range(); checkOpcode(Opcode::READ_BY_GROUP_TYPE_RSP); if( getPDUValueSize() % getElementSize() != 0 ) { @@ -1639,6 +1679,7 @@ namespace direct_bt { */ void setElementSize(const uint8_t element_length) override { pdu.put_uint8_nc(1, element_length); + check_range(); } /** @@ -1662,7 +1703,8 @@ namespace direct_bt { AttReadByGroupTypeRsp(const jau::nsize_t total_length) : AttElementList(Opcode::READ_BY_GROUP_TYPE_RSP, total_length) { - pdu.put_uint8_nc(1, 2+2+2); // dummy element_size: handle + handle + uuid + pdu.put_uint8(1, 2+2+2); // dummy element_size: handle + handle + uuid + check_range(); } Element getElement(const jau::nsize_t elementIdx) const { @@ -1713,20 +1755,22 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 4.7.1 Discover All Characteristic Descriptors * </p> */ - class AttFindInfoReq : public AttPDUMsg + class AttFindInfoReq final : public AttPDUMsg { public: AttFindInfoReq(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::FIND_INFORMATION_REQ); } AttFindInfoReq(const uint16_t startHandle, const uint16_t endHandle) : AttPDUMsg(Opcode::FIND_INFORMATION_REQ, 1+2+2) { - pdu.put_uint16_nc(1, startHandle); - pdu.put_uint16_nc(3, endHandle); + pdu.put_uint16(1, startHandle); + pdu.put_uint16(3, endHandle); + check_range(); } /** opcode + handle_start + handle_end */ @@ -1765,7 +1809,7 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 4.7.1 Discover All Characteristic Descriptors * </p> */ - class AttFindInfoRsp : public AttElementList + class AttFindInfoRsp final : public AttElementList { private: static jau::uuid_t::TypeSize toTypeSize(const uint8_t format) { @@ -1803,6 +1847,7 @@ namespace direct_bt { AttFindInfoRsp(const uint8_t* source, const jau::nsize_t length) : AttElementList(source, length) { + check_range(); checkOpcode(Opcode::FIND_INFORMATION_RSP); if( getPDUValueSize() % getElementSize() != 0 ) { throw AttValueException("AttFindInfoRsp: Invalid packet size: pdu-value-size "+std::to_string(getPDUValueSize())+ @@ -1845,6 +1890,7 @@ namespace direct_bt { const jau::nsize_t tsz_i = element_length - 2 /* handle */; const jau::uuid_t::TypeSize tsz = jau::uuid_t::toTypeSize(tsz_i); pdu.put_uint8_nc(1, toFormatCode(tsz)); + check_range(); } /** @@ -1858,7 +1904,8 @@ namespace direct_bt { AttFindInfoRsp(const jau::nsize_t total_length) : AttElementList(Opcode::FIND_INFORMATION_RSP, total_length) { - pdu.put_uint8_nc(1, 2); // dummy format: uuid16_t + pdu.put_uint8(1, 2); // dummy format: uuid16_t + check_range(); } Element getElement(const jau::nsize_t elementIdx) const { @@ -1904,7 +1951,7 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 4.4.2 Discover Primary Service by Service UUID * </p> */ - class AttFindByTypeValueReq : public AttPDUMsg + class AttFindByTypeValueReq final : public AttPDUMsg { private: jau::uuid_t::TypeSize getAttValueTypeSize() const { @@ -1917,6 +1964,7 @@ namespace direct_bt { AttFindByTypeValueReq(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::FIND_BY_TYPE_VALUE_REQ); if( getPDUValueSize() == 0 ) { @@ -1930,10 +1978,11 @@ namespace direct_bt { const jau::uuid16_t &att_type, const jau::uuid_t& att_value) : AttPDUMsg(Opcode::FIND_BY_TYPE_VALUE_REQ, getPDUValueOffset()+att_value.getTypeSizeInt()) { - pdu.put_uint16_nc(1, startHandle); - pdu.put_uint16_nc(1+2, endHandle); - pdu.put_uuid_nc (1+2+2, att_type); - pdu.put_uuid_nc (1+2+2+2, att_value); + pdu.put_uint16(1, startHandle); + pdu.put_uint16(1+2, endHandle); + pdu.put_uuid (1+2+2, att_type); + pdu.put_uuid (1+2+2+2, att_value); + check_range(); } /** opcode + handle_start + handle_end + att_type */ @@ -1945,7 +1994,16 @@ namespace direct_bt { jau::uuid16_t getAttType() const noexcept { return pdu.get_uuid16_nc( 1 + 2 + 2 ); } - std::unique_ptr<const jau::uuid_t> getAttValue() const noexcept { return pdu.get_uuid(pdu_value_offset, getAttValueTypeSize()); } + std::unique_ptr<const jau::uuid_t> getAttValue() const noexcept { + try { + return pdu.get_uuid(pdu_value_offset, getAttValueTypeSize()); + } catch (const jau::ExceptionBase &e) { + ERR_PRINT("invalid att uuid: %s", e.message().c_str()); + } catch (...) { + ERR_PRINT("invalid att uuid: Unknown exception"); + } + return std::make_unique<jau::uuid16_t>(0); + } constexpr_cxx20 std::string getName() const noexcept override { return "AttFindByTypeValueReq"; @@ -1976,12 +2034,13 @@ namespace direct_bt { * BT Core Spec v5.2: Vol 3, Part G GATT: 4.4.2 Discover Primary Service by Service UUID * </p> */ - class AttFindByTypeValueRsp : public AttPDUMsg + class AttFindByTypeValueRsp final : public AttPDUMsg { public: AttFindByTypeValueRsp(const uint8_t* source, const jau::nsize_t length) : AttPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::FIND_BY_TYPE_VALUE_RSP); if( getPDUValueSize() % getElementSize() != 0 ) { throw AttValueException("AttFindInfoRsp: Invalid packet size: pdu-value-size "+std::to_string(getPDUValueSize())+ @@ -1998,7 +2057,7 @@ namespace direct_bt { * element := { uint16_t handle_start, uint16_t handle_end } * </p> */ - constexpr jau::nsize_t getElementSize() const { + constexpr jau::nsize_t getElementSize() const noexcept { return 2 /* handle */ + 2 /* handle_end */; } @@ -2028,9 +2087,10 @@ namespace direct_bt { throw AttValueException(getName()+": Invalid packet size: pdu-value-size "+std::to_string(getPDUValueSize())+ " not multiple of element-size "+std::to_string(getElementSize()), E_FILE_LINE); } + check_range(); } - jau::nsize_t getElementPDUOffset(const jau::nsize_t elementIdx) const { + jau::nsize_t getElementPDUOffset(const jau::nsize_t elementIdx) const noexcept { return getPDUValueOffset() + elementIdx * getElementSize(); } @@ -2042,13 +2102,14 @@ namespace direct_bt { * Create an incomplete response with maximal (MTU) length. * * User shall set all elements via the set*() methods - * and finally use setElementSize() to fixate element length and element count. + * and finally use setElementCount() to fixate element count. * * @param total_length maximum */ AttFindByTypeValueRsp(const jau::nsize_t total_length) : AttPDUMsg(Opcode::FIND_BY_TYPE_VALUE_RSP, total_length) { + check_range(); } uint16_t getElementHandle(const jau::nsize_t elementIdx) const { @@ -2060,8 +2121,8 @@ namespace direct_bt { void setElementHandles(const jau::nsize_t elementIdx, const uint16_t handle, const uint16_t handle_end) { const jau::nsize_t offset = getElementPDUOffset(elementIdx); - pdu.put_uint16_nc( offset, handle ); - pdu.put_uint16_nc( offset, handle_end ); + pdu.put_uint16( offset, handle ); + pdu.put_uint16( offset, handle_end ); } constexpr_cxx20 std::string getName() const noexcept override { diff --git a/api/direct_bt/SMPTypes.hpp b/api/direct_bt/SMPTypes.hpp index b0b50f2b..767ebe62 100644 --- a/api/direct_bt/SMPTypes.hpp +++ b/api/direct_bt/SMPTypes.hpp @@ -29,6 +29,7 @@ #include <cstring> #include <string> #include <cstdint> +#include <cmath> #include <algorithm> #include <mutex> @@ -847,6 +848,10 @@ namespace direct_bt { protected: friend class SMPHandler; + void check_range() { + pdu.check_range(0, getDataOffset()+getDataSize(), E_FILE_LINE); + } + void checkOpcode(const Opcode expected) const { const Opcode has = getOpcode(); @@ -893,8 +898,14 @@ namespace direct_bt { SMPPDUMsg(const uint8_t* source, const jau::nsize_t size) : pdu(source, std::max<jau::nsize_t>(1, size), jau::endian::little), ts_creation(jau::getCurrentMilliseconds()) - { - pdu.check_range(0, getDataOffset()+getDataSize()); + { } + + /** Persistent memory, w/ ownership ..*/ + SMPPDUMsg(const uint8_t* source, const jau::nsize_t size, const jau::nsize_t min_size) + : pdu(source, std::max<jau::nsize_t>(1, size), jau::endian::little), + ts_creation(jau::getCurrentMilliseconds()) + { + pdu.check_range(0, std::max<jau::nsize_t>(1, min_size), E_FILE_LINE); } /** Persistent memory, w/ ownership ..*/ @@ -903,10 +914,9 @@ namespace direct_bt { ts_creation(jau::getCurrentMilliseconds()) { pdu.put_uint8_nc(0, number(opc)); - pdu.check_range(0, getDataOffset()+getDataSize()); } - virtual ~SMPPDUMsg() noexcept {} + virtual ~SMPPDUMsg() noexcept = default; /** * Clone template for convenience, based on derived class's copy-constructor. @@ -994,7 +1004,7 @@ namespace direct_bt { SMPEncKeyByteStream(const Opcode opc, const jau::nsize_t size) : SMPPDUMsg(opc, size) { } - virtual ~SMPEncKeyByteStream() noexcept {} + ~SMPEncKeyByteStream() noexcept override = default; }; /** @@ -1049,7 +1059,7 @@ namespace direct_bt { * are defined in Vol 3, Part C (GAP): 14.2 BRD/EDR/LE security aspects - Collision Handling. * </p> */ - class SMPPairingMsg : public SMPPDUMsg + class SMPPairingMsg final : public SMPPDUMsg { private: const bool request; @@ -1059,13 +1069,14 @@ namespace direct_bt { public: SMPPairingMsg(const bool request_, const uint8_t* source, const jau::nsize_t length) - : SMPPDUMsg(source, length), + : SMPPDUMsg(source, length, 7), request(request_), authReqMask(static_cast<SMPAuthReqs>( pdu.get_uint8_nc(3) )), initiator_key_dist(static_cast<SMPKeyType>(pdu.get_uint8_nc(5))), responder_key_dist(static_cast<SMPKeyType>(pdu.get_uint8_nc(6))) { checkOpcode(request? Opcode::PAIRING_REQUEST : Opcode::PAIRING_RESPONSE); + check_range(); } SMPPairingMsg(const bool request_, @@ -1077,12 +1088,13 @@ namespace direct_bt { request(request_), authReqMask(auth_req_mask), initiator_key_dist(initiator_key_dist_), responder_key_dist(responder_key_dist_) { - pdu.put_uint8_nc(1, direct_bt::number(ioc)); - pdu.put_uint8_nc(2, direct_bt::number(odf)); - pdu.put_uint8_nc(3, direct_bt::number(authReqMask)); - pdu.put_uint8_nc(4, maxEncKeySize); - pdu.put_uint8_nc(5, direct_bt::number(initiator_key_dist)); - pdu.put_uint8_nc(6, direct_bt::number(responder_key_dist)); + pdu.put_uint8(1, direct_bt::number(ioc)); + pdu.put_uint8(2, direct_bt::number(odf)); + pdu.put_uint8(3, direct_bt::number(authReqMask)); + pdu.put_uint8(4, maxEncKeySize); + pdu.put_uint8(5, direct_bt::number(initiator_key_dist)); + pdu.put_uint8(6, direct_bt::number(responder_key_dist)); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1209,12 +1221,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPPairConfirmMsg : public SMPEncKeyByteStream + class SMPPairConfirmMsg final : public SMPEncKeyByteStream { public: SMPPairConfirmMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::PAIRING_CONFIRM); } @@ -1222,6 +1235,7 @@ namespace direct_bt { : SMPEncKeyByteStream(Opcode::PAIRING_CONFIRM, 1+16) { jau::put_uint128(pdu.get_wptr(), 1, confirm_value); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1304,12 +1318,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPPairRandMsg : public SMPEncKeyByteStream + class SMPPairRandMsg final : public SMPEncKeyByteStream { public: SMPPairRandMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::PAIRING_RANDOM); } @@ -1317,6 +1332,7 @@ namespace direct_bt { : SMPEncKeyByteStream(Opcode::PAIRING_RANDOM, 1+16) { jau::put_uint128(pdu.get_wptr(), 1, random_value); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1361,7 +1377,7 @@ namespace direct_bt { * uint8_t reason_code * </pre> */ - class SMPPairFailedMsg: public SMPPDUMsg + class SMPPairFailedMsg final : public SMPPDUMsg { public: enum class ReasonCode : uint8_t { @@ -1386,14 +1402,18 @@ namespace direct_bt { } static std::string getReasonCodeString(const ReasonCode reasonCode) noexcept; - SMPPairFailedMsg(const uint8_t* source, const jau::nsize_t length) : SMPPDUMsg(source, length) { + SMPPairFailedMsg(const uint8_t* source, const jau::nsize_t length) + : SMPPDUMsg(source, length) + { + check_range(); checkOpcode(Opcode::PAIRING_FAILED); } SMPPairFailedMsg(const ReasonCode rc) : SMPPDUMsg(Opcode::PAIRING_FAILED, 1+1) { - pdu.put_uint8_nc(1, number(rc)); + pdu.put_uint8(1, number(rc)); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1438,12 +1458,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPPairPubKeyMsg : public SMPEncKeyByteStream + class SMPPairPubKeyMsg final : public SMPEncKeyByteStream { public: SMPPairPubKeyMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::PAIRING_PUBLIC_KEY); } @@ -1452,6 +1473,7 @@ namespace direct_bt { { jau::put_uint256(pdu.get_wptr(), 1, pub_key_x); jau::put_uint256(pdu.get_wptr(), 1+32, pub_key_y); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1502,12 +1524,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPPairDHKeyCheckMsg : public SMPEncKeyByteStream + class SMPPairDHKeyCheckMsg final : public SMPEncKeyByteStream { public: SMPPairDHKeyCheckMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::PAIRING_DHKEY_CHECK); } @@ -1515,6 +1538,7 @@ namespace direct_bt { : SMPEncKeyByteStream(Opcode::PAIRING_DHKEY_CHECK, 1+16) { jau::put_uint128(pdu.get_wptr(), 1, dhkey_check_values); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1553,7 +1577,7 @@ namespace direct_bt { * Message is used during the Passkey Entry protocol by a device with KeyboardOnly IO capabilities * to inform the remote device when keys have been entered or erased. */ - class SMPPasskeyNotification: public SMPPDUMsg + class SMPPasskeyNotification final : public SMPPDUMsg { public: enum class TypeCode : uint8_t { @@ -1568,7 +1592,10 @@ namespace direct_bt { } static std::string getTypeCodeString(const TypeCode tc) noexcept; - SMPPasskeyNotification(const uint8_t* source, const jau::nsize_t length) : SMPPDUMsg(source, length) { + SMPPasskeyNotification(const uint8_t* source, const jau::nsize_t length) + : SMPPDUMsg(source, length) + { + check_range(); checkOpcode(Opcode::PAIRING_KEYPRESS_NOTIFICATION); } @@ -1576,6 +1603,7 @@ namespace direct_bt { : SMPPDUMsg(Opcode::PAIRING_KEYPRESS_NOTIFICATION, 1+1) { pdu.put_uint8_nc(1, number(tc)); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1625,12 +1653,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPEncInfoMsg : public SMPEncKeyByteStream + class SMPEncInfoMsg final : public SMPEncKeyByteStream { public: SMPEncInfoMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::ENCRYPTION_INFORMATION); } @@ -1638,6 +1667,7 @@ namespace direct_bt { : SMPEncKeyByteStream(Opcode::ENCRYPTION_INFORMATION, 1+16) { jau::put_uint128(pdu.get_wptr(), 1, long_term_key); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1694,12 +1724,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPMasterIdentMsg : public SMPEncKeyByteStream + class SMPMasterIdentMsg final : public SMPEncKeyByteStream { public: SMPMasterIdentMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::MASTER_IDENTIFICATION); } @@ -1708,6 +1739,7 @@ namespace direct_bt { { jau::put_uint16(pdu.get_wptr(), 1, ediv); jau::put_uint64(pdu.get_wptr(), 1+2, rand); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1772,12 +1804,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPIdentInfoMsg : public SMPEncKeyByteStream + class SMPIdentInfoMsg final : public SMPEncKeyByteStream { public: SMPIdentInfoMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::IDENTITY_INFORMATION); } @@ -1785,6 +1818,7 @@ namespace direct_bt { : SMPEncKeyByteStream(Opcode::IDENTITY_INFORMATION, 1+16) { jau::put_uint128(pdu.get_wptr(), 1, identity_resolving_key); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1837,20 +1871,22 @@ namespace direct_bt { * Secure Connection: #2 in distribution * </p> */ - class SMPIdentAddrInfoMsg : public SMPPDUMsg + class SMPIdentAddrInfoMsg final : public SMPPDUMsg { public: SMPIdentAddrInfoMsg(const uint8_t* source, const jau::nsize_t length) : SMPPDUMsg(source, length) { + check_range(); checkOpcode(Opcode::IDENTITY_ADDRESS_INFORMATION); } SMPIdentAddrInfoMsg(const bool addrIsStaticRandom, const EUI48 & addr) : SMPPDUMsg(Opcode::IDENTITY_ADDRESS_INFORMATION, 1+1+6) { - pdu.put_uint8_nc(1, addrIsStaticRandom ? 0x01 : 0x00); - pdu.put_eui48_nc(1+1, addr); + pdu.put_uint8(1, addrIsStaticRandom ? 0x01 : 0x00); + pdu.put_eui48(1+1, addr); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1908,12 +1944,13 @@ namespace direct_bt { * since the encryption values are interpreted as little-endian or as a byte stream. * </p> */ - class SMPSignInfoMsg : public SMPEncKeyByteStream + class SMPSignInfoMsg final : public SMPEncKeyByteStream { public: SMPSignInfoMsg(const uint8_t* source, const jau::nsize_t length) : SMPEncKeyByteStream(source, length) { + check_range(); checkOpcode(Opcode::SIGNING_INFORMATION); } @@ -1921,6 +1958,7 @@ namespace direct_bt { : SMPEncKeyByteStream(Opcode::SIGNING_INFORMATION, 1+16) { jau::put_uint128(pdu.get_wptr(), 1, signature_key); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { @@ -1963,22 +2001,24 @@ namespace direct_bt { * Message is used by the slave to request that the master initiates security with the requested security properties,<br> * see Vol 3 (Host), Part H (SM): 2 (SM), 2.4 SECURITY IN BLUETOOTH LOW ENERGY, 2.4.6 Slave Security Request */ - class SMPSecurityReqMsg : public SMPPDUMsg + class SMPSecurityReqMsg final : public SMPPDUMsg { private: SMPAuthReqs authReqMask; public: SMPSecurityReqMsg(const uint8_t* source, const jau::nsize_t length) - : SMPPDUMsg(source, length), + : SMPPDUMsg(source, length, 2), authReqMask(static_cast<SMPAuthReqs>( pdu.get_uint8_nc(1) )) { + check_range(); checkOpcode(Opcode::SECURITY_REQUEST); } SMPSecurityReqMsg(const SMPAuthReqs auth_req_mask) : SMPPDUMsg(Opcode::SECURITY_REQUEST, 1+1), authReqMask(auth_req_mask) { - pdu.put_uint8_nc(1, direct_bt::number(authReqMask)); + pdu.put_uint8(1, direct_bt::number(authReqMask)); + check_range(); } constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override { |