blob: 0c2e908e9f974343cda4a1e951ea8cc6a4875369 [file] [log] [blame]
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -05003 * Copyright (c) 2013-2015 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#ifndef NDN_UTIL_SEGMENT_FETCHER_HPP
23#define NDN_UTIL_SEGMENT_FETCHER_HPP
24
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050025#include "scheduler.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070026#include "../common.hpp"
27#include "../face.hpp"
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050028#include "../security/validator.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070029
30namespace ndn {
31
32class OBufferStream;
33
34namespace util {
35
36/**
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070037 * @brief Utility class to fetch latest version of the segmented data
38 *
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070039 * SegmentFetcher assumes that the data is named `/<prefix>/<version>/<segment>`,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070040 * where:
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070041 * - `<prefix>` is the specified prefix,
42 * - `<version>` is an unknown version that needs to be discovered, and
43 * - `<segment>` is a segment number (number of segments is unknown and is controlled
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070044 * by `FinalBlockId` field in at least the last Data packet
45 *
46 * The following logic is implemented in SegmentFetcher:
47 *
48 * 1. Express first interest to discover version:
49 *
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070050 * >> Interest: `/<prefix>?ChildSelector=1&MustBeFresh=yes`
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070051 *
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070052 * 2. Infer the latest version of Data: `<version> = Data.getName().get(-2)`
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070053 *
54 * 3. If segment number in the retrieved packet == 0, go to step 5.
55 *
56 * 4. Send Interest for segment 0:
57 *
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070058 * >> Interest: `/<prefix>/<version>/<segment=0>`
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070059 *
60 * 5. Keep sending Interests for the next segment while the retrieved Data does not have
61 * FinalBlockId or FinalBlockId != Data.getName().get(-1).
62 *
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070063 * >> Interest: `/<prefix>/<version>/<segment=(N+1))>`
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070064 *
65 * 6. Fire onCompletion callback with memory block that combines content part from all
66 * segmented objects.
67 *
68 * If an error occurs during the fetching process, an error callback is fired
69 * with a proper error code. The following errors are possible:
70 *
71 * - `INTEREST_TIMEOUT`: if any of the Interests times out
72 * - `DATA_HAS_NO_SEGMENT`: if any of the retrieved Data packets don't have segment
73 * as a last component of the name (not counting implicit digest)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050074 * - `SEGMENT_VALIDATION_FAIL`: if any retrieved segment fails user-provided validation
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070075 *
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050076 * In order to validate individual segments, a Validator instance needs to be specified.
77 * If the segment validation is successful, afterValidationSuccess callback is fired, otherwise
78 * afterValidationFailure callback.
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070079 *
80 * Examples:
81 *
82 * void
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050083 * afterFetchComplete(const ConstBufferPtr& data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070084 * {
85 * ...
86 * }
87 *
88 * void
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050089 * afterFetchError(uint32_t errorCode, const std::string& errorMsg)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070090 * {
91 * ...
92 * }
93 *
94 * ...
95 * SegmentFetcher::fetch(face, Interest("/data/prefix", time::seconds(1000)),
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050096 * validator,
97 * bind(&afterFetchComplete, this, _1),
98 * bind(&afterFetchError, this, _1, _2));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070099 *
100 */
101class SegmentFetcher : noncopyable
102{
103public:
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500104 /**
105 * @brief Maximum number of times an interest will be reexpressed incase of NackCallback
106 */
107 static const uint32_t MAX_INTEREST_REEXPRESS;
108
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700109 typedef function<void (const ConstBufferPtr& data)> CompleteCallback;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700110 typedef function<void (uint32_t code, const std::string& msg)> ErrorCallback;
111
112 /**
113 * @brief Error codes that can be passed to ErrorCallback
114 */
115 enum ErrorCode {
116 INTEREST_TIMEOUT = 1,
117 DATA_HAS_NO_SEGMENT = 2,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500118 SEGMENT_VALIDATION_FAIL = 3,
119 NACK_ERROR = 4
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700120 };
121
122 /**
123 * @brief Initiate segment fetching
124 *
125 * @param face Reference to the Face that should be used to fetch data
126 * @param baseInterest An Interest for the initial segment of requested data.
127 * This interest may include custom InterestLifetime and selectors that
128 * will propagate to all subsequent Interests. The only exception is that
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500129 * the initial Interest will be forced to include "ChildSelector=rightmost" and
130 * "MustBeFresh=true" selectors, which will be turned off in subsequent
131 * Interests.
132 * @param validator Reference to the Validator that should be used to validate data. Caller
133 * must ensure validator is valid until either completeCallback or errorCallback
134 * is invoked.
135 *
136 * @param completeCallback Callback to be fired when all segments are fetched
137 * @param errorCallback Callback to be fired when an error occurs (@see Errors)
138 */
139 static
140 void
141 fetch(Face& face,
142 const Interest& baseInterest,
143 Validator& validator,
144 const CompleteCallback& completeCallback,
145 const ErrorCallback& errorCallback);
146
147 /**
148 * @brief Initiate segment fetching
149 *
150 * @param face Reference to the Face that should be used to fetch data
151 * @param baseInterest An Interest for the initial segment of requested data.
152 * This interest may include custom InterestLifetime and selectors that
153 * will propagate to all subsequent Interests. The only exception is that
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700154 * the initial Interest will be forced to include "ChildSelector=1" and
155 * "MustBeFresh=true" selectors, which will be turned off in subsequent
156 * Interests.
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500157 * @param validator A shared_ptr to the Validator that should be used to validate data.
158 *
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700159 * @param completeCallback Callback to be fired when all segments are fetched
160 * @param errorCallback Callback to be fired when an error occurs (@see Errors)
161 */
162 static
163 void
164 fetch(Face& face,
165 const Interest& baseInterest,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500166 shared_ptr<Validator> validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700167 const CompleteCallback& completeCallback,
168 const ErrorCallback& errorCallback);
169
170private:
171 SegmentFetcher(Face& face,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500172 shared_ptr<Validator> validator,
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700173 const CompleteCallback& completeCallback,
174 const ErrorCallback& errorCallback);
175
176 void
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500177 fetchFirstSegment(const Interest& baseInterest, shared_ptr<SegmentFetcher> self);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700178
179 void
180 fetchNextSegment(const Interest& origInterest, const Name& dataName, uint64_t segmentNo,
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500181 shared_ptr<SegmentFetcher> self);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700182
183 void
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500184 afterSegmentReceived(const Interest& origInterest,
185 const Data& data, bool isSegmentZeroExpected,
186 shared_ptr<SegmentFetcher> self);
187 void
188 afterValidationSuccess(const shared_ptr<const Data> data,
189 bool isSegmentZeroExpected,
190 const Interest& origInterest,
191 shared_ptr<SegmentFetcher> self);
192
193 void
194 afterValidationFailure(const shared_ptr<const Data> data);
195
196 void
197 afterNackReceived(const Interest& origInterest, const lp::Nack& nack,
198 uint32_t reExpressCount, shared_ptr<SegmentFetcher> self);
199
200 void
201 reExpressInterest(Interest interest, uint32_t reExpressCount,
202 shared_ptr<SegmentFetcher> self);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700203
204private:
205 Face& m_face;
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500206 Scheduler m_scheduler;
207 shared_ptr<Validator> m_validator;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700208 CompleteCallback m_completeCallback;
209 ErrorCallback m_errorCallback;
210
211 shared_ptr<OBufferStream> m_buffer;
212};
213
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500214} // namespace util
215} // namespace ndn
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700216
217#endif // NDN_UTIL_SEGMENT_FETCHER_HPP