| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /** |
| * Copyright (c) 2013-2014 Regents of the University of California. |
| * |
| * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). |
| * |
| * ndn-cxx library is free software: you can redistribute it and/or modify it under the |
| * terms of the GNU Lesser General Public License as published by the Free Software |
| * Foundation, either version 3 of the License, or (at your option) any later version. |
| * |
| * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
| * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
| * |
| * You should have received copies of the GNU General Public License and GNU Lesser |
| * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see |
| * <http://www.gnu.org/licenses/>. |
| * |
| * See AUTHORS.md for complete list of ndn-cxx authors and contributors. |
| */ |
| |
| #ifndef NDN_UTIL_SEGMENT_FETCHER_HPP |
| #define NDN_UTIL_SEGMENT_FETCHER_HPP |
| |
| #include "../common.hpp" |
| #include "../face.hpp" |
| |
| namespace ndn { |
| |
| class OBufferStream; |
| |
| namespace util { |
| |
| /** |
| * @brief Functor to skip validation of individual packets by SegmentFetcher |
| */ |
| class DontVerifySegment |
| { |
| public: |
| bool |
| operator()(const Data& data) const |
| { |
| return true; |
| } |
| }; |
| |
| /** |
| * @brief Utility class to fetch latest version of the segmented data |
| * |
| * SegmentFetcher assumes that the data is named /<prefix>/<version>/<segment>, |
| * where: |
| * - <prefix> is the specified prefix, |
| * - <version> is an unknown version that needs to be discovered, and |
| * - <segment> is a segment number (number of segments is unknown and is controlled |
| * by `FinalBlockId` field in at least the last Data packet |
| * |
| * The following logic is implemented in SegmentFetcher: |
| * |
| * 1. Express first interest to discover version: |
| * |
| * >> Interest: /<prefix>?ChildSelector=1&MustBeFresh=yes |
| * |
| * 2. Infer the latest version of Data: <version> = Data.getName().get(-2) |
| * |
| * 3. If segment number in the retrieved packet == 0, go to step 5. |
| * |
| * 4. Send Interest for segment 0: |
| * |
| * >> Interest: /<prefix>/<version>/<segment=0> |
| * |
| * 5. Keep sending Interests for the next segment while the retrieved Data does not have |
| * FinalBlockId or FinalBlockId != Data.getName().get(-1). |
| * |
| * >> Interest: /<prefix>/<version>/<segment=(N+1))> |
| * |
| * 6. Fire onCompletion callback with memory block that combines content part from all |
| * segmented objects. |
| * |
| * If an error occurs during the fetching process, an error callback is fired |
| * with a proper error code. The following errors are possible: |
| * |
| * - `INTEREST_TIMEOUT`: if any of the Interests times out |
| * - `DATA_HAS_NO_SEGMENT`: if any of the retrieved Data packets don't have segment |
| * as a last component of the name (not counting implicit digest) |
| * - `SEGMENT_VERIFICATION_FAIL`: if any retrieved segment fails user-provided validation |
| * |
| * In order to validate individual segments, an VerifySegment callback needs to be specified. |
| * If the callback returns false, fetching process is aborted with SEGMENT_VERIFICATION_FAIL. |
| * If data validation is not required, provided DontVerifySegment() functor can be used. |
| * |
| * Examples: |
| * |
| * void |
| * onComplete(const ConstBufferPtr& data) |
| * { |
| * ... |
| * } |
| * |
| * void |
| * onError(uint32_t errorCode, const std::string& errorMsg) |
| * { |
| * ... |
| * } |
| * |
| * ... |
| * SegmentFetcher::fetch(face, Interest("/data/prefix", time::seconds(1000)), |
| * DontVerifySegment(), |
| * bind(&onComplete, this, _1), |
| * bind(&onError, this, _1, _2)); |
| * |
| */ |
| class SegmentFetcher : noncopyable |
| { |
| public: |
| typedef function<void (const ConstBufferPtr& data)> CompleteCallback; |
| typedef function<bool (const Data& data)> VerifySegment; |
| typedef function<void (uint32_t code, const std::string& msg)> ErrorCallback; |
| |
| /** |
| * @brief Error codes that can be passed to ErrorCallback |
| */ |
| enum ErrorCode { |
| INTEREST_TIMEOUT = 1, |
| DATA_HAS_NO_SEGMENT = 2, |
| SEGMENT_VERIFICATION_FAIL = 3 |
| }; |
| |
| /** |
| * @brief Initiate segment fetching |
| * |
| * @param face Reference to the Face that should be used to fetch data |
| * @param baseInterest An Interest for the initial segment of requested data. |
| * This interest may include custom InterestLifetime and selectors that |
| * will propagate to all subsequent Interests. The only exception is that |
| * the initial Interest will be forced to include "ChildSelector=1" and |
| * "MustBeFresh=true" selectors, which will be turned off in subsequent |
| * Interests. |
| * @param verifySegment Functor to be called when Data segment is received. If |
| * functor return false, fetching will be aborted with |
| * SEGMENT_VERIFICATION_FAIL error |
| * @param completeCallback Callback to be fired when all segments are fetched |
| * @param errorCallback Callback to be fired when an error occurs (@see Errors) |
| */ |
| static |
| void |
| fetch(Face& face, |
| const Interest& baseInterest, |
| const VerifySegment& verifySegment, |
| const CompleteCallback& completeCallback, |
| const ErrorCallback& errorCallback); |
| |
| private: |
| SegmentFetcher(Face& face, |
| const VerifySegment& verifySegment, |
| const CompleteCallback& completeCallback, |
| const ErrorCallback& errorCallback); |
| |
| void |
| fetchFirstSegment(const Interest& baseInterest, const shared_ptr<SegmentFetcher>& self); |
| |
| void |
| fetchNextSegment(const Interest& origInterest, const Name& dataName, uint64_t segmentNo, |
| const shared_ptr<SegmentFetcher>& self); |
| |
| void |
| onSegmentReceived(const Interest& origInterest, |
| const Data& data, bool isSegmentZeroExpected, |
| const shared_ptr<SegmentFetcher>& self); |
| |
| private: |
| Face& m_face; |
| VerifySegment m_verifySegment; |
| CompleteCallback m_completeCallback; |
| ErrorCallback m_errorCallback; |
| |
| shared_ptr<OBufferStream> m_buffer; |
| }; |
| |
| } // util |
| } // ndn |
| |
| #endif // NDN_UTIL_SEGMENT_FETCHER_HPP |