diff --git a/client.go b/client.go index 578294fb..14205d89 100644 --- a/client.go +++ b/client.go @@ -1,17 +1,3 @@ -/* -Package torrent implements a torrent client. - -Simple example: - - c, _ := torrent.NewClient(&torrent.Config{}) - defer c.Close() - t, _ := c.AddMagnet("magnet:?xt=urn:btih:ZOCMZQIPFFW7OLLMIC5HUB6BPCSDEOQU") - t.DownloadAll() - c.WaitAll() - log.Print("ermahgerd, torrent downloaded") - - -*/ package torrent import ( @@ -38,18 +24,18 @@ import ( "syscall" "time" - "github.com/anacrolix/torrent/bencode" - "github.com/anacrolix/torrent/metainfo" "github.com/anacrolix/sync" "github.com/anacrolix/utp" "github.com/bradfitz/iter" + "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/data" filePkg "github.com/anacrolix/torrent/data/file" "github.com/anacrolix/torrent/dht" "github.com/anacrolix/torrent/internal/pieceordering" "github.com/anacrolix/torrent/iplist" "github.com/anacrolix/torrent/logonce" + "github.com/anacrolix/torrent/metainfo" "github.com/anacrolix/torrent/mse" pp "github.com/anacrolix/torrent/peer_protocol" "github.com/anacrolix/torrent/tracker" @@ -657,7 +643,7 @@ func (cl *Client) Torrent(ih InfoHash) (T Torrent, ok bool) { if !ok { return } - T = Torrent{cl, t} + T = Torrent{cl, t, t.gotMetainfo} return } @@ -1894,7 +1880,6 @@ func newTorrent(ih InfoHash) (t *torrent, err error) { HalfOpen: make(map[string]struct{}), } t.wantPeers.L = &t.stateMu - t.GotMetainfo = t.gotMetainfo return } @@ -1981,7 +1966,7 @@ type Handle interface { // available first. func (t Torrent) Files() (ret []File) { t.cl.mu.Lock() - info := t.Info + info := t.Info() t.cl.mu.Unlock() if info == nil { return @@ -2017,7 +2002,8 @@ func (t Torrent) AddPeers(pp []Peer) error { return nil } -// Marks the entire torrent for download. +// Marks the entire torrent for download. Requires the info first, see +// GotInfo. func (t Torrent) DownloadAll() { t.cl.mu.Lock() defer t.cl.mu.Unlock() @@ -2626,7 +2612,7 @@ func (cl *Client) verifyPiece(t *torrent, index pp.Integer) { func (me *Client) Torrents() (ret []Torrent) { me.mu.Lock() for _, t := range me.torrents { - ret = append(ret, Torrent{me, t}) + ret = append(ret, Torrent{me, t, t.gotMetainfo}) } me.mu.Unlock() return diff --git a/cmd/magnet-metainfo/main.go b/cmd/magnet-metainfo/main.go index 079f38b7..da94532e 100644 --- a/cmd/magnet-metainfo/main.go +++ b/cmd/magnet-metainfo/main.go @@ -7,9 +7,8 @@ import ( "os" "sync" - "github.com/anacrolix/torrent/bencode" - "github.com/anacrolix/torrent" + "github.com/anacrolix/torrent/bencode" ) func main() { @@ -27,7 +26,7 @@ func main() { wg.Add(1) go func() { defer wg.Done() - <-t.GotMetainfo + <-t.GotInfo mi := t.MetaInfo() t.Drop() f, err := os.Create(mi.Info.Name + ".torrent") diff --git a/cmd/torrent/main.go b/cmd/torrent/main.go index 116b33b9..dcb46914 100644 --- a/cmd/torrent/main.go +++ b/cmd/torrent/main.go @@ -12,11 +12,11 @@ import ( "time" _ "github.com/anacrolix/envpprof" - "github.com/anacrolix/torrent/metainfo" "github.com/dustin/go-humanize" "github.com/jessevdk/go-flags" "github.com/anacrolix/torrent" + "github.com/anacrolix/torrent/metainfo" ) // fmt.Fprintf(os.Stderr, "Usage: %s \n", os.Args[0]) @@ -49,11 +49,12 @@ func bytesCompleted(tc *torrent.Client) (ret int64) { func totalBytesEstimate(tc *torrent.Client) (ret int64) { var noInfo, hadInfo int64 for _, t := range tc.Torrents() { - if t.Info == nil { + info := t.Info() + if info == nil { noInfo++ continue } - ret += t.Info.TotalLength() + ret += info.TotalLength() hadInfo++ } if hadInfo != 0 { @@ -127,7 +128,7 @@ func main() { log.Fatal(err) } go func() { - <-t.GotMetainfo + <-t.GotInfo t.DownloadAll() }() } diff --git a/doc.go b/doc.go new file mode 100644 index 00000000..f8670a96 --- /dev/null +++ b/doc.go @@ -0,0 +1,16 @@ +/* +Package torrent implements a torrent client. + +Simple example: + + c, _ := torrent.NewClient(&torrent.Config{}) + defer c.Close() + t, _ := c.AddMagnet("magnet:?xt=urn:btih:ZOCMZQIPFFW7OLLMIC5HUB6BPCSDEOQU") + <-t.GotInfo + t.DownloadAll() + c.WaitAll() + log.Print("ermahgerd, torrent downloaded") + + +*/ +package torrent diff --git a/fs/torrentfs.go b/fs/torrentfs.go index b7988313..5fcd8eea 100644 --- a/fs/torrentfs.go +++ b/fs/torrentfs.go @@ -10,10 +10,10 @@ import ( "bazil.org/fuse" fusefs "bazil.org/fuse/fs" - "github.com/anacrolix/torrent/metainfo" "golang.org/x/net/context" "github.com/anacrolix/torrent" + "github.com/anacrolix/torrent/metainfo" ) const ( @@ -237,16 +237,17 @@ func (dn dirNode) Attr(attr *fuse.Attr) { func (me rootNode) Lookup(ctx context.Context, name string) (_node fusefs.Node, err error) { for _, t := range me.fs.Client.Torrents() { - if t.Name() != name || t.Info == nil { + info := t.Info() + if t.Name() != name || info == nil { continue } __node := node{ - metadata: t.Info, + metadata: info, FS: me.fs, t: t, } - if !t.Info.IsDir() { - _node = fileNode{__node, uint64(t.Info.Length), 0} + if !info.IsDir() { + _node = fileNode{__node, uint64(info.Length), 0} } else { _node = dirNode{__node} } @@ -260,13 +261,14 @@ func (me rootNode) Lookup(ctx context.Context, name string) (_node fusefs.Node, func (me rootNode) ReadDirAll(ctx context.Context) (dirents []fuse.Dirent, err error) { for _, t := range me.fs.Client.Torrents() { - if t.Info == nil { + info := t.Info() + if info == nil { continue } dirents = append(dirents, fuse.Dirent{ - Name: t.Info.Name, + Name: info.Name, Type: func() fuse.DirentType { - if !t.Info.IsDir() { + if !info.IsDir() { return fuse.DT_File } else { return fuse.DT_Dir diff --git a/reader.go b/reader.go index 60357f4e..3cdae00a 100644 --- a/reader.go +++ b/reader.go @@ -89,7 +89,7 @@ func (r *Reader) readAt(b []byte, pos int64) (n int, err error) { // }() r.t.cl.mu.Lock() defer r.t.cl.mu.Unlock() - maxLen := r.t.Info.TotalLength() - pos + maxLen := r.t.torrent.Info.TotalLength() - pos if maxLen <= 0 { err = io.EOF return @@ -123,7 +123,7 @@ func (r *Reader) Seek(off int64, whence int) (ret int64, err error) { case os.SEEK_CUR: r.pos += off case os.SEEK_END: - r.pos = r.t.Info.TotalLength() + off + r.pos = r.t.torrent.Info.TotalLength() + off default: err = errors.New("bad whence") } diff --git a/t.go b/t.go index be35c8c6..a4cf064f 100644 --- a/t.go +++ b/t.go @@ -1,11 +1,23 @@ package torrent +import ( + "github.com/anacrolix/torrent/metainfo" +) + // The public interface for a torrent within a Client. // A handle to a live torrent within a Client. type Torrent struct { cl *Client *torrent + // Closed when the info (.Info()) for the torrent has become available. + // Using features of Torrent that require the info before it is available + // will have undefined behaviour. + GotInfo <-chan struct{} +} + +func (t *Torrent) Info() *metainfo.Info { + return t.torrent.Info } func (t *Torrent) NewReader() (ret *Reader) { diff --git a/torrent.go b/torrent.go index 88863646..fd213d5b 100644 --- a/torrent.go +++ b/torrent.go @@ -10,11 +10,11 @@ import ( "sync" "time" - "github.com/anacrolix/torrent/bencode" - "github.com/anacrolix/torrent/metainfo" "github.com/bradfitz/iter" + "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/data" + "github.com/anacrolix/torrent/metainfo" pp "github.com/anacrolix/torrent/peer_protocol" "github.com/anacrolix/torrent/tracker" "github.com/anacrolix/torrent/util" @@ -73,7 +73,7 @@ type torrent struct { data StatefulData - // The info dict. Nil if we don't have it. + // The info dict. Nil if we don't have it (yet). Info *metainfo.Info // Active peer connections, running message stream loops. Conns []*connection @@ -100,7 +100,6 @@ type torrent struct { // Closed when .Info is set. gotMetainfo chan struct{} - GotMetainfo <-chan struct{} pruneTimer *time.Timer }