client.go | 43 +++++++++++++++++++------------------------ client_test.go | 6 +++++- diff --git a/client.go b/client.go index 48843c85e06c40927d423f17318544d725c3c577..6876f6b13ae0d10e3ab7587f8885991453c106f2 100644 --- a/client.go +++ b/client.go @@ -64,7 +64,6 @@ listeners []net.Listener utpSock *utp.Socket dHT *dht.Server ipBlockList iplist.Ranger - bannedTorrents map[metainfo.Hash]struct{} config Config pruneTimer *time.Timer extensionBytes peerExtensionBytes @@ -1435,8 +1434,9 @@ // Prepare a Torrent without any attachment to a Client. That means we can // initialize fields all fields that don't require the Client without locking // it. -func newTorrent(ih metainfo.Hash) (t *Torrent) { +func (cl *Client) newTorrent(ih metainfo.Hash) (t *Torrent) { t = &Torrent{ + cl: cl, infoHash: ih, chunkSize: defaultChunkSize, peers: make(map[peersKey]Peer), @@ -1448,7 +1448,10 @@ gotMetainfo: make(chan struct{}), halfOpen: make(map[string]struct{}), pieceStateChanges: pubsub.NewPubSub(), + + storageOpener: cl.defaultStorage, } + t.wantPeers.L = &cl.mu return } @@ -1540,36 +1543,28 @@ } return } +func (cl *Client) AddTorrentInfoHash(infoHash metainfo.Hash) (t *Torrent, new bool) { + cl.mu.Lock() + defer cl.mu.Unlock() + t, ok := cl.torrents[infoHash] + if ok { + return + } + new = true + t = cl.newTorrent(infoHash) + return +} + // Add or merge a torrent spec. If the torrent is already present, the // trackers will be merged with the existing ones. If the Info isn't yet // known, it will be set. The display name is replaced if the new spec // provides one. Returns new if the torrent wasn't already in the client. func (cl *Client) AddTorrentSpec(spec *TorrentSpec) (t *Torrent, new bool, err error) { + t, new = cl.AddTorrentInfoHash(spec.InfoHash) + cl.mu.Lock() defer cl.mu.Unlock() - t, ok := cl.torrents[spec.InfoHash] - if !ok { - new = true - - // TODO: This doesn't belong in the core client, it's more of a - // helper. - if _, ok := cl.bannedTorrents[spec.InfoHash]; ok { - err = errors.New("banned torrent") - return - } - // TODO: Tidy this up? - t = newTorrent(spec.InfoHash) - t.cl = cl - t.wantPeers.L = &cl.mu - if spec.ChunkSize != 0 { - t.chunkSize = pp.Integer(spec.ChunkSize) - } - t.storageOpener = spec.Storage - if t.storageOpener == nil { - t.storageOpener = cl.defaultStorage - } - } if spec.DisplayName != "" { t.setDisplayName(spec.DisplayName) } diff --git a/client_test.go b/client_test.go index 94ea00da07d8b380b9d71f62c30789189b4db2a0..2fedb5a952bc52a8db90cfa98b1cd118385bf580 100644 --- a/client_test.go +++ b/client_test.go @@ -18,6 +18,7 @@ _ "github.com/anacrolix/envpprof" "github.com/anacrolix/missinggo" "github.com/anacrolix/missinggo/filecache" + "github.com/anacrolix/missinggo/pubsub" "github.com/anacrolix/utp" "github.com/bradfitz/iter" "github.com/stretchr/testify/assert" @@ -84,7 +85,10 @@ func TestTorrentInitialState(t *testing.T) { dir, mi := testutil.GreetingTestTorrent() defer os.RemoveAll(dir) - tor := newTorrent(mi.Info.Hash()) + tor := &Torrent{ + infoHash: mi.Info.Hash(), + pieceStateChanges: pubsub.NewPubSub(), + } tor.chunkSize = 2 tor.storageOpener = storage.NewFile(dir) // Needed to lock for asynchronous piece verification.