blob: b23b99164708e63175e0937eadd9c5c3e1ddc480 [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
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000049shared_ptr<SegmentFetcher>
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070050SegmentFetcher::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*) {});
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000057 return fetch(face, baseInterest, validatorPtr, completeCallback, errorCallback);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050058}
59
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000060shared_ptr<SegmentFetcher>
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050061SegmentFetcher::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);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000071
72 return fetcher;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070073}
74
75void
76SegmentFetcher::fetchFirstSegment(const Interest& baseInterest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050077 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070078{
79 Interest interest(baseInterest);
80 interest.setChildSelector(1);
81 interest.setMustBeFresh(true);
82
83 m_face.expressInterest(interest,
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +000084 bind(&SegmentFetcher::afterSegmentReceivedCb, this, _1, _2, true, self),
85 bind(&SegmentFetcher::afterNackReceivedCb, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070086 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
87}
88
89void
90SegmentFetcher::fetchNextSegment(const Interest& origInterest, const Name& dataName,
91 uint64_t segmentNo,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050092 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070093{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050094 Interest interest(origInterest); // to preserve any selectors
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070095 interest.refreshNonce();
96 interest.setChildSelector(0);
97 interest.setMustBeFresh(false);
98 interest.setName(dataName.getPrefix(-1).appendSegment(segmentNo));
99 m_face.expressInterest(interest,
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000100 bind(&SegmentFetcher::afterSegmentReceivedCb, this, _1, _2, false, self),
101 bind(&SegmentFetcher::afterNackReceivedCb, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700102 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
103}
104
105void
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000106SegmentFetcher::afterSegmentReceivedCb(const Interest& origInterest,
107 const Data& data, bool isSegmentZeroExpected,
108 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700109{
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000110 afterSegmentReceived(data);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500111 m_validator->validate(data,
112 bind(&SegmentFetcher::afterValidationSuccess, this, _1,
113 isSegmentZeroExpected, origInterest, self),
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800114 bind(&SegmentFetcher::afterValidationFailure, this, _1, _2));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700115
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500116}
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700117
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500118void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800119SegmentFetcher::afterValidationSuccess(const Data& data,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500120 bool isSegmentZeroExpected,
121 const Interest& origInterest,
122 shared_ptr<SegmentFetcher> self)
123{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800124 name::Component currentSegment = data.getName().get(-1);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500125
126 if (currentSegment.isSegment()) {
127 if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800128 fetchNextSegment(origInterest, data.getName(), 0, self);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700129 }
130 else {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800131 m_buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
132 data.getContent().value_size());
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000133 afterSegmentValidated(data);
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800134 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500135 if (finalBlockId.empty() || (finalBlockId > currentSegment)) {
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800136 fetchNextSegment(origInterest, data.getName(), currentSegment.toSegment() + 1, self);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500137 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700138 else {
139 return m_completeCallback(m_buffer->buf());
140 }
141 }
142 }
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500143 else {
144 m_errorCallback(DATA_HAS_NO_SEGMENT, "Data Name has no segment number.");
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700145 }
146}
147
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500148void
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800149SegmentFetcher::afterValidationFailure(const Data& data, const security::v2::ValidationError& error)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500150{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800151 return m_errorCallback(SEGMENT_VALIDATION_FAIL, "Segment validation fail " +
152 boost::lexical_cast<std::string>(error));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500153}
154
155
156void
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000157SegmentFetcher::afterNackReceivedCb(const Interest& origInterest, const lp::Nack& nack,
158 uint32_t reExpressCount, shared_ptr<SegmentFetcher> self)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500159{
160 if (reExpressCount >= MAX_INTEREST_REEXPRESS) {
161 m_errorCallback(NACK_ERROR, "Nack Error");
162 }
163 else {
164 switch (nack.getReason()) {
165 case lp::NackReason::DUPLICATE:
166 reExpressInterest(origInterest, reExpressCount, self);
167 break;
168 case lp::NackReason::CONGESTION:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500169 using ms = time::milliseconds;
170 m_scheduler.scheduleEvent(ms(static_cast<ms::rep>(std::pow(2, reExpressCount + 1))),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500171 bind(&SegmentFetcher::reExpressInterest, this,
172 origInterest, reExpressCount, self));
173 break;
174 default:
175 m_errorCallback(NACK_ERROR, "Nack Error");
176 break;
177 }
178 }
179}
180
181void
182SegmentFetcher::reExpressInterest(Interest interest, uint32_t reExpressCount,
183 shared_ptr<SegmentFetcher> self)
184{
185 interest.refreshNonce();
186 BOOST_ASSERT(interest.hasNonce());
187
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500188 bool isSegmentZeroExpected = true;
189 if (!interest.getName().empty()) {
190 name::Component lastComponent = interest.getName().get(-1);
191 isSegmentZeroExpected = !lastComponent.isSegment();
192 }
193
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500194 m_face.expressInterest(interest,
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000195 bind(&SegmentFetcher::afterSegmentReceivedCb, this, _1, _2,
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500196 isSegmentZeroExpected, self),
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000197 bind(&SegmentFetcher::afterNackReceivedCb, this, _1, _2,
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500198 ++reExpressCount, self),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500199 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
200}
201
202} // namespace util
203} // namespace ndn