Don't re-attempt connections when detecting a connection to self

Closes #1286.
This commit is contained in:
Neil Alexander
2025-11-11 23:18:56 +00:00
parent b920e17f24
commit b43e213c32

View File

@@ -155,6 +155,7 @@ const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
const ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid")
const ErrLinkSNINotSupported = linkError("SNI not supported on this link type")
const ErrLinkNoSuitableIPs = linkError("peer has no suitable addresses")
const ErrLinkToSelf = linkError("node cannot connect to self")
func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
var retErr error
@@ -264,12 +265,18 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
// The caller should check the return value to decide whether
// or not to give up trying.
backoffNow := func() bool {
if backoff < 32 {
if backoff >= 0 && backoff < 32 {
backoff++
}
duration := time.Second << backoff
if duration > options.maxBackoff {
duration = options.maxBackoff
var timeout <-chan time.Time
if backoff < 0 {
timeout = make(chan time.Time)
} else {
duration := time.Second << backoff
if duration > options.maxBackoff {
duration = options.maxBackoff
}
timeout = time.After(duration)
}
select {
case <-state.kick:
@@ -278,7 +285,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
return false
case <-l.core.ctx.Done():
return false
case <-time.After(duration):
case <-timeout:
return true
}
}
@@ -358,6 +365,8 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
doRet = true
}
state._conn = lc
state._err = nil
state._errtime = time.Now()
})
if doRet {
return
@@ -366,6 +375,9 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
// Give the connection to the handler. The handler will block
// for the lifetime of the connection.
switch err = l.handler(linkType, options, lc, resetBackoff, false); {
case errors.Is(err, ErrLinkToSelf):
// This is a pretty permanent error, don't retry.
backoff = -1
case err == nil:
case errors.Is(err, io.EOF):
case errors.Is(err, net.ErrClosed):
@@ -634,6 +646,10 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
if err = conn.SetDeadline(time.Time{}); err != nil {
return fmt.Errorf("failed to clear handshake deadline: %w", err)
}
// Check that the node isn't trying to connect to itself.
if meta.publicKey.Equal(l.core.public) {
return ErrLinkToSelf
}
// Check if the remote side matches the keys we expected. This is a bit of a weak
// check - in future versions we really should check a signature or something like that.
if pinned := options.pinnedEd25519Keys; len(pinned) > 0 {