From: Matt Joiner Date: Fri, 1 Mar 2024 12:40:05 +0000 (+1100) Subject: Misc improvements X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=38c4ce1b1d345382d7812a9a4aab3e5c55e5f44e;p=btrtrc.git Misc improvements --- diff --git a/cmd/torrent2/main.go b/cmd/torrent2/main.go index 0d57f013..6017464f 100644 --- a/cmd/torrent2/main.go +++ b/cmd/torrent2/main.go @@ -4,6 +4,7 @@ package main import ( + "fmt" "os" "github.com/anacrolix/torrent/metainfo" @@ -39,6 +40,26 @@ func main() { err = metainfo.ValidatePieceLayers(mi.PieceLayers, &info.FileTree, info.PieceLength) assertOk(err) }, + "pprint": func() { + mi, err := metainfo.LoadFromFile(args[2]) + assertOk(err) + info, err := mi.UnmarshalInfo() + assertOk(err) + files := info.UpvertedFiles() + pieceIndex := 0 + for _, f := range files { + numPieces := int((f.Length + info.PieceLength - 1) / info.PieceLength) + endIndex := pieceIndex + numPieces + fmt.Printf( + "%x: %q: pieces (%v-%v)\n", + f.PiecesRoot.Unwrap(), + f.BestPath(), + pieceIndex, + endIndex-1, + ) + pieceIndex = endIndex + } + }, }[args[1]]() }, }[args[0]]() diff --git a/merkle/hash.go b/merkle/hash.go index 1a8f67a9..5984547a 100644 --- a/merkle/hash.go +++ b/merkle/hash.go @@ -3,12 +3,14 @@ package merkle import ( "crypto/sha256" "hash" + "unsafe" ) func NewHash() *Hash { - return &Hash{ + h := &Hash{ nextBlock: sha256.New(), } + return h } type Hash struct { @@ -41,7 +43,9 @@ func (h *Hash) Write(p []byte) (n int, err error) { } func (h *Hash) nextBlockSum() (sum [32]byte) { - h.nextBlock.Sum(sum[:0]) + if unsafe.SliceData(h.nextBlock.Sum(sum[:0])) != unsafe.SliceData(sum[:]) { + panic("go sux") + } return } @@ -57,6 +61,7 @@ func (h *Hash) Sum(b []byte) []byte { func (h *Hash) Reset() { h.blocks = h.blocks[:0] h.nextBlock.Reset() + h.written = 0 } func (h *Hash) Size() int { diff --git a/metainfo/file-tree.go b/metainfo/file-tree.go index bfb7229e..0d7e1caf 100644 --- a/metainfo/file-tree.go +++ b/metainfo/file-tree.go @@ -64,23 +64,35 @@ func (ft *FileTree) orderedKeys() []string { return keys } -func (ft *FileTree) UpvertedFiles(path []string, out func(fi FileInfo)) { +func (ft *FileTree) upvertedFiles(pieceLength int64, out func(fi FileInfo)) { + var offset int64 + ft.upvertedFilesInner(pieceLength, nil, &offset, out) +} + +func (ft *FileTree) upvertedFilesInner( + pieceLength int64, + path []string, + offset *int64, + out func(fi FileInfo), +) { if ft.IsDir() { for _, key := range ft.orderedKeys() { if key == FileTreePropertiesKey { continue } sub := g.MapMustGet(ft.Dir, key) - sub.UpvertedFiles(append(path, key), out) + sub.upvertedFilesInner(pieceLength, append(path, key), offset, out) } } else { out(FileInfo{ Length: ft.File.Length, Path: append([]string(nil), path...), // BEP 52 requires paths be UTF-8 if possible. - PathUtf8: append([]string(nil), path...), - PiecesRoot: ft.PiecesRootAsByteArray(), + PathUtf8: append([]string(nil), path...), + PiecesRoot: ft.PiecesRootAsByteArray(), + TorrentOffset: *offset, }) + *offset += (ft.File.Length + pieceLength - 1) / pieceLength * pieceLength } } diff --git a/metainfo/fileinfo.go b/metainfo/fileinfo.go index 66ee2da8..25c26252 100644 --- a/metainfo/fileinfo.go +++ b/metainfo/fileinfo.go @@ -18,7 +18,8 @@ type FileInfo struct { // BEP 52. This isn't encoded in a v1 FileInfo, but is exposed here for APIs that expect to deal // v1 files. - PiecesRoot g.Option[[32]byte] `bencode:"-"` + PiecesRoot g.Option[[32]byte] `bencode:"-"` + TorrentOffset int64 `bencode:"-"` } func (fi *FileInfo) DisplayPath(info *Info) string { diff --git a/metainfo/info.go b/metainfo/info.go index d1b54d44..8b8749c7 100644 --- a/metainfo/info.go +++ b/metainfo/info.go @@ -155,7 +155,7 @@ func (info *Info) IsDir() bool { // single and multi-file torrent infos. func (info *Info) UpvertedFiles() (files []FileInfo) { if info.HasV2() { - info.FileTree.UpvertedFiles(nil, func(fi FileInfo) { + info.FileTree.upvertedFiles(info.PieceLength, func(fi FileInfo) { files = append(files, fi) }) return diff --git a/metainfo/piece.go b/metainfo/piece.go index c7377f5d..4972e529 100644 --- a/metainfo/piece.go +++ b/metainfo/piece.go @@ -13,7 +13,7 @@ func (p Piece) Length() int64 { pieceLength := p.Info.PieceLength lastFileEnd := int64(0) done := false - p.Info.FileTree.UpvertedFiles(nil, func(fi FileInfo) { + p.Info.FileTree.upvertedFiles(pieceLength, func(fi FileInfo) { if done { return } diff --git a/segments/segments.go b/segments/segments.go index 90e77ce0..38700425 100644 --- a/segments/segments.go +++ b/segments/segments.go @@ -4,16 +4,6 @@ type Int = int64 type Length = Int -func min(i Int, rest ...Int) Int { - ret := i - for _, i := range rest { - if i < ret { - ret = i - } - } - return ret -} - type Extent struct { Start, Length Int } @@ -23,10 +13,12 @@ func (e Extent) End() Int { } type ( - Callback = func(int, Extent) bool + Callback = func(segmentIndex int, segmentBounds Extent) bool LengthIter = func() (Length, bool) ) +// Returns true if callback returns false early, or all segments in the haystack for the needle are +// found. func Scan(haystack LengthIter, needle Extent, callback Callback) bool { i := 0 for needle.Length != 0 { diff --git a/spec.go b/spec.go index 49a1104e..f54b325b 100644 --- a/spec.go +++ b/spec.go @@ -71,13 +71,13 @@ func TorrentSpecFromMetaInfoErr(mi *metainfo.MetaInfo) (*TorrentSpec, error) { if err != nil { err = fmt.Errorf("unmarshalling info: %w", err) } - v1Ih := mi.HashInfoBytes() + var v1Ih metainfo.Hash + if info.HasV1() { + v1Ih = mi.HashInfoBytes() + } var v2Infohash g.Option[infohash_v2.T] if info.HasV2() { v2Infohash.Set(infohash_v2.HashBytes(mi.InfoBytes)) - if !info.HasV1() { - v1Ih = *v2Infohash.Value.ToShort() - } } return &TorrentSpec{ diff --git a/torrent.go b/torrent.go index e7b579b3..64e80660 100644 --- a/torrent.go +++ b/torrent.go @@ -2489,11 +2489,15 @@ func (t *Torrent) dropBannedPeers() { func (t *Torrent) pieceHasher(index pieceIndex) { p := t.piece(index) + // Do we really need to spell out that it's a copy error? If it's a failure to hash the hash + // will just be wrong. correct, failedPeers, copyErr := t.hashPiece(index) switch copyErr { case nil, io.EOF: default: - log.Fmsg("piece %v (%s) hash failure copy error: %v", p, p.hash.HexString(), copyErr).Log(t.logger) + t.logger.Levelf( + log.Warning, + "error hashing piece %v: %v", index, copyErr) } t.storageLock.RUnlock() t.cl.lock()