blob: 0d53aaf62fcdb26deec7bd29af9f7ce9ac4283d3 [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"
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050023#include "../name-component.hpp"
24#include "../lp/nack.hpp"
25#include "../lp/nack-header.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070026
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080027#include <boost/lexical_cast.hpp>
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050028#include <cmath>
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080029
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
Eric Newberrycc910cd2018-05-06 17:01:40 -070035SegmentFetcher::SegmentFetcher(Face& face, security::v2::Validator& validator)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070036 : m_face(face)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050037 , m_scheduler(m_face.getIoService())
38 , m_validator(validator)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070039{
40}
41
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000042shared_ptr<SegmentFetcher>
Eric Newberrycc910cd2018-05-06 17:01:40 -070043SegmentFetcher::start(Face& face,
44 const Interest& baseInterest,
45 security::v2::Validator& validator)
46{
47 shared_ptr<SegmentFetcher> fetcher(new SegmentFetcher(face, validator));
48 fetcher->fetchFirstSegment(baseInterest, fetcher);
49 return fetcher;
50}
51
52shared_ptr<SegmentFetcher>
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070053SegmentFetcher::fetch(Face& face,
54 const Interest& baseInterest,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080055 security::v2::Validator& validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070056 const CompleteCallback& completeCallback,
57 const ErrorCallback& errorCallback)
58{
Eric Newberrycc910cd2018-05-06 17:01:40 -070059 shared_ptr<SegmentFetcher> fetcher = start(face, baseInterest, validator);
60 fetcher->onComplete.connect(completeCallback);
61 fetcher->onError.connect(errorCallback);
62 return fetcher;
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050063}
64
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000065shared_ptr<SegmentFetcher>
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050066SegmentFetcher::fetch(Face& face,
67 const Interest& baseInterest,
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -080068 shared_ptr<security::v2::Validator> validator,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050069 const CompleteCallback& completeCallback,
70 const ErrorCallback& errorCallback)
71{
Eric Newberrycc910cd2018-05-06 17:01:40 -070072 auto fetcher = fetch(face, baseInterest, *validator, completeCallback, errorCallback);
73 fetcher->onComplete.connect([validator] (ConstBufferPtr) {});
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000074 return fetcher;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070075}
76
77void
78SegmentFetcher::fetchFirstSegment(const Interest& baseInterest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050079 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070080{
81 Interest interest(baseInterest);
82 interest.setChildSelector(1);
83 interest.setMustBeFresh(true);
84
85 m_face.expressInterest(interest,
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000086 bind(&SegmentFetcher::afterSegmentReceivedCb, this, _1, _2, true, self),
87 bind(&SegmentFetcher::afterNackReceivedCb, this, _1, _2, 0, self),
Eric Newberrycc910cd2018-05-06 17:01:40 -070088 bind([this] { onError(INTEREST_TIMEOUT, "Timeout"); }));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070089}
90
91void
92SegmentFetcher::fetchNextSegment(const Interest& origInterest, const Name& dataName,
93 uint64_t segmentNo,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050094 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070095{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050096 Interest interest(origInterest); // to preserve any selectors
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070097 interest.refreshNonce();
98 interest.setChildSelector(0);
99 interest.setMustBeFresh(false);
100 interest.setName(dataName.getPrefix(-1).appendSegment(segmentNo));
101 m_face.expressInterest(interest,
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000102 bind(&SegmentFetcher::afterSegmentReceivedCb, this, _1, _2, false, self),
103 bind(&SegmentFetcher::afterNackReceivedCb, this, _1, _2, 0, self),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700104 bind([this] { onError(INTEREST_TIMEOUT, "Timeout"); }));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700105}
106
107void
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000108SegmentFetcher::afterSegmentReceivedCb(const Interest& origInterest,
109 const Data& data, bool isSegmentZeroExpected,
110 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700111{
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000112 afterSegmentReceived(data);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700113 m_validator.validate(data,
114 bind(&SegmentFetcher::afterValidationSuccess, this, _1,
115 isSegmentZeroExpected, origInterest, self),
116 bind(&SegmentFetcher::afterValidationFailure, this, _1, _2));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700117
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500118}
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700119
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500120void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800121SegmentFetcher::afterValidationSuccess(const Data& data,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500122 bool isSegmentZeroExpected,
123 const Interest& origInterest,
124 shared_ptr<SegmentFetcher> self)
125{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800126 name::Component currentSegment = data.getName().get(-1);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500127
128 if (currentSegment.isSegment()) {
129 if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800130 fetchNextSegment(origInterest, data.getName(), 0, self);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700131 }
132 else {
Eric Newberrycc910cd2018-05-06 17:01:40 -0700133 m_buffer.write(reinterpret_cast<const char*>(data.getContent().value()),
134 data.getContent().value_size());
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000135 afterSegmentValidated(data);
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000136 const auto& finalBlockId = data.getFinalBlock();
137 if (!finalBlockId || (*finalBlockId > currentSegment)) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800138 fetchNextSegment(origInterest, data.getName(), currentSegment.toSegment() + 1, self);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500139 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700140 else {
Eric Newberrycc910cd2018-05-06 17:01:40 -0700141 onComplete(m_buffer.buf());
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700142 }
143 }
144 }
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500145 else {
Eric Newberrycc910cd2018-05-06 17:01:40 -0700146 onError(DATA_HAS_NO_SEGMENT, "Data Name has no segment number.");
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700147 }
148}
149
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500150void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800151SegmentFetcher::afterValidationFailure(const Data& data, const security::v2::ValidationError& error)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500152{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700153 onError(SEGMENT_VALIDATION_FAIL, "Segment validation fail " +
154 boost::lexical_cast<std::string>(error));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500155}
156
157
158void
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000159SegmentFetcher::afterNackReceivedCb(const Interest& origInterest, const lp::Nack& nack,
160 uint32_t reExpressCount, shared_ptr<SegmentFetcher> self)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500161{
162 if (reExpressCount >= MAX_INTEREST_REEXPRESS) {
Eric Newberrycc910cd2018-05-06 17:01:40 -0700163 onError(NACK_ERROR, "Nack Error");
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500164 }
165 else {
166 switch (nack.getReason()) {
167 case lp::NackReason::DUPLICATE:
168 reExpressInterest(origInterest, reExpressCount, self);
169 break;
170 case lp::NackReason::CONGESTION:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500171 using ms = time::milliseconds;
172 m_scheduler.scheduleEvent(ms(static_cast<ms::rep>(std::pow(2, reExpressCount + 1))),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500173 bind(&SegmentFetcher::reExpressInterest, this,
174 origInterest, reExpressCount, self));
175 break;
176 default:
Eric Newberrycc910cd2018-05-06 17:01:40 -0700177 onError(NACK_ERROR, "Nack Error");
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500178 break;
179 }
180 }
181}
182
183void
184SegmentFetcher::reExpressInterest(Interest interest, uint32_t reExpressCount,
185 shared_ptr<SegmentFetcher> self)
186{
187 interest.refreshNonce();
188 BOOST_ASSERT(interest.hasNonce());
189
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500190 bool isSegmentZeroExpected = true;
191 if (!interest.getName().empty()) {
192 name::Component lastComponent = interest.getName().get(-1);
193 isSegmentZeroExpected = !lastComponent.isSegment();
194 }
195
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500196 m_face.expressInterest(interest,
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000197 bind(&SegmentFetcher::afterSegmentReceivedCb, this, _1, _2,
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500198 isSegmentZeroExpected, self),
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000199 bind(&SegmentFetcher::afterNackReceivedCb, this, _1, _2,
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500200 ++reExpressCount, self),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700201 bind([this] { onError(INTEREST_TIMEOUT, "Timeout"); }));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500202}
203
204} // namespace util
205} // namespace ndn