mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 11:45:18 +00:00
p2p, types: remove legacy NetAddress type (#7084)
This commit is contained in:
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/tendermint/tendermint/abci/example/kvstore"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
cstypes "github.com/tendermint/tendermint/internal/consensus/types"
|
||||
p2pmock "github.com/tendermint/tendermint/internal/p2p/mock"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
@@ -1864,7 +1863,8 @@ func TestStateOutputsBlockPartsStats(t *testing.T) {
|
||||
|
||||
// create dummy peer
|
||||
cs, _ := randState(config, 1)
|
||||
peer := p2pmock.NewPeer(nil)
|
||||
peerID, err := types.NewNodeID("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
||||
require.NoError(t, err)
|
||||
|
||||
// 1) new block part
|
||||
parts := types.NewPartSetFromData(tmrand.Bytes(100), 10)
|
||||
@@ -1875,26 +1875,26 @@ func TestStateOutputsBlockPartsStats(t *testing.T) {
|
||||
}
|
||||
|
||||
cs.ProposalBlockParts = types.NewPartSetFromHeader(parts.Header())
|
||||
cs.handleMsg(msgInfo{msg, peer.ID()})
|
||||
cs.handleMsg(msgInfo{msg, peerID})
|
||||
|
||||
statsMessage := <-cs.statsMsgQueue
|
||||
require.Equal(t, msg, statsMessage.Msg, "")
|
||||
require.Equal(t, peer.ID(), statsMessage.PeerID, "")
|
||||
require.Equal(t, peerID, statsMessage.PeerID, "")
|
||||
|
||||
// sending the same part from different peer
|
||||
cs.handleMsg(msgInfo{msg, "peer2"})
|
||||
|
||||
// sending the part with the same height, but different round
|
||||
msg.Round = 1
|
||||
cs.handleMsg(msgInfo{msg, peer.ID()})
|
||||
cs.handleMsg(msgInfo{msg, peerID})
|
||||
|
||||
// sending the part from the smaller height
|
||||
msg.Height = 0
|
||||
cs.handleMsg(msgInfo{msg, peer.ID()})
|
||||
cs.handleMsg(msgInfo{msg, peerID})
|
||||
|
||||
// sending the part from the bigger height
|
||||
msg.Height = 3
|
||||
cs.handleMsg(msgInfo{msg, peer.ID()})
|
||||
cs.handleMsg(msgInfo{msg, peerID})
|
||||
|
||||
select {
|
||||
case <-cs.statsMsgQueue:
|
||||
@@ -1909,18 +1909,19 @@ func TestStateOutputVoteStats(t *testing.T) {
|
||||
|
||||
cs, vss := randState(config, 2)
|
||||
// create dummy peer
|
||||
peer := p2pmock.NewPeer(nil)
|
||||
peerID, err := types.NewNodeID("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
||||
require.NoError(t, err)
|
||||
|
||||
randBytes := tmrand.Bytes(tmhash.Size)
|
||||
|
||||
vote := signVote(vss[1], config, tmproto.PrecommitType, randBytes, types.PartSetHeader{})
|
||||
|
||||
voteMessage := &VoteMessage{vote}
|
||||
cs.handleMsg(msgInfo{voteMessage, peer.ID()})
|
||||
cs.handleMsg(msgInfo{voteMessage, peerID})
|
||||
|
||||
statsMessage := <-cs.statsMsgQueue
|
||||
require.Equal(t, voteMessage, statsMessage.Msg, "")
|
||||
require.Equal(t, peer.ID(), statsMessage.PeerID, "")
|
||||
require.Equal(t, peerID, statsMessage.PeerID, "")
|
||||
|
||||
// sending the same part from different peer
|
||||
cs.handleMsg(msgInfo{&VoteMessage{vote}, "peer2"})
|
||||
@@ -1929,7 +1930,7 @@ func TestStateOutputVoteStats(t *testing.T) {
|
||||
incrementHeight(vss[1])
|
||||
vote = signVote(vss[1], config, tmproto.PrecommitType, randBytes, types.PartSetHeader{})
|
||||
|
||||
cs.handleMsg(msgInfo{&VoteMessage{vote}, peer.ID()})
|
||||
cs.handleMsg(msgInfo{&VoteMessage{vote}, peerID})
|
||||
|
||||
select {
|
||||
case <-cs.statsMsgQueue:
|
||||
|
||||
@@ -17,7 +17,7 @@ func (e ErrFilterTimeout) Error() string {
|
||||
// ErrRejected indicates that a Peer was rejected carrying additional
|
||||
// information as to the reason.
|
||||
type ErrRejected struct {
|
||||
addr NetAddress
|
||||
addr NodeAddress
|
||||
conn net.Conn
|
||||
err error
|
||||
id types.NodeID
|
||||
@@ -30,7 +30,7 @@ type ErrRejected struct {
|
||||
}
|
||||
|
||||
// Addr returns the NetAddress for the rejected Peer.
|
||||
func (e ErrRejected) Addr() NetAddress {
|
||||
func (e ErrRejected) Addr() NodeAddress {
|
||||
return e.addr
|
||||
}
|
||||
|
||||
@@ -120,15 +120,15 @@ func (e ErrSwitchDuplicatePeerIP) Error() string {
|
||||
|
||||
// ErrSwitchConnectToSelf to be raised when trying to connect to itself.
|
||||
type ErrSwitchConnectToSelf struct {
|
||||
Addr *NetAddress
|
||||
Addr *NodeAddress
|
||||
}
|
||||
|
||||
func (e ErrSwitchConnectToSelf) Error() string {
|
||||
return fmt.Sprintf("connect to self: %v", e.Addr)
|
||||
return fmt.Sprintf("connect to self: %s", e.Addr)
|
||||
}
|
||||
|
||||
type ErrSwitchAuthenticationFailure struct {
|
||||
Dialed *NetAddress
|
||||
Dialed *NodeAddress
|
||||
Got types.NodeID
|
||||
}
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/tendermint/tendermint/internal/p2p"
|
||||
"github.com/tendermint/tendermint/libs/service"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
type Peer struct {
|
||||
*service.BaseService
|
||||
ip net.IP
|
||||
id types.NodeID
|
||||
addr *p2p.NetAddress
|
||||
kv map[string]interface{}
|
||||
Outbound, Persistent bool
|
||||
}
|
||||
|
||||
// NewPeer creates and starts a new mock peer. If the ip
|
||||
// is nil, random routable address is used.
|
||||
func NewPeer(ip net.IP) *Peer {
|
||||
var netAddr *p2p.NetAddress
|
||||
if ip == nil {
|
||||
_, netAddr = p2p.CreateRoutableAddr()
|
||||
} else {
|
||||
netAddr = types.NewNetAddressIPPort(ip, 26656)
|
||||
}
|
||||
nodeKey := types.GenNodeKey()
|
||||
netAddr.ID = nodeKey.ID
|
||||
mp := &Peer{
|
||||
ip: ip,
|
||||
id: nodeKey.ID,
|
||||
addr: netAddr,
|
||||
kv: make(map[string]interface{}),
|
||||
}
|
||||
mp.BaseService = service.NewBaseService(nil, "MockPeer", mp)
|
||||
if err := mp.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
func (mp *Peer) FlushStop() { mp.Stop() } //nolint:errcheck //ignore error
|
||||
func (mp *Peer) TrySend(chID byte, msgBytes []byte) bool { return true }
|
||||
func (mp *Peer) Send(chID byte, msgBytes []byte) bool { return true }
|
||||
func (mp *Peer) NodeInfo() types.NodeInfo {
|
||||
return types.NodeInfo{
|
||||
NodeID: mp.addr.ID,
|
||||
ListenAddr: mp.addr.DialString(),
|
||||
}
|
||||
}
|
||||
|
||||
func (mp *Peer) ID() types.NodeID { return mp.id }
|
||||
func (mp *Peer) IsOutbound() bool { return mp.Outbound }
|
||||
func (mp *Peer) IsPersistent() bool { return mp.Persistent }
|
||||
func (mp *Peer) Get(key string) interface{} {
|
||||
if value, ok := mp.kv[key]; ok {
|
||||
return value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (mp *Peer) Set(key string, value interface{}) {
|
||||
mp.kv[key] = value
|
||||
}
|
||||
func (mp *Peer) RemoteIP() net.IP { return mp.ip }
|
||||
func (mp *Peer) SocketAddr() *p2p.NetAddress { return mp.addr }
|
||||
func (mp *Peer) RemoteAddr() net.Addr { return &net.TCPAddr{IP: mp.ip, Port: 8800} }
|
||||
func (mp *Peer) CloseConn() error { return nil }
|
||||
@@ -1,319 +0,0 @@
|
||||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
log "github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
net "net"
|
||||
|
||||
types "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// Peer is an autogenerated mock type for the Peer type
|
||||
type Peer struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// CloseConn provides a mock function with given fields:
|
||||
func (_m *Peer) CloseConn() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// FlushStop provides a mock function with given fields:
|
||||
func (_m *Peer) FlushStop() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: _a0
|
||||
func (_m *Peer) Get(_a0 string) interface{} {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
var r0 interface{}
|
||||
if rf, ok := ret.Get(0).(func(string) interface{}); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(interface{})
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ID provides a mock function with given fields:
|
||||
func (_m *Peer) ID() types.NodeID {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 types.NodeID
|
||||
if rf, ok := ret.Get(0).(func() types.NodeID); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.NodeID)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// IsOutbound provides a mock function with given fields:
|
||||
func (_m *Peer) IsOutbound() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// IsPersistent provides a mock function with given fields:
|
||||
func (_m *Peer) IsPersistent() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// IsRunning provides a mock function with given fields:
|
||||
func (_m *Peer) IsRunning() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// NodeInfo provides a mock function with given fields:
|
||||
func (_m *Peer) NodeInfo() types.NodeInfo {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 types.NodeInfo
|
||||
if rf, ok := ret.Get(0).(func() types.NodeInfo); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.NodeInfo)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OnReset provides a mock function with given fields:
|
||||
func (_m *Peer) OnReset() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OnStart provides a mock function with given fields:
|
||||
func (_m *Peer) OnStart() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OnStop provides a mock function with given fields:
|
||||
func (_m *Peer) OnStop() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// Quit provides a mock function with given fields:
|
||||
func (_m *Peer) Quit() <-chan struct{} {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 <-chan struct{}
|
||||
if rf, ok := ret.Get(0).(func() <-chan struct{}); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(<-chan struct{})
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoteAddr provides a mock function with given fields:
|
||||
func (_m *Peer) RemoteAddr() net.Addr {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 net.Addr
|
||||
if rf, ok := ret.Get(0).(func() net.Addr); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(net.Addr)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoteIP provides a mock function with given fields:
|
||||
func (_m *Peer) RemoteIP() net.IP {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 net.IP
|
||||
if rf, ok := ret.Get(0).(func() net.IP); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(net.IP)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Reset provides a mock function with given fields:
|
||||
func (_m *Peer) Reset() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Send provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Peer) Send(_a0 byte, _a1 []byte) bool {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(byte, []byte) bool); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Set provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Peer) Set(_a0 string, _a1 interface{}) {
|
||||
_m.Called(_a0, _a1)
|
||||
}
|
||||
|
||||
// SetLogger provides a mock function with given fields: _a0
|
||||
func (_m *Peer) SetLogger(_a0 log.Logger) {
|
||||
_m.Called(_a0)
|
||||
}
|
||||
|
||||
// SocketAddr provides a mock function with given fields:
|
||||
func (_m *Peer) SocketAddr() *types.NetAddress {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 *types.NetAddress
|
||||
if rf, ok := ret.Get(0).(func() *types.NetAddress); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.NetAddress)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Start provides a mock function with given fields:
|
||||
func (_m *Peer) Start() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Stop provides a mock function with given fields:
|
||||
func (_m *Peer) Stop() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// String provides a mock function with given fields:
|
||||
func (_m *Peer) String() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TrySend provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Peer) TrySend(_a0 byte, _a1 []byte) bool {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(byte, []byte) bool); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Wait provides a mock function with given fields:
|
||||
func (_m *Peer) Wait() {
|
||||
_m.Called()
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// Modified for Tendermint
|
||||
// Originally Copyright (c) 2013-2014 Conformal Systems LLC.
|
||||
// https://github.com/conformal/btcd/blob/master/LICENSE
|
||||
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
type NetAddress = types.NetAddress
|
||||
@@ -1,78 +0,0 @@
|
||||
package pex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/internal/p2p"
|
||||
)
|
||||
|
||||
type ErrAddrBookNonRoutable struct {
|
||||
Addr *p2p.NetAddress
|
||||
}
|
||||
|
||||
func (err ErrAddrBookNonRoutable) Error() string {
|
||||
return fmt.Sprintf("Cannot add non-routable address %v", err.Addr)
|
||||
}
|
||||
|
||||
type ErrAddrBookSelf struct {
|
||||
Addr *p2p.NetAddress
|
||||
}
|
||||
|
||||
func (err ErrAddrBookSelf) Error() string {
|
||||
return fmt.Sprintf("Cannot add ourselves with address %v", err.Addr)
|
||||
}
|
||||
|
||||
type ErrAddrBookPrivate struct {
|
||||
Addr *p2p.NetAddress
|
||||
}
|
||||
|
||||
func (err ErrAddrBookPrivate) Error() string {
|
||||
return fmt.Sprintf("Cannot add private peer with address %v", err.Addr)
|
||||
}
|
||||
|
||||
func (err ErrAddrBookPrivate) PrivateAddr() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type ErrAddrBookPrivateSrc struct {
|
||||
Src *p2p.NetAddress
|
||||
}
|
||||
|
||||
func (err ErrAddrBookPrivateSrc) Error() string {
|
||||
return fmt.Sprintf("Cannot add peer coming from private peer with address %v", err.Src)
|
||||
}
|
||||
|
||||
func (err ErrAddrBookPrivateSrc) PrivateAddr() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type ErrAddrBookNilAddr struct {
|
||||
Addr *p2p.NetAddress
|
||||
Src *p2p.NetAddress
|
||||
}
|
||||
|
||||
func (err ErrAddrBookNilAddr) Error() string {
|
||||
return fmt.Sprintf("Cannot add a nil address. Got (addr, src) = (%v, %v)", err.Addr, err.Src)
|
||||
}
|
||||
|
||||
type ErrAddrBookInvalidAddr struct {
|
||||
Addr *p2p.NetAddress
|
||||
AddrErr error
|
||||
}
|
||||
|
||||
func (err ErrAddrBookInvalidAddr) Error() string {
|
||||
return fmt.Sprintf("Cannot add invalid address %v: %v", err.Addr, err.AddrErr)
|
||||
}
|
||||
|
||||
// ErrAddressBanned is thrown when the address has been banned and therefore cannot be used
|
||||
type ErrAddressBanned struct {
|
||||
Addr *p2p.NetAddress
|
||||
}
|
||||
|
||||
func (err ErrAddressBanned) Error() string {
|
||||
return fmt.Sprintf("Address: %v is currently banned", err.Addr)
|
||||
}
|
||||
|
||||
// ErrUnsolicitedList is thrown when a peer provides a list of addresses that have not been asked for.
|
||||
var ErrUnsolicitedList = errors.New("unsolicited pexAddrsMessage")
|
||||
@@ -1012,13 +1012,11 @@ func (r *Router) NodeInfo() types.NodeInfo {
|
||||
|
||||
// OnStart implements service.Service.
|
||||
func (r *Router) OnStart() error {
|
||||
netAddr, _ := r.nodeInfo.NetAddress()
|
||||
r.Logger.Info(
|
||||
"starting router",
|
||||
"node_id", r.nodeInfo.NodeID,
|
||||
"channels", r.nodeInfo.Channels,
|
||||
"listen_addr", r.nodeInfo.ListenAddr,
|
||||
"net_addr", netAddr,
|
||||
)
|
||||
|
||||
go r.dialPeers()
|
||||
|
||||
@@ -367,7 +367,7 @@ func TestRouter_AcceptPeers(t *testing.T) {
|
||||
mockTransport.On("Protocols").Return([]p2p.Protocol{"mock"})
|
||||
mockTransport.On("Close").Return(nil)
|
||||
mockTransport.On("Accept").Once().Return(mockConnection, nil)
|
||||
mockTransport.On("Accept").Once().Return(nil, io.EOF)
|
||||
mockTransport.On("Accept").Maybe().Return(nil, io.EOF)
|
||||
|
||||
// Set up and start the router.
|
||||
peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
|
||||
@@ -755,7 +755,7 @@ func TestRouter_EvictPeers(t *testing.T) {
|
||||
mockTransport.On("Protocols").Return([]p2p.Protocol{"mock"})
|
||||
mockTransport.On("Close").Return(nil)
|
||||
mockTransport.On("Accept").Once().Return(mockConnection, nil)
|
||||
mockTransport.On("Accept").Once().Return(nil, io.EOF)
|
||||
mockTransport.On("Accept").Maybe().Return(nil, io.EOF)
|
||||
|
||||
// Set up and start the router.
|
||||
peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
|
||||
@@ -869,7 +869,7 @@ func TestRouter_DontSendOnInvalidChannel(t *testing.T) {
|
||||
mockTransport.On("Protocols").Return([]p2p.Protocol{"mock"})
|
||||
mockTransport.On("Close").Return(nil)
|
||||
mockTransport.On("Accept").Once().Return(mockConnection, nil)
|
||||
mockTransport.On("Accept").Once().Return(nil, io.EOF)
|
||||
mockTransport.On("Accept").Maybe().Return(nil, io.EOF)
|
||||
|
||||
// Set up and start the router.
|
||||
peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
mrand "math/rand"
|
||||
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// nolint:gosec // G404: Use of weak random number generator
|
||||
func CreateRoutableAddr() (addr string, netAddr *NetAddress) {
|
||||
for {
|
||||
var err error
|
||||
addr = fmt.Sprintf("%X@%v.%v.%v.%v:26656",
|
||||
tmrand.Bytes(20),
|
||||
mrand.Int()%256,
|
||||
mrand.Int()%256,
|
||||
mrand.Int()%256,
|
||||
mrand.Int()%256)
|
||||
netAddr, err = types.NewNetAddressString(addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if netAddr.Routable() {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -122,12 +122,17 @@ type Endpoint struct {
|
||||
}
|
||||
|
||||
// NewEndpoint constructs an Endpoint from a types.NetAddress structure.
|
||||
func NewEndpoint(na *types.NetAddress) Endpoint {
|
||||
func NewEndpoint(addr string) (Endpoint, error) {
|
||||
ip, port, err := types.ParseAddressString(addr)
|
||||
if err != nil {
|
||||
return Endpoint{}, err
|
||||
}
|
||||
|
||||
return Endpoint{
|
||||
Protocol: MConnProtocol,
|
||||
IP: na.IP,
|
||||
Port: na.Port,
|
||||
}
|
||||
IP: ip,
|
||||
Port: port,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NodeAddress converts the endpoint into a NodeAddress for the given node ID.
|
||||
|
||||
@@ -520,11 +520,11 @@ func (n *nodeImpl) OnStart() error {
|
||||
}
|
||||
|
||||
// Start the transport.
|
||||
addr, err := types.NewNetAddressString(n.nodeKey.ID.AddressString(n.config.P2P.ListenAddress))
|
||||
ep, err := p2p.NewEndpoint(n.nodeKey.ID.AddressString(n.config.P2P.ListenAddress))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.transport.Listen(p2p.NewEndpoint(addr)); err != nil {
|
||||
if err := n.transport.Listen(ep); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
// Modified for Tendermint
|
||||
// Originally Copyright (c) 2013-2014 Conformal Systems LLC.
|
||||
// https://github.com/conformal/btcd/blob/master/LICENSE
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// EmptyNetAddress defines the string representation of an empty NetAddress
|
||||
const EmptyNetAddress = "<nil-NetAddress>"
|
||||
|
||||
// NetAddress defines information about a peer on the network
|
||||
// including its ID, IP address, and port.
|
||||
type NetAddress struct {
|
||||
ID NodeID `json:"id"`
|
||||
IP net.IP `json:"ip"`
|
||||
Port uint16 `json:"port"`
|
||||
}
|
||||
|
||||
// NewNetAddress returns a new NetAddress using the provided TCP
|
||||
// address. When testing, other net.Addr (except TCP) will result in
|
||||
// using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will
|
||||
// panic. Panics if ID is invalid.
|
||||
// TODO: socks proxies?
|
||||
func NewNetAddress(id NodeID, addr net.Addr) *NetAddress {
|
||||
tcpAddr, ok := addr.(*net.TCPAddr)
|
||||
if !ok {
|
||||
if flag.Lookup("test.v") == nil { // normal run
|
||||
panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr))
|
||||
} else { // in testing
|
||||
netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0)
|
||||
netAddr.ID = id
|
||||
return netAddr
|
||||
}
|
||||
}
|
||||
|
||||
if err := id.Validate(); err != nil {
|
||||
panic(fmt.Sprintf("Invalid ID %v: %v (addr: %v)", id, err, addr))
|
||||
}
|
||||
|
||||
ip := tcpAddr.IP
|
||||
port := uint16(tcpAddr.Port)
|
||||
na := NewNetAddressIPPort(ip, port)
|
||||
na.ID = id
|
||||
return na
|
||||
}
|
||||
|
||||
// NewNetAddressIPPort returns a new NetAddress using the provided IP
|
||||
// and port number.
|
||||
func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress {
|
||||
return &NetAddress{
|
||||
IP: ip,
|
||||
Port: port,
|
||||
}
|
||||
}
|
||||
|
||||
// NewNetAddressString returns a new NetAddress using the provided address in
|
||||
// the form of "ID@IP:Port".
|
||||
// Also resolves the host if host is not an IP.
|
||||
// Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup)
|
||||
func NewNetAddressString(addr string) (*NetAddress, error) {
|
||||
addrWithoutProtocol := removeProtocolIfDefined(addr)
|
||||
spl := strings.Split(addrWithoutProtocol, "@")
|
||||
if len(spl) != 2 {
|
||||
return nil, ErrNetAddressNoID{addr}
|
||||
}
|
||||
|
||||
id, err := NewNodeID(spl[0])
|
||||
if err != nil {
|
||||
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
|
||||
}
|
||||
|
||||
if err := id.Validate(); err != nil {
|
||||
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
|
||||
}
|
||||
|
||||
addrWithoutProtocol = spl[1]
|
||||
|
||||
// get host and port
|
||||
host, portStr, err := net.SplitHostPort(addrWithoutProtocol)
|
||||
if err != nil {
|
||||
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
|
||||
}
|
||||
if len(host) == 0 {
|
||||
return nil, ErrNetAddressInvalid{
|
||||
addrWithoutProtocol,
|
||||
errors.New("host is empty")}
|
||||
}
|
||||
|
||||
ip := net.ParseIP(host)
|
||||
if ip == nil {
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
return nil, ErrNetAddressLookup{host, err}
|
||||
}
|
||||
ip = ips[0]
|
||||
}
|
||||
|
||||
port, err := strconv.ParseUint(portStr, 10, 16)
|
||||
if err != nil {
|
||||
return nil, ErrNetAddressInvalid{portStr, err}
|
||||
}
|
||||
|
||||
na := NewNetAddressIPPort(ip, uint16(port))
|
||||
na.ID = id
|
||||
return na, nil
|
||||
}
|
||||
|
||||
// Equals reports whether na and other are the same addresses,
|
||||
// including their ID, IP, and Port.
|
||||
func (na *NetAddress) Equals(other interface{}) bool {
|
||||
if o, ok := other.(*NetAddress); ok {
|
||||
return na.String() == o.String()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Same returns true is na has the same non-empty ID or DialString as other.
|
||||
func (na *NetAddress) Same(other interface{}) bool {
|
||||
if o, ok := other.(*NetAddress); ok {
|
||||
if na.DialString() == o.DialString() {
|
||||
return true
|
||||
}
|
||||
if na.ID != "" && na.ID == o.ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// String representation: <ID>@<IP>:<PORT>
|
||||
func (na *NetAddress) String() string {
|
||||
if na == nil {
|
||||
return EmptyNetAddress
|
||||
}
|
||||
|
||||
addrStr := na.DialString()
|
||||
if na.ID != "" {
|
||||
addrStr = na.ID.AddressString(addrStr)
|
||||
}
|
||||
|
||||
return addrStr
|
||||
}
|
||||
|
||||
func (na *NetAddress) DialString() string {
|
||||
if na == nil {
|
||||
return "<nil-NetAddress>"
|
||||
}
|
||||
return net.JoinHostPort(
|
||||
na.IP.String(),
|
||||
strconv.FormatUint(uint64(na.Port), 10),
|
||||
)
|
||||
}
|
||||
|
||||
// Dial calls net.Dial on the address.
|
||||
func (na *NetAddress) Dial() (net.Conn, error) {
|
||||
conn, err := net.Dial("tcp", na.DialString())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// DialTimeout calls net.DialTimeout on the address.
|
||||
func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) {
|
||||
conn, err := net.DialTimeout("tcp", na.DialString(), timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// Routable returns true if the address is routable.
|
||||
func (na *NetAddress) Routable() bool {
|
||||
if err := na.Valid(); err != nil {
|
||||
return false
|
||||
}
|
||||
// TODO(oga) bitcoind doesn't include RFC3849 here, but should we?
|
||||
return !(na.RFC1918() || na.RFC3927() || na.RFC4862() ||
|
||||
na.RFC4193() || na.RFC4843() || na.Local())
|
||||
}
|
||||
|
||||
// For IPv4 these are either a 0 or all bits set address. For IPv6 a zero
|
||||
// address or one that matches the RFC3849 documentation address format.
|
||||
func (na *NetAddress) Valid() error {
|
||||
if err := na.ID.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid ID: %w", err)
|
||||
}
|
||||
|
||||
if na.IP == nil {
|
||||
return errors.New("no IP")
|
||||
}
|
||||
if na.IP.IsUnspecified() || na.RFC3849() || na.IP.Equal(net.IPv4bcast) {
|
||||
return errors.New("invalid IP")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Local returns true if it is a local address.
|
||||
func (na *NetAddress) Local() bool {
|
||||
return na.IP.IsLoopback() || zero4.Contains(na.IP)
|
||||
}
|
||||
|
||||
// ReachabilityTo checks whenever o can be reached from na.
|
||||
func (na *NetAddress) ReachabilityTo(o *NetAddress) int {
|
||||
const (
|
||||
Unreachable = 0
|
||||
Default = iota
|
||||
Teredo
|
||||
Ipv6Weak
|
||||
Ipv4
|
||||
Ipv6Strong
|
||||
)
|
||||
switch {
|
||||
case !na.Routable():
|
||||
return Unreachable
|
||||
case na.RFC4380():
|
||||
switch {
|
||||
case !o.Routable():
|
||||
return Default
|
||||
case o.RFC4380():
|
||||
return Teredo
|
||||
case o.IP.To4() != nil:
|
||||
return Ipv4
|
||||
default: // ipv6
|
||||
return Ipv6Weak
|
||||
}
|
||||
case na.IP.To4() != nil:
|
||||
if o.Routable() && o.IP.To4() != nil {
|
||||
return Ipv4
|
||||
}
|
||||
return Default
|
||||
default: /* ipv6 */
|
||||
var tunneled bool
|
||||
// Is our v6 is tunneled?
|
||||
if o.RFC3964() || o.RFC6052() || o.RFC6145() {
|
||||
tunneled = true
|
||||
}
|
||||
switch {
|
||||
case !o.Routable():
|
||||
return Default
|
||||
case o.RFC4380():
|
||||
return Teredo
|
||||
case o.IP.To4() != nil:
|
||||
return Ipv4
|
||||
case tunneled:
|
||||
// only prioritize ipv6 if we aren't tunneling it.
|
||||
return Ipv6Weak
|
||||
}
|
||||
return Ipv6Strong
|
||||
}
|
||||
}
|
||||
|
||||
// RFC1918: IPv4 Private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||
// RFC3849: IPv6 Documentation address (2001:0DB8::/32)
|
||||
// RFC3927: IPv4 Autoconfig (169.254.0.0/16)
|
||||
// RFC3964: IPv6 6to4 (2002::/16)
|
||||
// RFC4193: IPv6 unique local (FC00::/7)
|
||||
// RFC4380: IPv6 Teredo tunneling (2001::/32)
|
||||
// RFC4843: IPv6 ORCHID: (2001:10::/28)
|
||||
// RFC4862: IPv6 Autoconfig (FE80::/64)
|
||||
// RFC6052: IPv6 well known prefix (64:FF9B::/96)
|
||||
// RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96
|
||||
var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)}
|
||||
var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)}
|
||||
var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)}
|
||||
var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)}
|
||||
var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)}
|
||||
var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)}
|
||||
var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)}
|
||||
var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)}
|
||||
var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)}
|
||||
var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)}
|
||||
var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)}
|
||||
var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)}
|
||||
var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)}
|
||||
var (
|
||||
// onionCatNet defines the IPv6 address block used to support Tor.
|
||||
// bitcoind encodes a .onion address as a 16 byte number by decoding the
|
||||
// address prior to the .onion (i.e. the key hash) base32 into a ten
|
||||
// byte number. It then stores the first 6 bytes of the address as
|
||||
// 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43.
|
||||
//
|
||||
// This is the same range used by OnionCat, which is part part of the
|
||||
// RFC4193 unique local IPv6 range.
|
||||
//
|
||||
// In summary the format is:
|
||||
// { magic 6 bytes, 10 bytes base32 decode of key hash }
|
||||
onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128)
|
||||
)
|
||||
|
||||
func (na *NetAddress) RFC1918() bool {
|
||||
return rfc1918_10.Contains(na.IP) ||
|
||||
rfc1918_192.Contains(na.IP) ||
|
||||
rfc1918_172.Contains(na.IP)
|
||||
}
|
||||
func (na *NetAddress) RFC3849() bool { return rfc3849.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC3927() bool { return rfc3927.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC3964() bool { return rfc3964.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC4193() bool { return rfc4193.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC4380() bool { return rfc4380.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC4843() bool { return rfc4843.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC4862() bool { return rfc4862.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC6052() bool { return rfc6052.Contains(na.IP) }
|
||||
func (na *NetAddress) RFC6145() bool { return rfc6145.Contains(na.IP) }
|
||||
func (na *NetAddress) OnionCatTor() bool { return onionCatNet.Contains(na.IP) }
|
||||
|
||||
func removeProtocolIfDefined(addr string) string {
|
||||
if strings.Contains(addr, "://") {
|
||||
return strings.Split(addr, "://")[1]
|
||||
}
|
||||
return addr
|
||||
|
||||
}
|
||||
|
||||
// ipNet returns a net.IPNet struct given the passed IP address string, number
|
||||
// of one bits to include at the start of the mask, and the total number of bits
|
||||
// for the mask.
|
||||
func ipNet(ip string, ones, bits int) net.IPNet {
|
||||
return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNetAddress_String(t *testing.T) {
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
|
||||
require.Nil(t, err)
|
||||
|
||||
netAddr := NewNetAddress("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", tcpAddr)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_ = netAddr.String()
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
s := netAddr.String()
|
||||
require.Equal(t, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", s)
|
||||
}
|
||||
|
||||
func TestNewNetAddress(t *testing.T) {
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Panics(t, func() {
|
||||
NewNetAddress("", tcpAddr)
|
||||
})
|
||||
|
||||
addr := NewNetAddress("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", tcpAddr)
|
||||
assert.Equal(t, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", addr.String())
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
NewNetAddress("", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8000})
|
||||
}, "Calling NewNetAddress with UDPAddr should not panic in testing")
|
||||
}
|
||||
|
||||
func TestNewNetAddressString(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
addr string
|
||||
expected string
|
||||
correct bool
|
||||
}{
|
||||
{"no node id and no protocol", "127.0.0.1:8080", "", false},
|
||||
{"no node id w/ tcp input", "tcp://127.0.0.1:8080", "", false},
|
||||
{"no node id w/ udp input", "udp://127.0.0.1:8080", "", false},
|
||||
|
||||
{
|
||||
"no protocol",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"tcp input",
|
||||
"tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"udp input",
|
||||
"udp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
{"malformed tcp input", "tcp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
{"malformed udp input", "udp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
|
||||
// {"127.0.0:8080", false},
|
||||
{"invalid host", "notahost", "", false},
|
||||
{"invalid port", "127.0.0.1:notapath", "", false},
|
||||
{"invalid host w/ port", "notahost:8080", "", false},
|
||||
{"just a port", "8082", "", false},
|
||||
{"non-existent port", "127.0.0:8080000", "", false},
|
||||
|
||||
{"too short nodeId", "deadbeef@127.0.0.1:8080", "", false},
|
||||
{"too short, not hex nodeId", "this-isnot-hex@127.0.0.1:8080", "", false},
|
||||
{"not hex nodeId", "xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
|
||||
{"too short nodeId w/tcp", "tcp://deadbeef@127.0.0.1:8080", "", false},
|
||||
{"too short notHex nodeId w/tcp", "tcp://this-isnot-hex@127.0.0.1:8080", "", false},
|
||||
{"notHex nodeId w/tcp", "tcp://xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
{
|
||||
"correct nodeId w/tcp",
|
||||
"tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
|
||||
{"no node id", "tcp://@127.0.0.1:8080", "", false},
|
||||
{"no node id or IP", "tcp://@", "", false},
|
||||
{"tcp no host, w/ port", "tcp://:26656", "", false},
|
||||
{"empty", "", "", false},
|
||||
{"node id delimiter 1", "@", "", false},
|
||||
{"node id delimiter 2", " @", "", false},
|
||||
{"node id delimiter 3", " @ ", "", false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
addr, err := NewNetAddressString(tc.addr)
|
||||
if tc.correct {
|
||||
if assert.Nil(t, err, tc.addr) {
|
||||
assert.Equal(t, tc.expected, addr.String())
|
||||
}
|
||||
} else {
|
||||
assert.NotNil(t, err, tc.addr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewNetAddressIPPort(t *testing.T) {
|
||||
addr := NewNetAddressIPPort(net.ParseIP("127.0.0.1"), 8080)
|
||||
assert.Equal(t, "127.0.0.1:8080", addr.String())
|
||||
}
|
||||
|
||||
func TestNetAddressProperties(t *testing.T) {
|
||||
// TODO add more test cases
|
||||
testCases := []struct {
|
||||
addr string
|
||||
valid bool
|
||||
local bool
|
||||
routable bool
|
||||
}{
|
||||
{"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", true, true, false},
|
||||
{"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@ya.ru:80", true, false, true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
addr, err := NewNetAddressString(tc.addr)
|
||||
require.Nil(t, err)
|
||||
|
||||
err = addr.Valid()
|
||||
if tc.valid {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
assert.Equal(t, tc.local, addr.Local())
|
||||
assert.Equal(t, tc.routable, addr.Routable())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetAddressReachabilityTo(t *testing.T) {
|
||||
// TODO add more test cases
|
||||
testCases := []struct {
|
||||
addr string
|
||||
other string
|
||||
reachability int
|
||||
}{
|
||||
{
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8081",
|
||||
0,
|
||||
},
|
||||
{"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@ya.ru:80", "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", 1},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
addr, err := NewNetAddressString(tc.addr)
|
||||
require.Nil(t, err)
|
||||
|
||||
other, err := NewNetAddressString(tc.other)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, tc.reachability, addr.ReachabilityTo(other))
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,7 @@ func NewNodeID(nodeID string) (NodeID, error) {
|
||||
// IDAddressString returns id@hostPort. It strips the leading
|
||||
// protocol from protocolHostPort if it exists.
|
||||
func (id NodeID) AddressString(protocolHostPort string) string {
|
||||
hostPort := removeProtocolIfDefined(protocolHostPort)
|
||||
return fmt.Sprintf("%s@%s", id, hostPort)
|
||||
return fmt.Sprintf("%s@%s", id, removeProtocolIfDefined(protocolHostPort))
|
||||
}
|
||||
|
||||
// NodeIDFromPubKey creates a node ID from a given PubKey address.
|
||||
|
||||
@@ -3,6 +3,9 @@ package types
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/bytes"
|
||||
tmstrings "github.com/tendermint/tendermint/libs/strings"
|
||||
@@ -74,17 +77,10 @@ func (info NodeInfo) ID() NodeID {
|
||||
// url-encoding), and we just need to be careful with how we handle that in our
|
||||
// clients. (e.g. off by default).
|
||||
func (info NodeInfo) Validate() error {
|
||||
|
||||
// ID is already validated.
|
||||
|
||||
// Validate ListenAddr.
|
||||
_, err := NewNetAddressString(info.ID().AddressString(info.ListenAddr))
|
||||
if err != nil {
|
||||
if _, _, err := ParseAddressString(info.ID().AddressString(info.ListenAddr)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Network is validated in CompatibleWith.
|
||||
|
||||
// Validate Version
|
||||
if len(info.Version) > 0 &&
|
||||
(!tmstrings.IsASCIIText(info.Version) || tmstrings.ASCIITrim(info.Version) == "") {
|
||||
@@ -163,15 +159,6 @@ OUTER_LOOP:
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetAddress returns a NetAddress derived from the NodeInfo -
|
||||
// it includes the authenticated peer ID and the self-reported
|
||||
// ListenAddr. Note that the ListenAddr is not authenticated and
|
||||
// may not match that address actually dialed if its an outbound peer.
|
||||
func (info NodeInfo) NetAddress() (*NetAddress, error) {
|
||||
idAddr := info.ID().AddressString(info.ListenAddr)
|
||||
return NewNetAddressString(idAddr)
|
||||
}
|
||||
|
||||
// AddChannel is used by the router when a channel is opened to add it to the node info
|
||||
func (info *NodeInfo) AddChannel(channel uint16) {
|
||||
// check that the channel doesn't already exist
|
||||
@@ -244,3 +231,58 @@ func NodeInfoFromProto(pb *tmp2p.NodeInfo) (NodeInfo, error) {
|
||||
|
||||
return dni, nil
|
||||
}
|
||||
|
||||
// ParseAddressString reads an address string, and returns the IP
|
||||
// address and port information, returning an error for any validation
|
||||
// errors.
|
||||
func ParseAddressString(addr string) (net.IP, uint16, error) {
|
||||
addrWithoutProtocol := removeProtocolIfDefined(addr)
|
||||
spl := strings.Split(addrWithoutProtocol, "@")
|
||||
if len(spl) != 2 {
|
||||
return nil, 0, errors.New("invalid address")
|
||||
}
|
||||
|
||||
id, err := NewNodeID(spl[0])
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := id.Validate(); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
addrWithoutProtocol = spl[1]
|
||||
|
||||
// get host and port
|
||||
host, portStr, err := net.SplitHostPort(addrWithoutProtocol)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if len(host) == 0 {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
ip := net.ParseIP(host)
|
||||
if ip == nil {
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
ip = ips[0]
|
||||
}
|
||||
|
||||
port, err := strconv.ParseUint(portStr, 10, 16)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return ip, uint16(port), nil
|
||||
}
|
||||
|
||||
func removeProtocolIfDefined(addr string) string {
|
||||
if strings.Contains(addr, "://") {
|
||||
return strings.Split(addr, "://")[1]
|
||||
}
|
||||
return addr
|
||||
|
||||
}
|
||||
|
||||
@@ -173,3 +173,80 @@ func TestNodeInfoAddChannel(t *testing.T) {
|
||||
nodeInfo.AddChannel(2)
|
||||
require.Contains(t, nodeInfo.Channels, byte(0x02))
|
||||
}
|
||||
|
||||
func TestParseAddressString(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
addr string
|
||||
expected string
|
||||
correct bool
|
||||
}{
|
||||
{"no node id and no protocol", "127.0.0.1:8080", "", false},
|
||||
{"no node id w/ tcp input", "tcp://127.0.0.1:8080", "", false},
|
||||
{"no node id w/ udp input", "udp://127.0.0.1:8080", "", false},
|
||||
|
||||
{
|
||||
"no protocol",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"tcp input",
|
||||
"tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"udp input",
|
||||
"udp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
{"malformed tcp input", "tcp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
{"malformed udp input", "udp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
|
||||
// {"127.0.0:8080", false},
|
||||
{"invalid host", "notahost", "", false},
|
||||
{"invalid port", "127.0.0.1:notapath", "", false},
|
||||
{"invalid host w/ port", "notahost:8080", "", false},
|
||||
{"just a port", "8082", "", false},
|
||||
{"non-existent port", "127.0.0:8080000", "", false},
|
||||
|
||||
{"too short nodeId", "deadbeef@127.0.0.1:8080", "", false},
|
||||
{"too short, not hex nodeId", "this-isnot-hex@127.0.0.1:8080", "", false},
|
||||
{"not hex nodeId", "xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
|
||||
{"too short nodeId w/tcp", "tcp://deadbeef@127.0.0.1:8080", "", false},
|
||||
{"too short notHex nodeId w/tcp", "tcp://this-isnot-hex@127.0.0.1:8080", "", false},
|
||||
{"notHex nodeId w/tcp", "tcp://xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
|
||||
{
|
||||
"correct nodeId w/tcp",
|
||||
"tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
|
||||
true,
|
||||
},
|
||||
|
||||
{"no node id", "tcp://@127.0.0.1:8080", "", false},
|
||||
{"no node id or IP", "tcp://@", "", false},
|
||||
{"tcp no host, w/ port", "tcp://:26656", "", false},
|
||||
{"empty", "", "", false},
|
||||
{"node id delimiter 1", "@", "", false},
|
||||
{"node id delimiter 2", " @", "", false},
|
||||
{"node id delimiter 3", " @ ", "", false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
addr, port, err := ParseAddressString(tc.addr)
|
||||
if tc.correct {
|
||||
require.Nil(t, err, tc.addr)
|
||||
assert.Contains(t, tc.expected, addr.String())
|
||||
assert.Contains(t, tc.expected, fmt.Sprint(port))
|
||||
} else {
|
||||
assert.Error(t, err, "%v", tc.addr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user