segmenter.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2023 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
23 
24 #include <boost/iostreams/read.hpp>
25 
26 namespace ndn {
27 
28 Segmenter::Segmenter(KeyChain& keyChain, const security::SigningInfo& signingInfo)
29  : m_keyChain(keyChain)
30  , m_signingInfo(signingInfo)
31 {
32 }
33 
34 std::vector<std::shared_ptr<Data>>
35 Segmenter::segment(span<const uint8_t> buffer, const Name& dataName, size_t maxSegmentSize,
36  time::milliseconds freshnessPeriod, uint32_t contentType)
37 {
38  if (maxSegmentSize == 0) {
39  NDN_THROW(std::invalid_argument("maxSegmentSize must be greater than 0"));
40  }
41 
42  // minimum of one (possibly empty) segment
43  const uint64_t numSegments = 1 + (buffer.size() - !buffer.empty()) / maxSegmentSize;
44  const auto finalBlockId = name::Component::fromSegment(numSegments - 1);
45 
46  std::vector<std::shared_ptr<Data>> segments;
47  segments.reserve(numSegments);
48 
49  do {
50  auto segLen = std::min(buffer.size(), maxSegmentSize);
51 
52  auto data = std::make_shared<Data>();
53  data->setName(Name(dataName).appendSegment(segments.size()));
54  data->setContentType(contentType);
55  data->setFreshnessPeriod(freshnessPeriod);
56  data->setFinalBlock(finalBlockId);
57  data->setContent(buffer.first(segLen));
58 
59  m_keyChain.sign(*data, m_signingInfo);
60  segments.push_back(std::move(data));
61 
62  buffer = buffer.subspan(segLen);
63  } while (!buffer.empty());
64 
65  BOOST_ASSERT(segments.size() == numSegments);
66  return segments;
67 }
68 
69 std::vector<std::shared_ptr<Data>>
70 Segmenter::segment(std::istream& input, const Name& dataName, size_t maxSegmentSize,
71  time::milliseconds freshnessPeriod, uint32_t contentType)
72 {
73  if (maxSegmentSize == 0) {
74  NDN_THROW(std::invalid_argument("maxSegmentSize must be greater than 0"));
75  }
76 
77  std::vector<std::shared_ptr<Data>> segments;
78 
79  while (true) {
80  auto buffer = std::make_shared<Buffer>(maxSegmentSize);
81  auto n = boost::iostreams::read(input, buffer->get<char>(), buffer->size());
82  if (n < 0) { // EOF
83  break;
84  }
85  buffer->resize(n);
86 
87  auto data = std::make_shared<Data>();
88  data->setName(Name(dataName).appendSegment(segments.size()));
89  data->setContentType(contentType);
90  data->setFreshnessPeriod(freshnessPeriod);
91  data->setContent(std::move(buffer));
92 
93  segments.push_back(std::move(data));
94  }
95 
96  // ensure we return at least one (empty) segment
97  if (segments.empty()) {
98  auto data = std::make_shared<Data>();
99  data->setName(Name(dataName).appendSegment(0));
100  data->setContentType(contentType);
101  data->setFreshnessPeriod(freshnessPeriod);
102  segments.push_back(std::move(data));
103  }
104 
105  // add the FinalBlockId to each packet and sign
106  const auto finalBlockId = name::Component::fromSegment(segments.size() - 1);
107  for (const auto& data : segments) {
108  data->setFinalBlock(finalBlockId);
109  m_keyChain.sign(*data, m_signingInfo);
110  }
111 
112  return segments;
113 }
114 
115 } // namespace ndn
Represents an absolute name.
Definition: name.hpp:45
Segmenter(KeyChain &keyChain, const security::SigningInfo &signingInfo)
Constructor.
Definition: segmenter.cpp:28
std::vector< std::shared_ptr< Data > > segment(span< const uint8_t > buffer, const Name &dataName, size_t maxSegmentSize, time::milliseconds freshnessPeriod, uint32_t contentType=tlv::ContentType_Blob)
Splits a blob of bytes into one or more Data packets (segments).
Definition: segmenter.cpp:35
static Component fromSegment(uint64_t segmentNo)
Create a segment number component using NDN naming conventions.
The main interface for signing key management.
Definition: key-chain.hpp:87
void sign(Data &data, const SigningInfo &params=SigningInfo())
Sign a Data packet according to the supplied signing information.
Definition: key-chain.cpp:400
Signing parameters passed to KeyChain.
#define NDN_THROW(e)
Definition: exception.hpp:56
::boost::chrono::milliseconds milliseconds
Definition: time.hpp:52
@ Name
Definition: tlv.hpp:71
Definition: data.cpp:25