client.go | 28 +++++++--------------------- cmd/magnet-metainfo/main.go | 5 ++--- cmd/torrent/main.go | 9 +++++---- doc.go | 16 ++++++++++++++++ fs/torrentfs.go | 18 ++++++++++-------- reader.go | 4 ++-- t.go | 12 ++++++++++++ torrent.go | 7 +++---- diff --git a/client.go b/client.go index 578294fb742f5ec47827d231ae9cd030c27872cf..14205d8994fa35dc4151fd7417dc8d216cc641c2 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 @@ "strings" "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 @@ t, ok := cl.torrents[ih] if !ok { return } - T = Torrent{cl, t} + T = Torrent{cl, t, t.gotMetainfo} return } @@ -1894,7 +1880,6 @@ HalfOpen: make(map[string]struct{}), } t.wantPeers.L = &t.stateMu - t.GotMetainfo = t.gotMetainfo return } @@ -1981,7 +1966,7 @@ // Returns handles to the files in the torrent. This requires the metainfo is // 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 @@ cl.addPeers(t.torrent, pp) 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 @@ // Returns handles to all the torrents loaded in the Client. 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 079f38b751a1cdcef9742144a80c5e8ccece9c8d..da94532ebd383d45fc50b8b98a41874d69f19e6e 100644 --- a/cmd/magnet-metainfo/main.go +++ b/cmd/magnet-metainfo/main.go @@ -7,9 +7,8 @@ "log" "os" "sync" + "github.com/anacrolix/torrent" "github.com/anacrolix/torrent/bencode" - - "github.com/anacrolix/torrent" ) func main() { @@ -27,7 +26,7 @@ } 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 116b33b94eb05cf19d51553722f31fb029df38fd..dcb46914cc5a6c4705aadbf1b93c278823b84821 100644 --- a/cmd/torrent/main.go +++ b/cmd/torrent/main.go @@ -12,11 +12,11 @@ "strings" "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 @@ // Returns an estimate of the total bytes for all torrents. 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 @@ if err != nil { log.Fatal(err) } go func() { - <-t.GotMetainfo + <-t.GotInfo t.DownloadAll() }() } diff --git a/doc.go b/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..f8670a967d500d3e918a138fa1017dde5286a14e --- /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 b7988313f3a9ce653da5abee8c59f660b08a2212..5fcd8eea1ab79024c37a76d6f094c0c2896d257f 100644 --- a/fs/torrentfs.go +++ b/fs/torrentfs.go @@ -10,10 +10,10 @@ "sync" "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 (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) 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 60357f4effc2d460d954c4b220ce42d98ee5d07e..3cdae00a010efb1995666d9f4b18f1abb43ce073 100644 --- a/reader.go +++ b/reader.go @@ -89,7 +89,7 @@ // log.Println(pos, n, err) // }() 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 @@ r.pos = off 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 be35c8c6d7a4789c0804a1811d2cb22c05b77358..a4cf064f115ba14f92c7592c32acb184d3cd8eb6 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 8886364634201e5286b92948fe062697454bd11a..fd213d5bc16c215b79482b60ce746a37897d43db 100644 --- a/torrent.go +++ b/torrent.go @@ -10,11 +10,11 @@ "sort" "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 @@ length int64 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 @@ metadataHave []bool // Closed when .Info is set. gotMetainfo chan struct{} - GotMetainfo <-chan struct{} pruneTimer *time.Timer }