-/*
-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 (
"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"
if !ok {
return
}
- T = Torrent{cl, t}
+ T = Torrent{cl, t, t.gotMetainfo}
return
}
HalfOpen: make(map[string]struct{}),
}
t.wantPeers.L = &t.stateMu
- t.GotMetainfo = t.gotMetainfo
return
}
// 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
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()
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
"os"
"sync"
- "github.com/anacrolix/torrent/bencode"
-
"github.com/anacrolix/torrent"
+ "github.com/anacrolix/torrent/bencode"
)
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")
"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])
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 {
log.Fatal(err)
}
go func() {
- <-t.GotMetainfo
+ <-t.GotInfo
t.DownloadAll()
}()
}
--- /dev/null
+/*
+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
"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 (
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}
}
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
// }()
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
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")
}
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) {
"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"
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
// Closed when .Info is set.
gotMetainfo chan struct{}
- GotMetainfo <-chan struct{}
pruneTimer *time.Timer
}