server: user NodeAnnouncement addresses and ports for reconnect

Use addresses and ports from NodeAnnouncement messages for reconnection
attempts. For those nodes that don't explicitly report IP addresses, use
the IP address from previous connections connection request along with
the default peer port number.
This commit is contained in:
bryanvu 2017-03-25 01:40:33 -07:00 committed by Olaoluwa Osuntokun
parent 085b7333cb
commit c9c2848427
3 changed files with 101 additions and 17 deletions

View File

@ -2080,7 +2080,6 @@ func testNodeAnnouncement(net *networkHarness, t *harnessTest) {
ipAddresses := map[string]bool{
"192.168.1.1:8333": true,
"[2001:db8:85a3:8d3:1319:8a2e:370:7348]:8337": true,
"127.0.0.1:8335": true,
}
var lndArgs []string
@ -2118,8 +2117,11 @@ func testNodeAnnouncement(net *networkHarness, t *harnessTest) {
if ipAddresses[parts[3]] {
delete(ipAddresses, parts[3])
} else {
t.Fatalf("unexpected IP address: %v",
parts[3])
if !strings.HasPrefix(parts[3],
"127.0.0.1:") {
t.Fatalf("unexpected IP: %v",
parts[3])
}
}
}
}

View File

@ -133,6 +133,9 @@ func newLightningNode(rpcConfig *btcrpcclient.ConnConfig, lndArgs []string) (*li
numActiveNodes++
lndArgs = append(lndArgs, "--externalip=127.0.0.1:"+
strconv.Itoa(cfg.PeerPort))
return &lightningNode{
cfg: cfg,
p2pAddr: net.JoinHostPort("127.0.0.1", strconv.Itoa(cfg.PeerPort)),

107
server.go
View File

@ -243,33 +243,107 @@ func newServer(listenAddrs []string, notifier chainntnfs.ChainNotifier,
// In order to promote liveness of our active channels, instruct the
// connection manager to attempt to establish and maintain persistent
// connections to all our direct channel counterparties.
// nodeAddrsMap stores the combination of node public keys and
// addresses that we'll attempt to reconnect to. PubKey strings are
// used as keys since other PubKey forms can't be compared.
nodeAddrsMap := map[string]*nodeAddresses{}
// Iterate through the list of LinkNodes to find addresses we should
// attempt to connect to based on our set of previous connections. Set
// the reconnection port to the default peer port.
linkNodes, err := s.chanDB.FetchAllLinkNodes()
if err != nil && err != channeldb.ErrLinkNodesNotFound {
return nil, err
}
for _, node := range linkNodes {
pubStr := string(node.IdentityPub.SerializeCompressed())
// In case a node has multiple addresses, attempt to connect to
// each of them.
for _, address := range node.Addresses {
// Create a wrapper address which couples the IP and the pubkey
// so the brontide authenticated connection can be established.
if address.Port == 0 {
address.Port = defaultPeerPort
}
}
pubStr := string(node.IdentityPub.SerializeCompressed())
nodeAddrs := &nodeAddresses{
pubKey: node.IdentityPub,
addresses: node.Addresses,
}
nodeAddrsMap[pubStr] = nodeAddrs
}
// After checking our previous connections for addresses to connect to,
// iterate through the nodes in our channel graph to find addresses
// that have been added via NodeAnnouncement messages.
sourceNode, err := chanGraph.SourceNode()
if err != nil {
return nil, err
}
err = sourceNode.ForEachChannel(nil, func(_ *channeldb.ChannelEdgeInfo,
policy *channeldb.ChannelEdgePolicy) error {
pubStr := string(policy.Node.PubKey.SerializeCompressed())
// Add addresses from channel graph/NodeAnnouncements to the
// list of addresses we'll connect to. If there are duplicates
// that have different ports specified, the port from the
// channel graph should supersede the port from the link node.
var addrs []*net.TCPAddr
linkNodeAddrs, ok := nodeAddrsMap[pubStr]
if ok {
for _, lnAddress := range linkNodeAddrs.addresses {
var addrMatched bool
for _, polAddress := range policy.Node.Addresses {
polTCPAddr, ok :=
polAddress.(*net.TCPAddr)
if ok && polTCPAddr.IP.Equal(lnAddress.IP) {
addrMatched = true
addrs = append(addrs, polTCPAddr)
}
}
if !addrMatched {
addrs = append(addrs, lnAddress)
}
}
} else {
for _, addr := range policy.Node.Addresses {
polTCPAddr, ok := addr.(*net.TCPAddr)
if ok {
addrs = append(addrs, polTCPAddr)
}
}
}
nodeAddrsMap[pubStr] = &nodeAddresses{
pubKey: policy.Node.PubKey,
addresses: addrs,
}
return nil
})
if err != nil && err != channeldb.ErrGraphNoEdgesFound {
return nil, err
}
// Iterate through the combined list of addresses from prior links and
// node announcements and attempt to reconnect to each node.
for pubStr, nodeAddr := range nodeAddrsMap {
for _, address := range nodeAddr.addresses {
// Create a wrapper address which couples the IP and
// the pubkey so the brontide authenticated connection
// can be established.
lnAddr := &lnwire.NetAddress{
IdentityKey: node.IdentityPub,
IdentityKey: nodeAddr.pubKey,
Address: address,
}
srvrLog.Debugf("Attempting persistent connection to channel "+
"peer %v", lnAddr)
// Send the persistent connection request to the connection
// manager, saving the request itself so we can cancel/restart
// the process as needed.
// TODO(roasbeef): use default addr
srvrLog.Debugf("Attempting persistent connection to "+
"channel peer %v", lnAddr)
// Send the persistent connection request to
// the connection manager, saving the request
// itself so we can cancel/restart the process
// as needed.
connReq := &connmgr.ConnReq{
Addr: lnAddr,
Permanent: true,
}
s.persistentConnReqs[pubStr] =
append(s.persistentConnReqs[pubStr], connReq)
go s.connMgr.Connect(connReq)
@ -398,6 +472,11 @@ type sendReq struct {
errChan chan error
}
type nodeAddresses struct {
pubKey *btcec.PublicKey
addresses []*net.TCPAddr
}
// sendToPeer send a message to the server telling it to send the specific set
// of message to a particular peer. If the peer connect be found, then this
// method will return a non-nil error.