mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-05-03 23:02:27 +00:00
network: rework peer handshaking, fix #458
This allows to start handshaking from both client and server (mainnet/testnet nodes were seen to not care about string ordering for it), but still maintains some sane checks in the process. It also makes functions thread-safe because we have two goroutines servicing read and write side of the Peer connection, so they can clash on access to the struct fields. Add a test for it also.
This commit is contained in:
parent
e859e03240
commit
ec76ed23a5
3 changed files with 117 additions and 46 deletions
83
pkg/network/tcp_peer_test.go
Normal file
83
pkg/network/tcp_peer_test.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/network/payload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func connReadStub(conn net.Conn) {
|
||||
b := make([]byte, 1024)
|
||||
var err error
|
||||
for ; err == nil; _, err = conn.Read(b) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeerHandshake(t *testing.T) {
|
||||
server, client := net.Pipe()
|
||||
|
||||
tcpS := NewTCPPeer(server)
|
||||
tcpC := NewTCPPeer(client)
|
||||
|
||||
// Something should read things written into the pipe.
|
||||
go connReadStub(tcpS.conn)
|
||||
go connReadStub(tcpC.conn)
|
||||
|
||||
// No handshake yet.
|
||||
require.Equal(t, false, tcpS.Handshaked())
|
||||
require.Equal(t, false, tcpC.Handshaked())
|
||||
|
||||
// No ordinary messages can be written.
|
||||
require.Error(t, tcpS.WriteMsg(&Message{}))
|
||||
require.Error(t, tcpC.WriteMsg(&Message{}))
|
||||
|
||||
// Try to mess with VersionAck on both client and server, it should fail.
|
||||
require.Error(t, tcpS.SendVersionAck(&Message{}))
|
||||
require.Error(t, tcpS.HandleVersionAck())
|
||||
require.Error(t, tcpC.SendVersionAck(&Message{}))
|
||||
require.Error(t, tcpC.HandleVersionAck())
|
||||
|
||||
// No handshake yet.
|
||||
require.Equal(t, false, tcpS.Handshaked())
|
||||
require.Equal(t, false, tcpC.Handshaked())
|
||||
|
||||
// Now send and handle versions, but in a different order on client and
|
||||
// server.
|
||||
require.NoError(t, tcpC.SendVersion(&Message{}))
|
||||
require.NoError(t, tcpS.HandleVersion(&payload.Version{}))
|
||||
require.NoError(t, tcpC.HandleVersion(&payload.Version{}))
|
||||
require.NoError(t, tcpS.SendVersion(&Message{}))
|
||||
|
||||
// No handshake yet.
|
||||
require.Equal(t, false, tcpS.Handshaked())
|
||||
require.Equal(t, false, tcpC.Handshaked())
|
||||
|
||||
// These are sent/received and should fail now.
|
||||
require.Error(t, tcpC.SendVersion(&Message{}))
|
||||
require.Error(t, tcpS.HandleVersion(&payload.Version{}))
|
||||
require.Error(t, tcpC.HandleVersion(&payload.Version{}))
|
||||
require.Error(t, tcpS.SendVersion(&Message{}))
|
||||
|
||||
// Now send and handle ACK, again in a different order on client and
|
||||
// server.
|
||||
require.NoError(t, tcpC.SendVersionAck(&Message{}))
|
||||
require.NoError(t, tcpS.HandleVersionAck())
|
||||
require.NoError(t, tcpC.HandleVersionAck())
|
||||
require.NoError(t, tcpS.SendVersionAck(&Message{}))
|
||||
|
||||
// Handshaked now.
|
||||
require.Equal(t, true, tcpS.Handshaked())
|
||||
require.Equal(t, true, tcpC.Handshaked())
|
||||
|
||||
// Subsequent ACKing should fail.
|
||||
require.Error(t, tcpC.SendVersionAck(&Message{}))
|
||||
require.Error(t, tcpS.HandleVersionAck())
|
||||
require.Error(t, tcpC.HandleVersionAck())
|
||||
require.Error(t, tcpS.SendVersionAck(&Message{}))
|
||||
|
||||
// Now regular messaging can proceed.
|
||||
require.NoError(t, tcpS.WriteMsg(&Message{}))
|
||||
require.NoError(t, tcpC.WriteMsg(&Message{}))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue