Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make UAuthority store binary IP addresses, update tests, and address bugs found along the way #73

Merged
80 changes: 40 additions & 40 deletions include/up-cpp/uri/builder/BuildUAuthority.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*

* Copyright (c) 2024 General Motors GTO LLC
*
* Licensed to the Apache Software Foundation (ASF) under one
Expand All @@ -18,12 +18,12 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* SPDX-FileType: SOURCE
* SPDX-FileCopyrightText: 2024 General Motors GTO LLC
* SPDX-License-Identifier: Apache-2.0


*/

#ifndef UPROTOCOL_CPP_BUILDUAUTHORITY_H
Expand All @@ -37,6 +37,7 @@
#include <string_view>
#include <arpa/inet.h>
#include <spdlog/spdlog.h>
#include "../tools/IpAddress.h"
#include "../tools/Utils.h"
#include "up-core-api/uri.pb.h"

Expand All @@ -45,7 +46,7 @@ namespace uprotocol::uri {
uprotocol::v1::UAuthority authority_;
gregmedd marked this conversation as resolved.
Show resolved Hide resolved
public:
BuildUAuthority() { authority_.Clear(); }
gregmedd marked this conversation as resolved.
Show resolved Hide resolved

/**
* set name of the authority. if name is empty or blank, an error will be logged and the name will not be set
* if name is already set, it will not be changed
Expand All @@ -54,11 +55,11 @@ namespace uprotocol::uri {
*/
auto setName(const std::string &name) -> BuildUAuthority & {
if (authority_.has_name() && !authority_.name().empty()) {
spdlog::error("UAutority already has a remote set. Ignoring setName()");
spdlog::error("UAuthority already has a remote set. Ignoring setName()");
return *this;
}
if (isBlank(name)) {
spdlog::error("UAutority name is blank. Ignoring setName()");
spdlog::error("UAuthority name is blank. Ignoring setName()");
return *this;
} else {
auto tmp = name;
Expand All @@ -74,15 +75,15 @@ namespace uprotocol::uri {
* if name is already set, it will not be changed
* @param device std::string
* @param domain std::string
* @return
* @return
*/
auto setName(const std::string &device, const std::string &domain) -> BuildUAuthority & {
if (authority_.has_name() && !authority_.name().empty()) {
spdlog::error("UAutority already has a name {} set. Ignoring setName()", authority_.name());
spdlog::error("UAuthority already has a name {} set. Ignoring setName()", authority_.name());
return *this;
}
if (isBlank(device) && isBlank(domain)) {
spdlog::error("UAutority device or domain is blank. Ignoring setName()");
spdlog::error("UAuthority device or domain is blank. Ignoring setName()");
return *this;
}
if (isBlank(device)) {
Expand All @@ -95,54 +96,53 @@ namespace uprotocol::uri {
setName(device + "." + domain);
return *this;
}

/**
* set authority IP address. if address is empty or blank, an error will be logged and the address will not be set
* wrong IP address format will be ignored
* @param address std::string
* @return
* @return
*/
auto setIp(const std::string &address) -> BuildUAuthority & {
return setIp(IpAddress(address));
}

/**
* set authority IP address. if address is empty or blank, an error will be logged and the address will not be set
* wrong IP address format will be ignored
* @param address IpAddress
* @return
*/
auto setIp(const IpAddress &address) -> BuildUAuthority & {
if (authority_.has_ip() && !authority_.ip().empty()) {
spdlog::error("UAutority already has ip set {}. Ignoring setIp()", authority_.ip());
spdlog::error("UAuthority already has ip set {}. Ignoring setIp()", authority_.ip());
return *this;
}
std::string m_address = isBlank(address) ? "" : address;

char ip_char[INET6_ADDRSTRLEN + 1];
memset(ip_char, 0, INET6_ADDRSTRLEN + 1);
if (in6_addr ipv6{}; inet_pton(AF_INET6, m_address.c_str(), &ipv6) == 1) {
if (inet_ntop(AF_INET6,
&ipv6,
ip_char,
INET6_ADDRSTRLEN) != nullptr) {
authority_.set_ip(ip_char);
}
} else if (struct in_addr ipv4{}; inet_pton(AF_INET, m_address.c_str(), &ipv4) == 1) {
if (inet_ntop(AF_INET,
&ipv4,
ip_char,
INET_ADDRSTRLEN) != nullptr) {
authority_.set_ip(ip_char);
} else {
spdlog::error<std::string_view>("UAutority address is not a valid IPV4 address. Ignoring setIp()");
return *this;
}
} else {
spdlog::error<std::string_view>("UAutority address is not a valid IP address. Ignoring setIp()");

if (address.getType() == IpAddress::Type::Invalid) {
spdlog::error<std::string_view>("UAuthority address is not a valid IP address. Ignoring setIp()");
// Note: setting an empty string here will allow the micro
// serializer to detect that something was wrong instead
// of thinking it has been asked to serialize a Local
// authority.
authority_.set_ip("");
return *this;
}

authority_.set_ip(address.getBytesString());

return *this;
}

auto setId(const std::string &id) -> BuildUAuthority & {
gregmedd marked this conversation as resolved.
Show resolved Hide resolved
if (authority_.has_id() && !authority_.id().empty()) {
spdlog::error("UAutority already has a id set {}. Ignoring setId()", authority_.id());
spdlog::error("UAuthority already has a id set {}. Ignoring setId()", authority_.id());
return *this;
}
authority_.set_id(id.c_str());
authority_.set_id(id);
return *this;
}

auto build() const -> uprotocol::v1::UAuthority {
return authority_;
}
Expand Down
18 changes: 7 additions & 11 deletions include/up-cpp/uri/builder/BuildUUri.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,12 @@ namespace uprotocol::uri {
* @return
*/
auto setAutority(uprotocol::v1::UAuthority const &authority) -> BuildUUri & {
if (uri_.has_authority()) {
if (uri_.has_authority() && !isEmpty(uri_.authority())) {
spdlog::error("UUri already has a authority set. Ignoring setAuthority()");
return *this;
}

if (!isEmpty(authority)) {
uri_.mutable_authority()->CopyFrom(authority);
}
uri_.mutable_authority()->CopyFrom(authority);
return *this;
}
/**
Expand All @@ -72,9 +70,8 @@ namespace uprotocol::uri {
spdlog::error("UUri already has a entity set. Ignoring setEntity()");
return *this;
}
if (!isEmpty(entity)) {
uri_.mutable_entity()->CopyFrom(entity);
}

gregmedd marked this conversation as resolved.
Show resolved Hide resolved
uri_.mutable_entity()->CopyFrom(entity);
return *this;
}
/**
Expand All @@ -83,13 +80,12 @@ namespace uprotocol::uri {
* @return
*/
auto setResource(uprotocol::v1::UResource const &resource) -> BuildUUri & {
if (uri_.has_resource()) {
if (uri_.has_resource() && !isEmpty(uri_.resource())) {
spdlog::error("UUri already has a resource set. Ignoring setResource()");
return *this;
}
if (!isEmpty(resource)) {
uri_.mutable_resource()->CopyFrom(resource);
}

gregmedd marked this conversation as resolved.
Show resolved Hide resolved
uri_.mutable_resource()->CopyFrom(resource);
return *this;
}
/**
Expand Down
90 changes: 58 additions & 32 deletions include/up-cpp/uri/serializer/MicroUriSerializer.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 General Motors GTO LLC
* Copyright (c) 2024 General Motors GTO LLC
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
Expand All @@ -19,7 +19,7 @@
* under the License.
*
* SPDX-FileType: SOURCE
* SPDX-FileCopyrightText: 2023 General Motors GTO LLC
* SPDX-FileCopyrightText: 2024 General Motors GTO LLC
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef MICRO_URI_SERIALIZER_H_
Expand All @@ -29,12 +29,18 @@
#include <up-cpp/uri/builder/BuildUAuthority.h>
#include <up-cpp/uri/builder/BuildEntity.h>
#include <up-cpp/uri/builder/BuildUResource.h>
#include "up-cpp/uri/serializer/IpAddress.h"

using AddressType = uprotocol::uri::IpAddress::AddressType;
#include "up-cpp/uri/tools/IpAddress.h"

namespace uprotocol::uri {

enum class AuthorityType : uint8_t {
Local = 0,
IpV4,
IpV6,
Id,
Invalid
};

/**
* UUri Serializer that serializes a UUri to a vector<uint8_t> (micro format) per
* <a href="https://github.com/eclipse-uprotocol/uprotocol-spec/blob/main/basics/uri.adoc">...</a>
Expand All @@ -50,67 +56,91 @@ class MicroUriSerializer {

/**
* Deserialize a vector<uint8_t> into a UUri object.
* @param microUri A vector<uint8_t> uProtocol micro URI.
* @return Returns an UUri data object from the serialized format of a microUri.
* @param micro_uri A vector<uint8_t> uProtocol micro URI.
* @return Returns an UUri data object from the serialized format of a micro URI.
*/
[[nodiscard]] static auto deserialize(std::vector<uint8_t> const& addr) -> uprotocol::v1::UUri;
[[nodiscard]] static auto deserialize(std::vector<uint8_t> const& micro_uri) -> uprotocol::v1::UUri;

private:
/**
* Default MicroUriSerializer constructor.
*/
MicroUriSerializer() = default;
/**
* find the address type enum
* Deserialize an AuthorityType from uint8_t
* @param type
* @return std::optional<AddressType> std::nullopt if not found and AddressType if foundddr
* @return AuthorityType, with AuthorityType::Invalid indicating an unsupported type
*/
[[nodiscard]] static auto getAddressType(uint8_t type) -> std::optional<AddressType>;
[[nodiscard]] static auto getAuthorityType(uint8_t type) -> AuthorityType;
/**
* Check that the micro URI size fit the definitions
* @param size
* @param address_type
* @param type
* @return
*/
[[nodiscard]] static auto checkMicroUriSize(std::size_t size, AddressType address_type) -> bool;
[[nodiscard]] static auto checkMicroUriSize(std::size_t size, AuthorityType type) -> bool;
/**
* Get UAthority from the address and type
* @param addr
* @param type
* @return uprotocol::v1::UAuthority if address is not valid UAuthority return empty
*/
[[nodiscard]] static auto getUauthority(const std::vector<uint8_t> &addr, AddressType type) -> uprotocol::v1::UAuthority;
[[nodiscard]] static auto getUauthority(const std::vector<uint8_t> &addr, AuthorityType type) -> uprotocol::v1::UAuthority;
/**
* Debug function to print the ip address
* @param ip
* @return
*/
[[maybe_unused]] static auto printIp(std::vector<uint8_t> ip);

/**
* Add the ip address to the micro URI
* @param u_uri vector of uint8_t representing the micro URI
* @param uri uprotocol::v1::UUri
* @param address String of the ip address or the ID
* The length of the micro URI header.
*/
[[maybe_unused]] static auto addIpOrId(const uprotocol::v1::UUri &u_uri, std::vector<uint8_t> &uri, std::string &address) -> void;

static constexpr uint32_t MicroUriHeaderLength = 8;
/**
* The length of a local micro URI.
*/
static constexpr uint32_t LocalMicroUriLength = 8;
* The length of a local micro URI.
*/
static constexpr uint32_t LocalMicroUriLength = MicroUriHeaderLength;
/**
* The length of a IPv4 micro URI.
*/
static constexpr uint32_t IpV4MicroUriLength = 12;
static constexpr uint32_t IpV4MicroUriLength =
MicroUriHeaderLength + IpAddress::IpV4AddressBytes;
/**
* The length of a IPv6 micro URI.
*/
static constexpr uint32_t IpV6MicroUriLength = 24;
static constexpr uint32_t IpV6MicroUriLength =
MicroUriHeaderLength + IpAddress::IpV6AddressBytes;
/**
* the length of the ID length field in the micro URI.
*/
static constexpr uint8_t UAuthorityIdLenSize = 1;
/**
* Starting position of the IP address in the micro URI.
* the min size of id string in the micro URI.
*/
static constexpr uint8_t UAuthorityIdMinLength = 1;
/**
* the max size of id string in the micro URI.
*/
static constexpr uint8_t IpaddressStartPosition = LocalMicroUriLength;
static constexpr uint8_t UAuthorityIdMaxLength = 255;
/**
* The minimum length of an ID micro URI.
*/
static constexpr uint32_t IdMicroUriMinLength =
MicroUriHeaderLength + UAuthorityIdLenSize + UAuthorityIdMinLength;
/**
* The maximum length of an ID micro URI.
*/
static constexpr uint32_t IdMicroUriMaxLength =
MicroUriHeaderLength + UAuthorityIdLenSize + UAuthorityIdMaxLength;
/**
* Starting position of the Authority in the micro URI.
*/
static constexpr uint8_t AuthorityStartPosition = LocalMicroUriLength;
/**
* Position of the ID_LEN field in ID micro URIs.
*/
static constexpr uint8_t IdLengthPosition = AuthorityStartPosition;
/**
* Starting position of the entity id in the micro URI.
*/
Expand All @@ -123,10 +153,6 @@ class MicroUriSerializer {
* UE version position in the micro URI.
*/
static constexpr uint8_t UeVersionPosition = EntityIdStartPosition + 2;
/**
* the max size of id string in the micro URI.
*/
static constexpr uint8_t UAutorityIdMaxLength = 255;
/**
* The version of the UProtocol.
*/
Expand Down
Loading