update torrent info and save .torent file from BEP9 metadata

This commit is contained in:
orignal committed 2026-09-04 17:36:28 -04:00
1 parent d608d3f5b2
commit d203db13a7
4 files changed
+57 -16

No files matched your search

+13 -6
View File
@@ -373,7 +373,6 @@ namespace torrents
return len;
}
size_t Torrent::ParseInfo (std::string_view buf)
{
size_t len = ParseDictionary (buf, [this](std::string_view key, std::string_view buf)->size_t
@@ -423,6 +422,12 @@ namespace torrents
return len;
}
std::string Torrent::CreateTorrentFileContent () const
{
if (m_Info.empty ()) return "";
return CreateDictionary ( {{ "info", std::string_view ((const char *)m_Info.data (), m_Info.size ()) }} );
}
bool Torrent::IsSafeName (std::string_view name)
{
if (name.empty () || name == "." || name == "..") return false;
@@ -1279,7 +1284,7 @@ namespace torrents
void PeerConnection::HandleBitfieldMsg (const uint8_t * buf, size_t len)
{
if (!m_Torrent) return;
if (!m_Torrent || !m_Torrent->GetLength ()) return; // we are magnet and don't have torrent info yet
m_IsInterested = false;
size_t numPieces = m_Torrent->GetNumPieces ();
m_RemoteBitfield.resize (numPieces);
@@ -1640,6 +1645,9 @@ namespace torrents
}
return 0;
});
if (!m_Torrent->GetLength () && m_RemoteMetadataSize) // torrent is magnet and peer supports BEP9
// request first piece of info
SendExtendedMsg (EXTENSION_MSGID_UT_METADATA, CreateDictionary ({{ "msg_type", CreateInteger (0) }, { "piece", CreateInteger (0) }}));
}
else
{
@@ -1748,11 +1756,10 @@ namespace torrents
uint8_t digest[SHA_DIGEST_LENGTH];
SHA1 (m_RemoteMetadata.data (), m_RemoteMetadata.size (), digest);
if (memcmp (m_Torrent->GetInfoHash ().data (), digest, SHA_DIGEST_LENGTH))
GetTorrentsTunnel ()->UpdateTorrentInfo (m_Torrent, std::string_view ((const char *)m_RemoteMetadata.data (), m_RemoteMetadata.size ()));
else
LogPrint (eLogError, "Torrents: ut_metadata info doesn't match infoHash");
// TODO: update torrent
// cleanup
std::vector<uint8_t> tmp;
m_RemoteMetadata.swap (tmp);
Close (); // we need to reconnect to receive bitfield
}
}
break;
+2 -1
View File
@@ -162,6 +162,8 @@ namespace torrents
Torrent (std::string_view buf);
Torrent (const InfoHash& infoHash);
size_t ParseInfo (std::string_view buf);
std::string CreateTorrentFileContent () const;
void ParseTrackerResponse (size_t trackerID, std::string_view buf);
void HandleDatagramTrackerResponse (size_t trackerID, uint32_t interval,
const uint8_t * hashes, size_t hashesLen, int numSeeders, int numLeechers);
@@ -230,7 +232,6 @@ namespace torrents
Torrent ();
size_t ParsePieces (std::string_view buf);
size_t ParseInfo (std::string_view buf);
size_t ParsePeers (size_t trackerID, std::string_view buf);
size_t ParseFiles (std::string_view buf);
static bool IsSafeName (std::string_view name); // a name from a torrent file before it becomes a path
+40 -9
View File
@@ -134,6 +134,20 @@ namespace torrents
}
}
void TorrentsTunnel::SaveTorrentFile (std::shared_ptr<Torrent> torrent)
{
if (!torrent) return;
auto torrentFilePath = torrent->GetFullPath (); torrentFilePath += ".torrent";
std::ofstream f(torrentFilePath, std::ofstream::binary);
if (f)
{
auto content = torrent->CreateTorrentFileContent ();
f.write (content.data (), content.size ());
}
else
LogPrint (eLogError, "TorrentsTunnel: Can't open ", torrentFilePath);
}
void TorrentsTunnel::InitTorrentFiles (std::shared_ptr<Torrent> torrent)
{
if (!torrent) return;
@@ -315,15 +329,20 @@ namespace torrents
if (m_Torrents.find (torrent->GetInfoHash ()) == m_Torrents.end ())
{
torrent->SetFullPath (m_TorrentsDir/std::filesystem::path (torrent->GetName ()));
{
auto torrentFilePath = torrent->GetFullPath (); torrentFilePath += ".torrent";
std::ofstream f(torrentFilePath, std::ofstream::binary);
if (f)
f.write (torrentFileContent.data (), torrentFileContent.size ());
else
return { torrent, 0 };
}
InitTorrentFiles (torrent);
std::string content (torrentFileContent);
boost::asio::post (GetDiskIOService (), [this, torrent, content]()
{
auto torrentFilePath = torrent->GetFullPath (); torrentFilePath += ".torrent";
{
// TODO: replace by SaveTorrentFile
std::ofstream f(torrentFilePath, std::ofstream::binary);
if (f)
f.write (content.data (), content.size ());
else
LogPrint (eLogError, "TorrentsTunnel: Can't open ", torrentFilePath);
}
InitTorrentFiles (torrent);
});
return { torrent, InsertTorrent (torrent) };
}
return { torrent, 0 };
@@ -502,6 +521,18 @@ namespace torrents
return true;
}
void TorrentsTunnel::UpdateTorrentInfo (std::shared_ptr<Torrent> torrent, std::string_view info)
{
if (!torrent) return;
torrent->ParseInfo (info);
torrent->SetFullPath (m_TorrentsDir/std::filesystem::path (torrent->GetName ()));
boost::asio::post (GetDiskIOService (), [this, torrent]()
{
SaveTorrentFile (torrent);
InitTorrentFiles (torrent);
});
}
void TorrentsTunnel::Accept ()
{
auto localDestination = GetLocalDestination ();
+2
View File
@@ -100,6 +100,7 @@ namespace torrents
std::vector<int> GetTorrentIDs () const;
std::pair<std::shared_ptr<Torrent>, int> AddTorrent (std::string_view torrentFileContent); // retrun (torrent, id)
std::pair<std::shared_ptr<Torrent>, int> AddMagnet (std::string_view magnet); // return (torrent, id)
void UpdateTorrentInfo (std::shared_ptr<Torrent> torrent, std::string_view info); // magnet
bool RemoveTorrent (int id, bool deleteFiles);
bool StopTorrent (int id);
bool StartTorrent (int id);
@@ -112,6 +113,7 @@ namespace torrents
void Accept ();
void ReadTorrentFile (const std::filesystem::path& torrentFilePath);
void SaveTorrentFile (std::shared_ptr<Torrent> torrent);
void InitTorrentFiles (std::shared_ptr<Torrent> torrent);
int InsertTorrent (std::shared_ptr<Torrent> torrent); // returns id > 0 if success and 0 if failed
void RemoveTorrent (std::shared_ptr<Torrent> torrent, bool deleteFiles);