]> Sergey Matveev's repositories - btrtrc.git/blob - t.go
Add File.NewReader
[btrtrc.git] / t.go
1 package torrent
2
3 import (
4         "strings"
5
6         "github.com/anacrolix/missinggo/pubsub"
7
8         "github.com/anacrolix/torrent/metainfo"
9 )
10
11 // The torrent's infohash. This is fixed and cannot change. It uniquely
12 // identifies a torrent.
13 func (t *Torrent) InfoHash() metainfo.Hash {
14         return t.infoHash
15 }
16
17 // Returns a channel that is closed when the info (.Info()) for the torrent
18 // has become available.
19 func (t *Torrent) GotInfo() <-chan struct{} {
20         t.cl.mu.Lock()
21         defer t.cl.mu.Unlock()
22         return t.gotMetainfo.C()
23 }
24
25 // Returns the metainfo info dictionary, or nil if it's not yet available.
26 func (t *Torrent) Info() *metainfo.Info {
27         t.cl.mu.Lock()
28         defer t.cl.mu.Unlock()
29         return t.info
30 }
31
32 // Returns a Reader bound to the torrent's data. All read calls block until
33 // the data requested is actually available.
34 func (t *Torrent) NewReader() Reader {
35         r := reader{
36                 mu:        &t.cl.mu,
37                 t:         t,
38                 readahead: 5 * 1024 * 1024,
39         }
40         t.addReader(&r)
41         return &r
42 }
43
44 // Returns the state of pieces of the torrent. They are grouped into runs of
45 // same state. The sum of the state run lengths is the number of pieces
46 // in the torrent.
47 func (t *Torrent) PieceStateRuns() []PieceStateRun {
48         t.cl.mu.Lock()
49         defer t.cl.mu.Unlock()
50         return t.pieceStateRuns()
51 }
52
53 func (t *Torrent) PieceState(piece int) PieceState {
54         t.cl.mu.Lock()
55         defer t.cl.mu.Unlock()
56         return t.pieceState(piece)
57 }
58
59 // The number of pieces in the torrent. This requires that the info has been
60 // obtained first.
61 func (t *Torrent) NumPieces() int {
62         return t.numPieces()
63 }
64
65 // Get missing bytes count for specific piece.
66 func (t *Torrent) PieceBytesMissing(piece int) int64 {
67         t.cl.mu.Lock()
68         defer t.cl.mu.Unlock()
69
70         return int64(t.pieces[piece].bytesLeft())
71 }
72
73 // Drop the torrent from the client, and close it. It's always safe to do
74 // this. No data corruption can, or should occur to either the torrent's data,
75 // or connected peers.
76 func (t *Torrent) Drop() {
77         t.cl.mu.Lock()
78         t.cl.dropTorrent(t.infoHash)
79         t.cl.mu.Unlock()
80 }
81
82 // Number of bytes of the entire torrent we have completed.
83 func (t *Torrent) BytesCompleted() int64 {
84         t.cl.mu.RLock()
85         defer t.cl.mu.RUnlock()
86         return t.bytesCompleted()
87 }
88
89 // The subscription emits as (int) the index of pieces as their state changes.
90 // A state change is when the PieceState for a piece alters in value.
91 func (t *Torrent) SubscribePieceStateChanges() *pubsub.Subscription {
92         return t.pieceStateChanges.Subscribe()
93 }
94
95 // Returns true if the torrent is currently being seeded. This occurs when the
96 // client is willing to upload without wanting anything in return.
97 func (t *Torrent) Seeding() bool {
98         t.cl.mu.Lock()
99         defer t.cl.mu.Unlock()
100         return t.seeding()
101 }
102
103 // Clobbers the torrent display name. The display name is used as the torrent
104 // name if the metainfo is not available.
105 func (t *Torrent) SetDisplayName(dn string) {
106         t.cl.mu.Lock()
107         defer t.cl.mu.Unlock()
108         t.setDisplayName(dn)
109 }
110
111 // The current working name for the torrent. Either the name in the info dict,
112 // or a display name given such as by the dn value in a magnet link, or "".
113 func (t *Torrent) Name() string {
114         t.cl.mu.Lock()
115         defer t.cl.mu.Unlock()
116         return t.name()
117 }
118
119 // The completed length of all the torrent data, in all its files. This is
120 // derived from the torrent info, when it is available.
121 func (t *Torrent) Length() int64 {
122         if t.info == nil {
123                 panic("not valid until info obtained")
124         }
125         return t.length
126 }
127
128 // Returns a run-time generated metainfo for the torrent that includes the
129 // info bytes and announce-list as currently known to the client.
130 func (t *Torrent) Metainfo() metainfo.MetaInfo {
131         t.cl.mu.Lock()
132         defer t.cl.mu.Unlock()
133         return t.newMetaInfo()
134 }
135
136 func (t *Torrent) addReader(r *reader) {
137         t.cl.mu.Lock()
138         defer t.cl.mu.Unlock()
139         if t.readers == nil {
140                 t.readers = make(map[*reader]struct{})
141         }
142         t.readers[r] = struct{}{}
143         r.posChanged()
144 }
145
146 func (t *Torrent) deleteReader(r *reader) {
147         delete(t.readers, r)
148         t.readersChanged()
149 }
150
151 func (t *Torrent) DownloadPieces(begin, end int) {
152         t.cl.mu.Lock()
153         defer t.cl.mu.Unlock()
154         t.pendPieceRange(begin, end)
155 }
156
157 func (t *Torrent) CancelPieces(begin, end int) {
158         t.cl.mu.Lock()
159         defer t.cl.mu.Unlock()
160         t.unpendPieceRange(begin, end)
161 }
162
163 // Returns handles to the files in the torrent. This requires the metainfo is
164 // available first.
165 func (t *Torrent) Files() (ret []File) {
166         info := t.Info()
167         if info == nil {
168                 return
169         }
170         var offset int64
171         for _, fi := range info.UpvertedFiles() {
172                 ret = append(ret, File{
173                         t,
174                         strings.Join(append([]string{info.Name}, fi.Path...), "/"),
175                         offset,
176                         fi.Length,
177                         fi,
178                 })
179                 offset += fi.Length
180         }
181         return
182 }
183
184 func (t *Torrent) AddPeers(pp []Peer) {
185         cl := t.cl
186         cl.mu.Lock()
187         defer cl.mu.Unlock()
188         t.addPeers(pp)
189 }
190
191 // Marks the entire torrent for download. Requires the info first, see
192 // GotInfo.
193 func (t *Torrent) DownloadAll() {
194         t.cl.mu.Lock()
195         defer t.cl.mu.Unlock()
196         t.pendPieceRange(0, t.numPieces())
197 }
198
199 func (t *Torrent) String() string {
200         s := t.name()
201         if s == "" {
202                 s = t.infoHash.HexString()
203         }
204         return s
205 }
206
207 func (t *Torrent) AddTrackers(announceList [][]string) {
208         t.cl.mu.Lock()
209         defer t.cl.mu.Unlock()
210         t.addTrackers(announceList)
211 }
212
213 func (t *Torrent) Piece(i int) *Piece {
214         t.cl.mu.Lock()
215         defer t.cl.mu.Unlock()
216         return &t.pieces[i]
217 }