]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Only allow chunk size to be set for new Torrents
authorMatt Joiner <anacrolix@gmail.com>
Sun, 10 Oct 2021 00:22:29 +0000 (11:22 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Tue, 19 Oct 2021 03:04:07 +0000 (14:04 +1100)
(cherry picked from commit 09e73e9fce139cd78da48c442e8610501b6fd26b)

client.go
spec.go

index dcf93628e631d4bd4e48a15cb0d1b6862b13acc9..3aa3ad2516b6ff0dedc86abe18021b26d38db56c 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1095,15 +1095,23 @@ func (cl *Client) badPeerIPPort(ip net.IP, port int) bool {
 
 // Return a Torrent ready for insertion into a Client.
 func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (t *Torrent) {
+       return cl.newTorrentOpt(addTorrentOpts{
+               InfoHash: ih,
+               Storage:  specStorage,
+       })
+}
+
+// Return a Torrent ready for insertion into a Client.
+func (cl *Client) newTorrentOpt(opts addTorrentOpts) (t *Torrent) {
        // use provided storage, if provided
        storageClient := cl.defaultStorage
-       if specStorage != nil {
-               storageClient = storage.NewClient(specStorage)
+       if opts.Storage != nil {
+               storageClient = storage.NewClient(opts.Storage)
        }
 
        t = &Torrent{
                cl:       cl,
-               infoHash: ih,
+               infoHash: opts.InfoHash,
                peers: prioritizedPeers{
                        om: btree.New(32),
                        getPrio: func(p PeerInfo) peerPriority {
@@ -1128,7 +1136,10 @@ func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (
        t.networkingEnabled.Set()
        t._pendingPieces.NewSet = priorityBitmapStableNewSet
        t.logger = cl.logger.WithContextValue(t)
-       t.setChunkSize(defaultChunkSize)
+       if opts.ChunkSize == 0 {
+               opts.ChunkSize = defaultChunkSize
+       }
+       t.setChunkSize(opts.ChunkSize)
        return
 }
 
@@ -1170,11 +1181,54 @@ func (cl *Client) AddTorrentInfoHashWithStorage(infoHash metainfo.Hash, specStor
        return
 }
 
+// Adds a torrent by InfoHash with a custom Storage implementation.
+// If the torrent already exists then this Storage is ignored and the
+// existing torrent returned with `new` set to `false`
+func (cl *Client) AddTorrentOpt(opts addTorrentOpts) (t *Torrent, new bool) {
+       infoHash := opts.InfoHash
+       cl.lock()
+       defer cl.unlock()
+       t, ok := cl.torrents[infoHash]
+       if ok {
+               return
+       }
+       new = true
+
+       t = cl.newTorrentOpt(opts)
+       cl.eachDhtServer(func(s DhtServer) {
+               if cl.config.PeriodicallyAnnounceTorrentsToDht {
+                       go t.dhtAnnouncer(s)
+               }
+       })
+       cl.torrents[infoHash] = t
+       cl.clearAcceptLimits()
+       t.updateWantPeersEvent()
+       // Tickle Client.waitAccept, new torrent may want conns.
+       cl.event.Broadcast()
+       return
+}
+
+type addTorrentOpts struct {
+       InfoHash  InfoHash
+       Storage   storage.ClientImpl
+       ChunkSize pp.Integer
+}
+
 // Add or merge a torrent spec. Returns new if the torrent wasn't already in the client. See also
 // Torrent.MergeSpec.
 func (cl *Client) AddTorrentSpec(spec *TorrentSpec) (t *Torrent, new bool, err error) {
-       t, new = cl.AddTorrentInfoHashWithStorage(spec.InfoHash, spec.Storage)
-       err = t.MergeSpec(spec)
+       t, new = cl.AddTorrentOpt(addTorrentOpts{
+               InfoHash:  spec.InfoHash,
+               Storage:   spec.Storage,
+               ChunkSize: spec.ChunkSize,
+       })
+       modSpec := *spec
+       if new {
+               // ChunkSize was already applied by adding a new Torrent, and MergeSpec disallows changing
+               // it.
+               modSpec.ChunkSize = 0
+       }
+       err = t.MergeSpec(&modSpec)
        if err != nil && new {
                t.Drop()
        }
@@ -1218,7 +1272,7 @@ func (t *Torrent) MergeSpec(spec *TorrentSpec) error {
                })
        }
        if spec.ChunkSize != 0 {
-               t.setChunkSize(pp.Integer(spec.ChunkSize))
+               panic("chunk size cannot be changed for existing Torrent")
        }
        t.addTrackers(spec.Trackers)
        t.maybeNewConns()
diff --git a/spec.go b/spec.go
index 21058477e30d28658dc997b5719a8b2d2210fb28..a69e2093d9e386d406f9c95831f17ee00876e874 100644 (file)
--- a/spec.go
+++ b/spec.go
@@ -4,14 +4,17 @@ import (
        "fmt"
 
        "github.com/anacrolix/torrent/metainfo"
+       pp "github.com/anacrolix/torrent/peer_protocol"
        "github.com/anacrolix/torrent/storage"
 )
 
-// Specifies a new torrent for adding to a client. There are helpers for magnet URIs and torrent
-// metainfo files.
+// Specifies a new torrent for adding to a client, or additions to an existing Torrent. There are
+// constructor functions for magnet URIs and torrent metainfo files. TODO: This type should be
+// dismantled into a new Torrent option type, and separate Torrent mutate method(s).
 type TorrentSpec struct {
        // The tiered tracker URIs.
-       Trackers  [][]string
+       Trackers [][]string
+       // TODO: Move into a "new" Torrent opt type.
        InfoHash  metainfo.Hash
        InfoBytes []byte
        // The name to use if the Name field from the Info isn't available.
@@ -22,10 +25,13 @@ type TorrentSpec struct {
        // The combination of the "xs" and "as" fields in magnet links, for now.
        Sources []string
 
-       // The chunk size to use for outbound requests. Defaults to 16KiB if not set.
-       ChunkSize                int
+       // The chunk size to use for outbound requests. Defaults to 16KiB if not set. Can only be set
+       // for new Torrents. TODO: Move into a "new" Torrent opt type.
+       ChunkSize pp.Integer
+       // TODO: Move into a "new" Torrent opt type.
+       Storage storage.ClientImpl
+       
        DisableInitialPieceCheck bool
-       Storage                  storage.ClientImpl
 
        // Whether to allow data download or upload
        DisallowDataUpload   bool