]> Sergey Matveev's repositories - btrtrc.git/blob - client.go
f5a82300de051abc625a38b3864b77efb6f99147
[btrtrc.git] / client.go
1 package torrent
2
3 import (
4         "bufio"
5         "bytes"
6         "context"
7         "crypto/rand"
8         "encoding/binary"
9         "errors"
10         "fmt"
11         "io"
12         "net"
13         "strconv"
14         "strings"
15         "time"
16
17         "github.com/anacrolix/dht"
18         "github.com/anacrolix/dht/krpc"
19         "github.com/anacrolix/log"
20         "github.com/anacrolix/missinggo"
21         "github.com/anacrolix/missinggo/pproffd"
22         "github.com/anacrolix/missinggo/pubsub"
23         "github.com/anacrolix/missinggo/slices"
24         "github.com/anacrolix/sync"
25         "github.com/dustin/go-humanize"
26         "github.com/google/btree"
27         "golang.org/x/time/rate"
28
29         "github.com/anacrolix/torrent/bencode"
30         "github.com/anacrolix/torrent/iplist"
31         "github.com/anacrolix/torrent/metainfo"
32         "github.com/anacrolix/torrent/mse"
33         pp "github.com/anacrolix/torrent/peer_protocol"
34         "github.com/anacrolix/torrent/storage"
35 )
36
37 // Clients contain zero or more Torrents. A Client manages a blocklist, the
38 // TCP/UDP protocol ports, and DHT as desired.
39 type Client struct {
40         mu     sync.RWMutex
41         event  sync.Cond
42         closed missinggo.Event
43
44         config Config
45         logger *log.Logger
46
47         halfOpenLimit  int
48         peerID         PeerID
49         defaultStorage *storage.Client
50         onClose        []func()
51         conns          []socket
52         dhtServers     []*dht.Server
53         ipBlockList    iplist.Ranger
54         // Our BitTorrent protocol extension bytes, sent in our BT handshakes.
55         extensionBytes peerExtensionBytes
56         uploadLimit    *rate.Limiter
57         downloadLimit  *rate.Limiter
58
59         // Set of addresses that have our client ID. This intentionally will
60         // include ourselves if we end up trying to connect to our own address
61         // through legitimate channels.
62         dopplegangerAddrs map[string]struct{}
63         badPeerIPs        map[string]struct{}
64         torrents          map[metainfo.Hash]*Torrent
65 }
66
67 func (cl *Client) BadPeerIPs() []string {
68         cl.mu.RLock()
69         defer cl.mu.RUnlock()
70         return cl.badPeerIPsLocked()
71 }
72
73 func (cl *Client) badPeerIPsLocked() []string {
74         return slices.FromMapKeys(cl.badPeerIPs).([]string)
75 }
76
77 func (cl *Client) PeerID() PeerID {
78         return cl.peerID
79 }
80
81 type torrentAddr string
82
83 func (torrentAddr) Network() string { return "" }
84
85 func (me torrentAddr) String() string { return string(me) }
86
87 func (cl *Client) LocalPort() (port int) {
88         cl.eachListener(func(l socket) bool {
89                 _port := missinggo.AddrPort(l.Addr())
90                 if _port == 0 {
91                         panic(l)
92                 }
93                 if port == 0 {
94                         port = _port
95                 } else if port != _port {
96                         panic("mismatched ports")
97                 }
98                 return true
99         })
100         return
101 }
102
103 func writeDhtServerStatus(w io.Writer, s *dht.Server) {
104         dhtStats := s.Stats()
105         fmt.Fprintf(w, "\t# Nodes: %d (%d good, %d banned)\n", dhtStats.Nodes, dhtStats.GoodNodes, dhtStats.BadNodes)
106         fmt.Fprintf(w, "\tServer ID: %x\n", s.ID())
107         fmt.Fprintf(w, "\tAnnounces: %d\n", dhtStats.SuccessfulOutboundAnnouncePeerQueries)
108         fmt.Fprintf(w, "\tOutstanding transactions: %d\n", dhtStats.OutstandingTransactions)
109 }
110
111 // Writes out a human readable status of the client, such as for writing to a
112 // HTTP status page.
113 func (cl *Client) WriteStatus(_w io.Writer) {
114         cl.mu.Lock()
115         defer cl.mu.Unlock()
116         w := bufio.NewWriter(_w)
117         defer w.Flush()
118         fmt.Fprintf(w, "Listen port: %d\n", cl.LocalPort())
119         fmt.Fprintf(w, "Peer ID: %+q\n", cl.PeerID())
120         fmt.Fprintf(w, "Announce key: %x\n", cl.announceKey())
121         fmt.Fprintf(w, "Banned IPs: %d\n", len(cl.badPeerIPsLocked()))
122         cl.eachDhtServer(func(s *dht.Server) {
123                 fmt.Fprintf(w, "%s DHT server at %s:\n", s.Addr().Network(), s.Addr().String())
124                 writeDhtServerStatus(w, s)
125         })
126         fmt.Fprintf(w, "# Torrents: %d\n", len(cl.torrentsAsSlice()))
127         fmt.Fprintln(w)
128         for _, t := range slices.Sort(cl.torrentsAsSlice(), func(l, r *Torrent) bool {
129                 return l.InfoHash().AsString() < r.InfoHash().AsString()
130         }).([]*Torrent) {
131                 if t.name() == "" {
132                         fmt.Fprint(w, "<unknown name>")
133                 } else {
134                         fmt.Fprint(w, t.name())
135                 }
136                 fmt.Fprint(w, "\n")
137                 if t.info != nil {
138                         fmt.Fprintf(w, "%f%% of %d bytes (%s)", 100*(1-float64(t.bytesMissingLocked())/float64(t.info.TotalLength())), t.length, humanize.Bytes(uint64(t.info.TotalLength())))
139                 } else {
140                         w.WriteString("<missing metainfo>")
141                 }
142                 fmt.Fprint(w, "\n")
143                 t.writeStatus(w)
144                 fmt.Fprintln(w)
145         }
146 }
147
148 const debugLogValue = "debug"
149
150 func (cl *Client) debugLogFilter(m *log.Msg) bool {
151         if !cl.config.Debug {
152                 _, ok := m.Values()[debugLogValue]
153                 return !ok
154         }
155         return true
156 }
157
158 func (cl *Client) initLogger() {
159         cl.logger = log.Default.Clone().AddValue(cl).AddFilter(log.NewFilter(cl.debugLogFilter))
160 }
161
162 func (cl *Client) announceKey() int32 {
163         return int32(binary.BigEndian.Uint32(cl.peerID[16:20]))
164 }
165
166 func NewClient(cfg *Config) (cl *Client, err error) {
167         if cfg == nil {
168                 cfg = &Config{}
169         }
170         cfg.setDefaults()
171
172         defer func() {
173                 if err != nil {
174                         cl = nil
175                 }
176         }()
177         cl = &Client{
178                 halfOpenLimit:     cfg.HalfOpenConnsPerTorrent,
179                 config:            *cfg,
180                 dopplegangerAddrs: make(map[string]struct{}),
181                 torrents:          make(map[metainfo.Hash]*Torrent),
182         }
183         cl.initLogger()
184         defer func() {
185                 if err == nil {
186                         return
187                 }
188                 cl.Close()
189         }()
190         if cfg.UploadRateLimiter == nil {
191                 cl.uploadLimit = rate.NewLimiter(rate.Inf, 0)
192         } else {
193                 cl.uploadLimit = cfg.UploadRateLimiter
194         }
195         if cfg.DownloadRateLimiter == nil {
196                 cl.downloadLimit = rate.NewLimiter(rate.Inf, 0)
197         } else {
198                 cl.downloadLimit = cfg.DownloadRateLimiter
199         }
200         cl.extensionBytes = defaultPeerExtensionBytes()
201         cl.event.L = &cl.mu
202         storageImpl := cfg.DefaultStorage
203         if storageImpl == nil {
204                 // We'd use mmap but HFS+ doesn't support sparse files.
205                 storageImpl = storage.NewFile(cfg.DataDir)
206                 cl.onClose = append(cl.onClose, func() {
207                         if err := storageImpl.Close(); err != nil {
208                                 log.Printf("error closing default storage: %s", err)
209                         }
210                 })
211         }
212         cl.defaultStorage = storage.NewClient(storageImpl)
213         if cfg.IPBlocklist != nil {
214                 cl.ipBlockList = cfg.IPBlocklist
215         }
216
217         if cfg.PeerID != "" {
218                 missinggo.CopyExact(&cl.peerID, cfg.PeerID)
219         } else {
220                 o := copy(cl.peerID[:], cfg.Bep20)
221                 _, err = rand.Read(cl.peerID[o:])
222                 if err != nil {
223                         panic("error generating peer id")
224                 }
225         }
226
227         cl.conns, err = listenAll(cl.enabledPeerNetworks(), cl.config.ListenHost, cl.config.ListenPort, cl.config.ProxyURL)
228         if err != nil {
229                 return
230         }
231         // Check for panics.
232         cl.LocalPort()
233
234         for _, s := range cl.conns {
235                 if peerNetworkEnabled(s.Addr().Network(), cl.config) {
236                         go cl.acceptConnections(s)
237                 }
238         }
239
240         go cl.forwardPort()
241         if !cfg.NoDHT {
242                 for _, s := range cl.conns {
243                         if pc, ok := s.(net.PacketConn); ok {
244                                 ds, err := cl.newDhtServer(pc)
245                                 if err != nil {
246                                         panic(err)
247                                 }
248                                 cl.dhtServers = append(cl.dhtServers, ds)
249                         }
250                 }
251         }
252
253         return
254 }
255
256 func (cl *Client) enabledPeerNetworks() (ns []string) {
257         for _, n := range allPeerNetworks {
258                 if peerNetworkEnabled(n, cl.config) {
259                         ns = append(ns, n)
260                 }
261         }
262         return
263 }
264
265 func (cl *Client) newDhtServer(conn net.PacketConn) (s *dht.Server, err error) {
266         cfg := dht.ServerConfig{
267                 IPBlocklist:    cl.ipBlockList,
268                 Conn:           conn,
269                 OnAnnouncePeer: cl.onDHTAnnouncePeer,
270                 PublicIP: func() net.IP {
271                         if connIsIpv6(conn) && cl.config.PublicIp6 != nil {
272                                 return cl.config.PublicIp6
273                         }
274                         return cl.config.PublicIp4
275                 }(),
276                 StartingNodes: cl.config.DhtStartingNodes,
277         }
278         s, err = dht.NewServer(&cfg)
279         if err == nil {
280                 go func() {
281                         if _, err := s.Bootstrap(); err != nil {
282                                 log.Printf("error bootstrapping dht: %s", err)
283                         }
284                 }()
285         }
286         return
287 }
288
289 func firstNonEmptyString(ss ...string) string {
290         for _, s := range ss {
291                 if s != "" {
292                         return s
293                 }
294         }
295         return ""
296 }
297
298 func (cl *Client) Closed() <-chan struct{} {
299         cl.mu.Lock()
300         defer cl.mu.Unlock()
301         return cl.closed.C()
302 }
303
304 func (cl *Client) eachDhtServer(f func(*dht.Server)) {
305         for _, ds := range cl.dhtServers {
306                 f(ds)
307         }
308 }
309
310 func (cl *Client) closeSockets() {
311         cl.eachListener(func(l socket) bool {
312                 l.Close()
313                 return true
314         })
315         cl.conns = nil
316 }
317
318 // Stops the client. All connections to peers are closed and all activity will
319 // come to a halt.
320 func (cl *Client) Close() {
321         cl.mu.Lock()
322         defer cl.mu.Unlock()
323         cl.closed.Set()
324         cl.eachDhtServer(func(s *dht.Server) { s.Close() })
325         cl.closeSockets()
326         for _, t := range cl.torrents {
327                 t.close()
328         }
329         for _, f := range cl.onClose {
330                 f()
331         }
332         cl.event.Broadcast()
333 }
334
335 func (cl *Client) ipBlockRange(ip net.IP) (r iplist.Range, blocked bool) {
336         if cl.ipBlockList == nil {
337                 return
338         }
339         return cl.ipBlockList.Lookup(ip)
340 }
341
342 func (cl *Client) ipIsBlocked(ip net.IP) bool {
343         _, blocked := cl.ipBlockRange(ip)
344         return blocked
345 }
346
347 func (cl *Client) waitAccept() {
348         for {
349                 for _, t := range cl.torrents {
350                         if t.wantConns() {
351                                 return
352                         }
353                 }
354                 if cl.closed.IsSet() {
355                         return
356                 }
357                 cl.event.Wait()
358         }
359 }
360
361 func (cl *Client) rejectAccepted(conn net.Conn) bool {
362         ra := conn.RemoteAddr()
363         rip := missinggo.AddrIP(ra)
364         if cl.config.DisableIPv4Peers && rip.To4() != nil {
365                 return true
366         }
367         if cl.config.DisableIPv4 && len(rip) == net.IPv4len {
368                 return true
369         }
370         if cl.config.DisableIPv6 && len(rip) == net.IPv6len && rip.To4() == nil {
371                 return true
372         }
373         return cl.badPeerIPPort(rip, missinggo.AddrPort(ra))
374 }
375
376 func (cl *Client) acceptConnections(l net.Listener) {
377         cl.mu.Lock()
378         defer cl.mu.Unlock()
379         for {
380                 cl.waitAccept()
381                 cl.mu.Unlock()
382                 conn, err := l.Accept()
383                 conn = pproffd.WrapNetConn(conn)
384                 cl.mu.Lock()
385                 if cl.closed.IsSet() {
386                         if conn != nil {
387                                 conn.Close()
388                         }
389                         return
390                 }
391                 if err != nil {
392                         log.Print(err)
393                         // I think something harsher should happen here? Our accept
394                         // routine just fucked off.
395                         return
396                 }
397                 log.Fmsg("accepted %s connection from %s", conn.RemoteAddr().Network(), conn.RemoteAddr()).AddValue(debugLogValue).Log(cl.logger)
398                 go torrent.Add(fmt.Sprintf("accepted conn remote IP len=%d", len(missinggo.AddrIP(conn.RemoteAddr()))), 1)
399                 go torrent.Add(fmt.Sprintf("accepted conn network=%s", conn.RemoteAddr().Network()), 1)
400                 go torrent.Add(fmt.Sprintf("accepted on %s listener", l.Addr().Network()), 1)
401                 if cl.rejectAccepted(conn) {
402                         go torrent.Add("rejected accepted connections", 1)
403                         conn.Close()
404                 } else {
405                         go cl.incomingConnection(conn)
406                 }
407         }
408 }
409
410 func (cl *Client) incomingConnection(nc net.Conn) {
411         defer nc.Close()
412         if tc, ok := nc.(*net.TCPConn); ok {
413                 tc.SetLinger(0)
414         }
415         c := cl.newConnection(nc)
416         c.Discovery = peerSourceIncoming
417         cl.runReceivedConn(c)
418 }
419
420 // Returns a handle to the given torrent, if it's present in the client.
421 func (cl *Client) Torrent(ih metainfo.Hash) (t *Torrent, ok bool) {
422         cl.mu.Lock()
423         defer cl.mu.Unlock()
424         t, ok = cl.torrents[ih]
425         return
426 }
427
428 func (cl *Client) torrent(ih metainfo.Hash) *Torrent {
429         return cl.torrents[ih]
430 }
431
432 type dialResult struct {
433         Conn net.Conn
434 }
435
436 func countDialResult(err error) {
437         if err == nil {
438                 successfulDials.Add(1)
439         } else {
440                 unsuccessfulDials.Add(1)
441         }
442 }
443
444 func reducedDialTimeout(minDialTimeout, max time.Duration, halfOpenLimit int, pendingPeers int) (ret time.Duration) {
445         ret = max / time.Duration((pendingPeers+halfOpenLimit)/halfOpenLimit)
446         if ret < minDialTimeout {
447                 ret = minDialTimeout
448         }
449         return
450 }
451
452 // Returns whether an address is known to connect to a client with our own ID.
453 func (cl *Client) dopplegangerAddr(addr string) bool {
454         _, ok := cl.dopplegangerAddrs[addr]
455         return ok
456 }
457
458 func (cl *Client) dialTCP(ctx context.Context, addr string) (c net.Conn, err error) {
459         d := net.Dialer{
460                 // Can't bind to the listen address, even though we intend to create an
461                 // endpoint pair that is distinct. Oh well.
462
463                 // LocalAddr: cl.tcpListener.Addr(),
464         }
465         c, err = d.DialContext(ctx, "tcp"+ipNetworkSuffix(!cl.config.DisableIPv4 && !cl.config.DisableIPv4Peers, !cl.config.DisableIPv6), addr)
466         countDialResult(err)
467         if err == nil {
468                 c.(*net.TCPConn).SetLinger(0)
469         }
470         c = pproffd.WrapNetConn(c)
471         return
472 }
473
474 func ipNetworkSuffix(allowIpv4, allowIpv6 bool) string {
475         switch {
476         case allowIpv4 && allowIpv6:
477                 return ""
478         case allowIpv4 && !allowIpv6:
479                 return "4"
480         case !allowIpv4 && allowIpv6:
481                 return "6"
482         default:
483                 panic("unhandled ip network combination")
484         }
485 }
486
487 func dialUTP(ctx context.Context, addr string, sock utpSocket) (c net.Conn, err error) {
488         return sock.DialContext(ctx, "", addr)
489 }
490
491 var allPeerNetworks = []string{"tcp4", "tcp6", "udp4", "udp6"}
492
493 func peerNetworkEnabled(network string, cfg Config) bool {
494         c := func(s string) bool {
495                 return strings.Contains(network, s)
496         }
497         if cfg.DisableUTP {
498                 if c("udp") || c("utp") {
499                         return false
500                 }
501         }
502         if cfg.DisableTCP && c("tcp") {
503                 return false
504         }
505         if cfg.DisableIPv6 && c("6") {
506                 return false
507         }
508         return true
509 }
510
511 // Returns a connection over UTP or TCP, whichever is first to connect.
512 func (cl *Client) dialFirst(ctx context.Context, addr string) net.Conn {
513         ctx, cancel := context.WithCancel(ctx)
514         // As soon as we return one connection, cancel the others.
515         defer cancel()
516         left := 0
517         resCh := make(chan dialResult, left)
518         dial := func(f func(_ context.Context, addr string) (net.Conn, error)) {
519                 left++
520                 go func() {
521                         c, err := f(ctx, addr)
522                         countDialResult(err)
523                         resCh <- dialResult{c}
524                 }()
525         }
526         func() {
527                 cl.mu.Lock()
528                 defer cl.mu.Unlock()
529                 cl.eachListener(func(s socket) bool {
530                         if peerNetworkEnabled(s.Addr().Network(), cl.config) {
531                                 dial(s.dial)
532                         }
533                         return true
534                 })
535         }()
536         var res dialResult
537         // Wait for a successful connection.
538         for ; left > 0 && res.Conn == nil; left-- {
539                 res = <-resCh
540         }
541         // There are still incompleted dials.
542         go func() {
543                 for ; left > 0; left-- {
544                         conn := (<-resCh).Conn
545                         if conn != nil {
546                                 conn.Close()
547                         }
548                 }
549         }()
550         if res.Conn != nil {
551                 go torrent.Add(fmt.Sprintf("network dialed first: %s", res.Conn.RemoteAddr().Network()), 1)
552         }
553         return res.Conn
554 }
555
556 func (cl *Client) noLongerHalfOpen(t *Torrent, addr string) {
557         if _, ok := t.halfOpen[addr]; !ok {
558                 panic("invariant broken")
559         }
560         delete(t.halfOpen, addr)
561         t.openNewConns()
562 }
563
564 // Performs initiator handshakes and returns a connection. Returns nil
565 // *connection if no connection for valid reasons.
566 func (cl *Client) handshakesConnection(ctx context.Context, nc net.Conn, t *Torrent, encryptHeader bool) (c *connection, err error) {
567         c = cl.newConnection(nc)
568         c.headerEncrypted = encryptHeader
569         ctx, cancel := context.WithTimeout(ctx, cl.config.HandshakesTimeout)
570         defer cancel()
571         dl, ok := ctx.Deadline()
572         if !ok {
573                 panic(ctx)
574         }
575         err = nc.SetDeadline(dl)
576         if err != nil {
577                 panic(err)
578         }
579         ok, err = cl.initiateHandshakes(c, t)
580         if !ok {
581                 c = nil
582         }
583         return
584 }
585
586 // Returns nil connection and nil error if no connection could be established
587 // for valid reasons.
588 func (cl *Client) establishOutgoingConnEx(t *Torrent, addr string, ctx context.Context, obfuscatedHeader bool) (c *connection, err error) {
589         nc := cl.dialFirst(ctx, addr)
590         if nc == nil {
591                 return
592         }
593         defer func() {
594                 if c == nil || err != nil {
595                         nc.Close()
596                 }
597         }()
598         return cl.handshakesConnection(ctx, nc, t, obfuscatedHeader)
599 }
600
601 // Returns nil connection and nil error if no connection could be established
602 // for valid reasons.
603 func (cl *Client) establishOutgoingConn(t *Torrent, addr string) (c *connection, err error) {
604         ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
605         defer cancel()
606         obfuscatedHeaderFirst := !cl.config.DisableEncryption && !cl.config.PreferNoEncryption
607         c, err = cl.establishOutgoingConnEx(t, addr, ctx, obfuscatedHeaderFirst)
608         if err != nil {
609                 return
610         }
611         if c != nil {
612                 go torrent.Add("initiated conn with preferred header obfuscation", 1)
613                 return
614         }
615         if cl.config.ForceEncryption {
616                 // We should have just tried with an obfuscated header. A plaintext
617                 // header can't result in an encrypted connection, so we're done.
618                 if !obfuscatedHeaderFirst {
619                         panic(cl.config.EncryptionPolicy)
620                 }
621                 return
622         }
623         // Try again with encryption if we didn't earlier, or without if we did.
624         c, err = cl.establishOutgoingConnEx(t, addr, ctx, !obfuscatedHeaderFirst)
625         if c != nil {
626                 go torrent.Add("initiated conn with fallback header obfuscation", 1)
627         }
628         return
629 }
630
631 // Called to dial out and run a connection. The addr we're given is already
632 // considered half-open.
633 func (cl *Client) outgoingConnection(t *Torrent, addr string, ps peerSource) {
634         c, err := cl.establishOutgoingConn(t, addr)
635         cl.mu.Lock()
636         defer cl.mu.Unlock()
637         // Don't release lock between here and addConnection, unless it's for
638         // failure.
639         cl.noLongerHalfOpen(t, addr)
640         if err != nil {
641                 if cl.config.Debug {
642                         log.Printf("error establishing outgoing connection: %s", err)
643                 }
644                 return
645         }
646         if c == nil {
647                 return
648         }
649         defer c.Close()
650         c.Discovery = ps
651         cl.runHandshookConn(c, t, true)
652 }
653
654 // The port number for incoming peer connections. 0 if the client isn't
655 // listening.
656 func (cl *Client) incomingPeerPort() int {
657         return cl.LocalPort()
658 }
659
660 func (cl *Client) initiateHandshakes(c *connection, t *Torrent) (ok bool, err error) {
661         if c.headerEncrypted {
662                 var rw io.ReadWriter
663                 rw, c.cryptoMethod, err = mse.InitiateHandshake(
664                         struct {
665                                 io.Reader
666                                 io.Writer
667                         }{c.r, c.w},
668                         t.infoHash[:],
669                         nil,
670                         func() mse.CryptoMethod {
671                                 switch {
672                                 case cl.config.ForceEncryption:
673                                         return mse.CryptoMethodRC4
674                                 case cl.config.DisableEncryption:
675                                         return mse.CryptoMethodPlaintext
676                                 default:
677                                         return mse.AllSupportedCrypto
678                                 }
679                         }(),
680                 )
681                 c.setRW(rw)
682                 if err != nil {
683                         return
684                 }
685         }
686         ih, ok, err := cl.connBTHandshake(c, &t.infoHash)
687         if ih != t.infoHash {
688                 ok = false
689         }
690         return
691 }
692
693 // Calls f with any secret keys.
694 func (cl *Client) forSkeys(f func([]byte) bool) {
695         cl.mu.Lock()
696         defer cl.mu.Unlock()
697         for ih := range cl.torrents {
698                 if !f(ih[:]) {
699                         break
700                 }
701         }
702 }
703
704 // Do encryption and bittorrent handshakes as receiver.
705 func (cl *Client) receiveHandshakes(c *connection) (t *Torrent, err error) {
706         var rw io.ReadWriter
707         rw, c.headerEncrypted, c.cryptoMethod, err = handleEncryption(c.rw(), cl.forSkeys, cl.config.EncryptionPolicy)
708         c.setRW(rw)
709         if err != nil {
710                 if err == mse.ErrNoSecretKeyMatch {
711                         err = nil
712                 }
713                 return
714         }
715         if cl.config.ForceEncryption && !c.headerEncrypted {
716                 err = errors.New("connection not encrypted")
717                 return
718         }
719         ih, ok, err := cl.connBTHandshake(c, nil)
720         if err != nil {
721                 err = fmt.Errorf("error during bt handshake: %s", err)
722                 return
723         }
724         if !ok {
725                 return
726         }
727         cl.mu.Lock()
728         t = cl.torrents[ih]
729         cl.mu.Unlock()
730         return
731 }
732
733 // Returns !ok if handshake failed for valid reasons.
734 func (cl *Client) connBTHandshake(c *connection, ih *metainfo.Hash) (ret metainfo.Hash, ok bool, err error) {
735         res, ok, err := handshake(c.rw(), ih, cl.peerID, cl.extensionBytes)
736         if err != nil || !ok {
737                 return
738         }
739         ret = res.Hash
740         c.PeerExtensionBytes = res.peerExtensionBytes
741         c.PeerID = res.PeerID
742         c.completedHandshake = time.Now()
743         return
744 }
745
746 func (cl *Client) runReceivedConn(c *connection) {
747         err := c.conn.SetDeadline(time.Now().Add(cl.config.HandshakesTimeout))
748         if err != nil {
749                 panic(err)
750         }
751         t, err := cl.receiveHandshakes(c)
752         if err != nil {
753                 if cl.config.Debug {
754                         log.Printf("error receiving handshakes: %s", err)
755                 }
756                 return
757         }
758         if t == nil {
759                 return
760         }
761         cl.mu.Lock()
762         defer cl.mu.Unlock()
763         cl.runHandshookConn(c, t, false)
764 }
765
766 func (cl *Client) runHandshookConn(c *connection, t *Torrent, outgoing bool) {
767         t.reconcileHandshakeStats(c)
768         if c.PeerID == cl.peerID {
769                 if outgoing {
770                         connsToSelf.Add(1)
771                         addr := c.conn.RemoteAddr().String()
772                         cl.dopplegangerAddrs[addr] = struct{}{}
773                 } else {
774                         // Because the remote address is not necessarily the same as its
775                         // client's torrent listen address, we won't record the remote address
776                         // as a doppleganger. Instead, the initiator can record *us* as the
777                         // doppleganger.
778                 }
779                 return
780         }
781         c.conn.SetWriteDeadline(time.Time{})
782         c.r = deadlineReader{c.conn, c.r}
783         completedHandshakeConnectionFlags.Add(c.connectionFlags(), 1)
784         if connIsIpv6(c.conn) {
785                 torrent.Add("completed handshake over ipv6", 1)
786         }
787         if !t.addConnection(c, outgoing) {
788                 return
789         }
790         defer t.dropConnection(c)
791         go c.writer(time.Minute)
792         cl.sendInitialMessages(c, t)
793         err := c.mainReadLoop()
794         if err != nil && cl.config.Debug {
795                 log.Printf("error during connection main read loop: %s", err)
796         }
797 }
798
799 func (cl *Client) sendInitialMessages(conn *connection, torrent *Torrent) {
800         func() {
801                 if conn.fastEnabled() {
802                         if torrent.haveAllPieces() {
803                                 conn.Post(pp.Message{Type: pp.HaveAll})
804                                 conn.sentHaves.AddRange(0, conn.t.NumPieces())
805                                 return
806                         } else if !torrent.haveAnyPieces() {
807                                 conn.Post(pp.Message{Type: pp.HaveNone})
808                                 conn.sentHaves.Clear()
809                                 return
810                         }
811                 }
812                 conn.PostBitfield()
813         }()
814         if conn.PeerExtensionBytes.SupportsExtended() && cl.extensionBytes.SupportsExtended() {
815                 conn.Post(pp.Message{
816                         Type:       pp.Extended,
817                         ExtendedID: pp.HandshakeExtendedID,
818                         ExtendedPayload: func() []byte {
819                                 d := map[string]interface{}{
820                                         "m": func() (ret map[string]int) {
821                                                 ret = make(map[string]int, 2)
822                                                 ret["ut_metadata"] = metadataExtendedId
823                                                 if !cl.config.DisablePEX {
824                                                         ret["ut_pex"] = pexExtendedId
825                                                 }
826                                                 return
827                                         }(),
828                                         "v": cl.config.ExtendedHandshakeClientVersion,
829                                         // No upload queue is implemented yet.
830                                         "reqq": 64,
831                                 }
832                                 if !cl.config.DisableEncryption {
833                                         d["e"] = 1
834                                 }
835                                 if torrent.metadataSizeKnown() {
836                                         d["metadata_size"] = torrent.metadataSize()
837                                 }
838                                 if p := cl.incomingPeerPort(); p != 0 {
839                                         d["p"] = p
840                                 }
841                                 yourip, err := addrCompactIP(conn.remoteAddr())
842                                 if err != nil {
843                                         log.Printf("error calculating yourip field value in extension handshake: %s", err)
844                                 } else {
845                                         d["yourip"] = yourip
846                                 }
847                                 // log.Printf("sending %v", d)
848                                 b, err := bencode.Marshal(d)
849                                 if err != nil {
850                                         panic(err)
851                                 }
852                                 return b
853                         }(),
854                 })
855         }
856         if conn.PeerExtensionBytes.SupportsDHT() && cl.extensionBytes.SupportsDHT() && cl.haveDhtServer() {
857                 conn.Post(pp.Message{
858                         Type: pp.Port,
859                         Port: cl.dhtPort(),
860                 })
861         }
862 }
863
864 func (cl *Client) dhtPort() (ret uint16) {
865         cl.eachDhtServer(func(s *dht.Server) {
866                 ret = uint16(missinggo.AddrPort(s.Addr()))
867         })
868         return
869 }
870
871 func (cl *Client) haveDhtServer() (ret bool) {
872         cl.eachDhtServer(func(_ *dht.Server) {
873                 ret = true
874         })
875         return
876 }
877
878 // Process incoming ut_metadata message.
879 func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *connection) error {
880         var d map[string]int
881         err := bencode.Unmarshal(payload, &d)
882         if _, ok := err.(bencode.ErrUnusedTrailingBytes); ok {
883         } else if err != nil {
884                 return fmt.Errorf("error unmarshalling bencode: %s", err)
885         }
886         msgType, ok := d["msg_type"]
887         if !ok {
888                 return errors.New("missing msg_type field")
889         }
890         piece := d["piece"]
891         switch msgType {
892         case pp.DataMetadataExtensionMsgType:
893                 if !c.requestedMetadataPiece(piece) {
894                         return fmt.Errorf("got unexpected piece %d", piece)
895                 }
896                 c.metadataRequests[piece] = false
897                 begin := len(payload) - metadataPieceSize(d["total_size"], piece)
898                 if begin < 0 || begin >= len(payload) {
899                         return fmt.Errorf("data has bad offset in payload: %d", begin)
900                 }
901                 t.saveMetadataPiece(piece, payload[begin:])
902                 c.stats.ChunksReadUseful++
903                 c.t.stats.ChunksReadUseful++
904                 c.lastUsefulChunkReceived = time.Now()
905                 return t.maybeCompleteMetadata()
906         case pp.RequestMetadataExtensionMsgType:
907                 if !t.haveMetadataPiece(piece) {
908                         c.Post(t.newMetadataExtensionMessage(c, pp.RejectMetadataExtensionMsgType, d["piece"], nil))
909                         return nil
910                 }
911                 start := (1 << 14) * piece
912                 c.Post(t.newMetadataExtensionMessage(c, pp.DataMetadataExtensionMsgType, piece, t.metadataBytes[start:start+t.metadataPieceSize(piece)]))
913                 return nil
914         case pp.RejectMetadataExtensionMsgType:
915                 return nil
916         default:
917                 return errors.New("unknown msg_type value")
918         }
919 }
920
921 func (cl *Client) badPeerIPPort(ip net.IP, port int) bool {
922         if port == 0 {
923                 return true
924         }
925         if cl.dopplegangerAddr(net.JoinHostPort(ip.String(), strconv.FormatInt(int64(port), 10))) {
926                 return true
927         }
928         if _, ok := cl.ipBlockRange(ip); ok {
929                 return true
930         }
931         if _, ok := cl.badPeerIPs[ip.String()]; ok {
932                 return true
933         }
934         return false
935 }
936
937 // Return a Torrent ready for insertion into a Client.
938 func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (t *Torrent) {
939         // use provided storage, if provided
940         storageClient := cl.defaultStorage
941         if specStorage != nil {
942                 storageClient = storage.NewClient(specStorage)
943         }
944
945         t = &Torrent{
946                 cl:       cl,
947                 infoHash: ih,
948                 peers: prioritizedPeers{
949                         om: btree.New(32),
950                         getPrio: func(p Peer) peerPriority {
951                                 return bep40PriorityIgnoreError(cl.publicAddr(p.IP), p.addr())
952                         },
953                 },
954                 conns: make(map[*connection]struct{}, 2*cl.config.EstablishedConnsPerTorrent),
955
956                 halfOpen:          make(map[string]Peer),
957                 pieceStateChanges: pubsub.NewPubSub(),
958
959                 storageOpener:       storageClient,
960                 maxEstablishedConns: cl.config.EstablishedConnsPerTorrent,
961
962                 networkingEnabled: true,
963                 requestStrategy:   2,
964                 metadataChanged: sync.Cond{
965                         L: &cl.mu,
966                 },
967         }
968         t.logger = cl.logger.Clone().AddValue(t)
969         t.setChunkSize(defaultChunkSize)
970         return
971 }
972
973 // A file-like handle to some torrent data resource.
974 type Handle interface {
975         io.Reader
976         io.Seeker
977         io.Closer
978         io.ReaderAt
979 }
980
981 func (cl *Client) AddTorrentInfoHash(infoHash metainfo.Hash) (t *Torrent, new bool) {
982         return cl.AddTorrentInfoHashWithStorage(infoHash, nil)
983 }
984
985 // Adds a torrent by InfoHash with a custom Storage implementation.
986 // If the torrent already exists then this Storage is ignored and the
987 // existing torrent returned with `new` set to `false`
988 func (cl *Client) AddTorrentInfoHashWithStorage(infoHash metainfo.Hash, specStorage storage.ClientImpl) (t *Torrent, new bool) {
989         cl.mu.Lock()
990         defer cl.mu.Unlock()
991         t, ok := cl.torrents[infoHash]
992         if ok {
993                 return
994         }
995         new = true
996         t = cl.newTorrent(infoHash, specStorage)
997         cl.eachDhtServer(func(s *dht.Server) {
998                 go t.dhtAnnouncer(s)
999         })
1000         cl.torrents[infoHash] = t
1001         t.updateWantPeersEvent()
1002         // Tickle Client.waitAccept, new torrent may want conns.
1003         cl.event.Broadcast()
1004         return
1005 }
1006
1007 // Add or merge a torrent spec. If the torrent is already present, the
1008 // trackers will be merged with the existing ones. If the Info isn't yet
1009 // known, it will be set. The display name is replaced if the new spec
1010 // provides one. Returns new if the torrent wasn't already in the client.
1011 // Note that any `Storage` defined on the spec will be ignored if the
1012 // torrent is already present (i.e. `new` return value is `true`)
1013 func (cl *Client) AddTorrentSpec(spec *TorrentSpec) (t *Torrent, new bool, err error) {
1014         t, new = cl.AddTorrentInfoHashWithStorage(spec.InfoHash, spec.Storage)
1015         if spec.DisplayName != "" {
1016                 t.SetDisplayName(spec.DisplayName)
1017         }
1018         if spec.InfoBytes != nil {
1019                 err = t.SetInfoBytes(spec.InfoBytes)
1020                 if err != nil {
1021                         return
1022                 }
1023         }
1024         cl.mu.Lock()
1025         defer cl.mu.Unlock()
1026         if spec.ChunkSize != 0 {
1027                 t.setChunkSize(pp.Integer(spec.ChunkSize))
1028         }
1029         t.addTrackers(spec.Trackers)
1030         t.maybeNewConns()
1031         return
1032 }
1033
1034 func (cl *Client) dropTorrent(infoHash metainfo.Hash) (err error) {
1035         t, ok := cl.torrents[infoHash]
1036         if !ok {
1037                 err = fmt.Errorf("no such torrent")
1038                 return
1039         }
1040         err = t.close()
1041         if err != nil {
1042                 panic(err)
1043         }
1044         delete(cl.torrents, infoHash)
1045         return
1046 }
1047
1048 func (cl *Client) allTorrentsCompleted() bool {
1049         for _, t := range cl.torrents {
1050                 if !t.haveInfo() {
1051                         return false
1052                 }
1053                 if !t.haveAllPieces() {
1054                         return false
1055                 }
1056         }
1057         return true
1058 }
1059
1060 // Returns true when all torrents are completely downloaded and false if the
1061 // client is stopped before that.
1062 func (cl *Client) WaitAll() bool {
1063         cl.mu.Lock()
1064         defer cl.mu.Unlock()
1065         for !cl.allTorrentsCompleted() {
1066                 if cl.closed.IsSet() {
1067                         return false
1068                 }
1069                 cl.event.Wait()
1070         }
1071         return true
1072 }
1073
1074 // Returns handles to all the torrents loaded in the Client.
1075 func (cl *Client) Torrents() []*Torrent {
1076         cl.mu.Lock()
1077         defer cl.mu.Unlock()
1078         return cl.torrentsAsSlice()
1079 }
1080
1081 func (cl *Client) torrentsAsSlice() (ret []*Torrent) {
1082         for _, t := range cl.torrents {
1083                 ret = append(ret, t)
1084         }
1085         return
1086 }
1087
1088 func (cl *Client) AddMagnet(uri string) (T *Torrent, err error) {
1089         spec, err := TorrentSpecFromMagnetURI(uri)
1090         if err != nil {
1091                 return
1092         }
1093         T, _, err = cl.AddTorrentSpec(spec)
1094         return
1095 }
1096
1097 func (cl *Client) AddTorrent(mi *metainfo.MetaInfo) (T *Torrent, err error) {
1098         T, _, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
1099         var ss []string
1100         slices.MakeInto(&ss, mi.Nodes)
1101         cl.AddDHTNodes(ss)
1102         return
1103 }
1104
1105 func (cl *Client) AddTorrentFromFile(filename string) (T *Torrent, err error) {
1106         mi, err := metainfo.LoadFromFile(filename)
1107         if err != nil {
1108                 return
1109         }
1110         return cl.AddTorrent(mi)
1111 }
1112
1113 func (cl *Client) DhtServers() []*dht.Server {
1114         return cl.dhtServers
1115 }
1116
1117 func (cl *Client) AddDHTNodes(nodes []string) {
1118         for _, n := range nodes {
1119                 hmp := missinggo.SplitHostMaybePort(n)
1120                 ip := net.ParseIP(hmp.Host)
1121                 if ip == nil {
1122                         log.Printf("won't add DHT node with bad IP: %q", hmp.Host)
1123                         continue
1124                 }
1125                 ni := krpc.NodeInfo{
1126                         Addr: krpc.NodeAddr{
1127                                 IP:   ip,
1128                                 Port: hmp.Port,
1129                         },
1130                 }
1131                 cl.eachDhtServer(func(s *dht.Server) {
1132                         s.AddNode(ni)
1133                 })
1134         }
1135 }
1136
1137 func (cl *Client) banPeerIP(ip net.IP) {
1138         if cl.badPeerIPs == nil {
1139                 cl.badPeerIPs = make(map[string]struct{})
1140         }
1141         cl.badPeerIPs[ip.String()] = struct{}{}
1142 }
1143
1144 func (cl *Client) newConnection(nc net.Conn) (c *connection) {
1145         c = &connection{
1146                 conn:            nc,
1147                 Choked:          true,
1148                 PeerChoked:      true,
1149                 PeerMaxRequests: 250,
1150                 writeBuffer:     new(bytes.Buffer),
1151         }
1152         c.writerCond.L = &cl.mu
1153         c.setRW(connStatsReadWriter{nc, &cl.mu, c})
1154         c.r = &rateLimitedReader{
1155                 l: cl.downloadLimit,
1156                 r: c.r,
1157         }
1158         return
1159 }
1160
1161 func (cl *Client) onDHTAnnouncePeer(ih metainfo.Hash, p dht.Peer) {
1162         cl.mu.Lock()
1163         defer cl.mu.Unlock()
1164         t := cl.torrent(ih)
1165         if t == nil {
1166                 return
1167         }
1168         t.addPeers([]Peer{{
1169                 IP:     p.IP,
1170                 Port:   p.Port,
1171                 Source: peerSourceDHTAnnouncePeer,
1172         }})
1173 }
1174
1175 func firstNotNil(ips ...net.IP) net.IP {
1176         for _, ip := range ips {
1177                 if ip != nil {
1178                         return ip
1179                 }
1180         }
1181         return nil
1182 }
1183
1184 func (cl *Client) eachListener(f func(socket) bool) {
1185         for _, s := range cl.conns {
1186                 if !f(s) {
1187                         break
1188                 }
1189         }
1190 }
1191
1192 func (cl *Client) findListener(f func(net.Listener) bool) (ret net.Listener) {
1193         cl.eachListener(func(l socket) bool {
1194                 ret = l
1195                 return !f(l)
1196         })
1197         return
1198 }
1199
1200 func (cl *Client) publicIp(peer net.IP) net.IP {
1201         // TODO: Use BEP 10 to determine how peers are seeing us.
1202         if peer.To4() != nil {
1203                 return firstNotNil(
1204                         cl.config.PublicIp4,
1205                         cl.findListenerIp(func(ip net.IP) bool { return ip.To4() != nil }),
1206                 )
1207         } else {
1208                 return firstNotNil(
1209                         cl.config.PublicIp6,
1210                         cl.findListenerIp(func(ip net.IP) bool { return ip.To4() == nil }),
1211                 )
1212         }
1213 }
1214
1215 func (cl *Client) findListenerIp(f func(net.IP) bool) net.IP {
1216         return missinggo.AddrIP(cl.findListener(func(l net.Listener) bool {
1217                 return f(missinggo.AddrIP(l.Addr()))
1218         }).Addr())
1219 }
1220
1221 // Our IP as a peer should see it.
1222 func (cl *Client) publicAddr(peer net.IP) ipPort {
1223         return ipPort{cl.publicIp(peer), uint16(cl.incomingPeerPort())}
1224 }
1225
1226 func (cl *Client) ListenAddrs() (ret []net.Addr) {
1227         cl.eachListener(func(l socket) bool {
1228                 ret = append(ret, l.Addr())
1229                 return true
1230         })
1231         return
1232 }