func TestDownloadOnDemand(t *testing.T) { layout, err := newGreetingLayout() require.NoError(t, err) defer layout.Destroy() seeder, err := torrent.NewClient(&torrent.Config{ DataDir: layout.Completed, DisableTrackers: true, NoDHT: true, ListenAddr: "localhost:0", Seed: true, // Ensure that the metainfo is obtained over the wire, since we added // the torrent to the seeder by magnet. DisableMetainfoCache: true, }) require.NoError(t, err) defer seeder.Close() testutil.ExportStatusWriter(seeder, "s") _, err = seeder.AddMagnet(fmt.Sprintf("magnet:?xt=urn:btih:%s", layout.Metainfo.Info.Hash.HexString())) require.NoError(t, err) leecher, err := torrent.NewClient(&torrent.Config{ DisableTrackers: true, NoDHT: true, ListenAddr: "localhost:0", DisableTCP: true, DefaultStorage: storage.NewMMap(filepath.Join(layout.BaseDir, "download")), // This can be used to check if clients can connect to other clients // with the same ID. // PeerID: seeder.PeerID(), }) require.NoError(t, err) testutil.ExportStatusWriter(leecher, "l") defer leecher.Close() leecherTorrent, _ := leecher.AddTorrent(layout.Metainfo) leecherTorrent.AddPeers([]torrent.Peer{ torrent.Peer{ IP: missinggo.AddrIP(seeder.ListenAddr()), Port: missinggo.AddrPort(seeder.ListenAddr()), }, }) fs := New(leecher) defer fs.Destroy() root, _ := fs.Root() node, _ := root.(fusefs.NodeStringLookuper).Lookup(netContext.Background(), "greeting") var attr fuse.Attr node.Attr(netContext.Background(), &attr) size := attr.Size resp := &fuse.ReadResponse{ Data: make([]byte, size), } node.(fusefs.HandleReader).Read(netContext.Background(), &fuse.ReadRequest{ Size: int(size), }, resp) assert.EqualValues(t, testutil.GreetingFileContents, resp.Data) }
func (e *Engine) Configure(c Config) error { //recieve config if e.client != nil { e.client.Close() } tc := torrent.Config{ DataDir: c.DownloadDirectory, ConfigDir: filepath.Join(c.DownloadDirectory, ".config"), NoUpload: !c.EnableUpload, Seed: c.EnableSeeding, } client, err := torrent.NewClient(&tc) if err != nil { return err } e.mut.Lock() e.cacheDir = filepath.Join(tc.ConfigDir, "torrents") if files, err := ioutil.ReadDir(e.cacheDir); err == nil { for _, f := range files { if filepath.Ext(f.Name()) != ".torrent" { continue } tt, err := client.AddTorrentFromFile(filepath.Join(e.cacheDir, f.Name())) if err == nil { e.upsertTorrent(tt) } } } e.config = c e.client = client e.mut.Unlock() //reset e.GetTorrents() return nil }
func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) tagflag.Parse(&opts, tagflag.SkipBadTypes()) clientConfig := opts.Config if opts.Mmap { clientConfig.TorrentDataOpener = func(info *metainfo.Info) torrent.Data { ret, err := mmap.TorrentData(info, "") if err != nil { log.Fatalf("error opening torrent data for %q: %s", info.Name, err) } return ret } } client, err := torrent.NewClient(&clientConfig) if err != nil { log.Fatalf("error creating client: %s", err) } defer client.Close() http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { client.WriteStatus(w) }) uiprogress.Start() addTorrents(client) if client.WaitAll() { log.Print("downloaded ALL the torrents") } else { log.Fatal("y u no complete torrents?!") } if opts.Seed { select {} } }
func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) tagflag.Parse(&flags) var clientConfig torrent.Config if flags.Mmap { clientConfig.DefaultStorage = storage.NewMMap("") } if flags.Addr != nil { clientConfig.ListenAddr = flags.Addr.String() } client, err := torrent.NewClient(&clientConfig) if err != nil { log.Fatalf("error creating client: %s", err) } defer client.Close() // Write status on the root path on the default HTTP muxer. This will be // bound to localhost somewhere if GOPPROF is set, thanks to the envpprof // import. http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { client.WriteStatus(w) }) uiprogress.Start() addTorrents(client) if client.WaitAll() { log.Print("downloaded ALL the torrents") } else { log.Fatal("y u no complete torrents?!") } if flags.Seed { select {} } }
func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) tagflag.Parse(&opts, tagflag.SkipBadTypes()) clientConfig := opts.Config if opts.Mmap { clientConfig.DefaultStorage = storage.NewMMap("") } client, err := torrent.NewClient(&clientConfig) if err != nil { log.Fatalf("error creating client: %s", err) } defer client.Close() http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { client.WriteStatus(w) }) uiprogress.Start() addTorrents(client) if client.WaitAll() { log.Print("downloaded ALL the torrents") } else { log.Fatal("y u no complete torrents?!") } if opts.Seed { select {} } }
// NewClient creates a new torrent client based on a magnet or a torrent file. // If the torrent file is on http, we try downloading it. func NewClient(torrentPath string, port int, seed bool) (client Client, err error) { var t torrent.Torrent var c *torrent.Client client.Port = port // Create client. c, err = torrent.NewClient(&torrent.Config{ DataDir: os.TempDir(), NoUpload: !seed, Seed: seed, }) if err != nil { return client, ClientError{Type: "creating torrent client", Origin: err} } client.Client = c // Add torrent. // Add as magnet url. if strings.HasPrefix(torrentPath, "magnet:") { if t, err = c.AddMagnet(torrentPath); err != nil { return client, ClientError{Type: "adding torrent", Origin: err} } } else { // Otherwise add as a torrent file. // If it's online, we try downloading the file. if isHTTP.MatchString(torrentPath) { if torrentPath, err = downloadFile(torrentPath); err != nil { return client, ClientError{Type: "downloading torrent file", Origin: err} } } // Check if the file exists. if _, err = os.Stat(torrentPath); err != nil { return client, ClientError{Type: "file not found", Origin: err} } if t, err = c.AddTorrentFromFile(torrentPath); err != nil { return client, ClientError{Type: "adding torrent to the client", Origin: err} } } client.Torrent = t go func() { <-t.GotInfo() t.DownloadAll() // Prioritize first 5% of the file. client.getLargestFile().PrioritizeRegion(0, int64(t.NumPieces()/100*5)) }() go client.addBlocklist() return }
func New(uri string) (*Downloader, string, error) { var err error var id string var client *torrent.Client var downloader = &Downloader{} id = utils.CalcMd5(uri) downloader.Id = id client, err = torrent.NewClient(&torrent.Config{ DataDir: filepath.Join(os.TempDir(), "gochromecast"), NoUpload: true, Seed: true, }) if err != nil { return downloader, id, errors.New( errors.DOWNLOADER_CANNOT_CREATE_TCLIENT_CODE, errors.DOWNLOADER_CANNOT_CREATE_TCLIENT_MESSAGE, err, ) } downloader.Client = client return downloader, id, nil }
func main() { flag.Parse() cl, err := torrent.NewClient(nil) if err != nil { log.Fatalf("error creating client: %s", err) } wg := sync.WaitGroup{} for _, arg := range flag.Args() { t, err := cl.AddMagnet(arg) if err != nil { log.Fatalf("error adding magnet to client: %s", err) } wg.Add(1) go func() { defer wg.Done() <-t.GotInfo() mi := t.Metainfo() t.Drop() f, err := os.Create(mi.Info.Name + ".torrent") if err != nil { log.Fatalf("error creating torrent metainfo file: %s", err) } defer f.Close() err = bencode.NewEncoder(f).Encode(mi) if err != nil { log.Fatalf("error writing torrent metainfo file: %s", err) } }() } wg.Wait() }
// NewClient creates a new torrent client based on a magnet or a torrent file. // If the torrent file is on http, we try downloading it. func NewClient(cfg ClientConfig) (client Client, err error) { var t *torrent.Torrent var c *torrent.Client client.Config = cfg // Create client. c, err = torrent.NewClient(&torrent.Config{ DataDir: os.TempDir(), NoUpload: !cfg.Seed, Seed: cfg.Seed, DisableTCP: !cfg.TCP, ListenAddr: fmt.Sprintf(":%d", cfg.TorrentPort), }) if err != nil { return client, ClientError{Type: "creating torrent client", Origin: err} } client.Client = c // Add torrent. // Add as magnet url. if strings.HasPrefix(cfg.TorrentPath, "magnet:") { if t, err = c.AddMagnet(cfg.TorrentPath); err != nil { return client, ClientError{Type: "adding torrent", Origin: err} } } else { // Otherwise add as a torrent file. // If it's online, we try downloading the file. if isHTTP.MatchString(cfg.TorrentPath) { if cfg.TorrentPath, err = downloadFile(cfg.TorrentPath); err != nil { return client, ClientError{Type: "downloading torrent file", Origin: err} } } if t, err = c.AddTorrentFromFile(cfg.TorrentPath); err != nil { return client, ClientError{Type: "adding torrent to the client", Origin: err} } } client.Torrent = t client.Torrent.SetMaxEstablishedConns(cfg.MaxConnections) go func() { <-t.GotInfo() t.DownloadAll() // Prioritize first 5% of the file. client.getLargestFile().PrioritizeRegion(0, int64(t.NumPieces()/100*5)) }() go client.addBlocklist() return }
func Example() { c, _ := torrent.NewClient(nil) defer c.Close() t, _ := c.AddMagnet("magnet:?xt=urn:btih:ZOCMZQIPFFW7OLLMIC5HUB6BPCSDEOQU") <-t.GotInfo() t.DownloadAll() c.WaitAll() log.Print("ermahgerd, torrent downloaded") }
// NewClient creates a new torrent client based on a magnet or a torrent file. // If the torrent file is on http, we try downloading it. func NewClient(torrentPath string) (client Client, err error) { var t torrent.Torrent var c *torrent.Client // Create client. c, err = torrent.NewClient(&torrent.Config{ DataDir: os.TempDir(), NoUpload: !(*seed), }) if err != nil { return client, ClientError{Type: "creating torrent client", Origin: err} } client.Client = c // Add torrent. // Add as magnet url. if strings.HasPrefix(torrentPath, "magnet:") { if t, err = c.AddMagnet(torrentPath); err != nil { return client, ClientError{Type: "adding torrent", Origin: err} } } else { // Otherwise add as a torrent file. // If it's online, we try downloading the file. if isHTTP.MatchString(torrentPath) { if torrentPath, err = downloadFile(torrentPath); err != nil { return client, ClientError{Type: "downloading torrent file", Origin: err} } } // Check if the file exists. if _, err = os.Stat(torrentPath); err != nil { return client, ClientError{Type: "file not found", Origin: err} } if t, err = c.AddTorrentFromFile(torrentPath); err != nil { return client, ClientError{Type: "adding torrent to the client", Origin: err} } } client.Torrent = t go func() { <-t.GotInfo() t.DownloadAll() }() return }
func (n *Native) SetConfig(obj interface{}) error { //recieve config c, ok := obj.(*config) if !ok { return fmt.Errorf("Invalid config") } client, err := torrent.NewClient(&c.Config) if err != nil { return err } n.client = client return nil }
func NewClient(downloadFolder string) (*Client, error) { client, err := torrent.NewClient(&torrent.Config{ DataDir: downloadFolder, NoUpload: false, Seed: true, DisableTCP: false, }) if err != nil { return nil, ClientError{Type: "creating torrent client", Origin: err} } return &Client{ Client: client, downloadFolder: downloadFolder, }, nil }
func NewBuiltin(dataDir string) (builtin *Builtin, err error) { cfg := &torrent.Config{ DataDir: dataDir, Seed: true, NoDHT: true, } client, err := torrent.NewClient(cfg) if err != nil { return } builtin = &Builtin{ Client: client, } return }
func (e *Engine) Configure(c Config) error { //recieve config if e.client != nil { e.client.Close() time.Sleep(1 * time.Second) } if c.IncomingPort <= 0 { return fmt.Errorf("Invalid incoming port (%d)", c.IncomingPort) } tc := torrent.Config{ DataDir: c.DownloadDirectory, ListenAddr: "0.0.0.0:" + strconv.Itoa(c.IncomingPort), NoUpload: !c.EnableUpload, Seed: c.EnableSeeding, DisableEncryption: c.DisableEncryption, } client, err := torrent.NewClient(&tc) if err != nil { return err } e.mut.Lock() e.cacheDir = filepath.Join(c.DownloadDirectory, ".config", "magnets") os.MkdirAll(e.cacheDir, 0777) if files, err := ioutil.ReadDir(e.cacheDir); err == nil { for _, f := range files { if filepath.Ext(f.Name()) != ".magnet" { continue } b, err := ioutil.ReadFile(filepath.Join(e.cacheDir, f.Name())) if err == nil { tt, err := client.AddMagnet(string(b[:])) if err == nil { e.upsertTorrent(tt) } } } } e.config = c e.client = client e.mut.Unlock() //reset e.GetTorrents() return nil }
func TestDownloadOnDemand(t *testing.T) { layout, err := newGreetingLayout() if err != nil { t.Fatal(err) } defer layout.Destroy() seeder, err := torrent.NewClient(&torrent.Config{ DataDir: layout.Completed, DisableTrackers: true, NoDHT: true, ListenAddr: ":0", Seed: true, NoDefaultBlocklist: true, // Ensure that the metainfo is obtained over the wire, since we added // the torrent to the seeder by magnet. DisableMetainfoCache: true, }) if err != nil { t.Fatalf("error creating seeder client: %s", err) } seeder.SetIPBlockList(nil) defer seeder.Close() http.HandleFunc("/seeder", func(w http.ResponseWriter, req *http.Request) { seeder.WriteStatus(w) }) _, err = seeder.AddMagnet(fmt.Sprintf("magnet:?xt=urn:btih:%x", layout.Metainfo.Info.Hash)) if err != nil { t.Fatal(err) } leecher, err := torrent.NewClient(&torrent.Config{ DisableTrackers: true, NoDHT: true, ListenAddr: ":0", DisableTCP: true, NoDefaultBlocklist: true, TorrentDataOpener: func(info *metainfo.Info) data.Data { ret, _ := mmap.TorrentData(info, filepath.Join(layout.BaseDir, "download")) return ret }, // This can be used to check if clients can connect to other clients // with the same ID. // PeerID: seeder.PeerID(), }) leecher.SetIPBlockList(nil) http.HandleFunc("/leecher", func(w http.ResponseWriter, req *http.Request) { leecher.WriteStatus(w) }) defer leecher.Close() leecherTorrent, _ := leecher.AddTorrent(layout.Metainfo) leecherTorrent.AddPeers([]torrent.Peer{func() torrent.Peer { _, port, err := net.SplitHostPort(seeder.ListenAddr().String()) if err != nil { panic(err) } portInt64, err := strconv.ParseInt(port, 0, 0) if err != nil { panic(err) } return torrent.Peer{ IP: func() net.IP { ret, _ := net.ResolveIPAddr("ip", "localhost") return ret.IP }(), Port: int(portInt64), } }()}) fs := New(leecher) defer fs.Destroy() root, _ := fs.Root() node, _ := root.(fusefs.NodeStringLookuper).Lookup(netContext.Background(), "greeting") var attr fuse.Attr node.Attr(netContext.Background(), &attr) size := attr.Size resp := &fuse.ReadResponse{ Data: make([]byte, size), } node.(fusefs.HandleReader).Read(netContext.Background(), &fuse.ReadRequest{ Size: int(size), }, resp) content := resp.Data if string(content) != testutil.GreetingFileContents { t.Fatalf("%q != %q", string(content), testutil.GreetingFileContents) } }
func main() { flag.Parse() if flag.NArg() != 0 { os.Stderr.WriteString("one does not simply pass positional args\n") os.Exit(2) } if *mountDir == "" { os.Stderr.WriteString("y u no specify mountpoint?\n") os.Exit(2) } log.SetFlags(log.LstdFlags | log.Lshortfile) conn, err := fuse.Mount(*mountDir) if err != nil { log.Fatal(err) } defer fuse.Unmount(*mountDir) // TODO: Think about the ramifications of exiting not due to a signal. defer conn.Close() client, err := torrent.NewClient(&torrent.Config{ DataDir: *downloadDir, DisableTrackers: *disableTrackers, ListenAddr: *listenAddr, NoUpload: true, // Ensure that downloads are responsive. }) if err != nil { log.Fatal(err) } // This is naturally exported via GOPPROF=http. http.DefaultServeMux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { client.WriteStatus(w) }) dw, err := dirwatch.New(*torrentPath) if err != nil { log.Fatal(err) } go func() { for ev := range dw.Events { switch ev.Change { case dirwatch.Added: if ev.TorrentFilePath != "" { _, err := client.AddTorrentFromFile(ev.TorrentFilePath) if err != nil { log.Printf("error adding torrent to client: %s", err) } } else if ev.MagnetURI != "" { _, err := client.AddMagnet(ev.MagnetURI) if err != nil { log.Printf("error adding magnet: %s", err) } } case dirwatch.Removed: T, ok := client.Torrent(ev.InfoHash) if !ok { break } T.Drop() } } }() resolveTestPeerAddr() fs := torrentfs.New(client) go exitSignalHandlers(fs) go func() { for { addTestPeer(client) time.Sleep(10 * time.Second) } }() if err := fusefs.Serve(conn, fs); err != nil { log.Fatal(err) } <-conn.Ready if err := conn.MountError; err != nil { log.Fatal(err) } }
func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) var rootGroup struct { Client torrent.Config `group:"Client Options"` TestPeers []string `long:"test-peer" description:"address of peer to inject to every torrent"` MMap bool `long:"mmap" description:"memory-map the torrent files"` } // Don't pass flags.PrintError because it's inconsistent with printing. // https://github.com/jessevdk/go-flags/issues/132 parser := flags.NewParser(&rootGroup, flags.HelpFlag|flags.PassDoubleDash) parser.Usage = "[OPTIONS] (magnet URI or .torrent file path)..." posArgs, err := parser.Parse() if err != nil { fmt.Fprintln(os.Stderr, "Download from the BitTorrent network.") fmt.Println(err) os.Exit(2) } testPeers, err := resolvedPeerAddrs(rootGroup.TestPeers) if err != nil { log.Fatal(err) } if rootGroup.MMap { rootGroup.Client.TorrentDataOpener = func(info *metainfo.Info) torrent.Data { ret, err := mmap.TorrentData(info, "") if err != nil { log.Fatalf("error opening torrent data for %q: %s", info.Name, err) } return ret } } if len(posArgs) == 0 { fmt.Fprintln(os.Stderr, "no torrents specified") return } client, err := torrent.NewClient(&rootGroup.Client) if err != nil { log.Fatalf("error creating client: %s", err) } http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { client.WriteStatus(w) }) defer client.Close() for _, arg := range posArgs { t := func() torrent.Torrent { if strings.HasPrefix(arg, "magnet:") { t, err := client.AddMagnet(arg) if err != nil { log.Fatalf("error adding magnet: %s", err) } return t } else { metaInfo, err := metainfo.LoadFromFile(arg) if err != nil { log.Fatal(err) } t, err := client.AddTorrent(metaInfo) if err != nil { log.Fatal(err) } return t } }() err := t.AddPeers(testPeers) if err != nil { log.Fatal(err) } go func() { <-t.GotInfo() t.DownloadAll() }() } done := make(chan struct{}) go func() { defer close(done) if client.WaitAll() { log.Print("downloaded ALL the torrents") } else { log.Fatal("y u no complete torrents?!") } }() ticker := time.NewTicker(time.Second) waitDone: for { select { case <-done: break waitDone case <-ticker.C: os.Stdout.WriteString(progressLine(client)) } } if rootGroup.Client.Seed { select {} } }
func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) var rootGroup struct { Client torrent.Config `group:"Client Options"` TestPeers []string `long:"test-peer" description:"address of peer to inject to every torrent"` Pick string `long:"pick" description:"filename to pick"` } // Don't pass flags.PrintError because it's inconsistent with printing. // https://github.com/jessevdk/go-flags/issues/132 parser := flags.NewParser(&rootGroup, flags.HelpFlag|flags.PassDoubleDash) parser.Usage = "[OPTIONS] (magnet URI or .torrent file path)..." posArgs, err := parser.Parse() if err != nil { fmt.Fprintln(os.Stderr, "Download from the BitTorrent network.\n") fmt.Println(err) os.Exit(2) } log.Printf("File to pick: %s", rootGroup.Pick) testPeers, err := resolvedPeerAddrs(rootGroup.TestPeers) if err != nil { log.Fatal(err) } if len(posArgs) == 0 { fmt.Fprintln(os.Stderr, "no torrents specified") return } tmpdir, err := ioutil.TempDir("", "torrent-pick-") if err != nil { log.Fatal(err) } defer os.RemoveAll(tmpdir) rootGroup.Client.DataDir = tmpdir client, err := torrent.NewClient(&rootGroup.Client) if err != nil { log.Fatalf("error creating client: %s", err) } http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { client.WriteStatus(w) }) defer client.Close() dstName := dstFileName(rootGroup.Pick) f, err := os.Create(dstName) if err != nil { log.Fatal(err) } dstWriter := bufio.NewWriter(f) done := make(chan struct{}) for _, arg := range posArgs { t := func() torrent.Torrent { if strings.HasPrefix(arg, "magnet:") { t, err := client.AddMagnet(arg) if err != nil { log.Fatalf("error adding magnet: %s", err) } return t } else { metaInfo, err := metainfo.LoadFromFile(arg) if err != nil { log.Fatal(err) } t, err := client.AddTorrent(metaInfo) if err != nil { log.Fatal(err) } return t } }() err := t.AddPeers(testPeers) if err != nil { log.Fatal(err) } go func() { defer close(done) <-t.GotInfo() for _, file := range t.Files() { if file.DisplayPath() != rootGroup.Pick { continue } srcReader := io.NewSectionReader(t.NewReader(), file.Offset(), file.Length()) io.Copy(dstWriter, srcReader) return } log.Print("file not found") }() } ticker := time.NewTicker(time.Second) waitDone: for { select { case <-done: break waitDone case <-ticker.C: os.Stdout.WriteString(progressLine(client)) } } if rootGroup.Client.Seed { select {} } }
func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) var opts struct { torrent.Config `name:"Client"` Mmap bool `help:"memory-map torrent data"` TestPeer []*net.TCPAddr `short:"p" help:"addresses of some starting peers"` Torrent []string `type:"pos" arity:"+" help:"torrent file path or magnet uri"` } tagflag.Parse(&opts, tagflag.SkipBadTypes()) clientConfig := opts.Config if opts.Mmap { clientConfig.TorrentDataOpener = func(info *metainfo.Info) torrent.Data { ret, err := mmap.TorrentData(info, "") if err != nil { log.Fatalf("error opening torrent data for %q: %s", info.Name, err) } return ret } } torrents := opts.Torrent if len(torrents) == 0 { fmt.Fprintf(os.Stderr, "no torrents specified\n") return } client, err := torrent.NewClient(&clientConfig) if err != nil { log.Fatalf("error creating client: %s", err) } http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { client.WriteStatus(w) }) defer client.Close() for _, arg := range torrents { t := func() torrent.Torrent { if strings.HasPrefix(arg, "magnet:") { t, err := client.AddMagnet(arg) if err != nil { log.Fatalf("error adding magnet: %s", err) } return t } else { metaInfo, err := metainfo.LoadFromFile(arg) if err != nil { fmt.Fprintf(os.Stderr, "error loading torrent file %q: %s\n", arg, err) os.Exit(1) } t, err := client.AddTorrent(metaInfo) if err != nil { log.Fatal(err) } return t } }() err := t.AddPeers(func() (ret []torrent.Peer) { for _, ta := range opts.TestPeer { ret = append(ret, torrent.Peer{ IP: ta.IP, Port: ta.Port, }) } return }()) if err != nil { log.Fatal(err) } go func() { <-t.GotInfo() t.DownloadAll() }() } done := make(chan struct{}) go func() { defer close(done) if client.WaitAll() { log.Print("downloaded ALL the torrents") } else { log.Fatal("y u no complete torrents?!") } }() ticker := time.NewTicker(time.Second) waitDone: for { select { case <-done: break waitDone case <-ticker.C: os.Stdout.WriteString(progressLine(client)) } } if opts.Seed { select {} } }
// Unmount without first killing the FUSE connection while there are FUSE // operations blocked inside the filesystem code. func TestUnmountWedged(t *testing.T) { layout, err := newGreetingLayout() if err != nil { t.Fatal(err) } defer func() { err := layout.Destroy() if err != nil { t.Log(err) } }() client, err := torrent.NewClient(&torrent.Config{ DataDir: filepath.Join(layout.BaseDir, "incomplete"), DisableTrackers: true, NoDHT: true, ListenAddr: "redonk", DisableTCP: true, DisableUTP: true, NoDefaultBlocklist: true, }) if err != nil { t.Fatal(err) } defer client.Close() client.AddTorrent(layout.Metainfo) fs := New(client) fuseConn, err := fuse.Mount(layout.MountDir) if err != nil { msg := fmt.Sprintf("error mounting: %s", err) if strings.Contains(err.Error(), "fuse") || err.Error() == "exit status 71" { t.Skip(msg) } t.Fatal(msg) } go func() { server := fusefs.New(fuseConn, &fusefs.Config{ Debug: func(msg interface{}) { t.Log(msg) }, }) server.Serve(fs) }() <-fuseConn.Ready if err := fuseConn.MountError; err != nil { t.Fatalf("mount error: %s", err) } // Read the greeting file, though it will never be available. This should // "wedge" FUSE, requiring the fs object to be forcibly destroyed. The // read call will return with a FS error. go func() { _, err := ioutil.ReadFile(filepath.Join(layout.MountDir, layout.Metainfo.Info.Name)) if err == nil { t.Fatal("expected error reading greeting") } }() // Wait until the read has blocked inside the filesystem code. fs.mu.Lock() for fs.blockedReads != 1 { fs.event.Wait() } fs.mu.Unlock() fs.Destroy() for { err = fuse.Unmount(layout.MountDir) if err != nil { t.Logf("error unmounting: %s", err) time.Sleep(time.Millisecond) } else { break } } err = fuseConn.Close() if err != nil { t.Fatalf("error closing fuse conn: %s", err) } }
func Start() torrent.Client { client, err := torrent.NewClient(nil) util.CheckError(err) return *client }
// Add Torrent/Magnet func add(w http.ResponseWriter, r *http.Request) { c := Add{} if e := json.NewDecoder(r.Body).Decode(&c); e != nil { httpd.Error(w, e, "Invalid input.") return } if c.User == "" { httpd.Error(w, nil, "No user.") return } if c.Dir == "" { httpd.Error(w, nil, "No dir.") return } if strings.Contains(c.Dir, "..") { httpd.Error(w, nil, "Dir hack.") return } if _, ok := clients[c.User]; !ok { dlDir := fmt.Sprintf(config.C.Basedir + c.Dir) if _, e := os.Stat(config.C.Basedir); os.IsNotExist(e) { if e := os.Mkdir(dlDir, os.ModeDir); e != nil { config.L.Printf("CRIT: %s", e.Error()) httpd.Error(w, e, "Permission error.") return } } // https://github.com/anacrolix/torrent/blob/master/config.go#L9 cl, e := torrent.NewClient(&torrent.Config{ DataDir: config.C.Basedir + c.Dir, // IPBlocklist => http://john.bitsurge.net/public/biglist.p2p.gz }) if e != nil { httpd.Error(w, e, "Client init failed") return } clients[c.User] = cl } client := clients[c.User] var ( t torrent.Torrent e error ) if len(c.Magnet) > 0 { t, e = client.AddMagnet(c.Magnet) if e != nil { httpd.Error(w, e, "Magnet add failed") return } } else if len(c.Torrent) > 0 { // strip base64 b, e := base64.StdEncoding.DecodeString(c.Torrent) if e != nil { httpd.Error(w, e, "Failed base64 decode torrent input") return } m, e := metainfo.Load(bytes.NewReader(b)) if e != nil { httpd.Error(w, e, "Failed base64 decode torrent input") return } t, e = client.AddTorrent(m) if e != nil { httpd.Error(w, e, "Failed adding torrent") return } } else { httpd.Error(w, nil, "No magnet nor torrent.") return } // queue go func() { <-t.GotInfo() t.DownloadAll() }() // (cl *Client) AddTorrentSpec(spec *TorrentSpec) (T Torrent, new bool, err error) { // TorrentSpecFromMagnetURI(uri string) (spec *TorrentSpec, err error) { // TorrentSpecFromMetaInfo(mi *metainfo.MetaInfo) (spec *TorrentSpec) { // (me *Client) AddMagnet(uri string) (T Torrent, err error) { // (me *Client) AddTorrent(mi *metainfo.MetaInfo) (T Torrent, err error) { msg := fmt.Sprintf(`{"status": true, "hash": "%s", "text": "Queued."}`, t.InfoHash().HexString()) w.Header().Set("Content-Type", "application/json") if _, e := w.Write([]byte(msg)); e != nil { httpd.Error(w, e, "Flush failed") return } }