From: Matt Joiner Date: Sun, 25 Feb 2024 06:00:16 +0000 (+1100) Subject: Add BitTorrent v2 fields, consts and reference torrents X-Git-Tag: v1.55.0~14 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=3ad279e85cd0d1b11cbeeca9a9ed69d7d26e976e;p=btrtrc.git Add BitTorrent v2 fields, consts and reference torrents --- diff --git a/metainfo/file-tree.go b/metainfo/file-tree.go new file mode 100644 index 00000000..0bccb153 --- /dev/null +++ b/metainfo/file-tree.go @@ -0,0 +1,9 @@ +package metainfo + +type FileTree struct { + File struct { + Length int64 `bencode:"length"` + PiecesRoot string `bencode:"pieces root"` + } + Dir map[string]FileTree +} diff --git a/metainfo/info.go b/metainfo/info.go index 1ee2704e..5eedfa3b 100644 --- a/metainfo/info.go +++ b/metainfo/info.go @@ -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 } diff --git a/metainfo/metainfo.go b/metainfo/metainfo.go index 93f9103b..9f410989 100644 --- a/metainfo/metainfo.go +++ b/metainfo/metainfo.go @@ -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 diff --git a/peer_protocol/handshake.go b/peer_protocol/handshake.go index a6f648cf..bce28340 100644 --- a/peer_protocol/handshake.go +++ b/peer_protocol/handshake.go @@ -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 index 00000000..8ee3a722 --- /dev/null +++ b/peer_protocol/reserved_test.go @@ -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 index 00000000..9a5c8762 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 index 00000000..8ad4c7ea Binary files /dev/null and b/testdata/bittorrent-v2-test.torrent differ diff --git a/types/infohash/infohash.go b/types/infohash/infohash.go index 0763b01e..c90f7451 100644 --- a/types/infohash/infohash.go +++ b/types/infohash/infohash.go @@ -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 +}