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-2022 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 namespace util {
28 
29 Segmenter::Segmenter(KeyChain& keyChain, const security::SigningInfo& signingInfo)
30  : m_keyChain(keyChain)
31  , m_signingInfo(signingInfo)
32 {
33 }
34 
35 std::vector<std::shared_ptr<Data>>
36 Segmenter::segment(span<const uint8_t> buffer, const Name& dataName, size_t maxSegmentSize,
37  time::milliseconds freshnessPeriod, uint32_t contentType)
38 {
39  if (maxSegmentSize == 0) {
40  NDN_THROW(std::invalid_argument("maxSegmentSize must be greater than 0"));
41  }
42 
43  // minimum of one (possibly empty) segment
44  const uint64_t numSegments = 1 + (buffer.size() - !buffer.empty()) / maxSegmentSize;
45  const auto finalBlockId = name::Component::fromSegment(numSegments - 1);
46 
47  std::vector<std::shared_ptr<Data>> segments;
48  segments.reserve(numSegments);
49 
50  do {
51  auto segLen = std::min(buffer.size(), maxSegmentSize);
52 
53  auto data = std::make_shared<Data>();
54  data->setName(Name(dataName).appendSegment(segments.size()));
55  data->setContentType(contentType);
56  data->setFreshnessPeriod(freshnessPeriod);
57  data->setFinalBlock(finalBlockId);
58  data->setContent(buffer.first(segLen));
59 
60  m_keyChain.sign(*data, m_signingInfo);
61  segments.push_back(std::move(data));
62 
63  buffer = buffer.subspan(segLen);
64  } while (!buffer.empty());
65 
66  BOOST_ASSERT(segments.size() == numSegments);
67  return segments;
68 }
69 
70 std::vector<std::shared_ptr<Data>>
71 Segmenter::segment(std::istream& input, const Name& dataName, size_t maxSegmentSize,
72  time::milliseconds freshnessPeriod, uint32_t contentType)
73 {
74  if (maxSegmentSize == 0) {
75  NDN_THROW(std::invalid_argument("maxSegmentSize must be greater than 0"));
76  }
77 
78  std::vector<std::shared_ptr<Data>> segments;
79 
80  while (true) {
81  auto buffer = std::make_shared<Buffer>(maxSegmentSize);
82  auto n = boost::iostreams::read(input, buffer->get<char>(), buffer->size());
83  if (n < 0) { // EOF
84  break;
85  }
86  buffer->resize(n);
87 
88  auto data = std::make_shared<Data>();
89  data->setName(Name(dataName).appendSegment(segments.size()));
90  data->setContentType(contentType);
91  data->setFreshnessPeriod(freshnessPeriod);
92  data->setContent(std::move(buffer));
93 
94  segments.push_back(std::move(data));
95  }
96 
97  // ensure we return at least one (empty) segment
98  if (segments.empty()) {
99  auto data = std::make_shared<Data>();
100  data->setName(Name(dataName).appendSegment(0));
101  data->setContentType(contentType);
102  data->setFreshnessPeriod(freshnessPeriod);
103  segments.push_back(std::move(data));
104  }
105 
106  // add the FinalBlockId to each packet and sign
107  const auto finalBlockId = name::Component::fromSegment(segments.size() - 1);
108  for (const auto& data : segments) {
109  data->setFinalBlock(finalBlockId);
110  m_keyChain.sign(*data, m_signingInfo);
111  }
112 
113  return segments;
114 }
115 
116 } // namespace util
117 } // namespace ndn
Represents an absolute name.
Definition: name.hpp:44
static Component fromSegment(uint64_t segmentNo)
Create a segment number component using NDN naming conventions.
Signing parameters passed to KeyChain.
Segmenter(KeyChain &keyChain, const security::SigningInfo &signingInfo)
Constructor.
Definition: segmenter.cpp:29
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:36
#define NDN_THROW(e)
Definition: exception.hpp:61
boost::chrono::milliseconds milliseconds
Definition: time.hpp:48
@ Name
Definition: tlv.hpp:71
Definition: data.cpp:25