blob: e7703c52ad14a8d6e4091b3210ce1f1782a1317f [file] [log] [blame]
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 Regents of the University of California.
4 *
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"
23
24#include "../encoding/buffer-stream.hpp"
25
26namespace ndn {
27namespace util {
28
29SegmentFetcher::SegmentFetcher(Face& face,
30 const VerifySegment& verifySegment,
31 const CompleteCallback& completeCallback,
32 const ErrorCallback& errorCallback)
33 : m_face(face)
34 , m_verifySegment(verifySegment)
35 , m_completeCallback(completeCallback)
36 , m_errorCallback(errorCallback)
37 , m_buffer(make_shared<OBufferStream>())
38{
39}
40
41void
42SegmentFetcher::fetch(Face& face,
43 const Interest& baseInterest,
44 const VerifySegment& verifySegment,
45 const CompleteCallback& completeCallback,
46 const ErrorCallback& errorCallback)
47{
48 shared_ptr<SegmentFetcher> fetcher =
49 shared_ptr<SegmentFetcher>(new SegmentFetcher(face, verifySegment,
50 completeCallback, errorCallback));
51
52 fetcher->fetchFirstSegment(baseInterest, fetcher);
53}
54
55void
56SegmentFetcher::fetchFirstSegment(const Interest& baseInterest,
57 const shared_ptr<SegmentFetcher>& self)
58{
59 Interest interest(baseInterest);
60 interest.setChildSelector(1);
61 interest.setMustBeFresh(true);
62
63 m_face.expressInterest(interest,
64 bind(&SegmentFetcher::onSegmentReceived, this, _1, _2, true, self),
65 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
66}
67
68void
69SegmentFetcher::fetchNextSegment(const Interest& origInterest, const Name& dataName,
70 uint64_t segmentNo,
71 const shared_ptr<SegmentFetcher>& self)
72{
73 Interest interest(origInterest); // to preserve any special selectors
74 interest.refreshNonce();
75 interest.setChildSelector(0);
76 interest.setMustBeFresh(false);
77 interest.setName(dataName.getPrefix(-1).appendSegment(segmentNo));
78 m_face.expressInterest(interest,
79 bind(&SegmentFetcher::onSegmentReceived, this, _1, _2, false, self),
80 bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
81}
82
83void
84SegmentFetcher::onSegmentReceived(const Interest& origInterest,
85 const Data& data, bool isSegmentZeroExpected,
86 const shared_ptr<SegmentFetcher>& self)
87{
88 if (!m_verifySegment(data)) {
89 return m_errorCallback(SEGMENT_VERIFICATION_FAIL, "Segment validation fail");
90 }
91
92 try {
93 uint64_t currentSegment = data.getName().get(-1).toSegment();
94
95 if (isSegmentZeroExpected && currentSegment != 0) {
96 fetchNextSegment(origInterest, data.getName(), 0, self);
97 }
98 else {
99 m_buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
100 data.getContent().value_size());
101
102 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
103 if (finalBlockId.empty() ||
104 finalBlockId.toSegment() > currentSegment)
105 {
106 fetchNextSegment(origInterest, data.getName(), currentSegment + 1, self);
107 }
108 else {
109 return m_completeCallback(m_buffer->buf());
110 }
111 }
112 }
113 catch (const tlv::Error& e) {
114 m_errorCallback(DATA_HAS_NO_SEGMENT, std::string("Error while decoding segment: ") + e.what());
115 }
116}
117
118} // util
119} // ndn