]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Add BitTorrent v2 fields, consts and reference torrents
authorMatt Joiner <anacrolix@gmail.com>
Sun, 25 Feb 2024 06:00:16 +0000 (17:00 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Sun, 25 Feb 2024 06:01:01 +0000 (17:01 +1100)
metainfo/file-tree.go [new file with mode: 0644]
metainfo/info.go
metainfo/metainfo.go
peer_protocol/handshake.go
peer_protocol/reserved_test.go [new file with mode: 0644]
testdata/bittorrent-v2-hybrid-test.torrent [new file with mode: 0644]
testdata/bittorrent-v2-test.torrent [new file with mode: 0644]
types/infohash/infohash.go

diff --git a/metainfo/file-tree.go b/metainfo/file-tree.go
new file mode 100644 (file)
index 0000000..0bccb15
--- /dev/null
@@ -0,0 +1,9 @@
+package metainfo
+
+type FileTree struct {
+       File struct {
+               Length     int64  `bencode:"length"`
+               PiecesRoot string `bencode:"pieces root"`
+       }
+       Dir map[string]FileTree
+}
index 1ee2704ec97b760025eda2a951966a8174665626..5eedfa3b4c41730ddb92543abfb855ad635e27e4 100644 (file)
@@ -11,7 +11,7 @@ import (
        "github.com/anacrolix/missinggo/v2/slices"
 )
 
-// The info dictionary.
+// The info dictionary. See BEP 3 and BEP 52.
 type Info struct {
        PieceLength int64  `bencode:"piece length"` // BEP3
        Pieces      []byte `bencode:"pieces"`       // BEP3
@@ -22,6 +22,10 @@ type Info struct {
        // TODO: Document this field.
        Source string     `bencode:"source,omitempty"`
        Files  []FileInfo `bencode:"files,omitempty"` // BEP3, mutually exclusive with Length
+
+       // BEP 52 (BitTorrent v2)
+       MetaVersion int64    `bencode:"meta version,omitempty"`
+       FileTree    FileTree `bencode:"file tree,omitempty"`
 }
 
 // The Info.Name field is "advisory". For multi-file torrents it's usually a suggested directory
@@ -157,7 +161,7 @@ func (info *Info) Piece(index int) Piece {
        return Piece{info, pieceIndex(index)}
 }
 
-func (info Info) BestName() string {
+func (info *Info) BestName() string {
        if info.NameUtf8 != "" {
                return info.NameUtf8
        }
index 93f9103b968b09f661cb3aa9a9a6618a8102cdb6..9f4109899c7a6b54f202a0c14f43cfbcd8806722 100644 (file)
@@ -10,6 +10,7 @@ import (
        "github.com/anacrolix/torrent/bencode"
 )
 
+// Also known as a torrent file.
 type MetaInfo struct {
        InfoBytes    bencode.Bytes `bencode:"info,omitempty"`                              // BEP 3
        Announce     string        `bencode:"announce,omitempty"`                          // BEP 3
@@ -23,10 +24,12 @@ type MetaInfo struct {
        CreatedBy    string  `bencode:"created by,omitempty"`
        Encoding     string  `bencode:"encoding,omitempty"`
        UrlList      UrlList `bencode:"url-list,omitempty"` // BEP 19 WebSeeds
+       // BEP 52 (BitTorrent v2): Keys are file merkle roots (pieces root?), and the values are the
+       // concatenated hashes of the merkle tree layer that corresponds to the piece length.
+       PieceLayers map[string]string `bencode:"piece layers,omitempty"`
 }
 
-// Load a MetaInfo from an io.Reader. Returns a non-nil error in case of
-// failure.
+// Load a MetaInfo from an io.Reader. Returns a non-nil error in case of failure.
 func Load(r io.Reader) (*MetaInfo, error) {
        var mi MetaInfo
        d := bencode.NewDecoder(r)
@@ -85,8 +88,7 @@ func (mi MetaInfo) Magnet(infoHash *Hash, info *Info) (m Magnet) {
        return
 }
 
-// Returns the announce list converted from the old single announce field if
-// necessary.
+// Returns the announce-list converted from the old single announce field if necessary.
 func (mi *MetaInfo) UpvertedAnnounceList() AnnounceList {
        if mi.AnnounceList.OverridesAnnounce(mi.Announce) {
                return mi.AnnounceList
index a6f648cfe6e16ea3a6b147dd8bd5490a14c57022..bce28340bbe8c60d75c4aa735ae1c42d790a9990 100644 (file)
@@ -18,9 +18,12 @@ type ExtensionBit uint
 // https://www.bittorrent.org/beps/bep_0004.html
 // https://wiki.theory.org/BitTorrentSpecification.html#Reserved_Bytes
 const (
-       ExtensionBitDht                          = 0 // http://www.bittorrent.org/beps/bep_0005.html
-       ExtensionBitFast                         = 2 // http://www.bittorrent.org/beps/bep_0006.html
-       ExtensionBitV2                           = 7 // "Hybrid torrent legacy to v2 upgrade"
+       ExtensionBitDht  = 0 // http://www.bittorrent.org/beps/bep_0005.html
+       ExtensionBitFast = 2 // http://www.bittorrent.org/beps/bep_0006.html
+       // A peer connection initiator can set this when sending a v1 infohash during handshake if they
+       // allow the receiving end to upgrade to v2 by responding with the corresponding v2 infohash.
+       // BEP 52, and BEP 4
+       ExtensionBitV2Upgrade                    = 4
        ExtensionBitAzureusExtensionNegotiation1 = 16
        ExtensionBitAzureusExtensionNegotiation2 = 17
        // LibTorrent Extension Protocol, http://www.bittorrent.org/beps/bep_0010.html
@@ -56,7 +59,7 @@ var bitTags = []struct {
        {ExtensionBitLtep, "ltep"},
        {ExtensionBitAzureusExtensionNegotiation2, "azen2"},
        {ExtensionBitAzureusExtensionNegotiation1, "azen1"},
-       {ExtensionBitV2, "v2"},
+       {ExtensionBitV2Upgrade, "v2"},
        {ExtensionBitFast, "fast"},
        {ExtensionBitDht, "dht"},
 }
diff --git a/peer_protocol/reserved_test.go b/peer_protocol/reserved_test.go
new file mode 100644 (file)
index 0000000..8ee3a72
--- /dev/null
@@ -0,0 +1,13 @@
+package peer_protocol
+
+import (
+       qt "github.com/frankban/quicktest"
+       "testing"
+)
+
+func TestV2BitLocation(t *testing.T) {
+       var bits PeerExtensionBits
+       bits.SetBit(ExtensionBitV2Upgrade, true)
+       c := qt.New(t)
+       c.Assert(bits[7], qt.Equals, byte(0x10))
+}
diff --git a/testdata/bittorrent-v2-hybrid-test.torrent b/testdata/bittorrent-v2-hybrid-test.torrent
new file mode 100644 (file)
index 0000000..9a5c876
Binary files /dev/null and b/testdata/bittorrent-v2-hybrid-test.torrent differ
diff --git a/testdata/bittorrent-v2-test.torrent b/testdata/bittorrent-v2-test.torrent
new file mode 100644 (file)
index 0000000..8ad4c7e
Binary files /dev/null and b/testdata/bittorrent-v2-test.torrent differ
index 0763b01e0e8c4243e186407a22019b5620ba3f67..c90f7451e45d443d4889904a450c3552bf166cbf 100644 (file)
@@ -2,6 +2,7 @@ package infohash
 
 import (
        "crypto/sha1"
+       "crypto/sha256"
        "encoding"
        "encoding/hex"
        "fmt"
@@ -78,3 +79,10 @@ func HashBytes(b []byte) (ret T) {
        copy(ret[:], hasher.Sum(nil))
        return
 }
+
+func HashBytesV2(b []byte) (ret T) {
+       hasher := sha256.New()
+       hasher.Write(b)
+       copy(ret[:], hasher.Sum(nil))
+       return
+}