]> Sergey Matveev's repositories - btrtrc.git/blob - webseed-peer.go
Handle errors in webseed peers for bad URLs
[btrtrc.git] / webseed-peer.go
1 package torrent
2
3 import (
4         "fmt"
5         "strings"
6
7         "github.com/anacrolix/torrent/common"
8         "github.com/anacrolix/torrent/metainfo"
9         pp "github.com/anacrolix/torrent/peer_protocol"
10         "github.com/anacrolix/torrent/segments"
11         "github.com/anacrolix/torrent/webseed"
12         "github.com/pkg/errors"
13 )
14
15 type webseedPeer struct {
16         client   webseed.Client
17         requests map[request]webseed.Request
18         peer     peer
19 }
20
21 var _ peerImpl = (*webseedPeer)(nil)
22
23 func (ws *webseedPeer) String() string {
24         return fmt.Sprintf("webseed peer for %q", ws.client.Url)
25 }
26
27 func (ws *webseedPeer) onGotInfo(info *metainfo.Info) {
28         ws.client.FileIndex = segments.NewIndex(common.LengthIterFromUpvertedFiles(info.UpvertedFiles()))
29         ws.client.Info = info
30 }
31
32 func (ws *webseedPeer) _postCancel(r request) {
33         ws.cancel(r)
34 }
35
36 func (ws *webseedPeer) writeInterested(interested bool) bool {
37         return true
38 }
39
40 func (ws *webseedPeer) cancel(r request) bool {
41         ws.requests[r].Cancel()
42         return true
43 }
44
45 func (ws *webseedPeer) intoSpec(r request) webseed.RequestSpec {
46         return webseed.RequestSpec{ws.peer.t.requestOffset(r), int64(r.Length)}
47 }
48
49 func (ws *webseedPeer) request(r request) bool {
50         webseedRequest := ws.client.NewRequest(ws.intoSpec(r))
51         ws.requests[r] = webseedRequest
52         go ws.requestResultHandler(r, webseedRequest)
53         return true
54 }
55
56 func (ws *webseedPeer) connectionFlags() string {
57         return "WS"
58 }
59
60 // TODO: This is called when banning peers. Perhaps we want to be able to ban webseeds too.
61 func (ws *webseedPeer) drop() {}
62
63 func (ws *webseedPeer) updateRequests() {
64         ws.peer.doRequestState()
65 }
66
67 func (ws *webseedPeer) _close() {}
68
69 func (ws *webseedPeer) requestResultHandler(r request, webseedRequest webseed.Request) {
70         result := <-webseedRequest.Result
71         ws.peer.t.cl.lock()
72         defer ws.peer.t.cl.unlock()
73         if result.Err != nil {
74                 ws.peer.logger.Printf("request %v rejected: %v", r, result.Err)
75                 if strings.Contains(errors.Cause(result.Err).Error(), "unsupported protocol scheme") {
76                         ws.peer.close()
77                 } else {
78                         ws.peer.remoteRejectedRequest(r)
79                 }
80         } else {
81                 err := ws.peer.receiveChunk(&pp.Message{
82                         Type:  pp.Piece,
83                         Index: r.Index,
84                         Begin: r.Begin,
85                         Piece: result.Bytes,
86                 })
87                 if err != nil {
88                         panic(err)
89                 }
90         }
91 }