12 "github.com/anacrolix/dht/v2"
13 analog "github.com/anacrolix/log"
15 "github.com/anacrolix/torrent"
16 "github.com/anacrolix/torrent/storage"
19 const TorrentExt = ".torrent"
22 log.SetFlags(log.Ldate | log.Ltime)
23 dhtBoot := flag.String("dht", "dht.cypherpunks.ru:8991", "Comma-separated list of DHT bootstrap nodes")
24 addr := flag.String("bind", "[::]:6881", "Address to bind to")
25 pub4 := flag.String("4", "", "External IPv4 address")
26 pub6 := flag.String("6", "", "External IPv6 address")
27 debug := flag.Bool("debug", false, "Enable debug messages")
28 noDHT := flag.Bool("nodht", false, "Disable DHT")
29 verify := flag.Bool("verify", false, "Force verification of provided torrents")
32 dht.DefaultGlobalBootstrapHostPorts = strings.Split(*dhtBoot, ",")
33 cc := torrent.NewDefaultClientConfig()
35 cc.DisableAcceptRateLimiting = true
36 cc.NoDefaultPortForwarding = true
37 cc.DisableWebtorrent = true
38 cc.Logger = analog.Default.WithNames("main", "client")
39 cc.HTTPUserAgent = "btrtrc/0.1.0"
40 cc.ExtendedHandshakeClientVersion = "btrtrc/0.1.0"
41 cc.DefaultStorage = storage.NewFileWithCompletion(".", NewBFPieceCompletion())
43 doVerify(cc, flag.Args())
50 cc.PublicIp4 = net.ParseIP(*pub4).To4()
55 cc.PublicIp6 = net.ParseIP(*pub6).To16()
58 cc.SetListenAddr(*addr)
59 client, err := torrent.NewClient(cc)
61 log.Fatalln("torrent.NewClient:", err)
65 needsShutdown := make(chan os.Signal)
66 overallStatusCancel := make(chan struct{})
67 txStatsDumperCancel := make(chan struct{})
68 signal.Notify(needsShutdown, syscall.SIGTERM, syscall.SIGINT)
71 overallStatusCancel <- struct{}{}
72 txStatsDumperCancel <- struct{}{}
77 log.Println("started", client.PublicIPs())
78 go overallStatus(client, overallStatusCancel)
80 go fifoDHTList(client)
83 go txStatsDumper(client, txStatsDumperCancel)
88 log.Println("finished")