From ec42e11dbc313d770cd628cdc0e0a7c275679255 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 8 Dec 2025 15:19:18 +0200 Subject: [PATCH 01/31] The invalidAttributeType added to enum class Error declaration. --- include/radproto/error.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/radproto/error.h b/include/radproto/error.h index b9c4ef2..1248722 100644 --- a/include/radproto/error.h +++ b/include/radproto/error.h @@ -21,6 +21,7 @@ namespace RadProto eapMessageAttributeError, invalidAttributeCode, invalidAttributeSize, + invalidAttributeType, invalidVendorSpecificAttributeId, suchAttributeNameAlreadyExists, suchAttributeCodeAlreadyExists, From 273e0071e9214462d54c8640ca41e1ec6d831433 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 8 Dec 2025 15:27:33 +0200 Subject: [PATCH 02/31] The enum class ValueType and function make added to the class Attribute declaration. --- include/radproto/attribute.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/radproto/attribute.h b/include/radproto/attribute.h index b00410a..7433cfb 100644 --- a/include/radproto/attribute.h +++ b/include/radproto/attribute.h @@ -16,6 +16,19 @@ namespace RadProto virtual std::string toString() const = 0; virtual std::vector toVector(const std::string& secret, const std::array& auth) const = 0; virtual Attribute* clone() const = 0; + + enum class ValueType : uint8_t + { + String, + Integer, + IpAddress, + Encrypted, + Bytes, + VendorSpecific, + ChapPassword + }; + + static Attribute* make(uint8_t code, const std::string& type, const std::string& data); private: uint8_t m_code; }; From 3710e5963af7c7418cd7cc2dbd8a77f67bfd6034 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 8 Dec 2025 15:33:35 +0200 Subject: [PATCH 03/31] The case Error::invalidAttributeType added to switch in the function message. --- src/error.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/error.cpp b/src/error.cpp index b31d423..651ee74 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -37,6 +37,8 @@ std::string ErrorCategory::message(int ev) const noexcept return "Invalid attribute code"; case Error::invalidAttributeSize: return "Invalid attribute size"; + case Error::invalidAttributeType: + return "Invalid attribute type"; case Error::invalidVendorSpecificAttributeId: return "Invalid Vendor Specific attribute Id"; case Error::suchAttributeNameAlreadyExists: From d7ad025e4e7f56c991abb5f8f1769b5f78bdbe5d Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 8 Dec 2025 16:50:53 +0200 Subject: [PATCH 04/31] Function Attribute::make definition added. --- src/attribute.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/attribute.cpp b/src/attribute.cpp index 043f8af..ab6dfef 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -2,6 +2,7 @@ #include "attribute.h" #include "utils.h" #include "error.h" +#include #include #include #include @@ -12,6 +13,53 @@ Attribute::Attribute(uint8_t code) { } +Attribute* Attribute::make(uint8_t code, const std::string& type, const std::string& data) +{ + ValueType valueType; + if (type == "string") + valueType = ValueType::String; + else if (type == "integer" || "date") + valueType = ValueType::Integer; + else if (type == "ipaddr") + valueType = ValueType::IpAddress; + else if (type == "encrypted") + valueType = ValueType::Encrypted; + else if (type == "octet") + valueType = ValueType::Bytes; + else if (type == "vsa") + valueType = ValueType::VendorSpecific; + else + throw RadProto::Exception(RadProto::Error::invalidAttributeType); + + using tokenizer = boost::tokenizer>; + boost::char_separator sep("."); + + tokenizer tok(data, sep); + size_t i = 0; + switch (valueType) + { + case ValueType::String: + return new String(code, data); + case ValueType::Integer: + return new Integer(code, std::stoul(data)); + case ValueType::IpAddress: + std::array ipAddr; + for (const auto& t : tok) + { + ipAddr[i] = std::stoul(t); + i++; + } + return new IpAddress(code, ipAddr); + case ValueType::Encrypted: + return new Encrypted(code, data); + case ValueType::Bytes: + std::vector bytes; + for (const auto& t : tok) + bytes.push_back(std::stoul(t)); + return new Bytes(code, bytes); + } +} + using String = RadProto::String; String::String(uint8_t code, const uint8_t* data, size_t size) : Attribute(code), From 735836fb7c373959434b79a76868400e44845527 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 10 Dec 2025 16:43:39 +0200 Subject: [PATCH 05/31] The case Error::typeIsNotSupported added to switch in the function message. --- src/error.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/error.cpp b/src/error.cpp index 651ee74..62edca1 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -47,7 +47,9 @@ std::string ErrorCategory::message(int ev) const noexcept return "Such attribute code already exists"; case Error::suchAttributeNameWithAnotherTypeAlreadyExists: return "Such attribute name with another type already exists"; - default: + case Error::typeIsNotSupported: + return "Type 'vsa' is not supported in this class"; + default: return "(Unrecognized error)"; } } From d964a8ea2b9cc7e29ada0e527074040cef1dd697 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 10 Dec 2025 16:51:53 +0200 Subject: [PATCH 06/31] Exception added if type == vsa in the function make. --- src/attribute.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index ab6dfef..ab8c49a 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -27,15 +27,14 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str else if (type == "octet") valueType = ValueType::Bytes; else if (type == "vsa") - valueType = ValueType::VendorSpecific; + throw RadProto::Exception(RadProto::Error::invalidAttributeType); else throw RadProto::Exception(RadProto::Error::invalidAttributeType); using tokenizer = boost::tokenizer>; boost::char_separator sep("."); - tokenizer tok(data, sep); - size_t i = 0; + switch (valueType) { case ValueType::String: @@ -43,20 +42,25 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str case ValueType::Integer: return new Integer(code, std::stoul(data)); case ValueType::IpAddress: + { std::array ipAddr; + size_t i = 0; for (const auto& t : tok) { ipAddr[i] = std::stoul(t); - i++; + ++i; } return new IpAddress(code, ipAddr); + } case ValueType::Encrypted: return new Encrypted(code, data); case ValueType::Bytes: + { std::vector bytes; for (const auto& t : tok) bytes.push_back(std::stoul(t)); return new Bytes(code, bytes); + } } } From 0826ceb95a21e1839c815e0e6a8edbb37abe927f Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 10 Dec 2025 16:55:37 +0200 Subject: [PATCH 07/31] The typeIsNotSupported added to enum class Error declaration. --- include/radproto/error.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/radproto/error.h b/include/radproto/error.h index 1248722..610bb55 100644 --- a/include/radproto/error.h +++ b/include/radproto/error.h @@ -25,7 +25,8 @@ namespace RadProto invalidVendorSpecificAttributeId, suchAttributeNameAlreadyExists, suchAttributeCodeAlreadyExists, - suchAttributeNameWithAnotherTypeAlreadyExists + suchAttributeNameWithAnotherTypeAlreadyExists, + typeIsNotSupported }; class Exception: public std::runtime_error From d500b094f9d0de6f5afc6f44941c7f9f11cb2970 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 16 Dec 2025 13:58:14 +0200 Subject: [PATCH 08/31] The "vsa" check removed in make function make. --- src/attribute.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index ab8c49a..9472948 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -26,8 +26,6 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str valueType = ValueType::Encrypted; else if (type == "octet") valueType = ValueType::Bytes; - else if (type == "vsa") - throw RadProto::Exception(RadProto::Error::invalidAttributeType); else throw RadProto::Exception(RadProto::Error::invalidAttributeType); From 514d485722c1c3a8adba595f6552948b57f226e1 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 17 Dec 2025 14:57:06 +0200 Subject: [PATCH 09/31] The parseValueType function definition and call in the function make added. --- src/attribute.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index 9472948..cf79aa7 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -8,31 +8,37 @@ #include using Attribute = RadProto::Attribute; -Attribute::Attribute(uint8_t code) - : m_code(code) -{ -} +using ValueType = RadProto::Attribute::ValueType; -Attribute* Attribute::make(uint8_t code, const std::string& type, const std::string& data) +ValueType parseValueType(const std::string& type) { - ValueType valueType; if (type == "string") - valueType = ValueType::String; + return ValueType::String; else if (type == "integer" || "date") - valueType = ValueType::Integer; + return ValueType::Integer; else if (type == "ipaddr") - valueType = ValueType::IpAddress; + return ValueType::IpAddress; else if (type == "encrypted") - valueType = ValueType::Encrypted; + return ValueType::Encrypted; else if (type == "octet") - valueType = ValueType::Bytes; + return ValueType::Bytes; else throw RadProto::Exception(RadProto::Error::invalidAttributeType); +} + +Attribute::Attribute(uint8_t code) + : m_code(code) +{ +} +Attribute* Attribute::make(uint8_t code, const std::string& type, const std::string& data) +{ using tokenizer = boost::tokenizer>; boost::char_separator sep("."); tokenizer tok(data, sep); + ValueType valueType = parseValueType(type); + switch (valueType) { case ValueType::String: From 30ed640416e08a0a2db7a9fbf048a8d13f3bf526 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 17 Dec 2025 16:20:38 +0200 Subject: [PATCH 10/31] The variant default added to switch(valueType). --- src/attribute.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/attribute.cpp b/src/attribute.cpp index cf79aa7..c235ecb 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -65,6 +65,8 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str bytes.push_back(std::stoul(t)); return new Bytes(code, bytes); } + default: + throw RadProto::Exception(RadProto::Error::invalidValueTypeMember); } } From 906bdbf49534435d3e829e460db1629a0d15cbaa Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 17 Dec 2025 16:23:54 +0200 Subject: [PATCH 11/31] Case Error::invalidValueTypeMember and error message added to the message function. --- src/error.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/error.cpp b/src/error.cpp index 62edca1..b82a96c 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -39,6 +39,8 @@ std::string ErrorCategory::message(int ev) const noexcept return "Invalid attribute size"; case Error::invalidAttributeType: return "Invalid attribute type"; + case Error::invalidValueTypeMember: + return "Invalid member of type ValueType"; case Error::invalidVendorSpecificAttributeId: return "Invalid Vendor Specific attribute Id"; case Error::suchAttributeNameAlreadyExists: From 353e0daddc4eae329b6a0eb55063631bea84eb8b Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 17 Dec 2025 16:27:26 +0200 Subject: [PATCH 12/31] The element invalidValueTypeMember added to enum class Error. --- include/radproto/error.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/radproto/error.h b/include/radproto/error.h index 610bb55..77e86cb 100644 --- a/include/radproto/error.h +++ b/include/radproto/error.h @@ -22,6 +22,7 @@ namespace RadProto invalidAttributeCode, invalidAttributeSize, invalidAttributeType, + invalidValueTypeMember, invalidVendorSpecificAttributeId, suchAttributeNameAlreadyExists, suchAttributeCodeAlreadyExists, From 4022d0f05a48285b854c0ef9d007d012cefdfbea Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 17 Dec 2025 18:45:53 +0200 Subject: [PATCH 13/31] The check "vsa" added to parseValueType function. --- src/attribute.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/attribute.cpp b/src/attribute.cpp index c235ecb..1c4d561 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -22,6 +22,8 @@ ValueType parseValueType(const std::string& type) return ValueType::Encrypted; else if (type == "octet") return ValueType::Bytes; + else if (type == "vsa") + throw RadProto::Exception(RadProto::Error::typeIsNotSupported); else throw RadProto::Exception(RadProto::Error::invalidAttributeType); } From 51263e85f1401bd59ddc04a5a0f1ed5a804c1953 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 22 Dec 2025 14:16:25 +0200 Subject: [PATCH 14/31] The case Error::invalidValueTypeMember and error message changed in the function message. --- src/error.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/error.cpp b/src/error.cpp index b82a96c..041bd24 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -39,8 +39,8 @@ std::string ErrorCategory::message(int ev) const noexcept return "Invalid attribute size"; case Error::invalidAttributeType: return "Invalid attribute type"; - case Error::invalidValueTypeMember: - return "Invalid member of type ValueType"; + case Error::invalidValueType: + return "Invalid type of enum ValueType"; case Error::invalidVendorSpecificAttributeId: return "Invalid Vendor Specific attribute Id"; case Error::suchAttributeNameAlreadyExists: From 46976a1139b21e8f7ac7eccb84b7c5b065350baf Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 22 Dec 2025 14:40:29 +0200 Subject: [PATCH 15/31] The throw RadProto::Exception(RadProto::Error::invalidAttributeType) changed in parseValueType function. Variant default changed in switch in make function. --- src/attribute.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index 1c4d561..8d83576 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -25,7 +25,7 @@ ValueType parseValueType(const std::string& type) else if (type == "vsa") throw RadProto::Exception(RadProto::Error::typeIsNotSupported); else - throw RadProto::Exception(RadProto::Error::invalidAttributeType); + throw RadProto::Exception(RadProto::Error::invalidValueType); } Attribute::Attribute(uint8_t code) @@ -68,7 +68,7 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str return new Bytes(code, bytes); } default: - throw RadProto::Exception(RadProto::Error::invalidValueTypeMember); + throw RadProto::Exception(RadProto::Error::invalidValueType); } } From 8d6e68f3052783d340dcd5033112273fe9f35209 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 22 Dec 2025 15:31:26 +0200 Subject: [PATCH 16/31] The invalidValueTypeMember changed to invalidValueType in enum class Error. --- include/radproto/error.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/radproto/error.h b/include/radproto/error.h index 77e86cb..5f22a2e 100644 --- a/include/radproto/error.h +++ b/include/radproto/error.h @@ -22,7 +22,7 @@ namespace RadProto invalidAttributeCode, invalidAttributeSize, invalidAttributeType, - invalidValueTypeMember, + invalidValueType, invalidVendorSpecificAttributeId, suchAttributeNameAlreadyExists, suchAttributeCodeAlreadyExists, From 57868eca9583826889572535ea23bdc6718931bf Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Mon, 22 Dec 2025 15:36:36 +0200 Subject: [PATCH 17/31] The parseValueType function declaration added. --- src/attribute.cpp | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index 8d83576..4140297 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -10,23 +10,7 @@ using Attribute = RadProto::Attribute; using ValueType = RadProto::Attribute::ValueType; -ValueType parseValueType(const std::string& type) -{ - if (type == "string") - return ValueType::String; - else if (type == "integer" || "date") - return ValueType::Integer; - else if (type == "ipaddr") - return ValueType::IpAddress; - else if (type == "encrypted") - return ValueType::Encrypted; - else if (type == "octet") - return ValueType::Bytes; - else if (type == "vsa") - throw RadProto::Exception(RadProto::Error::typeIsNotSupported); - else - throw RadProto::Exception(RadProto::Error::invalidValueType); -} +ValueType parseValueType(const std::string& type); Attribute::Attribute(uint8_t code) : m_code(code) @@ -72,6 +56,24 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str } } +ValueType parseValueType(const std::string& type) +{ + if (type == "string") + return ValueType::String; + else if (type == "integer" || "date") + return ValueType::Integer; + else if (type == "ipaddr") + return ValueType::IpAddress; + else if (type == "encrypted") + return ValueType::Encrypted; + else if (type == "octet") + return ValueType::Bytes; + else if (type == "vsa") + throw RadProto::Exception(RadProto::Error::typeIsNotSupported); + else + throw RadProto::Exception(RadProto::Error::invalidValueType); +} + using String = RadProto::String; String::String(uint8_t code, const uint8_t* data, size_t size) : Attribute(code), From 29e7b8b7f2581de5a5bda4b99df1b8851f688dc4 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 23 Dec 2025 15:07:45 +0200 Subject: [PATCH 18/31] The enum class ValueType added, using ValueType removed. --- src/attribute.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index 4140297..3b5630c 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -8,7 +8,17 @@ #include using Attribute = RadProto::Attribute; -using ValueType = RadProto::Attribute::ValueType; + +enum class ValueType : uint8_t + { + String, + Integer, + IpAddress, + Encrypted, + Bytes, + VendorSpecific, + ChapPassword + }; ValueType parseValueType(const std::string& type); From fa61b6d9e592a5e97896e9fecbe00c252d6e08f5 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 23 Dec 2025 15:12:54 +0200 Subject: [PATCH 19/31] The enum class ValueType removed. --- include/radproto/attribute.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/include/radproto/attribute.h b/include/radproto/attribute.h index 7433cfb..9934d19 100644 --- a/include/radproto/attribute.h +++ b/include/radproto/attribute.h @@ -16,18 +16,6 @@ namespace RadProto virtual std::string toString() const = 0; virtual std::vector toVector(const std::string& secret, const std::array& auth) const = 0; virtual Attribute* clone() const = 0; - - enum class ValueType : uint8_t - { - String, - Integer, - IpAddress, - Encrypted, - Bytes, - VendorSpecific, - ChapPassword - }; - static Attribute* make(uint8_t code, const std::string& type, const std::string& data); private: uint8_t m_code; From 2d1b0ffc9a7fa77cbb2683a46f25860228b9a5ad Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 24 Dec 2025 15:12:39 +0200 Subject: [PATCH 20/31] The parseValueType function and enum class ValueType moved to anonymous namespace. --- src/attribute.cpp | 61 ++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index 3b5630c..314280e 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -8,19 +8,37 @@ #include using Attribute = RadProto::Attribute; - -enum class ValueType : uint8_t - { - String, - Integer, - IpAddress, - Encrypted, - Bytes, - VendorSpecific, - ChapPassword - }; - -ValueType parseValueType(const std::string& type); +namespace +{ + enum class ValueType : uint8_t + { + String, + Integer, + IpAddress, + Encrypted, + Bytes, + VendorSpecific, + ChapPassword + }; + + ValueType parseValueType(const std::string& type) + { + if (type == "string") + return ValueType::String; + else if (type == "integer" || "date") + return ValueType::Integer; + else if (type == "ipaddr") + return ValueType::IpAddress; + else if (type == "encrypted") + return ValueType::Encrypted; + else if (type == "octet") + return ValueType::Bytes; + else if (type == "vsa") + throw RadProto::Exception(RadProto::Error::typeIsNotSupported); + else + throw RadProto::Exception(RadProto::Error::invalidValueType); + } +} Attribute::Attribute(uint8_t code) : m_code(code) @@ -66,23 +84,6 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str } } -ValueType parseValueType(const std::string& type) -{ - if (type == "string") - return ValueType::String; - else if (type == "integer" || "date") - return ValueType::Integer; - else if (type == "ipaddr") - return ValueType::IpAddress; - else if (type == "encrypted") - return ValueType::Encrypted; - else if (type == "octet") - return ValueType::Bytes; - else if (type == "vsa") - throw RadProto::Exception(RadProto::Error::typeIsNotSupported); - else - throw RadProto::Exception(RadProto::Error::invalidValueType); -} using String = RadProto::String; String::String(uint8_t code, const uint8_t* data, size_t size) From 9b4966c805505bf22ea6b9476c34b74a7f0a6ad2 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 14:29:36 +0200 Subject: [PATCH 21/31] The invalidHexStringLength added to enum class Error. --- include/radproto/error.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/radproto/error.h b/include/radproto/error.h index 5f22a2e..affb4f9 100644 --- a/include/radproto/error.h +++ b/include/radproto/error.h @@ -27,7 +27,8 @@ namespace RadProto suchAttributeNameAlreadyExists, suchAttributeCodeAlreadyExists, suchAttributeNameWithAnotherTypeAlreadyExists, - typeIsNotSupported + typeIsNotSupported, + invalidHexStringLength }; class Exception: public std::runtime_error From c3826f25d95437ada6b7d4a8904561770f4e2356 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 14:32:55 +0200 Subject: [PATCH 22/31] The case Error::invalidHexStringLength added in the function message. --- src/error.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/error.cpp b/src/error.cpp index 041bd24..5720916 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -51,6 +51,8 @@ std::string ErrorCategory::message(int ev) const noexcept return "Such attribute name with another type already exists"; case Error::typeIsNotSupported: return "Type 'vsa' is not supported in this class"; + case Error::invalidHexStringLength: + return "Invalid length of hex string"; default: return "(Unrecognized error)"; } From d814d7336a9f83d62ab31b9879eb78fe85bba1e5 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 14:44:22 +0200 Subject: [PATCH 23/31] The header file removed, function parseValueType fixed. The case ValueType::IpAddress and case ValueType Bytes changed in the function make. --- src/attribute.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/attribute.cpp b/src/attribute.cpp index 314280e..6126a0d 100644 --- a/src/attribute.cpp +++ b/src/attribute.cpp @@ -5,7 +5,6 @@ #include #include #include -#include using Attribute = RadProto::Attribute; namespace @@ -25,13 +24,13 @@ namespace { if (type == "string") return ValueType::String; - else if (type == "integer" || "date") + else if (type == "integer" || type == "date") return ValueType::Integer; else if (type == "ipaddr") return ValueType::IpAddress; else if (type == "encrypted") return ValueType::Encrypted; - else if (type == "octet") + else if (type == "octets") return ValueType::Bytes; else if (type == "vsa") throw RadProto::Exception(RadProto::Error::typeIsNotSupported); @@ -47,10 +46,6 @@ Attribute::Attribute(uint8_t code) Attribute* Attribute::make(uint8_t code, const std::string& type, const std::string& data) { - using tokenizer = boost::tokenizer>; - boost::char_separator sep("."); - tokenizer tok(data, sep); - ValueType valueType = parseValueType(type); switch (valueType) @@ -59,24 +54,35 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str return new String(code, data); case ValueType::Integer: return new Integer(code, std::stoul(data)); + case ValueType::Encrypted: + return new Encrypted(code, data); case ValueType::IpAddress: { + using tokenizer = boost::tokenizer>; + boost::char_separator sep("."); + tokenizer tok(data, sep); + std::array ipAddr; size_t i = 0; for (const auto& t : tok) { - ipAddr[i] = std::stoul(t); + ipAddr[i] = static_cast(std::stoul(t)); ++i; } return new IpAddress(code, ipAddr); } - case ValueType::Encrypted: - return new Encrypted(code, data); case ValueType::Bytes: { + if (data.length() % 2 != 0) + throw RadProto::Exception(RadProto::Error::invalidHexStringLength); + std::vector bytes; - for (const auto& t : tok) - bytes.push_back(std::stoul(t)); + + for (size_t i = 0; i < data.length(); i += 2) + { + auto byte = static_cast(std::stoi(data.substr(i, 2), nullptr, 16)); + bytes.push_back(byte); + } return new Bytes(code, bytes); } default: @@ -84,7 +90,6 @@ Attribute* Attribute::make(uint8_t code, const std::string& type, const std::str } } - using String = RadProto::String; String::String(uint8_t code, const uint8_t* data, size_t size) : Attribute(code), From 8f32fec60e0dcf4eca8d1fdcd5072389467d1465 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 15:34:36 +0200 Subject: [PATCH 24/31] The test suite AttributeMakeTests added. --- tests/attribute_tests.cpp | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index b929788..cf0b4be 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -19,6 +19,58 @@ BOOST_AUTO_TEST_SUITE(AttributeTests) +BOOST_AUTO_TEST_SUITE(AttributeMakeTests) + +BOOST_AUTO_TEST_CASE(TypeStringTest) +{ + RadProto::Attribute* attribute = RadProto::Attribute::make(1, "string", "User"); + RadProto::String* str = dynamic_cast(attribute); + + BOOST_REQUIRE(str); +} + +BOOST_AUTO_TEST_CASE(TypeIntegerTest) +{ + RadProto::Attribute* attribute = RadProto::Attribute::make(5, "integer", "123456"); + RadProto::Integer* intg = dynamic_cast(attribute); + + BOOST_REQUIRE(intg); +} + +BOOST_AUTO_TEST_CASE(TypeDateToIntegerTest) +{ + RadProto::Attribute* attribute = RadProto::Attribute::make(75, "date", "123456"); + RadProto::Integer* intg = dynamic_cast(attribute); + + BOOST_REQUIRE(intg); +} + +BOOST_AUTO_TEST_CASE(TypeIpaddrTest) +{ + RadProto::Attribute* attribute = RadProto::Attribute::make(4, "ipaddr", "127.104.22.17"); + RadProto::IpAddress* ipadr = dynamic_cast(attribute); + + BOOST_REQUIRE(ipadr); +} + +BOOST_AUTO_TEST_CASE(TypeEncryptedTest) +{ + RadProto::Attribute* attribute = RadProto::Attribute::make(2, "encrypted", "123456"); + RadProto::Encrypted* encrypt = dynamic_cast(attribute); + + BOOST_REQUIRE(encrypt); +} + +BOOST_AUTO_TEST_CASE(TypeOctetsTest) +{ + RadProto::Attribute* attribute = RadProto::Attribute::make(3, "octets", "313233616263"); + RadProto::Bytes* bts = dynamic_cast(attribute); + + BOOST_REQUIRE(bts); +} + +BOOST_AUTO_TEST_SUITE_END() + BOOST_AUTO_TEST_CASE(StringDataConstructor) { std::vector d {'t', 'e', 's', 't'}; From 1319b720cc4a5a9a2b60979c9fe5b120efb30ce8 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 15:56:35 +0200 Subject: [PATCH 25/31] The tests for methods of class String added to test case TypeStringTest. --- tests/attribute_tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index cf0b4be..01b152b 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -27,6 +27,15 @@ BOOST_AUTO_TEST_CASE(TypeStringTest) RadProto::String* str = dynamic_cast(attribute); BOOST_REQUIRE(str); + + BOOST_CHECK_EQUAL(str->toString(), "User"); + + std::vector values = str->toVector({}, {}); + std::vector expected {1, 6, 'U', 's', 'e', 'r'}; + + BOOST_TEST(values == expected, boost::test_tools::per_element()); + + BOOST_CHECK_EQUAL(str->code(), 1); } BOOST_AUTO_TEST_CASE(TypeIntegerTest) From c8f3c1e89d16b1d35916f32e79c6848084869840 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 18:35:32 +0200 Subject: [PATCH 26/31] The tests for methods of class Integer added to test case TypeIntegerTest. --- tests/attribute_tests.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index 01b152b..ad9e9f0 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -40,10 +40,19 @@ BOOST_AUTO_TEST_CASE(TypeStringTest) BOOST_AUTO_TEST_CASE(TypeIntegerTest) { - RadProto::Attribute* attribute = RadProto::Attribute::make(5, "integer", "123456"); + RadProto::Attribute* attribute = RadProto::Attribute::make(5, "integer", "169090600"); RadProto::Integer* intg = dynamic_cast(attribute); BOOST_REQUIRE(intg); + + BOOST_CHECK_EQUAL(intg->toString(), "169090600"); + + std::vector values = intg->toVector({}, {}); + std::vector expected {5, 6, 10, 20, 30, 40}; + + BOOST_TEST(values == expected, boost::test_tools::per_element()); + + BOOST_CHECK_EQUAL(intg->code(), 5); } BOOST_AUTO_TEST_CASE(TypeDateToIntegerTest) From e96a9bd67981a56596f1cd1bc95cd9016fd3abca Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 18:40:21 +0200 Subject: [PATCH 27/31] The names of case changed in test suite AttributeMakeTests. --- tests/attribute_tests.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index ad9e9f0..1110b56 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -21,7 +21,7 @@ BOOST_AUTO_TEST_SUITE(AttributeTests) BOOST_AUTO_TEST_SUITE(AttributeMakeTests) -BOOST_AUTO_TEST_CASE(TypeStringTest) +BOOST_AUTO_TEST_CASE(TypeString) { RadProto::Attribute* attribute = RadProto::Attribute::make(1, "string", "User"); RadProto::String* str = dynamic_cast(attribute); @@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(TypeStringTest) BOOST_CHECK_EQUAL(str->code(), 1); } -BOOST_AUTO_TEST_CASE(TypeIntegerTest) +BOOST_AUTO_TEST_CASE(TypeInteger) { RadProto::Attribute* attribute = RadProto::Attribute::make(5, "integer", "169090600"); RadProto::Integer* intg = dynamic_cast(attribute); @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(TypeIntegerTest) BOOST_CHECK_EQUAL(intg->code(), 5); } -BOOST_AUTO_TEST_CASE(TypeDateToIntegerTest) +BOOST_AUTO_TEST_CASE(TypeDateToInteger) { RadProto::Attribute* attribute = RadProto::Attribute::make(75, "date", "123456"); RadProto::Integer* intg = dynamic_cast(attribute); @@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(TypeDateToIntegerTest) BOOST_REQUIRE(intg); } -BOOST_AUTO_TEST_CASE(TypeIpaddrTest) +BOOST_AUTO_TEST_CASE(TypeIpaddr) { RadProto::Attribute* attribute = RadProto::Attribute::make(4, "ipaddr", "127.104.22.17"); RadProto::IpAddress* ipadr = dynamic_cast(attribute); @@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(TypeIpaddrTest) BOOST_REQUIRE(ipadr); } -BOOST_AUTO_TEST_CASE(TypeEncryptedTest) +BOOST_AUTO_TEST_CASE(TypeEncrypted) { RadProto::Attribute* attribute = RadProto::Attribute::make(2, "encrypted", "123456"); RadProto::Encrypted* encrypt = dynamic_cast(attribute); @@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(TypeEncryptedTest) BOOST_REQUIRE(encrypt); } -BOOST_AUTO_TEST_CASE(TypeOctetsTest) +BOOST_AUTO_TEST_CASE(TypeOctets) { RadProto::Attribute* attribute = RadProto::Attribute::make(3, "octets", "313233616263"); RadProto::Bytes* bts = dynamic_cast(attribute); From 170c19461fc6473a3df83522a24e861fff34d25d Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Tue, 13 Jan 2026 18:47:18 +0200 Subject: [PATCH 28/31] The tests for methods of class Integer added to test case TypeDateInteger. --- tests/attribute_tests.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index 1110b56..61ee5bb 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -57,10 +57,19 @@ BOOST_AUTO_TEST_CASE(TypeInteger) BOOST_AUTO_TEST_CASE(TypeDateToInteger) { - RadProto::Attribute* attribute = RadProto::Attribute::make(75, "date", "123456"); + RadProto::Attribute* attribute = RadProto::Attribute::make(75, "date", "169090600"); RadProto::Integer* intg = dynamic_cast(attribute); BOOST_REQUIRE(intg); + + BOOST_CHECK_EQUAL(intg->toString(), "169090600"); + + std::vector values = intg->toVector({}, {}); + std::vector expected {75, 6, 10, 20, 30, 40}; + + BOOST_TEST(values == expected, boost::test_tools::per_element()); + + BOOST_CHECK_EQUAL(intg->code(), 75); } BOOST_AUTO_TEST_CASE(TypeIpaddr) From 31dbc9c71b944ab42389bae46301f3679931b41a Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 14 Jan 2026 13:49:16 +0200 Subject: [PATCH 29/31] The tests for methods of class IpAddress added to test case TypeIpaddr. --- tests/attribute_tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index 61ee5bb..b948d22 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -78,6 +78,15 @@ BOOST_AUTO_TEST_CASE(TypeIpaddr) RadProto::IpAddress* ipadr = dynamic_cast(attribute); BOOST_REQUIRE(ipadr); + + BOOST_CHECK_EQUAL(ipadr->toString(), "127.104.22.17"); + + std::vector values = ipadr->toVector({}, {}); + std::vector expected {4, 6, 127, 104, 22, 17}; + + BOOST_TEST(values == expected, boost::test_tools::per_element()); + + BOOST_CHECK_EQUAL(ipadr->code(), 4); } BOOST_AUTO_TEST_CASE(TypeEncrypted) From ef898c169233495596f3f759724ded5af4b3a901 Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 14 Jan 2026 14:12:17 +0200 Subject: [PATCH 30/31] The tests for methods of class Encrypted added to test case TypeEncrypted. --- tests/attribute_tests.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index b948d22..07d9b50 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -95,6 +95,16 @@ BOOST_AUTO_TEST_CASE(TypeEncrypted) RadProto::Encrypted* encrypt = dynamic_cast(attribute); BOOST_REQUIRE(encrypt); + + BOOST_CHECK_EQUAL(encrypt->toString(), "123456"); + + std::array auth {0x92, 0xfa, 0xa1, 0xed, 0x98, 0x9b, 0xb4, 0x79, 0xfe, 0x20, 0xe2, 0xf4, 0x7f, 0x4a, 0x5a, 0x70}; + std::vector values = encrypt->toVector("secret", auth); + std::vector expected {0x02, 0x12, 0x25, 0x38, 0x58, 0x18, 0xae, 0x97, 0xeb, 0xeb, 0xbd, 0x46, 0xfd, 0xb9, 0xd1, 0x17, 0x84, 0xeb}; + + BOOST_TEST(values == expected, boost::test_tools::per_element()); + + BOOST_CHECK_EQUAL(encrypt->code(), 2); } BOOST_AUTO_TEST_CASE(TypeOctets) From de0f9afca367b6d5f93a010041b8812142b0afee Mon Sep 17 00:00:00 2001 From: Elena Mamontova Date: Wed, 14 Jan 2026 14:27:29 +0200 Subject: [PATCH 31/31] The tests for methods of class Bytes added to test case TypeOctets. --- tests/attribute_tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/attribute_tests.cpp b/tests/attribute_tests.cpp index 07d9b50..db00861 100644 --- a/tests/attribute_tests.cpp +++ b/tests/attribute_tests.cpp @@ -113,6 +113,15 @@ BOOST_AUTO_TEST_CASE(TypeOctets) RadProto::Bytes* bts = dynamic_cast(attribute); BOOST_REQUIRE(bts); + + BOOST_CHECK_EQUAL(bts->toString(), "313233616263"); + + std::vector values = bts->toVector({}, {}); + std::vector expected({3, 8, '1', '2', '3', 'a', 'b', 'c'}); + + BOOST_TEST(values == expected, boost::test_tools::per_element()); + + BOOST_CHECK_EQUAL(bts->code(), 3); } BOOST_AUTO_TEST_SUITE_END()