Help us shape the future of Go! Take the 2026 Go Developer Survey

adapter

package
v0.0.158 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 12 Imported by: 1

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrGroupClosed = errors.New("group is closed")

ErrGroupClosed is returned by MutableOutboundGroup Add/Remove when the group has already been torn down.

Functions

func ContextWithDirectTransport

func ContextWithDirectTransport(ctx context.Context, rt http.RoundTripper) context.Context

ContextWithDirectTransport returns a copy of ctx carrying the given http.RoundTripper as the "direct transport". Outbounds that need to make HTTP requests outside the user-facing VPN tunnel (e.g. unbounded's signaling to freddie) should retrieve this transport via DirectTransportFromContext.

The caller (typically radiance, when starting the libbox service) is responsible for building a RoundTripper that dials via the physical interface rather than re-entering the TUN — usually a kindling-backed RoundTripper whose underlying dialer is sing-box's direct outbound, which applies platform socket protection (VpnService.protect on Android, IP_BOUND_IF on iOS/macOS) automatically.

If no direct transport is set, outbounds should fall back to their own DialerOptions-derived dialer. That path does NOT bypass the tunnel, so it is suitable for tests and stand-alone sing-box use but not for production on-device VPN operation.

func ContextWithProbe

func ContextWithProbe(ctx context.Context) context.Context

ContextWithProbe marks dials made with ctx as probes: connections that test an outbound rather than carry user traffic.

func DirectTransportFromContext

func DirectTransportFromContext(ctx context.Context) http.RoundTripper

DirectTransportFromContext returns the direct http.RoundTripper stored in ctx, or nil if none was registered.

func IsProbe

func IsProbe(ctx context.Context) bool

IsProbe reports whether ctx was marked by ContextWithProbe.

Types

type AutoSelectHistoryStorage

type AutoSelectHistoryStorage interface {
	Load(tag string) *TagHistory
	Store(tag string, h *TagHistory)
	Delete(tag string)
	All() map[string]*TagHistory
	SetHook(hook func(tag string))
	Close() error
}

AutoSelectHistoryStorage is the store the MutableAutoSelect group writes to whenever a member's history changes.

Implementations must be safe for concurrent use. Store and Delete must be non-blocking and fast: the group calls them while holding internal locks, so blocking work — disk I/O, network calls, slow serialization — must happen out-of-band via the hook, not inline. When a state change actually occurs, the hook fires after the change is visible to subsequent Load callers. A Store of nil is equivalent to Delete. Calls that arrive after Close are dropped without panic.

func NewAutoSelectHistoryStorage

func NewAutoSelectHistoryStorage() AutoSelectHistoryStorage

NewAutoSelectHistoryStorage returns an in-memory AutoSelectHistoryStorage. The returned storage is empty; hosts seed it by calling Store for each entry restored from disk before registering it in the service context.

type ExhaustionSignaler

type ExhaustionSignaler interface {
	ExhaustionSignal() <-chan struct{}
}

ExhaustionSignaler exposes a channel the host can select on to learn that the group's reconnection ladder finished without finding a working candidate. At most one value is sent per ladder run; the host decides what to do (typically a rate-limited config refetch).

type MutableOutboundGroup

type MutableOutboundGroup interface {
	adapter.OutboundGroup
	Add(tags ...string) (n int, err error)
	Remove(tags ...string) (n int, err error)
}

type OutboundChecker

type OutboundChecker interface {
	CheckOutbounds()
}

OutboundChecker is implemented by outbound groups that support on-demand URL testing.

type TagHistory

type TagHistory struct {
	// LastSuccessDelayMs is the most recent successful probe RTT.
	// 0 means "no successful probe yet".
	LastSuccessDelayMs uint32 `json:"last_success_delay_ms,omitempty"`
	// LastOutcomeAt is the timestamp of the most recent probe outcome.
	LastOutcomeAt time.Time `json:"last_outcome_at,omitempty"`
	// ConsecutiveFailures counts probe failures since the last probe
	// success. Resets to zero on probe success.
	ConsecutiveFailures uint32 `json:"consecutive_failures,omitempty"`
	// UserFailures is the sliding window of user-traffic failures, each
	// tagged with its kind. Probe successes never enter this window; entries
	// age out naturally on the next mutation older than the group's
	// userFailureWindow.
	UserFailures []UserFailure `json:"user_failures,omitempty"`
	// HardDemoted reports whether the member has reached the hard-demote
	// tier from its own recorded probe and user-traffic failures.
	HardDemoted bool      `json:"hard_demoted,omitempty"`
	UpdatedAt   time.Time `json:"updated_at"`
}

TagHistory is a point-in-time snapshot of one member's selection state, mirroring the in-memory history kept by the MutableAutoSelect group. Probe outcomes feed the scalar fields; real user-traffic outcomes (dial errors, data-plane stalls) feed the UserFailures sliding window. The two tracks are kept separate so a censor that lets the probe URL through while dropping user traffic shows up as elevated UserFailures with healthy probe scalars simultaneously.

func (*TagHistory) LatestSuccessDelay

func (h *TagHistory) LatestSuccessDelay() uint32

LatestSuccessDelay returns LastSuccessDelayMs, or 0 when h is nil. Kept as a method for symmetry with LatestSuccessTime and to let callers handle nil snapshots without an extra branch.

func (*TagHistory) LatestSuccessTime

func (h *TagHistory) LatestSuccessTime() time.Time

LatestSuccessTime is best-effort: the spec only persists the most recent outcome timestamp (success or failure), so callers asking "tested N seconds ago" get UpdatedAt as a usable reference even when the most recent outcome was a failure. Returns the zero time when h is nil.

type TaggedConn

type TaggedConn struct {
	net.Conn
	// contains filtered or unexported fields
}

TaggedConn is a net.Conn tagged with the outbound tag used to create it.

func NewTaggedConn

func NewTaggedConn(conn net.Conn, outboundTag string) *TaggedConn

func (*TaggedConn) Tag

func (c *TaggedConn) Tag() string

func (*TaggedConn) Upstream

func (c *TaggedConn) Upstream() any

Upstream exposes the wrapped conn to common.Cast, so lookups such as the router's pending-handshake check see through the tag.

type TaggedPacketConn

type TaggedPacketConn struct {
	net.PacketConn
	// contains filtered or unexported fields
}

TaggedPacketConn is a net.PacketConn tagged with the outbound tag used to create it.

It implements N.NetPacketConn so packets written to a domain-name destination reach the wrapped conn with the domain intact. Written only as a net.PacketConn, sing's bufio adapter would reduce the destination to an IP-only address, which per-packet-addressed outbounds reject.

func NewTaggedPacketConn

func NewTaggedPacketConn(conn net.PacketConn, outboundTag string) *TaggedPacketConn

func (*TaggedPacketConn) ReadPacket

func (c *TaggedPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error)

func (*TaggedPacketConn) Tag

func (c *TaggedPacketConn) Tag() string

func (*TaggedPacketConn) Upstream

func (c *TaggedPacketConn) Upstream() any

Upstream exposes the wrapped conn to common.Cast and headroom/MTU lookups. TaggedPacketConn is deliberately not Reader/WriterReplaceable, so copy loops never bypass it or the wrappers beneath it.

func (*TaggedPacketConn) WritePacket

func (c *TaggedPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error

type URLOverrideSetter

type URLOverrideSetter interface {
	SetURLOverrides(overrides map[string]string)
}

URLOverrideSetter is implemented by outbound groups that support per-outbound URL test overrides.

type UserFailure

type UserFailure struct {
	At   time.Time       `json:"at"`
	Kind UserFailureKind `json:"kind,omitempty"`
}

UserFailure stores when a user-traffic failure happened and what kind it was.

func (*UserFailure) UnmarshalJSON

func (u *UserFailure) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts both the current object form and the legacy bare timestamp form. Legacy entries are tagged as unknown.

type UserFailureKind

type UserFailureKind string

UserFailureKind distinguishes how a member's user traffic failed.

const (
	// UserFailureDial is a failure to establish the connection to the member.
	UserFailureDial UserFailureKind = "dial"
	// UserFailureStall is a data-plane stall on an already-dialed connection:
	// the tunnel carried traffic, then went silent for the idle window.
	UserFailureStall UserFailureKind = "stall"
	// UserFailureReset is a non-benign transport error (e.g. RST) on an
	// already-established connection — the tunnel broke mid-stream rather
	// than going quiet.
	UserFailureReset   UserFailureKind = "reset"
	UserFailureUnknown UserFailureKind = "unknown"
	// UserFailureNoResponse is a dialed connection that sent data but had no
	// response observed before the first-response timeout.
	UserFailureNoResponse UserFailureKind = "no_response"
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL