blob: 70ad63237c367b6fb99e2af9924b20cb50a08053 [file] [log] [blame]
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -05003 * Copyright (c) 2013-2016 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
28namespace ndn {
29namespace util {
30
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050031const uint32_t SegmentFetcher::MAX_INTEREST_REEXPRESS = 3;
32
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070033SegmentFetcher::SegmentFetcher(Face& face,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050034 shared_ptr<Validator> validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070035 const CompleteCallback& completeCallback,
36 const ErrorCallback& errorCallback)
37 : m_face(face)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050038 , m_scheduler(m_face.getIoService())
39 , m_validator(validator)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070040 , m_completeCallback(completeCallback)
41 , m_errorCallback(errorCallback)
42 , m_buffer(make_shared<OBufferStream>())
43{
44}
45
46void
47SegmentFetcher::fetch(Face& face,
48 const Interest& baseInterest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050049 Validator& validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070050 const CompleteCallback& completeCallback,
51 const ErrorCallback& errorCallback)
52{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050053 shared_ptr<Validator> sharedValidator = shared_ptr<Validator>(&validator, [] (Validator*) {});
54
55 fetch(face, baseInterest, sharedValidator, completeCallback, errorCallback);
56}
57
58void
59SegmentFetcher::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));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070067
68 fetcher->fetchFirstSegment(baseInterest, fetcher);
69}
70
71void
72SegmentFetcher::fetchFirstSegment(const Interest& baseInterest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050073 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070074{
75 Interest interest(baseInterest);
76 interest.setChildSelector(1);
77 interest.setMustBeFresh(true);
78
79 m_face.expressInterest(interest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050080 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, true, self),
81 bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070082 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
83}
84
85void
86SegmentFetcher::fetchNextSegment(const Interest& origInterest, const Name& dataName,
87 uint64_t segmentNo,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050088 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070089{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050090 Interest interest(origInterest); // to preserve any selectors
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070091 interest.refreshNonce();
92 interest.setChildSelector(0);
93 interest.setMustBeFresh(false);
94 interest.setName(dataName.getPrefix(-1).appendSegment(segmentNo));
95 m_face.expressInterest(interest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050096 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, false, self),
97 bind(&SegmentFetcher::afterNackReceived, this, _1, _2, 0, self),
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070098 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
99}
100
101void
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500102SegmentFetcher::afterSegmentReceived(const Interest& origInterest,
103 const Data& data, bool isSegmentZeroExpected,
104 shared_ptr<SegmentFetcher> self)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700105{
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500106 m_validator->validate(data,
107 bind(&SegmentFetcher::afterValidationSuccess, this, _1,
108 isSegmentZeroExpected, origInterest, self),
109 bind(&SegmentFetcher::afterValidationFailure, this, _1));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700110
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500111}
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700112
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500113void
114SegmentFetcher::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);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700124 }
125 else {
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500126 m_buffer->write(reinterpret_cast<const char*>(data->getContent().value()),
127 data->getContent().value_size());
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700128
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500129 const name::Component& finalBlockId = data->getMetaInfo().getFinalBlockId();
130 if (finalBlockId.empty() || (finalBlockId > currentSegment)) {
131 fetchNextSegment(origInterest, data->getName(), currentSegment.toSegment() + 1, self);
132 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700133 else {
134 return m_completeCallback(m_buffer->buf());
135 }
136 }
137 }
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500138 else {
139 m_errorCallback(DATA_HAS_NO_SEGMENT, "Data Name has no segment number.");
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700140 }
141}
142
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500143void
144SegmentFetcher::afterValidationFailure(const shared_ptr<const Data> data)
145{
146 return m_errorCallback(SEGMENT_VALIDATION_FAIL, "Segment validation fail");
147}
148
149
150void
151SegmentFetcher::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()) {
159 case lp::NackReason::DUPLICATE:
160 reExpressInterest(origInterest, reExpressCount, self);
161 break;
162 case lp::NackReason::CONGESTION:
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
174void
175SegmentFetcher::reExpressInterest(Interest interest, uint32_t reExpressCount,
176 shared_ptr<SegmentFetcher> self)
177{
178 interest.refreshNonce();
179 BOOST_ASSERT(interest.hasNonce());
180
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500181 bool isSegmentZeroExpected = true;
182 if (!interest.getName().empty()) {
183 name::Component lastComponent = interest.getName().get(-1);
184 isSegmentZeroExpected = !lastComponent.isSegment();
185 }
186
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500187 m_face.expressInterest(interest,
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500188 bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2,
189 isSegmentZeroExpected, self),
190 bind(&SegmentFetcher::afterNackReceived, this, _1, _2,
191 ++reExpressCount, self),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500192 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
193}
194
195} // namespace util
196} // namespace ndn