blob: 0d549156f4e1ae5aa924a013e47b6b9254050e7a [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/*
Davide Pesavento5afbb0b2018-01-01 17:24:18 -05003 * Copyright (c) 2013-2018 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>
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050029#include <cmath>
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080030
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070031namespace ndn {
32namespace util {
33
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050034const uint32_t SegmentFetcher::MAX_INTEREST_REEXPRESS = 3;
35
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070036SegmentFetcher::SegmentFetcher(Face& face,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080037 shared_ptr<security::v2::Validator> validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070038 const CompleteCallback& completeCallback,
39 const ErrorCallback& errorCallback)
40 : m_face(face)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050041 , m_scheduler(m_face.getIoService())
42 , m_validator(validator)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070043 , m_completeCallback(completeCallback)
44 , m_errorCallback(errorCallback)
45 , m_buffer(make_shared<OBufferStream>())
46{
47}
48
49void
50SegmentFetcher::fetch(Face& face,
51 const Interest& baseInterest,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080052 security::v2::Validator& validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070053 const CompleteCallback& completeCallback,
54 const ErrorCallback& errorCallback)
55{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080056 shared_ptr<security::v2::Validator> validatorPtr(&validator, [] (security::v2::Validator*) {});
57 fetch(face, baseInterest, validatorPtr, completeCallback, errorCallback);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050058}
59
60void
61SegmentFetcher::fetch(Face& face,
62 const Interest& baseInterest,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080063 shared_ptr<security::v2::Validator> validator,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050064 const CompleteCallback& completeCallback,
65 const ErrorCallback& errorCallback)
66{
67 shared_ptr<SegmentFetcher> fetcher(new SegmentFetcher(face, validator, completeCallback,
68 errorCallback));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070069
70 fetcher->fetchFirstSegment(baseInterest, fetcher);
71}
72
73void
74SegmentFetcher::fetchFirstSegment(const Interest& baseInterest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050075 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070076{
77 Interest interest(baseInterest);
78 interest.setChildSelector(1);
79 interest.setMustBeFresh(true);
80
81 m_face.expressInterest(interest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050082 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, true, self),
83 bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070084 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
85}
86
87void
88SegmentFetcher::fetchNextSegment(const Interest& origInterest, const Name& dataName,
89 uint64_t segmentNo,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050090 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070091{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050092 Interest interest(origInterest); // to preserve any selectors
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070093 interest.refreshNonce();
94 interest.setChildSelector(0);
95 interest.setMustBeFresh(false);
96 interest.setName(dataName.getPrefix(-1).appendSegment(segmentNo));
97 m_face.expressInterest(interest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050098 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, false, self),
99 bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700100 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
101}
102
103void
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500104SegmentFetcher::afterSegmentReceived(const Interest& origInterest,
105 const Data& data, bool isSegmentZeroExpected,
106 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700107{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500108 m_validator->validate(data,
109 bind(&SegmentFetcher::afterValidationSuccess, this, _1,
110 isSegmentZeroExpected, origInterest, self),
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800111 bind(&SegmentFetcher::afterValidationFailure, this, _1, _2));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700112
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500113}
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700114
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500115void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800116SegmentFetcher::afterValidationSuccess(const Data& data,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500117 bool isSegmentZeroExpected,
118 const Interest& origInterest,
119 shared_ptr<SegmentFetcher> self)
120{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800121 name::Component currentSegment = data.getName().get(-1);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500122
123 if (currentSegment.isSegment()) {
124 if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800125 fetchNextSegment(origInterest, data.getName(), 0, self);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700126 }
127 else {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800128 m_buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
129 data.getContent().value_size());
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700130
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800131 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500132 if (finalBlockId.empty() || (finalBlockId > currentSegment)) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800133 fetchNextSegment(origInterest, data.getName(), currentSegment.toSegment() + 1, self);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500134 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700135 else {
136 return m_completeCallback(m_buffer->buf());
137 }
138 }
139 }
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500140 else {
141 m_errorCallback(DATA_HAS_NO_SEGMENT, "Data Name has no segment number.");
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700142 }
143}
144
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500145void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800146SegmentFetcher::afterValidationFailure(const Data& data, const security::v2::ValidationError& error)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500147{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800148 return m_errorCallback(SEGMENT_VALIDATION_FAIL, "Segment validation fail " +
149 boost::lexical_cast<std::string>(error));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500150}
151
152
153void
154SegmentFetcher::afterNackReceived(const Interest& origInterest, const lp::Nack& nack,
155 uint32_t reExpressCount, shared_ptr<SegmentFetcher> self)
156{
157 if (reExpressCount >= MAX_INTEREST_REEXPRESS) {
158 m_errorCallback(NACK_ERROR, "Nack Error");
159 }
160 else {
161 switch (nack.getReason()) {
162 case lp::NackReason::DUPLICATE:
163 reExpressInterest(origInterest, reExpressCount, self);
164 break;
165 case lp::NackReason::CONGESTION:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500166 using ms = time::milliseconds;
167 m_scheduler.scheduleEvent(ms(static_cast<ms::rep>(std::pow(2, reExpressCount + 1))),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500168 bind(&SegmentFetcher::reExpressInterest, this,
169 origInterest, reExpressCount, self));
170 break;
171 default:
172 m_errorCallback(NACK_ERROR, "Nack Error");
173 break;
174 }
175 }
176}
177
178void
179SegmentFetcher::reExpressInterest(Interest interest, uint32_t reExpressCount,
180 shared_ptr<SegmentFetcher> self)
181{
182 interest.refreshNonce();
183 BOOST_ASSERT(interest.hasNonce());
184
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500185 bool isSegmentZeroExpected = true;
186 if (!interest.getName().empty()) {
187 name::Component lastComponent = interest.getName().get(-1);
188 isSegmentZeroExpected = !lastComponent.isSegment();
189 }
190
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500191 m_face.expressInterest(interest,
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500192 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2,
193 isSegmentZeroExpected, self),
194 bind(&SegmentFetcher::afterNackReceived, this, _1, _2,
195 ++reExpressCount, self),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500196 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
197}
198
199} // namespace util
200} // namespace ndn