mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-10-06 03:28:05 +00:00
BEP6
This commit is contained in:
@@ -879,7 +879,7 @@ namespace torrents
|
||||
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_RemoteMetadataSize (0),
|
||||
m_Downloaded (0), m_Uploaded (0)
|
||||
m_IsFast (false), m_Downloaded (0), m_Uploaded (0)
|
||||
{
|
||||
ResetStats ();
|
||||
}
|
||||
@@ -1175,6 +1175,15 @@ namespace torrents
|
||||
case eMessageTypeExtended:
|
||||
HandleExtendedMsg (m_ReceiveBuffer + offset + 1, msgLen - 1);
|
||||
break;
|
||||
case eMessageTypeSuggestPiece:
|
||||
LogPrint (eLogDebug, "Torrents: suggest piece msg received");
|
||||
break;
|
||||
case eMessageTypeRejectRequest:
|
||||
LogPrint (eLogDebug, "Torrents: reject request msg received");
|
||||
break;
|
||||
case eMessageTypeAllowedFast:
|
||||
LogPrint (eLogDebug, "Torrents: allowed fast msg received");
|
||||
break;
|
||||
default:
|
||||
LogPrint (eLogWarning, "Torrents: Unexpected message type ", (int)m_ReceiveBuffer[offset], ". Ignored");
|
||||
};
|
||||
@@ -1215,7 +1224,8 @@ namespace torrents
|
||||
// respond with handshake if incoming
|
||||
if (!m_IsHandshakeSent)
|
||||
SendHandshakeMsg ();
|
||||
if (m_ReceiveBuffer[20 + 5] & 0x10) // bit 20 of reserved, BEP10
|
||||
// BEP10
|
||||
if (m_ReceiveBuffer[20 + 5] & 0x10) // bit 20 of reserved
|
||||
SendExtendedMsg (); // extended handshake if peer supports BEP10
|
||||
else if (!m_Torrent->GetLength ()) // we are magnet without info
|
||||
{
|
||||
@@ -1223,10 +1233,20 @@ namespace torrents
|
||||
Terminate ();
|
||||
return 0;
|
||||
}
|
||||
// send bitfield if not empty
|
||||
// BEP6
|
||||
if (m_ReceiveBuffer[20 + 7] & 0x04) // bit 61 of reserved
|
||||
m_IsFast = true;
|
||||
// send bitfield, have all or have none
|
||||
auto [bitfield, empty] = m_Torrent->CreateBitfield ();
|
||||
if (!empty)
|
||||
SendBitfieldMsg (bitfield.data (), bitfield.size ());
|
||||
{
|
||||
if (m_IsFast && m_Torrent->IsComplete ())
|
||||
SendHaveAllMsg ();
|
||||
else
|
||||
SendBitfieldMsg (bitfield.data (), bitfield.size ());
|
||||
}
|
||||
else if (m_IsFast)
|
||||
SendHaveNoneMsg ();
|
||||
m_IsEstablished = true;
|
||||
return HANDSHAKE_MSG_LENGTH;
|
||||
}
|
||||
@@ -1238,6 +1258,7 @@ namespace torrents
|
||||
buf[0] = 19; memcpy (buf + 1, "BitTorrent protocol", 19);
|
||||
memset (buf + 20, 0, 8); // reserved
|
||||
buf[20 + 5] |= 0x10; // bit 20 of reserved, BEP10
|
||||
buf[20 + 7] |= 0x04; // bit 61 of reserved, BEP6
|
||||
memcpy (buf + 28, m_Torrent->GetInfoHash ().data (), 20);
|
||||
memset (buf + 48, '0', 20);
|
||||
if (GetTorrentsTunnel ())
|
||||
@@ -1342,6 +1363,14 @@ namespace torrents
|
||||
Terminate (); // we don't need this connection
|
||||
}
|
||||
|
||||
void PeerConnection::SendHaveAllMsg ()
|
||||
{
|
||||
uint8_t buf[HAVE_ALL_MSG_LENGTH];
|
||||
htobe32buf (buf, 1);
|
||||
buf[4] = eMessageTypeHaveAll;
|
||||
WriteToStream (buf, HAVE_ALL_MSG_LENGTH);
|
||||
}
|
||||
|
||||
void PeerConnection::HandleHaveNoneMsg ()
|
||||
{
|
||||
if (!m_Torrent) return;
|
||||
@@ -1350,6 +1379,14 @@ namespace torrents
|
||||
m_RemoteBitfield.reset ();
|
||||
}
|
||||
|
||||
void PeerConnection::SendHaveNoneMsg ()
|
||||
{
|
||||
uint8_t buf[HAVE_NONE_MSG_LENGTH];
|
||||
htobe32buf (buf, 1);
|
||||
buf[4] = eMessageTypeHaveNone;
|
||||
WriteToStream (buf, HAVE_NONE_MSG_LENGTH);
|
||||
}
|
||||
|
||||
void PeerConnection::HandlePieceMsg (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (len < 8) return;
|
||||
@@ -1466,6 +1503,17 @@ namespace torrents
|
||||
m_Torrent->AddUploaded (len);
|
||||
}
|
||||
|
||||
void PeerConnection::SendRejectRequestMsg (uint32_t index, uint32_t offset, uint32_t len)
|
||||
{
|
||||
uint8_t buf[REJECT_REQUEST_MSG_LENGTH];
|
||||
htobe32buf (buf, REJECT_REQUEST_MSG_PAYLOAD_LENGTH + 1); // msg length
|
||||
buf[4] = eMessageTypeRejectRequest; // msg ID
|
||||
htobe32buf (buf + 5, index); // index
|
||||
htobe32buf (buf + 9, offset); // offset
|
||||
htobe32buf (buf + 13, len); // length
|
||||
WriteToStream (buf, REJECT_REQUEST_MSG_LENGTH);
|
||||
}
|
||||
|
||||
void PeerConnection::HandleRequestMsg (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (!m_Torrent) return;
|
||||
@@ -1541,10 +1589,18 @@ namespace torrents
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "Torrents: Requested block (", index, ",", offset, ") is not available");
|
||||
if (m_IsFast)
|
||||
SendRejectRequestMsg (index, offset, length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "Torrents: Requested index ", index, "exceeds number of pieces", m_Torrent->GetNumPieces ());
|
||||
if (m_IsFast)
|
||||
SendRejectRequestMsg (index, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
bool PeerConnection::SendRequestedBlock (const RequestedBlock& requestedBlock)
|
||||
|
||||
@@ -51,8 +51,12 @@ namespace torrents
|
||||
constexpr size_t NOTINTERESTED_MSG_LENGTH = 5;
|
||||
constexpr size_t CHOKE_MSG_LENGTH = 5;
|
||||
constexpr size_t UNCHOKE_MSG_LENGTH = 5;
|
||||
constexpr size_t HAVE_ALL_MSG_LENGTH = 5;
|
||||
constexpr size_t HAVE_NONE_MSG_LENGTH = 5;
|
||||
constexpr size_t REQUEST_MSG_PAYLOAD_LENGTH = 12;
|
||||
constexpr size_t REQUEST_MSG_LENGTH = REQUEST_MSG_PAYLOAD_LENGTH + 5;
|
||||
constexpr size_t REJECT_REQUEST_MSG_PAYLOAD_LENGTH = 12;
|
||||
constexpr size_t REJECT_REQUEST_MSG_LENGTH = REJECT_REQUEST_MSG_PAYLOAD_LENGTH + 5;
|
||||
constexpr size_t HAVE_MSG_PAYLOAD_LENGTH = 4;
|
||||
|
||||
// extensions
|
||||
@@ -69,9 +73,14 @@ namespace torrents
|
||||
eMessageTypeBitfield = 5,
|
||||
eMessageTypeRequest = 6,
|
||||
eMessageTypePiece = 7,
|
||||
// BEP6
|
||||
eMessageTypeSuggestPiece = 13,
|
||||
eMessageTypeHaveAll = 14,
|
||||
eMessageTypeHaveNone = 15,
|
||||
eMessageTypeExtended = 20 // BEP10
|
||||
eMessageTypeRejectRequest = 16,
|
||||
eMessageTypeAllowedFast = 17,
|
||||
// BEP10
|
||||
eMessageTypeExtended = 20
|
||||
};
|
||||
|
||||
struct PieceFileFragment // fragment to save to/load from file
|
||||
@@ -315,9 +324,12 @@ namespace torrents
|
||||
void HandleBitfieldMsg (const uint8_t * buf, size_t len);
|
||||
void SendBitfieldMsg (const uint8_t * bitfield, size_t bitfieldLen);
|
||||
void HandleHaveAllMsg ();
|
||||
void SendHaveAllMsg ();
|
||||
void HandleHaveNoneMsg ();
|
||||
void SendHaveNoneMsg ();
|
||||
void HandlePieceMsg (const uint8_t * buf, size_t len);
|
||||
void SendPieceMsg (uint32_t index, uint32_t offset, const uint8_t * data, size_t len);
|
||||
void SendRejectRequestMsg (uint32_t index, uint32_t offset, uint32_t len);
|
||||
void HandleRequestMsg (const uint8_t * buf, size_t len);
|
||||
void SendRequestMsg (uint32_t index, uint32_t offset, uint32_t len);
|
||||
size_t FillRequestMsg (uint8_t * buf, uint32_t index, uint32_t offset, uint32_t len);
|
||||
@@ -355,6 +367,8 @@ namespace torrents
|
||||
// BEP9
|
||||
size_t m_RemoteMetadataSize;
|
||||
std::vector<uint8_t> m_RemoteMetadata;
|
||||
// BEP6
|
||||
bool m_IsFast;
|
||||
// stats
|
||||
uint64_t m_DownloadRate, m_UploadRate; // B/sec
|
||||
uint64_t m_LastBlockDownloadTimestamp, m_LastBlockUploadTimestamp; // monotonic milliseconds
|
||||
|
||||
Reference in New Issue
Block a user