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{ ipAddresses := map[string]bool{
"192.168.1.1:8333": true, "192.168.1.1:8333": true,
"[2001:db8:85a3:8d3:1319:8a2e:370:7348]:8337": true, "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:8337": true,
"127.0.0.1:8335": true,
} }
var lndArgs []string var lndArgs []string
@@ -2118,8 +2117,11 @@ func testNodeAnnouncement(net *networkHarness, t *harnessTest) {
if ipAddresses[parts[3]] { if ipAddresses[parts[3]] {
delete(ipAddresses, parts[3]) delete(ipAddresses, parts[3])
} else { } else {
t.Fatalf("unexpected IP address: %v", if !strings.HasPrefix(parts[3],
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++ numActiveNodes++
lndArgs = append(lndArgs, "--externalip=127.0.0.1:"+
strconv.Itoa(cfg.PeerPort))
return &lightningNode{ return &lightningNode{
cfg: cfg, cfg: cfg,
p2pAddr: net.JoinHostPort("127.0.0.1", strconv.Itoa(cfg.PeerPort)), 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 // In order to promote liveness of our active channels, instruct the
// connection manager to attempt to establish and maintain persistent // connection manager to attempt to establish and maintain persistent
// connections to all our direct channel counterparties. // 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() linkNodes, err := s.chanDB.FetchAllLinkNodes()
if err != nil && err != channeldb.ErrLinkNodesNotFound { if err != nil && err != channeldb.ErrLinkNodesNotFound {
return nil, err return nil, err
} }
for _, node := range linkNodes { 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 { for _, address := range node.Addresses {
// Create a wrapper address which couples the IP and the pubkey if address.Port == 0 {
// so the brontide authenticated connection can be established. 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{ lnAddr := &lnwire.NetAddress{
IdentityKey: node.IdentityPub, IdentityKey: nodeAddr.pubKey,
Address: address, Address: address,
} }
srvrLog.Debugf("Attempting persistent connection to channel "+ srvrLog.Debugf("Attempting persistent connection to "+
"peer %v", lnAddr) "channel peer %v", lnAddr)
// Send the persistent connection request to
// Send the persistent connection request to the connection // the connection manager, saving the request
// manager, saving the request itself so we can cancel/restart // itself so we can cancel/restart the process
// the process as needed. // as needed.
// TODO(roasbeef): use default addr
connReq := &connmgr.ConnReq{ connReq := &connmgr.ConnReq{
Addr: lnAddr, Addr: lnAddr,
Permanent: true, Permanent: true,
} }
s.persistentConnReqs[pubStr] = s.persistentConnReqs[pubStr] =
append(s.persistentConnReqs[pubStr], connReq) append(s.persistentConnReqs[pubStr], connReq)
go s.connMgr.Connect(connReq) go s.connMgr.Connect(connReq)
@@ -398,6 +472,11 @@ type sendReq struct {
errChan chan error 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 // 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 // of message to a particular peer. If the peer connect be found, then this
// method will return a non-nil error. // method will return a non-nil error.