/* * Copyright (c) 2017-2019 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include namespace transport { namespace core { Name::Name() { name_ = createEmptyName(); } Name::Name(int family, const uint8_t *ip_address, std::uint32_t suffix) : name_(createEmptyName()) { std::size_t length; uint8_t *dst = NULL; if (family == AF_INET) { dst = name_->ip4.prefix_as_u8; length = IPV4_ADDR_LEN; name_->type = HNT_CONTIGUOUS_V4; } else if (family == AF_INET6) { dst = name_->ip6.prefix_as_u8; length = IPV6_ADDR_LEN; name_->type = HNT_CONTIGUOUS_V6; } else { throw errors::RuntimeException("Specified name family does not exist."); } std::memcpy(dst, ip_address, length); *reinterpret_cast(dst + length) = suffix; } Name::Name(const char *name, uint32_t segment) { name_ = createEmptyName(); if (hicn_name_create(name, segment, name_.get()) < 0) { throw errors::InvalidIpAddressException(); } } Name::Name(const std::string &uri, uint32_t segment) : Name(uri.c_str(), segment) {} Name::Name(const std::string &uri) { utils::StringTokenizer tokenizer(uri, "|"); std::string ip_address; std::string seq_number; ip_address = tokenizer.nextToken(); try { seq_number = tokenizer.nextToken(); } catch (errors::TokenizerException &) { seq_number = "0"; } name_ = createEmptyName(); if (hicn_name_create(ip_address.c_str(), (uint32_t)atoi(seq_number.c_str()), name_.get()) < 0) { throw errors::InvalidIpAddressException(); } } Name::Name(const Name &name, bool hard_copy) { name_ = createEmptyName(); if (hard_copy) { if (hicn_name_copy(this->name_.get(), name.name_.get()) < 0) { throw errors::MalformedNameException(); } } else { *this->name_ = *name.name_; } } Name::Name(Name &&name) : name_(std::move(name.name_)) {} Name &Name::operator=(const Name &name) { if (hicn_name_copy(this->name_.get(), name.name_.get()) < 0) { throw errors::MalformedNameException(); } return *this; } bool Name::operator==(const Name &name) const { return this->equals(name, true); } bool Name::operator!=(const Name &name) const { return !this->operator==(name); } Name::operator bool() const { return bool(hicn_name_empty((hicn_name_t *)name_.get())); } bool Name::equals(const Name &name, bool consider_segment) const { return !hicn_name_compare(name_.get(), name.name_.get(), consider_segment); } std::string Name::toString() const { char *name = new char[100]; int ret = hicn_name_ntop(name_.get(), name, standard_name_string_length); if (ret < 0) { throw errors::MalformedNameException(); } std::string name_string(name); delete[] name; return name_string; } uint32_t Name::getHash32() const { uint32_t hash; if (hicn_name_hash((hicn_name_t *)name_.get(), &hash) < 0) { throw errors::RuntimeException("Error computing the hash of the name!"); } return hash; } void Name::clear() { name_.reset(); name_ = createEmptyName(); }; Name::Type Name::getType() const { return name_->type; } uint32_t Name::getSuffix() const { uint32_t ret = 0; if (hicn_name_get_seq_number((hicn_name_t *)name_.get(), &ret) < 0) { throw errors::RuntimeException( "Impossible to retrieve the sequence number from the name."); } return ret; } Name &Name::setSuffix(uint32_t seq_number) { if (hicn_name_set_seq_number(name_.get(), seq_number) < 0) { throw errors::RuntimeException( "Impossible to set the sequence number to the name."); } return *this; } std::shared_ptr Name::getAddress() const { Sockaddr *ret = nullptr; switch (name_->type) { case HNT_CONTIGUOUS_V4: case HNT_IOV_V4: ret = (Sockaddr *)new Sockaddr4; break; case HNT_CONTIGUOUS_V6: case HNT_IOV_V6: ret = (Sockaddr *)new Sockaddr6; break; default: throw errors::MalformedNameException(); } if (hicn_name_to_sockaddr_address((hicn_name_t *)name_.get(), ret) < 0) { throw errors::MalformedNameException(); } return std::shared_ptr(ret); } ip_address_t Name::toIpAddress() const { ip_address_t ret; std::memset(&ret, 0, sizeof(ret)); if (hicn_name_to_ip_address(name_.get(), &ret) < 0) { throw errors::InvalidIpAddressException(); } return ret; } int Name::getAddressFamily() const { int ret = 0; if (hicn_name_get_family(name_.get(), &ret) < 0) { throw errors::InvalidIpAddressException(); } return ret; } void Name::copyToDestination(uint8_t *destination, bool include_suffix) const { if (hicn_name_copy_to_destination(destination, name_.get(), include_suffix) < 0) { throw errors::RuntimeException( "Impossibe to copy the name into the " "provided destination"); } } std::ostream &operator<<(std::ostream &os, const Name &name) { const std::string &str = name.toString(); // os << "core:/"; os << str; return os; } } // end namespace core } // end namespace transport namespace std { size_t hash::operator()( const transport::core::Name &name) const { return name.getHash32(); } } // end namespace std