blob: 9a5ae5f4e27adb6039522c65c1ea79652ea5a5dd [file] [log] [blame]
spirosmastorakis2f769c22016-03-12 11:46:04 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3* Copyright (c) 2016 Regents of the University of California.
4*
5* This file is part of the nTorrent codebase.
6*
7* nTorrent 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* nTorrent 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 nTorrent, e.g., in COPYING.md file. If not, see
17* <http://www.gnu.org/licenses/>.
18*
19* See AUTHORS for complete list of nTorrent authors and contributors.
20*/
21
22#include "sequential-data-fetcher.hpp"
Mickey Sweatt617d2d42016-04-25 22:02:08 -070023#include "util/logging.hpp"
spirosmastorakis2f769c22016-03-12 11:46:04 -080024#include "util/io-util.hpp"
25
26namespace ndn {
27namespace ntorrent {
28
29SequentialDataFetcher::SequentialDataFetcher(const ndn::Name& torrentFileName,
30 const std::string& dataPath)
31 : m_dataPath(dataPath)
32 , m_torrentFileName(torrentFileName)
33{
34 m_manager = make_shared<TorrentManager>(m_torrentFileName, m_dataPath);
35}
36
37SequentialDataFetcher::~SequentialDataFetcher()
38{
39}
40
41void
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070042SequentialDataFetcher::start(const time::milliseconds& timeout)
spirosmastorakis2f769c22016-03-12 11:46:04 -080043{
44 m_manager->Initialize();
45 // downloading logic
46 this->implementSequentialLogic();
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070047 m_manager->processEvents(timeout);
spirosmastorakis2f769c22016-03-12 11:46:04 -080048}
49
50void
51SequentialDataFetcher::pause()
52{
53 // TODO(Spyros): Implement asyncrhonous pause of the torrent downloading
54 // For now, do nothing...
55 throw(Error("Not implemented yet"));
56}
57
58void
59SequentialDataFetcher::resume()
60{
61 // TODO(Spyros): Implement asyncrhonous re-establishment of the torrent downloading
62 // For now, do nothing...
63 throw(Error("Not implemented yet"));
64}
65
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070066void
spirosmastorakis2f769c22016-03-12 11:46:04 -080067SequentialDataFetcher::downloadTorrentFile()
68{
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070069 auto torrentPath = ".appdata/" + m_torrentFileName.get(-3).toUri() + "/torrent_files/";
70 m_manager->downloadTorrentFile(torrentPath,
71 bind(&SequentialDataFetcher::onTorrentFileSegmentReceived, this, _1),
72 bind(&SequentialDataFetcher::onDataRetrievalFailure, this, _1, _2));
spirosmastorakis2f769c22016-03-12 11:46:04 -080073}
74
75void
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070076SequentialDataFetcher::downloadManifestFiles(const std::vector<ndn::Name>& manifestNames)
spirosmastorakis2f769c22016-03-12 11:46:04 -080077{
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070078 auto manifestPath = ".appdata/" + m_torrentFileName.get(-3).toUri() + "/manifests/";
79 for (auto i = manifestNames.begin(); i != manifestNames.end(); i++) {
spirosmastorakis2f769c22016-03-12 11:46:04 -080080 m_manager->download_file_manifest(*i,
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070081 manifestPath,
spirosmastorakis2f769c22016-03-12 11:46:04 -080082 bind(&SequentialDataFetcher::onManifestReceived, this, _1),
83 bind(&SequentialDataFetcher::onDataRetrievalFailure, this, _1, _2));
84 }
85}
86
87void
88SequentialDataFetcher::downloadPackets(const std::vector<ndn::Name>& packetsName)
89{
90 for (auto i = packetsName.begin(); i != packetsName.end(); i++) {
91 m_manager->download_data_packet(*i,
92 bind(&SequentialDataFetcher::onDataPacketReceived, this, _1),
93 bind(&SequentialDataFetcher::onDataRetrievalFailure, this, _1, _2));
94 }
95}
96
97void
98SequentialDataFetcher::implementSequentialLogic() {
Mickey Sweatt15dde2d2016-04-28 23:42:45 -070099 // TODO(?) Fix seeding, and implement windowing:
100 /*
101 Alex says look at ndn-cxx:
102 * fetcher with queue (with window)
103 * segment fetcher ?
104 * catchunks (pipeline?)
105 */
106 if (!m_manager->hasAllTorrentSegments()) {
107 this->downloadTorrentFile();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800108 }
109 else {
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700110 LOG_INFO << m_torrentFileName << " complete" << std::endl;
111 std::vector<ndn::Name> namesToFetch;
112 m_manager->findFileManifestsToDownload(namesToFetch);
113 if (!namesToFetch.empty()) {
114 this->downloadManifestFiles(namesToFetch);
115 }
116 else {
117 LOG_INFO << "All manifests complete" << std::endl;
118 m_manager->findAllMissingDataPackets(namesToFetch);
119 if (!namesToFetch.empty()) {
120 this->downloadPackets(namesToFetch);
121 }
122 else {
123 LOG_INFO << "All data complete" << std::endl;
124 }
125 }
spirosmastorakis2f769c22016-03-12 11:46:04 -0800126 }
127}
128
129void
130SequentialDataFetcher::onDataPacketReceived(const ndn::Data& data)
131{
132 // Data Packet Received
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700133 LOG_INFO << "Data Packet Received: " << data.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800134}
135
136void
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700137SequentialDataFetcher::onTorrentFileSegmentReceived(const std::vector<Name>& manifestNames)
138{
139 this->downloadManifestFiles(manifestNames);
140}
141
142void
spirosmastorakis2f769c22016-03-12 11:46:04 -0800143SequentialDataFetcher::onManifestReceived(const std::vector<Name>& packetNames)
144{
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700145 LOG_INFO << "Manifest File Received: "
spirosmastorakis2f769c22016-03-12 11:46:04 -0800146 << packetNames[0].getSubName(0, packetNames[0].size()- 3) << std::endl;
147 this->downloadPackets(packetNames);
148}
149
150void
151SequentialDataFetcher::onDataRetrievalFailure(const ndn::Interest& interest,
152 const std::string& errorCode)
153{
spirosmastorakis2f769c22016-03-12 11:46:04 -0800154 // Data retrieval failure
155 uint32_t nameType = IoUtil::findType(interest.getName());
156 if (nameType == IoUtil::TORRENT_FILE) {
157 // this should never happen
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700158 LOG_ERROR << "Torrent File Segment Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800159 this->downloadTorrentFile();
160 }
161 else if (nameType == IoUtil::FILE_MANIFEST) {
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700162 LOG_ERROR << "Manifest File Segment Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800163 this->downloadManifestFiles({ interest.getName() });
164 }
165 else if (nameType == IoUtil::DATA_PACKET) {
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700166 LOG_ERROR << "Torrent File Segment Downloading Failed: " << interest.getName();
167 this->downloadTorrentFile();
168 }
169 else if (nameType == IoUtil::FILE_MANIFEST) {
170 LOG_ERROR << "Manifest File Segment Downloading Failed: " << interest.getName();
171 this->downloadManifestFiles({ interest.getName() });
172 }
173 else if (nameType == IoUtil::DATA_PACKET) {
174 LOG_ERROR << "Data Packet Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800175 this->downloadPackets({ interest.getName() });
176 }
177 else {
178 // This should never happen
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700179 LOG_ERROR << "Unknown Packet Type Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800180 }
181}
182
183} // namespace ntorrent
184} // namespace ndn