From d34c37f3dd45b38a678165495ea19aa474cab55c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 30 Mar 2018 15:59:05 -0700 Subject: [PATCH] server: when constructing peer addr's attempt to locate proper port, fallback to default port In this commit, we fix an existing bug within the codebase: if a peer connected to us inbound, then we'd attempt to use the assigned port when re-establishing a connection to them. We fix this issue in this commit by adding a new method to look up any advertisements for the peer, and use the specified port that matches our connection attempt. If we can't find a proper advertisement, then we'll simply use the default peer port. --- server.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/server.go b/server.go index 92ca6a42..53ae5e55 100644 --- a/server.go +++ b/server.go @@ -1285,7 +1285,6 @@ func (s *server) peerTerminationWatcher(p *peer) { // Otherwise, we'll launch a new connection request in order to // attempt to maintain a persistent connection with this peer. - // TODO(roasbeef): look up latest info for peer in database connReq := &connmgr.ConnReq{ Addr: p.addr, Permanent: true, @@ -1337,9 +1336,19 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, inbound bool) { brontideConn := conn.(*brontide.Conn) + addr := conn.RemoteAddr() + pubKey := brontideConn.RemotePub() + + // We'll ensure that we locate the proper port to use within the peer's + // address for reconnecting purposes. + if tcpAddr, ok := addr.(*net.TCPAddr); ok { + targetPort := s.fetchNodeAdvertisedPort(pubKey, tcpAddr) + tcpAddr.Port = targetPort + } + peerAddr := &lnwire.NetAddress{ - IdentityKey: brontideConn.RemotePub(), - Address: conn.RemoteAddr(), + IdentityKey: pubKey, + Address: addr, ChainNet: activeNetParams.Net, } @@ -1908,3 +1917,43 @@ func computeNextBackoff(currBackoff time.Duration) time.Duration { // that the backoff can tweaked by 1/20 in either direction. return nextBackoff + (time.Duration(wiggle.Uint64()) - margin/2) } + +// fetchNodeAdvertisedPort attempts to fetch the advertised port of the target +// node. If a port isn't found, then the default port will be used. +func (s *server) fetchNodeAdvertisedPort(pub *btcec.PublicKey, + targetAddr *net.TCPAddr) int { + + // If the target port is already the default peer port, then we'll + // return that. + if targetAddr.Port == defaultPeerPort { + return defaultPeerPort + } + + node, err := s.chanDB.ChannelGraph().FetchLightningNode(pub) + + // If the node wasn't found, then we'll just return the current default + // port. + if err != nil { + return defaultPeerPort + } + + // Otherwise, we'll attempt to find a matching advertised IP, and will + // then use the port for that. + for _, addr := range node.Addresses { + // We'll only examine an address if it's a TCP address. + tcpAddr, ok := addr.(*net.TCPAddr) + if !ok { + continue + } + + // If this is the matching IP, then we'll return the port that + // it has been advertised with. + if tcpAddr.IP.Equal(targetAddr.IP) { + return tcpAddr.Port + } + } + + // If we couldn't find a matching IP, then we'll just return the + // default port. + return defaultPeerPort +}