blob: b99438488708acfb29bbb4d792f4fdc3a35b5464 [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
42SequentialDataFetcher::start()
43{
44 m_manager->Initialize();
45 // downloading logic
46 this->implementSequentialLogic();
47}
48
49void
50SequentialDataFetcher::pause()
51{
52 // TODO(Spyros): Implement asyncrhonous pause of the torrent downloading
53 // For now, do nothing...
54 throw(Error("Not implemented yet"));
55}
56
57void
58SequentialDataFetcher::resume()
59{
60 // TODO(Spyros): Implement asyncrhonous re-establishment of the torrent downloading
61 // For now, do nothing...
62 throw(Error("Not implemented yet"));
63}
64
65std::vector<ndn::Name>
66SequentialDataFetcher::downloadTorrentFile()
67{
68 std::vector<ndn::Name> returnedNames;
69 returnedNames = m_manager->downloadTorrentFile(".appdata/torrent_files/");
Mickey Sweatt67133bf2016-04-25 12:37:35 -070070 if (!returnedNames.empty() && IoUtil::NAME_TYPE::FILE_MANIFEST == IoUtil::findType(returnedNames[0])) {
Mickey Sweatt617d2d42016-04-25 22:02:08 -070071 LOG_INFO << "Torrent File Received: "
Mickey Sweatt67133bf2016-04-25 12:37:35 -070072 << m_torrentFileName.getSubName(0, m_torrentFileName.size() - 1) << std::endl;
73 }
spirosmastorakis2f769c22016-03-12 11:46:04 -080074 return returnedNames;
75}
76
77void
78SequentialDataFetcher::downloadManifestFiles(const std::vector<ndn::Name>& manifestsName)
79{
80 std::vector<ndn::Name> packetsName;
81 for (auto i = manifestsName.begin(); i != manifestsName.end(); i++) {
82 m_manager->download_file_manifest(*i,
83 ".appdata/manifests/",
84 bind(&SequentialDataFetcher::onManifestReceived, this, _1),
85 bind(&SequentialDataFetcher::onDataRetrievalFailure, this, _1, _2));
Mickey Sweattb7ee19c2016-04-21 12:18:15 -070086 m_manager->processEvents();
spirosmastorakis2f769c22016-03-12 11:46:04 -080087 }
88}
89
90void
91SequentialDataFetcher::downloadPackets(const std::vector<ndn::Name>& packetsName)
92{
93 for (auto i = packetsName.begin(); i != packetsName.end(); i++) {
94 m_manager->download_data_packet(*i,
95 bind(&SequentialDataFetcher::onDataPacketReceived, this, _1),
96 bind(&SequentialDataFetcher::onDataRetrievalFailure, this, _1, _2));
97 }
Mickey Sweatt67133bf2016-04-25 12:37:35 -070098 m_manager->processEvents();
spirosmastorakis2f769c22016-03-12 11:46:04 -080099}
100
101void
102SequentialDataFetcher::implementSequentialLogic() {
103 std::vector<ndn::Name> returnedNames;
104 returnedNames = this->downloadTorrentFile();
105 if (returnedNames.empty()) {
106 // we have downloaded the entire torrent (including manifests, data packets, etc..)
107 return;
108 }
109 // check the first returned name whether it is the name of a file manifest or a data packet
110 const Name& nameToCheck = returnedNames[0];
111 if (IoUtil::findType(nameToCheck) == IoUtil::DATA_PACKET) {
112 // In this case, the returned names correspond to data packets
113 this->downloadPackets(returnedNames);
114 }
115 else {
116 // In this case, the returned names correspond to file manifests
117 this->downloadManifestFiles(returnedNames);
118 }
119}
120
121void
122SequentialDataFetcher::onDataPacketReceived(const ndn::Data& data)
123{
124 // Data Packet Received
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700125 LOG_INFO << "Data Packet Received: " << data.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800126}
127
128void
129SequentialDataFetcher::onManifestReceived(const std::vector<Name>& packetNames)
130{
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700131 LOG_INFO << "Manifest File Received: "
spirosmastorakis2f769c22016-03-12 11:46:04 -0800132 << packetNames[0].getSubName(0, packetNames[0].size()- 3) << std::endl;
133 this->downloadPackets(packetNames);
134}
135
136void
137SequentialDataFetcher::onDataRetrievalFailure(const ndn::Interest& interest,
138 const std::string& errorCode)
139{
spirosmastorakis2f769c22016-03-12 11:46:04 -0800140 // Data retrieval failure
141 uint32_t nameType = IoUtil::findType(interest.getName());
142 if (nameType == IoUtil::TORRENT_FILE) {
143 // this should never happen
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700144 LOG_ERROR << "Torrent File Segment Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800145 this->downloadTorrentFile();
146 }
147 else if (nameType == IoUtil::FILE_MANIFEST) {
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700148 LOG_ERROR << "Manifest File Segment Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800149 this->downloadManifestFiles({ interest.getName() });
150 }
151 else if (nameType == IoUtil::DATA_PACKET) {
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700152 LOG_ERROR << "Torrent File Segment Downloading Failed: " << interest.getName();
153 this->downloadTorrentFile();
154 }
155 else if (nameType == IoUtil::FILE_MANIFEST) {
156 LOG_ERROR << "Manifest File Segment Downloading Failed: " << interest.getName();
157 this->downloadManifestFiles({ interest.getName() });
158 }
159 else if (nameType == IoUtil::DATA_PACKET) {
160 LOG_ERROR << "Data Packet Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800161 this->downloadPackets({ interest.getName() });
162 }
163 else {
164 // This should never happen
Mickey Sweatt617d2d42016-04-25 22:02:08 -0700165 LOG_ERROR << "Unknown Packet Type Downloading Failed: " << interest.getName();
spirosmastorakis2f769c22016-03-12 11:46:04 -0800166 }
167}
168
169} // namespace ntorrent
170} // namespace ndn