]> Sergey Matveev's repositories - btrtrc.git/blob - client.go
Law of Demeter Client.mu
[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/bitmap"
22         "github.com/anacrolix/missinggo/perf"
23         "github.com/anacrolix/missinggo/pproffd"
24         "github.com/anacrolix/missinggo/pubsub"
25         "github.com/anacrolix/missinggo/slices"
26         "github.com/anacrolix/sync"
27         "github.com/davecgh/go-spew/spew"
28         "github.com/dustin/go-humanize"
29         "github.com/google/btree"
30
31         "github.com/anacrolix/torrent/bencode"
32         "github.com/anacrolix/torrent/iplist"
33         "github.com/anacrolix/torrent/metainfo"
34         "github.com/anacrolix/torrent/mse"
35         pp "github.com/anacrolix/torrent/peer_protocol"
36         "github.com/anacrolix/torrent/storage"
37 )
38
39 // Clients contain zero or more Torrents. A Client manages a blocklist, the
40 // TCP/UDP protocol ports, and DHT as desired.
41 type Client struct {
42         // An aggregate of stats over all connections. First in struct to ensure
43         // 64-bit alignment of fields. See #262.
44         stats ConnStats
45
46         _mu    sync.RWMutex
47         event  sync.Cond
48         closed missinggo.Event
49
50         config *ClientConfig
51         logger *log.Logger
52
53         peerID         PeerID
54         defaultStorage *storage.Client
55         onClose        []func()
56         conns          []socket
57         dhtServers     []*dht.Server
58         ipBlockList    iplist.Ranger
59         // Our BitTorrent protocol extension bytes, sent in our BT handshakes.
60         extensionBytes pp.PeerExtensionBits
61
62         // Set of addresses that have our client ID. This intentionally will
63         // include ourselves if we end up trying to connect to our own address
64         // through legitimate channels.
65         dopplegangerAddrs map[string]struct{}
66         badPeerIPs        map[string]struct{}
67         torrents          map[InfoHash]*Torrent
68
69         acceptLimiter map[ipStr]int
70 }
71
72 type ipStr string
73
74 func (cl *Client) BadPeerIPs() []string {
75         cl.rLock()
76         defer cl.rUnlock()
77         return cl.badPeerIPsLocked()
78 }
79
80 func (cl *Client) badPeerIPsLocked() []string {
81         return slices.FromMapKeys(cl.badPeerIPs).([]string)
82 }
83
84 func (cl *Client) PeerID() PeerID {
85         return cl.peerID
86 }
87
88 type torrentAddr string
89
90 func (torrentAddr) Network() string { return "" }
91
92 func (me torrentAddr) String() string { return string(me) }
93
94 func (cl *Client) LocalPort() (port int) {
95         cl.eachListener(func(l socket) bool {
96                 _port := missinggo.AddrPort(l.Addr())
97                 if _port == 0 {
98                         panic(l)
99                 }
100                 if port == 0 {
101                         port = _port
102                 } else if port != _port {
103                         panic("mismatched ports")
104                 }
105                 return true
106         })
107         return
108 }
109
110 func writeDhtServerStatus(w io.Writer, s *dht.Server) {
111         dhtStats := s.Stats()
112         fmt.Fprintf(w, "\t# Nodes: %d (%d good, %d banned)\n", dhtStats.Nodes, dhtStats.GoodNodes, dhtStats.BadNodes)
113         fmt.Fprintf(w, "\tServer ID: %x\n", s.ID())
114         fmt.Fprintf(w, "\tAnnounces: %d\n", dhtStats.SuccessfulOutboundAnnouncePeerQueries)
115         fmt.Fprintf(w, "\tOutstanding transactions: %d\n", dhtStats.OutstandingTransactions)
116 }
117
118 // Writes out a human readable status of the client, such as for writing to a
119 // HTTP status page.
120 func (cl *Client) WriteStatus(_w io.Writer) {
121         cl.rLock()
122         defer cl.rUnlock()
123         w := bufio.NewWriter(_w)
124         defer w.Flush()
125         fmt.Fprintf(w, "Listen port: %d\n", cl.LocalPort())
126         fmt.Fprintf(w, "Peer ID: %+q\n", cl.PeerID())
127         fmt.Fprintf(w, "Announce key: %x\n", cl.announceKey())
128         fmt.Fprintf(w, "Banned IPs: %d\n", len(cl.badPeerIPsLocked()))
129         cl.eachDhtServer(func(s *dht.Server) {
130                 fmt.Fprintf(w, "%s DHT server at %s:\n", s.Addr().Network(), s.Addr().String())
131                 writeDhtServerStatus(w, s)
132         })
133         spew.Fdump(w, cl.stats)
134         fmt.Fprintf(w, "# Torrents: %d\n", len(cl.torrentsAsSlice()))
135         fmt.Fprintln(w)
136         for _, t := range slices.Sort(cl.torrentsAsSlice(), func(l, r *Torrent) bool {
137                 return l.InfoHash().AsString() < r.InfoHash().AsString()
138         }).([]*Torrent) {
139                 if t.name() == "" {
140                         fmt.Fprint(w, "<unknown name>")
141                 } else {
142                         fmt.Fprint(w, t.name())
143                 }
144                 fmt.Fprint(w, "\n")
145                 if t.info != nil {
146                         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())))
147                 } else {
148                         w.WriteString("<missing metainfo>")
149                 }
150                 fmt.Fprint(w, "\n")
151                 t.writeStatus(w)
152                 fmt.Fprintln(w)
153         }
154 }
155
156 const debugLogValue = "debug"
157
158 func (cl *Client) debugLogFilter(m *log.Msg) bool {
159         if !cl.config.Debug {
160                 _, ok := m.Values()[debugLogValue]
161                 return !ok
162         }
163         return true
164 }
165
166 func (cl *Client) initLogger() {
167         cl.logger = log.Default.Clone().AddValue(cl).AddFilter(log.NewFilter(cl.debugLogFilter))
168 }
169
170 func (cl *Client) announceKey() int32 {
171         return int32(binary.BigEndian.Uint32(cl.peerID[16:20]))
172 }
173
174 func NewClient(cfg *ClientConfig) (cl *Client, err error) {
175         if cfg == nil {
176                 cfg = NewDefaultClientConfig()
177         }
178         defer func() {
179                 if err != nil {
180                         cl = nil
181                 }
182         }()
183         cl = &Client{
184                 config:            cfg,
185                 dopplegangerAddrs: make(map[string]struct{}),
186                 torrents:          make(map[metainfo.Hash]*Torrent),
187         }
188         go cl.acceptLimitClearer()
189         cl.initLogger()
190         defer func() {
191                 if err == nil {
192                         return
193                 }
194                 cl.Close()
195         }()
196         cl.extensionBytes = defaultPeerExtensionBytes()
197         cl.event.L = cl.locker()
198         storageImpl := cfg.DefaultStorage
199         if storageImpl == nil {
200                 // We'd use mmap but HFS+ doesn't support sparse files.
201                 storageImpl = storage.NewFile(cfg.DataDir)
202                 cl.onClose = append(cl.onClose, func() {
203                         if err := storageImpl.Close(); err != nil {
204                                 log.Printf("error closing default storage: %s", err)
205                         }
206                 })
207         }
208         cl.defaultStorage = storage.NewClient(storageImpl)
209         if cfg.IPBlocklist != nil {
210                 cl.ipBlockList = cfg.IPBlocklist
211         }
212
213         if cfg.PeerID != "" {
214                 missinggo.CopyExact(&cl.peerID, cfg.PeerID)
215         } else {
216                 o := copy(cl.peerID[:], cfg.Bep20)
217                 _, err = rand.Read(cl.peerID[o:])
218                 if err != nil {
219                         panic("error generating peer id")
220                 }
221         }
222
223         cl.conns, err = listenAll(cl.enabledPeerNetworks(), cl.config.ListenHost, cl.config.ListenPort, cl.config.ProxyURL)
224         if err != nil {
225                 return
226         }
227         // Check for panics.
228         cl.LocalPort()
229
230         for _, s := range cl.conns {
231                 if peerNetworkEnabled(s.Addr().Network(), cl.config) {
232                         go cl.acceptConnections(s)
233                 }
234         }
235
236         go cl.forwardPort()
237         if !cfg.NoDHT {
238                 for _, s := range cl.conns {
239                         if pc, ok := s.(net.PacketConn); ok {
240                                 ds, err := cl.newDhtServer(pc)
241                                 if err != nil {
242                                         panic(err)
243                                 }
244                                 cl.dhtServers = append(cl.dhtServers, ds)
245                         }
246                 }
247         }
248
249         return
250 }
251
252 func (cl *Client) enabledPeerNetworks() (ns []string) {
253         for _, n := range allPeerNetworks {
254                 if peerNetworkEnabled(n, cl.config) {
255                         ns = append(ns, n)
256                 }
257         }
258         return
259 }
260
261 func (cl *Client) newDhtServer(conn net.PacketConn) (s *dht.Server, err error) {
262         cfg := dht.ServerConfig{
263                 IPBlocklist:    cl.ipBlockList,
264                 Conn:           conn,
265                 OnAnnouncePeer: cl.onDHTAnnouncePeer,
266                 PublicIP: func() net.IP {
267                         if connIsIpv6(conn) && cl.config.PublicIp6 != nil {
268                                 return cl.config.PublicIp6
269                         }
270                         return cl.config.PublicIp4
271                 }(),
272                 StartingNodes: cl.config.DhtStartingNodes,
273         }
274         s, err = dht.NewServer(&cfg)
275         if err == nil {
276                 go func() {
277                         if _, err := s.Bootstrap(); err != nil {
278                                 log.Printf("error bootstrapping dht: %s", err)
279                         }
280                 }()
281         }
282         return
283 }
284
285 func firstNonEmptyString(ss ...string) string {
286         for _, s := range ss {
287                 if s != "" {
288                         return s
289                 }
290         }
291         return ""
292 }
293
294 func (cl *Client) Closed() <-chan struct{} {
295         cl.lock()
296         defer cl.unlock()
297         return cl.closed.C()
298 }
299
300 func (cl *Client) eachDhtServer(f func(*dht.Server)) {
301         for _, ds := range cl.dhtServers {
302                 f(ds)
303         }
304 }
305
306 func (cl *Client) closeSockets() {
307         cl.eachListener(func(l socket) bool {
308                 l.Close()
309                 return true
310         })
311         cl.conns = nil
312 }
313
314 // Stops the client. All connections to peers are closed and all activity will
315 // come to a halt.
316 func (cl *Client) Close() {
317         cl.lock()
318         defer cl.unlock()
319         cl.closed.Set()
320         cl.eachDhtServer(func(s *dht.Server) { s.Close() })
321         cl.closeSockets()
322         for _, t := range cl.torrents {
323                 t.close()
324         }
325         for _, f := range cl.onClose {
326                 f()
327         }
328         cl.event.Broadcast()
329 }
330
331 func (cl *Client) ipBlockRange(ip net.IP) (r iplist.Range, blocked bool) {
332         if cl.ipBlockList == nil {
333                 return
334         }
335         return cl.ipBlockList.Lookup(ip)
336 }
337
338 func (cl *Client) ipIsBlocked(ip net.IP) bool {
339         _, blocked := cl.ipBlockRange(ip)
340         return blocked
341 }
342
343 func (cl *Client) waitAccept() {
344         for {
345                 for _, t := range cl.torrents {
346                         if t.wantConns() {
347                                 return
348                         }
349                 }
350                 if cl.closed.IsSet() {
351                         return
352                 }
353                 cl.event.Wait()
354         }
355 }
356
357 func (cl *Client) rejectAccepted(conn net.Conn) bool {
358         ra := conn.RemoteAddr()
359         rip := missinggo.AddrIP(ra)
360         if cl.config.DisableIPv4Peers && rip.To4() != nil {
361                 return true
362         }
363         if cl.config.DisableIPv4 && len(rip) == net.IPv4len {
364                 return true
365         }
366         if cl.config.DisableIPv6 && len(rip) == net.IPv6len && rip.To4() == nil {
367                 return true
368         }
369         if cl.rateLimitAccept(rip) {
370                 return true
371         }
372         return cl.badPeerIPPort(rip, missinggo.AddrPort(ra))
373 }
374
375 func (cl *Client) acceptConnections(l net.Listener) {
376         for {
377                 conn, err := l.Accept()
378                 conn = pproffd.WrapNetConn(conn)
379                 cl.rLock()
380                 closed := cl.closed.IsSet()
381                 reject := false
382                 if conn != nil {
383                         reject = cl.rejectAccepted(conn)
384                 }
385                 cl.rUnlock()
386                 if closed {
387                         if conn != nil {
388                                 conn.Close()
389                         }
390                         return
391                 }
392                 if err != nil {
393                         log.Printf("error accepting connection: %s", err)
394                 }
395                 go func() {
396                         if reject {
397                                 torrent.Add("rejected accepted connections", 1)
398                                 conn.Close()
399                         } else {
400                                 go cl.incomingConnection(conn)
401                         }
402                         log.Fmsg("accepted %s connection from %s", conn.RemoteAddr().Network(), conn.RemoteAddr()).AddValue(debugLogValue).Log(cl.logger)
403                         torrent.Add(fmt.Sprintf("accepted conn remote IP len=%d", len(missinggo.AddrIP(conn.RemoteAddr()))), 1)
404                         torrent.Add(fmt.Sprintf("accepted conn network=%s", conn.RemoteAddr().Network()), 1)
405                         torrent.Add(fmt.Sprintf("accepted on %s listener", l.Addr().Network()), 1)
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, false)
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.lock()
423         defer cl.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                 torrent.Add("successful dials", 1)
439         } else {
440                 torrent.Add("unsuccessful dials", 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 ipNetworkSuffix(allowIpv4, allowIpv6 bool) string {
459         switch {
460         case allowIpv4 && allowIpv6:
461                 return ""
462         case allowIpv4 && !allowIpv6:
463                 return "4"
464         case !allowIpv4 && allowIpv6:
465                 return "6"
466         default:
467                 panic("unhandled ip network combination")
468         }
469 }
470
471 func dialUTP(ctx context.Context, addr string, sock utpSocket) (c net.Conn, err error) {
472         return sock.DialContext(ctx, "", addr)
473 }
474
475 var allPeerNetworks = []string{"tcp4", "tcp6", "udp4", "udp6"}
476
477 func peerNetworkEnabled(network string, cfg *ClientConfig) bool {
478         c := func(s string) bool {
479                 return strings.Contains(network, s)
480         }
481         if cfg.DisableUTP {
482                 if c("udp") || c("utp") {
483                         return false
484                 }
485         }
486         if cfg.DisableTCP && c("tcp") {
487                 return false
488         }
489         if cfg.DisableIPv6 && c("6") {
490                 return false
491         }
492         return true
493 }
494
495 // Returns a connection over UTP or TCP, whichever is first to connect.
496 func (cl *Client) dialFirst(ctx context.Context, addr string) net.Conn {
497         ctx, cancel := context.WithCancel(ctx)
498         // As soon as we return one connection, cancel the others.
499         defer cancel()
500         left := 0
501         resCh := make(chan dialResult, left)
502         dial := func(f func(_ context.Context, addr string) (net.Conn, error)) {
503                 left++
504                 go func() {
505                         c, err := f(ctx, addr)
506                         // This is a bit optimistic, but it looks non-trivial to thread
507                         // this through the proxy code. Set it now in case we close the
508                         // connection forthwith.
509                         if tc, ok := c.(*net.TCPConn); ok {
510                                 tc.SetLinger(0)
511                         }
512                         countDialResult(err)
513                         resCh <- dialResult{c}
514                 }()
515         }
516         func() {
517                 cl.lock()
518                 defer cl.unlock()
519                 cl.eachListener(func(s socket) bool {
520                         if peerNetworkEnabled(s.Addr().Network(), cl.config) {
521                                 dial(s.dial)
522                         }
523                         return true
524                 })
525         }()
526         var res dialResult
527         // Wait for a successful connection.
528         func() {
529                 defer perf.ScopeTimer()()
530                 for ; left > 0 && res.Conn == nil; left-- {
531                         res = <-resCh
532                 }
533         }()
534         // There are still incompleted dials.
535         go func() {
536                 for ; left > 0; left-- {
537                         conn := (<-resCh).Conn
538                         if conn != nil {
539                                 conn.Close()
540                         }
541                 }
542         }()
543         if res.Conn != nil {
544                 go torrent.Add(fmt.Sprintf("network dialed first: %s", res.Conn.RemoteAddr().Network()), 1)
545         }
546         return res.Conn
547 }
548
549 func (cl *Client) noLongerHalfOpen(t *Torrent, addr string) {
550         if _, ok := t.halfOpen[addr]; !ok {
551                 panic("invariant broken")
552         }
553         delete(t.halfOpen, addr)
554         t.openNewConns()
555 }
556
557 // Performs initiator handshakes and returns a connection. Returns nil
558 // *connection if no connection for valid reasons.
559 func (cl *Client) handshakesConnection(ctx context.Context, nc net.Conn, t *Torrent, encryptHeader bool) (c *connection, err error) {
560         c = cl.newConnection(nc, true)
561         c.headerEncrypted = encryptHeader
562         ctx, cancel := context.WithTimeout(ctx, cl.config.HandshakesTimeout)
563         defer cancel()
564         dl, ok := ctx.Deadline()
565         if !ok {
566                 panic(ctx)
567         }
568         err = nc.SetDeadline(dl)
569         if err != nil {
570                 panic(err)
571         }
572         ok, err = cl.initiateHandshakes(c, t)
573         if !ok {
574                 c = nil
575         }
576         return
577 }
578
579 // Returns nil connection and nil error if no connection could be established
580 // for valid reasons.
581 func (cl *Client) establishOutgoingConnEx(t *Torrent, addr string, ctx context.Context, obfuscatedHeader bool) (c *connection, err error) {
582         nc := cl.dialFirst(ctx, addr)
583         if nc == nil {
584                 return
585         }
586         defer func() {
587                 if c == nil || err != nil {
588                         nc.Close()
589                 }
590         }()
591         return cl.handshakesConnection(ctx, nc, t, obfuscatedHeader)
592 }
593
594 // Returns nil connection and nil error if no connection could be established
595 // for valid reasons.
596 func (cl *Client) establishOutgoingConn(t *Torrent, addr string) (c *connection, err error) {
597         ctx, cancel := context.WithTimeout(context.Background(), func() time.Duration {
598                 cl.rLock()
599                 defer cl.rUnlock()
600                 return t.dialTimeout()
601         }())
602         defer cancel()
603         obfuscatedHeaderFirst := !cl.config.DisableEncryption && !cl.config.PreferNoEncryption
604         c, err = cl.establishOutgoingConnEx(t, addr, ctx, obfuscatedHeaderFirst)
605         if err != nil {
606                 return
607         }
608         if c != nil {
609                 torrent.Add("initiated conn with preferred header obfuscation", 1)
610                 return
611         }
612         if cl.config.ForceEncryption {
613                 // We should have just tried with an obfuscated header. A plaintext
614                 // header can't result in an encrypted connection, so we're done.
615                 if !obfuscatedHeaderFirst {
616                         panic(cl.config.EncryptionPolicy)
617                 }
618                 return
619         }
620         // Try again with encryption if we didn't earlier, or without if we did.
621         c, err = cl.establishOutgoingConnEx(t, addr, ctx, !obfuscatedHeaderFirst)
622         if c != nil {
623                 torrent.Add("initiated conn with fallback header obfuscation", 1)
624         }
625         return
626 }
627
628 // Called to dial out and run a connection. The addr we're given is already
629 // considered half-open.
630 func (cl *Client) outgoingConnection(t *Torrent, addr string, ps peerSource) {
631         c, err := cl.establishOutgoingConn(t, addr)
632         cl.lock()
633         defer cl.unlock()
634         // Don't release lock between here and addConnection, unless it's for
635         // failure.
636         cl.noLongerHalfOpen(t, addr)
637         if err != nil {
638                 if cl.config.Debug {
639                         log.Printf("error establishing outgoing connection: %s", err)
640                 }
641                 return
642         }
643         if c == nil {
644                 return
645         }
646         defer c.Close()
647         c.Discovery = ps
648         cl.runHandshookConn(c, t)
649 }
650
651 // The port number for incoming peer connections. 0 if the client isn't
652 // listening.
653 func (cl *Client) incomingPeerPort() int {
654         return cl.LocalPort()
655 }
656
657 func (cl *Client) initiateHandshakes(c *connection, t *Torrent) (ok bool, err error) {
658         if c.headerEncrypted {
659                 var rw io.ReadWriter
660                 rw, c.cryptoMethod, err = mse.InitiateHandshake(
661                         struct {
662                                 io.Reader
663                                 io.Writer
664                         }{c.r, c.w},
665                         t.infoHash[:],
666                         nil,
667                         func() mse.CryptoMethod {
668                                 switch {
669                                 case cl.config.ForceEncryption:
670                                         return mse.CryptoMethodRC4
671                                 case cl.config.DisableEncryption:
672                                         return mse.CryptoMethodPlaintext
673                                 default:
674                                         return mse.AllSupportedCrypto
675                                 }
676                         }(),
677                 )
678                 c.setRW(rw)
679                 if err != nil {
680                         return
681                 }
682         }
683         ih, ok, err := cl.connBTHandshake(c, &t.infoHash)
684         if ih != t.infoHash {
685                 ok = false
686         }
687         return
688 }
689
690 // Calls f with any secret keys.
691 func (cl *Client) forSkeys(f func([]byte) bool) {
692         cl.lock()
693         defer cl.unlock()
694         for ih := range cl.torrents {
695                 if !f(ih[:]) {
696                         break
697                 }
698         }
699 }
700
701 // Do encryption and bittorrent handshakes as receiver.
702 func (cl *Client) receiveHandshakes(c *connection) (t *Torrent, err error) {
703         defer perf.ScopeTimerErr(&err)()
704         var rw io.ReadWriter
705         rw, c.headerEncrypted, c.cryptoMethod, err = handleEncryption(c.rw(), cl.forSkeys, cl.config.EncryptionPolicy)
706         c.setRW(rw)
707         if err != nil {
708                 if err == mse.ErrNoSecretKeyMatch {
709                         err = nil
710                 }
711                 return
712         }
713         if cl.config.ForceEncryption && !c.headerEncrypted {
714                 err = errors.New("connection not encrypted")
715                 return
716         }
717         ih, ok, err := cl.connBTHandshake(c, nil)
718         if err != nil {
719                 err = fmt.Errorf("error during bt handshake: %s", err)
720                 return
721         }
722         if !ok {
723                 return
724         }
725         cl.lock()
726         t = cl.torrents[ih]
727         cl.unlock()
728         return
729 }
730
731 // Returns !ok if handshake failed for valid reasons.
732 func (cl *Client) connBTHandshake(c *connection, ih *metainfo.Hash) (ret metainfo.Hash, ok bool, err error) {
733         res, ok, err := pp.Handshake(c.rw(), ih, cl.peerID, cl.extensionBytes)
734         if err != nil || !ok {
735                 return
736         }
737         ret = res.Hash
738         c.PeerExtensionBytes = res.PeerExtensionBits
739         c.PeerID = res.PeerID
740         c.completedHandshake = time.Now()
741         return
742 }
743
744 func (cl *Client) runReceivedConn(c *connection) {
745         err := c.conn.SetDeadline(time.Now().Add(cl.config.HandshakesTimeout))
746         if err != nil {
747                 panic(err)
748         }
749         t, err := cl.receiveHandshakes(c)
750         if err != nil {
751                 log.Fmsg(
752                         "error receiving handshakes: %s", err,
753                 ).AddValue(
754                         debugLogValue,
755                 ).Add(
756                         "network", c.remoteAddr().Network(),
757                 ).Log(cl.logger)
758                 torrent.Add("error receiving handshake", 1)
759                 cl.lock()
760                 cl.onBadAccept(c.remoteAddr())
761                 cl.unlock()
762                 return
763         }
764         if t == nil {
765                 torrent.Add("received handshake for unloaded torrent", 1)
766                 cl.lock()
767                 cl.onBadAccept(c.remoteAddr())
768                 cl.unlock()
769                 return
770         }
771         torrent.Add("received handshake for loaded torrent", 1)
772         cl.lock()
773         defer cl.unlock()
774         cl.runHandshookConn(c, t)
775 }
776
777 func (cl *Client) runHandshookConn(c *connection, t *Torrent) {
778         c.setTorrent(t)
779         if c.PeerID == cl.peerID {
780                 if c.outgoing {
781                         connsToSelf.Add(1)
782                         addr := c.conn.RemoteAddr().String()
783                         cl.dopplegangerAddrs[addr] = struct{}{}
784                 } else {
785                         // Because the remote address is not necessarily the same as its
786                         // client's torrent listen address, we won't record the remote address
787                         // as a doppleganger. Instead, the initiator can record *us* as the
788                         // doppleganger.
789                 }
790                 return
791         }
792         c.conn.SetWriteDeadline(time.Time{})
793         c.r = deadlineReader{c.conn, c.r}
794         completedHandshakeConnectionFlags.Add(c.connectionFlags(), 1)
795         if connIsIpv6(c.conn) {
796                 torrent.Add("completed handshake over ipv6", 1)
797         }
798         if err := t.addConnection(c); err != nil {
799                 log.Fmsg("error adding connection: %s", err).AddValues(c, debugLogValue).Log(t.logger)
800                 return
801         }
802         defer t.dropConnection(c)
803         go c.writer(time.Minute)
804         cl.sendInitialMessages(c, t)
805         err := c.mainReadLoop()
806         if err != nil && cl.config.Debug {
807                 log.Printf("error during connection main read loop: %s", err)
808         }
809 }
810
811 // See the order given in Transmission's tr_peerMsgsNew.
812 func (cl *Client) sendInitialMessages(conn *connection, torrent *Torrent) {
813         if conn.PeerExtensionBytes.SupportsExtended() && cl.extensionBytes.SupportsExtended() {
814                 conn.Post(pp.Message{
815                         Type:       pp.Extended,
816                         ExtendedID: pp.HandshakeExtendedID,
817                         ExtendedPayload: func() []byte {
818                                 msg := pp.ExtendedHandshakeMessage{
819                                         M: map[pp.ExtensionName]pp.ExtensionNumber{
820                                                 pp.ExtensionNameMetadata: metadataExtendedId,
821                                         },
822                                         V:            cl.config.ExtendedHandshakeClientVersion,
823                                         Reqq:         64, // TODO: Really?
824                                         YourIp:       pp.CompactIp(missinggo.AddrIP(conn.remoteAddr())),
825                                         Encryption:   !cl.config.DisableEncryption,
826                                         Port:         cl.incomingPeerPort(),
827                                         MetadataSize: torrent.metadataSize(),
828                                         // TODO: We can figured these out specific to the socket
829                                         // used.
830                                         Ipv4: pp.CompactIp(cl.config.PublicIp4.To4()),
831                                         Ipv6: cl.config.PublicIp6.To16(),
832                                 }
833                                 if !cl.config.DisablePEX {
834                                         msg.M[pp.ExtensionNamePex] = pexExtendedId
835                                 }
836                                 return bencode.MustMarshal(msg)
837                         }(),
838                 })
839         }
840         func() {
841                 if conn.fastEnabled() {
842                         if torrent.haveAllPieces() {
843                                 conn.Post(pp.Message{Type: pp.HaveAll})
844                                 conn.sentHaves.AddRange(0, bitmap.BitIndex(conn.t.NumPieces()))
845                                 return
846                         } else if !torrent.haveAnyPieces() {
847                                 conn.Post(pp.Message{Type: pp.HaveNone})
848                                 conn.sentHaves.Clear()
849                                 return
850                         }
851                 }
852                 conn.PostBitfield()
853         }()
854         if conn.PeerExtensionBytes.SupportsDHT() && cl.extensionBytes.SupportsDHT() && cl.haveDhtServer() {
855                 conn.Post(pp.Message{
856                         Type: pp.Port,
857                         Port: cl.dhtPort(),
858                 })
859         }
860 }
861
862 func (cl *Client) dhtPort() (ret uint16) {
863         cl.eachDhtServer(func(s *dht.Server) {
864                 ret = uint16(missinggo.AddrPort(s.Addr()))
865         })
866         return
867 }
868
869 func (cl *Client) haveDhtServer() (ret bool) {
870         cl.eachDhtServer(func(_ *dht.Server) {
871                 ret = true
872         })
873         return
874 }
875
876 // Process incoming ut_metadata message.
877 func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *connection) error {
878         var d map[string]int
879         err := bencode.Unmarshal(payload, &d)
880         if _, ok := err.(bencode.ErrUnusedTrailingBytes); ok {
881         } else if err != nil {
882                 return fmt.Errorf("error unmarshalling bencode: %s", err)
883         }
884         msgType, ok := d["msg_type"]
885         if !ok {
886                 return errors.New("missing msg_type field")
887         }
888         piece := d["piece"]
889         switch msgType {
890         case pp.DataMetadataExtensionMsgType:
891                 c.allStats(add(1, func(cs *ConnStats) *Count { return &cs.MetadataChunksRead }))
892                 if !c.requestedMetadataPiece(piece) {
893                         return fmt.Errorf("got unexpected piece %d", piece)
894                 }
895                 c.metadataRequests[piece] = false
896                 begin := len(payload) - metadataPieceSize(d["total_size"], piece)
897                 if begin < 0 || begin >= len(payload) {
898                         return fmt.Errorf("data has bad offset in payload: %d", begin)
899                 }
900                 t.saveMetadataPiece(piece, payload[begin:])
901                 c.lastUsefulChunkReceived = time.Now()
902                 return t.maybeCompleteMetadata()
903         case pp.RequestMetadataExtensionMsgType:
904                 if !t.haveMetadataPiece(piece) {
905                         c.Post(t.newMetadataExtensionMessage(c, pp.RejectMetadataExtensionMsgType, d["piece"], nil))
906                         return nil
907                 }
908                 start := (1 << 14) * piece
909                 c.Post(t.newMetadataExtensionMessage(c, pp.DataMetadataExtensionMsgType, piece, t.metadataBytes[start:start+t.metadataPieceSize(piece)]))
910                 return nil
911         case pp.RejectMetadataExtensionMsgType:
912                 return nil
913         default:
914                 return errors.New("unknown msg_type value")
915         }
916 }
917
918 func (cl *Client) badPeerIPPort(ip net.IP, port int) bool {
919         if port == 0 {
920                 return true
921         }
922         if cl.dopplegangerAddr(net.JoinHostPort(ip.String(), strconv.FormatInt(int64(port), 10))) {
923                 return true
924         }
925         if _, ok := cl.ipBlockRange(ip); ok {
926                 return true
927         }
928         if _, ok := cl.badPeerIPs[ip.String()]; ok {
929                 return true
930         }
931         return false
932 }
933
934 // Return a Torrent ready for insertion into a Client.
935 func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (t *Torrent) {
936         // use provided storage, if provided
937         storageClient := cl.defaultStorage
938         if specStorage != nil {
939                 storageClient = storage.NewClient(specStorage)
940         }
941
942         t = &Torrent{
943                 cl:       cl,
944                 infoHash: ih,
945                 peers: prioritizedPeers{
946                         om: btree.New(32),
947                         getPrio: func(p Peer) peerPriority {
948                                 return bep40PriorityIgnoreError(cl.publicAddr(p.IP), p.addr())
949                         },
950                 },
951                 conns: make(map[*connection]struct{}, 2*cl.config.EstablishedConnsPerTorrent),
952
953                 halfOpen:          make(map[string]Peer),
954                 pieceStateChanges: pubsub.NewPubSub(),
955
956                 storageOpener:       storageClient,
957                 maxEstablishedConns: cl.config.EstablishedConnsPerTorrent,
958
959                 networkingEnabled: true,
960                 requestStrategy:   3,
961                 metadataChanged: sync.Cond{
962                         L: cl.locker(),
963                 },
964                 duplicateRequestTimeout: 1 * time.Second,
965         }
966         t.logger = cl.logger.Clone().AddValue(t)
967         t.setChunkSize(defaultChunkSize)
968         return
969 }
970
971 // A file-like handle to some torrent data resource.
972 type Handle interface {
973         io.Reader
974         io.Seeker
975         io.Closer
976         io.ReaderAt
977 }
978
979 func (cl *Client) AddTorrentInfoHash(infoHash metainfo.Hash) (t *Torrent, new bool) {
980         return cl.AddTorrentInfoHashWithStorage(infoHash, nil)
981 }
982
983 // Adds a torrent by InfoHash with a custom Storage implementation.
984 // If the torrent already exists then this Storage is ignored and the
985 // existing torrent returned with `new` set to `false`
986 func (cl *Client) AddTorrentInfoHashWithStorage(infoHash metainfo.Hash, specStorage storage.ClientImpl) (t *Torrent, new bool) {
987         cl.lock()
988         defer cl.unlock()
989         t, ok := cl.torrents[infoHash]
990         if ok {
991                 return
992         }
993         new = true
994
995         t = cl.newTorrent(infoHash, specStorage)
996         cl.eachDhtServer(func(s *dht.Server) {
997                 go t.dhtAnnouncer(s)
998         })
999         cl.torrents[infoHash] = t
1000         cl.clearAcceptLimits()
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.lock()
1025         defer cl.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.lock()
1064         defer cl.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.lock()
1077         defer cl.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, outgoing bool) (c *connection) {
1145         c = &connection{
1146                 conn:            nc,
1147                 outgoing:        outgoing,
1148                 Choked:          true,
1149                 PeerChoked:      true,
1150                 PeerMaxRequests: 250,
1151                 writeBuffer:     new(bytes.Buffer),
1152         }
1153         c.writerCond.L = cl.locker()
1154         c.setRW(connStatsReadWriter{nc, c})
1155         c.r = &rateLimitedReader{
1156                 l: cl.config.DownloadRateLimiter,
1157                 r: c.r,
1158         }
1159         return
1160 }
1161
1162 func (cl *Client) onDHTAnnouncePeer(ih metainfo.Hash, p dht.Peer) {
1163         cl.lock()
1164         defer cl.unlock()
1165         t := cl.torrent(ih)
1166         if t == nil {
1167                 return
1168         }
1169         t.addPeers([]Peer{{
1170                 IP:     p.IP,
1171                 Port:   p.Port,
1172                 Source: peerSourceDHTAnnouncePeer,
1173         }})
1174 }
1175
1176 func firstNotNil(ips ...net.IP) net.IP {
1177         for _, ip := range ips {
1178                 if ip != nil {
1179                         return ip
1180                 }
1181         }
1182         return nil
1183 }
1184
1185 func (cl *Client) eachListener(f func(socket) bool) {
1186         for _, s := range cl.conns {
1187                 if !f(s) {
1188                         break
1189                 }
1190         }
1191 }
1192
1193 func (cl *Client) findListener(f func(net.Listener) bool) (ret net.Listener) {
1194         cl.eachListener(func(l socket) bool {
1195                 ret = l
1196                 return !f(l)
1197         })
1198         return
1199 }
1200
1201 func (cl *Client) publicIp(peer net.IP) net.IP {
1202         // TODO: Use BEP 10 to determine how peers are seeing us.
1203         if peer.To4() != nil {
1204                 return firstNotNil(
1205                         cl.config.PublicIp4,
1206                         cl.findListenerIp(func(ip net.IP) bool { return ip.To4() != nil }),
1207                 )
1208         } else {
1209                 return firstNotNil(
1210                         cl.config.PublicIp6,
1211                         cl.findListenerIp(func(ip net.IP) bool { return ip.To4() == nil }),
1212                 )
1213         }
1214 }
1215
1216 func (cl *Client) findListenerIp(f func(net.IP) bool) net.IP {
1217         return missinggo.AddrIP(cl.findListener(func(l net.Listener) bool {
1218                 return f(missinggo.AddrIP(l.Addr()))
1219         }).Addr())
1220 }
1221
1222 // Our IP as a peer should see it.
1223 func (cl *Client) publicAddr(peer net.IP) ipPort {
1224         return ipPort{cl.publicIp(peer), uint16(cl.incomingPeerPort())}
1225 }
1226
1227 func (cl *Client) ListenAddrs() (ret []net.Addr) {
1228         cl.lock()
1229         defer cl.unlock()
1230         cl.eachListener(func(l socket) bool {
1231                 ret = append(ret, l.Addr())
1232                 return true
1233         })
1234         return
1235 }
1236
1237 func (cl *Client) onBadAccept(addr net.Addr) {
1238         ip := maskIpForAcceptLimiting(missinggo.AddrIP(addr))
1239         if cl.acceptLimiter == nil {
1240                 cl.acceptLimiter = make(map[ipStr]int)
1241         }
1242         cl.acceptLimiter[ipStr(ip.String())]++
1243 }
1244
1245 func maskIpForAcceptLimiting(ip net.IP) net.IP {
1246         if ip4 := ip.To4(); ip4 != nil {
1247                 return ip4.Mask(net.CIDRMask(24, 32))
1248         }
1249         return ip
1250 }
1251
1252 func (cl *Client) clearAcceptLimits() {
1253         cl.acceptLimiter = nil
1254 }
1255
1256 func (cl *Client) acceptLimitClearer() {
1257         for {
1258                 select {
1259                 case <-cl.closed.LockedChan(cl.locker()):
1260                         return
1261                 case <-time.After(15 * time.Minute):
1262                         cl.lock()
1263                         cl.clearAcceptLimits()
1264                         cl.unlock()
1265                 }
1266         }
1267 }
1268
1269 func (cl *Client) rateLimitAccept(ip net.IP) bool {
1270         if cl.config.DisableAcceptRateLimiting {
1271                 return false
1272         }
1273         return cl.acceptLimiter[ipStr(maskIpForAcceptLimiting(ip).String())] > 0
1274 }
1275
1276 func (cl *Client) rLock() {
1277         cl._mu.RLock()
1278 }
1279
1280 func (cl *Client) rUnlock() {
1281         cl._mu.RUnlock()
1282 }
1283
1284 func (cl *Client) lock() {
1285         cl._mu.Lock()
1286 }
1287
1288 func (cl *Client) unlock() {
1289         cl._mu.Unlock()
1290 }
1291
1292 func (cl *Client) locker() sync.Locker {
1293         return clientLocker{cl}
1294 }
1295
1296 type clientLocker struct {
1297         *Client
1298 }
1299
1300 func (cl clientLocker) Lock() {
1301         cl.lock()
1302 }
1303
1304 func (cl clientLocker) Unlock() {
1305         cl.unlock()
1306 }