blob: c8075e7cb3823b1cdbb152cc300556ed56a4a75b [file] [log] [blame]
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -08002/*
3 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07004 *
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
22#include "segment-fetcher.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070023#include "../encoding/buffer-stream.hpp"
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050024#include "../name-component.hpp"
25#include "../lp/nack.hpp"
26#include "../lp/nack-header.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070027
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080028#include <boost/lexical_cast.hpp>
29
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070030namespace ndn {
31namespace util {
32
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050033const uint32_t SegmentFetcher::MAX_INTEREST_REEXPRESS = 3;
34
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070035SegmentFetcher::SegmentFetcher(Face& face,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080036 shared_ptr<security::v2::Validator> validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070037 const CompleteCallback& completeCallback,
38 const ErrorCallback& errorCallback)
39 : m_face(face)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050040 , m_scheduler(m_face.getIoService())
41 , m_validator(validator)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070042 , m_completeCallback(completeCallback)
43 , m_errorCallback(errorCallback)
44 , m_buffer(make_shared<OBufferStream>())
45{
46}
47
48void
49SegmentFetcher::fetch(Face& face,
50 const Interest& baseInterest,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080051 security::v2::Validator& validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070052 const CompleteCallback& completeCallback,
53 const ErrorCallback& errorCallback)
54{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080055 shared_ptr<security::v2::Validator> validatorPtr(&validator, [] (security::v2::Validator*) {});
56 fetch(face, baseInterest, validatorPtr, completeCallback, errorCallback);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050057}
58
59void
60SegmentFetcher::fetch(Face& face,
61 const Interest& baseInterest,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080062 shared_ptr<security::v2::Validator> validator,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050063 const CompleteCallback& completeCallback,
64 const ErrorCallback& errorCallback)
65{
66 shared_ptr<SegmentFetcher> fetcher(new SegmentFetcher(face, validator, completeCallback,
67 errorCallback));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070068
69 fetcher->fetchFirstSegment(baseInterest, fetcher);
70}
71
72void
73SegmentFetcher::fetchFirstSegment(const Interest& baseInterest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050074 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070075{
76 Interest interest(baseInterest);
77 interest.setChildSelector(1);
78 interest.setMustBeFresh(true);
79
80 m_face.expressInterest(interest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050081 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, true, self),
82 bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070083 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
84}
85
86void
87SegmentFetcher::fetchNextSegment(const Interest& origInterest, const Name& dataName,
88 uint64_t segmentNo,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050089 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070090{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050091 Interest interest(origInterest); // to preserve any selectors
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070092 interest.refreshNonce();
93 interest.setChildSelector(0);
94 interest.setMustBeFresh(false);
95 interest.setName(dataName.getPrefix(-1).appendSegment(segmentNo));
96 m_face.expressInterest(interest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050097 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, false, self),
98 bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070099 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
100}
101
102void
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500103SegmentFetcher::afterSegmentReceived(const Interest& origInterest,
104 const Data& data, bool isSegmentZeroExpected,
105 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700106{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500107 m_validator->validate(data,
108 bind(&SegmentFetcher::afterValidationSuccess, this, _1,
109 isSegmentZeroExpected, origInterest, self),
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800110 bind(&SegmentFetcher::afterValidationFailure, this, _1, _2));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700111
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500112}
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700113
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500114void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800115SegmentFetcher::afterValidationSuccess(const Data& data,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500116 bool isSegmentZeroExpected,
117 const Interest& origInterest,
118 shared_ptr<SegmentFetcher> self)
119{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800120 name::Component currentSegment = data.getName().get(-1);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500121
122 if (currentSegment.isSegment()) {
123 if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800124 fetchNextSegment(origInterest, data.getName(), 0, self);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700125 }
126 else {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800127 m_buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
128 data.getContent().value_size());
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700129
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800130 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500131 if (finalBlockId.empty() || (finalBlockId > currentSegment)) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800132 fetchNextSegment(origInterest, data.getName(), currentSegment.toSegment() + 1, self);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500133 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700134 else {
135 return m_completeCallback(m_buffer->buf());
136 }
137 }
138 }
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500139 else {
140 m_errorCallback(DATA_HAS_NO_SEGMENT, "Data Name has no segment number.");
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700141 }
142}
143
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500144void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800145SegmentFetcher::afterValidationFailure(const Data& data, const security::v2::ValidationError& error)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500146{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800147 return m_errorCallback(SEGMENT_VALIDATION_FAIL, "Segment validation fail " +
148 boost::lexical_cast<std::string>(error));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500149}
150
151
152void
153SegmentFetcher::afterNackReceived(const Interest& origInterest, const lp::Nack& nack,
154 uint32_t reExpressCount, shared_ptr<SegmentFetcher> self)
155{
156 if (reExpressCount >= MAX_INTEREST_REEXPRESS) {
157 m_errorCallback(NACK_ERROR, "Nack Error");
158 }
159 else {
160 switch (nack.getReason()) {
161 case lp::NackReason::DUPLICATE:
162 reExpressInterest(origInterest, reExpressCount, self);
163 break;
164 case lp::NackReason::CONGESTION:
165 m_scheduler.scheduleEvent(time::milliseconds(static_cast<uint32_t>(pow(2, reExpressCount + 1))),
166 bind(&SegmentFetcher::reExpressInterest, this,
167 origInterest, reExpressCount, self));
168 break;
169 default:
170 m_errorCallback(NACK_ERROR, "Nack Error");
171 break;
172 }
173 }
174}
175
176void
177SegmentFetcher::reExpressInterest(Interest interest, uint32_t reExpressCount,
178 shared_ptr<SegmentFetcher> self)
179{
180 interest.refreshNonce();
181 BOOST_ASSERT(interest.hasNonce());
182
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500183 bool isSegmentZeroExpected = true;
184 if (!interest.getName().empty()) {
185 name::Component lastComponent = interest.getName().get(-1);
186 isSegmentZeroExpected = !lastComponent.isSegment();
187 }
188
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500189 m_face.expressInterest(interest,
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500190 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2,
191 isSegmentZeroExpected, self),
192 bind(&SegmentFetcher::afterNackReceived, this, _1, _2,
193 ++reExpressCount, self),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500194 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
195}
196
197} // namespace util
198} // namespace ndn