diff options
Diffstat (limited to 'libtransport/src/core/manifest_format_fixed.cc')
-rw-r--r-- | libtransport/src/core/manifest_format_fixed.cc | 375 |
1 files changed, 248 insertions, 127 deletions
diff --git a/libtransport/src/core/manifest_format_fixed.cc b/libtransport/src/core/manifest_format_fixed.cc index ca80c38b1..bda666c0c 100644 --- a/libtransport/src/core/manifest_format_fixed.cc +++ b/libtransport/src/core/manifest_format_fixed.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 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: @@ -13,215 +13,336 @@ * limitations under the License. */ +#include <core/manifest_format_fixed.h> #include <hicn/transport/core/packet.h> #include <hicn/transport/utils/literals.h> -#include <core/manifest_format_fixed.h> - namespace transport { - namespace core { -// TODO use preallocated pool of membufs -FixedManifestEncoder::FixedManifestEncoder(Packet &packet, - std::size_t signature_size) +// --------------------------------------------------------- +// FixedManifest +// --------------------------------------------------------- +size_t FixedManifest::manifestHeaderSize( + interface::ProductionProtocolAlgorithms transport_type) { + uint32_t params_size = 0; + + switch (transport_type) { + case interface::ProductionProtocolAlgorithms::BYTE_STREAM: + params_size = MANIFEST_PARAMS_BYTESTREAM_SIZE; + break; + case interface::ProductionProtocolAlgorithms::RTC_PROD: + params_size = MANIFEST_PARAMS_RTC_SIZE; + break; + default: + break; + } + + return MANIFEST_META_SIZE + MANIFEST_ENTRY_META_SIZE + params_size; +} + +size_t FixedManifest::manifestPayloadSize(size_t nb_entries) { + return nb_entries * MANIFEST_ENTRY_SIZE; +} + +// --------------------------------------------------------- +// FixedManifestEncoder +// --------------------------------------------------------- +FixedManifestEncoder::FixedManifestEncoder(Packet::Ptr packet, bool clear) : packet_(packet), - max_size_(Packet::default_mtu - packet_.headerSize() - signature_size), - manifest_( - utils::MemBuf::create(Packet::default_mtu - packet_.headerSize())), - manifest_header_( - reinterpret_cast<ManifestHeader *>(manifest_->writableData())), - manifest_entries_(reinterpret_cast<ManifestEntry *>( - manifest_->writableData() + sizeof(ManifestHeader))), - current_entry_(0), - signature_size_(signature_size) { - *manifest_header_ = {0}; + transport_type_(interface::ProductionProtocolAlgorithms::UNKNOWN), + encoded_(false) { + manifest_meta_ = reinterpret_cast<ManifestMeta *>(packet_->writableData() + + packet_->headerSize()); + manifest_entry_meta_ = + reinterpret_cast<ManifestEntryMeta *>(manifest_meta_ + 1); + + if (clear) { + *manifest_meta_ = {0}; + *manifest_entry_meta_ = {0}; + } } FixedManifestEncoder::~FixedManifestEncoder() {} FixedManifestEncoder &FixedManifestEncoder::encodeImpl() { - manifest_->append(sizeof(ManifestHeader) + - manifest_header_->number_of_entries * - sizeof(ManifestEntry)); - packet_.appendPayload(std::move(manifest_)); + if (encoded_) { + return *this; + } + + // Copy manifest header + manifest_meta_->transport_type = static_cast<uint8_t>(transport_type_); + manifest_entry_meta_->nb_entries = manifest_entries_.size(); + + packet_->append(manifestHeaderSizeImpl()); + + packet_->updateLength(); + auto params = reinterpret_cast<uint8_t *>(manifest_entry_meta_ + 1); + + switch (transport_type_) { + case interface::ProductionProtocolAlgorithms::BYTE_STREAM: { + auto bytestream = reinterpret_cast<const uint8_t *>(¶ms_bytestream_); + std::memcpy(params, bytestream, MANIFEST_PARAMS_BYTESTREAM_SIZE); + break; + } + case interface::ProductionProtocolAlgorithms::RTC_PROD: { + auto rtc = reinterpret_cast<const uint8_t *>(¶ms_rtc_); + std::memcpy(params, rtc, MANIFEST_PARAMS_RTC_SIZE); + break; + } + default: + break; + } + + // Copy manifest entries + auto payload = reinterpret_cast<const uint8_t *>(manifest_entries_.data()); + packet_->appendPayload(payload, manifestPayloadSizeImpl()); + + packet_->updateLength(); + if (TRANSPORT_EXPECT_FALSE(packet_->payloadSize() < manifestSizeImpl())) { + throw errors::RuntimeException("Error encoding the manifest"); + } + + encoded_ = true; return *this; } FixedManifestEncoder &FixedManifestEncoder::clearImpl() { - manifest_ = utils::MemBuf::create(Packet::default_mtu - packet_.headerSize() - - signature_size_); + if (encoded_) { + packet_->trimEnd(manifestSizeImpl()); + } + + transport_type_ = interface::ProductionProtocolAlgorithms::UNKNOWN; + encoded_ = false; + *manifest_meta_ = {0}; + *manifest_entry_meta_ = {0}; + params_bytestream_ = {0}; + params_rtc_ = {0}; + manifest_entries_.clear(); + return *this; } -FixedManifestEncoder &FixedManifestEncoder::setHashAlgorithmImpl( - utils::CryptoHashType algorithm) { - manifest_header_->hash_algorithm = static_cast<uint8_t>(algorithm); +bool FixedManifestEncoder::isEncodedImpl() const { return encoded_; } + +FixedManifestEncoder &FixedManifestEncoder::setTypeImpl( + ManifestType manifest_type) { + manifest_meta_->type = static_cast<uint8_t>(manifest_type); return *this; } -FixedManifestEncoder &FixedManifestEncoder::setManifestTypeImpl( - ManifestType manifest_type) { - manifest_header_->manifest_type = static_cast<uint8_t>(manifest_type); +FixedManifestEncoder &FixedManifestEncoder::setMaxCapacityImpl( + uint8_t max_capacity) { + manifest_meta_->max_capacity = max_capacity; + return *this; +} + +FixedManifestEncoder &FixedManifestEncoder::setHashAlgorithmImpl( + auth::CryptoHashType algorithm) { + manifest_meta_->hash_algorithm = static_cast<uint8_t>(algorithm); return *this; } -FixedManifestEncoder & -FixedManifestEncoder::setNextSegmentCalculationStrategyImpl( - NextSegmentCalculationStrategy strategy) { - manifest_header_->next_segment_strategy = static_cast<uint8_t>(strategy); +FixedManifestEncoder &FixedManifestEncoder::setIsLastImpl(bool is_last) { + manifest_meta_->is_last = static_cast<uint8_t>(is_last); return *this; } FixedManifestEncoder &FixedManifestEncoder::setBaseNameImpl( const core::Name &base_name) { - base_name.copyToDestination( - reinterpret_cast<uint8_t *>(&manifest_header_->prefix[0]), false); - manifest_header_->flags.ipv6 = + manifest_entry_meta_->is_ipv6 = base_name.getAddressFamily() == AF_INET6 ? 1_U8 : 0_U8; + base_name.copyPrefixToDestination( + reinterpret_cast<uint8_t *>(&manifest_entry_meta_->prefix[0])); return *this; } -FixedManifestEncoder &FixedManifestEncoder::addSuffixAndHashImpl( - uint32_t suffix, const utils::CryptoHash &hash) { - auto _hash = hash.getDigest<std::uint8_t>(); - addSuffixHashBytes(suffix, _hash.data(), _hash.length()); +FixedManifestEncoder &FixedManifestEncoder::setParamsBytestreamImpl( + const ParamsBytestream ¶ms) { + transport_type_ = interface::ProductionProtocolAlgorithms::BYTE_STREAM; + params_bytestream_ = TransportParamsBytestream{ + .final_segment = params.final_segment, + }; return *this; } -void FixedManifestEncoder::addSuffixHashBytes(uint32_t suffix, - const uint8_t *hash, - std::size_t length) { - manifest_entries_[current_entry_].suffix = htonl(suffix); - // std::copy(hash, hash + length, - // manifest_entries_[current_entry_].hash); - std::memcpy( - reinterpret_cast<uint8_t *>(manifest_entries_[current_entry_].hash), hash, - length); +FixedManifestEncoder &FixedManifestEncoder::setParamsRTCImpl( + const ParamsRTC ¶ms) { + transport_type_ = interface::ProductionProtocolAlgorithms::RTC_PROD; + params_rtc_ = TransportParamsRTC{ + .timestamp = params.timestamp, + .prod_rate = params.prod_rate, + .prod_seg = params.prod_seg, + .fec_type = static_cast<uint32_t>(params.fec_type), + }; + return *this; +} - manifest_header_->number_of_entries++; - current_entry_++; +FixedManifestEncoder &FixedManifestEncoder::addEntryImpl( + uint32_t suffix, const auth::CryptoHash &hash) { + ManifestEntry last_entry = { + .suffix = portability::host_to_net(suffix), + .hash = {0}, + }; - if (TRANSPORT_EXPECT_FALSE(estimateSerializedLengthImpl() > max_size_)) { - throw errors::RuntimeException("Manifest size exceeded the packet MTU!"); - } -} + auto last_hash = reinterpret_cast<uint8_t *>(last_entry.hash); + std::memcpy(last_hash, hash.getDigest()->data(), hash.getSize()); -FixedManifestEncoder &FixedManifestEncoder::setIsFinalManifestImpl( - bool is_last) { - manifest_header_->flags.is_last = static_cast<uint8_t>(is_last); + manifest_entries_.push_back(last_entry); return *this; } -FixedManifestEncoder &FixedManifestEncoder::setVersionImpl( - ManifestVersion version) { - manifest_header_->version = static_cast<uint8_t>(version); +FixedManifestEncoder &FixedManifestEncoder::removeEntryImpl(uint32_t suffix) { + for (auto it = manifest_entries_.begin(); it != manifest_entries_.end();) { + if (it->suffix == suffix) + it = manifest_entries_.erase(it); + else + ++it; + } return *this; } -std::size_t FixedManifestEncoder::estimateSerializedLengthImpl( - std::size_t additional_entries) { - return sizeof(ManifestHeader) + - (manifest_header_->number_of_entries + additional_entries) * - sizeof(ManifestEntry); -} - -FixedManifestEncoder &FixedManifestEncoder::updateImpl() { - max_size_ = Packet::default_mtu - packet_.headerSize() - signature_size_; - return *this; +size_t FixedManifestEncoder::manifestHeaderSizeImpl() const { + return FixedManifest::manifestHeaderSize(transport_type_); } -FixedManifestEncoder &FixedManifestEncoder::setFinalBlockNumberImpl( - std::uint32_t final_block_number) { - manifest_header_->final_block_number = htonl(final_block_number); - return *this; +size_t FixedManifestEncoder::manifestPayloadSizeImpl( + size_t additional_entries) const { + return FixedManifest::manifestPayloadSize(manifest_entries_.size() + + additional_entries); } -std::size_t FixedManifestEncoder::getManifestHeaderSizeImpl() { - return sizeof(ManifestHeader); +size_t FixedManifestEncoder::manifestSizeImpl(size_t additional_entries) const { + return manifestHeaderSizeImpl() + manifestPayloadSizeImpl(additional_entries); } -std::size_t FixedManifestEncoder::getManifestEntrySizeImpl() { - return sizeof(ManifestEntry); +// --------------------------------------------------------- +// FixedManifestDecoder +// --------------------------------------------------------- +FixedManifestDecoder::FixedManifestDecoder(Packet::Ptr packet) + : packet_(packet), decoded_(false) { + manifest_meta_ = + reinterpret_cast<ManifestMeta *>(packet_->getPayload()->writableData()); + manifest_entry_meta_ = + reinterpret_cast<ManifestEntryMeta *>(manifest_meta_ + 1); } -FixedManifestDecoder::FixedManifestDecoder(Packet &packet) - : packet_(packet), - manifest_header_(reinterpret_cast<ManifestHeader *>( - packet_.getPayload()->writableData())), - manifest_entries_(reinterpret_cast<ManifestEntry *>( - packet_.getPayload()->writableData() + sizeof(ManifestHeader))) {} - FixedManifestDecoder::~FixedManifestDecoder() {} -void FixedManifestDecoder::decodeImpl() { - std::size_t packet_size = packet_.payloadSize(); +FixedManifestDecoder &FixedManifestDecoder::decodeImpl() { + if (decoded_) { + return *this; + } - if (packet_size < sizeof(ManifestHeader) || - packet_size < estimateSerializedLengthImpl()) { + if (packet_->payloadSize() < manifestSizeImpl()) { throw errors::RuntimeException( - "The packet does not match expected manifest size."); + "The packet payload size does not match expected manifest size"); } -} -FixedManifestDecoder &FixedManifestDecoder::clearImpl() { return *this; } + switch (getTransportTypeImpl()) { + case interface::ProductionProtocolAlgorithms::BYTE_STREAM: + params_bytestream_ = reinterpret_cast<TransportParamsBytestream *>( + manifest_entry_meta_ + 1); + manifest_entries_ = + reinterpret_cast<ManifestEntry *>(params_bytestream_ + 1); + break; + case interface::ProductionProtocolAlgorithms::RTC_PROD: + params_rtc_ = + reinterpret_cast<TransportParamsRTC *>(manifest_entry_meta_ + 1); + manifest_entries_ = reinterpret_cast<ManifestEntry *>(params_rtc_ + 1); + break; + default: + manifest_entries_ = + reinterpret_cast<ManifestEntry *>(manifest_entry_meta_ + 1); + break; + } -ManifestType FixedManifestDecoder::getManifestTypeImpl() const { - return static_cast<ManifestType>(manifest_header_->manifest_type); + decoded_ = true; + return *this; } -utils::CryptoHashType FixedManifestDecoder::getHashAlgorithmImpl() const { - return static_cast<utils::CryptoHashType>(manifest_header_->hash_algorithm); +FixedManifestDecoder &FixedManifestDecoder::clearImpl() { + decoded_ = false; + return *this; } -NextSegmentCalculationStrategy -FixedManifestDecoder::getNextSegmentCalculationStrategyImpl() const { - return static_cast<NextSegmentCalculationStrategy>( - manifest_header_->next_segment_strategy); +bool FixedManifestDecoder::isDecodedImpl() const { return decoded_; } + +ManifestType FixedManifestDecoder::getTypeImpl() const { + return static_cast<ManifestType>(manifest_meta_->type); } -typename Fixed::SuffixList FixedManifestDecoder::getSuffixHashListImpl() { - typename Fixed::SuffixList hash_list; +interface::ProductionProtocolAlgorithms +FixedManifestDecoder::getTransportTypeImpl() const { + return static_cast<interface::ProductionProtocolAlgorithms>( + manifest_meta_->transport_type); +} - for (int i = 0; i < manifest_header_->number_of_entries; i++) { - hash_list.insert(hash_list.end(), - std::make_pair(ntohl(manifest_entries_[i].suffix), - reinterpret_cast<uint8_t *>( - &manifest_entries_[i].hash[0]))); - } +uint8_t FixedManifestDecoder::getMaxCapacityImpl() const { + return manifest_meta_->max_capacity; +} - return hash_list; +auth::CryptoHashType FixedManifestDecoder::getHashAlgorithmImpl() const { + return static_cast<auth::CryptoHashType>(manifest_meta_->hash_algorithm); +} + +bool FixedManifestDecoder::getIsLastImpl() const { + return static_cast<bool>(manifest_meta_->is_last); } core::Name FixedManifestDecoder::getBaseNameImpl() const { - if (static_cast<bool>(manifest_header_->flags.ipv6)) { - return core::Name(AF_INET6, - reinterpret_cast<uint8_t *>(&manifest_header_->prefix)); + if (static_cast<bool>(manifest_entry_meta_->is_ipv6)) { + return core::Name( + AF_INET6, reinterpret_cast<uint8_t *>(&manifest_entry_meta_->prefix)); } else { - return core::Name(AF_INET, - reinterpret_cast<uint8_t *>(&manifest_header_->prefix)); + return core::Name( + AF_INET, reinterpret_cast<uint8_t *>(&manifest_entry_meta_->prefix)); } } -bool FixedManifestDecoder::getIsFinalManifestImpl() const { - return static_cast<bool>(manifest_header_->flags.is_last); +ParamsBytestream FixedManifestDecoder::getParamsBytestreamImpl() const { + return ParamsBytestream{ + .final_segment = params_bytestream_->final_segment, + }; } -ManifestVersion FixedManifestDecoder::getVersionImpl() const { - return static_cast<ManifestVersion>(manifest_header_->version); +ParamsRTC FixedManifestDecoder::getParamsRTCImpl() const { + return ParamsRTC{ + .timestamp = params_rtc_->timestamp, + .prod_rate = params_rtc_->prod_rate, + .prod_seg = params_rtc_->prod_seg, + .fec_type = static_cast<protocol::fec::FECType>(params_rtc_->fec_type), + }; } -std::size_t FixedManifestDecoder::estimateSerializedLengthImpl( - std::size_t additional_entries) const { - return sizeof(ManifestHeader) + - (additional_entries + manifest_header_->number_of_entries) * - sizeof(ManifestEntry); +typename Fixed::SuffixList FixedManifestDecoder::getEntriesImpl() const { + typename Fixed::SuffixList hash_list; + + for (int i = 0; i < manifest_entry_meta_->nb_entries; i++) { + hash_list.insert( + hash_list.end(), + std::make_pair( + portability::net_to_host(manifest_entries_[i].suffix), + reinterpret_cast<uint8_t *>(&manifest_entries_[i].hash[0]))); + } + + return hash_list; } -uint32_t FixedManifestDecoder::getFinalBlockNumberImpl() const { - return ntohl(manifest_header_->final_block_number); +size_t FixedManifestDecoder::manifestHeaderSizeImpl() const { + interface::ProductionProtocolAlgorithms type = getTransportTypeImpl(); + return FixedManifest::manifestHeaderSize(type); } -} // end namespace core +size_t FixedManifestDecoder::manifestPayloadSizeImpl( + size_t additional_entries) const { + size_t nb_entries = manifest_entry_meta_->nb_entries + additional_entries; + return FixedManifest::manifestPayloadSize(nb_entries); +} +size_t FixedManifestDecoder::manifestSizeImpl(size_t additional_entries) const { + return manifestHeaderSizeImpl() + manifestPayloadSizeImpl(additional_entries); +} + +} // end namespace core } // end namespace transport |