mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-10-23 21:32:57 +00:00
torrent download completion. correct last piece size
This commit is contained in:
1 parent
314af9e4ba
commit
8fa6896328
2 files changed
+39
-13
No files matched your search
+36
-11
@@ -305,10 +305,13 @@ namespace torrents
|
||||
size_t Torrent::ParsePieces (std::string_view buf)
|
||||
{
|
||||
auto [hashes, len] = ExtractByteString (buf);
|
||||
while (!hashes.empty ())
|
||||
size_t totalLen = 0;
|
||||
while (!hashes.empty () && totalLen < m_Length)
|
||||
{
|
||||
m_Pieces.emplace_back (m_PieceLength, (const uint8_t *)hashes.substr (0, SHA_DIGEST_LENGTH).data ());
|
||||
auto l = (totalLen + m_PieceLength <= m_Length) ? m_PieceLength : m_Length - totalLen;
|
||||
m_Pieces.emplace_back (l, (const uint8_t *)hashes.substr (0, SHA_DIGEST_LENGTH).data ());
|
||||
hashes = hashes.substr (SHA_DIGEST_LENGTH);
|
||||
totalLen += l;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@@ -419,9 +422,9 @@ namespace torrents
|
||||
return { ret, empty };
|
||||
}
|
||||
|
||||
void Torrent::ApplyBitfield (const std::vector<uint8_t>& bitfield)
|
||||
bool Torrent::ApplyBitfield (const std::vector<uint8_t>& bitfield)
|
||||
{
|
||||
m_IsComplete = true;
|
||||
bool complete = true;
|
||||
size_t numPieces = m_Pieces.size ();
|
||||
size_t idx = 0;
|
||||
for (size_t i = 0; i < bitfield.size (); i++)
|
||||
@@ -433,12 +436,13 @@ namespace torrents
|
||||
if (bitfield[i] & bit)
|
||||
m_Pieces[idx].Complete ();
|
||||
else
|
||||
m_IsComplete = false;
|
||||
complete = false;
|
||||
bit >>= 1;
|
||||
idx++;
|
||||
}
|
||||
if (idx >= numPieces) break;
|
||||
}
|
||||
return complete;
|
||||
}
|
||||
|
||||
std::tuple<uint32_t, uint32_t, uint32_t> Torrent::GetNextBlockToRequest (std::shared_ptr<PeerConnection> conn)
|
||||
@@ -469,15 +473,16 @@ namespace torrents
|
||||
return { 0, 0, 0 };
|
||||
}
|
||||
|
||||
void Torrent::UpdateStatus (uint64_t ts)
|
||||
bool Torrent::UpdateStatus (uint64_t ts)
|
||||
{
|
||||
//bool complete = true;
|
||||
bool complete = true;
|
||||
for (auto& it: m_Pieces)
|
||||
{
|
||||
// if (!it.IsComplete ()) complete = false;
|
||||
if (ts > it.GetLastActivityTimestamp () + PIECE_INACTIVITY_TIMEOUT) // piece was incactive recently
|
||||
if (!it.IsComplete ()) complete = false;
|
||||
if (ts > it.GetLastActivityTimestamp () + PIECE_INACTIVITY_TIMEOUT) // piece was inactive recently
|
||||
it.Reset ();
|
||||
}
|
||||
return complete;
|
||||
}
|
||||
|
||||
void Torrent::SetComplete ()
|
||||
@@ -1163,7 +1168,8 @@ namespace torrents
|
||||
rs.seekg(0, std::ios::beg);
|
||||
std::vector<uint8_t> bitfield(l);
|
||||
rs.read((char *)bitfield.data (), l);
|
||||
torrent->ApplyBitfield (bitfield);
|
||||
if (torrent->ApplyBitfield (bitfield))
|
||||
CompleteTorrent (torrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1178,6 +1184,24 @@ namespace torrents
|
||||
LogPrint (eLogError, "Torrents: Can't open file ", path);
|
||||
}
|
||||
|
||||
void TorrentsTunnel::CompleteTorrent (std::shared_ptr<Torrent> torrent)
|
||||
{
|
||||
boost::asio::post (GetDiskIOService (), [torrent,
|
||||
filePath = GetTorrentFilePath (torrent->GetName ()),
|
||||
partFilePath = GetTorrentFilePath (torrent->GetName () + ".part"),
|
||||
resumeFilePath = GetTorrentFilePath (torrent->GetName () + ".resume")]()
|
||||
{
|
||||
if (i2p::fs::Rename (partFilePath, filePath))
|
||||
{
|
||||
torrent->SetComplete ();
|
||||
i2p::fs::Remove (resumeFilePath);
|
||||
LogPrint (eLogInfo, "Torrents: Download complete ", filePath);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Torrents: Can't rename ", partFilePath);
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<Torrent> TorrentsTunnel::FindTorrent (const Torrent::InfoHash& infoHash) const
|
||||
{
|
||||
auto it = m_Torrents.find (infoHash);
|
||||
@@ -1396,7 +1420,8 @@ namespace torrents
|
||||
{
|
||||
auto ts = i2p::util::GetMonotonicSeconds ();
|
||||
for (auto it: m_Torrents)
|
||||
it.second->UpdateStatus (ts);
|
||||
if (!it.second->IsComplete () && it.second->UpdateStatus (ts))
|
||||
CompleteTorrent (it.second);
|
||||
ScheduleStatusUpdate ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,10 +142,10 @@ namespace torrents
|
||||
size_t GetNumPieces () const { return m_Pieces.size (); }
|
||||
Piece& GetPiece (int index) { return m_Pieces[index]; }
|
||||
std::pair<std::vector<uint8_t>, bool> CreateBitfield () const; // (bitfield, empty)
|
||||
void ApplyBitfield (const std::vector<uint8_t>& bitfield);
|
||||
bool ApplyBitfield (const std::vector<uint8_t>& bitfield); // return true if complete
|
||||
const std::unordered_set<i2p::data::IdentHash>& GetPeers () const { return m_Peers; }
|
||||
std::tuple<uint32_t, uint32_t, uint32_t> GetNextBlockToRequest (std::shared_ptr<PeerConnection> conn); // return (index, offset, len)
|
||||
void UpdateStatus (uint64_t ts);
|
||||
bool UpdateStatus (uint64_t ts); // return true if complete
|
||||
|
||||
uint64_t GetNextTrackerRequestTime () const { return m_NextTrackerRequestTime; }
|
||||
void SetNextTrackerRequestTime (uint64_t ts) { m_NextTrackerRequestTime = ts; }
|
||||
@@ -280,6 +280,7 @@ namespace torrents
|
||||
|
||||
void Accept ();
|
||||
void ReadTorrentFile (const std::string& path);
|
||||
void CompleteTorrent (std::shared_ptr<Torrent> torrent);
|
||||
void RequestTracker (std::shared_ptr<Torrent> torrent);
|
||||
void TrackerRequestSent (const boost::beast::error_code& ecode, size_t bytes_transferred,
|
||||
std::shared_ptr<i2p::client::BoostAsyncStream> httpStream, std::shared_ptr<Torrent> torrent,
|
||||
|
||||
Reference in new issue
Block a user