]> Sergey Matveev's repositories - btrtrc.git/blob - client.go
Allow disabling accept limiting and modify some constants
[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/missinggo/perf"
18
19         "github.com/anacrolix/dht"
20         "github.com/anacrolix/dht/krpc"
21         "github.com/anacrolix/log"
22         "github.com/anacrolix/missinggo"
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         mu     sync.RWMutex
43         event  sync.Cond
44         closed missinggo.Event
45
46         config *ClientConfig
47         logger *log.Logger
48
49         halfOpenLimit  int
50         peerID         PeerID
51         defaultStorage *storage.Client
52         onClose        []func()
53         conns          []socket
54         dhtServers     []*dht.Server
55         ipBlockList    iplist.Ranger
56         // Our BitTorrent protocol extension bytes, sent in our BT handshakes.
57         extensionBytes peerExtensionBytes
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         // An aggregate of stats over all connections.
66         stats ConnStats
67
68         acceptLimiter map[ipStr]int
69 }
70
71 type ipStr string
72
73 func (cl *Client) BadPeerIPs() []string {
74         cl.mu.RLock()
75         defer cl.mu.RUnlock()
76         return cl.badPeerIPsLocked()
77 }
78
79 func (cl *Client) badPeerIPsLocked() []string {
80         return slices.FromMapKeys(cl.badPeerIPs).([]string)
81 }
82
83 func (cl *Client) PeerID() PeerID {
84         return cl.peerID
85 }
86
87 type torrentAddr string
88
89 func (torrentAddr) Network() string { return "" }
90
91 func (me torrentAddr) String() string { return string(me) }
92
93 func (cl *Client) LocalPort() (port int) {
94         cl.eachListener(func(l socket) bool {
95                 _port := missinggo.AddrPort(l.Addr())
96                 if _port == 0 {
97                         panic(l)
98                 }
99                 if port == 0 {
100                         port = _port
101                 } else if port != _port {
102                         panic("mismatched ports")
103                 }
104                 return true
105         })
106         return
107 }
108
109 func writeDhtServerStatus(w io.Writer, s *dht.Server) {
110         dhtStats := s.Stats()
111         fmt.Fprintf(w, "\t# Nodes: %d (%d good, %d banned)\n", dhtStats.Nodes, dhtStats.GoodNodes, dhtStats.BadNodes)
112         fmt.Fprintf(w, "\tServer ID: %x\n", s.ID())
113         fmt.Fprintf(w, "\tAnnounces: %d\n", dhtStats.SuccessfulOutboundAnnouncePeerQueries)
114         fmt.Fprintf(w, "\tOutstanding transactions: %d\n", dhtStats.OutstandingTransactions)
115 }
116
117 // Writes out a human readable status of the client, such as for writing to a
118 // HTTP status page.
119 func (cl *Client) WriteStatus(_w io.Writer) {
120         cl.mu.Lock()
121         defer cl.mu.Unlock()
122         w := bufio.NewWriter(_w)
123         defer w.Flush()
124         fmt.Fprintf(w, "Listen port: %d\n", cl.LocalPort())
125         fmt.Fprintf(w, "Peer ID: %+q\n", cl.PeerID())
126         fmt.Fprintf(w, "Announce key: %x\n", cl.announceKey())
127         fmt.Fprintf(w, "Banned IPs: %d\n", len(cl.badPeerIPsLocked()))
128         cl.eachDhtServer(func(s *dht.Server) {
129                 fmt.Fprintf(w, "%s DHT server at %s:\n", s.Addr().Network(), s.Addr().String())
130                 writeDhtServerStatus(w, s)
131         })
132         spew.Fdump(w, cl.stats)
133         fmt.Fprintf(w, "# Torrents: %d\n", len(cl.torrentsAsSlice()))
134         fmt.Fprintln(w)
135         for _, t := range slices.Sort(cl.torrentsAsSlice(), func(l, r *Torrent) bool {
136                 return l.InfoHash().AsString() < r.InfoHash().AsString()
137         }).([]*Torrent) {
138                 if t.name() == "" {
139                         fmt.Fprint(w, "<unknown name>")
140                 } else {
141                         fmt.Fprint(w, t.name())
142                 }
143                 fmt.Fprint(w, "\n")
144                 if t.info != nil {
145                         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())))
146                 } else {
147                         w.WriteString("<missing metainfo>")
148                 }
149                 fmt.Fprint(w, "\n")
150                 t.writeStatus(w)
151                 fmt.Fprintln(w)
152         }
153 }
154
155 const debugLogValue = "debug"
156
157 func (cl *Client) debugLogFilter(m *log.Msg) bool {
158         if !cl.config.Debug {
159                 _, ok := m.Values()[debugLogValue]
160                 return !ok
161         }
162         return true
163 }
164
165 func (cl *Client) initLogger() {
166         cl.logger = log.Default.Clone().AddValue(cl).AddFilter(log.NewFilter(cl.debugLogFilter))
167 }
168
169 func (cl *Client) announceKey() int32 {
170         return int32(binary.BigEndian.Uint32(cl.peerID[16:20]))
171 }
172
173 func NewClient(cfg *ClientConfig) (cl *Client, err error) {
174         if cfg == nil {
175                 cfg = NewDefaultClientConfig()
176         }
177         defer func() {
178                 if err != nil {
179                         cl = nil
180                 }
181         }()
182         cl = &Client{
183                 halfOpenLimit:     cfg.HalfOpenConnsPerTorrent,
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.mu
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.mu.Lock()
296         defer cl.mu.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.mu.Lock()
318         defer cl.mu.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.mu.RLock()
380                 closed := cl.closed.IsSet()
381                 reject := false
382                 if conn != nil {
383                         reject = cl.rejectAccepted(conn)
384                 }
385                 cl.mu.RUnlock()
386                 if closed {
387                         if conn != nil {
388                                 conn.Close()
389                         }
390                         return
391                 }
392                 if err != nil {
393                         log.Print(err)
394                         // I think something harsher should happen here? Our accept
395                         // routine just fucked off.
396                         return
397                 }
398                 go func() {
399                         if reject {
400                                 torrent.Add("rejected accepted connections", 1)
401                                 conn.Close()
402                         } else {
403                                 go cl.incomingConnection(conn)
404                         }
405                         log.Fmsg("accepted %s connection from %s", conn.RemoteAddr().Network(), conn.RemoteAddr()).AddValue(debugLogValue).Log(cl.logger)
406                         torrent.Add(fmt.Sprintf("accepted conn remote IP len=%d", len(missinggo.AddrIP(conn.RemoteAddr()))), 1)
407                         torrent.Add(fmt.Sprintf("accepted conn network=%s", conn.RemoteAddr().Network()), 1)
408                         torrent.Add(fmt.Sprintf("accepted on %s listener", l.Addr().Network()), 1)
409                 }()
410         }
411 }
412
413 func (cl *Client) incomingConnection(nc net.Conn) {
414         defer nc.Close()
415         if tc, ok := nc.(*net.TCPConn); ok {
416                 tc.SetLinger(0)
417         }
418         c := cl.newConnection(nc, false)
419         c.Discovery = peerSourceIncoming
420         cl.runReceivedConn(c)
421 }
422
423 // Returns a handle to the given torrent, if it's present in the client.
424 func (cl *Client) Torrent(ih metainfo.Hash) (t *Torrent, ok bool) {
425         cl.mu.Lock()
426         defer cl.mu.Unlock()
427         t, ok = cl.torrents[ih]
428         return
429 }
430
431 func (cl *Client) torrent(ih metainfo.Hash) *Torrent {
432         return cl.torrents[ih]
433 }
434
435 type dialResult struct {
436         Conn net.Conn
437 }
438
439 func countDialResult(err error) {
440         if err == nil {
441                 torrent.Add("successful dials", 1)
442         } else {
443                 torrent.Add("unsuccessful dials", 1)
444         }
445 }
446
447 func reducedDialTimeout(minDialTimeout, max time.Duration, halfOpenLimit int, pendingPeers int) (ret time.Duration) {
448         ret = max / time.Duration((pendingPeers+halfOpenLimit)/halfOpenLimit)
449         if ret < minDialTimeout {
450                 ret = minDialTimeout
451         }
452         return
453 }
454
455 // Returns whether an address is known to connect to a client with our own ID.
456 func (cl *Client) dopplegangerAddr(addr string) bool {
457         _, ok := cl.dopplegangerAddrs[addr]
458         return ok
459 }
460
461 func ipNetworkSuffix(allowIpv4, allowIpv6 bool) string {
462         switch {
463         case allowIpv4 && allowIpv6:
464                 return ""
465         case allowIpv4 && !allowIpv6:
466                 return "4"
467         case !allowIpv4 && allowIpv6:
468                 return "6"
469         default:
470                 panic("unhandled ip network combination")
471         }
472 }
473
474 func dialUTP(ctx context.Context, addr string, sock utpSocket) (c net.Conn, err error) {
475         return sock.DialContext(ctx, "", addr)
476 }
477
478 var allPeerNetworks = []string{"tcp4", "tcp6", "udp4", "udp6"}
479
480 func peerNetworkEnabled(network string, cfg *ClientConfig) bool {
481         c := func(s string) bool {
482                 return strings.Contains(network, s)
483         }
484         if cfg.DisableUTP {
485                 if c("udp") || c("utp") {
486                         return false
487                 }
488         }
489         if cfg.DisableTCP && c("tcp") {
490                 return false
491         }
492         if cfg.DisableIPv6 && c("6") {
493                 return false
494         }
495         return true
496 }
497
498 // Returns a connection over UTP or TCP, whichever is first to connect.
499 func (cl *Client) dialFirst(ctx context.Context, addr string) net.Conn {
500         ctx, cancel := context.WithCancel(ctx)
501         // As soon as we return one connection, cancel the others.
502         defer cancel()
503         left := 0
504         resCh := make(chan dialResult, left)
505         dial := func(f func(_ context.Context, addr string) (net.Conn, error)) {
506                 left++
507                 go func() {
508                         c, err := f(ctx, addr)
509                         // This is a bit optimistic, but it looks non-trivial to thread
510                         // this through the proxy code. Set it now in case we close the
511                         // connection forthwith.
512                         if tc, ok := c.(*net.TCPConn); ok {
513                                 tc.SetLinger(0)
514                         }
515                         countDialResult(err)
516                         resCh <- dialResult{c}
517                 }()
518         }
519         func() {
520                 cl.mu.Lock()
521                 defer cl.mu.Unlock()
522                 cl.eachListener(func(s socket) bool {
523                         if peerNetworkEnabled(s.Addr().Network(), cl.config) {
524                                 dial(s.dial)
525                         }
526                         return true
527                 })
528         }()
529         var res dialResult
530         // Wait for a successful connection.
531         func() {
532                 defer perf.ScopeTimer()()
533                 for ; left > 0 && res.Conn == nil; left-- {
534                         res = <-resCh
535                 }
536         }()
537         // There are still incompleted dials.
538         go func() {
539                 for ; left > 0; left-- {
540                         conn := (<-resCh).Conn
541                         if conn != nil {
542                                 conn.Close()
543                         }
544                 }
545         }()
546         if res.Conn != nil {
547                 go torrent.Add(fmt.Sprintf("network dialed first: %s", res.Conn.RemoteAddr().Network()), 1)
548         }
549         return res.Conn
550 }
551
552 func (cl *Client) noLongerHalfOpen(t *Torrent, addr string) {
553         if _, ok := t.halfOpen[addr]; !ok {
554                 panic("invariant broken")
555         }
556         delete(t.halfOpen, addr)
557         t.openNewConns()
558 }
559
560 // Performs initiator handshakes and returns a connection. Returns nil
561 // *connection if no connection for valid reasons.
562 func (cl *Client) handshakesConnection(ctx context.Context, nc net.Conn, t *Torrent, encryptHeader bool) (c *connection, err error) {
563         c = cl.newConnection(nc, true)
564         c.headerEncrypted = encryptHeader
565         ctx, cancel := context.WithTimeout(ctx, cl.config.HandshakesTimeout)
566         defer cancel()
567         dl, ok := ctx.Deadline()
568         if !ok {
569                 panic(ctx)
570         }
571         err = nc.SetDeadline(dl)
572         if err != nil {
573                 panic(err)
574         }
575         ok, err = cl.initiateHandshakes(c, t)
576         if !ok {
577                 c = nil
578         }
579         return
580 }
581
582 // Returns nil connection and nil error if no connection could be established
583 // for valid reasons.
584 func (cl *Client) establishOutgoingConnEx(t *Torrent, addr string, ctx context.Context, obfuscatedHeader bool) (c *connection, err error) {
585         nc := cl.dialFirst(ctx, addr)
586         if nc == nil {
587                 return
588         }
589         defer func() {
590                 if c == nil || err != nil {
591                         nc.Close()
592                 }
593         }()
594         return cl.handshakesConnection(ctx, nc, t, obfuscatedHeader)
595 }
596
597 // Returns nil connection and nil error if no connection could be established
598 // for valid reasons.
599 func (cl *Client) establishOutgoingConn(t *Torrent, addr string) (c *connection, err error) {
600         ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
601         defer cancel()
602         obfuscatedHeaderFirst := !cl.config.DisableEncryption && !cl.config.PreferNoEncryption
603         c, err = cl.establishOutgoingConnEx(t, addr, ctx, obfuscatedHeaderFirst)
604         if err != nil {
605                 return
606         }
607         if c != nil {
608                 torrent.Add("initiated conn with preferred header obfuscation", 1)
609                 return
610         }
611         if cl.config.ForceEncryption {
612                 // We should have just tried with an obfuscated header. A plaintext
613                 // header can't result in an encrypted connection, so we're done.
614                 if !obfuscatedHeaderFirst {
615                         panic(cl.config.EncryptionPolicy)
616                 }
617                 return
618         }
619         // Try again with encryption if we didn't earlier, or without if we did.
620         c, err = cl.establishOutgoingConnEx(t, addr, ctx, !obfuscatedHeaderFirst)
621         if c != nil {
622                 torrent.Add("initiated conn with fallback header obfuscation", 1)
623         }
624         return
625 }
626
627 // Called to dial out and run a connection. The addr we're given is already
628 // considered half-open.
629 func (cl *Client) outgoingConnection(t *Torrent, addr string, ps peerSource) {
630         c, err := cl.establishOutgoingConn(t, addr)
631         cl.mu.Lock()
632         defer cl.mu.Unlock()
633         // Don't release lock between here and addConnection, unless it's for
634         // failure.
635         cl.noLongerHalfOpen(t, addr)
636         if err != nil {
637                 if cl.config.Debug {
638                         log.Printf("error establishing outgoing connection: %s", err)
639                 }
640                 return
641         }
642         if c == nil {
643                 return
644         }
645         defer c.Close()
646         c.Discovery = ps
647         cl.runHandshookConn(c, t)
648 }
649
650 // The port number for incoming peer connections. 0 if the client isn't
651 // listening.
652 func (cl *Client) incomingPeerPort() int {
653         return cl.LocalPort()
654 }
655
656 func (cl *Client) initiateHandshakes(c *connection, t *Torrent) (ok bool, err error) {
657         if c.headerEncrypted {
658                 var rw io.ReadWriter
659                 rw, c.cryptoMethod, err = mse.InitiateHandshake(
660                         struct {
661                                 io.Reader
662                                 io.Writer
663                         }{c.r, c.w},
664                         t.infoHash[:],
665                         nil,
666                         func() mse.CryptoMethod {
667                                 switch {
668                                 case cl.config.ForceEncryption:
669                                         return mse.CryptoMethodRC4
670                                 case cl.config.DisableEncryption:
671                                         return mse.CryptoMethodPlaintext
672                                 default:
673                                         return mse.AllSupportedCrypto
674                                 }
675                         }(),
676                 )
677                 c.setRW(rw)
678                 if err != nil {
679                         return
680                 }
681         }
682         ih, ok, err := cl.connBTHandshake(c, &t.infoHash)
683         if ih != t.infoHash {
684                 ok = false
685         }
686         return
687 }
688
689 // Calls f with any secret keys.
690 func (cl *Client) forSkeys(f func([]byte) bool) {
691         cl.mu.Lock()
692         defer cl.mu.Unlock()
693         for ih := range cl.torrents {
694                 if !f(ih[:]) {
695                         break
696                 }
697         }
698 }
699
700 // Do encryption and bittorrent handshakes as receiver.
701 func (cl *Client) receiveHandshakes(c *connection) (t *Torrent, err error) {
702         defer perf.ScopeTimerErr(&err)()
703         var rw io.ReadWriter
704         rw, c.headerEncrypted, c.cryptoMethod, err = handleEncryption(c.rw(), cl.forSkeys, cl.config.EncryptionPolicy)
705         c.setRW(rw)
706         if err != nil {
707                 if err == mse.ErrNoSecretKeyMatch {
708                         err = nil
709                 }
710                 return
711         }
712         if cl.config.ForceEncryption && !c.headerEncrypted {
713                 err = errors.New("connection not encrypted")
714                 return
715         }
716         ih, ok, err := cl.connBTHandshake(c, nil)
717         if err != nil {
718                 err = fmt.Errorf("error during bt handshake: %s", err)
719                 return
720         }
721         if !ok {
722                 return
723         }
724         cl.mu.Lock()
725         t = cl.torrents[ih]
726         cl.mu.Unlock()
727         return
728 }
729
730 // Returns !ok if handshake failed for valid reasons.
731 func (cl *Client) connBTHandshake(c *connection, ih *metainfo.Hash) (ret metainfo.Hash, ok bool, err error) {
732         res, ok, err := handshake(c.rw(), ih, cl.peerID, cl.extensionBytes)
733         if err != nil || !ok {
734                 return
735         }
736         ret = res.Hash
737         c.PeerExtensionBytes = res.peerExtensionBytes
738         c.PeerID = res.PeerID
739         c.completedHandshake = time.Now()
740         return
741 }
742
743 func (cl *Client) runReceivedConn(c *connection) {
744         err := c.conn.SetDeadline(time.Now().Add(cl.config.HandshakesTimeout))
745         if err != nil {
746                 panic(err)
747         }
748         t, err := cl.receiveHandshakes(c)
749         if err != nil {
750                 log.Fmsg(
751                         "error receiving handshakes: %s", err,
752                 ).AddValue(
753                         debugLogValue,
754                 ).Add(
755                         "network", c.remoteAddr().Network(),
756                 ).Log(cl.logger)
757                 torrent.Add("error receiving handshake", 1)
758                 cl.mu.Lock()
759                 cl.onBadAccept(c.remoteAddr())
760                 cl.mu.Unlock()
761                 return
762         }
763         if t == nil {
764                 torrent.Add("received handshake for unloaded torrent", 1)
765                 cl.mu.Lock()
766                 cl.onBadAccept(c.remoteAddr())
767                 cl.mu.Unlock()
768                 return
769         }
770         torrent.Add("received handshake for loaded torrent", 1)
771         cl.mu.Lock()
772         defer cl.mu.Unlock()
773         cl.runHandshookConn(c, t)
774 }
775
776 func (cl *Client) runHandshookConn(c *connection, t *Torrent) {
777         c.setTorrent(t)
778         if c.PeerID == cl.peerID {
779                 if c.outgoing {
780                         connsToSelf.Add(1)
781                         addr := c.conn.RemoteAddr().String()
782                         cl.dopplegangerAddrs[addr] = struct{}{}
783                 } else {
784                         // Because the remote address is not necessarily the same as its
785                         // client's torrent listen address, we won't record the remote address
786                         // as a doppleganger. Instead, the initiator can record *us* as the
787                         // doppleganger.
788                 }
789                 return
790         }
791         c.conn.SetWriteDeadline(time.Time{})
792         c.r = deadlineReader{c.conn, c.r}
793         completedHandshakeConnectionFlags.Add(c.connectionFlags(), 1)
794         if connIsIpv6(c.conn) {
795                 torrent.Add("completed handshake over ipv6", 1)
796         }
797         if err := t.addConnection(c); err != nil {
798                 log.Fmsg("error adding connection: %s", err).AddValues(c, debugLogValue).Log(t.logger)
799                 return
800         }
801         defer t.dropConnection(c)
802         go c.writer(time.Minute)
803         cl.sendInitialMessages(c, t)
804         err := c.mainReadLoop()
805         if err != nil && cl.config.Debug {
806                 log.Printf("error during connection main read loop: %s", err)
807         }
808 }
809
810 func (cl *Client) sendInitialMessages(conn *connection, torrent *Torrent) {
811         func() {
812                 if conn.fastEnabled() {
813                         if torrent.haveAllPieces() {
814                                 conn.Post(pp.Message{Type: pp.HaveAll})
815                                 conn.sentHaves.AddRange(0, conn.t.NumPieces())
816                                 return
817                         } else if !torrent.haveAnyPieces() {
818                                 conn.Post(pp.Message{Type: pp.HaveNone})
819                                 conn.sentHaves.Clear()
820                                 return
821                         }
822                 }
823                 conn.PostBitfield()
824         }()
825         if conn.PeerExtensionBytes.SupportsExtended() && cl.extensionBytes.SupportsExtended() {
826                 conn.Post(pp.Message{
827                         Type:       pp.Extended,
828                         ExtendedID: pp.HandshakeExtendedID,
829                         ExtendedPayload: func() []byte {
830                                 d := map[string]interface{}{
831                                         "m": func() (ret map[string]int) {
832                                                 ret = make(map[string]int, 2)
833                                                 ret["ut_metadata"] = metadataExtendedId
834                                                 if !cl.config.DisablePEX {
835                                                         ret["ut_pex"] = pexExtendedId
836                                                 }
837                                                 return
838                                         }(),
839                                         "v": cl.config.ExtendedHandshakeClientVersion,
840                                         // No upload queue is implemented yet.
841                                         "reqq": 64,
842                                 }
843                                 if !cl.config.DisableEncryption {
844                                         d["e"] = 1
845                                 }
846                                 if torrent.metadataSizeKnown() {
847                                         d["metadata_size"] = torrent.metadataSize()
848                                 }
849                                 if p := cl.incomingPeerPort(); p != 0 {
850                                         d["p"] = p
851                                 }
852                                 yourip, err := addrCompactIP(conn.remoteAddr())
853                                 if err != nil {
854                                         log.Printf("error calculating yourip field value in extension handshake: %s", err)
855                                 } else {
856                                         d["yourip"] = yourip
857                                 }
858                                 // log.Printf("sending %v", d)
859                                 b, err := bencode.Marshal(d)
860                                 if err != nil {
861                                         panic(err)
862                                 }
863                                 return b
864                         }(),
865                 })
866         }
867         if conn.PeerExtensionBytes.SupportsDHT() && cl.extensionBytes.SupportsDHT() && cl.haveDhtServer() {
868                 conn.Post(pp.Message{
869                         Type: pp.Port,
870                         Port: cl.dhtPort(),
871                 })
872         }
873 }
874
875 func (cl *Client) dhtPort() (ret uint16) {
876         cl.eachDhtServer(func(s *dht.Server) {
877                 ret = uint16(missinggo.AddrPort(s.Addr()))
878         })
879         return
880 }
881
882 func (cl *Client) haveDhtServer() (ret bool) {
883         cl.eachDhtServer(func(_ *dht.Server) {
884                 ret = true
885         })
886         return
887 }
888
889 // Process incoming ut_metadata message.
890 func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *connection) error {
891         var d map[string]int
892         err := bencode.Unmarshal(payload, &d)
893         if _, ok := err.(bencode.ErrUnusedTrailingBytes); ok {
894         } else if err != nil {
895                 return fmt.Errorf("error unmarshalling bencode: %s", err)
896         }
897         msgType, ok := d["msg_type"]
898         if !ok {
899                 return errors.New("missing msg_type field")
900         }
901         piece := d["piece"]
902         switch msgType {
903         case pp.DataMetadataExtensionMsgType:
904                 if !c.requestedMetadataPiece(piece) {
905                         return fmt.Errorf("got unexpected piece %d", piece)
906                 }
907                 c.metadataRequests[piece] = false
908                 begin := len(payload) - metadataPieceSize(d["total_size"], piece)
909                 if begin < 0 || begin >= len(payload) {
910                         return fmt.Errorf("data has bad offset in payload: %d", begin)
911                 }
912                 t.saveMetadataPiece(piece, payload[begin:])
913                 c.allStats(add(1, func(cs *ConnStats) *Count { return &cs.ChunksReadUseful }))
914                 c.lastUsefulChunkReceived = time.Now()
915                 return t.maybeCompleteMetadata()
916         case pp.RequestMetadataExtensionMsgType:
917                 if !t.haveMetadataPiece(piece) {
918                         c.Post(t.newMetadataExtensionMessage(c, pp.RejectMetadataExtensionMsgType, d["piece"], nil))
919                         return nil
920                 }
921                 start := (1 << 14) * piece
922                 c.Post(t.newMetadataExtensionMessage(c, pp.DataMetadataExtensionMsgType, piece, t.metadataBytes[start:start+t.metadataPieceSize(piece)]))
923                 return nil
924         case pp.RejectMetadataExtensionMsgType:
925                 return nil
926         default:
927                 return errors.New("unknown msg_type value")
928         }
929 }
930
931 func (cl *Client) badPeerIPPort(ip net.IP, port int) bool {
932         if port == 0 {
933                 return true
934         }
935         if cl.dopplegangerAddr(net.JoinHostPort(ip.String(), strconv.FormatInt(int64(port), 10))) {
936                 return true
937         }
938         if _, ok := cl.ipBlockRange(ip); ok {
939                 return true
940         }
941         if _, ok := cl.badPeerIPs[ip.String()]; ok {
942                 return true
943         }
944         return false
945 }
946
947 // Return a Torrent ready for insertion into a Client.
948 func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (t *Torrent) {
949         // use provided storage, if provided
950         storageClient := cl.defaultStorage
951         if specStorage != nil {
952                 storageClient = storage.NewClient(specStorage)
953         }
954
955         t = &Torrent{
956                 cl:       cl,
957                 infoHash: ih,
958                 peers: prioritizedPeers{
959                         om: btree.New(32),
960                         getPrio: func(p Peer) peerPriority {
961                                 return bep40PriorityIgnoreError(cl.publicAddr(p.IP), p.addr())
962                         },
963                 },
964                 conns: make(map[*connection]struct{}, 2*cl.config.EstablishedConnsPerTorrent),
965
966                 halfOpen:          make(map[string]Peer),
967                 pieceStateChanges: pubsub.NewPubSub(),
968
969                 storageOpener:       storageClient,
970                 maxEstablishedConns: cl.config.EstablishedConnsPerTorrent,
971
972                 networkingEnabled: true,
973                 requestStrategy:   2,
974                 metadataChanged: sync.Cond{
975                         L: &cl.mu,
976                 },
977         }
978         t.logger = cl.logger.Clone().AddValue(t)
979         t.setChunkSize(defaultChunkSize)
980         return
981 }
982
983 // A file-like handle to some torrent data resource.
984 type Handle interface {
985         io.Reader
986         io.Seeker
987         io.Closer
988         io.ReaderAt
989 }
990
991 func (cl *Client) AddTorrentInfoHash(infoHash metainfo.Hash) (t *Torrent, new bool) {
992         return cl.AddTorrentInfoHashWithStorage(infoHash, nil)
993 }
994
995 // Adds a torrent by InfoHash with a custom Storage implementation.
996 // If the torrent already exists then this Storage is ignored and the
997 // existing torrent returned with `new` set to `false`
998 func (cl *Client) AddTorrentInfoHashWithStorage(infoHash metainfo.Hash, specStorage storage.ClientImpl) (t *Torrent, new bool) {
999         cl.mu.Lock()
1000         defer cl.mu.Unlock()
1001         t, ok := cl.torrents[infoHash]
1002         if ok {
1003                 return
1004         }
1005         new = true
1006
1007         t = cl.newTorrent(infoHash, specStorage)
1008         cl.eachDhtServer(func(s *dht.Server) {
1009                 go t.dhtAnnouncer(s)
1010         })
1011         cl.torrents[infoHash] = t
1012         cl.clearAcceptLimits()
1013         t.updateWantPeersEvent()
1014         // Tickle Client.waitAccept, new torrent may want conns.
1015         cl.event.Broadcast()
1016         return
1017 }
1018
1019 // Add or merge a torrent spec. If the torrent is already present, the
1020 // trackers will be merged with the existing ones. If the Info isn't yet
1021 // known, it will be set. The display name is replaced if the new spec
1022 // provides one. Returns new if the torrent wasn't already in the client.
1023 // Note that any `Storage` defined on the spec will be ignored if the
1024 // torrent is already present (i.e. `new` return value is `true`)
1025 func (cl *Client) AddTorrentSpec(spec *TorrentSpec) (t *Torrent, new bool, err error) {
1026         t, new = cl.AddTorrentInfoHashWithStorage(spec.InfoHash, spec.Storage)
1027         if spec.DisplayName != "" {
1028                 t.SetDisplayName(spec.DisplayName)
1029         }
1030         if spec.InfoBytes != nil {
1031                 err = t.SetInfoBytes(spec.InfoBytes)
1032                 if err != nil {
1033                         return
1034                 }
1035         }
1036         cl.mu.Lock()
1037         defer cl.mu.Unlock()
1038         if spec.ChunkSize != 0 {
1039                 t.setChunkSize(pp.Integer(spec.ChunkSize))
1040         }
1041         t.addTrackers(spec.Trackers)
1042         t.maybeNewConns()
1043         return
1044 }
1045
1046 func (cl *Client) dropTorrent(infoHash metainfo.Hash) (err error) {
1047         t, ok := cl.torrents[infoHash]
1048         if !ok {
1049                 err = fmt.Errorf("no such torrent")
1050                 return
1051         }
1052         err = t.close()
1053         if err != nil {
1054                 panic(err)
1055         }
1056         delete(cl.torrents, infoHash)
1057         return
1058 }
1059
1060 func (cl *Client) allTorrentsCompleted() bool {
1061         for _, t := range cl.torrents {
1062                 if !t.haveInfo() {
1063                         return false
1064                 }
1065                 if !t.haveAllPieces() {
1066                         return false
1067                 }
1068         }
1069         return true
1070 }
1071
1072 // Returns true when all torrents are completely downloaded and false if the
1073 // client is stopped before that.
1074 func (cl *Client) WaitAll() bool {
1075         cl.mu.Lock()
1076         defer cl.mu.Unlock()
1077         for !cl.allTorrentsCompleted() {
1078                 if cl.closed.IsSet() {
1079                         return false
1080                 }
1081                 cl.event.Wait()
1082         }
1083         return true
1084 }
1085
1086 // Returns handles to all the torrents loaded in the Client.
1087 func (cl *Client) Torrents() []*Torrent {
1088         cl.mu.Lock()
1089         defer cl.mu.Unlock()
1090         return cl.torrentsAsSlice()
1091 }
1092
1093 func (cl *Client) torrentsAsSlice() (ret []*Torrent) {
1094         for _, t := range cl.torrents {
1095                 ret = append(ret, t)
1096         }
1097         return
1098 }
1099
1100 func (cl *Client) AddMagnet(uri string) (T *Torrent, err error) {
1101         spec, err := TorrentSpecFromMagnetURI(uri)
1102         if err != nil {
1103                 return
1104         }
1105         T, _, err = cl.AddTorrentSpec(spec)
1106         return
1107 }
1108
1109 func (cl *Client) AddTorrent(mi *metainfo.MetaInfo) (T *Torrent, err error) {
1110         T, _, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
1111         var ss []string
1112         slices.MakeInto(&ss, mi.Nodes)
1113         cl.AddDHTNodes(ss)
1114         return
1115 }
1116
1117 func (cl *Client) AddTorrentFromFile(filename string) (T *Torrent, err error) {
1118         mi, err := metainfo.LoadFromFile(filename)
1119         if err != nil {
1120                 return
1121         }
1122         return cl.AddTorrent(mi)
1123 }
1124
1125 func (cl *Client) DhtServers() []*dht.Server {
1126         return cl.dhtServers
1127 }
1128
1129 func (cl *Client) AddDHTNodes(nodes []string) {
1130         for _, n := range nodes {
1131                 hmp := missinggo.SplitHostMaybePort(n)
1132                 ip := net.ParseIP(hmp.Host)
1133                 if ip == nil {
1134                         log.Printf("won't add DHT node with bad IP: %q", hmp.Host)
1135                         continue
1136                 }
1137                 ni := krpc.NodeInfo{
1138                         Addr: krpc.NodeAddr{
1139                                 IP:   ip,
1140                                 Port: hmp.Port,
1141                         },
1142                 }
1143                 cl.eachDhtServer(func(s *dht.Server) {
1144                         s.AddNode(ni)
1145                 })
1146         }
1147 }
1148
1149 func (cl *Client) banPeerIP(ip net.IP) {
1150         if cl.badPeerIPs == nil {
1151                 cl.badPeerIPs = make(map[string]struct{})
1152         }
1153         cl.badPeerIPs[ip.String()] = struct{}{}
1154 }
1155
1156 func (cl *Client) newConnection(nc net.Conn, outgoing bool) (c *connection) {
1157         c = &connection{
1158                 conn:            nc,
1159                 outgoing:        outgoing,
1160                 Choked:          true,
1161                 PeerChoked:      true,
1162                 PeerMaxRequests: 250,
1163                 writeBuffer:     new(bytes.Buffer),
1164         }
1165         c.writerCond.L = &cl.mu
1166         c.setRW(connStatsReadWriter{nc, c})
1167         c.r = &rateLimitedReader{
1168                 l: cl.config.DownloadRateLimiter,
1169                 r: c.r,
1170         }
1171         return
1172 }
1173
1174 func (cl *Client) onDHTAnnouncePeer(ih metainfo.Hash, p dht.Peer) {
1175         cl.mu.Lock()
1176         defer cl.mu.Unlock()
1177         t := cl.torrent(ih)
1178         if t == nil {
1179                 return
1180         }
1181         t.addPeers([]Peer{{
1182                 IP:     p.IP,
1183                 Port:   p.Port,
1184                 Source: peerSourceDHTAnnouncePeer,
1185         }})
1186 }
1187
1188 func firstNotNil(ips ...net.IP) net.IP {
1189         for _, ip := range ips {
1190                 if ip != nil {
1191                         return ip
1192                 }
1193         }
1194         return nil
1195 }
1196
1197 func (cl *Client) eachListener(f func(socket) bool) {
1198         for _, s := range cl.conns {
1199                 if !f(s) {
1200                         break
1201                 }
1202         }
1203 }
1204
1205 func (cl *Client) findListener(f func(net.Listener) bool) (ret net.Listener) {
1206         cl.eachListener(func(l socket) bool {
1207                 ret = l
1208                 return !f(l)
1209         })
1210         return
1211 }
1212
1213 func (cl *Client) publicIp(peer net.IP) net.IP {
1214         // TODO: Use BEP 10 to determine how peers are seeing us.
1215         if peer.To4() != nil {
1216                 return firstNotNil(
1217                         cl.config.PublicIp4,
1218                         cl.findListenerIp(func(ip net.IP) bool { return ip.To4() != nil }),
1219                 )
1220         } else {
1221                 return firstNotNil(
1222                         cl.config.PublicIp6,
1223                         cl.findListenerIp(func(ip net.IP) bool { return ip.To4() == nil }),
1224                 )
1225         }
1226 }
1227
1228 func (cl *Client) findListenerIp(f func(net.IP) bool) net.IP {
1229         return missinggo.AddrIP(cl.findListener(func(l net.Listener) bool {
1230                 return f(missinggo.AddrIP(l.Addr()))
1231         }).Addr())
1232 }
1233
1234 // Our IP as a peer should see it.
1235 func (cl *Client) publicAddr(peer net.IP) ipPort {
1236         return ipPort{cl.publicIp(peer), uint16(cl.incomingPeerPort())}
1237 }
1238
1239 func (cl *Client) ListenAddrs() (ret []net.Addr) {
1240         cl.mu.Lock()
1241         defer cl.mu.Unlock()
1242         cl.eachListener(func(l socket) bool {
1243                 ret = append(ret, l.Addr())
1244                 return true
1245         })
1246         return
1247 }
1248
1249 func (cl *Client) onBadAccept(addr net.Addr) {
1250         ip := maskIpForAcceptLimiting(missinggo.AddrIP(addr))
1251         if cl.acceptLimiter == nil {
1252                 cl.acceptLimiter = make(map[ipStr]int)
1253         }
1254         cl.acceptLimiter[ipStr(ip.String())]++
1255 }
1256
1257 func maskIpForAcceptLimiting(ip net.IP) net.IP {
1258         if ip4 := ip.To4(); ip4 != nil {
1259                 return ip4.Mask(net.CIDRMask(24, 32))
1260         }
1261         return ip
1262 }
1263
1264 func (cl *Client) clearAcceptLimits() {
1265         cl.acceptLimiter = nil
1266 }
1267
1268 func (cl *Client) acceptLimitClearer() {
1269         for {
1270                 select {
1271                 case <-cl.closed.LockedChan(&cl.mu):
1272                         return
1273                 case <-time.After(5 * time.Minute):
1274                         cl.mu.Lock()
1275                         cl.clearAcceptLimits()
1276                         cl.mu.Unlock()
1277                 }
1278         }
1279 }
1280
1281 func (cl *Client) rateLimitAccept(ip net.IP) bool {
1282         if cl.config.DisableAcceptRateLimiting {
1283                 return false
1284         }
1285         return cl.acceptLimiter[ipStr(maskIpForAcceptLimiting(ip).String())] >= 3
1286 }