if t == nil {
return errors.New("no such active torrent")
}
- newPriorities := make([]Request, 0, (len_+chunkSize-1)/chunkSize)
+ newPriorities := make([]request, 0, (len_+chunkSize-1)/chunkSize)
for len_ > 0 {
req, ok := t.offsetRequest(off)
if !ok {
type dataSpec struct {
InfoHash
- Request
+ request
}
type Client struct {
me.peerGotPiece(torrent, conn, int(msg.Index))
case peer_protocol.Request:
if conn.PeerRequests == nil {
- conn.PeerRequests = make(map[Request]struct{}, maxRequests)
+ conn.PeerRequests = make(map[request]struct{}, maxRequests)
}
- request := Request{
+ request := request{
Index: msg.Index,
chunkSpec: chunkSpec{msg.Begin, msg.Length},
}
}
}
case peer_protocol.Piece:
- request_ := Request{msg.Index, chunkSpec{msg.Begin, peer_protocol.Integer(len(msg.Piece))}}
+ request_ := request{msg.Index, chunkSpec{msg.Begin, peer_protocol.Integer(len(msg.Piece))}}
if _, ok := conn.Requests[request_]; !ok {
err = fmt.Errorf("unexpected piece: %s", request_)
break
func (me *Client) replenishConnRequests(torrent *torrent, conn *connection) {
requestHeatMap := torrent.requestHeat()
- addRequest := func(req Request) (again bool) {
+ addRequest := func(req request) (again bool) {
piece := torrent.Pieces[req.Index]
if piece.Hashing {
// We can't be sure we want this.
// First request prioritized chunks.
if torrent.Priorities != nil {
for e := torrent.Priorities.Front(); e != nil; e = e.Next() {
- if !addRequest(e.Value.(Request)) {
+ if !addRequest(e.Value.(request)) {
return
}
}
continue
}
for chunkSpec := range torrent.Pieces[index].PendingChunkSpecs {
- if !addRequest(Request{index, chunkSpec}) {
+ if !addRequest(request{index, chunkSpec}) {
return
}
}
}
func (me *Client) downloadedChunk(torrent *torrent, msg *peer_protocol.Message) (err error) {
- request := Request{msg.Index, chunkSpec{msg.Begin, peer_protocol.Integer(len(msg.Piece))}}
- if _, ok := torrent.Pieces[request.Index].PendingChunkSpecs[request.chunkSpec]; !ok {
- log.Printf("got unnecessary chunk: %s", request)
+ req := request{msg.Index, chunkSpec{msg.Begin, peer_protocol.Integer(len(msg.Piece))}}
+ if _, ok := torrent.Pieces[req.Index].PendingChunkSpecs[req.chunkSpec]; !ok {
+ log.Printf("got unnecessary chunk: %s", req)
return
}
err = torrent.WriteChunk(int(msg.Index), int64(msg.Begin), msg.Piece)
if err != nil {
return
}
- delete(torrent.Pieces[request.Index].PendingChunkSpecs, request.chunkSpec)
- if len(torrent.Pieces[request.Index].PendingChunkSpecs) == 0 {
- me.queuePieceCheck(torrent, request.Index)
+ delete(torrent.Pieces[req.Index].PendingChunkSpecs, req.chunkSpec)
+ if len(torrent.Pieces[req.Index].PendingChunkSpecs) == 0 {
+ me.queuePieceCheck(torrent, req.Index)
}
var next *list.Element
for e := torrent.Priorities.Front(); e != nil; e = next {
next = e.Next()
- if e.Value.(Request) == request {
+ if e.Value.(request) == req {
torrent.Priorities.Remove(e)
}
}
- me.dataReady(dataSpec{torrent.InfoHash, request})
+ me.dataReady(dataSpec{torrent.InfoHash, req})
return
}
if t.Priorities != nil {
for e := t.Priorities.Front(); e != nil; e = next {
next = e.Next()
- if e.Value.(Request).Index == piece {
+ if e.Value.(request).Index == piece {
t.Priorities.Remove(e)
}
}
}
me.dataReady(dataSpec{
t.InfoHash,
- Request{
+ request{
peer_protocol.Integer(piece),
chunkSpec{0, peer_protocol.Integer(t.PieceLength(piece))},
},
// Stuff controlled by the local peer.
Interested bool
Choked bool
- Requests map[Request]struct{}
+ Requests map[request]struct{}
// Stuff controlled by the remote peer.
PeerId [20]byte
PeerInterested bool
PeerChoked bool
- PeerRequests map[Request]struct{}
+ PeerRequests map[request]struct{}
PeerExtensions [8]byte
PeerPieces []bool
}
}
// Returns true if more requests can be sent.
-func (c *connection) Request(chunk Request) bool {
+func (c *connection) Request(chunk request) bool {
if len(c.Requests) >= maxRequests {
return false
}
})
}
if c.Requests == nil {
- c.Requests = make(map[Request]struct{}, maxRequests)
+ c.Requests = make(map[request]struct{}, maxRequests)
}
c.Requests[chunk] = struct{}{}
return true
}
// Returns true if an unsatisfied request was canceled.
-func (c *connection) PeerCancel(r Request) bool {
+func (c *connection) PeerCancel(r request) bool {
if c.PeerRequests == nil {
return false
}
Begin, Length peer_protocol.Integer
}
-type Request struct {
+type request struct {
Index peer_protocol.Integer
chunkSpec
}
-func newRequest(index, begin, length peer_protocol.Integer) Request {
- return Request{index, chunkSpec{begin, length}}
+func newRequest(index, begin, length peer_protocol.Integer) request {
+ return request{index, chunkSpec{begin, length}}
}
type pieceByBytesPendingSlice struct {
// Return the request that would include the given offset into the torrent data.
func torrentOffsetRequest(torrentLength, pieceSize, chunkSize, offset int64) (
- r Request, ok bool) {
+ r request, ok bool) {
if offset < 0 || offset >= torrentLength {
return
}
return
}
-func torrentRequestOffset(torrentLength, pieceSize int64, r Request) (off int64) {
+func torrentRequestOffset(torrentLength, pieceSize int64, r request) (off int64) {
off = int64(r.Index)*pieceSize + int64(r.Begin)
if off < 0 || off >= torrentLength {
panic("invalid request")
return
}
-func (t *torrent) requestOffset(r Request) int64 {
+func (t *torrent) requestOffset(r request) int64 {
return torrentRequestOffset(t.Length(), t.MetaInfo.PieceLength, r)
}
// Return the request that would include the given offset into the torrent data.
-func (t *torrent) offsetRequest(off int64) (req Request, ok bool) {
+func (t *torrent) offsetRequest(off int64) (req request, ok bool) {
return torrentOffsetRequest(t.Length(), t.MetaInfo.PieceLength, chunkSize, off)
}
return
}
-func (t *torrent) requestHeat() (ret map[Request]int) {
- ret = make(map[Request]int)
+func (t *torrent) requestHeat() (ret map[request]int) {
+ ret = make(map[request]int)
for _, conn := range t.Conns {
for req, _ := range conn.Requests {
ret[req]++
"testing"
)
-func r(i, b, l peer_protocol.Integer) Request {
- return Request{i, chunkSpec{b, l}}
+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.
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.
+ req request // The expected Request. The zero value means !ok.
}{
// Invalid offset.
- {-1, Request{}},
+ {-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{}},
+ {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)},
{16384, r(0, 16384, 16384)},
} {
req, ok := torrentOffsetRequest(472183431, 1<<18, 16384, _case.off)
- if (_case.req == Request{}) == ok {
+ if (_case.req == request{}) == ok {
t.Fatalf("expected %v, got %v", _case.req, req)
}
if req != _case.req {