--- /dev/null
+package metainfo
+
+type FileTree struct {
+ File struct {
+ Length int64 `bencode:"length"`
+ PiecesRoot string `bencode:"pieces root"`
+ }
+ Dir map[string]FileTree
+}
"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
// 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
return Piece{info, pieceIndex(index)}
}
-func (info Info) BestName() string {
+func (info *Info) BestName() string {
if info.NameUtf8 != "" {
return info.NameUtf8
}
"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
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)
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
// 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
{ExtensionBitLtep, "ltep"},
{ExtensionBitAzureusExtensionNegotiation2, "azen2"},
{ExtensionBitAzureusExtensionNegotiation1, "azen1"},
- {ExtensionBitV2, "v2"},
+ {ExtensionBitV2Upgrade, "v2"},
{ExtensionBitFast, "fast"},
{ExtensionBitDht, "dht"},
}
--- /dev/null
+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))
+}
import (
"crypto/sha1"
+ "crypto/sha256"
"encoding"
"encoding/hex"
"fmt"
copy(ret[:], hasher.Sum(nil))
return
}
+
+func HashBytesV2(b []byte) (ret T) {
+ hasher := sha256.New()
+ hasher.Write(b)
+ copy(ret[:], hasher.Sum(nil))
+ return
+}