]> Sergey Matveev's repositories - btrtrc.git/blob - handshake.go
Rework header obfuscation and add tests for fallbacks
[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 func handleEncryption(
31         rw io.ReadWriter,
32         skeys mse.SecretKeyIter,
33         policy HeaderObfuscationPolicy,
34         selector mse.CryptoSelector,
35 ) (
36         ret io.ReadWriter,
37         headerEncrypted bool,
38         cryptoMethod mse.CryptoMethod,
39         err error,
40 ) {
41         if !policy.RequirePreferred || !policy.Preferred {
42                 var protocol [len(pp.Protocol)]byte
43                 _, err = io.ReadFull(rw, protocol[:])
44                 if err != nil {
45                         return
46                 }
47                 rw = struct {
48                         io.Reader
49                         io.Writer
50                 }{
51                         io.MultiReader(bytes.NewReader(protocol[:]), rw),
52                         rw,
53                 }
54                 if string(protocol[:]) == pp.Protocol {
55                         ret = rw
56                         return
57                 }
58                 if policy.RequirePreferred {
59                         err = fmt.Errorf("unexpected protocol string %q and header obfuscation disabled", protocol)
60                         return
61                 }
62         }
63         headerEncrypted = true
64         ret, cryptoMethod, err = mse.ReceiveHandshake(rw, skeys, selector)
65         return
66 }
67
68 type PeerExtensionBits = pp.PeerExtensionBits