return slice.Indices
}
-func (t *Torrent) offsetRequest(off int64) (req Request, ok bool) {
- req.Index = peer_protocol.Integer(off / t.MetaInfo.PieceLength)
- if req.Index < 0 || int(req.Index) >= len(t.Pieces) {
- return
- }
- off %= t.MetaInfo.PieceLength
- pieceLeft := t.PieceLength(req.Index) - peer_protocol.Integer(off)
- if pieceLeft <= 0 {
+// Return the request that would include the given offset into the torrent data.
+func torrentOffsetRequest(torrentLength, pieceSize, chunkSize, offset int64) (
+ r Request, ok bool) {
+ if offset < 0 || offset >= torrentLength {
return
}
- req.Begin = chunkSize * (peer_protocol.Integer(off) / chunkSize)
- req.Length = chunkSize
- if req.Length > pieceLeft {
- req.Length = pieceLeft
+ r.Index = peer_protocol.Integer(offset / pieceSize)
+ r.Begin = peer_protocol.Integer(offset % pieceSize / chunkSize * chunkSize)
+ left := torrentLength - int64(r.Index)*pieceSize - int64(r.Begin)
+ if chunkSize < left {
+ r.Length = peer_protocol.Integer(chunkSize)
+ } else {
+ r.Length = peer_protocol.Integer(left)
}
ok = true
return
}
+// Return the request that would include the given offset into the torrent data.
+func (t *Torrent) offsetRequest(off int64) (req Request, ok bool) {
+ return torrentOffsetRequest(t.Length(), t.MetaInfo.PieceLength, chunkSize, off)
+}
+
func (t *Torrent) WriteChunk(piece int, begin int64, data []byte) (err error) {
_, err = t.Data.WriteAt(data, int64(piece)*t.MetaInfo.PieceLength+begin)
return
--- /dev/null
+package torrent
+
+import (
+ "bitbucket.org/anacrolix/go.torrent/peer_protocol"
+ "testing"
+)
+
+func r(i, b, l peer_protocol.Integer) Request {
+ return Request{i, ChunkSpec{b, l}}
+}
+
+// Check the given Request is correct for various torrent offsets.
+func TestTorrentRequest(t *testing.T) {
+ const s = 472183431 // Length of torrent.
+ for _, _case := range []struct {
+ off int64 // An offset into the torrent.
+ req Request // The expected Request. The zero value means !ok.
+ }{
+ // Invalid offset.
+ {-1, Request{}},
+ {0, r(0, 0, 16384)},
+ // One before the end of a piece.
+ {1<<18 - 1, r(0, 1<<18-16384, 16384)},
+ // Offset beyond torrent length.
+ {472 * 1 << 20, Request{}},
+ // One before the end of the torrent. Complicates the chunk length.
+ {s - 1, r((s-1)/(1<<18), (s-1)%(1<<18)/(16384)*(16384), 12935)},
+ {1, r(0, 0, 16384)},
+ // One before end of chunk.
+ {16383, r(0, 0, 16384)},
+ // Second chunk.
+ {16384, r(0, 16384, 16384)},
+ } {
+ req, ok := torrentOffsetRequest(472183431, 1<<18, 16384, _case.off)
+ if (_case.req == Request{}) == ok {
+ t.Fatalf("expected %v, got %v", _case.req, req)
+ }
+ if req != _case.req {
+ t.Fatalf("expected %v, got %v", _case.req, req)
+ }
+ }
+}