mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-22 09:29:38 +00:00
neorpc: extend getpeers method
Signed-off-by: edgedlt <edgedlt@protonmail.com>
This commit is contained in:
parent
cf4d4a2611
commit
aab2620548
6 changed files with 77 additions and 18 deletions
|
@ -207,6 +207,15 @@ the error-free C# response that provides a default result.
|
||||||
NeoGo can generate an error in response to an invalid proof, unlike
|
NeoGo can generate an error in response to an invalid proof, unlike
|
||||||
the error-free C# implementation.
|
the error-free C# implementation.
|
||||||
|
|
||||||
|
##### `getPeers`
|
||||||
|
|
||||||
|
NeoGo extends the `getpeers` RPC call to return the user agent
|
||||||
|
(`useragent` JSON field) and last known block height
|
||||||
|
(`lastknownheight` JSON field) for each connected peer where available.
|
||||||
|
The last known block height field may be stale depending on the
|
||||||
|
PingInterval node config and the time since the last ping.
|
||||||
|
Ping behavior may also differ between node implementations.
|
||||||
|
|
||||||
### Unsupported methods
|
### Unsupported methods
|
||||||
|
|
||||||
Methods listed below are not going to be supported for various reasons
|
Methods listed below are not going to be supported for various reasons
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -19,8 +21,10 @@ type (
|
||||||
|
|
||||||
// Peer represents a peer.
|
// Peer represents a peer.
|
||||||
Peer struct {
|
Peer struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
|
UserAgent string `json:"useragent,omitempty"`
|
||||||
|
LastKnownHeight uint32 `json:"lastknownheight,omitempty"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,9 +42,9 @@ func (g *GetPeers) AddUnconnected(addrs []string) {
|
||||||
g.Unconnected.addPeers(addrs)
|
g.Unconnected.addPeers(addrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddConnected adds a set of peers to the connected peers slice.
|
// AddConnected adds a set of connected peers to the connected peers slice.
|
||||||
func (g *GetPeers) AddConnected(addrs []string) {
|
func (g *GetPeers) AddConnected(connectedPeers []network.PeerInfo) {
|
||||||
g.Connected.addPeers(addrs)
|
g.Connected.addConnectedPeers(connectedPeers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddBad adds a set of peers to the bad peers slice.
|
// AddBad adds a set of peers to the bad peers slice.
|
||||||
|
@ -51,17 +55,31 @@ func (g *GetPeers) AddBad(addrs []string) {
|
||||||
// addPeers adds a set of peers to the given peer slice.
|
// addPeers adds a set of peers to the given peer slice.
|
||||||
func (p *Peers) addPeers(addrs []string) {
|
func (p *Peers) addPeers(addrs []string) {
|
||||||
for i := range addrs {
|
for i := range addrs {
|
||||||
host, portStr, err := net.SplitHostPort(addrs[i])
|
host, port, err := parseHostPort(addrs[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
port, err := strconv.ParseUint(portStr, 10, 16)
|
|
||||||
if err != nil {
|
|
||||||
port = 0
|
|
||||||
}
|
|
||||||
peer := Peer{
|
peer := Peer{
|
||||||
Address: host,
|
Address: host,
|
||||||
Port: uint16(port),
|
Port: port,
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = append(*p, peer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addConnectedPeers adds a set of connected peers to the given peer slice.
|
||||||
|
func (p *Peers) addConnectedPeers(connectedPeers []network.PeerInfo) {
|
||||||
|
for i := range connectedPeers {
|
||||||
|
host, port, err := parseHostPort(connectedPeers[i].Address)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
peer := Peer{
|
||||||
|
Address: host,
|
||||||
|
Port: port,
|
||||||
|
UserAgent: connectedPeers[i].UserAgent,
|
||||||
|
LastKnownHeight: connectedPeers[i].Height,
|
||||||
}
|
}
|
||||||
|
|
||||||
*p = append(*p, peer)
|
*p = append(*p, peer)
|
||||||
|
@ -98,3 +116,14 @@ func (p *Peer) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseHostPort parses host and port from the given address.
|
||||||
|
// An improperly formatted port string will return zero port.
|
||||||
|
func parseHostPort(addr string) (string, uint16, error) {
|
||||||
|
host, portStr, err := net.SplitHostPort(addr)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
port, _ := strconv.ParseUint(portStr, 10, 16)
|
||||||
|
return host, uint16(port), nil
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/network"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,7 +16,11 @@ func TestGetPeers(t *testing.T) {
|
||||||
|
|
||||||
gp.AddUnconnected([]string{"1.1.1.1:53", "8.8.8.8:53", "9.9.9.9:53"})
|
gp.AddUnconnected([]string{"1.1.1.1:53", "8.8.8.8:53", "9.9.9.9:53"})
|
||||||
unsupportedFormat := "2001:DB0:0:123A:::30"
|
unsupportedFormat := "2001:DB0:0:123A:::30"
|
||||||
gp.AddConnected([]string{"192.168.0.1:10333", unsupportedFormat, "[2001:DB0:0:123A::]:30"})
|
gp.AddConnected([]network.PeerInfo{
|
||||||
|
{Address: "192.168.0.1:10333", UserAgent: "/NEO-GO:0.106.2/", Height: 100},
|
||||||
|
{Address: unsupportedFormat, UserAgent: "", Height: 0},
|
||||||
|
{Address: "[2001:DB0:0:123A::]:30", UserAgent: "/NEO-GO:0.106.2/", Height: 200},
|
||||||
|
})
|
||||||
gp.AddBad([]string{"127.0.0.1:20333", "127.0.0.1:65536"})
|
gp.AddBad([]string{"127.0.0.1:20333", "127.0.0.1:65536"})
|
||||||
|
|
||||||
require.Equal(t, 3, len(gp.Unconnected))
|
require.Equal(t, 3, len(gp.Unconnected))
|
||||||
|
@ -23,10 +28,13 @@ func TestGetPeers(t *testing.T) {
|
||||||
require.Equal(t, 2, len(gp.Bad))
|
require.Equal(t, 2, len(gp.Bad))
|
||||||
require.Equal(t, "192.168.0.1", gp.Connected[0].Address)
|
require.Equal(t, "192.168.0.1", gp.Connected[0].Address)
|
||||||
require.Equal(t, uint16(10333), gp.Connected[0].Port)
|
require.Equal(t, uint16(10333), gp.Connected[0].Port)
|
||||||
|
require.Equal(t, "/NEO-GO:0.106.2/", gp.Connected[0].UserAgent)
|
||||||
|
require.Equal(t, uint32(100), gp.Connected[0].LastKnownHeight)
|
||||||
require.Equal(t, uint16(30), gp.Connected[1].Port)
|
require.Equal(t, uint16(30), gp.Connected[1].Port)
|
||||||
|
require.Equal(t, "/NEO-GO:0.106.2/", gp.Connected[1].UserAgent)
|
||||||
|
require.Equal(t, uint32(200), gp.Connected[1].LastKnownHeight)
|
||||||
require.Equal(t, "127.0.0.1", gp.Bad[0].Address)
|
require.Equal(t, "127.0.0.1", gp.Bad[0].Address)
|
||||||
require.Equal(t, uint16(20333), gp.Bad[0].Port)
|
require.Equal(t, uint16(20333), gp.Bad[0].Port)
|
||||||
require.Equal(t, uint16(0), gp.Bad[1].Port)
|
|
||||||
|
|
||||||
gps := GetPeers{}
|
gps := GetPeers{}
|
||||||
oldPeerFormat := `{"unconnected": [{"address": "20.109.188.128","port": "10333"},{"address": "27.188.182.47","port": "10333"}],"connected": [{"address": "54.227.43.72","port": "10333"},{"address": "157.90.177.38","port": "10333"}],"bad": [{"address": "5.226.142.226","port": "10333"}]}`
|
oldPeerFormat := `{"unconnected": [{"address": "20.109.188.128","port": "10333"},{"address": "27.188.182.47","port": "10333"}],"connected": [{"address": "54.227.43.72","port": "10333"},{"address": "157.90.177.38","port": "10333"}],"bad": [{"address": "5.226.142.226","port": "10333"}]}`
|
||||||
|
|
|
@ -7,6 +7,13 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PeerInfo represents the info for a connected peer.
|
||||||
|
type PeerInfo struct {
|
||||||
|
Address string
|
||||||
|
UserAgent string
|
||||||
|
Height uint32
|
||||||
|
}
|
||||||
|
|
||||||
type AddressablePeer interface {
|
type AddressablePeer interface {
|
||||||
// ConnectionAddr returns an address-like identifier of this connection
|
// ConnectionAddr returns an address-like identifier of this connection
|
||||||
// before we have a proper one (after the handshake). It's either the
|
// before we have a proper one (after the handshake). It's either the
|
||||||
|
|
|
@ -427,13 +427,17 @@ func (s *Server) BadPeers() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectedPeers returns a list of currently connected peers.
|
// ConnectedPeers returns a list of currently connected peers.
|
||||||
func (s *Server) ConnectedPeers() []string {
|
func (s *Server) ConnectedPeers() []PeerInfo {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
peers := make([]string, 0, len(s.peers))
|
peers := make([]PeerInfo, 0, len(s.peers))
|
||||||
for k := range s.peers {
|
for k := range s.peers {
|
||||||
peers = append(peers, k.PeerAddr().String())
|
peers = append(peers, PeerInfo{
|
||||||
|
Address: k.PeerAddr().String(),
|
||||||
|
UserAgent: string(k.Version().UserAgent),
|
||||||
|
Height: k.LastBlockIndex(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return peers
|
return peers
|
||||||
|
|
|
@ -580,8 +580,10 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
},
|
},
|
||||||
Connected: result.Peers{
|
Connected: result.Peers{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
Port: 20335,
|
Port: 20335,
|
||||||
|
UserAgent: "/NEO-GO:0.106.2/",
|
||||||
|
LastKnownHeight: 1000,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Bad: result.Peers{
|
Bad: result.Peers{
|
||||||
|
|
Loading…
Reference in a new issue