mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-09-16 12:42:56 +00:00
maintain connection to datagram tracker
This commit is contained in:
+21
-21
@@ -490,8 +490,8 @@ namespace torrents
|
||||
|
||||
void Torrent::ParseTrackerResponse (size_t trackerID, std::string_view buf)
|
||||
{
|
||||
if (trackerID >= m_TrackersInfo.size ())
|
||||
m_TrackersInfo.resize (trackerID + 1, TrackerInfo{{}, MIN_TRACKER_REQUESTS_INTERVAL,
|
||||
if (trackerID >= m_TrackerStats.size ())
|
||||
m_TrackerStats.resize (trackerID + 1, TrackerStats{{}, MIN_TRACKER_REQUESTS_INTERVAL,
|
||||
0, 0, 0, i2p::util::GetSecondsSinceEpoch ()});
|
||||
ParseDictionary (buf, [this, trackerID](std::string_view key, std::string_view buf)->size_t
|
||||
{
|
||||
@@ -501,8 +501,8 @@ namespace torrents
|
||||
if (l)
|
||||
{
|
||||
int interval = std::max (MIN_TRACKER_REQUESTS_INTERVAL, (int)value*1000); // in milliseconds
|
||||
std::get<1>(m_TrackersInfo[trackerID]) = interval;
|
||||
std::get<2>(m_TrackersInfo[trackerID]) = i2p::util::GetMonotonicMilliseconds () + interval; // reset next request
|
||||
std::get<1>(m_TrackerStats[trackerID]) = interval;
|
||||
std::get<2>(m_TrackerStats[trackerID]) = i2p::util::GetMonotonicMilliseconds () + interval; // reset next request
|
||||
}
|
||||
return l;
|
||||
}
|
||||
@@ -511,13 +511,13 @@ namespace torrents
|
||||
else if (key == "complete")
|
||||
{
|
||||
auto [seeders, l] = ExtractInteger (buf);
|
||||
if (l) std::get<3>(m_TrackersInfo[trackerID]) = seeders;
|
||||
if (l) std::get<3>(m_TrackerStats[trackerID]) = seeders;
|
||||
return l;
|
||||
}
|
||||
else if (key == "incomplete")
|
||||
{
|
||||
auto [leechers, l] = ExtractInteger (buf);
|
||||
if (l) std::get<4>(m_TrackersInfo[trackerID]) = leechers;
|
||||
if (l) std::get<4>(m_TrackerStats[trackerID]) = leechers;
|
||||
return l;
|
||||
}
|
||||
else if (key == "failure reason")
|
||||
@@ -525,19 +525,19 @@ namespace torrents
|
||||
auto [reason, l] = ExtractByteString (buf);
|
||||
LogPrint (eLogError, "Torrents: Tracker error: ", reason);
|
||||
// double interval if tracker failure
|
||||
int interval = std::max (MIN_TRACKER_REQUESTS_INTERVAL, std::get<1>(m_TrackersInfo[trackerID])*2);
|
||||
std::get<1>(m_TrackersInfo[trackerID]) = interval;
|
||||
std::get<2>(m_TrackersInfo[trackerID]) = i2p::util::GetMonotonicMilliseconds () + interval;
|
||||
int interval = std::max (MIN_TRACKER_REQUESTS_INTERVAL, std::get<1>(m_TrackerStats[trackerID])*2);
|
||||
std::get<1>(m_TrackerStats[trackerID]) = interval;
|
||||
std::get<2>(m_TrackerStats[trackerID]) = i2p::util::GetMonotonicMilliseconds () + interval;
|
||||
return l;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
std::get<5>(m_TrackersInfo[trackerID]) = i2p::util::GetSecondsSinceEpoch ();
|
||||
std::get<5>(m_TrackerStats[trackerID]) = i2p::util::GetSecondsSinceEpoch ();
|
||||
}
|
||||
|
||||
size_t Torrent::ParsePeers (size_t trackerID, std::string_view buf)
|
||||
{
|
||||
auto& peers = std::get<0>(m_TrackersInfo[trackerID]);
|
||||
auto& peers = std::get<0>(m_TrackerStats[trackerID]);
|
||||
peers.clear ();
|
||||
auto [hashes, len] = ExtractByteString (buf);
|
||||
while (!hashes.empty ())
|
||||
@@ -551,10 +551,10 @@ namespace torrents
|
||||
void Torrent::HandleDatagramTrackerResponse (size_t trackerID, uint32_t interval,
|
||||
const uint8_t * hashes, size_t hashesLen, int numSeeders, int numLeechers)
|
||||
{
|
||||
if (trackerID >= m_TrackersInfo.size ())
|
||||
m_TrackersInfo.resize (trackerID + 1, TrackerInfo{{}, MIN_TRACKER_REQUESTS_INTERVAL,
|
||||
if (trackerID >= m_TrackerStats.size ())
|
||||
m_TrackerStats.resize (trackerID + 1, TrackerStats{{}, MIN_TRACKER_REQUESTS_INTERVAL,
|
||||
0, 0, 0, i2p::util::GetSecondsSinceEpoch () });
|
||||
auto& [peers, trackerRequestInterval, nextRequestTime, seeders, leechers, lastUpdateTime] = m_TrackersInfo[trackerID];
|
||||
auto& [peers, trackerRequestInterval, nextRequestTime, seeders, leechers, lastUpdateTime] = m_TrackerStats[trackerID];
|
||||
trackerRequestInterval = interval*1000; // milliseconds
|
||||
nextRequestTime = i2p::util::GetMonotonicMilliseconds () + trackerRequestInterval;
|
||||
seeders = numSeeders;
|
||||
@@ -795,10 +795,10 @@ namespace torrents
|
||||
|
||||
std::unordered_set<i2p::data::IdentHash> Torrent::GetPeers () const
|
||||
{
|
||||
if (m_TrackersInfo.size () == 1)
|
||||
return std::get<0>(m_TrackersInfo.front ());
|
||||
if (m_TrackerStats.size () == 1)
|
||||
return std::get<0>(m_TrackerStats.front ());
|
||||
std::unordered_set<i2p::data::IdentHash> ret;
|
||||
for (const auto& it: m_TrackersInfo)
|
||||
for (const auto& it: m_TrackerStats)
|
||||
{
|
||||
const auto& peers = std::get<0>(it);
|
||||
ret.insert (peers.begin (), peers.end ());
|
||||
@@ -808,16 +808,16 @@ namespace torrents
|
||||
|
||||
uint64_t Torrent::GetNextTrackerRequestTime (size_t trackerID) const
|
||||
{
|
||||
if (trackerID < m_TrackersInfo.size ()) return std::get<2>(m_TrackersInfo[trackerID]);
|
||||
if (trackerID < m_TrackerStats.size ()) return std::get<2>(m_TrackerStats[trackerID]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Torrent::SetNextTrackerRequestTime (size_t trackerID, uint64_t ts)
|
||||
{
|
||||
if (trackerID >= m_TrackersInfo.size ())
|
||||
m_TrackersInfo.resize (trackerID + 1, TrackerInfo{{}, MIN_TRACKER_REQUESTS_INTERVAL,
|
||||
if (trackerID >= m_TrackerStats.size ())
|
||||
m_TrackerStats.resize (trackerID + 1, TrackerStats{{}, MIN_TRACKER_REQUESTS_INTERVAL,
|
||||
0, 0, 0, i2p::util::GetSecondsSinceEpoch ()});
|
||||
std::get<2>(m_TrackersInfo[trackerID]) = ts;
|
||||
std::get<2>(m_TrackerStats[trackerID]) = ts;
|
||||
}
|
||||
|
||||
TorrentStatus Torrent::GetStatus () const
|
||||
|
||||
@@ -146,12 +146,12 @@ namespace torrents
|
||||
using RequestedBlock = std::tuple<uint32_t, uint32_t, uint32_t>; // (index, offset, len)
|
||||
class Torrent final
|
||||
{
|
||||
using TrackerStats = std::tuple<std::unordered_set<i2p::data::IdentHash>, int, uint64_t, int, int, uint64_t>;
|
||||
// (peers, interval, next tracker request time in monotonic milliseconds,
|
||||
// seeders, leechers, last update time in seconds since epoch)
|
||||
public:
|
||||
|
||||
using InfoHash = std::array<uint8_t, 20>;
|
||||
using TrackerInfo = std::tuple<std::unordered_set<i2p::data::IdentHash>, int, uint64_t, int, int, uint64_t>;
|
||||
// (peers, interval, next tracker request time in monotonic milliseconds,
|
||||
// seeders, leechers, last update time in seconds since epoch)
|
||||
|
||||
Torrent (std::string_view buf);
|
||||
void ParseTrackerResponse (size_t trackerID, std::string_view buf);
|
||||
@@ -173,7 +173,7 @@ namespace torrents
|
||||
std::list<std::pair<std::filesystem::path, size_t> >& GetFiles () { return m_Files; }
|
||||
size_t GetLength () const { return m_Length; }
|
||||
size_t GetPieceLength () const { return m_PieceLength; }
|
||||
int GetInterval (size_t trackerID) const { return (trackerID < m_TrackersInfo.size ()) ? std::get<1>(m_TrackersInfo[trackerID]) : MIN_TRACKER_REQUESTS_INTERVAL; }
|
||||
int GetInterval (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<1>(m_TrackerStats[trackerID]) : MIN_TRACKER_REQUESTS_INTERVAL; }
|
||||
const InfoHash& GetInfoHash () const { return m_InfoHash; }
|
||||
size_t GetLeft () const;
|
||||
std::string GetHexStringInfoHash () const; // in url format
|
||||
@@ -210,10 +210,10 @@ namespace torrents
|
||||
int GetNumUploadingToPeers () const { return m_NumUploadingToPeers; }
|
||||
void SetNumUploadingToPeers (int numUploadingToPeers) { m_NumUploadingToPeers = numUploadingToPeers; }
|
||||
|
||||
int GetNumSeeders (size_t trackerID) const { return (trackerID < m_TrackersInfo.size ()) ? std::get<3>(m_TrackersInfo[trackerID]) : 0; }
|
||||
int GetNumLeechers (size_t trackerID) const { return (trackerID < m_TrackersInfo.size ()) ? std::get<4>(m_TrackersInfo[trackerID]) : 0; }
|
||||
int GetNumPeers (size_t trackerID) const { return (trackerID < m_TrackersInfo.size ()) ? std::get<0>(m_TrackersInfo[trackerID]).size () : 0; }
|
||||
uint64_t GetLastTrackerUpdateTime (size_t trackerID) const { return (trackerID < m_TrackersInfo.size ()) ? std::get<5>(m_TrackersInfo[trackerID]) : 0; }
|
||||
int GetNumSeeders (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<3>(m_TrackerStats[trackerID]) : 0; }
|
||||
int GetNumLeechers (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<4>(m_TrackerStats[trackerID]) : 0; }
|
||||
int GetNumPeers (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<0>(m_TrackerStats[trackerID]).size () : 0; }
|
||||
uint64_t GetLastTrackerUpdateTime (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<5>(m_TrackerStats[trackerID]) : 0; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -230,7 +230,7 @@ namespace torrents
|
||||
size_t m_Length, m_PieceLength;
|
||||
InfoHash m_InfoHash; // SHA1
|
||||
std::vector<Piece> m_Pieces;
|
||||
std::vector<TrackerInfo> m_TrackersInfo;
|
||||
std::vector<TrackerStats> m_TrackerStats;
|
||||
bool m_IsComplete, m_IsStopped;
|
||||
std::list<std::pair<std::filesystem::path, size_t> > m_Files; // list of (path, length)
|
||||
size_t m_Uploaded, m_Downloaded;
|
||||
|
||||
@@ -411,12 +411,11 @@ namespace torrents
|
||||
boost::json::array JSONRPCHandler::GetTrackers (std::shared_ptr<Torrent> torrent) const
|
||||
{
|
||||
boost::json::array trackers;
|
||||
const auto& tunnelTrackers = m_Tunnel->GetTrackers ();
|
||||
for (size_t i = 0; i < tunnelTrackers.size (); i++)
|
||||
for (size_t i = 0; i < m_Tunnel->GetNumTrackers (); i++)
|
||||
{
|
||||
boost::json::object tracker;
|
||||
tracker["id"] = i;
|
||||
tracker["announce"] = tunnelTrackers[i];
|
||||
tracker["announce"] = m_Tunnel->GetTrackerAnnounce (i);
|
||||
tracker["tier"] = 0;
|
||||
trackers.push_back (tracker);
|
||||
}
|
||||
@@ -426,14 +425,13 @@ namespace torrents
|
||||
boost::json::array JSONRPCHandler::GetTrackerStats (std::shared_ptr<Torrent> torrent) const
|
||||
{
|
||||
boost::json::array trackers;
|
||||
const auto& tunnelTrackers = m_Tunnel->GetTrackers ();
|
||||
for (size_t i = 0; i < tunnelTrackers.size (); i++)
|
||||
for (size_t i = 0; i < m_Tunnel->GetNumTrackers (); i++)
|
||||
{
|
||||
boost::json::object tracker;
|
||||
tracker["id"] = i;
|
||||
tracker["announce"] = tunnelTrackers[i];
|
||||
tracker["announce"] = m_Tunnel->GetTrackerAnnounce (i);
|
||||
i2p::http::URL announceURL;
|
||||
announceURL.parse (tunnelTrackers[i]);
|
||||
announceURL.parse (m_Tunnel->GetTrackerAnnounce (i));
|
||||
tracker["host"]= announceURL.host;
|
||||
tracker["announceState"] = 1;
|
||||
tracker["scrapeState"] = 0;
|
||||
|
||||
@@ -33,7 +33,12 @@ namespace torrents
|
||||
m_PeerID += localDestination->GetIdentHash ().ToBase64 ();
|
||||
m_PeerID.resize (20, '0');
|
||||
if (!trackers.empty ())
|
||||
boost::split(m_Trackers, trackers, boost::is_any_of(","), boost::token_compress_on);
|
||||
{
|
||||
std::vector<std::string> trackersList;
|
||||
boost::split(trackersList, trackers, boost::is_any_of(","), boost::token_compress_on);
|
||||
for (const auto& it: trackersList)
|
||||
m_Trackers.emplace_back (TrackerInfo{ it, 0, 0, 0 });
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentsTunnel::Start ()
|
||||
@@ -473,7 +478,7 @@ namespace torrents
|
||||
if (!torrent) return;
|
||||
i2p::http::URL reqURL;
|
||||
if (trackerID < m_Trackers.size())
|
||||
reqURL.parse (m_Trackers[trackerID]);
|
||||
reqURL.parse (std::get<0>(m_Trackers[trackerID]));
|
||||
else
|
||||
reqURL.parse (torrent->GetAnnounce ());
|
||||
#if __cplusplus >= 202002L // C++20
|
||||
@@ -487,7 +492,19 @@ namespace torrents
|
||||
}
|
||||
if (reqURL.schema == "udp")
|
||||
{
|
||||
ConnectToDatagramTracker (torrent, trackerID, reqURL.host, reqURL.port, event);
|
||||
if (trackerID >= m_Trackers.size()) return;
|
||||
auto ts = i2p::util::GetMonotonicMilliseconds ();
|
||||
auto& [announce, connectionID, expiration, fromPort] = m_Trackers[trackerID];
|
||||
if (connectionID && ts <= expiration)
|
||||
SendAnnounceToDatagramTracker (trackerID, connectionID, torrent, reqURL.host, reqURL.port, fromPort, event);
|
||||
else
|
||||
{
|
||||
if (!expiration || ts >= expiration) // don't connect if pending connection
|
||||
{
|
||||
expiration = ts + DATAGRAM_TRACKER_TRANSACTION_TIMEOUT;
|
||||
ConnectToDatagramTracker (trackerID, reqURL.host, reqURL.port);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
std::map<std::string, std::string> params;
|
||||
@@ -604,7 +621,7 @@ namespace torrents
|
||||
auto it = m_DatragramTrackerTransactions.begin ();
|
||||
while (it != m_DatragramTrackerTransactions.end ())
|
||||
{
|
||||
if (ts > (std::get<5>(it->second) + DATAGRAM_TRACKER_TRANSACTION_TIMEOUT)*1000LL)
|
||||
if (ts > std::get<3>(it->second) + DATAGRAM_TRACKER_TRANSACTION_TIMEOUT)
|
||||
it = m_DatragramTrackerTransactions.erase (it);
|
||||
else
|
||||
it++;
|
||||
@@ -820,8 +837,7 @@ namespace torrents
|
||||
LogPrint (eLogInfo, "TorrentsTunnel: Datagram tracker error response: ", std::string_view ((const char *)(buf + 4), len - 4));
|
||||
}
|
||||
|
||||
void TorrentsTunnel::ConnectToDatagramTracker (std::shared_ptr<Torrent> torrent,
|
||||
size_t trackerID, std::string_view dest, uint16_t port, TrackerAnnounceEvent event)
|
||||
void TorrentsTunnel::ConnectToDatagramTracker (size_t trackerID, std::string_view dest, uint16_t port)
|
||||
{
|
||||
LogPrint (eLogDebug, "TorrentsTunnel: Connecting to datagram tracker ", dest, ":", port);
|
||||
auto address = i2p::client::context.GetAddressBook ().GetAddress (dest);
|
||||
@@ -840,8 +856,8 @@ namespace torrents
|
||||
auto session = dgramDest->GetSession (address->identHash);
|
||||
if (session)
|
||||
{
|
||||
m_DatragramTrackerTransactions.emplace (transactionID, std::make_tuple (torrent,
|
||||
trackerID, address->identHash, port, fromPort, i2p::util::GetMonotonicSeconds (), event));
|
||||
m_DatragramTrackerTransactions.emplace (transactionID, std::make_tuple (
|
||||
trackerID, fromPort, std::shared_ptr<Torrent>(nullptr), i2p::util::GetMonotonicMilliseconds ()));
|
||||
session->SetVersion (i2p::datagram::eDatagramV2); // send datagram2
|
||||
dgramDest->SendDatagram (session, connectRequest, 16, fromPort, port);
|
||||
}
|
||||
@@ -871,48 +887,62 @@ namespace torrents
|
||||
return;
|
||||
}
|
||||
uint64_t connectionID = bufbe64toh (buf + 4);
|
||||
auto [torrent, trackerID, ident, port, fromPort, ts, event] = it->second;
|
||||
if (!torrent.expired ())
|
||||
SendAnnounceToDatagramTracker (transactionID, connectionID, torrent.lock (), ident, port, fromPort, event);
|
||||
else
|
||||
m_DatragramTrackerTransactions.erase (it);
|
||||
auto [trackerID, fromPort, torrent, ts] = it->second;
|
||||
if (trackerID < m_Trackers.size ())
|
||||
{
|
||||
auto& [announce, connID, connExpiration, connFromPort] = m_Trackers[trackerID];
|
||||
connID = connectionID;
|
||||
connExpiration = i2p::util::GetMonotonicMilliseconds () + DATAGRAM_TRACKER_CONNECTION_EXPIRATION;
|
||||
connFromPort = fromPort;
|
||||
}
|
||||
m_DatragramTrackerTransactions.erase (it);
|
||||
}
|
||||
|
||||
void TorrentsTunnel::SendAnnounceToDatagramTracker (uint32_t transactionID,
|
||||
uint64_t connectionID, std::shared_ptr<Torrent> torrent, const i2p::data::IdentHash& ident,
|
||||
uint16_t port, uint16_t fromPort, TrackerAnnounceEvent event)
|
||||
void TorrentsTunnel::SendAnnounceToDatagramTracker (size_t trackerID, uint64_t connectionID,
|
||||
std::shared_ptr<Torrent> torrent, std::string_view dest, uint16_t port,
|
||||
uint16_t fromPort, TrackerAnnounceEvent event)
|
||||
{
|
||||
auto localDestination = GetLocalDestination ();
|
||||
auto dgramDest = localDestination->GetDatagramDestination ();
|
||||
if (dgramDest)
|
||||
LogPrint (eLogDebug, "TorrentsTunnel: Sending announce to datagram tracker ", dest, ":", port);
|
||||
auto address = i2p::client::context.GetAddressBook ().GetAddress (dest);
|
||||
if (address && address->IsIdentHash ())
|
||||
{
|
||||
uint8_t announce[98];
|
||||
htobe64buf (announce, connectionID); // connection_id
|
||||
htobe32buf (announce + 8, eDatagramTrackerActionAnnounce); // action
|
||||
htobe32buf (announce + 12, transactionID); // transaction_id
|
||||
memcpy (announce + 16, torrent->GetInfoHash ().data (), 20); // info_hash
|
||||
memcpy (announce + 36, m_PeerID.data (), 20); // peer_id
|
||||
auto left = torrent->GetLeft ();
|
||||
htobe64buf (announce + 56, torrent->GetLength () - left); // downloaded
|
||||
htobe64buf (announce + 64, left); // left
|
||||
htobe64buf (announce + 72, torrent->GetUploaded ()); // uploaded
|
||||
htobe32buf (announce + 80, event); // event
|
||||
htobe32buf (announce + 84, 0); // IP address 0:not used
|
||||
htobe32buf (announce + 88, 0); // key, ignored
|
||||
int numWant = 0;
|
||||
if (!torrent->IsComplete () && (event == eTrackerAnnounceEventNone || event == eTrackerAnnounceEventStarted))
|
||||
numWant = TRACKER_MAX_NUM_WANT;
|
||||
htobe32buf (announce + 92, numWant); // num_want
|
||||
htobe16buf (announce + 96, fromPort); // from port
|
||||
auto session = dgramDest->GetSession (ident);
|
||||
if (session)
|
||||
auto localDestination = GetLocalDestination ();
|
||||
auto dgramDest = localDestination->GetDatagramDestination ();
|
||||
if (dgramDest)
|
||||
{
|
||||
session->SetVersion (i2p::datagram::eDatagramV3); // send datagram3
|
||||
dgramDest->SendDatagram (session, announce, 98, fromPort, port);
|
||||
uint8_t announce[98];
|
||||
htobe64buf (announce, connectionID); // connection_id
|
||||
htobe32buf (announce + 8, eDatagramTrackerActionAnnounce); // action
|
||||
uint32_t transactionID = localDestination->GetRng()();
|
||||
htobe32buf (announce + 12, transactionID); // transaction_id
|
||||
memcpy (announce + 16, torrent->GetInfoHash ().data (), 20); // info_hash
|
||||
memcpy (announce + 36, m_PeerID.data (), 20); // peer_id
|
||||
auto left = torrent->GetLeft ();
|
||||
htobe64buf (announce + 56, torrent->GetLength () - left); // downloaded
|
||||
htobe64buf (announce + 64, left); // left
|
||||
htobe64buf (announce + 72, torrent->GetUploaded ()); // uploaded
|
||||
htobe32buf (announce + 80, event); // event
|
||||
htobe32buf (announce + 84, 0); // IP address 0:not used
|
||||
htobe32buf (announce + 88, 0); // key, ignored
|
||||
int numWant = 0;
|
||||
if (!torrent->IsComplete () && (event == eTrackerAnnounceEventNone || event == eTrackerAnnounceEventStarted))
|
||||
numWant = TRACKER_MAX_NUM_WANT;
|
||||
htobe32buf (announce + 92, numWant); // num_want
|
||||
htobe16buf (announce + 96, fromPort); // from port
|
||||
auto session = dgramDest->GetSession (address->identHash);
|
||||
if (session)
|
||||
{
|
||||
m_DatragramTrackerTransactions.emplace (transactionID, std::make_tuple (
|
||||
trackerID, fromPort, torrent, i2p::util::GetMonotonicMilliseconds ()));
|
||||
session->SetVersion (i2p::datagram::eDatagramV3); // send datagram3
|
||||
dgramDest->SendDatagram (session, announce, 98, fromPort, port);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "TorrentsTunnel: Can't obtain datagram session");
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "TorrentsTunnel: Can't obtain datagram session");
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "TorrentsTunnel: Tracker not found: ", dest);
|
||||
}
|
||||
|
||||
void TorrentsTunnel::HandleAnnounceResponse (const uint8_t * buf, size_t len)
|
||||
@@ -930,7 +960,7 @@ namespace torrents
|
||||
LogPrint (eLogInfo, "TorrentsTunnel: Datagram tracker transaction ", transactionID, " not found");
|
||||
return;
|
||||
}
|
||||
auto [torrent, trackerID, ident, port, fromPort, ts, event] = it->second;
|
||||
auto [trackerID, fromPort, torrent, ts] = it->second;
|
||||
if (!torrent.expired ())
|
||||
{
|
||||
uint32_t interval = bufbe32toh (buf + 4);
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace i2p
|
||||
namespace torrents
|
||||
{
|
||||
constexpr int TRACKER_RESPONSE_TIMEOUT = 8; // in seconds
|
||||
constexpr int DATAGRAM_TRACKER_TRANSACTION_TIMEOUT = 60; // in seconds
|
||||
constexpr int DATAGRAM_TRACKER_TRANSACTION_TIMEOUT = 10000; // in milliseconds
|
||||
constexpr int DATAGRAM_TRACKER_CONNECTION_EXPIRATION = 60000; // in milliseconds
|
||||
constexpr int TRACKER_REQUESTS_CHECK_TIMEOUT = 1900; // in milliseconds
|
||||
constexpr int RECONNECT_CHECK_INTERVAL = 70; // in seconds
|
||||
constexpr int TRACKER_REQUESTS_INTERVAL_VARIANCE = 3000; // in milliseconds
|
||||
@@ -76,6 +77,9 @@ namespace torrents
|
||||
void Stop () { StopWorkAndFinishTasks (); }
|
||||
};
|
||||
|
||||
using TrackerInfo = std::tuple<std::string, uint64_t, uint64_t, uint16_t>;
|
||||
// (announce, connection_id, connection expiration time in monotonic milliseconds, connction from_port)
|
||||
|
||||
public:
|
||||
|
||||
TorrentsTunnel (std::string_view name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
||||
@@ -86,7 +90,8 @@ namespace torrents
|
||||
auto& GetDiskIOService () { return m_DiskIOService.GetService (); };
|
||||
|
||||
const std::string& GetPeerID () const { return m_PeerID; }
|
||||
const std::vector<std::string>& GetTrackers () const { return m_Trackers; }
|
||||
std::string_view GetTrackerAnnounce (size_t id) const { return (id < m_Trackers.size ()) ? std::get<0>(m_Trackers[id]) : 0; }
|
||||
size_t GetNumTrackers () const { return m_Trackers.size (); }
|
||||
std::shared_ptr<Torrent> FindTorrent (const Torrent::InfoHash& infoHash) const;
|
||||
std::shared_ptr<Torrent> FindTorrentByID (int id) const;
|
||||
std::vector<int> GetTorrentIDs () const;
|
||||
@@ -134,29 +139,27 @@ namespace torrents
|
||||
void UpdateStats ();
|
||||
|
||||
void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
void ConnectToDatagramTracker (std::shared_ptr<Torrent> torrent, size_t trackerID,
|
||||
std::string_view dest, uint16_t port, TrackerAnnounceEvent event);
|
||||
void ConnectToDatagramTracker (size_t trackerID, std::string_view dest, uint16_t port);
|
||||
void HandleConnectResponse (const uint8_t * buf, size_t len);
|
||||
void HandleErrorResponse (const uint8_t * buf, size_t len);
|
||||
void HandleAnnounceResponse (const uint8_t * buf, size_t len);
|
||||
void SendAnnounceToDatagramTracker (uint32_t transactionID, uint64_t connectionID,
|
||||
std::shared_ptr<Torrent> torrent, const i2p::data::IdentHash& ident,
|
||||
uint16_t port, uint16_t fromPort, TrackerAnnounceEvent event);
|
||||
void SendAnnounceToDatagramTracker (size_t trackerID, uint64_t connectionID,
|
||||
std::shared_ptr<Torrent> torrent, std::string_view dest, uint16_t port,
|
||||
uint16_t fromPort, TrackerAnnounceEvent event);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Name, m_PeerID; // 20 characters
|
||||
std::filesystem::path m_TorrentsDir;
|
||||
std::vector<std::string> m_Trackers;
|
||||
std::vector<TrackerInfo> m_Trackers;
|
||||
std::map<Torrent::InfoHash, std::shared_ptr<Torrent> > m_Torrents;
|
||||
std::map<int, std::weak_ptr<Torrent> > m_TorrentsByID;
|
||||
mutable std::mutex m_TorrentsMutex;
|
||||
boost::asio::steady_timer m_TrackerRequestsCheckTimer, m_KeepAliveCheckTimer,
|
||||
m_ReconnectCheckTimer, m_TorrentsStatusUpdateTimer;
|
||||
DiskIOService m_DiskIOService;
|
||||
std::unordered_map<uint32_t, std::tuple<std::weak_ptr<Torrent>, size_t, i2p::data::IdentHash,
|
||||
uint16_t, uint16_t, uint64_t, TrackerAnnounceEvent> > m_DatragramTrackerTransactions;
|
||||
// transactionID->(torrent, trackerID, ident, port, fromPort, ts in monotonic seconds, event)
|
||||
std::unordered_map<uint32_t, std::tuple<size_t, uint16_t, std::weak_ptr<Torrent>, uint64_t > > m_DatragramTrackerTransactions;
|
||||
// transactionID->(trackerID, from_port, torrent, timestamp monotonic milliseconds)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user