Browse Source

do not even try to dial ourselves

also, remove address from the book (plus mark it as our address)
and return an error if we fail to parse peers list
pull/1350/head
Anton Kaliaev 7 years ago
parent
commit
6e39ec6e26
No known key found for this signature in database GPG Key ID: 7B6881D965918214
4 changed files with 77 additions and 35 deletions
  1. +12
    -2
      p2p/pex/addrbook.go
  2. +16
    -0
      p2p/pex/addrbook_test.go
  3. +25
    -14
      p2p/switch.go
  4. +24
    -19
      p2p/switch_test.go

+ 12
- 2
p2p/pex/addrbook.go View File

@ -33,13 +33,15 @@ type AddrBook interface {
// Add our own addresses so we don't later add ourselves // Add our own addresses so we don't later add ourselves
AddOurAddress(*p2p.NetAddress) AddOurAddress(*p2p.NetAddress)
// Check if it is our address // Check if it is our address
OurAddress(*p2p.NetAddress) bool OurAddress(*p2p.NetAddress) bool
// Add and remove an address // Add and remove an address
AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error
RemoveAddress(addr *p2p.NetAddress)
RemoveAddress(*p2p.NetAddress)
// Check if the address is in the book
HasAddress(*p2p.NetAddress) bool
// Do we need more peers? // Do we need more peers?
NeedMoreAddrs() bool NeedMoreAddrs() bool
@ -196,6 +198,14 @@ func (a *addrBook) IsGood(addr *p2p.NetAddress) bool {
return a.addrLookup[addr.ID].isOld() return a.addrLookup[addr.ID].isOld()
} }
// HasAddress returns true if the address is in the book.
func (a *addrBook) HasAddress(addr *p2p.NetAddress) bool {
a.mtx.Lock()
defer a.mtx.Unlock()
ka := a.addrLookup[addr.ID]
return ka != nil
}
// NeedMoreAddrs implements AddrBook - returns true if there are not have enough addresses in the book. // NeedMoreAddrs implements AddrBook - returns true if there are not have enough addresses in the book.
func (a *addrBook) NeedMoreAddrs() bool { func (a *addrBook) NeedMoreAddrs() bool {
return a.Size() < needAddressThreshold return a.Size() < needAddressThreshold


+ 16
- 0
p2p/pex/addrbook_test.go View File

@ -338,3 +338,19 @@ func TestAddrBookGetSelectionWithBias(t *testing.T) {
t.Fatalf("expected more good peers (%% got: %d, %% expected: %d, number of good addrs: %d, total: %d)", got, expected, good, len(selection)) t.Fatalf("expected more good peers (%% got: %d, %% expected: %d, number of good addrs: %d, total: %d)", got, expected, good, len(selection))
} }
} }
func TestAddrBookHasAddress(t *testing.T) {
fname := createTempFileName("addrbook_test")
defer deleteTempFile(fname)
book := NewAddrBook(fname, true)
book.SetLogger(log.TestingLogger())
addr := randIPv4Address(t)
book.AddAddress(addr, addr)
assert.True(t, book.HasAddress(addr))
book.RemoveAddress(addr)
assert.False(t, book.HasAddress(addr))
}

+ 25
- 14
p2p/switch.go View File

@ -40,6 +40,8 @@ type AddrBook interface {
AddOurAddress(*NetAddress) AddOurAddress(*NetAddress)
OurAddress(*NetAddress) bool OurAddress(*NetAddress) bool
MarkGood(*NetAddress) MarkGood(*NetAddress)
RemoveAddress(*NetAddress)
HasAddress(*NetAddress) bool
Save() Save()
} }
@ -351,17 +353,20 @@ func (sw *Switch) DialPeersAsync(addrBook AddrBook, peers []string, persistent b
for _, err := range errs { for _, err := range errs {
sw.Logger.Error("Error in peer's address", "err", err) sw.Logger.Error("Error in peer's address", "err", err)
} }
if len(errs) > 0 {
return errors.New("Errors in peer addresses (see errors above)")
}
ourAddr := sw.nodeInfo.NetAddress()
// TODO: move this out of here ?
if addrBook != nil { if addrBook != nil {
// add peers to `addrBook` // add peers to `addrBook`
ourAddr := sw.nodeInfo.NetAddress()
for _, netAddr := range netAddrs { for _, netAddr := range netAddrs {
// do not add our address or ID // do not add our address or ID
if netAddr.Same(ourAddr) {
continue
if !netAddr.Same(ourAddr) {
addrBook.AddAddress(netAddr, ourAddr)
} }
// TODO: move this out of here ?
addrBook.AddAddress(netAddr, ourAddr)
} }
// Persist some peers to disk right away. // Persist some peers to disk right away.
// NOTE: integration tests depend on this // NOTE: integration tests depend on this
@ -372,8 +377,14 @@ func (sw *Switch) DialPeersAsync(addrBook AddrBook, peers []string, persistent b
perm := sw.rng.Perm(len(netAddrs)) perm := sw.rng.Perm(len(netAddrs))
for i := 0; i < len(perm); i++ { for i := 0; i < len(perm); i++ {
go func(i int) { go func(i int) {
sw.randomSleep(0)
j := perm[i] j := perm[i]
// do not dial ourselves
if netAddrs[j].Same(ourAddr) {
return
}
sw.randomSleep(0)
err := sw.DialPeerWithAddress(netAddrs[j], persistent) err := sw.DialPeerWithAddress(netAddrs[j], persistent)
if err != nil { if err != nil {
sw.Logger.Error("Error dialing peer", "err", err) sw.Logger.Error("Error dialing peer", "err", err)
@ -386,11 +397,6 @@ func (sw *Switch) DialPeersAsync(addrBook AddrBook, peers []string, persistent b
// DialPeerWithAddress dials the given peer and runs sw.addPeer if it connects and authenticates successfully. // DialPeerWithAddress dials the given peer and runs sw.addPeer if it connects and authenticates successfully.
// If `persistent == true`, the switch will always try to reconnect to this peer if the connection ever fails. // If `persistent == true`, the switch will always try to reconnect to this peer if the connection ever fails.
func (sw *Switch) DialPeerWithAddress(addr *NetAddress, persistent bool) error { func (sw *Switch) DialPeerWithAddress(addr *NetAddress, persistent bool) error {
// do not dial ourselves
if sw.addrBook.OurAddress(addr) {
return ErrSwitchConnectToSelf
}
sw.dialing.Set(string(addr.ID), addr) sw.dialing.Set(string(addr.ID), addr)
defer sw.dialing.Delete(string(addr.ID)) defer sw.dialing.Delete(string(addr.ID))
return sw.addOutboundPeerWithConfig(addr, sw.peerConfig, persistent) return sw.addOutboundPeerWithConfig(addr, sw.peerConfig, persistent)
@ -532,9 +538,14 @@ func (sw *Switch) addPeer(pc peerConn) error {
// Avoid self // Avoid self
if sw.nodeKey.ID() == peerID { if sw.nodeKey.ID() == peerID {
// add given address to the address book to avoid dialing ourselves again
// this is our public address
sw.addrBook.AddOurAddress(peerNodeInfo.NetAddress())
addr := peerNodeInfo.NetAddress()
// remove the given address from the address book if we're added it earlier
sw.addrBook.RemoveAddress(addr)
// add the given address to the address book to avoid dialing ourselves
// again this is our public address
sw.addrBook.AddOurAddress(addr)
return ErrSwitchConnectToSelf return ErrSwitchConnectToSelf
} }


+ 24
- 19
p2p/switch_test.go View File

@ -90,7 +90,9 @@ func MakeSwitchPair(t testing.TB, initSwitch func(int, *Switch) *Switch) (*Switc
} }
func initSwitchFunc(i int, sw *Switch) *Switch { func initSwitchFunc(i int, sw *Switch) *Switch {
sw.SetAddrBook(&addrBookMock{ourAddrs: make(map[string]struct{})})
sw.SetAddrBook(&addrBookMock{
addrs: make(map[string]struct{}, 0),
ourAddrs: make(map[string]struct{}, 0)})
// Make two reactors of two channels each // Make two reactors of two channels each
sw.AddReactor("foo", NewTestReactor([]*conn.ChannelDescriptor{ sw.AddReactor("foo", NewTestReactor([]*conn.ChannelDescriptor{
@ -180,32 +182,24 @@ func TestConnAddrFilter(t *testing.T) {
func TestSwitchFiltersOutItself(t *testing.T) { func TestSwitchFiltersOutItself(t *testing.T) {
s1 := MakeSwitch(config, 1, "127.0.0.2", "123.123.123", initSwitchFunc) s1 := MakeSwitch(config, 1, "127.0.0.2", "123.123.123", initSwitchFunc)
addr := s1.NodeInfo().NetAddress()
// addr := s1.NodeInfo().NetAddress()
// add ourselves like we do in node.go#427
s1.addrBook.AddOurAddress(addr)
// addr should be rejected immediately because of the same IP & port
err := s1.DialPeerWithAddress(addr, false)
if assert.Error(t, err) {
assert.Equal(t, ErrSwitchConnectToSelf, err)
}
// // add ourselves like we do in node.go#427
// s1.addrBook.AddOurAddress(addr)
// simulate s1 having a public IP by creating a remote peer with the same ID // simulate s1 having a public IP by creating a remote peer with the same ID
rp := &remotePeer{PrivKey: s1.nodeKey.PrivKey, Config: DefaultPeerConfig()} rp := &remotePeer{PrivKey: s1.nodeKey.PrivKey, Config: DefaultPeerConfig()}
rp.Start() rp.Start()
// addr should be rejected in addPeer based on the same ID // addr should be rejected in addPeer based on the same ID
err = s1.DialPeerWithAddress(rp.Addr(), false)
err := s1.DialPeerWithAddress(rp.Addr(), false)
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Equal(t, ErrSwitchConnectToSelf, err) assert.Equal(t, ErrSwitchConnectToSelf, err)
} }
// addr should be rejected immediately because during previous step we changed node's public IP
err = s1.DialPeerWithAddress(rp.Addr(), false)
if assert.Error(t, err) {
assert.Equal(t, ErrSwitchConnectToSelf, err)
}
assert.True(t, s1.addrBook.OurAddress(rp.Addr()))
assert.False(t, s1.addrBook.HasAddress(rp.Addr()))
rp.Stop() rp.Stop()
@ -379,16 +373,27 @@ func BenchmarkSwitchBroadcast(b *testing.B) {
} }
type addrBookMock struct { type addrBookMock struct {
addrs map[string]struct{}
ourAddrs map[string]struct{} ourAddrs map[string]struct{}
} }
var _ AddrBook = (*addrBookMock)(nil) var _ AddrBook = (*addrBookMock)(nil)
func (book *addrBookMock) AddAddress(addr *NetAddress, src *NetAddress) error { return nil }
func (book *addrBookMock) AddOurAddress(addr *NetAddress) { book.ourAddrs[addr.String()] = struct{}{} }
func (book *addrBookMock) AddAddress(addr *NetAddress, src *NetAddress) error {
book.addrs[addr.String()] = struct{}{}
return nil
}
func (book *addrBookMock) AddOurAddress(addr *NetAddress) { book.ourAddrs[addr.String()] = struct{}{} }
func (book *addrBookMock) OurAddress(addr *NetAddress) bool { func (book *addrBookMock) OurAddress(addr *NetAddress) bool {
_, ok := book.ourAddrs[addr.String()] _, ok := book.ourAddrs[addr.String()]
return ok return ok
} }
func (book *addrBookMock) MarkGood(*NetAddress) {} func (book *addrBookMock) MarkGood(*NetAddress) {}
func (book *addrBookMock) Save() {}
func (book *addrBookMock) HasAddress(addr *NetAddress) bool {
_, ok := book.addrs[addr.String()]
return ok
}
func (book *addrBookMock) RemoveAddress(addr *NetAddress) {
delete(book.addrs, addr.String())
}
func (book *addrBookMock) Save() {}

Loading…
Cancel
Save