handle BEP9 message

This commit is contained in:
orignal
2026-09-01 15:26:24 -04:00
parent b8282d2d4c
commit 39d6178f33
2 changed files with 48 additions and 4 deletions
+45 -4
View File
@@ -854,7 +854,7 @@ namespace torrents
m_Stream (stream), m_ReceiveBufferOffset (0), m_NextMsgLength (0),
m_IsHandshakeSent (false), m_IsEstablished (false), m_IsChoked (true), m_IsRemoteChoked (true),
m_IsInterested (false), m_IsRemoteInterested (false), m_LastReceiveTime (0), m_LastSendTime (0),
m_NumRequests (0), m_NumPieces (0), m_LastRequestedPieceIndex (-1),
m_NumRequests (0), m_NumPieces (0), m_LastRequestedPieceIndex (-1), m_RemoteMetadataSize (0),
m_Downloaded (0), m_Uploaded (0)
{
ResetStats ();
@@ -1608,6 +1608,12 @@ namespace torrents
return l;
});
}
else if (key == "metadata_size")
{
auto [s, l] = ExtractInteger (buf);
if (l) m_RemoteMetadataSize = s;
return l;
}
else if (key == "v")
{
auto [v, l] = ExtractByteString (buf);
@@ -1661,8 +1667,9 @@ namespace torrents
{
if (!m_Torrent) return;
int msgType = -1, piece = -1;
ParseDictionary (std::string_view ((const char *)buf, len),
[&msgType, &piece](std::string_view key, std::string_view buf)->size_t
size_t size = 0;
auto payloadLen = ParseDictionary (std::string_view ((const char *)buf, len),
[&msgType, &piece, &size](std::string_view key, std::string_view buf)->size_t
{
if (key == "msg_type")
{
@@ -1676,13 +1683,19 @@ namespace torrents
if (!l) piece = value;
return l;
}
else if (key == "total_size")
{
auto [s, l] = ExtractInteger (buf);
if (!l) size = s;
return l;
}
return 0;
});
if (msgType >=0 && piece >= 0)
{
switch (msgType)
{
case 0:
case 0: // request
{
auto& info = m_Torrent->GetInfo ();
size_t offset = piece*REQUEST_BLOCK_SIZE;
@@ -1695,8 +1708,36 @@ namespace torrents
{ "total_size", CreateInteger (totalSize) } }),
std::string_view ((const char *)info.data () + offset, totalSize));
}
else
SendExtendedMsg (EXTENSION_MSGID_UT_METADATA, CreateDictionary ({{ "msg_type", CreateInteger (2) }, { "piece", CreateInteger (piece) }}));
break;
}
case 1: // data
{
if (payloadLen + size > len) break;
size_t offset = piece*REQUEST_BLOCK_SIZE;
if (offset == m_RemoteMetadata.size () && size)
{
m_RemoteMetadata.resize (m_RemoteMetadata.size () + size);
memcpy (m_RemoteMetadata.data () + offset,buf + payloadLen, size);
if (m_RemoteMetadata.size () < m_RemoteMetadataSize)
// request next piece
SendExtendedMsg (EXTENSION_MSGID_UT_METADATA, CreateDictionary ({{ "msg_type", CreateInteger (0) }, { "piece", CreateInteger (piece + 1) }}));
else
{
// all info received
LogPrint (eLogDebug, "Torrents: ut_metadata ", m_RemoteMetadataSize, " bytes of info received");
// TODO: update torrent
// cleanup
std::vector<uint8_t> tmp;
m_RemoteMetadata.swap (tmp);
}
}
break;
}
case 2: // reject
LogPrint (eLogError, "Torrents: ut_metadata piece ", piece, " request rejected");
break;
default:
LogPrint (eLogInfo, "Torrents: ut_metadata msg_type ", msgType, " is not supported");
}
+3
View File
@@ -347,6 +347,9 @@ namespace torrents
int m_LastRequestedPieceIndex;
std::unique_ptr<boost::asio::steady_timer> m_HandshakeReceiveTimer;
std::unordered_map<uint8_t, PeerConnection::ExtendedMessageHandler> m_ExtendedMessageHandlers;
// BEP9
size_t m_RemoteMetadataSize;
std::vector<uint8_t> m_RemoteMetadata;
// stats
uint64_t m_DownloadRate, m_UploadRate; // B/sec
uint64_t m_LastBlockDownloadTimestamp, m_LastBlockUploadTimestamp; // monotonic milliseconds