Skip to content

Commit

Permalink
Adjust default backoff max to just over 1 hour, add ?maxbackoff= pe…
Browse files Browse the repository at this point in the history
…er option (#1124)

Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
  • Loading branch information
neilalexander and neilalexander committed Jan 15, 2024
1 parent 9f4c89a commit 180d7bf
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions src/core/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/hex"
"fmt"
"io"
"math"
"net"
"net/netip"
"net/url"
Expand All @@ -28,6 +27,9 @@ const (
linkTypeIncoming // Incoming connection
)

const defaultBackoffLimit = time.Second << 12 // 1h8m16s
const minimumBackoffLimit = time.Second * 30

type links struct {
phony.Inbox
core *Core
Expand Down Expand Up @@ -69,6 +71,7 @@ type linkOptions struct {
priority uint8
tlsSNI string
password []byte
maxBackoff time.Duration
}

type Listener struct {
Expand Down Expand Up @@ -136,6 +139,7 @@ const ErrLinkPriorityInvalid = linkError("priority value is invalid")
const ErrLinkPinnedKeyInvalid = linkError("pinned public key is invalid")
const ErrLinkPasswordInvalid = linkError("password is invalid")
const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
const ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid")

func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
var retErr error
Expand All @@ -150,7 +154,9 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {

// Collect together the link options, these are global options
// that are not specific to any given protocol.
var options linkOptions
options := linkOptions{
maxBackoff: defaultBackoffLimit,
}
for _, pubkey := range u.Query()["key"] {
sigPub, err := hex.DecodeString(pubkey)
if err != nil {
Expand Down Expand Up @@ -179,6 +185,14 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
}
options.password = []byte(p)
}
if p := u.Query().Get("maxbackoff"); p != "" {
d, err := time.ParseDuration(p)
if err != nil || d < minimumBackoffLimit {
retErr = ErrLinkMaxBackoffInvalid
return
}
options.maxBackoff = d
}
// SNI headers must contain hostnames and not IP addresses, so we must make sure
// that we do not populate the SNI with an IP literal. We do this by splitting
// the host-port combo from the query option and then seeing if it parses to an
Expand Down Expand Up @@ -235,10 +249,13 @@ 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 < 14 { // Cap at roughly 4.5 hours maximum.
if backoff < 32 {
backoff++
}
duration := time.Second * time.Duration(math.Exp2(float64(backoff)))
duration := time.Second << backoff
if duration > options.maxBackoff {
duration = options.maxBackoff
}
select {
case <-state.kick:
return true
Expand Down

0 comments on commit 180d7bf

Please sign in to comment.