]> Sergey Matveev's repositories - btrtrc.git/blob - cmd/btrtrc/main.go
Remove FIFOs at quit
[btrtrc.git] / cmd / btrtrc / main.go
1 package main
2
3 import (
4         "bytes"
5         "flag"
6         "log"
7         "net"
8         "os"
9         "os/signal"
10         "strings"
11         "syscall"
12
13         "github.com/anacrolix/dht/v2"
14         analog "github.com/anacrolix/log"
15
16         "github.com/anacrolix/torrent"
17         "github.com/anacrolix/torrent/storage"
18 )
19
20 const TorrentExt = ".torrent"
21
22 func saveTorrent(t *torrent.Torrent) error {
23         pth := t.InfoHash().HexString() + TorrentExt
24         if _, err := os.Stat(pth); err == nil {
25                 return nil
26         }
27         var b bytes.Buffer
28         t.Metainfo().Write(&b)
29         if err := os.WriteFile(pth, b.Bytes(), 0666); err != nil {
30                 return err
31         }
32         return os.Symlink(pth, t.Name()+TorrentExt)
33 }
34
35 func main() {
36         log.SetFlags(log.Ldate | log.Ltime)
37         dhtBoot := flag.String("dht", "dht.cypherpunks.ru:8991", "Comma-separated list of DHT bootstrap nodes")
38         addr := flag.String("bind", "[::]:6881", "Address to bind to")
39         pub4 := flag.String("4", "", "External IPv4 address")
40         pub6 := flag.String("6", "", "External IPv6 address")
41         debug := flag.Bool("debug", false, "Enable debug messages")
42         noDHT := flag.Bool("nodht", false, "Disable DHT")
43         verify := flag.Bool("verify", false, "Force verification of provided torrents")
44         flag.Parse()
45
46         dht.DefaultGlobalBootstrapHostPorts = strings.Split(*dhtBoot, ",")
47         cc := torrent.NewDefaultClientConfig()
48         cc.Debug = *debug
49         cc.DisableAcceptRateLimiting = true
50         cc.NoDefaultPortForwarding = true
51         cc.DisableWebtorrent = true
52         cc.Logger = analog.Default.WithNames("main", "client")
53         cc.DefaultStorage = storage.NewFileWithCompletion(".", NewBFPieceCompletion())
54         if *verify {
55                 doVerify(cc, flag.Args())
56                 return
57         }
58         cc.Seed = true
59         if *pub4 == "" {
60                 cc.DisableIPv4 = true
61         } else {
62                 cc.PublicIp4 = net.ParseIP(*pub4).To4()
63         }
64         if *pub6 == "" {
65                 cc.DisableIPv6 = true
66         } else {
67                 cc.PublicIp6 = net.ParseIP(*pub6).To16()
68         }
69         cc.NoDHT = *noDHT
70         cc.SetListenAddr(*addr)
71         client, err := torrent.NewClient(cc)
72         if err != nil {
73                 log.Fatalln("torrent.NewClient:", err)
74         }
75         defer client.Close()
76
77         needsShutdown := make(chan os.Signal)
78         overallStatusCancel := make(chan struct{})
79         txStatsDumperCancel := make(chan struct{})
80         signal.Notify(needsShutdown, syscall.SIGTERM, syscall.SIGINT)
81         go func() {
82                 <-needsShutdown
83                 overallStatusCancel <- struct{}{}
84                 txStatsDumperCancel <- struct{}{}
85                 client.Close()
86         }()
87
88         fifosPrepare()
89         log.Println("started", client.PublicIPs())
90         go overallStatus(client, overallStatusCancel)
91         go fifoList(client)
92         go fifoDHTList(client)
93         go fifoAdd(client)
94         go fifoDel(client)
95         go txStatsDumper(client, txStatsDumperCancel)
96         <-client.Closed()
97         <-overallStatusCancel
98         <-txStatsDumperCancel
99         fifosCleanup()
100         log.Println("finished")
101 }