segment-fetcher.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22 #include "segment-fetcher.hpp"
23 #include "../encoding/buffer-stream.hpp"
24 #include "../name-component.hpp"
25 #include "../lp/nack.hpp"
26 #include "../lp/nack-header.hpp"
27 
28 namespace ndn {
29 namespace util {
30 
32 
33 SegmentFetcher::SegmentFetcher(Face& face,
34  shared_ptr<Validator> validator,
35  const CompleteCallback& completeCallback,
36  const ErrorCallback& errorCallback)
37  : m_face(face)
38  , m_scheduler(m_face.getIoService())
39  , m_validator(validator)
40  , m_completeCallback(completeCallback)
41  , m_errorCallback(errorCallback)
42  , m_buffer(make_shared<OBufferStream>())
43 {
44 }
45 
46 void
47 SegmentFetcher::fetch(Face& face,
48  const Interest& baseInterest,
49  Validator& validator,
50  const CompleteCallback& completeCallback,
51  const ErrorCallback& errorCallback)
52 {
53  shared_ptr<Validator> sharedValidator = shared_ptr<Validator>(&validator, [] (Validator*) {});
54 
55  fetch(face, baseInterest, sharedValidator, completeCallback, errorCallback);
56 }
57 
58 void
59 SegmentFetcher::fetch(Face& face,
60  const Interest& baseInterest,
61  shared_ptr<Validator> validator,
62  const CompleteCallback& completeCallback,
63  const ErrorCallback& errorCallback)
64 {
65  shared_ptr<SegmentFetcher> fetcher(new SegmentFetcher(face, validator, completeCallback,
66  errorCallback));
67 
68  fetcher->fetchFirstSegment(baseInterest, fetcher);
69 }
70 
71 void
72 SegmentFetcher::fetchFirstSegment(const Interest& baseInterest,
73  shared_ptr<SegmentFetcher> self)
74 {
75  Interest interest(baseInterest);
76  interest.setChildSelector(1);
77  interest.setMustBeFresh(true);
78 
79  m_face.expressInterest(interest,
80  bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, true, self),
81  bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
82  bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
83 }
84 
85 void
86 SegmentFetcher::fetchNextSegment(const Interest& origInterest, const Name& dataName,
87  uint64_t segmentNo,
88  shared_ptr<SegmentFetcher> self)
89 {
90  Interest interest(origInterest); // to preserve any selectors
91  interest.refreshNonce();
92  interest.setChildSelector(0);
93  interest.setMustBeFresh(false);
94  interest.setName(dataName.getPrefix(-1).appendSegment(segmentNo));
95  m_face.expressInterest(interest,
96  bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, false, self),
97  bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
98  bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
99 }
100 
101 void
102 SegmentFetcher::afterSegmentReceived(const Interest& origInterest,
103  const Data& data, bool isSegmentZeroExpected,
104  shared_ptr<SegmentFetcher> self)
105 {
106  m_validator->validate(data,
107  bind(&SegmentFetcher::afterValidationSuccess, this, _1,
108  isSegmentZeroExpected, origInterest, self),
109  bind(&SegmentFetcher::afterValidationFailure, this, _1));
110 
111 }
112 
113 void
114 SegmentFetcher::afterValidationSuccess(const shared_ptr<const Data> data,
115  bool isSegmentZeroExpected,
116  const Interest& origInterest,
117  shared_ptr<SegmentFetcher> self)
118 {
119  name::Component currentSegment = data->getName().get(-1);
120 
121  if (currentSegment.isSegment()) {
122  if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
123  fetchNextSegment(origInterest, data->getName(), 0, self);
124  }
125  else {
126  m_buffer->write(reinterpret_cast<const char*>(data->getContent().value()),
127  data->getContent().value_size());
128 
129  const name::Component& finalBlockId = data->getMetaInfo().getFinalBlockId();
130  if (finalBlockId.empty() || (finalBlockId > currentSegment)) {
131  fetchNextSegment(origInterest, data->getName(), currentSegment.toSegment() + 1, self);
132  }
133  else {
134  return m_completeCallback(m_buffer->buf());
135  }
136  }
137  }
138  else {
139  m_errorCallback(DATA_HAS_NO_SEGMENT, "Data Name has no segment number.");
140  }
141 }
142 
143 void
144 SegmentFetcher::afterValidationFailure(const shared_ptr<const Data> data)
145 {
146  return m_errorCallback(SEGMENT_VALIDATION_FAIL, "Segment validation fail");
147 }
148 
149 
150 void
151 SegmentFetcher::afterNackReceived(const Interest& origInterest, const lp::Nack& nack,
152  uint32_t reExpressCount, shared_ptr<SegmentFetcher> self)
153 {
154  if (reExpressCount >= MAX_INTEREST_REEXPRESS) {
155  m_errorCallback(NACK_ERROR, "Nack Error");
156  }
157  else {
158  switch (nack.getReason()) {
160  reExpressInterest(origInterest, reExpressCount, self);
161  break;
163  m_scheduler.scheduleEvent(time::milliseconds(static_cast<uint32_t>(pow(2, reExpressCount + 1))),
164  bind(&SegmentFetcher::reExpressInterest, this,
165  origInterest, reExpressCount, self));
166  break;
167  default:
168  m_errorCallback(NACK_ERROR, "Nack Error");
169  break;
170  }
171  }
172 }
173 
174 void
175 SegmentFetcher::reExpressInterest(Interest interest, uint32_t reExpressCount,
176  shared_ptr<SegmentFetcher> self)
177 {
178  interest.refreshNonce();
179  BOOST_ASSERT(interest.hasNonce());
180 
181  bool isSegmentZeroExpected = true;
182  if (!interest.getName().empty()) {
183  name::Component lastComponent = interest.getName().get(-1);
184  isSegmentZeroExpected = !lastComponent.isSegment();
185  }
186 
187  m_face.expressInterest(interest,
188  bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2,
189  isSegmentZeroExpected, self),
190  bind(&SegmentFetcher::afterNackReceived, this, _1, _2,
191  ++reExpressCount, self),
192  bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
193 }
194 
195 } // namespace util
196 } // namespace ndn
Copyright (c) 2013-2016 Regents of the University of California.
Definition: common.hpp:74
ndn security v2 Validator
function< void(uint32_t code, const std::string &msg)> ErrorCallback
Utility class to fetch latest version of the segmented data.
represents an Interest packet
Definition: interest.hpp:42
function< void(const std::string &reason)> ErrorCallback
Definition: dns.hpp:79
Name & appendSegment(uint64_t segmentNo)
Append segment number (sequential) using NDN naming conventions.
Definition: name.cpp:220
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:121
Name abstraction to represent an absolute name.
Definition: name.hpp:46
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
Definition: name.hpp:241
static const uint32_t MAX_INTEREST_REEXPRESS
Maximum number of times an interest will be reexpressed incase of NackCallback.
function< void(const ConstBufferPtr &data)> CompleteCallback