]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Rework handshake parsing
authorMatt Joiner <anacrolix@gmail.com>
Sat, 28 Sep 2024 12:19:29 +0000 (22:19 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Sun, 29 Sep 2024 03:13:52 +0000 (13:13 +1000)
go.mod
go.sum
peer_protocol/handshake.go
peer_protocol/protocol.go

diff --git a/go.mod b/go.mod
index fe0f108eeb25032def28d97681982e5d8b91af84..35cc26b65c913921e96e14fd0c2d260a65e1cbf2 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -11,7 +11,7 @@ require (
        github.com/anacrolix/dht/v2 v2.19.2-0.20221121215055-066ad8494444
        github.com/anacrolix/envpprof v1.3.0
        github.com/anacrolix/fuse v0.2.0
-       github.com/anacrolix/generics v0.0.2-0.20240227122613-f95486179cab
+       github.com/anacrolix/generics v0.0.3-0.20240902042256-7fb2702ef0ca
        github.com/anacrolix/go-libutp v1.3.1
        github.com/anacrolix/gostdapp v0.1.0
        github.com/anacrolix/log v0.15.3-0.20240627045001-cd912c641d83
diff --git a/go.sum b/go.sum
index 52a865de24139bcaf1218ba901faadcc034e658a..2de5eff7e5c76c0936dc4771b9210664d22f9364 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -80,8 +80,8 @@ github.com/anacrolix/envpprof v1.3.0/go.mod h1:7QIG4CaX1uexQ3tqd5+BRa/9e2D02Wcer
 github.com/anacrolix/fuse v0.2.0 h1:pc+To78kI2d/WUjIyrsdqeJQAesuwpGxlI3h1nAv3Do=
 github.com/anacrolix/fuse v0.2.0/go.mod h1:Kfu02xBwnySDpH3N23BmrP3MDfwAQGRLUCj6XyeOvBQ=
 github.com/anacrolix/generics v0.0.0-20230113004304-d6428d516633/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
-github.com/anacrolix/generics v0.0.2-0.20240227122613-f95486179cab h1:MvuAC/UJtcohN6xWc8zYXSZfllh1LVNepQ0R3BCX5I4=
-github.com/anacrolix/generics v0.0.2-0.20240227122613-f95486179cab/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
+github.com/anacrolix/generics v0.0.3-0.20240902042256-7fb2702ef0ca h1:aiiGqSQWjtVNdi8zUMfA//IrM8fPkv2bWwZVPbDe0wg=
+github.com/anacrolix/generics v0.0.3-0.20240902042256-7fb2702ef0ca/go.mod h1:MN3ve08Z3zSV/rTuX/ouI4lNdlfTxgdafQJiLzyNRB8=
 github.com/anacrolix/go-libutp v1.3.1 h1:idJzreNLl+hNjGC3ZnUOjujEaryeOGgkwHLqSGoige0=
 github.com/anacrolix/go-libutp v1.3.1/go.mod h1:heF41EC8kN0qCLMokLBVkB8NXiLwx3t8R8810MTNI5o=
 github.com/anacrolix/gostdapp v0.1.0 h1:sZC+gSLhA7Hdalak5rPCkhO0YSEl0tt/lsovxh6qka4=
index a87b7c92159dfa81e0ed6da91c9578f22204a759..162047f3aae9c9614481f86980ffd90ea619604d 100644 (file)
@@ -3,12 +3,11 @@ package peer_protocol
 import (
        "context"
        "encoding/hex"
-       "errors"
        "fmt"
+       "github.com/anacrolix/missinggo/v2/panicif"
        "github.com/anacrolix/torrent/internal/ctxrw"
        "io"
        "math/bits"
-       "strconv"
        "strings"
        "unsafe"
 
@@ -153,37 +152,39 @@ func Handshake(
        }()
 
        post := func(bb []byte) {
-               select {
-               case postCh <- bb:
-               default:
-                       panic("mustn't block while posting")
-               }
+               panicif.SendBlocks(postCh, bb)
        }
 
-       post([]byte(Protocol))
+       post(protocolBytes())
        post(extensions[:])
        if ih != nil { // We already know what we want.
                post(ih[:])
                post(peerID[:])
        }
-       var b [68]byte
-       _, err = io.ReadFull(sock, b[:68])
+
+       // Putting an array on the heap still escapes.
+       b := make([]byte, 68)
+       // Read in one hit to avoid potential overhead in underlying reader.
+       _, err = io.ReadFull(sock, b[:])
        if err != nil {
                return res, fmt.Errorf("while reading: %w", err)
        }
-       if string(b[:20]) != Protocol {
-               return res, errors.New("unexpected protocol string")
-       }
 
-       copyExact := func(dst, src []byte) {
-               if dstLen, srcLen := uint64(len(dst)), uint64(len(src)); dstLen != srcLen {
-                       panic("dst len " + strconv.FormatUint(dstLen, 10) + " != src len " + strconv.FormatUint(srcLen, 10))
-               }
-               copy(dst, src)
+       p := b[:len(Protocol)]
+       // This gets optimized to runtime.memequal
+       if string(p) != Protocol {
+               return res, fmt.Errorf("unexpected protocol string %q", string(p))
+       }
+       b = b[len(p):]
+       read := func(dst []byte) {
+               n := copy(dst, b)
+               panicif.NotEq(n, len(dst))
+               b = b[n:]
        }
-       copyExact(res.PeerExtensionBits[:], b[20:28])
-       copyExact(res.Hash[:], b[28:48])
-       copyExact(res.PeerID[:], b[48:68])
+       read(res.PeerExtensionBits[:])
+       read(res.Hash[:])
+       read(res.PeerID[:])
+       panicif.NotEq(len(b), 0)
        // peerExtensions.Add(res.PeerExtensionBits.String(), 1)
 
        // TODO: Maybe we can just drop peers here if we're not interested. This
index b1790d1c1038ee59258f7b09f0ac333549174100..ebd0a7a17b7bb5c53dac6217ecf507f33a289184 100644 (file)
@@ -1,9 +1,19 @@
 package peer_protocol
 
+import (
+       "unsafe"
+)
+
 const (
        Protocol = "\x13BitTorrent protocol"
 )
 
+var protocolStr = Protocol
+
+func protocolBytes() []byte {
+       return unsafe.Slice(unsafe.StringData(Protocol), len(Protocol))
+}
+
 type MessageType byte
 
 // golang.org/x/tools/cmd/stringer