@@ -155,6 +155,7 @@ const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
155155const ErrLinkMaxBackoffInvalid = linkError ("max backoff duration invalid" )
156156const ErrLinkSNINotSupported = linkError ("SNI not supported on this link type" )
157157const ErrLinkNoSuitableIPs = linkError ("peer has no suitable addresses" )
158+ const ErrLinkToSelf = linkError ("node cannot connect to self" )
158159
159160func (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