Network-related operations of the TorrentManager class
This commit adds the downloadTorrentFile, download_file_manifest, download_data_packet methods
Change-Id: Ie221bc07907eb58117e83e317eca578174142d6d
Refs: #3505
diff --git a/src/torrent-manager.cpp b/src/torrent-manager.cpp
index afda819..c06db40 100644
--- a/src/torrent-manager.cpp
+++ b/src/torrent-manager.cpp
@@ -434,5 +434,195 @@
// TODO(msweatt) IMPLEMENT ME
}
+void
+TorrentManager::downloadTorrentFile(const std::string& path,
+ DataReceivedCallback onSuccess,
+ FailedCallback onFailed)
+{
+ auto manifestNames = make_shared<std::vector<Name>>();
+ this->downloadTorrentFileSegment(m_torrentFileName, path, manifestNames,
+ true, onSuccess, onFailed);
+}
+
+std::vector<Name>
+TorrentManager::downloadTorrentFile(const std::string& path)
+{
+ auto manifestNames = make_shared<std::vector<Name>>();
+ this->downloadTorrentFileSegment(m_torrentFileName, path, manifestNames,
+ false, {}, {});
+ return *manifestNames;
+}
+
+void
+TorrentManager::downloadTorrentFileSegment(const ndn::Name& name,
+ const std::string& path,
+ std::shared_ptr<std::vector<Name>> manifestNames,
+ bool async,
+ DataReceivedCallback onSuccess,
+ FailedCallback onFailed)
+{
+ shared_ptr<Interest> interest = createInterest(name);
+
+ auto dataReceived = [manifestNames, path, async, onSuccess, onFailed, this]
+ (const Interest& interest, const Data& data) {
+ // Stats Table update here...
+ m_stats_table_iter->incrementReceivedData();
+ m_retries = 0;
+
+ TorrentFile file(data.wireEncode());
+
+ // Write the torrent file segment to disk...
+ writeTorrentSegment(file, path);
+
+ const std::vector<Name>& manifestCatalog = file.getCatalog();
+ manifestNames->insert(manifestNames->end(), manifestCatalog.begin(), manifestCatalog.end());
+
+ shared_ptr<Name> nextSegmentPtr = file.getTorrentFilePtr();
+
+ if (async) {
+ onSuccess(file.getName());
+ }
+ if (nextSegmentPtr != nullptr) {
+ this->downloadTorrentFileSegment(*nextSegmentPtr, path, manifestNames,
+ async, onSuccess, onFailed);
+ }
+ };
+
+ auto dataFailed = [manifestNames, path, name, async, onSuccess, onFailed, this]
+ (const Interest& interest) {
+ ++m_retries;
+ if (m_retries >= MAX_NUM_OF_RETRIES) {
+ ++m_stats_table_iter;
+ if (m_stats_table_iter == m_statsTable.end()) {
+ m_stats_table_iter = m_statsTable.begin();
+ }
+ }
+ if (async) {
+ onFailed(interest.getName(), "Unknown error");
+ }
+ this->downloadTorrentFileSegment(name, path, manifestNames, async, onSuccess, onFailed);
+ };
+
+ m_face.expressInterest(*interest, dataReceived, dataFailed);
+
+ if (!async) {
+ m_face.processEvents();
+ }
+}
+
+
+void
+TorrentManager::download_file_manifest(const Name& manifestName,
+ const std::string& path,
+ TorrentManager::ManifestReceivedCallback onSuccess,
+ TorrentManager::FailedCallback onFailed)
+{
+ auto packetNames = make_shared<std::vector<Name>>();
+ this->downloadFileManifestSegment(manifestName, path, packetNames, onSuccess, onFailed);
+}
+
+void
+TorrentManager::downloadFileManifestSegment(const Name& manifestName,
+ const std::string& path,
+ std::shared_ptr<std::vector<Name>> packetNames,
+ TorrentManager::ManifestReceivedCallback onSuccess,
+ TorrentManager::FailedCallback onFailed)
+{
+ shared_ptr<Interest> interest = this->createInterest(manifestName);
+
+ auto dataReceived = [packetNames, path, onSuccess, onFailed, this]
+ (const Interest& interest, const Data& data) {
+ // Stats Table update here...
+ m_stats_table_iter->incrementReceivedData();
+ m_retries = 0;
+
+ FileManifest file(data.wireEncode());
+
+ // Write the file manifest segment to disk...
+ writeFileManifest(file, path);
+
+ const std::vector<Name>& packetsCatalog = file.catalog();
+ packetNames->insert(packetNames->end(), packetsCatalog.begin(), packetsCatalog.end());
+ shared_ptr<Name> nextSegmentPtr = file.submanifest_ptr();
+ if (nextSegmentPtr != nullptr) {
+ this->downloadFileManifestSegment(*nextSegmentPtr, path, packetNames, onSuccess, onFailed);
+ }
+ else
+ onSuccess(*packetNames);
+ };
+
+ auto dataFailed = [packetNames, path, manifestName, onFailed, this]
+ (const Interest& interest) {
+ m_retries++;
+ if (m_retries >= MAX_NUM_OF_RETRIES) {
+ m_stats_table_iter++;
+ if (m_stats_table_iter == m_statsTable.end())
+ m_stats_table_iter = m_statsTable.begin();
+ }
+ onFailed(interest.getName(), "Unknown failure");
+ };
+
+ m_face.expressInterest(*interest, dataReceived, dataFailed);
+}
+
+void
+TorrentManager::download_data_packet(const Name& packetName,
+ DataReceivedCallback onSuccess,
+ FailedCallback onFailed)
+{
+ shared_ptr<Interest> interest = this->createInterest(packetName);
+
+ auto dataReceived = [onSuccess, onFailed, this]
+ (const Interest& interest, const Data& data) {
+ // Write data to disk...
+ writeData(data);
+
+ // Stats Table update here...
+ m_stats_table_iter->incrementReceivedData();
+ m_retries = 0;
+ onSuccess(data.getName());
+ };
+ auto dataFailed = [onFailed, this]
+ (const Interest& interest) {
+ m_retries++;
+ if (m_retries >= MAX_NUM_OF_RETRIES) {
+ m_stats_table_iter++;
+ if (m_stats_table_iter == m_statsTable.end())
+ m_stats_table_iter = m_statsTable.begin();
+ }
+ onFailed(interest.getName(), "Unknown failure");
+ };
+
+ m_face.expressInterest(*interest, dataReceived, dataFailed);
+}
+
+shared_ptr<Interest>
+TorrentManager::createInterest(Name name)
+{
+ shared_ptr<Interest> interest = make_shared<Interest>(name);
+ interest->setInterestLifetime(time::milliseconds(2000));
+ interest->setMustBeFresh(true);
+
+ // Select routable prefix
+ Link link(name, { {1, m_stats_table_iter->getRecordName()} });
+ m_keyChain->sign(link, signingWithSha256());
+ Block linkWire = link.wireEncode();
+
+ // Stats Table update here...
+ m_stats_table_iter->incrementSentInterests();
+
+ m_sortingCounter++;
+ if (m_sortingCounter >= SORTING_INTERVAL) {
+ m_sortingCounter = 0;
+ m_statsTable.sort();
+ m_stats_table_iter = m_statsTable.begin();
+ m_retries = 0;
+ }
+
+ interest->setLink(linkWire);
+
+ return interest;
+}
+
} // end ntorrent
-} // end ndn
\ No newline at end of file
+} // end ndn