Skip to content

Commit

Permalink
more discriminate connectivity
Browse files Browse the repository at this point in the history
If a peer was specified on the command line w/o a port, then do not
connect to it if we have inbound connections from that IP.

This eliminates unnecessary (and ultimately failing0 connection
attempts in the common scenario of several peers having been told
about each other on their command lines.

Closes #478.
  • Loading branch information
rade committed Apr 14, 2015
1 parent 961801b commit a471c0f
Showing 1 changed file with 34 additions and 12 deletions.
46 changes: 34 additions & 12 deletions router/connection_maker.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type ConnectionMaker struct {
peers *Peers
normalisePeerAddr func(string) string
targets map[string]*Target
cmdLinePeers map[string]string
cmdLinePeers map[string]*CmdLinePeer
actionChan chan<- ConnectionMakerAction
}

Expand All @@ -31,14 +31,19 @@ type Target struct {
tryInterval time.Duration // backoff time on next failure
}

type CmdLinePeer struct {
address string // normalised and resolved address of peer to connect to
portSupplied bool // did the original address contain a port?
}

type ConnectionMakerAction func() bool

func NewConnectionMaker(ourself *LocalPeer, peers *Peers, normalisePeerAddr func(string) string) *ConnectionMaker {
return &ConnectionMaker{
ourself: ourself,
peers: peers,
normalisePeerAddr: normalisePeerAddr,
cmdLinePeers: make(map[string]string),
cmdLinePeers: make(map[string]*CmdLinePeer),
targets: make(map[string]*Target)}
}

Expand All @@ -49,14 +54,15 @@ func (cm *ConnectionMaker) Start() {
}

func (cm *ConnectionMaker) InitiateConnection(peer string) error {
addr, err := net.ResolveTCPAddr("tcp4", cm.normalisePeerAddr(peer))
normalisedPeerAddr := cm.normalisePeerAddr(peer)
addr, err := net.ResolveTCPAddr("tcp4", normalisedPeerAddr)
if err != nil {
return err
}
address := addr.String()

portSupplied := peer == normalisedPeerAddr
cm.actionChan <- func() bool {
cm.cmdLinePeers[peer] = address
cm.cmdLinePeers[peer] = &CmdLinePeer{address: address, portSupplied: portSupplied}
// curtail any existing reconnect interval
if target, found := cm.targets[address]; found {
target.tryAfter, target.tryInterval = tryImmediately()
Expand Down Expand Up @@ -138,7 +144,7 @@ func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
// Copy the set of things we are connected to, so we can access
// them without locking. Also clear out any entries in cm.targets
// for existing connections.
ourConnectedPeers, ourConnectedTargets := cm.ourConnections()
ourConnectedPeers, ourConnectedTargets, ourInboundIPs := cm.ourConnections()

addTarget := func(address string) {
if _, connected := ourConnectedTargets[address]; connected {
Expand All @@ -154,9 +160,18 @@ func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
}

// Add command-line targets that are not connected
for _, address := range cm.cmdLinePeers {
addTarget(address)
cmdLineTarget[address] = void
for _, cmdLinePeer := range cm.cmdLinePeers {
cmdLineTarget[cmdLinePeer.address] = void
// if a peer was specified w/o a port, then do not connect to
// it if we have inbound connections from that IP.
if !cmdLinePeer.portSupplied {
if ip, _, err := net.SplitHostPort(cmdLinePeer.address); err == nil { // should always succeed
if _, connected := ourInboundIPs[ip]; connected {
continue
}
}
}
addTarget(cmdLinePeer.address)
}

// Add targets for peers that someone else is connected to, but we
Expand All @@ -166,18 +181,25 @@ func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
return cm.connectToTargets(validTarget, cmdLineTarget)
}

func (cm *ConnectionMaker) ourConnections() (PeerNameSet, map[string]struct{}) {
func (cm *ConnectionMaker) ourConnections() (PeerNameSet, map[string]struct{}, map[string]struct{}) {
var (
ourConnectedPeers = make(PeerNameSet)
ourConnectedTargets = make(map[string]struct{})
ourInboundIPs = make(map[string]struct{})
)
for conn := range cm.ourself.Connections() {
address := conn.RemoteTCPAddr()
delete(cm.targets, address)
ourConnectedPeers[conn.Remote().Name] = void
ourConnectedTargets[address] = void
delete(cm.targets, address)
if conn.Outbound() {
continue
}
if ip, _, err := net.SplitHostPort(address); err == nil { // should always succeed
ourInboundIPs[ip] = void
}
}
return ourConnectedPeers, ourConnectedTargets
return ourConnectedPeers, ourConnectedTargets, ourInboundIPs
}

func (cm *ConnectionMaker) addPeerTargets(ourConnectedPeers PeerNameSet, addTarget func(string)) {
Expand Down

0 comments on commit a471c0f

Please sign in to comment.