})
}
if torrent.haveAnyPieces() {
- conn.Post(pp.Message{
- Type: pp.Bitfield,
- Bitfield: torrent.bitfield(),
- })
+ conn.Bitfield(torrent.bitfield())
} else if me.extensionBytes.SupportsFast() && conn.PeerExtensionBytes.SupportsFast() {
conn.Post(pp.Message{
Type: pp.HaveNone,
me.pieceChanged(t, int(piece))
}
-// TODO: Check this isn't called more than once for each piece being correct.
func (me *Client) pieceChanged(t *torrent, piece int) {
correct := t.pieceComplete(piece)
p := &t.Pieces[piece]
}
for _, conn := range t.Conns {
if correct {
- conn.Post(pp.Message{
- Type: pp.Have,
- Index: pp.Integer(piece),
- })
- // TODO: Cancel requests for this piece.
+ conn.Have(piece)
for r := range conn.Requests {
if int(r.Index) == piece {
conn.Cancel(r)
// Indexed by metadata piece, set to true if posted and pending a
// response.
metadataRequests []bool
+ sentHaves []bool
// Stuff controlled by the remote peer.
PeerID [20]byte
}
}
}
+
+func (cn *connection) Have(piece int) {
+ for piece >= len(cn.sentHaves) {
+ cn.sentHaves = append(cn.sentHaves, false)
+ }
+ if cn.sentHaves[piece] {
+ return
+ }
+ cn.Post(pp.Message{
+ Type: pp.Have,
+ Index: pp.Integer(piece),
+ })
+ cn.sentHaves[piece] = true
+}
+
+func (cn *connection) Bitfield(haves []bool) {
+ if len(cn.sentHaves) != nil {
+ panic("bitfield must be first have-related message sent")
+ }
+ cn.Post(pp.Message{
+ Type: pp.Bitfield,
+ Bitfield: haves,
+ })
+ cn.sentHaves = haves
+}