diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index eb26164b..b3e87af6 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -374,6 +374,27 @@ namespace client return ""; } + bool Address::operator==(const Address& other) const + { + if (addressType != other.addressType) return false; + switch (addressType) + { + case eAddressIndentHash: + return identHash == other.identHash; + break; + case eAddressBlindedPublicKey: + if (blindedPublicKey && other.blindedPublicKey && + blindedPublicKey->GetPublicKeyLen () == other.blindedPublicKey->GetPublicKeyLen () && + blindedPublicKey->GetSigType () == other.blindedPublicKey->GetSigType () && + blindedPublicKey->GetBlindedSigType () == other.blindedPublicKey->GetBlindedSigType ()) + return !memcmp (blindedPublicKey->GetPublicKey (), other.blindedPublicKey->GetPublicKey (), + blindedPublicKey->GetPublicKeyLen ()); + break; + default: ; + } + return false; + } + AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr), m_IsEnabled (true) diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index 927c597f..2cf5e9df 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -54,6 +54,8 @@ namespace client bool IsIdentHash () const { return addressType == eAddressIndentHash; }; bool IsValid () const { return addressType != eAddressInvalid; }; std::string ToBase32 () const; + + bool operator==(const Address& other) const; }; inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } diff --git a/libi2pd_client/Torrents.cpp b/libi2pd_client/Torrents.cpp index 7c815fbd..5160f923 100644 --- a/libi2pd_client/Torrents.cpp +++ b/libi2pd_client/Torrents.cpp @@ -430,9 +430,9 @@ namespace torrents } Torrent::Torrent (): - m_Length (0), m_PieceLength (0), m_IsComplete (false), m_IsStopped (false), m_IsSingleFile (true), - m_Uploaded (0), m_Downloaded (0), m_NextUpdateStatusTime (0), m_NextReconnectTime (0), - m_Error (eTorrentErrorNoError) + m_AnnounceTrackerID (-1), m_Length (0), m_PieceLength (0), m_IsComplete (false), + m_IsStopped (false), m_IsSingleFile (true), m_Uploaded (0), m_Downloaded (0), + m_NextUpdateStatusTime (0), m_NextReconnectTime (0), m_Error (eTorrentErrorNoError) { } diff --git a/libi2pd_client/Torrents.h b/libi2pd_client/Torrents.h index 1daa6f90..b8cd94db 100644 --- a/libi2pd_client/Torrents.h +++ b/libi2pd_client/Torrents.h @@ -247,6 +247,8 @@ namespace torrents std::string_view GetAnnounce () const { return m_Announce; } void SetAnnounce (std::string_view announce) { m_Announce = announce; } + int GetAnnounceTrackerID () const { return m_AnnounceTrackerID; } + void SetAnnounceTrackerID (int trackerID) { m_AnnounceTrackerID = trackerID; } std::string_view GetName () const { return m_Name; } void SetName (std::string_view name) { m_Name = AdjustName (name); } bool IsValid () const { return !m_Name.empty () && m_PieceLength && (m_Length || !m_Files.empty ()); } @@ -321,6 +323,7 @@ namespace torrents private: std::string m_Name, m_Announce; + int m_AnnounceTrackerID; // -1 not set std::filesystem::path m_FullPath; size_t m_Length, m_PieceLength; std::vector m_Info; // for BEP9 diff --git a/libi2pd_client/TorrentsTunnel.cpp b/libi2pd_client/TorrentsTunnel.cpp index d47b6d96..bf080294 100644 --- a/libi2pd_client/TorrentsTunnel.cpp +++ b/libi2pd_client/TorrentsTunnel.cpp @@ -411,22 +411,7 @@ namespace torrents id = m_TorrentsByID.rbegin ()->first + 1; m_TorrentsByID.emplace (id, torrent); if (!torrent->GetAnnounce ().empty ()) - { - // add announce to trackers - i2p::http::URL reqURL (torrent->GetAnnounce ()); - auto it = std::find_if (m_Trackers.begin (), m_Trackers.end (), - [host = std::string_view (reqURL.host)](const TrackerInfo& tracker) - { - return std::get<0>(tracker).host == host; - }); - if (it == m_Trackers.end()) - { - if (reqURL.host.ends_with (".i2p")) - m_Trackers.emplace_back (TrackerInfo{ torrent->GetAnnounce (), false, 0, 0, 0 }); - else - LogPrint (eLogInfo, "TorrentsTunnel: Non-I2P address ", reqURL.host, " in announce for torrent ", torrent->GetName ()); - } - } + torrent->SetAnnounceTrackerID (AddTracker (torrent->GetAnnounce (), false)); // add announce to trackers return id; } return 0; @@ -754,7 +739,7 @@ namespace torrents for (size_t i = 0; i < m_Trackers.size (); i++) { if (!it.second->GetNextTrackerRequestTime (i) && // first time - (std::get<1>(m_Trackers[i]) || std::get<0>(m_Trackers[i]).host == i2p::http::URL (it.second->GetAnnounce ()).host)) + (std::get<1>(m_Trackers[i]) || it.second->GetAnnounceTrackerID () == (int)i)) { auto initialInterval = GetLocalDestination ()->GetRng()() % TRACKER_INITIAL_REQUEST_INTERVAL_VARIANCE; if (initialInterval <= TRACKER_REQUESTS_CHECK_TIMEOUT) initialInterval = 0; // request immeditely @@ -1063,6 +1048,35 @@ namespace torrents } m_DatragramTrackerTransactions.erase (it); } + + int TorrentsTunnel::AddTracker (std::string_view announce, bool isCommon) + { + if (announce.empty ()) return -1; + i2p::http::URL reqURL (announce); + if (!reqURL.host.ends_with (".i2p")) + { + LogPrint (eLogInfo, "TorrentsTunnel: Non-I2P address ", reqURL.host, " in tracker announce"); + return -1; + } + auto reqAddr = i2p::client::context.GetAddressBook ().GetAddress (reqURL.host); + if (reqAddr) + { + auto it = std::find_if (m_Trackers.begin (), m_Trackers.end (), + [host = std::string_view (reqURL.host), reqAddr](const TrackerInfo& tracker) + { + const auto& url = std::get<0>(tracker); + if (url.host == host) return true; + auto addr = i2p::client::context.GetAddressBook ().GetAddress (url.host); + if (!addr) return false; + return *addr == *reqAddr; + }); + if (it != m_Trackers.end ()) // existing + return it - m_Trackers.begin(); + } + + m_Trackers.emplace_back (TrackerInfo{ announce, isCommon, 0, 0, 0 }); + return m_Trackers.size () - 1; + } } } diff --git a/libi2pd_client/TorrentsTunnel.h b/libi2pd_client/TorrentsTunnel.h index a950d999..866f5bb7 100644 --- a/libi2pd_client/TorrentsTunnel.h +++ b/libi2pd_client/TorrentsTunnel.h @@ -100,6 +100,7 @@ namespace torrents const std::filesystem::path& GetTorrentsDir () const { return m_TorrentsDir; } std::string GetTrackerAnnounce (size_t id) const { return (id < m_Trackers.size ()) ? std::get<0>(m_Trackers[id]).to_string () : ""; } size_t GetNumTrackers () const { return m_Trackers.size (); } + int AddTracker (std::string_view announce, bool isCommon); // tarckerID or -1 if not inserted std::shared_ptr FindTorrent (const Torrent::InfoHash& infoHash) const; std::shared_ptr FindTorrentByID (int id) const; std::vector GetTorrentIDs () const;