]> Sergey Matveev's repositories - btrtrc.git/blob - handshake.go
Drop support for go 1.20
[btrtrc.git] / handshake.go
1 package torrent
2
3 import (
4         "bytes"
5         "fmt"
6         "io"
7         "net"
8         "time"
9
10         "github.com/anacrolix/torrent/mse"
11         pp "github.com/anacrolix/torrent/peer_protocol"
12 )
13
14 // Wraps a raw connection and provides the interface we want for using the
15 // connection in the message loop.
16 type deadlineReader struct {
17         nc net.Conn
18         r  io.Reader
19 }
20
21 func (r deadlineReader) Read(b []byte) (int, error) {
22         // Keep-alives should be received every 2 mins. Give a bit of gracetime.
23         err := r.nc.SetReadDeadline(time.Now().Add(150 * time.Second))
24         if err != nil {
25                 return 0, fmt.Errorf("error setting read deadline: %s", err)
26         }
27         return r.r.Read(b)
28 }
29
30 // Handles stream encryption for inbound connections.
31 func handleEncryption(
32         rw io.ReadWriter,
33         skeys mse.SecretKeyIter,
34         policy HeaderObfuscationPolicy,
35         selector mse.CryptoSelector,
36 ) (
37         ret io.ReadWriter,
38         headerEncrypted bool,
39         cryptoMethod mse.CryptoMethod,
40         err error,
41 ) {
42         // Tries to start an unencrypted stream.
43         if !policy.RequirePreferred || !policy.Preferred {
44                 var protocol [len(pp.Protocol)]byte
45                 _, err = io.ReadFull(rw, protocol[:])
46                 if err != nil {
47                         return
48                 }
49                 // Put the protocol back into the stream.
50                 rw = struct {
51                         io.Reader
52                         io.Writer
53                 }{
54                         io.MultiReader(bytes.NewReader(protocol[:]), rw),
55                         rw,
56                 }
57                 if string(protocol[:]) == pp.Protocol {
58                         ret = rw
59                         return
60                 }
61                 if policy.RequirePreferred {
62                         // We are here because we require unencrypted connections.
63                         err = fmt.Errorf("unexpected protocol string %q and header obfuscation disabled", protocol)
64                         return
65                 }
66         }
67         headerEncrypted = true
68         ret, cryptoMethod, err = mse.ReceiveHandshake(rw, skeys, selector)
69         return
70 }
71
72 type PeerExtensionBits = pp.PeerExtensionBits