Skip to content

Commit b43e213

Browse files
committed
Don't re-attempt connections when detecting a connection to self
Closes #1286.
1 parent b920e17 commit b43e213

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

src/core/link.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
155155
const ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid")
156156
const ErrLinkSNINotSupported = linkError("SNI not supported on this link type")
157157
const ErrLinkNoSuitableIPs = linkError("peer has no suitable addresses")
158+
const ErrLinkToSelf = linkError("node cannot connect to self")
158159

159160
func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
160161
var retErr error
@@ -264,12 +265,18 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
264265
// The caller should check the return value to decide whether
265266
// or not to give up trying.
266267
backoffNow := func() bool {
267-
if backoff < 32 {
268+
if backoff >= 0 && backoff < 32 {
268269
backoff++
269270
}
270-
duration := time.Second << backoff
271-
if duration > options.maxBackoff {
272-
duration = options.maxBackoff
271+
var timeout <-chan time.Time
272+
if backoff < 0 {
273+
timeout = make(chan time.Time)
274+
} else {
275+
duration := time.Second << backoff
276+
if duration > options.maxBackoff {
277+
duration = options.maxBackoff
278+
}
279+
timeout = time.After(duration)
273280
}
274281
select {
275282
case <-state.kick:
@@ -278,7 +285,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
278285
return false
279286
case <-l.core.ctx.Done():
280287
return false
281-
case <-time.After(duration):
288+
case <-timeout:
282289
return true
283290
}
284291
}
@@ -358,6 +365,8 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
358365
doRet = true
359366
}
360367
state._conn = lc
368+
state._err = nil
369+
state._errtime = time.Now()
361370
})
362371
if doRet {
363372
return
@@ -366,6 +375,9 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
366375
// Give the connection to the handler. The handler will block
367376
// for the lifetime of the connection.
368377
switch err = l.handler(linkType, options, lc, resetBackoff, false); {
378+
case errors.Is(err, ErrLinkToSelf):
379+
// This is a pretty permanent error, don't retry.
380+
backoff = -1
369381
case err == nil:
370382
case errors.Is(err, io.EOF):
371383
case errors.Is(err, net.ErrClosed):
@@ -634,6 +646,10 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
634646
if err = conn.SetDeadline(time.Time{}); err != nil {
635647
return fmt.Errorf("failed to clear handshake deadline: %w", err)
636648
}
649+
// Check that the node isn't trying to connect to itself.
650+
if meta.publicKey.Equal(l.core.public) {
651+
return ErrLinkToSelf
652+
}
637653
// Check if the remote side matches the keys we expected. This is a bit of a weak
638654
// check - in future versions we really should check a signature or something like that.
639655
if pinned := options.pinnedEd25519Keys; len(pinned) > 0 {

0 commit comments

Comments
 (0)