From 5c1492bffe88d867272ee3a901fae6f9073ab86e Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Thu, 21 Aug 2014 18:24:19 +1000 Subject: [PATCH] Add CopyExact util function --- client.go | 4 +++- client_test.go | 11 ++++++++--- cmd/scrape/main.go | 10 ++++++---- cmd/torrent/main.go | 2 +- misc.go | 20 ++++---------------- torrent.go | 4 ++-- util/copy.go | 26 +++++++++++++++++++++++++ util/copy_test.go | 46 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 util/copy.go create mode 100644 util/copy_test.go diff --git a/client.go b/client.go index 68d89965..299feacf 100644 --- a/client.go +++ b/client.go @@ -996,7 +996,9 @@ func (me *Client) addTorrent(t *torrent) (err error) { // Adds the torrent to the client. func (me *Client) AddTorrent(metaInfo *metainfo.MetaInfo) (err error) { - t, err := newTorrent(BytesInfoHash(metaInfo.Info.Hash), metaInfo.AnnounceList) + var ih InfoHash + CopyExact(&ih, metaInfo.Info.Hash) + t, err := newTorrent(ih, metaInfo.AnnounceList) if err != nil { return } diff --git a/client_test.go b/client_test.go index 1d1e9c30..6287b65c 100644 --- a/client_test.go +++ b/client_test.go @@ -1,10 +1,12 @@ package torrent import ( - "bitbucket.org/anacrolix/go.torrent/testutil" - "github.com/anacrolix/libtorgo/bencode" "os" "testing" + + "bitbucket.org/anacrolix/go.torrent/testutil" + "bitbucket.org/anacrolix/go.torrent/util" + "github.com/anacrolix/libtorgo/bencode" ) func TestClientDefault(t *testing.T) { @@ -36,7 +38,10 @@ func TestPieceHashSize(t *testing.T) { func TestTorrentInitialState(t *testing.T) { dir, mi := testutil.GreetingTestTorrent() defer os.RemoveAll(dir) - tor, err := newTorrent(BytesInfoHash(mi.Info.Hash), nil) + tor, err := newTorrent(func() (ih InfoHash) { + util.CopyExact(ih[:], mi.Info.Hash) + return + }(), nil) if err != nil { t.Fatal(err) } diff --git a/cmd/scrape/main.go b/cmd/scrape/main.go index 4b059684..826aacf7 100644 --- a/cmd/scrape/main.go +++ b/cmd/scrape/main.go @@ -8,6 +8,7 @@ import ( "bitbucket.org/anacrolix/go.torrent" "bitbucket.org/anacrolix/go.torrent/tracker" _ "bitbucket.org/anacrolix/go.torrent/tracker/udp" + "bitbucket.org/anacrolix/go.torrent/util" metainfo "github.com/nsf/libtorgo/torrent" ) @@ -27,10 +28,11 @@ func main() { if err != nil { log.Fatal(err) } - resp, err := tr.Announce(&tracker.AnnounceRequest{ - NumWant: -1, - InfoHash: torrent.BytesInfoHash(mi.InfoHash), - }) + ar := tracker.AnnounceRequest{ + NumWant: -1, + } + util.CopyExact(ar.InfoHash, mi.InfoHash) + resp, err := tr.Announce(&ar) if err != nil { log.Fatal(err) } diff --git a/cmd/torrent/main.go b/cmd/torrent/main.go index 8442f5f7..20443b7b 100644 --- a/cmd/torrent/main.go +++ b/cmd/torrent/main.go @@ -73,7 +73,7 @@ func main() { if err != nil { log.Fatal(err) } - ih = torrent.BytesInfoHash(metaInfo.Info.Hash) + util.CopyExact(&ih, metaInfo.Info.Hash) } client.PrioritizeDataRegion(ih, 0, 999999999) err := client.AddPeers(ih, func() []torrent.Peer { diff --git a/misc.go b/misc.go index ab9cd9d2..b2232f1d 100644 --- a/misc.go +++ b/misc.go @@ -21,22 +21,10 @@ const ( dialTimeout = time.Second * 15 ) -type InfoHash [20]byte - -type pieceSum [20]byte - -func copyHashSum(dst, src []byte) { - if len(dst) != len(src) || copy(dst, src) != len(dst) { - panic("hash sum sizes differ") - } -} - -func BytesInfoHash(b []byte) (ih InfoHash) { - if len(b) != len(ih) || copy(ih[:], b) != len(ih) { - panic("bad infohash bytes") - } - return -} +type ( + InfoHash [20]byte + pieceSum [20]byte +) type piece struct { Hash pieceSum diff --git a/torrent.go b/torrent.go index c6f26716..dd99fb0a 100644 --- a/torrent.go +++ b/torrent.go @@ -117,7 +117,7 @@ func (t *torrent) setMetadata(md metainfo.Info, dataDir string, infoBytes []byte }) for index, hash := range infoPieceHashes(&md) { piece := &torrentPiece{} - copyHashSum(piece.Hash[:], []byte(hash)) + util.CopyExact(piece.Hash[:], hash) t.Pieces = append(t.Pieces, piece) piece.bytesLeftElement = t.PiecesByBytesLeft.Insert(index) t.pendAllChunkSpecs(pp.Integer(index)) @@ -392,7 +392,7 @@ func (t *torrent) HashPiece(piece pp.Integer) (ps pieceSum) { // log.Print(t.Info) panic(fmt.Sprintf("hashed wrong number of bytes: expected %d; did %d; piece %d", t.PieceLength(piece), n, piece)) } - copyHashSum(ps[:], hash.Sum(nil)) + util.CopyExact(ps[:], hash.Sum(nil)) return } func (t *torrent) haveAllPieces() bool { diff --git a/util/copy.go b/util/copy.go new file mode 100644 index 00000000..c7d64cc2 --- /dev/null +++ b/util/copy.go @@ -0,0 +1,26 @@ +package util + +import ( + "fmt" + "reflect" +) + +func CopyExact(dest interface{}, src interface{}) { + dV := reflect.ValueOf(dest) + sV := reflect.ValueOf(src) + if dV.Kind() == reflect.Ptr { + dV = dV.Elem() + } + if dV.Kind() == reflect.Array && !dV.CanAddr() { + panic(fmt.Sprintf("dest not addressable: %T", dest)) + } + if sV.Kind() == reflect.String { + sV = sV.Convert(dV.Type()) + } + if dV.Len() != sV.Len() { + panic(fmt.Sprintf("dest len (%d) != src len (%d)", dV.Len(), sV.Len())) + } + if dV.Len() != reflect.Copy(dV, sV) { + panic("dammit") + } +} diff --git a/util/copy_test.go b/util/copy_test.go new file mode 100644 index 00000000..450e5c4b --- /dev/null +++ b/util/copy_test.go @@ -0,0 +1,46 @@ +package util + +import ( + "bytes" + "testing" +) + +func TestCopyToArray(t *testing.T) { + var arr [3]byte + bb := []byte{1, 2, 3} + CopyExact(&arr, bb) + if !bytes.Equal(arr[:], bb) { + t.FailNow() + } +} + +func TestCopyToSlicedArray(t *testing.T) { + var arr [5]byte + CopyExact(arr[:], "hello") + if !bytes.Equal(arr[:], []byte("hello")) { + t.FailNow() + } +} + +func TestCopyDestNotAddr(t *testing.T) { + defer func() { + r := recover() + if r == nil { + t.FailNow() + } + t.Log(r) + }() + var arr [3]byte + CopyExact(arr, "nope") +} + +func TestCopyLenMismatch(t *testing.T) { + defer func() { + r := recover() + if r == nil { + t.FailNow() + } + t.Log(r) + }() + CopyExact(make([]byte, 2), "abc") +} -- 2.48.1