diff options
Diffstat (limited to 'libtransport/includes')
54 files changed, 2218 insertions, 306 deletions
diff --git a/libtransport/includes/hicn/transport/CMakeLists.txt b/libtransport/includes/hicn/transport/CMakeLists.txt index 1099e701d..ca53bdffd 100644 --- a/libtransport/includes/hicn/transport/CMakeLists.txt +++ b/libtransport/includes/hicn/transport/CMakeLists.txt @@ -22,7 +22,7 @@ add_subdirectory(errors) add_subdirectory(http) add_subdirectory(interfaces) add_subdirectory(portability) -add_subdirectory(security) +add_subdirectory(auth) add_subdirectory(utils) set(LIBTRANSPORT_INCLUDE_DIRS @@ -35,4 +35,4 @@ set(LIBHICNTRANSPORT_TO_INSTALL_HEADER_FILES ${HEADER_FILES} "" CACHE INTERNAL "" FORCE -)
\ No newline at end of file +) diff --git a/libtransport/includes/hicn/transport/auth/CMakeLists.txt b/libtransport/includes/hicn/transport/auth/CMakeLists.txt new file mode 100644 index 000000000..d855125b0 --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/CMakeLists.txt @@ -0,0 +1,29 @@ +# 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. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/common.h + ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.h + ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash_type.h + ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hasher.h + ${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.h + ${CMAKE_CURRENT_SOURCE_DIR}/identity.h + ${CMAKE_CURRENT_SOURCE_DIR}/key_id.h + ${CMAKE_CURRENT_SOURCE_DIR}/policies.h + ${CMAKE_CURRENT_SOURCE_DIR}/signer.h + ${CMAKE_CURRENT_SOURCE_DIR}/verifier.h +) + +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) diff --git a/libtransport/includes/hicn/transport/auth/common.h b/libtransport/includes/hicn/transport/auth/common.h new file mode 100644 index 000000000..911bcbc6a --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/common.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#pragma once + +#include <hicn/transport/core/packet.h> + +namespace transport { +namespace auth { + +using Hash = std::vector<uint8_t>; +using HashEntry = std::pair<CryptoHashType, Hash>; +using PacketPtr = core::Packet *; +using Suffix = uint32_t; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/crypto_hash.h b/libtransport/includes/hicn/transport/auth/crypto_hash.h new file mode 100644 index 000000000..26c251b38 --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/crypto_hash.h @@ -0,0 +1,121 @@ +/* + * 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. + */ + +#pragma once + +#include <hicn/transport/errors/runtime_exception.h> +#include <hicn/transport/portability/portability.h> +#include <hicn/transport/auth/crypto_hash_type.h> +#include <hicn/transport/utils/array.h> + +extern "C" { +#include <parc/security/parc_CryptoHash.h> +}; + +#include <cstring> +#include <unordered_map> + +namespace transport { +namespace auth { + +class CryptoHasher; + +struct EnumClassHash { + template <typename T> + std::size_t operator()(T t) const { + return static_cast<std::size_t>(t); + } +}; + +static std::unordered_map<CryptoHashType, std::size_t, EnumClassHash> + hash_size_map = {{CryptoHashType::SHA_256, 32}, + {CryptoHashType::CRC32C, 4}, + {CryptoHashType::SHA_512, 64}}; + +class Signer; +class Verifier; + +class CryptoHash { + friend class CryptoHasher; + friend class Signer; + friend class Verifier; + + public: + CryptoHash() : hash_(nullptr) {} + + CryptoHash(const CryptoHash& other) { + if (other.hash_) { + hash_ = parcCryptoHash_Acquire(other.hash_); + } + } + + CryptoHash(CryptoHash&& other) { + if (other.hash_) { + hash_ = parcCryptoHash_Acquire(other.hash_); + } + } + + template <typename T> + CryptoHash(const T* buffer, std::size_t length, CryptoHashType hash_type) { + hash_ = parcCryptoHash_CreateFromArray( + static_cast<PARCCryptoHashType>(hash_type), buffer, length); + } + + ~CryptoHash() { + if (hash_) { + parcCryptoHash_Release(&hash_); + } + } + + CryptoHash& operator=(const CryptoHash& other) { + if (other.hash_) { + hash_ = parcCryptoHash_Acquire(other.hash_); + } + + return *this; + } + + template <typename T> + utils::Array<T> getDigest() const { + return utils::Array<T>( + static_cast<T*>(parcBuffer_Overlay(parcCryptoHash_GetDigest(hash_), 0)), + parcBuffer_Remaining(parcCryptoHash_GetDigest(hash_))); + } + + CryptoHashType getType() { + return static_cast<CryptoHashType>(parcCryptoHash_GetDigestType(hash_)); + } + + template <typename T> + static bool compareBinaryDigest(const T* digest1, const T* digest2, + CryptoHashType hash_type) { + if (hash_size_map.find(hash_type) == hash_size_map.end()) { + return false; + } + + return !static_cast<bool>( + std::memcmp(digest1, digest2, hash_size_map[hash_type])); + } + + TRANSPORT_ALWAYS_INLINE void display() { + parcBuffer_Display(parcCryptoHash_GetDigest(hash_), 2); + } + + private: + PARCCryptoHash* hash_; +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/crypto_hash_type.h b/libtransport/includes/hicn/transport/auth/crypto_hash_type.h new file mode 100644 index 000000000..9d792624e --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/crypto_hash_type.h @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#pragma once + +extern "C" { +#include <parc/security/parc_CryptoHashType.h> +}; + +#include <cstdint> + +namespace transport { +namespace auth { + +enum class CryptoHashType : uint8_t { + SHA_256 = PARCCryptoHashType_SHA256, + SHA_512 = PARCCryptoHashType_SHA512, + CRC32C = PARCCryptoHashType_CRC32C, + NULL_HASH = PARCCryptoHashType_NULL +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/crypto_hasher.h b/libtransport/includes/hicn/transport/auth/crypto_hasher.h new file mode 100644 index 000000000..ada1a6ee8 --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/crypto_hasher.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#pragma once + +#include <hicn/transport/auth/crypto_hash.h> + +extern "C" { +#include <parc/security/parc_CryptoHasher.h> +}; + +namespace transport { +namespace auth { + +class CryptoHasher { + public: + CryptoHasher(CryptoHashType hash_type) + : hasher_(parcCryptoHasher_Create( + static_cast<PARCCryptoHashType>(hash_type))), + managed_(true) {} + + CryptoHasher(PARCCryptoHasher* hasher) : hasher_(hasher), managed_(false) {} + + ~CryptoHasher() { + if (managed_) { + parcCryptoHasher_Release(&hasher_); + } + } + + CryptoHasher& init() { + if (parcCryptoHasher_Init(hasher_) == -1) { + throw errors::RuntimeException("Cryptohash init failed."); + } + + return *this; + } + + template <typename T> + CryptoHasher& updateBytes(const T* buffer, std::size_t length) { + if (parcCryptoHasher_UpdateBytes(hasher_, buffer, length) == -1) { + throw errors::RuntimeException("Cryptohash updateBytes failed."); + } + return *this; + } + + CryptoHash finalize() { + CryptoHash hash; + hash.hash_ = parcCryptoHasher_Finalize(hasher_); + return hash; + } + + private: + PARCCryptoHasher* hasher_; + bool managed_; +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/crypto_suite.h b/libtransport/includes/hicn/transport/auth/crypto_suite.h new file mode 100644 index 000000000..11df6ac06 --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/crypto_suite.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#pragma once + +extern "C" { +#include <parc/security/parc_CryptoSuite.h> +}; + +#include <cstdint> + +namespace transport { +namespace auth { + +enum class CryptoSuite : uint8_t { + RSA_SHA256 = PARCCryptoSuite_RSA_SHA256, + DSA_SHA256 = PARCCryptoSuite_DSA_SHA256, + RSA_SHA512 = PARCCryptoSuite_RSA_SHA512, + HMAC_SHA256 = PARCCryptoSuite_HMAC_SHA256, + HMAC_SHA512 = PARCCryptoSuite_HMAC_SHA512, + NULL_CRC32C = PARCCryptoSuite_NULL_CRC32C, + ECDSA_256K1 = PARCCryptoSuite_ECDSA_SHA256, + UNKNOWN = PARCCryptoSuite_UNKNOWN +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/identity.h b/libtransport/includes/hicn/transport/auth/identity.h new file mode 100644 index 000000000..19157952e --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/identity.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 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. + */ + +#pragma once + +#include <hicn/transport/auth/signer.h> + +extern "C" { +#include <parc/security/parc_Identity.h> +#include <parc/security/parc_IdentityFile.h> +#include <parc/security/parc_Pkcs12KeyStore.h> +#include <parc/security/parc_Security.h> +}; + +namespace transport { +namespace auth { + +class Identity { + // This class holds several information about a client, including its public + // key. + public: + // Generate a new identity from the given parameters. The identity will be + // saved in 'keystore_path' and encrypted using 'keystore_pwd'. + Identity(const std::string &keystore_path, const std::string &keystore_pwd, + CryptoSuite suite, unsigned int signature_len, + unsigned int validity_days, const std::string &subject_name); + + // Create an identity from an already existing keystore path. + Identity(std::string &keystore_path, std::string &keystore_pwd, + CryptoHashType hash_type); + + Identity(const Identity &other); + Identity(Identity &&other); + ~Identity(); + + // Return the asymmetric signer object created from the public key. + std::shared_ptr<AsymmetricSigner> getSigner() const; + + // Return the key store filename. + std::string getFilename() const; + + // Return the key store password. + std::string getPassword() const; + + // Generate a new random identity. + static Identity generateIdentity(const std::string &subject_name = ""); + + private: + PARCIdentity *identity_; + std::shared_ptr<AsymmetricSigner> signer_; +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/key_id.h b/libtransport/includes/hicn/transport/auth/key_id.h new file mode 100644 index 000000000..3aa09336f --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/key_id.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#pragma once + +#include <cstdint> +#include <utility> + +namespace transport { +namespace auth { + +using KeyId = std::pair<uint8_t *, uint8_t>; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/policies.h b/libtransport/includes/hicn/transport/auth/policies.h new file mode 100644 index 000000000..00464d54b --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/policies.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 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. + */ + +#pragma once + +namespace transport { +namespace auth { + +/** + * These policies allows the verifier to tell the transport what action to + * perform after verification. + */ +enum class VerificationPolicy { + ABORT, + ACCEPT, + DROP, + UNKNOWN, +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/signer.h b/libtransport/includes/hicn/transport/auth/signer.h new file mode 100644 index 000000000..fd5c4e6c6 --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/signer.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 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. + */ + +#pragma once + +#include <hicn/transport/auth/common.h> +#include <hicn/transport/errors/errors.h> + +extern "C" { +#include <parc/security/parc_PublicKeySigner.h> +#include <parc/security/parc_Security.h> +#include <parc/security/parc_Signer.h> +#include <parc/security/parc_SymmetricKeySigner.h> +} + +namespace transport { +namespace auth { + +class Signer { + // The base class from which all signer classes derive. + public: + Signer(); + + Signer(PARCSigner *signer); + + virtual ~Signer(); + + // Sign a packet. + virtual void signPacket(PacketPtr packet); + + // Set the signer object used to sign packets. + void setSigner(PARCSigner *signer); + + // Return the signature size. + size_t getSignatureSize() const; + + // Return the crypto suite associated to the signer. + CryptoSuite getCryptoSuite() const; + + // Return the hash algorithm associated to the signer. + CryptoHashType getCryptoHashType() const; + + // Return the PARC signer. + PARCSigner *getParcSigner() const; + + // Return the PARC key store containing the signer key. + PARCKeyStore *getParcKeyStore() const; + + protected: + PARCSigner *signer_; + PARCKeyId *key_id_; +}; + +class AsymmetricSigner : public Signer { + // This class uses asymmetric verification to sign packets. The public key + // must be given from a PARCKeyStore. + public: + AsymmetricSigner() = default; + AsymmetricSigner(PARCSigner *signer) : Signer(signer){}; + + // Construct an AsymmetricSigner from a key store and a given crypto suite. + AsymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store); +}; + +class SymmetricSigner : public Signer { + // This class uses symmetric verification to sign packets. The symmetric + // key is derived from a passphrase. + public: + SymmetricSigner() = default; + SymmetricSigner(PARCSigner *signer) : Signer(signer){}; + + // Construct an SymmetricSigner from a key store and a given crypto suite. + SymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store); + + // Construct an AsymmetricSigner from a passphrase and a given crypto suite. + SymmetricSigner(CryptoSuite suite, const std::string &passphrase); +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/auth/verifier.h b/libtransport/includes/hicn/transport/auth/verifier.h new file mode 100644 index 000000000..e6e561918 --- /dev/null +++ b/libtransport/includes/hicn/transport/auth/verifier.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2017-2021 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. + */ + +#pragma once + +#include <hicn/transport/auth/common.h> +#include <hicn/transport/auth/policies.h> +#include <hicn/transport/core/content_object.h> +#include <hicn/transport/errors/errors.h> +#include <hicn/transport/interfaces/callbacks.h> + +#include <algorithm> + +extern "C" { +#include <parc/security/parc_CertificateFactory.h> +#include <parc/security/parc_InMemoryVerifier.h> +#include <parc/security/parc_Security.h> +#include <parc/security/parc_SymmetricKeySigner.h> +#include <parc/security/parc_Verifier.h> +} + +namespace transport { +namespace auth { + +class Verifier { + // The base class from which all verifier classes derive. + public: + // The VerificationFailedCallback will be called by the transport if a data + // packet (either a manifest or a content object) cannot be verified. The + // application decides what to do then by returning a VerificationPolicy + // object. + using VerificationFailedCallback = std::function<auth::VerificationPolicy( + const core::ContentObject &content_object, std::error_code ec)>; + + // The list of VerificationPolicy that will trigger the + // VerificationFailedCallback. + static const std::vector<VerificationPolicy> DEFAULT_FAILED_POLICIES; + + Verifier(); + + virtual ~Verifier(); + + // Verify a single packet and return whether or not the packet signature is + // valid. + virtual bool verifyPacket(PacketPtr packet); + + // Verify a batch of packets. Return a vector with the same size as the packet + // list, element i of that vector will contain the VerificationPolicy for + // packet i. + virtual std::vector<VerificationPolicy> verifyPackets( + const std::vector<PacketPtr> &packets); + VerificationPolicy verifyPackets(PacketPtr packet) { + return verifyPackets(std::vector<PacketPtr>{packet}).front(); + } + + // Verify that a batch of packets are valid using a map from packet suffixes + // to hashes. A packet is considered valid if its hash correspond to the hash + // present in the map. Return a vector with the same size as the packet list, + // element i of that vector will contain the VerificationPolicy for packet i. + virtual std::vector<VerificationPolicy> verifyPackets( + const std::vector<PacketPtr> &packets, + const std::unordered_map<Suffix, HashEntry> &suffix_map); + VerificationPolicy verifyPackets( + PacketPtr packet, + const std::unordered_map<Suffix, HashEntry> &suffix_map) { + return verifyPackets(std::vector<PacketPtr>{packet}, suffix_map).front(); + } + + // Add a general PARC key which can be used to verify packet signatures. + void addKey(PARCKey *key); + + // Set the hasher object used to compute packet hashes. + void setHasher(PARCCryptoHasher *hasher); + + // Set the callback for the case packet verification fails. + void setVerificationFailedCallback( + VerificationFailedCallback verification_failed_cb, + const std::vector<VerificationPolicy> &failed_policies = + DEFAULT_FAILED_POLICIES); + + // Retrieve the VerificationFailedCallback function. + void getVerificationFailedCallback( + VerificationFailedCallback **verification_failed_cb); + + static size_t getSignatureSize(const PacketPtr); + + protected: + PARCCryptoHasher *hasher_; + PARCVerifier *verifier_; + VerificationFailedCallback verification_failed_cb_; + std::vector<VerificationPolicy> failed_policies_; + + // Internally compute a packet hash using the hasher object. + virtual CryptoHash computeHash(PacketPtr packet); + + // Call VerificationFailedCallback if it is set and update the packet policy. + void callVerificationFailedCallback(PacketPtr packet, + VerificationPolicy &policy); +}; + +class VoidVerifier : public Verifier { + // This class is the default socket verifier. It ignores completely the packet + // signature and always returns true. + public: + bool verifyPacket(PacketPtr packet) override; + + std::vector<VerificationPolicy> verifyPackets( + const std::vector<PacketPtr> &packets) override; + + std::vector<VerificationPolicy> verifyPackets( + const std::vector<PacketPtr> &packets, + const std::unordered_map<Suffix, HashEntry> &suffix_map) override; +}; + +class AsymmetricVerifier : public Verifier { + // This class uses asymmetric verification to validate packets. The public key + // can be set directly or extracted from a certificate. + public: + AsymmetricVerifier() = default; + + // Add a public key to the verifier. + AsymmetricVerifier(PARCKey *pub_key); + + // Construct an AsymmetricVerifier from a certificate file. + AsymmetricVerifier(const std::string &cert_path); + + // Extract the public key of a certificate file. + void setCertificate(const std::string &cert_path); +}; + +class SymmetricVerifier : public Verifier { + // This class uses symmetric verification to validate packets. The symmetric + // key is derived from a passphrase. + public: + SymmetricVerifier() = default; + + // Construct a SymmetricVerifier from a passphrase. + SymmetricVerifier(const std::string &passphrase); + + ~SymmetricVerifier(); + + // Create and set a symmetric key from a passphrase. + void setPassphrase(const std::string &passphrase); + + // Construct a signer object. Passphrase must be set beforehand. + void setSigner(const PARCCryptoSuite &suite); + + virtual std::vector<VerificationPolicy> verifyPackets( + const std::vector<PacketPtr> &packets) override; + + protected: + PARCBuffer *passphrase_; + PARCSigner *signer_; +}; + +} // namespace auth +} // namespace transport diff --git a/libtransport/includes/hicn/transport/core/CMakeLists.txt b/libtransport/includes/hicn/transport/core/CMakeLists.txt index cb10745ff..2553b7dcd 100644 --- a/libtransport/includes/hicn/transport/core/CMakeLists.txt +++ b/libtransport/includes/hicn/transport/core/CMakeLists.txt @@ -20,6 +20,10 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/packet.h ${CMAKE_CURRENT_SOURCE_DIR}/payload_type.h ${CMAKE_CURRENT_SOURCE_DIR}/prefix.h + ${CMAKE_CURRENT_SOURCE_DIR}/io_module.h + ${CMAKE_CURRENT_SOURCE_DIR}/connector.h + ${CMAKE_CURRENT_SOURCE_DIR}/endpoint.h + ${CMAKE_CURRENT_SOURCE_DIR}/global_object_pool.h ) set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/core/connector.h b/libtransport/includes/hicn/transport/core/connector.h new file mode 100644 index 000000000..dcf38cdc8 --- /dev/null +++ b/libtransport/includes/hicn/transport/core/connector.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2021 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. + */ + +#pragma once + +#include <hicn/transport/core/connector_stats.h> +#include <hicn/transport/core/content_object.h> +#include <hicn/transport/core/endpoint.h> +#include <hicn/transport/core/global_object_pool.h> +#include <hicn/transport/core/interest.h> +#include <hicn/transport/core/packet.h> +#include <hicn/transport/portability/platform.h> +#include <hicn/transport/utils/membuf.h> +#include <hicn/transport/utils/object_pool.h> +#include <hicn/transport/utils/ring_buffer.h> +#include <hicn/transport/utils/shared_ptr_utils.h> + +#include <deque> +#include <functional> + +namespace transport { + +namespace core { + +class Connector : public std::enable_shared_from_this<Connector> { + public: + enum class Type : uint8_t { + SOCKET_CONNECTOR, + MEMIF_CONNECTOR, + LOOPBACK_CONNECTOR, + }; + + enum class State : std::uint8_t { + CLOSED, + CONNECTING, + CONNECTED, + }; + + enum class Role : std::uint8_t { CONSUMER, PRODUCER }; + + public: + static constexpr std::size_t queue_size = 4096; + static constexpr std::uint32_t invalid_connector = ~0; + +#ifdef LINUX + static constexpr std::uint16_t max_burst = 256; +#endif + + using Ptr = std::shared_ptr<Connector>; + using PacketQueue = std::deque<Packet::Ptr>; + using PacketReceivedCallback = std::function<void( + Connector *, utils::MemBuf &, const std::error_code &)>; + using PacketSentCallback = + std::function<void(Connector *, const std::error_code &)>; + using OnCloseCallback = std::function<void(Connector *)>; + using OnReconnectCallback = std::function<void(Connector *)>; + using Id = std::uint64_t; + + template <typename ReceiveCallback, typename SentCallback, typename OnClose, + typename OnReconnect> + Connector(ReceiveCallback &&receive_callback, SentCallback &&packet_sent, + OnClose &&close_callback, OnReconnect &&on_reconnect) + : receive_callback_(std::forward<ReceiveCallback &&>(receive_callback)), + sent_callback_(std::forward<SentCallback &&>(packet_sent)), + on_close_callback_(std::forward<OnClose &&>(close_callback)), + on_reconnect_callback_(std::forward<OnReconnect &&>(on_reconnect)), + state_(State::CLOSED), + connector_id_(invalid_connector) {} + + virtual ~Connector(){}; + + template <typename ReceiveCallback> + void setReceiveCallback(ReceiveCallback &&callback) { + receive_callback_ = std::forward<ReceiveCallback &&>(callback); + } + + template <typename SentCallback> + void setSentCallback(SentCallback &&callback) { + sent_callback_ = std::forward<SentCallback &&>(callback); + } + + template <typename OnClose> + void setOnCloseCallback(OnClose &&callback) { + on_close_callback_ = std::forward<OnClose &&>(callback); + } + + template <typename OnReconnect> + void setReconnectCallback(const OnReconnect &&callback) { + on_reconnect_callback_ = std::forward<OnReconnect>(callback); + } + + const PacketReceivedCallback &getReceiveCallback() const { + return receive_callback_; + } + + const PacketSentCallback &getSentCallback() { return sent_callback_; } + + const OnCloseCallback &getOnCloseCallback() { return on_close_callback_; } + + const OnReconnectCallback &getOnReconnectCallback() { + return on_reconnect_callback_; + } + + virtual void send(Packet &packet) = 0; + + virtual void send(const uint8_t *packet, std::size_t len) = 0; + + virtual void close() = 0; + + virtual State state() { return state_; }; + + virtual bool isConnected() { return state_ == State::CONNECTED; } + + void setConnectorId(Id connector_id) { connector_id_ = connector_id; } + + Id getConnectorId() { return connector_id_; } + + void setConnectorName(std::string connector_name) { + connector_name_ = connector_name; + } + + std::string getConnectorName() { return connector_name_; } + + Endpoint getLocalEndpoint() { return local_endpoint_; } + + Endpoint getRemoteEndpoint() { return remote_endpoint_; } + + void setRole(Role r) { role_ = r; } + + Role getRole() { return role_; } + + static utils::MemBuf::Ptr getPacketFromBuffer(uint8_t *buffer, + std::size_t size) { + utils::MemBuf::Ptr ret; + + auto format = Packet::getFormatFromBuffer(buffer, size); + + if (TRANSPORT_EXPECT_TRUE(format != HF_UNSPEC && !_is_icmp(format))) { + if (Packet::isInterest(buffer)) { + ret = core::PacketManager<>::getInstance() + .getPacketFromExistingBuffer<Interest>(buffer, size); + } else { + ret = core::PacketManager<>::getInstance() + .getPacketFromExistingBuffer<ContentObject>(buffer, size); + } + } else { + ret = core::PacketManager<>::getInstance().getMemBuf(buffer, size); + } + + return ret; + } + + static std::pair<uint8_t *, std::size_t> getRawBuffer() { + return core::PacketManager<>::getInstance().getRawBuffer(); + } + + protected: + inline void sendSuccess(const utils::MemBuf &packet) { + stats_.tx_packets_.fetch_add(1, std::memory_order_relaxed); + stats_.tx_bytes_.fetch_add(packet.length(), std::memory_order_relaxed); + } + + inline void receiveSuccess(const utils::MemBuf &packet) { + stats_.rx_packets_.fetch_add(1, std::memory_order_relaxed); + stats_.rx_bytes_.fetch_add(packet.length(), std::memory_order_relaxed); + } + + inline void sendFailed() { + stats_.drops_.fetch_add(1, std::memory_order_relaxed); + } + + protected: + PacketQueue output_buffer_; + + // Connector events + PacketReceivedCallback receive_callback_; + PacketSentCallback sent_callback_; + OnCloseCallback on_close_callback_; + OnReconnectCallback on_reconnect_callback_; + + // Connector state + std::atomic<State> state_; + Id connector_id_; + + // Endpoints + Endpoint local_endpoint_; + Endpoint remote_endpoint_; + + // Connector name + std::string connector_name_; + + // Connector role + Role role_; + + // Stats + AtomicConnectorStats stats_; +}; + +} // namespace core +} // namespace transport diff --git a/libtransport/includes/hicn/transport/core/connector_stats.h b/libtransport/includes/hicn/transport/core/connector_stats.h new file mode 100644 index 000000000..1985331e9 --- /dev/null +++ b/libtransport/includes/hicn/transport/core/connector_stats.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 Cisco and/or its affiliates. + */ + +#pragma once + +#include <atomic> +#include <cstdint> +#include <string> +#include <vector> + +namespace transport { +namespace core { + +struct AtomicConnectorStats { + AtomicConnectorStats() + : tx_packets_(0), tx_bytes_(0), rx_packets_(0), rx_bytes_(0), drops_(0) {} + std::atomic<uint64_t> tx_packets_; + std::atomic<uint64_t> tx_bytes_; + std::atomic<uint64_t> rx_packets_; + std::atomic<uint64_t> rx_bytes_; + std::atomic<uint64_t> drops_; +}; + +struct ConnectorStats { + ConnectorStats() + : tx_packets_(0), tx_bytes_(0), rx_packets_(0), rx_bytes_(0), drops_(0) {} + std::uint64_t tx_packets_; + std::uint64_t tx_bytes_; + std::uint64_t rx_packets_; + std::uint64_t rx_bytes_; + std::uint64_t drops_; +}; + +using TableEntry = std::tuple<std::string, std::uint64_t, std::uint64_t, + std::uint64_t, std::uint64_t, std::uint64_t>; +using StatisticTable = std::vector<TableEntry>; + +} // namespace core +} // namespace transport
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/core/content_object.h b/libtransport/includes/hicn/transport/core/content_object.h index 822790e56..805bc814c 100644 --- a/libtransport/includes/hicn/transport/core/content_object.h +++ b/libtransport/includes/hicn/transport/core/content_object.h @@ -17,6 +17,7 @@ #include <hicn/transport/core/name.h> #include <hicn/transport/core/packet.h> +#include <hicn/transport/utils/shared_ptr_utils.h> namespace transport { @@ -27,24 +28,53 @@ namespace core { class ContentObject : public Packet { public: - using Ptr = utils::ObjectPool<ContentObject>::Ptr; + using Ptr = std::shared_ptr<ContentObject>; using HICNContentObject = hicn_header_t; - ContentObject(Packet::Format format = HF_INET6_TCP); + ContentObject(Packet::Format format = HF_INET6_TCP, + std::size_t additional_header_size = 0); - ContentObject(const Name &name, Packet::Format format = HF_INET6_TCP); + ContentObject(const Name &name, Packet::Format format = HF_INET6_TCP, + std::size_t additional_header_size = 0); - ContentObject(const Name &name, hicn_format_t format, const uint8_t *payload, + ContentObject(const Name &name, hicn_format_t format, + std::size_t additional_header_size, const uint8_t *payload, std::size_t payload_size); - ContentObject(const uint8_t *buffer, std::size_t size); - ContentObject(MemBufPtr &&buffer); - - ContentObject(const ContentObject &content_object) = delete; + template <typename... Args> + ContentObject(CopyBufferOp op, Args &&...args) + : Packet(op, std::forward<Args>(args)...) { + if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) < + 0) { + throw errors::MalformedPacketException(); + } + } + + template <typename... Args> + ContentObject(WrapBufferOp op, Args &&...args) + : Packet(op, std::forward<Args>(args)...) { + if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) < + 0) { + throw errors::MalformedPacketException(); + } + } + + template <typename... Args> + ContentObject(CreateOp op, Args &&...args) + : Packet(op, std::forward<Args>(args)...) { + if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) < + 0) { + throw errors::MalformedPacketException(); + } + } + + ContentObject(const ContentObject &content_object); + + ContentObject &operator=(const ContentObject &other); ContentObject(ContentObject &&content_object); - ~ContentObject() override; + ~ContentObject(); const Name &getName() const override; @@ -66,6 +96,8 @@ class ContentObject : public Packet { uint32_t getLifetime() const override; + auto shared_from_this() { return utils::shared_from(this); } + private: void resetForHash() override; }; diff --git a/libtransport/includes/hicn/transport/core/endpoint.h b/libtransport/includes/hicn/transport/core/endpoint.h new file mode 100644 index 000000000..4a19744a7 --- /dev/null +++ b/libtransport/includes/hicn/transport/core/endpoint.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 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. + */ + +#pragma once + +#ifndef ASIO_STANDALONE +#define ASIO_STANDALONE +#endif +#include <asio.hpp> + +namespace transport { + +namespace core { + +const uint16_t INVALID_PORT = 0xffff; + +class Endpoint { + public: + Endpoint() : address_(), port_(INVALID_PORT) {} + + Endpoint(const Endpoint &other) + : address_(other.address_), port_(other.port_) {} + + Endpoint(Endpoint &&other) + : address_(std::move(other.address_)), port_(other.port_) {} + + Endpoint(std::string ip_address, uint32_t port) + : address_(asio::ip::address::from_string(ip_address)), port_(port) {} + + Endpoint(asio::ip::udp::endpoint endpoint) + : address_(endpoint.address()), port_(endpoint.port()) {} + + ~Endpoint() = default; + + Endpoint &operator=(const Endpoint &other) { + address_ = other.address_; + port_ = other.port_; + return *this; + } + + Endpoint &operator=(Endpoint &&other) { + address_ = std::move(other.address_); + port_ = std::move(other.port_); + return *this; + } + +#if 0 + template <typename Ip, typename Port> + Endpoint(Ip &&ip_address, Port &&port) + : address_(std::forward<Ip &&>(ip_address)), + port_(std::forward<Port &&>(port)) {} +#endif + + asio::ip::address getAddress() { return address_; } + uint16_t getPort() { return port_; } + + void setAddress(uint32_t address) { + address_ = asio::ip::address(asio::ip::address_v4(address)); + } + + void setPort(uint16_t port) { port_ = port; } + + private: + asio::ip::address address_; + uint16_t port_; +}; +} // namespace core +} // namespace transport diff --git a/libtransport/includes/hicn/transport/core/global_object_pool.h b/libtransport/includes/hicn/transport/core/global_object_pool.h new file mode 100644 index 000000000..e0b6e373f --- /dev/null +++ b/libtransport/includes/hicn/transport/core/global_object_pool.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021 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. + */ + +#pragma once + +#include <hicn/transport/core/packet.h> +#include <hicn/transport/utils/fixed_block_allocator.h> +#include <hicn/transport/utils/singleton.h> + +#include <array> +#include <mutex> + +namespace transport { + +namespace core { + +template <std::size_t packet_pool_size = 1024, std::size_t chunk_size = 2048> +class PacketManager + : public utils::Singleton<PacketManager<packet_pool_size, chunk_size>> { + friend class utils::Singleton<PacketManager<packet_pool_size, chunk_size>>; + + public: + using MemoryPool = utils::FixedBlockAllocator<chunk_size, packet_pool_size>; + using RawBuffer = std::pair<uint8_t *, std::size_t>; + + struct PacketStorage { + std::array<uint8_t, 256> packet_and_shared_ptr; + std::max_align_t align; + }; + + utils::MemBuf::Ptr getMemBuf() { + utils::MemBuf *memory = nullptr; + + memory = reinterpret_cast<utils::MemBuf *>(memory_pool_.allocateBlock()); + + utils::STLAllocator<utils::MemBuf, MemoryPool> allocator(memory, + &memory_pool_); + auto offset = offsetof(PacketStorage, align); + auto ret = std::allocate_shared<utils::MemBuf>( + allocator, utils::MemBuf::WRAP_BUFFER, (uint8_t *)memory + offset, 0, + chunk_size - offset); + ret->clear(); + + return ret; + } + + utils::MemBuf::Ptr getMemBuf(uint8_t *buffer, std::size_t length) { + auto offset = offsetof(PacketStorage, align); + auto memory = buffer - offset; + utils::STLAllocator<utils::MemBuf, MemoryPool> allocator( + (utils::MemBuf *)memory, &memory_pool_); + auto ret = std::allocate_shared<utils::MemBuf>( + allocator, utils::MemBuf::WRAP_BUFFER, (uint8_t *)buffer, length, + chunk_size - offset); + + return ret; + } + + template < + typename PacketType, typename... Args, + typename = std::enable_if_t<std::is_base_of<Packet, PacketType>::value>> + typename PacketType::Ptr getPacket(Args &&...args) { + PacketType *memory = nullptr; + + memory = reinterpret_cast<PacketType *>(memory_pool_.allocateBlock()); + utils::STLAllocator<PacketType, MemoryPool> allocator(memory, + &memory_pool_); + auto offset = offsetof(PacketStorage, align); + auto ret = std::allocate_shared<PacketType>( + allocator, PacketType::CREATE, (uint8_t *)memory + offset, 0, + chunk_size - offset, std::forward<Args>(args)...); + + return ret; + } + + std::pair<uint8_t *, std::size_t> getRawBuffer() { + uint8_t *memory = nullptr; + memory = reinterpret_cast<uint8_t *>(memory_pool_.allocateBlock()); + + auto offset = offsetof(PacketStorage, align); + memory += offset; + + return std::make_pair(memory, chunk_size - offset); + } + + template <typename PacketType, typename... Args> + typename PacketType::Ptr getPacketFromExistingBuffer(uint8_t *buffer, + std::size_t length, + Args &&...args) { + auto offset = offsetof(PacketStorage, align); + auto memory = reinterpret_cast<PacketType *>(buffer - offset); + utils::STLAllocator<PacketType, MemoryPool> allocator(memory, + &memory_pool_); + auto ret = std::allocate_shared<PacketType>( + allocator, PacketType::WRAP_BUFFER, (uint8_t *)buffer, length, + chunk_size - offset, std::forward<Args>(args)...); + + return ret; + } + + private: + PacketManager(std::size_t size = packet_pool_size) + : memory_pool_(MemoryPool::getInstance()), size_(0) {} + MemoryPool &memory_pool_; + std::atomic<size_t> size_; +}; + +} // end namespace core + +} // end namespace transport diff --git a/libtransport/includes/hicn/transport/core/interest.h b/libtransport/includes/hicn/transport/core/interest.h index c572afbff..b41b0c94a 100644 --- a/libtransport/includes/hicn/transport/core/interest.h +++ b/libtransport/includes/hicn/transport/core/interest.h @@ -17,6 +17,9 @@ #include <hicn/transport/core/name.h> #include <hicn/transport/core/packet.h> +#include <hicn/transport/utils/shared_ptr_utils.h> + +#include <set> namespace transport { @@ -24,25 +27,57 @@ namespace core { class Interest : public Packet /*, public std::enable_shared_from_this<Interest>*/ { - public: - using Ptr = utils::ObjectPool<Interest>::Ptr; - - Interest(Packet::Format format = HF_INET6_TCP); - - Interest(const Name &interest_name, Packet::Format format = HF_INET6_TCP); + private: + struct InterestManifestHeader { + /* This can be 16 bits, but we use 32 bits for alignment */ + uint32_t n_suffixes; + /* Followed by the list of prefixes to ask */ + /* ... */ + }; - Interest(const uint8_t *buffer, std::size_t size); - Interest(MemBufPtr &&buffer); + public: + using Ptr = std::shared_ptr<Interest>; + + Interest(Packet::Format format = HF_INET6_TCP, + std::size_t additional_header_size = 0); + + Interest(const Name &interest_name, Packet::Format format = HF_INET6_TCP, + std::size_t additional_header_size = 0); + + Interest(MemBuf &&buffer); + + template <typename... Args> + Interest(CopyBufferOp op, Args &&...args) + : Packet(op, std::forward<Args>(args)...) { + if (hicn_interest_get_name(format_, packet_start_, + name_.getStructReference()) < 0) { + throw errors::MalformedPacketException(); + } + } + + template <typename... Args> + Interest(WrapBufferOp op, Args &&...args) + : Packet(op, std::forward<Args>(args)...) { + if (hicn_interest_get_name(format_, packet_start_, + name_.getStructReference()) < 0) { + throw errors::MalformedPacketException(); + } + } + + template <typename... Args> + Interest(CreateOp op, Args &&...args) + : Packet(op, std::forward<Args>(args)...) {} + + /* Move constructor */ + Interest(Interest &&other_interest); - /* - * Enforce zero-copy. - */ - Interest(const Interest &other_interest) = delete; - Interest &operator=(const Interest &other_interest) = delete; + /* Copy constructor */ + Interest(const Interest &other_interest); - Interest(Interest &&other_interest); + /* Assginemnt operator */ + Interest &operator=(const Interest &other); - ~Interest() override; + ~Interest(); const Name &getName() const override; @@ -60,8 +95,21 @@ class Interest uint32_t getLifetime() const override; + bool hasManifest(); + + void appendSuffix(std::uint32_t suffix); + + void encodeSuffixes(); + + uint32_t *firstSuffix(); + + uint32_t numberOfSuffixes(); + + auto shared_from_this() { return utils::shared_from(this); } + private: void resetForHash() override; + std::set<uint32_t> suffix_set_; }; } // end namespace core diff --git a/libtransport/includes/hicn/transport/core/io_module.h b/libtransport/includes/hicn/transport/core/io_module.h new file mode 100644 index 000000000..d4c3bb03a --- /dev/null +++ b/libtransport/includes/hicn/transport/core/io_module.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2021 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. + */ + +#pragma once + +#include <hicn/transport/core/connector.h> +#include <hicn/transport/core/packet.h> +#include <hicn/transport/core/prefix.h> +#include <hicn/transport/portability/portability.h> +#include <hicn/transport/utils/chrono_typedefs.h> +#include <hicn/transport/utils/membuf.h> + +#include <deque> + +#ifndef ASIO_STANDALONE +#define ASIO_STANDALONE +#endif +#include <asio/io_service.hpp> + +namespace transport { + +namespace core { + +typedef struct { + uint64_t rx_packets; + uint64_t tx_packets; + uint64_t rx_bytes; + uint64_t tx_bytes; + uint64_t rx_errors; + uint64_t tx_errors; +} Counters; + +class Connector; + +class IoModule { + protected: + IoModule() + : inet_address_({}), + inet6_address_({}), + mtu_(1500), + output_interface_(""), + content_store_reserved_(5000) { + inet_address_.v4.as_u32 = htonl(0x7f00001); + inet6_address_.v6.as_u8[15] = 0x01; + } + + public: + static IoModule *load(const char *); + static bool unload(IoModule *); + + public: + virtual ~IoModule(); + + virtual void connect(bool is_consumer = true) = 0; + + virtual bool isConnected() = 0; + + virtual void init(Connector::PacketReceivedCallback &&receive_callback, + Connector::OnReconnectCallback &&reconnect_callback, + asio::io_service &io_service, + const std::string &app_name = "Libtransport") = 0; + + virtual void registerRoute(const Prefix &prefix) = 0; + + virtual std::uint32_t getMtu() = 0; + + virtual bool isControlMessage(const uint8_t *message) = 0; + + virtual void processControlMessageReply(utils::MemBuf &packet_buffer) = 0; + + virtual void closeConnection() = 0; + + virtual void send(Packet &packet) { + counters_.tx_packets++; + counters_.tx_bytes += packet.payloadSize() + packet.headerSize(); + + if (_is_ipv4(packet.getFormat())) { + packet.setLocator(inet_address_); + } else { + packet.setLocator(inet6_address_); + } + } + + virtual void send(const uint8_t *packet, std::size_t len) = 0; + + void setContentStoreSize(uint32_t cs_size) { + content_store_reserved_ = cs_size; + } + + uint32_t getContentStoreSize() const { return content_store_reserved_; } + + void setOutputInterface(const std::string &interface) { + output_interface_ = interface; + } + + const std::string &getOutputInterface() { return output_interface_; } + +#ifndef ANDROID + private: + void *handle_; +#endif + + protected: + ip_address_t inet_address_; + ip_address_t inet6_address_; + uint16_t mtu_; + std::string output_interface_; + uint32_t content_store_reserved_; + Counters counters_; +}; + +extern "C" IoModule *createModule(); + +} // namespace core +} // namespace transport diff --git a/libtransport/includes/hicn/transport/core/name.h b/libtransport/includes/hicn/transport/core/name.h index ea72797ad..033582289 100644 --- a/libtransport/includes/hicn/transport/core/name.h +++ b/libtransport/includes/hicn/transport/core/name.h @@ -77,6 +77,8 @@ class Name { operator bool() const; + bool isValid() const; + std::string toString() const; bool equals(const Name &name, bool consider_segment = true) const; @@ -125,14 +127,14 @@ struct compare2 {}; template <> struct compare2<transport::core::Name> { - size_t operator()(const transport::core::Name &name1, const transport::core::Name &name2) const; + size_t operator()(const transport::core::Name &name1, + const transport::core::Name &name2) const; }; } // end namespace core } // end namespace transport - namespace std { template <> struct hash<transport::core::Name> { diff --git a/libtransport/includes/hicn/transport/core/packet.h b/libtransport/includes/hicn/transport/core/packet.h index 91f957964..68daea841 100644 --- a/libtransport/includes/hicn/transport/core/packet.h +++ b/libtransport/includes/hicn/transport/core/packet.h @@ -19,21 +19,15 @@ #include <hicn/transport/core/payload_type.h> #include <hicn/transport/errors/malformed_packet_exception.h> #include <hicn/transport/portability/portability.h> -#include <hicn/transport/security/crypto_hasher.h> -#include <hicn/transport/security/crypto_suite.h> -#include <hicn/transport/security/key_id.h> +#include <hicn/transport/auth/crypto_hasher.h> +#include <hicn/transport/auth/crypto_suite.h> +#include <hicn/transport/auth/key_id.h> #include <hicn/transport/utils/branch_prediction.h> #include <hicn/transport/utils/log.h> #include <hicn/transport/utils/membuf.h> #include <hicn/transport/utils/object_pool.h> -namespace utils { -class Signer; -class Verifier; -} // namespace utils - namespace transport { - namespace core { /* @@ -45,11 +39,13 @@ namespace core { * \_______________________________________| */ -class Packet : public std::enable_shared_from_this<Packet> { - friend class utils::Signer; - friend class utils::Verifier; +class Packet : public utils::MemBuf, + public std::enable_shared_from_this<Packet> { + friend class auth::Signer; + friend class auth::Verifier; public: + using Ptr = std::shared_ptr<Packet>; using MemBufPtr = std::shared_ptr<utils::MemBuf>; using Format = hicn_format_t; static constexpr size_t default_mtu = 1500; @@ -59,24 +55,29 @@ class Packet : public std::enable_shared_from_this<Packet> { * the eventual payload will be added by prepending the payload buffer * to the buffer chain whose the fist buffer is the header itself. */ - Packet(Format format = HF_UNSPEC); + Packet(Format format = HF_INET6_TCP, std::size_t additional_header_size = 0); /** * Create new IP packet using raw buffer. */ - Packet(const uint8_t *buffer, std::size_t size); - Packet(MemBufPtr &&buffer); - /* - * Enforce zero-copy lifestyle. - */ - Packet(const Packet &other) = delete; - Packet &operator=(const Packet &other) = delete; + /* Copy buffer */ + Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size); + /* Wrap buffer */ + Packet(WrapBufferOp, uint8_t *buffer, std::size_t length, std::size_t size); + /* Create new using pre-allocated buffer */ + Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size, + Format format = HF_INET6_TCP, std::size_t additional_header_size = 0); + /* Move MemBuf */ + Packet(MemBuf &&buffer); + + Packet(Packet &&other); /* - * Move constructor. + * Copy constructor and assignemnt operators. */ - Packet(Packet &&other); + Packet(const Packet &other); + Packet &operator=(const Packet &other); friend bool operator==(const Packet &l_packet, const Packet &r_packet); @@ -98,36 +99,35 @@ class Packet : public std::enable_shared_from_this<Packet> { static bool isInterest(const uint8_t *buffer); + bool isInterest(); + static Format getFormatFromBuffer(const uint8_t *buffer, std::size_t length) { Format format = HF_UNSPEC; - - if (TRANSPORT_EXPECT_FALSE( - hicn_packet_get_format((const hicn_header_t *)buffer, &format) < - 0)) { - TRANSPORT_LOGE( - "Error while getting format from packet buffer. Packet will be " - "discarded."); - hicn_packet_dump(buffer, length); - } - + hicn_packet_get_format((const hicn_header_t *)buffer, &format); return format; } - TRANSPORT_ALWAYS_INLINE void replace(MemBufPtr &&buffer) { - packet_ = std::move(buffer); - packet_start_ = reinterpret_cast<hicn_header_t *>(packet_->writableData()); - header_head_ = packet_.get(); - payload_head_ = nullptr; - format_ = getFormatFromBuffer(reinterpret_cast<uint8_t *>(packet_start_), - packet_->length()); + void reset() { + clear(); + packet_start_ = reinterpret_cast<hicn_header_t *>(writableData()); + header_offset_ = 0; + format_ = HF_UNSPEC; + payload_type_ = PayloadType::UNSPECIFIED; name_.clear(); + + if (isChained()) { + separateChain(next(), prev()); + } } + void setFormat(Packet::Format format = HF_INET6_TCP, + std::size_t additional_header_size = 0); + std::size_t payloadSize() const; std::size_t headerSize() const; - const std::shared_ptr<utils::MemBuf> acquireMemBufReference() const; + std::shared_ptr<utils::MemBuf> acquireMemBufReference(); virtual const Name &getName() const = 0; @@ -145,25 +145,8 @@ class Packet : public std::enable_shared_from_this<Packet> { Packet &appendPayload(std::unique_ptr<utils::MemBuf> &&payload); - Packet &appendHeader(std::unique_ptr<utils::MemBuf> &&header); - - Packet &appendHeader(const uint8_t *buffer, std::size_t length); - std::unique_ptr<utils::MemBuf> getPayload() const; - std::pair<const uint8_t *, std::size_t> getPayloadReference() const { - int signature_size = 0; - - if (_is_ah(format_)) { - signature_size = (uint32_t)getSignatureSize(); - } - - auto header_size = getHeaderSizeFromFormat(format_, signature_size); - auto payload_length = payloadSize(); - - return std::make_pair(packet_->data() + header_size, payload_length); - } - Packet &updateLength(std::size_t length = 0); PayloadType getPayloadType() const; @@ -174,35 +157,38 @@ class Packet : public std::enable_shared_from_this<Packet> { void dump() const; + static void dump(uint8_t *buffer, std::size_t length); + virtual void setLocator(const ip_address_t &locator) = 0; virtual ip_address_t getLocator() const = 0; - void setSignatureTimestamp(const uint64_t ×tamp); + /** + * @brief Set signature timestamp, in milliseconds. + */ + void setSignatureTimestamp(const uint64_t ×tamp_milliseconds); uint64_t getSignatureTimestamp() const; - void setValidationAlgorithm(const utils::CryptoSuite &validation_algorithm); + void setValidationAlgorithm(const auth::CryptoSuite &validation_algorithm); - utils::CryptoSuite getValidationAlgorithm() const; + auth::CryptoSuite getValidationAlgorithm() const; - void setKeyId(const utils::KeyId &key_id); + void setKeyId(const auth::KeyId &key_id); - utils::KeyId getKeyId() const; + auth::KeyId getKeyId() const; - virtual utils::CryptoHash computeDigest( - utils::CryptoHashType algorithm) const; + virtual auth::CryptoHash computeDigest(auth::CryptoHashType algorithm) const; void setChecksum() { - uint16_t partial_csum = 0; - - for (utils::MemBuf *current = header_head_->next(); - current && current != header_head_; current = current->next()) { - if (partial_csum != 0) { - partial_csum = ~partial_csum; - } - partial_csum = csum(current->data(), current->length(), partial_csum); + uint16_t partial_csum = + csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0); + + for (utils::MemBuf *current = next(); current != this; + current = current->next()) { + partial_csum = csum(current->data(), current->length(), ~partial_csum); } + if (hicn_packet_compute_header_checksum(format_, packet_start_, partial_csum) < 0) { throw errors::MalformedPacketException(); @@ -234,12 +220,12 @@ class Packet : public std::enable_shared_from_this<Packet> { Packet &setTTL(uint8_t hops); uint8_t getTTL() const; - void separateHeaderPayload(); - void resetPayload(); - private: virtual void resetForHash() = 0; void setSignatureSize(std::size_t size_bytes); + void prependPayload(const uint8_t **buffer, std::size_t *size); + + bool authenticationHeader() const { return _is_ah(format_); } std::size_t getSignatureSize() const { size_t size_bytes; @@ -256,12 +242,11 @@ class Packet : public std::enable_shared_from_this<Packet> { uint8_t *getSignature() const; protected: - Name name_; - MemBufPtr packet_; hicn_header_t *packet_start_; - utils::MemBuf *header_head_; - utils::MemBuf *payload_head_; + std::size_t header_offset_; mutable Format format_; + Name name_; + mutable PayloadType payload_type_; static const core::Name base_name; }; diff --git a/libtransport/includes/hicn/transport/core/payload_type.h b/libtransport/includes/hicn/transport/core/payload_type.h index fa79db35a..8c918f792 100644 --- a/libtransport/includes/hicn/transport/core/payload_type.h +++ b/libtransport/includes/hicn/transport/core/payload_type.h @@ -20,8 +20,9 @@ namespace transport { namespace core { enum class PayloadType : uint16_t { - CONTENT_OBJECT = HPT_DATA, + DATA = HPT_DATA, MANIFEST = HPT_MANIFEST, + UNSPECIFIED = HPT_UNSPEC }; } // end namespace core diff --git a/libtransport/includes/hicn/transport/core/prefix.h b/libtransport/includes/hicn/transport/core/prefix.h index c3805f13f..7ef667bc8 100644 --- a/libtransport/includes/hicn/transport/core/prefix.h +++ b/libtransport/includes/hicn/transport/core/prefix.h @@ -35,9 +35,9 @@ class Prefix { Prefix(const core::Name &content_name, uint16_t prefix_length); - std::unique_ptr<Sockaddr> toSockaddr(); + std::unique_ptr<Sockaddr> toSockaddr() const; - uint16_t getPrefixLength(); + uint16_t getPrefixLength() const; Prefix &setPrefixLength(uint16_t prefix_length); @@ -58,13 +58,13 @@ class Prefix { Prefix &setNetwork(std::string &network); - int getAddressFamily(); + int getAddressFamily() const; Prefix &setAddressFamily(int address_family); Name makeRandomName() const; - ip_prefix_t &toIpPrefixStruct(); + const ip_prefix_t &toIpPrefixStruct() const; private: static bool checkPrefixLengthAndAddressFamily(uint16_t prefix_length, diff --git a/libtransport/includes/hicn/transport/errors/errors.h b/libtransport/includes/hicn/transport/errors/errors.h index 512e35736..b659820fa 100644 --- a/libtransport/includes/hicn/transport/errors/errors.h +++ b/libtransport/includes/hicn/transport/errors/errors.h @@ -15,10 +15,13 @@ #pragma once +#include <hicn/transport/errors/indexing_exception.h> #include <hicn/transport/errors/invalid_ip_address_exception.h> +#include <hicn/transport/errors/malformed_ahpacket_exception.h> #include <hicn/transport/errors/malformed_name_exception.h> #include <hicn/transport/errors/malformed_packet_exception.h> #include <hicn/transport/errors/not_implemented_exception.h> #include <hicn/transport/errors/null_pointer_exception.h> #include <hicn/transport/errors/runtime_exception.h> -#include <hicn/transport/errors/tokenizer_exception.h>
\ No newline at end of file +#include <hicn/transport/errors/tokenizer_exception.h> +#include <hicn/transport/errors/unexpected_manifest_exception.h> diff --git a/libtransport/includes/hicn/transport/http/client_connection.h b/libtransport/includes/hicn/transport/http/client_connection.h index 262756a09..7e78e9c59 100644 --- a/libtransport/includes/hicn/transport/http/client_connection.h +++ b/libtransport/includes/hicn/transport/http/client_connection.h @@ -68,7 +68,7 @@ class HTTPClientConnection { HTTPClientConnection &setTimeout(const std::chrono::seconds &timeout); - HTTPClientConnection &setCertificate(const std::string &cert_path); + HTTPClientConnection &setVerifier(std::shared_ptr<auth::Verifier> verifier); private: class Implementation; @@ -77,4 +77,4 @@ class HTTPClientConnection { } // end namespace http -} // end namespace transport
\ No newline at end of file +} // end namespace transport diff --git a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt index 7370ad1b0..08f880930 100644 --- a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt +++ b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt @@ -16,12 +16,11 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/socket_consumer.h ${CMAKE_CURRENT_SOURCE_DIR}/socket_producer.h - ${CMAKE_CURRENT_SOURCE_DIR}/rtc_socket_producer.h ${CMAKE_CURRENT_SOURCE_DIR}/publication_options.h ${CMAKE_CURRENT_SOURCE_DIR}/socket_options_default_values.h ${CMAKE_CURRENT_SOURCE_DIR}/socket_options_keys.h ${CMAKE_CURRENT_SOURCE_DIR}/callbacks.h - ${CMAKE_CURRENT_SOURCE_DIR}/verification_policy.h + ${CMAKE_CURRENT_SOURCE_DIR}/global_conf_interface.h ${CMAKE_CURRENT_SOURCE_DIR}/statistics.h ${CMAKE_CURRENT_SOURCE_DIR}/portal.h ) diff --git a/libtransport/includes/hicn/transport/interfaces/callbacks.h b/libtransport/includes/hicn/transport/interfaces/callbacks.h index 6ae07797e..95b4d1977 100644 --- a/libtransport/includes/hicn/transport/interfaces/callbacks.h +++ b/libtransport/includes/hicn/transport/interfaces/callbacks.h @@ -16,7 +16,7 @@ #pragma once #include <hicn/transport/interfaces/statistics.h> -#include <hicn/transport/interfaces/verification_policy.h> +#include <hicn/transport/auth/policies.h> #include <functional> #include <system_error> @@ -75,25 +75,6 @@ using ConsumerContentObjectCallback = std::function<void(ConsumerSocket &, const core::ContentObject &)>; /** - * The ConsumerContentObjectVerificationCallback will be called by the transport - * if an application is willing to verify each content object. Note that a - * better alternative is to instrument the transport to perform the verification - * autonomously, without requiring the intervention of the application. - */ -using ConsumerContentObjectVerificationCallback = - std::function<bool(ConsumerSocket &, const core::ContentObject &)>; - -/** - * The ConsumerContentObjectVerificationFailedCallback will be caled by the - * transport if a data packet (either manifest or content object) cannot be - * verified. The application here decides what to do by returning a - * VerificationFailedPolicy object. - */ -using ConsumerContentObjectVerificationFailedCallback = - std::function<VerificationPolicy( - ConsumerSocket &, const core::ContentObject &, std::error_code ec)>; - -/** * The ProducerContentObjectCallback will be called in different parts of the * consumer socket processing pipeline, with a ProducerSocket and an * ContentObject as parameters. diff --git a/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h b/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h new file mode 100644 index 000000000..a9fe6fac6 --- /dev/null +++ b/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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. + */ + +#pragma once + +#include <string> +#include <vector> + +/** + * Global configuration interface. + */ + +namespace transport { +namespace interface { +namespace global_config { + +static const constexpr char io_module_section[] = "io_module"; +void parseConfigurationFile(const std::string& path = ""); + +class ConfigurationObject { + public: + /** + * Set configuration. + */ + void set(); + + /** + * Get configuration. + */ + void get(); + + /** + * Get configuration key + */ + virtual std::string getKey() const = 0; +}; + +class IoModuleConfiguration : public ConfigurationObject { + public: + std::string getKey() const override { return io_module_section; } + + std::string name; + std::vector<std::string> search_path; +}; + +} // namespace global_config +} // namespace interface +} // namespace transport
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h index 6f0d48bb9..7b284c520 100644 --- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h +++ b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h @@ -16,8 +16,7 @@ #pragma once #include <hicn/transport/interfaces/socket_producer.h> - -#include <hicn/transport/security/identity.h> +#include <hicn/transport/auth/identity.h> namespace transport { @@ -27,7 +26,7 @@ class P2PSecureProducerSocket : public ProducerSocket { public: P2PSecureProducerSocket(); P2PSecureProducerSocket(bool rtc, - const std::shared_ptr<utils::Identity> &identity); + const std::shared_ptr<auth::Identity> &identity); ~P2PSecureProducerSocket() = default; }; diff --git a/libtransport/includes/hicn/transport/interfaces/portal.h b/libtransport/includes/hicn/transport/interfaces/portal.h index 724cd7592..22c8591f4 100644 --- a/libtransport/includes/hicn/transport/interfaces/portal.h +++ b/libtransport/includes/hicn/transport/interfaces/portal.h @@ -23,7 +23,6 @@ #define ASIO_STANDALONE #endif #include <asio/io_service.hpp> - #include <functional> #define UNSET_CALLBACK 0 @@ -71,8 +70,7 @@ class Portal { */ class ConsumerCallback { public: - virtual void onContentObject(core::Interest::Ptr &&i, - core::ContentObject::Ptr &&c) = 0; + virtual void onContentObject(core::Interest &i, core::ContentObject &c) = 0; virtual void onTimeout(core::Interest::Ptr &&i) = 0; virtual void onError(std::error_code ec) = 0; }; @@ -83,12 +81,12 @@ class Portal { */ class ProducerCallback { public: - virtual void onInterest(core::Interest::Ptr &&i) = 0; + virtual void onInterest(core::Interest &i) = 0; virtual void onError(std::error_code ec) = 0; }; using OnContentObjectCallback = - std::function<void(core::Interest::Ptr &&, core::ContentObject::Ptr &&)>; + std::function<void(core::Interest &, core::ContentObject &)>; using OnInterestTimeoutCallback = std::function<void(core::Interest::Ptr &&)>; Portal(); diff --git a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h index 2447f9b5b..621e7ce6f 100644 --- a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h +++ b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h @@ -21,7 +21,7 @@ #include <hicn/transport/interfaces/callbacks.h> #include <hicn/transport/interfaces/socket_options_default_values.h> #include <hicn/transport/interfaces/socket_options_keys.h> -#include <hicn/transport/security/verifier.h> +#include <hicn/transport/auth/verifier.h> #ifndef ASIO_STANDALONE #define ASIO_STANDALONE @@ -208,14 +208,6 @@ class ConsumerSocket { int asyncConsume(const Name &name); /** - * Verify the packets containing a key after the origin of the key has been - * validated by the client. - * - * @return true if all packets are valid, false otherwise - */ - bool verifyKeyPackets(); - - /** * Stops the consumer socket. If several downloads are queued (using * asyncConsume), this call stops just the current one. */ @@ -251,14 +243,6 @@ class ConsumerSocket { int setSocketOption(int socket_option_key, ConsumerContentObjectCallback socket_option_value); - int setSocketOption( - int socket_option_key, - ConsumerContentObjectVerificationFailedCallback socket_option_value); - - int setSocketOption( - int socket_option_key, - ConsumerContentObjectVerificationCallback socket_option_value); - int setSocketOption(int socket_option_key, ConsumerInterestCallback socket_option_value); @@ -267,7 +251,7 @@ class ConsumerSocket { int setSocketOption( int socket_option_key, - const std::shared_ptr<utils::Verifier> &socket_option_value); + const std::shared_ptr<auth::Verifier> &socket_option_value); int setSocketOption(int socket_option_key, const std::string &socket_option_value); @@ -286,21 +270,13 @@ class ConsumerSocket { int getSocketOption(int socket_option_key, ConsumerContentObjectCallback **socket_option_value); - int getSocketOption( - int socket_option_key, - ConsumerContentObjectVerificationFailedCallback **socket_option_value); - - int getSocketOption( - int socket_option_key, - ConsumerContentObjectVerificationCallback **socket_option_value); - int getSocketOption(int socket_option_key, ConsumerInterestCallback **socket_option_value); int getSocketOption(int socket_option_key, IcnObserver **socket_option_value); int getSocketOption(int socket_option_key, - std::shared_ptr<utils::Verifier> &socket_option_value); + std::shared_ptr<auth::Verifier> &socket_option_value); int getSocketOption(int socket_option_key, std::string &socket_option_value); diff --git a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h index bcf103b8c..f4945ac8a 100644 --- a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h +++ b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h @@ -16,6 +16,7 @@ #pragma once #include <hicn/base.h> + #include <chrono> #include <cstdint> diff --git a/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h b/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h index f50e919b4..00cd44075 100644 --- a/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h +++ b/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h @@ -32,6 +32,11 @@ typedef enum { } TransportProtocolAlgorithms; typedef enum { + BYTE_STREAM = 10, + RTC_PROD = 11, +} ProductionProtocolAlgorithms; + +typedef enum { INPUT_BUFFER_SIZE = 101, OUTPUT_BUFFER_SIZE = 102, NETWORK_NAME = 103, @@ -40,7 +45,6 @@ typedef enum { DATA_PACKET_SIZE = 106, INTEREST_LIFETIME = 107, CONTENT_OBJECT_EXPIRY_TIME = 108, - KEY_CONTENT = 110, MIN_WINDOW_SIZE = 111, MAX_WINDOW_SIZE = 112, CURRENT_WINDOW_SIZE = 113, @@ -50,12 +54,10 @@ typedef enum { RUNNING = 117, APPLICATION_BUFFER = 118, HASH_ALGORITHM = 119, - CRYPTO_SUITE = 120, SIGNER = 121, VERIFIER = 122, - CERTIFICATE = 123, - VERIFY_SIGNATURE = 124, STATS_INTERVAL = 125, + SUFFIX_STRATEGY = 126 } GeneralTransportOptions; typedef enum { @@ -98,6 +100,7 @@ typedef enum { CONTENT_OBJECT_READY = 510, CONTENT_OBJECT_OUTPUT = 511, CONTENT_PRODUCED = 512, + CONTENT_OBJECT_TO_SIGN = 513 } ProducerCallbacksOptions; typedef enum { OUTPUT_INTERFACE = 601 } DataLinkOptions; diff --git a/libtransport/includes/hicn/transport/interfaces/socket_producer.h b/libtransport/includes/hicn/transport/interfaces/socket_producer.h index e269fb83d..302b03f3f 100644 --- a/libtransport/includes/hicn/transport/interfaces/socket_producer.h +++ b/libtransport/includes/hicn/transport/interfaces/socket_producer.h @@ -21,7 +21,7 @@ #include <hicn/transport/interfaces/callbacks.h> #include <hicn/transport/interfaces/socket_options_default_values.h> #include <hicn/transport/interfaces/socket_options_keys.h> -#include <hicn/transport/security/signer.h> +#include <hicn/transport/auth/signer.h> #ifndef ASIO_STANDALONE #define ASIO_STANDALONE @@ -40,7 +40,10 @@ using namespace core; class ProducerSocket { public: - explicit ProducerSocket(int protocol = 0); + explicit ProducerSocket( + int protocol = ProductionProtocolAlgorithms::BYTE_STREAM); + + explicit ProducerSocket(int protocol, asio::io_service &io_service); virtual ~ProducerSocket(); @@ -48,22 +51,21 @@ class ProducerSocket { bool isRunning(); - uint32_t produce(Name content_name, const uint8_t *buffer, size_t buffer_size, - bool is_last = true, uint32_t start_offset = 0) { - return produce(content_name, utils::MemBuf::copyBuffer(buffer, buffer_size), - is_last, start_offset); - } + void registerPrefix(const Prefix &producer_namespace); - uint32_t produce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer, - bool is_last = true, uint32_t start_offset = 0); + uint32_t produceStream(const Name &content_name, const uint8_t *buffer, + size_t buffer_size, bool is_last = true, + uint32_t start_offset = 0); - void produce(ContentObject &content_object); + uint32_t produceStream(const Name &content_name, + std::unique_ptr<utils::MemBuf> &&buffer, + bool is_last = true, uint32_t start_offset = 0); - void produce(const uint8_t *buffer, size_t buffer_size) { - produce(utils::MemBuf::copyBuffer(buffer, buffer_size)); - } + uint32_t produceDatagram(const Name &content_name, const uint8_t *buffer, + size_t buffer_size); - void produce(std::unique_ptr<utils::MemBuf> &&buffer); + uint32_t produceDatagram(const Name &content_name, + std::unique_ptr<utils::MemBuf> &&buffer); void asyncProduce(const Name &suffix, const uint8_t *buf, size_t buffer_size, bool is_last = true, uint32_t *start_offset = nullptr); @@ -72,9 +74,7 @@ class ProducerSocket { bool is_last, uint32_t offset, uint32_t **last_segment = nullptr); - void asyncProduce(ContentObject &content_object); - - void registerPrefix(const Prefix &producer_namespace); + void produce(ContentObject &content_object); void serveForever(); @@ -104,14 +104,13 @@ class ProducerSocket { ProducerContentCallback socket_option_value); int setSocketOption(int socket_option_key, - utils::CryptoHashType socket_option_value); + auth::CryptoHashType socket_option_value); int setSocketOption(int socket_option_key, - utils::CryptoSuite socket_option_value); + auth::CryptoSuite socket_option_value); - int setSocketOption( - int socket_option_key, - const std::shared_ptr<utils::Signer> &socket_option_value); + int setSocketOption(int socket_option_key, + const std::shared_ptr<auth::Signer> &socket_option_value); int setSocketOption(int socket_option_key, const std::string &socket_option_value); @@ -133,13 +132,13 @@ class ProducerSocket { ProducerInterestCallback **socket_option_value); int getSocketOption(int socket_option_key, - utils::CryptoHashType &socket_option_value); + auth::CryptoHashType &socket_option_value); int getSocketOption(int socket_option_key, - utils::CryptoSuite &socket_option_value); + auth::CryptoSuite &socket_option_value); int getSocketOption(int socket_option_key, - std::shared_ptr<utils::Signer> &socket_option_value); + std::shared_ptr<auth::Signer> &socket_option_value); int getSocketOption(int socket_option_key, std::string &socket_option_value); diff --git a/libtransport/includes/hicn/transport/interfaces/statistics.h b/libtransport/includes/hicn/transport/interfaces/statistics.h index 26831fbf1..92c58da23 100644 --- a/libtransport/includes/hicn/transport/interfaces/statistics.h +++ b/libtransport/includes/hicn/transport/interfaces/statistics.h @@ -31,6 +31,8 @@ class IcnObserver { virtual void notifyDownloadTime(double downloadTime) = 0; }; +class ProductionStatistics {}; + class TransportStatistics { static constexpr double default_alpha = 0.7; @@ -43,7 +45,15 @@ class TransportStatistics { interest_tx_(0), alpha_(alpha), loss_ratio_(0.0), - queuing_delay_(0.0) {} + queuing_delay_(0.0), + interest_FEC_tx_(0), + bytes_FEC_received_(0), + lost_data_(0), + recovered_data_(0), + status_(-1), + // avg_data_rtt_(0), + avg_pending_pkt_(0.0), + received_nacks_(0) {} TRANSPORT_ALWAYS_INLINE void updateRetxCount(uint64_t retx) { retx_count_ += retx; @@ -74,6 +84,32 @@ class TransportStatistics { queuing_delay_ = queuing_delay; } + TRANSPORT_ALWAYS_INLINE void updateInterestFecTx(uint64_t int_tx) { + interest_FEC_tx_ += int_tx; + } + + TRANSPORT_ALWAYS_INLINE void updateBytesFecRecv(uint64_t bytes) { + bytes_FEC_received_ += bytes; + } + + TRANSPORT_ALWAYS_INLINE void updateLostData(uint64_t pkt) { + lost_data_ += pkt; + } + + TRANSPORT_ALWAYS_INLINE void updateRecoveredData(uint64_t bytes) { + recovered_data_ += bytes; + } + + TRANSPORT_ALWAYS_INLINE void updateCCState(int status) { status_ = status; } + + TRANSPORT_ALWAYS_INLINE void updateAveragePendingPktCount(double pkt) { + avg_pending_pkt_ = (alpha_ * avg_pending_pkt_) + ((1. - alpha_) * pkt); + } + + TRANSPORT_ALWAYS_INLINE void updateReceivedNacks(uint32_t nacks) { + received_nacks_ += nacks; + } + TRANSPORT_ALWAYS_INLINE uint64_t getRetxCount() const { return retx_count_; } TRANSPORT_ALWAYS_INLINE uint64_t getBytesRecv() const { @@ -96,6 +132,32 @@ class TransportStatistics { return queuing_delay_; } + TRANSPORT_ALWAYS_INLINE uint64_t getInterestFecTxCount() const { + return interest_FEC_tx_; + } + + TRANSPORT_ALWAYS_INLINE uint64_t getBytesFecRecv() const { + return bytes_FEC_received_; + } + + TRANSPORT_ALWAYS_INLINE uint64_t getLostData() const { return lost_data_; } + + TRANSPORT_ALWAYS_INLINE uint64_t getBytesRecoveredData() const { + return recovered_data_; + } + + TRANSPORT_ALWAYS_INLINE int getCCStatus() const { return status_; } + + TRANSPORT_ALWAYS_INLINE double getAveragePendingPktCount() const { + return avg_pending_pkt_; + } + + TRANSPORT_ALWAYS_INLINE uint32_t getReceivedNacks() const { + return received_nacks_; + } + + TRANSPORT_ALWAYS_INLINE void setAlpha(double val) { alpha_ = val; } + TRANSPORT_ALWAYS_INLINE void reset() { retx_count_ = 0; bytes_received_ = 0; @@ -103,6 +165,14 @@ class TransportStatistics { avg_window_size_ = 0; interest_tx_ = 0; loss_ratio_ = 0; + interest_FEC_tx_ = 0; + bytes_FEC_received_ = 0; + lost_data_ = 0; + recovered_data_ = 0; + status_ = 0; + // avg_data_rtt_ = 0; + avg_pending_pkt_ = 0; + received_nacks_ = 0; } private: @@ -114,6 +184,13 @@ class TransportStatistics { double alpha_; double loss_ratio_; double queuing_delay_; + uint64_t interest_FEC_tx_; + uint64_t bytes_FEC_received_; + uint64_t lost_data_; + uint64_t recovered_data_; + int status_; // transport status (e.g. sync status, congestion etc.) + double avg_pending_pkt_; + uint32_t received_nacks_; }; } // namespace interface diff --git a/libtransport/includes/hicn/transport/portability/c_portability.h b/libtransport/includes/hicn/transport/portability/c_portability.h index 71e976a81..9fe9ef90a 100644 --- a/libtransport/includes/hicn/transport/portability/c_portability.h +++ b/libtransport/includes/hicn/transport/portability/c_portability.h @@ -33,4 +33,4 @@ #define TRANSPORT_ALWAYS_INLINE inline __attribute__((__always_inline__)) #else #define TRANSPORT_ALWAYS_INLINE inline -#endif
\ No newline at end of file +#endif diff --git a/libtransport/includes/hicn/transport/portability/platform.h b/libtransport/includes/hicn/transport/portability/platform.h new file mode 100644 index 000000000..282d27740 --- /dev/null +++ b/libtransport/includes/hicn/transport/portability/platform.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 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. + */ + +#pragma once + +/* + * Extract the "MACINTOSH" flag from the compiler. + */ +#if defined(__APPLE__) +#define UNIX +#define MACINTOSH +#endif + +/* + * Extract the "SUNOS" flag from the compiler. + */ +#if defined(sun) +#define UNIX +#define SUNOS +#endif + +/* + * Extract the "LINUX" flag from compiler. + */ +#ifdef __linux__ +#define UNIX +#define LINUX +#endif + +/* + * Extract the "ANDROID" flag from compiler. + */ +#ifdef __ANDROID__ +#define UNIX +#define LINUX +#ifndef ANDROID +#define ANDROID +#endif +#endif + +/* + * Extract the "BSD" flag from compiler. + */ +#if defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) +#define OS_BSD +#define UNIX +#endif + +/* + * Extract the "MSDOS" flag from the compiler. + */ +#ifdef __MSDOS__ +#define MSDOS +#undef UNIX +#endif + +/* + * Extract the "WINDOWS" flag from the compiler. + */ +#if defined(_Windows) || defined(__WINDOWS__) || defined(__WIN32__) || \ + defined(WIN32) || defined(__WINNT__) || defined(__NT__) || \ + defined(_WIN32) || defined(_WIN64) +#define WINDOWS +#ifdef _MSC_VER +#define MSV +#if defined(DEBUG) || defined(DEBUGTRACE) +#ifdef NDEBUG +#undef NDEBUG +#endif +#else +#ifndef NDEBUG +#define NDEBUG +#endif +#endif +#else +#undef MSV +#endif +#undef UNIX +#undef MSDOS +#endif + +/* + * Remove the WINDOWS flag when using MACINTOSH. + */ +#ifdef MACINTOSH +#undef WINDOWS +#endif + +/* + * Assume UNIX if not Windows, Macintosh or MSDOS. + */ +#if !defined(WINDOWS) && !defined(MACINTOSH) && !defined(MSDOS) +#define UNIX +#endif diff --git a/libtransport/includes/hicn/transport/portability/portability.h b/libtransport/includes/hicn/transport/portability/portability.h index 1d97a346e..539ce2d5a 100644 --- a/libtransport/includes/hicn/transport/portability/portability.h +++ b/libtransport/includes/hicn/transport/portability/portability.h @@ -22,8 +22,8 @@ #endif #include <hicn/transport/portability/c_portability.h> - #include <string.h> + #include <cstddef> namespace portability { diff --git a/libtransport/includes/hicn/transport/portability/win_portability.h b/libtransport/includes/hicn/transport/portability/win_portability.h index 65d949291..bfbe431d1 100644 --- a/libtransport/includes/hicn/transport/portability/win_portability.h +++ b/libtransport/includes/hicn/transport/portability/win_portability.h @@ -31,6 +31,7 @@ #include <winsock2.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
+
#include <algorithm>
#define __ORDER_LITTLE_ENDIAN__ 0x41424344UL
diff --git a/libtransport/includes/hicn/transport/utils/CMakeLists.txt b/libtransport/includes/hicn/transport/utils/CMakeLists.txt index 11a9b0f25..7094601f4 100644 --- a/libtransport/includes/hicn/transport/utils/CMakeLists.txt +++ b/libtransport/includes/hicn/transport/utils/CMakeLists.txt @@ -31,6 +31,11 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/fixed_block_allocator.h ${CMAKE_CURRENT_SOURCE_DIR}/event_thread.h ${CMAKE_CURRENT_SOURCE_DIR}/string_utils.h + ${CMAKE_CURRENT_SOURCE_DIR}/file.h + ${CMAKE_CURRENT_SOURCE_DIR}/shared_ptr_utils.h + ${CMAKE_CURRENT_SOURCE_DIR}/move_wrapper.h + ${CMAKE_CURRENT_SOURCE_DIR}/noncopyable.h + ${CMAKE_CURRENT_SOURCE_DIR}/singleton.h ) if(NOT WIN32) diff --git a/libtransport/includes/hicn/transport/utils/conversions.h b/libtransport/includes/hicn/transport/utils/conversions.h index 24b529206..52d3e3168 100644 --- a/libtransport/includes/hicn/transport/utils/conversions.h +++ b/libtransport/includes/hicn/transport/utils/conversions.h @@ -16,8 +16,8 @@ #pragma once #include <hicn/transport/portability/portability.h> - #include <stdio.h> + #include <cstdint> #include <string> diff --git a/libtransport/includes/hicn/transport/utils/enum_iterator.h b/libtransport/includes/hicn/transport/utils/enum_iterator.h new file mode 100644 index 000000000..5e108b088 --- /dev/null +++ b/libtransport/includes/hicn/transport/utils/enum_iterator.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 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 <type_traits> + +template <typename C, C begin_val, C end_val> +class Iterator { + typedef typename std::underlying_type<C>::type val_t; + int val; + + public: + Iterator(const C& f) : val(static_cast<val_t>(f)) {} + + Iterator() : val(static_cast<val_t>(begin_val)) {} + + Iterator operator++() { + ++val; + return *this; + } + + C operator*() { return static_cast<C>(val); } + + Iterator begin() { return *this; } // default ctor is good + + Iterator end() { + static const Iterator endIter = ++Iterator(end_val); // cache it + return endIter; + } + + bool operator!=(const Iterator& i) { return val != i.val; } +};
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/utils/event_thread.h b/libtransport/includes/hicn/transport/utils/event_thread.h index 702c98f8d..bb6ab90ef 100644 --- a/libtransport/includes/hicn/transport/utils/event_thread.h +++ b/libtransport/includes/hicn/transport/utils/event_thread.h @@ -17,7 +17,11 @@ #include <hicn/transport/config.h> #include <hicn/transport/errors/runtime_exception.h> +#include <hicn/transport/utils/log.h> +#ifndef ASIO_STANDALONE +#define ASIO_STANDALONE +#endif #include <asio.hpp> #include <memory> #include <thread> @@ -25,36 +29,58 @@ namespace utils { class EventThread { - private: - // No copies - EventThread(const EventThread&) = delete; // non construction-copyable - EventThread& operator=(const EventThread&) = delete; // non copyable - public: - explicit EventThread(asio::io_service& io_service) + EventThread(asio::io_service& io_service, bool detached = false) : internal_io_service_(nullptr), - io_service_(io_service), + io_service_(std::ref(io_service)), work_(std::make_unique<asio::io_service::work>(io_service_)), - thread_(nullptr) { + thread_(nullptr), + detached_(detached) { run(); } - explicit EventThread() + EventThread(bool detached = false) : internal_io_service_(std::make_unique<asio::io_service>()), - io_service_(*internal_io_service_), + io_service_(std::ref(*internal_io_service_)), work_(std::make_unique<asio::io_service::work>(io_service_)), - thread_(nullptr) { + thread_(nullptr), + detached_(detached) { run(); } + EventThread(const EventThread&) = delete; + EventThread& operator=(const EventThread&) = delete; + + EventThread(EventThread&& other) + : internal_io_service_(std::move(other.internal_io_service_)), + io_service_(std::move(other.io_service_)), + work_(std::move(other.work_)), + thread_(std::move(other.thread_)), + detached_(std::move(other.detached_)) {} + + EventThread& operator=(EventThread&& other) { + internal_io_service_ = std::move(other.internal_io_service_); + io_service_ = std::move(other.io_service_); + work_ = std::move(other.work_); + thread_ = std::move(other.thread_); + detached_ = other.detached_; + + return *this; + } + ~EventThread() { stop(); } void run() { if (stopped()) { - io_service_.reset(); + io_service_.get().stopped(); } - thread_ = std::make_unique<std::thread>([this]() { io_service_.run(); }); + thread_ = + std::make_unique<std::thread>([this]() { io_service_.get().run(); }); + + if (detached_) { + thread_->detach(); + } } std::thread::id getThreadId() const { @@ -67,14 +93,12 @@ class EventThread { template <typename Func> void add(Func&& f) { - // If the function f - // TODO USe post in mac os, asio->post in xenial - io_service_.post(std::forward<Func&&>(f)); + io_service_.get().post(std::forward<Func&&>(f)); } template <typename Func> void tryRunHandlerNow(Func&& f) { - io_service_.dispatch(std::forward<Func&&>(f)); + io_service_.get().dispatch(std::forward<Func&&>(f)); } void stop() { @@ -87,15 +111,16 @@ class EventThread { thread_.reset(); } - bool stopped() { return io_service_.stopped(); } + bool stopped() { return io_service_.get().stopped(); } asio::io_service& getIoService() { return io_service_; } private: std::unique_ptr<asio::io_service> internal_io_service_; - asio::io_service& io_service_; + std::reference_wrapper<asio::io_service> io_service_; std::unique_ptr<asio::io_service::work> work_; std::unique_ptr<std::thread> thread_; + bool detached_; }; } // namespace utils
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/utils/file.h b/libtransport/includes/hicn/transport/utils/file.h new file mode 100644 index 000000000..4c73f33e8 --- /dev/null +++ b/libtransport/includes/hicn/transport/utils/file.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 <sys/stat.h> + +namespace utils { + +class File { + public: + static inline bool exists(const std::string& name) { + struct stat buffer; + return (stat(name.c_str(), &buffer) == 0); + } +}; + +} // namespace utils diff --git a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h index 1ade1516e..b1df36493 100644 --- a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h +++ b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h @@ -5,104 +5,99 @@ #pragma once #include <hicn/transport/portability/c_portability.h> +#include <hicn/transport/utils/singleton.h> #include <hicn/transport/utils/spinlock.h> - #include <stdint.h> + +#include <cassert> #include <cstdlib> #include <memory> -#include <cassert> namespace utils { -template <std::size_t DEFAULT_SIZE = 512, std::size_t OBJECTS = 4096> -class FixedBlockAllocator { - FixedBlockAllocator(std::size_t size = DEFAULT_SIZE, - std::size_t objects = OBJECTS) - : block_size_(size < sizeof(void*) ? sizeof(long*) : size), - object_size_(size), - max_objects_(objects), - p_head_(NULL), - pool_index_(0), - block_count_(0), - blocks_in_use_(0), - allocations_(0), - deallocations_(0) { - p_pool_ = (uint8_t*)new uint8_t[block_size_ * max_objects_]; - } +template <std::size_t SIZE = 512, std::size_t OBJECTS = 4096> +class FixedBlockAllocator + : public utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>> { + friend class utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>>; public: - static FixedBlockAllocator* getInstance() { - if (!instance_) { - instance_ = std::unique_ptr<FixedBlockAllocator>( - new FixedBlockAllocator(DEFAULT_SIZE, OBJECTS)); + ~FixedBlockAllocator() { + for (auto& p : p_pools_) { + delete[] p; } - - return instance_.get(); } - ~FixedBlockAllocator() { delete[] p_pool_; } - - TRANSPORT_ALWAYS_INLINE void* allocateBlock(size_t size = DEFAULT_SIZE) { - assert(size <= DEFAULT_SIZE); + void* allocateBlock(size_t size = SIZE) { + assert(size <= SIZE); uint32_t index; + SpinLock::Acquire locked(lock_); void* p_block = pop(); if (!p_block) { - if (pool_index_ < max_objects_) { - { - SpinLock::Acquire locked(lock_); - index = pool_index_++; - } - p_block = (void*)(p_pool_ + (index * block_size_)); - } else { - // TODO Consider increasing pool here instead of throwing an exception - throw std::runtime_error("No more memory available from packet pool!"); + if (TRANSPORT_EXPECT_FALSE(current_pool_index_ >= max_objects_)) { + // Allocate new memory block + TRANSPORT_LOGV("Allocating new block of %zu size", SIZE * OBJECTS); + p_pools_.emplace_front( + new typename std::aligned_storage<SIZE>::type[max_objects_]); + // reset current_pool_index_ + current_pool_index_ = 0; } - } - blocks_in_use_++; - allocations_++; + auto& latest = p_pools_.front(); + index = current_pool_index_++; + blocks_in_use_++; + allocations_++; + p_block = (void*)&latest[index]; + } return p_block; } - TRANSPORT_ALWAYS_INLINE void deallocateBlock(void* pBlock) { + void deallocateBlock(void* pBlock) { + SpinLock::Acquire locked(lock_); push(pBlock); - { - SpinLock::Acquire locked(lock_); - blocks_in_use_--; - deallocations_++; - } + blocks_in_use_--; + deallocations_++; } - TRANSPORT_ALWAYS_INLINE std::size_t blockSize() { return block_size_; } + public: + std::size_t blockSize() { return block_size_; } - TRANSPORT_ALWAYS_INLINE uint32_t blockCount() { return block_count_; } + uint32_t blockCount() { return block_count_; } - TRANSPORT_ALWAYS_INLINE uint32_t blocksInUse() { return blocks_in_use_; } + uint32_t blocksInUse() { return blocks_in_use_; } - TRANSPORT_ALWAYS_INLINE uint32_t allocations() { return allocations_; } + uint32_t allocations() { return allocations_; } - TRANSPORT_ALWAYS_INLINE uint32_t deallocations() { return deallocations_; } + uint32_t deallocations() { return deallocations_; } private: - TRANSPORT_ALWAYS_INLINE void push(void* p_memory) { + FixedBlockAllocator() + : block_size_(SIZE), + object_size_(SIZE), + max_objects_(OBJECTS), + p_head_(NULL), + current_pool_index_(0), + block_count_(0), + blocks_in_use_(0), + allocations_(0), + deallocations_(0) { + static_assert(SIZE >= sizeof(long*), "SIZE must be at least 8 bytes"); + p_pools_.emplace_front( + new typename std::aligned_storage<SIZE>::type[max_objects_]); + } + + void push(void* p_memory) { Block* p_block = (Block*)p_memory; - { - SpinLock::Acquire locked(lock_); - p_block->p_next = p_head_; - p_head_ = p_block; - } + p_block->p_next = p_head_; + p_head_ = p_block; } - TRANSPORT_ALWAYS_INLINE void* pop() { + void* pop() { Block* p_block = nullptr; - { - SpinLock::Acquire locked(lock_); - if (p_head_) { - p_block = p_head_; - p_head_ = p_head_->p_next; - } + if (p_head_) { + p_block = p_head_; + p_head_ = p_head_->p_next; } return (void*)p_block; @@ -119,8 +114,8 @@ class FixedBlockAllocator { const std::size_t max_objects_; Block* p_head_; - uint8_t* p_pool_; - uint32_t pool_index_; + uint32_t current_pool_index_; + std::list<typename std::aligned_storage<SIZE>::type*> p_pools_; uint32_t block_count_; uint32_t blocks_in_use_; uint32_t allocations_; @@ -133,4 +128,88 @@ template <std::size_t A, std::size_t B> std::unique_ptr<FixedBlockAllocator<A, B>> FixedBlockAllocator<A, B>::instance_ = nullptr; +/** + * STL Allocator trait to be used with allocate_shared. + */ +template <typename T, typename Pool> +class STLAllocator { + /** + * If STLAllocator is rebound to another type (!= T) using copy constructor, + * we may need to access private members of the source allocator to copy + * memory and pool. + */ + template <typename U, typename P> + friend class STLAllocator; + + public: + using size_type = std::size_t; + using difference_type = ptrdiff_t; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using value_type = T; + + STLAllocator(pointer memory, Pool* memory_pool) + : memory_(memory), pool_(memory_pool) { + TRANSPORT_LOGV("Creating allocator. This: %p, memory: %p, memory_pool: %p", + this, memory, memory_pool); + } + + ~STLAllocator() {} + + template <typename U> + STLAllocator(const STLAllocator<U, Pool>& other) { + memory_ = other.memory_; + pool_ = other.pool_; + } + + template <typename U> + struct rebind { + typedef STLAllocator<U, Pool> other; + }; + + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pointer allocate(size_type n, pointer hint = 0) { + TRANSPORT_LOGV( + "Allocating memory (%zu). This: %p, memory: %p, memory_pool: %p", n, + this, memory_, pool_); + return static_cast<pointer>(memory_); + } + + void deallocate(pointer p, size_type n) { + TRANSPORT_LOGV("Deallocating memory. This: %p, memory: %p, memory_pool: %p", + this, memory_, pool_); + pool_->deallocateBlock(memory_); + } + + template <typename... Args> + void construct(pointer p, Args&&... args) { + new (static_cast<pointer>(p)) T(std::forward<Args>(args)...); + } + + void destroy(pointer p) { + TRANSPORT_LOGV("Destroying object. This: %p, memory: %p, memory_pool: %p", + this, memory_, pool_); + p->~T(); + } + + private: + void* memory_; + Pool* pool_; +}; + +template <typename T, typename U, typename V> +inline bool operator==(const STLAllocator<T, V>&, const STLAllocator<U, V>&) { + return true; +} + +template <typename T, typename U, typename V> +inline bool operator!=(const STLAllocator<T, V>& a, + const STLAllocator<U, V>& b) { + return !(a == b); +} + } // namespace utils
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/utils/linux.h b/libtransport/includes/hicn/transport/utils/linux.h index 5820528e1..105196fd2 100644 --- a/libtransport/includes/hicn/transport/utils/linux.h +++ b/libtransport/includes/hicn/transport/utils/linux.h @@ -17,14 +17,14 @@ #ifdef __linux__ +#include <arpa/inet.h> #include <hicn/transport/portability/portability.h> #include <hicn/transport/utils/log.h> - -#include <arpa/inet.h> #include <ifaddrs.h> #include <netdb.h> #include <stdio.h> #include <sys/socket.h> + #include <string> #define LINK_LOCAL_PREFIX 0xfe80 diff --git a/libtransport/includes/hicn/transport/utils/membuf.h b/libtransport/includes/hicn/transport/utils/membuf.h index 9fc37dd25..0db87e9dd 100644 --- a/libtransport/includes/hicn/transport/utils/membuf.h +++ b/libtransport/includes/hicn/transport/utils/membuf.h @@ -23,6 +23,7 @@ #include <hicn/transport/portability/portability.h> #include <hicn/transport/utils/branch_prediction.h> +#include <stdlib.h> #include <atomic> #include <cassert> @@ -35,8 +36,6 @@ #include <type_traits> #include <vector> -#include <stdlib.h> - #ifndef _WIN32 TRANSPORT_GNU_DISABLE_WARNING("-Wshadow") #endif @@ -50,6 +49,8 @@ class MemBuf { enum TakeOwnershipOp { TAKE_OWNERSHIP }; enum CopyBufferOp { COPY_BUFFER }; + using Ptr = std::shared_ptr<MemBuf>; + typedef void (*FreeFunction)(void* buf, void* userData); static std::unique_ptr<MemBuf> create(std::size_t capacity); @@ -106,13 +107,14 @@ class MemBuf { FreeFunction freeFn = nullptr, void* userData = nullptr, bool freeOnError = true); - static std::unique_ptr<MemBuf> wrapBuffer(const void* buf, + static std::unique_ptr<MemBuf> wrapBuffer(const void* buf, std::size_t length, std::size_t capacity); - static MemBuf wrapBufferAsValue(const void* buf, + static MemBuf wrapBufferAsValue(const void* buf, std::size_t length, std::size_t capacity) noexcept; - MemBuf(WrapBufferOp op, const void* buf, std::size_t capacity) noexcept; + MemBuf(WrapBufferOp op, const void* buf, std::size_t length, + std::size_t capacity) noexcept; /** * Convenience function to create a new MemBuf object that copies data from a @@ -147,6 +149,8 @@ class MemBuf { std::size_t length() const { return length_; } + void setLength(std::size_t length) { length_ = length; } + std::size_t headroom() const { return std::size_t(data_ - buffer()); } std::size_t tailroom() const { return std::size_t(bufferEnd() - tail()); } @@ -689,6 +693,18 @@ class MemBuf { void* userData = nullptr, bool freeOnError = true); + /** + * Ensure the current MemBuf can hold at least capacity bytes and its + * memory is contiguous + */ + bool ensureCapacity(std::size_t capacity); + + /** + * Ensure packet buffer can hold at least 1500 bytes in contiguous memory and + * fill unused memory with placeholder + */ + bool ensureCapacityAndFillUnused(std::size_t capacity, uint8_t placeholder); + /* * Overridden operator new and delete. * These perform specialized memory management to help support @@ -700,6 +716,12 @@ class MemBuf { void operator delete(void* ptr); void operator delete(void* ptr, void* placement); + /** + * Override operator == and != + */ + bool operator ==(const MemBuf &other); + bool operator !=(const MemBuf &other); + // /** // * Iteration support: a chain of MemBufs may be iterated through using // * STL-style iterators over const ByteRanges. Iterators are only diff --git a/libtransport/includes/hicn/transport/utils/move_wrapper.h b/libtransport/includes/hicn/transport/utils/move_wrapper.h new file mode 100644 index 000000000..3aba345d6 --- /dev/null +++ b/libtransport/includes/hicn/transport/utils/move_wrapper.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright 2017 Facebook, Inc. + * + * 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. + */ + +#pragma once + +#include <type_traits> + +namespace utils { + +template <typename F> +struct MoveWrapper : F { + MoveWrapper(F&& f) : F(std::move(f)) {} + + MoveWrapper(MoveWrapper&&) = default; + MoveWrapper& operator=(MoveWrapper&&) = default; + + MoveWrapper(const MoveWrapper&); + MoveWrapper& operator=(const MoveWrapper&); +}; + +template <typename T> +auto moveHandler(T&& t) -> MoveWrapper<typename std::decay<T>::type> { + return std::move(t); +} +} // namespace utils
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/utils/noncopyable.h b/libtransport/includes/hicn/transport/utils/noncopyable.h new file mode 100644 index 000000000..83923e647 --- /dev/null +++ b/libtransport/includes/hicn/transport/utils/noncopyable.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#pragma once + +namespace utils { + +class NonCopyable { + protected: + NonCopyable() = default; + ~NonCopyable() = default; + + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; +}; + +} // namespace utils diff --git a/libtransport/includes/hicn/transport/utils/object_pool.h b/libtransport/includes/hicn/transport/utils/object_pool.h index f78bd2aa2..a5e8b2eef 100644 --- a/libtransport/includes/hicn/transport/utils/object_pool.h +++ b/libtransport/includes/hicn/transport/utils/object_pool.h @@ -17,6 +17,7 @@ // TODO #include <hicn/transport/utils/branch_prediction.h> +#include <hicn/transport/utils/log.h> #include <hicn/transport/utils/spinlock.h> #include <deque> @@ -33,6 +34,7 @@ class ObjectPool { void operator()(T *t) { if (pool_) { + TRANSPORT_LOGV("Back in pool"); pool_->add(t); } else { delete t; @@ -44,10 +46,13 @@ class ObjectPool { }; public: - using Ptr = std::unique_ptr<T, ObjectDeleter>; + using Ptr = std::shared_ptr<T>; ObjectPool() : destructor_(false) {} + // No copies + ObjectPool(const ObjectPool &other) = delete; + ~ObjectPool() { destructor_ = true; for (auto &ptr : object_pool_) { @@ -55,12 +60,17 @@ class ObjectPool { } } + bool empty() { + utils::SpinLock::Acquire locked(object_pool_lock_); + return object_pool_.empty(); + } + std::pair<bool, Ptr> get() { + utils::SpinLock::Acquire locked(object_pool_lock_); if (object_pool_.empty()) { - return std::make_pair<bool, Ptr>(false, makePtr(nullptr)); + return std::make_pair<bool, Ptr>(false, nullptr); } - utils::SpinLock::Acquire locked(object_pool_lock_); auto ret = std::move(object_pool_.front()); object_pool_.pop_front(); return std::make_pair<bool, Ptr>(true, std::move(ret)); @@ -70,7 +80,7 @@ class ObjectPool { utils::SpinLock::Acquire locked(object_pool_lock_); if (TRANSPORT_EXPECT_TRUE(!destructor_)) { - object_pool_.emplace_back(makePtr(object)); + object_pool_.emplace_front(makePtr(object)); } else { delete object; } @@ -79,12 +89,9 @@ class ObjectPool { Ptr makePtr(T *object) { return Ptr(object, ObjectDeleter(this)); } private: - // No copies - ObjectPool(const ObjectPool &other) = delete; - utils::SpinLock object_pool_lock_; std::deque<Ptr> object_pool_; - bool destructor_; + std::atomic<bool> destructor_; }; -} // namespace utils
\ No newline at end of file +} // namespace utils diff --git a/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h b/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h new file mode 100644 index 000000000..3387997b5 --- /dev/null +++ b/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + */ + +#pragma once + +#include <memory> + +namespace utils { + +template <typename Base> +inline std::shared_ptr<Base> shared_from_base( + std::enable_shared_from_this<Base>* base) { + return base->shared_from_this(); +} + +template <typename Base> +inline std::shared_ptr<const Base> shared_from_base( + std::enable_shared_from_this<Base> const* base) { + return base->shared_from_this(); +} + +template <typename That> +inline std::shared_ptr<That> shared_from(That* that) { + return std::static_pointer_cast<That>(shared_from_base(that)); +} + +} // namespace utils
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/utils/singleton.h b/libtransport/includes/hicn/transport/utils/singleton.h new file mode 100644 index 000000000..7fd8b912f --- /dev/null +++ b/libtransport/includes/hicn/transport/utils/singleton.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#pragma once + +#include <hicn/transport/utils/noncopyable.h> + +namespace utils { + +template <typename T> +class Singleton { + public: + static T& getInstance() { + static T instance; + return instance; + } + + protected: + Singleton() {} + ~Singleton() {} + + public: + Singleton(Singleton const&) = delete; + Singleton& operator=(Singleton const&) = delete; +}; + +} // namespace utils
\ No newline at end of file diff --git a/libtransport/includes/hicn/transport/utils/string_utils.h b/libtransport/includes/hicn/transport/utils/string_utils.h index bfda816f1..313c28cc6 100644 --- a/libtransport/includes/hicn/transport/utils/string_utils.h +++ b/libtransport/includes/hicn/transport/utils/string_utils.h @@ -72,4 +72,4 @@ static inline std::string trim_copy(std::string s) { return s; } -}
\ No newline at end of file +} // namespace utils
\ No newline at end of file |