// Name used if the info name isn't available. Should be cleared when the
// Info does become available.
displayName string
+
// The bencoded bytes of the info dict. This is actively manipulated if
// the info bytes aren't initially available, and we try to fetch them
// from peers.
// Each element corresponds to the 16KiB metadata pieces. If true, we have
// received that piece.
metadataCompletedChunks []bool
+ metadataChanged sync.Cond
// Set when .Info is obtained.
gotMetainfo missinggo.Event
}
t.metadataBytes = make([]byte, bytes)
t.metadataCompletedChunks = make([]bool, (bytes+(1<<14)-1)/(1<<14))
+ t.metadataChanged.Broadcast()
for c := range t.conns {
c.requestPendingMetadata()
}
package torrent
import (
+ "net"
"os"
"path/filepath"
"testing"
"github.com/anacrolix/torrent/bencode"
"github.com/anacrolix/torrent/internal/testutil"
"github.com/anacrolix/torrent/metainfo"
- "github.com/anacrolix/torrent/peer_protocol"
+ pp "github.com/anacrolix/torrent/peer_protocol"
"github.com/anacrolix/torrent/storage"
)
-func r(i, b, l peer_protocol.Integer) request {
+func r(i, b, l pp.Integer) request {
return request{i, chunkSpec{b, l}}
}
require.False(t, tt.pieceAllDirty(1))
tt.cl.mu.Unlock()
}
+
+// Check the behaviour of Torrent.Metainfo when metadata is not completed.
+func TestTorrentMetainfoIncompleteMetadata(t *testing.T) {
+ cfg := TestingConfig()
+ cfg.Debug = true
+ cl, err := NewClient(cfg)
+ require.NoError(t, err)
+ defer cl.Close()
+
+ mi := testutil.GreetingMetaInfo()
+ ih := mi.HashInfoBytes()
+
+ tt, _ := cl.AddTorrentInfoHash(ih)
+ assert.Nil(t, tt.Metainfo().InfoBytes)
+ assert.False(t, tt.haveAllMetadataPieces())
+
+ nc, err := net.Dial("tcp", cl.ListenAddr().String())
+ require.NoError(t, err)
+ defer nc.Close()
+
+ var pex peerExtensionBytes
+ pex.SetBit(ExtensionBitExtended)
+ hr, ok, err := handshake(nc, &ih, [20]byte{}, pex)
+ require.NoError(t, err)
+ assert.True(t, ok)
+ assert.True(t, hr.peerExtensionBytes.GetBit(ExtensionBitExtended))
+ assert.EqualValues(t, cl.PeerID(), hr.peerID)
+ assert.Equal(t, ih, hr.Hash)
+
+ assert.EqualValues(t, 0, tt.metadataSize())
+
+ func() {
+ cl.mu.Lock()
+ defer cl.mu.Unlock()
+ go func() {
+ _, err = nc.Write(pp.Message{
+ Type: pp.Extended,
+ ExtendedID: pp.HandshakeExtendedID,
+ ExtendedPayload: func() []byte {
+ d := map[string]interface{}{
+ "metadata_size": len(mi.InfoBytes),
+ }
+ b, err := bencode.Marshal(d)
+ if err != nil {
+ panic(err)
+ }
+ return b
+ }(),
+ }.MustMarshalBinary())
+ require.NoError(t, err)
+ }()
+ tt.metadataChanged.Wait()
+ }()
+ assert.Equal(t, make([]byte, len(mi.InfoBytes)), tt.metadataBytes)
+ assert.False(t, tt.haveAllMetadataPieces())
+ assert.Nil(t, tt.Metainfo().InfoBytes)
+}