metainfo.InfoEx.Hash becomes a function, UpdateBytes is added, and Bytes used in marshalling
Fixes #80.
This commit is contained in:
parent
533f01147d
commit
2d160b0419
|
@ -1465,7 +1465,7 @@ func (cl *Client) saveTorrentFile(t *Torrent) error {
|
|||
// able to save the torrent, but not load it again to check it.
|
||||
return nil
|
||||
}
|
||||
if !bytes.Equal(mi.Info.Hash.Bytes(), t.infoHash[:]) {
|
||||
if mi.Info.Hash() != t.infoHash {
|
||||
log.Fatalf("%x != %x", mi.Info.Hash, t.infoHash[:])
|
||||
}
|
||||
return nil
|
||||
|
@ -1570,7 +1570,7 @@ func (cl *Client) torrentCacheMetaInfo(ih metainfo.Hash) (mi *metainfo.MetaInfo,
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(mi.Info.Hash.Bytes(), ih[:]) {
|
||||
if mi.Info.Hash() != ih {
|
||||
err = fmt.Errorf("cached torrent has wrong infohash: %x != %x", mi.Info.Hash, ih[:])
|
||||
return
|
||||
}
|
||||
|
@ -1610,15 +1610,13 @@ func TorrentSpecFromMetaInfo(mi *metainfo.MetaInfo) (spec *TorrentSpec) {
|
|||
Trackers: mi.AnnounceList,
|
||||
Info: &mi.Info,
|
||||
DisplayName: mi.Info.Name,
|
||||
InfoHash: mi.Info.Hash(),
|
||||
}
|
||||
|
||||
if len(spec.Trackers) == 0 {
|
||||
spec.Trackers = [][]string{[]string{mi.Announce}}
|
||||
} else {
|
||||
spec.Trackers[0] = append(spec.Trackers[0], mi.Announce)
|
||||
}
|
||||
|
||||
missinggo.CopyExact(&spec.InfoHash, mi.Info.Hash)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -86,10 +86,7 @@ func TestPieceHashSize(t *testing.T) {
|
|||
func TestTorrentInitialState(t *testing.T) {
|
||||
dir, mi := testutil.GreetingTestTorrent()
|
||||
defer os.RemoveAll(dir)
|
||||
tor := newTorrent(func() (ih metainfo.Hash) {
|
||||
missinggo.CopyExact(ih[:], mi.Info.Hash)
|
||||
return
|
||||
}())
|
||||
tor := newTorrent(mi.Info.Hash())
|
||||
tor.chunkSize = 2
|
||||
tor.storageOpener = storage.NewFile(dir)
|
||||
// Needed to lock for asynchronous piece verification.
|
||||
|
@ -637,9 +634,9 @@ func TestAddTorrentSpecMerging(t *testing.T) {
|
|||
defer cl.Close()
|
||||
dir, mi := testutil.GreetingTestTorrent()
|
||||
defer os.RemoveAll(dir)
|
||||
var ts TorrentSpec
|
||||
missinggo.CopyExact(&ts.InfoHash, mi.Info.Hash)
|
||||
tt, new, err := cl.AddTorrentSpec(&ts)
|
||||
tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
|
||||
InfoHash: mi.Info.Hash(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.True(t, new)
|
||||
require.Nil(t, tt.Info())
|
||||
|
@ -664,17 +661,16 @@ func TestAddTorrentMetainfoInCache(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.True(t, new)
|
||||
require.NotNil(t, tt.Info())
|
||||
_, err = os.Stat(filepath.Join(cfg.ConfigDir, "torrents", fmt.Sprintf("%x.torrent", mi.Info.Hash.Bytes())))
|
||||
_, err = os.Stat(filepath.Join(cfg.ConfigDir, "torrents", fmt.Sprintf("%x.torrent", mi.Info.Hash())))
|
||||
require.NoError(t, err)
|
||||
// Contains only the infohash.
|
||||
var ts TorrentSpec
|
||||
missinggo.CopyExact(&ts.InfoHash, mi.Info.Hash)
|
||||
_, ok := cl.Torrent(ts.InfoHash)
|
||||
_, ok := cl.Torrent(mi.Info.Hash())
|
||||
require.True(t, ok)
|
||||
tt.Drop()
|
||||
_, ok = cl.Torrent(ts.InfoHash)
|
||||
_, ok = cl.Torrent(mi.Info.Hash())
|
||||
require.False(t, ok)
|
||||
tt, new, err = cl.AddTorrentSpec(&ts)
|
||||
tt, new, err = cl.AddTorrentSpec(&TorrentSpec{
|
||||
InfoHash: mi.Info.Hash(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.True(t, new)
|
||||
// Obtained from the metainfo cache.
|
||||
|
@ -686,9 +682,9 @@ func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
|
|||
os.RemoveAll(dir)
|
||||
cl, _ := NewClient(&TestingConfig)
|
||||
defer cl.Close()
|
||||
var ts TorrentSpec
|
||||
missinggo.CopyExact(&ts.InfoHash, mi.Info.Hash)
|
||||
tt, _, _ := cl.AddTorrentSpec(&ts)
|
||||
tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
|
||||
InfoHash: mi.Info.Hash(),
|
||||
})
|
||||
tt.Drop()
|
||||
assert.EqualValues(t, 0, len(cl.Torrents()))
|
||||
select {
|
||||
|
|
|
@ -38,7 +38,7 @@ func main() {
|
|||
"Name": info.Name,
|
||||
"NumPieces": info.NumPieces(),
|
||||
"PieceLength": info.PieceLength,
|
||||
"InfoHash": metainfo.Info.Hash.HexString(),
|
||||
"InfoHash": metainfo.Info.Hash().HexString(),
|
||||
"NumFiles": len(info.UpvertedFiles()),
|
||||
"TotalLength": info.TotalLength(),
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ func TestDownloadOnDemand(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
defer seeder.Close()
|
||||
testutil.ExportStatusWriter(seeder, "s")
|
||||
_, err = seeder.AddMagnet(fmt.Sprintf("magnet:?xt=urn:btih:%s", layout.Metainfo.Info.Hash.HexString()))
|
||||
_, err = seeder.AddMagnet(fmt.Sprintf("magnet:?xt=urn:btih:%s", layout.Metainfo.Info.Hash().HexString()))
|
||||
require.NoError(t, err)
|
||||
leecher, err := torrent.NewClient(&torrent.Config{
|
||||
DisableTrackers: true,
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -17,7 +16,6 @@ import (
|
|||
|
||||
"github.com/anacrolix/missinggo"
|
||||
|
||||
"github.com/anacrolix/torrent/bencode"
|
||||
"github.com/anacrolix/torrent/metainfo"
|
||||
)
|
||||
|
||||
|
@ -44,10 +42,7 @@ func GreetingMetaInfo() (mi *metainfo.MetaInfo) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
mi.Info.Bytes, _ = bencode.Marshal(&mi.Info.Info)
|
||||
h := sha1.New()
|
||||
h.Write(mi.Info.Bytes)
|
||||
missinggo.CopyExact(&mi.Info.Hash, h.Sum(nil))
|
||||
mi.Info.UpdateBytes()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package metainfo
|
||||
|
||||
import "github.com/anacrolix/torrent/bencode"
|
||||
|
||||
// A wrapper around Info that exposes the Bytes directly, in case marshalling
|
||||
// and unmarshalling Info doesn't produce the same bytes.
|
||||
type InfoEx struct {
|
||||
Info
|
||||
// Set when unmarshalling, and used when marshalling. Call .UpdateBytes to
|
||||
// set it by bencoding Info.
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
var (
|
||||
_ bencode.Marshaler = &InfoEx{}
|
||||
_ bencode.Unmarshaler = &InfoEx{}
|
||||
)
|
||||
|
||||
// Marshals .Info, and sets .Bytes with the result.
|
||||
func (ie *InfoEx) UpdateBytes() {
|
||||
var err error
|
||||
ie.Bytes, err = bencode.Marshal(&ie.Info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the SHA1 hash of .Bytes.
|
||||
func (ie *InfoEx) Hash() Hash {
|
||||
return HashBytes(ie.Bytes)
|
||||
}
|
||||
|
||||
func (ie *InfoEx) UnmarshalBencode(data []byte) error {
|
||||
ie.Bytes = append([]byte(nil), data...)
|
||||
return bencode.Unmarshal(data, &ie.Info)
|
||||
}
|
||||
|
||||
func (ie *InfoEx) MarshalBencode() ([]byte, error) {
|
||||
if ie.Bytes == nil {
|
||||
ie.UpdateBytes()
|
||||
}
|
||||
return ie.Bytes, nil
|
||||
}
|
|
@ -11,8 +11,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/missinggo"
|
||||
|
||||
"github.com/anacrolix/torrent/bencode"
|
||||
)
|
||||
|
||||
|
@ -183,34 +181,6 @@ func (info *Info) UpvertedFiles() []FileInfo {
|
|||
return info.Files
|
||||
}
|
||||
|
||||
// The info dictionary with its hash and raw bytes exposed, in case
|
||||
// remarshalling Info produces a different value.
|
||||
type InfoEx struct {
|
||||
Info
|
||||
Hash Hash // Only set when unmarshalling or UpdateHash.
|
||||
Bytes []byte // Only set when unmarshalling or UpdateBytes.
|
||||
}
|
||||
|
||||
var (
|
||||
_ bencode.Marshaler = InfoEx{}
|
||||
_ bencode.Unmarshaler = &InfoEx{}
|
||||
)
|
||||
|
||||
func (ie *InfoEx) UnmarshalBencode(data []byte) error {
|
||||
ie.Bytes = append([]byte(nil), data...)
|
||||
h := sha1.New()
|
||||
_, err := h.Write(ie.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
missinggo.CopyExact(&ie.Hash, h.Sum(nil))
|
||||
return bencode.Unmarshal(data, &ie.Info)
|
||||
}
|
||||
|
||||
func (ie InfoEx) MarshalBencode() ([]byte, error) {
|
||||
return bencode.Marshal(&ie.Info)
|
||||
}
|
||||
|
||||
type MetaInfo struct {
|
||||
Info InfoEx `bencode:"info"`
|
||||
Announce string `bencode:"announce,omitempty"`
|
||||
|
@ -236,7 +206,7 @@ func (mi *MetaInfo) SetDefaults() {
|
|||
mi.Info.PieceLength = 256 * 1024
|
||||
}
|
||||
|
||||
// Magnetize creates a Magnet from a MetaInfo.
|
||||
// Creates a Magnet from a MetaInfo.
|
||||
func (mi *MetaInfo) Magnet() (m Magnet) {
|
||||
for _, tier := range mi.AnnounceList {
|
||||
for _, tracker := range tier {
|
||||
|
@ -244,6 +214,6 @@ func (mi *MetaInfo) Magnet() (m Magnet) {
|
|||
}
|
||||
}
|
||||
m.DisplayName = mi.Info.Name
|
||||
m.InfoHash = mi.Info.Hash
|
||||
m.InfoHash = mi.Info.Hash()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -15,9 +15,7 @@ import (
|
|||
|
||||
func testFile(t *testing.T, filename string) {
|
||||
mi, err := LoadFromFile(filename)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if len(mi.Info.Files) == 1 {
|
||||
t.Logf("Single file: %s (length: %d)\n", mi.Info.Name, mi.Info.Files[0].Length)
|
||||
|
@ -33,13 +31,10 @@ func testFile(t *testing.T, filename string) {
|
|||
t.Logf("Tracker: %s\n", tracker)
|
||||
}
|
||||
}
|
||||
// for _, url := range mi.WebSeedURLs {
|
||||
// t.Logf("URL: %s\n", url)
|
||||
// }
|
||||
|
||||
b, err := bencode.Marshal(mi.Info)
|
||||
b, err := bencode.Marshal(&mi.Info.Info)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, b, mi.Info.Bytes)
|
||||
assert.EqualValues(t, string(b), string(mi.Info.Bytes))
|
||||
}
|
||||
|
||||
func TestFile(t *testing.T) {
|
||||
|
|
|
@ -41,15 +41,15 @@ func TestNodesListPairsBEP5(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func testMarshalMetainfo(t *testing.T, expected string, mi MetaInfo) {
|
||||
func testMarshalMetainfo(t *testing.T, expected string, mi *MetaInfo) {
|
||||
b, err := bencode.Marshal(mi)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, expected, string(b))
|
||||
}
|
||||
|
||||
func TestMarshalMetainfoNodes(t *testing.T) {
|
||||
testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:piecesleee", MetaInfo{})
|
||||
testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:pieceslee5:nodesl12:1.2.3.4:555514:not a hostportee", MetaInfo{
|
||||
testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:piecesleee", &MetaInfo{})
|
||||
testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:pieceslee5:nodesl12:1.2.3.4:555514:not a hostportee", &MetaInfo{
|
||||
Nodes: []Node{"1.2.3.4:5555", "not a hostport"},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -225,7 +225,6 @@ func (t *Torrent) setMetadata(md *metainfo.Info, infoBytes []byte) (err error) {
|
|||
t.info = &metainfo.InfoEx{
|
||||
Info: *md,
|
||||
Bytes: infoBytes,
|
||||
Hash: t.infoHash,
|
||||
}
|
||||
t.storage, err = t.storageOpener.OpenTorrent(t.info)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue