mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-07-28 23:09:25 +00:00
list of connections per piece. send bitfield
This commit is contained in:
@@ -194,6 +194,7 @@ namespace torrents
|
||||
f.write ((const char *)m_Data, m_Size);
|
||||
delete[] m_Data; m_Data = nullptr;
|
||||
if (m_Missing) BN_free (m_Missing);
|
||||
m_Connections.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +231,11 @@ namespace torrents
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
void Piece::AddConnection (std::shared_ptr<PeerConnection> connection)
|
||||
{
|
||||
m_Connections.emplace_back (connection);
|
||||
}
|
||||
|
||||
Torrent::Torrent (std::string_view buf):
|
||||
m_Length (0), m_PieceLength (0), m_Interval (0)
|
||||
{
|
||||
@@ -560,8 +566,13 @@ namespace torrents
|
||||
return 0;
|
||||
}
|
||||
m_RemotePeerID = std::string_view ((const char *)(m_ReceiveBuffer + 48), 20);
|
||||
// respond wiith handshake if incoming
|
||||
if (!m_IsHandshakeSent)
|
||||
SendHandshakeMsg ();
|
||||
// send bitfield if not empty
|
||||
auto bitfield = m_Torrent->CreateBitfield ();
|
||||
if (bitfield.size ())
|
||||
SendBitfieldMsg (bitfield.data (), bitfield.size ());
|
||||
m_IsEstablished = true;
|
||||
return HANDSHAKE_MSG_LENGTH;
|
||||
}
|
||||
@@ -596,6 +607,22 @@ namespace torrents
|
||||
BN_free (m_RemoteBitfield);
|
||||
m_RemoteBitfield = newBitfield;
|
||||
}
|
||||
if (m_Torrent)
|
||||
{
|
||||
size_t numPieces = m_Torrent->GetNumPieces ();
|
||||
for (size_t i = 0; i < numPieces; i++)
|
||||
if (BN_is_bit_set (m_RemoteBitfield, numPieces - i - 1))
|
||||
m_Torrent->GetPiece (i).AddConnection (shared_from_this ());
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::SendBitfieldMsg (const uint8_t * bitfield, size_t bitfieldLen)
|
||||
{
|
||||
std::vector<uint8_t> sendBuffer(bitfieldLen + 5);
|
||||
htobe32buf (sendBuffer.data (), bitfieldLen + 1); // length
|
||||
sendBuffer[4] = eMessageTypeBitfield; // msg ID
|
||||
memcpy (sendBuffer.data () + 5, bitfield, bitfieldLen);
|
||||
WriteToStream (sendBuffer.data (), sendBuffer.size ());
|
||||
}
|
||||
|
||||
void PeerConnection::HandlePieceMsg (const uint8_t * buf, size_t len)
|
||||
@@ -617,7 +644,7 @@ namespace torrents
|
||||
void PeerConnection::SendPieceMsg (uint32_t index, uint32_t offset, const uint8_t * data, size_t len)
|
||||
{
|
||||
std::vector<uint8_t> sendBuffer(len + 8 + 5);
|
||||
htobe32buf (sendBuffer.data (), len + 8); // length
|
||||
htobe32buf (sendBuffer.data (), len + 8 + 1); // length
|
||||
sendBuffer[4] = eMessageTypePiece; // msg ID
|
||||
htobe32buf (sendBuffer.data () + 5, index);
|
||||
htobe32buf (sendBuffer.data () + 9, offset);
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace torrents
|
||||
eMessageTypePiece = 7
|
||||
};
|
||||
|
||||
class PeerConnection;
|
||||
class Piece final
|
||||
{
|
||||
public:
|
||||
@@ -60,6 +61,8 @@ namespace torrents
|
||||
size_t GetSize () const { return m_Size; }
|
||||
std::pair<size_t, size_t> GetAvailableBuffer (size_t offset, size_t len) const; // return (offset, len) of available data
|
||||
|
||||
void AddConnection (std::shared_ptr<PeerConnection> connection);
|
||||
|
||||
private:
|
||||
|
||||
bool IsAvailable (int block) const;
|
||||
@@ -70,6 +73,7 @@ namespace torrents
|
||||
size_t m_Size;
|
||||
uint8_t * m_Data, m_Hash[SHA_DIGEST_LENGTH];
|
||||
BIGNUM * m_Missing; // bit is set if block is missing
|
||||
std::list<std::weak_ptr<PeerConnection> > m_Connections; // for incomplete pieces only
|
||||
};
|
||||
|
||||
class Torrent final
|
||||
@@ -136,6 +140,7 @@ namespace torrents
|
||||
void SendHandshakeMsg ();
|
||||
|
||||
void HandleBitfieldMsg (const uint8_t * buf, size_t len);
|
||||
void SendBitfieldMsg (const uint8_t * bitfield, size_t bitfieldLen);
|
||||
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 HandleRequestMsg (const uint8_t * buf, size_t len);
|
||||
|
||||
Reference in New Issue
Block a user