Commit 6fb93a60 authored by Kirill Smelkov's avatar Kirill Smelkov

Merge branch 'master' into t

* master:
  go/neo/neonet: DialLink: Fix SIGSEGV in case client handshake fails
  go/neo/neonet: Demonstrate DialLink misbehaviour when all handshake attempts fail
parents 839ee634 d75f4ac2
// Copyright (C) 2016-2023 Nexedi SA and Contributors.
// Copyright (C) 2016-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
......@@ -319,9 +319,10 @@ func init() {
// DialLink connects to address on given network, performs NEO protocol
// handshake and wraps the connection as NodeLink.
func DialLink(ctx context.Context, net xnet.Networker, addr string) (link *NodeLink, err error) {
func DialLink(ctx context.Context, xnet xnet.Networker, addr string) (link *NodeLink, err error) {
for _, enc := range dialEncTryOrder {
peerConn, err := net.Dial(ctx, addr)
var peerConn net.Conn
peerConn, err = xnet.Dial(ctx, addr)
if err != nil {
return nil, err
}
......
// Copyright (C) 2016-2023 Nexedi SA and Contributors.
// Copyright (C) 2016-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
......@@ -28,6 +28,8 @@ import (
"testing"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/xnet/pipenet"
"lab.nexedi.com/kirr/go123/xnet/virtnet"
"lab.nexedi.com/kirr/go123/xsync"
"lab.nexedi.com/kirr/neo/go/neo/proto"
)
......@@ -223,6 +225,69 @@ func _TestHandshake(t *T) {
}
}
// TestDialLink_AllHandshakeErr verifies that DialLink returns an error if all handshake attempts fail.
func TestDialLink_AllHandshakeErr(t *testing.T) {
X := exc.Raiseif
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
net := pipenet.New("")
c := net.Host("client")
s := net.Host("server")
l, err := s.Listen(ctx, ":1"); X(err)
defer xclose(l)
allGood := false
wg := xsync.NewWorkGroup(ctx)
// server accepts all connections but rejects any handshake
gox(wg, func(ctx context.Context) {
for {
X(ctx.Err())
conn, err := l.Accept(ctx); X(err)
xclose(conn)
}
})
// client tries to connect and handshake with server, but handshake should fail
gox(wg, func(ctx context.Context) {
xaddr := func (addr string) *virtnet.Addr {
a, err := virtnet.ParseAddr(net.Network(), addr); X(err)
return a
}
errOk := &_HandshakeError{_LinkClient, xaddr("client:1"), xaddr("server:2"), io.ErrUnexpectedEOF}
var errHand *_HandshakeError
link, err := DialLink(ctx, c, "server:1")
if link == nil && errors.As(err, &errHand) {
// we cannot reliably reason about underlying IO error cause because it is
// set by another package internally. Stub that with io.ErrUnexpectedEOF .
errHand.Err = io.ErrUnexpectedEOF
if reflect.DeepEqual(errHand, errOk) {
allGood = true
cancel()
return
}
}
exc.Raisef("DialLink to handshake-rejecting server:\nhave: link=%v err=%v\nwant: link=%v err=%v",
link, err, nil, errOk)
})
err = wg.Wait()
if allGood {
if ctx.Err() == nil {
panic("all good but ctx not canceled")
}
err = nil
}
X(err)
}
// estr returns err.Error() or "<nil>".
func estr(err error) string {
if err == nil {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment