]> Sergey Matveev's repositories - btrtrc.git/commitdiff
metainfo.InfoEx.Hash becomes a function, UpdateBytes is added, and Bytes used in...
authorMatt Joiner <anacrolix@gmail.com>
Thu, 5 May 2016 12:40:38 +0000 (22:40 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 5 May 2016 12:40:38 +0000 (22:40 +1000)
Fixes #80.

client.go
client_test.go
cmd/torrent-metainfo-pprint/main.go
fs/torrentfs_test.go
internal/testutil/testutil.go
metainfo/infoex.go [new file with mode: 0644]
metainfo/metainfo.go
metainfo/metainfo_test.go
metainfo/nodes_test.go
torrent.go

index 2c4655abd01592144e8db570d3faa781af04fe05..8bccd78f8db0b37507782453ddf73025e2939b2d 100644 (file)
--- 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
 }
 
index 0e6e16124515d68b8a6814ff6fe546fa9fa3d11d..59c79f2ed02fd92c7cfe77aad4daf1d492b14f70 100644 (file)
@@ -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 {
index dbd7ea75801282e971a48c8a0296e74c54b9a7cb..96fba9a8f035934859dd4628ccb3935d6a233b2d 100644 (file)
@@ -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(),
                }
index 688c7ac6996de10ed4d0a00dd34d18266f5bd5bc..96c8bf2e90ce05bd7ce0eab6aa743c6a978e3f09 100644 (file)
@@ -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,
index e9d21039dc1af653a9483d22cb94b0580266d0d9..1d2963969e38a0f31e5405526d273e0dec09f270 100644 (file)
@@ -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 (file)
index 0000000..95cf4c9
--- /dev/null
@@ -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
+}
index ea4b2b89c10f9cc0dfe0e96c5fe0c865e825523f..8ecd7c5d7123ab93396b84e725aabe941424b21a 100644 (file)
@@ -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
 }
index 2f13c52093552f74eb74608dbae2c411b4b220fa..b2845fa9d87f6ad11ef8a7d3a7ce66cf1806ef71 100644 (file)
@@ -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) {
index ca769b16ac4980ea53fc61f13e5401f938c60eee..2b8768a32879f3a263cf32e325b4eb91b8c56759 100644 (file)
@@ -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"},
        })
 }
index 3680fc3d1a6bd3f9323b95b0ff36a1faa3de5887..d89f25c6dbbbf75efc1b9fe781609b1e636cb774 100644 (file)
@@ -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 {