From: Matt Joiner Date: Thu, 5 May 2016 12:40:38 +0000 (+1000) Subject: metainfo.InfoEx.Hash becomes a function, UpdateBytes is added, and Bytes used in... X-Git-Tag: v1.0.0~751 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=2d160b041961ab7b65d332b270224b2ff99cd84e;p=btrtrc.git metainfo.InfoEx.Hash becomes a function, UpdateBytes is added, and Bytes used in marshalling Fixes #80. --- diff --git a/client.go b/client.go index 2c4655ab..8bccd78f 100644 --- a/client.go +++ b/client.go @@ -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 } diff --git a/client_test.go b/client_test.go index 0e6e1612..59c79f2e 100644 --- a/client_test.go +++ b/client_test.go @@ -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 { diff --git a/cmd/torrent-metainfo-pprint/main.go b/cmd/torrent-metainfo-pprint/main.go index dbd7ea75..96fba9a8 100644 --- a/cmd/torrent-metainfo-pprint/main.go +++ b/cmd/torrent-metainfo-pprint/main.go @@ -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(), } diff --git a/fs/torrentfs_test.go b/fs/torrentfs_test.go index 688c7ac6..96c8bf2e 100644 --- a/fs/torrentfs_test.go +++ b/fs/torrentfs_test.go @@ -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, diff --git a/internal/testutil/testutil.go b/internal/testutil/testutil.go index e9d21039..1d296396 100644 --- a/internal/testutil/testutil.go +++ b/internal/testutil/testutil.go @@ -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 } diff --git a/metainfo/infoex.go b/metainfo/infoex.go new file mode 100644 index 00000000..95cf4c9b --- /dev/null +++ b/metainfo/infoex.go @@ -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 +} diff --git a/metainfo/metainfo.go b/metainfo/metainfo.go index ea4b2b89..8ecd7c5d 100644 --- a/metainfo/metainfo.go +++ b/metainfo/metainfo.go @@ -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 } diff --git a/metainfo/metainfo_test.go b/metainfo/metainfo_test.go index 2f13c520..b2845fa9 100644 --- a/metainfo/metainfo_test.go +++ b/metainfo/metainfo_test.go @@ -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) { diff --git a/metainfo/nodes_test.go b/metainfo/nodes_test.go index ca769b16..2b8768a3 100644 --- a/metainfo/nodes_test.go +++ b/metainfo/nodes_test.go @@ -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"}, }) } diff --git a/torrent.go b/torrent.go index 3680fc3d..d89f25c6 100644 --- a/torrent.go +++ b/torrent.go @@ -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 {