diff --git a/libi2pd_client/Torrents.cpp b/libi2pd_client/Torrents.cpp index c4364b10..686f9dda 100644 --- a/libi2pd_client/Torrents.cpp +++ b/libi2pd_client/Torrents.cpp @@ -896,29 +896,16 @@ namespace torrents return completed; } - std::unordered_set Torrent::GetPeers () const - { - if (m_TrackerStats.size () == 1) - return std::get<0>(m_TrackerStats.front ()); - std::unordered_set ret; - for (const auto& it: m_TrackerStats) - { - const auto& peers = std::get<0>(it); - ret.insert (peers.begin (), peers.end ()); - } - return ret; - } - std::unordered_set Torrent::GetNonConnectedPeers () { std::unordered_set ret; for (const auto& it: m_TrackerStats) { const auto& peers = std::get<0>(it); - for (const auto& it: peers) + for (const auto& it1: peers) { - if (!IsConnectedToPeer (it)) - ret.emplace (it); + if (!IsConnectedToPeer (it1)) + ret.emplace (it1); } } return ret; @@ -1089,9 +1076,19 @@ namespace torrents void PeerConnection::Connect () { - SendHandshakeMsg (); - ScheduleHandshakeReceiveTimer (); - StreamReceive (); + if (m_Torrent && m_Torrent->AddConnection (shared_from_this ())) + { + SendHandshakeMsg (); + ScheduleHandshakeReceiveTimer (); + StreamReceive (); + } + else + { + LogPrint (eLogWarning, "Torrents: Connection with peer ", + i2p::data::GetIdentHashAbbreviation (m_Stream->GetRemoteIdentity ()->GetIdentHash ()), " already exists"); + Terminate (); + return; + } } void PeerConnection::ReceiveHandshake () @@ -1334,8 +1331,8 @@ namespace torrents { Torrent::InfoHash infoHash; memcpy (infoHash.data (), m_ReceiveBuffer + 28, 20); - m_Torrent = GetTorrentsTunnel ()->FindTorrent (infoHash); - if (!m_Torrent) + auto torrent = GetTorrentsTunnel ()->FindTorrent (infoHash); + if (!torrent) { std::string hexHash; boost::algorithm::hex (infoHash.begin(), infoHash.end(), std::back_inserter(hexHash)); @@ -1343,12 +1340,35 @@ namespace torrents Terminate (); return 0; } - if (m_Torrent->IsStopped ()) + if (torrent->IsStopped ()) { - LogPrint (eLogInfo, "Torrents: Torrent ", m_Torrent->GetName (), " is stopped"); + LogPrint (eLogInfo, "Torrents: Torrent ", torrent->GetName (), " is stopped"); Terminate (); return 0; } + if (m_Torrent) + { + // outgoing + if (m_Torrent->GetInfoHash () != infoHash) + { + LogPrint (eLogWarning, "Torrents: InfoHash mistmatch for ", torrent->GetName ()); + Terminate (); + return 0; + } + } + else + { + // incoming + if (torrent->AddConnection (shared_from_this ())) + m_Torrent = torrent; + else + { + LogPrint (eLogWarning, "Torrents: Incoming connection with peer ", + i2p::data::GetIdentHashAbbreviation (m_Stream->GetRemoteIdentity ()->GetIdentHash ()), " already exists"); + Terminate (); + return 0; + } + } } memcpy (m_RemotePeerID.data (), m_ReceiveBuffer + 48, m_RemotePeerID.size ()); // respond with handshake if incoming @@ -1366,15 +1386,7 @@ namespace torrents // BEP6 if (m_ReceiveBuffer[20 + 7] & 0x04) // bit 61 of reserved m_IsFast = true; - // established m_IsEstablished = true; - if (!m_Torrent->AddConnection (shared_from_this ())) - { - LogPrint (eLogWarning, "Torrents: Connection with peer ", - i2p::data::GetIdentHashAbbreviation (m_Stream->GetRemoteIdentity ()->GetIdentHash ()), " already exists"); - Terminate (); - return 0; - } // send bitfield, have all or have none auto [bitfield, have] = m_Torrent->CreateBitfield (); if (!have) // have none @@ -2066,13 +2078,7 @@ namespace torrents }); if (!newPeers.empty ()) { - auto existingPeers = m_Torrent->GetPeers (); - for (auto it: existingPeers) - newPeers.extract (it); - } - if (!newPeers.empty ()) - { - LogPrint (eLogDebug, "Torrents: I2P_PEX ", newPeers.size (), " new peers"); + LogPrint (eLogDebug, "Torrents: I2P_PEX ", newPeers.size (), " new peers received"); GetTorrentsTunnel ()->ConnectToNewPeers (m_Torrent, newPeers); } } diff --git a/libi2pd_client/Torrents.h b/libi2pd_client/Torrents.h index 9e009bdb..f6c7abc3 100644 --- a/libi2pd_client/Torrents.h +++ b/libi2pd_client/Torrents.h @@ -212,7 +212,6 @@ namespace torrents Piece& GetPiece (int index) { return m_Pieces[index]; } std::pair, boost::logic::tribool> CreateBitfield () const; // (bitfield, true - all false - none) bool ApplyBitfield (const std::vector& bitfield); // return true if complete - std::unordered_set GetPeers () const; // from trackers std::unordered_set GetNonConnectedPeers (); RequestedBlock GetNextBlockToRequest (std::shared_ptr conn, bool skipRequested = true); std::vector GetPieceFileFragments (int index) const; diff --git a/libi2pd_client/TorrentsTunnel.cpp b/libi2pd_client/TorrentsTunnel.cpp index 7436b47d..e565a2c8 100644 --- a/libi2pd_client/TorrentsTunnel.cpp +++ b/libi2pd_client/TorrentsTunnel.cpp @@ -340,7 +340,9 @@ namespace torrents SaveTorrentFile (torrent); InitTorrentFiles (torrent); }); - return { torrent, InsertTorrent (torrent) }; + auto id = InsertTorrent (torrent); + boost::asio::post (GetService (), [this, torrent] { RequestTorrentTrackers (torrent, eTrackerAnnounceEventNone); }); + return { torrent, id }; } return { torrent, 0 }; } @@ -395,7 +397,9 @@ namespace torrents auto torrent = std::make_shared (infoHash); if (!announce.empty ()) torrent->SetAnnounce (announce); if (!name.empty ()) torrent->SetName (name); - return { torrent, InsertTorrent (torrent) }; + auto id = InsertTorrent (torrent); + boost::asio::post (GetService (), [this, torrent] { RequestTorrentTrackers (torrent, eTrackerAnnounceEventNone); }); + return { torrent, id }; } } return { nullptr, 0 };