neorpc: change peer port to int type (fixes nspcc-dev#2910)

This commit is contained in:
Erik van den Brink 2023-04-06 18:33:09 +02:00
parent ce7658ef82
commit f479b2bc57
4 changed files with 83 additions and 15 deletions

View file

@ -114,3 +114,12 @@ for security reasons.
Removal of these options from ProtocolConfiguration is scheduled for May-June Removal of these options from ProtocolConfiguration is scheduled for May-June
2023 (~0.103.0 release). 2023 (~0.103.0 release).
## GetPeers RPC server response type changes and RPC client support
GetPeers RPC command returns a list of Peers where the port type has changed from
string to uint16 to match C#. The RPC client currently supports unmarshalling both
formats.
Removal of Peer unmarshalling with string based ports is scheduled for ~September 2023
(~0.105.0 release).

View file

@ -1,7 +1,9 @@
package result package result
import ( import (
"strings" "encoding/json"
"net"
"strconv"
) )
type ( type (
@ -18,7 +20,7 @@ type (
// Peer represents a peer. // Peer represents a peer.
Peer struct { Peer struct {
Address string `json:"address"` Address string `json:"address"`
Port string `json:"port"` Port uint16 `json:"port"`
} }
) )
@ -49,12 +51,50 @@ 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 {
addressParts := strings.Split(addrs[i], ":") host, portStr, err := net.SplitHostPort(addrs[i])
if err != nil {
continue
}
port, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
port = 0
}
peer := Peer{ peer := Peer{
Address: addressParts[0], Address: host,
Port: addressParts[1], Port: uint16(port),
} }
*p = append(*p, peer) *p = append(*p, peer)
} }
} }
func (p *Peer) UnmarshalJSON(data []byte) error {
type NewPeer Peer
var np NewPeer
err := json.Unmarshal(data, &np)
if err == nil {
*p = Peer(np)
return nil
}
type OldPeer struct {
Address string `json:"address"`
Port string `json:"port"`
}
var op OldPeer
err = json.Unmarshal(data, &op)
if err == nil {
port, err := strconv.ParseUint(op.Port, 10, 16)
if err != nil {
return err
}
*p = Peer{
Address: op.Address,
Port: uint16(port),
}
}
return err
}

View file

@ -1,6 +1,7 @@
package result package result
import ( import (
"encoding/json"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -13,14 +14,31 @@ func TestGetPeers(t *testing.T) {
require.Equal(t, 0, len(gp.Bad)) require.Equal(t, 0, len(gp.Bad))
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"})
gp.AddConnected([]string{"192.168.0.1:10333"}) unsupportedFormat := "2001:DB0:0:123A:::30"
gp.AddBad([]string{"127.0.0.1:20333"}) gp.AddConnected([]string{"192.168.0.1:10333", unsupportedFormat, "[2001:DB0:0:123A::]:30"})
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))
require.Equal(t, 1, len(gp.Connected)) require.Equal(t, 2, len(gp.Connected))
require.Equal(t, 1, 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, "10333", gp.Connected[0].Port) require.Equal(t, uint16(10333), gp.Connected[0].Port)
require.Equal(t, uint16(30), gp.Connected[1].Port)
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, "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{}
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"}]}`
err := json.Unmarshal([]byte(oldPeerFormat), &gps)
require.NoError(t, err)
newPeerFormat := `{"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},{"address": "54.208.117.178","port": 10333}]}`
err = json.Unmarshal([]byte(newPeerFormat), &gps)
require.NoError(t, err)
badIntFormat := `{"unconnected": [{"address": "20.109.188.128","port": 65536}],"connected": [],"bad": []}`
err = json.Unmarshal([]byte(badIntFormat), &gps)
require.Error(t, err)
badStringFormat := `{"unconnected": [{"address": "20.109.188.128","port": "badport"}],"connected": [],"bad": []}`
err = json.Unmarshal([]byte(badStringFormat), &gps)
require.Error(t, err)
} }

View file

@ -700,25 +700,26 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
invoke: func(c *Client) (any, error) { invoke: func(c *Client) (any, error) {
return c.GetPeers() return c.GetPeers()
}, },
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"unconnected":[{"address":"172.200.0.1","port":"20333"}],"connected":[{"address":"127.0.0.1","port":"20335"}],"bad":[{"address":"172.200.0.254","port":"20332"}]}}`, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"unconnected":[{"address":"172.200.0.1","port":20333}],"connected":[{"address":"127.0.0.1","port":20335}],"bad":[{"address":"172.200.0.254","port":20332}]}}`,
result: func(c *Client) any { result: func(c *Client) any {
return &result.GetPeers{ return &result.GetPeers{
Unconnected: result.Peers{ Unconnected: result.Peers{
{ {
Address: "172.200.0.1", Address: "172.200.0.1",
Port: "20333", Port: 20333,
}, },
}, },
Connected: result.Peers{ Connected: result.Peers{
{ {
Address: "127.0.0.1", Address: "127.0.0.1",
Port: "20335", Port: 20335,
}, },
}, },
Bad: result.Peers{ Bad: result.Peers{
{ {
Address: "172.200.0.254", Address: "172.200.0.254",
Port: "20332", Port: 20332,
}, },
}, },
} }