common

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: MPL-2.0 Imports: 42 Imported by: 0

Documentation

Overview

SPDX-License-Identifier: MPL-2.0 Copyright (c) 2025 KeibiSoft S.R.L. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

SPDX-License-Identifier: MPL-2.0 Copyright (c) 2025 KeibiSoft S.R.L. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

Index

Constants

View Source
const Timeout = 10*60 - 5

Timeout is the peer-join wait budget in seconds: 10 minutes minus a 5s margin, matching the relay registration TTL.

Variables

View Source
var (
	Version    = "0.3.1"
	CommitHash = "dev" // Build ldflags overwrite this value.
)
View Source
var (
	ErrNilPointer                    = errors.New("nil pointer")
	ErrEmptyFingerprint              = errors.New("fingerprint is empty")
	ErrInvalidLength                 = errors.New("invalid length")
	ErrRelayAtMaximumCapacity        = errors.New("relay at maximum capacity")
	ErrRateLimitHit                  = errors.New("relay rate limit hit, retry in 5 minutes")
	ErrMissingFingerprint            = errors.New("missing fingerprint header")
	ErrInvalidPayload                = errors.New("invalid registration payload")
	ErrMissingKeys                   = errors.New("missing public keys")
	ErrInvalidFingerprint            = errors.New("invalid fingerprint format")
	ErrServerError                   = errors.New("server error")
	ErrTemporaryRetry                = errors.New("temporary network issue")
	ErrTimeoutReached                = errors.New("timeout reached")
	ErrFingerprintMismatch           = errors.New("fingerprint mismatch")
	ErrRelayAtFullCapacityRetryLater = errors.New("relay at full capacity, retry later")
	ErrNotFound                      = errors.New("not found")
	ErrInvalidResponse               = errors.New("invalid response")
	ErrInvalidIP                     = errors.New("invalid IP")
	ErrSessionNotEstablished         = errors.New("session not established")
	ErrFilesystemAlreadyMounted      = errors.New("filesystem already mounted")
	ErrNilFilesystem                 = errors.New("filesystem not mounted")
	ErrAlreadyRunning                = errors.New("already running")
	ErrInvalidSession                = errors.New("invalid session")
	ErrServerAtCapacity              = errors.New("relay server at capacity, please try again in 5 minutes")
	ErrIdenticalFingerprints         = errors.New("own and peer fingerprints are identical")
	ErrDownloadPaused                = errors.New("download paused")
)
View Source
var ErrNoQUICForFold = errors.New("no quic channel for fold")

ErrNoQUICForFold routes the eager fold to TCP when no QUIC channel is up. It never escapes runEagerFold.

Functions

func DecideLocalRole added in v0.3.5

func DecideLocalRole(myName, peerName, peerAddr string) bool

DecideLocalRole reports whether this peer should create (listen) rather than join (dial) for a local-mode connection to peerName at peerAddr. It feeds LocalConnectRole this peer's LAN IPv4 and the peer's bare IP (port/zone stripped), so colliding names compare like-for-like.

func DialQUICControl added in v0.4.0

func DialQUICControl(ctx context.Context, s *session.Session, peerUDPAddr string) (net.Conn, *transport.MigratableConn, error)

DialQUICControl brings up the outbound QUIC control channel to peerUDPAddr. It wraps a migratable QUIC stream in the outbound SecureConn and returns the migration handle. It errors when the peer negotiated no QUIC key, so the caller falls back to TCP-only.

func GetDiscoveryLANAddress added in v0.3.5

func GetDiscoveryLANAddress() string

GetDiscoveryLANAddress returns this machine's private IPv4 in the form peers see via discovery. The local-connect tiebreak needs the same form on both sides. It returns "" when no private IPv4 exists.

func GetGlobalIPv6

func GetGlobalIPv6() (string, error)

GetGlobalIPv6 returns a stable, non-temporary global IPv6 address. RFC 4941 privacy extensions rotate temporary addresses. Connections bound to a temporary address break when the OS deprecates it.

func GetJSONWithURL

func GetJSONWithURL(client *http.Client, endpoint *url.URL, headers map[string]string, mapError ErrorMapperFunc) (*http.Response, error)

func GetLinkLocalAddress

func GetLinkLocalAddress(port int) (string, error)

GetLinkLocalAddress returns a link-local IPv6 address as "ip%zone:port" for direct LAN peer connections. It falls back to loopback when no link-local interface exists.

func GetLocalAddrs

func GetLocalAddrs() []string

GetLocalAddrs returns all private and link-local IP addresses for LAN discovery. The relay registration includes them, so same-network peers can connect directly.

func GetLocalIPv6

func GetLocalIPv6() (string, error)

func ListenQUICControl added in v0.4.0

func ListenQUICControl(s *session.Session, udpAddr string) (net.Listener, error)

ListenQUICControl starts the inbound QUIC control listener on udpAddr. It wraps each accepted stream in the inbound SecureConn and errors when the peer negotiated no QUIC key.

func LocalConnectRole added in v0.3.5

func LocalConnectRole(myName, peerName, myAddr, peerAddr string) (create bool)

LocalConnectRole picks who creates (listens) vs joins (dials) in local mode. Smaller name creates; if names collide (random), smaller address breaks it.

func NewSingleConnListener

func NewSingleConnListener(conn net.Conn) net.Listener

func ParsePeerDirectAddress

func ParsePeerDirectAddress(addr string) (ip string, zone string, port int, err error)

ParsePeerDirectAddress parses a direct LAN peer address in any stored form: "ip", "ip:port", "ip%zone", "ip%zone:port", "[ip]:port", or "[ip%zone]:port". It returns the bare IP, the zone ("" when absent), and the port (0 when absent). The IP must be link-local, loopback, or private. IPv6 link-local requires a zone.

func PostJSONWithURL

func PostJSONWithURL(client *http.Client, endpoint *url.URL, headers map[string]string, payload interface{}, mapError ErrorMapperFunc) (*http.Response, error)

func PrintBanner

func PrintBanner()

func RegisterErrorMapper

func RegisterErrorMapper(statusCode int, err error) error

func SanitizeLogContent

func SanitizeLogContent(raw string) string

SanitizeLogContent sanitizes log text in memory.

func SanitizeLogs

func SanitizeLogs(logPath string) (string, error)

SanitizeLogs reads a log file and returns sanitized content. It redacts file names (extensions stay), fingerprints, and IP addresses. It keeps timestamps, log levels, method names, error types, sizes, and connection events.

func SanitizeLogsToFile

func SanitizeLogsToFile(logPath, destPath string) error

SanitizeLogsToFile reads a log, sanitizes it, and writes to destPath.

func ValidateFingerprint

func ValidateFingerprint(fp string) error

Types

type ConnectionHint

type ConnectionHint struct {
	IP    string `json:"ip"`             // Public IP address, v4 or v6.
	Port  int    `json:"port"`           // Where the peer listens.
	IPv6  bool   `json:"ipv6"`           // True when this hint prefers IPv6.
	Proto string `json:"proto"`          // For example "tcp".
	Note  string `json:"note,omitempty"` // Optional: NAT behavior notes.
	// InboundBlocked means nothing reaches the address above, so a dial only burns the
	// timeout. It rides inside the encrypted blob, so the relay never sees it. Older
	// peers omit it, which decodes as false.
	InboundBlocked bool `json:"inbound_blocked,omitempty"`
}

type EnableOpts added in v0.2.0

type EnableOpts struct {
	PassphraseProtect  bool
	PassphraseProvider func() (string, error)
	ExternalMaster     []byte // 32-byte key from mobile bridge (iOS Keychain / Android Keystore)
}

EnableOpts controls how persistent identity loads:

  • PassphraseProtect: opt into Tier 2, a passphrase-derived key. Requires a non-nil PassphraseProvider.
  • PassphraseProvider: runs once when PassphraseProtect is true to obtain the passphrase. Typical sources: TTY prompt, stdin bridge, test stub.

type EncryptedRegistration

type EncryptedRegistration struct {
	Blob   string `json:"blob"`             // base64-encoded ChaCha20-Poly1305 ciphertext
	Bridge string `json:"bridge,omitempty"` // relay-suggested bridge address (e.g., "fra1.bridge.keibisoft.com:26600")
	Tier   string `json:"tier,omitempty"`   // bandwidth tier: "free", "priority" (relay metadata, not encrypted)
}

EncryptedRegistration is the relay-visible payload, an opaque blob. Only peers with the shared room password can decrypt it.

type ErrorMapperFunc

type ErrorMapperFunc func(statusCode int, err error) error

ErrorMapperFunc maps server status errors to semantic errors.

type ImplFileStreamProvider

type ImplFileStreamProvider struct {
	// contains filtered or unexported fields
}

func NewImplStreamProviderDual added in v0.4.0

func NewImplStreamProviderDual(bulk, fast bindings.KeibiServiceClient) *ImplFileStreamProvider

NewImplStreamProviderDual routes bulk prefetch to TCP, on-demand reads and chunk hashes to QUIC. A cache miss then does not queue behind a running prefetch.

func (*ImplFileStreamProvider) GetChunkHashes added in v0.3.6

func (sp *ImplFileStreamProvider) GetChunkHashes(ctx context.Context, path string, chunkSize, fromChunk, count uint64) (types.ChunkHashReceiver, error)

GetChunkHashes requests per-chunk xxh3-64 fingerprints from the peer. An older peer returns codes.Unimplemented. The caller decides the fallback.

func (*ImplFileStreamProvider) OpenRemoteFile

func (sp *ImplFileStreamProvider) OpenRemoteFile(ctx context.Context, inode uint64, path string) (types.RemoteFileStream, error)

func (*ImplFileStreamProvider) StreamFile

func (sp *ImplFileStreamProvider) StreamFile(ctx context.Context, path string, startOffset uint64) (types.StreamFileReceiver, error)

StreamFile starts a push-based download via the server-streaming StreamFile RPC. It uses preferBulk routing: TCP first, QUIC when TCP is dead.

type ImplRemoteFileStream

type ImplRemoteFileStream struct {
	// contains filtered or unexported fields
}

func (*ImplRemoteFileStream) Close

func (rfs *ImplRemoteFileStream) Close() error

func (*ImplRemoteFileStream) ReadAt

func (rfs *ImplRemoteFileStream) ReadAt(ctx context.Context, offset int64, size int64) ([]byte, error)

type KeibiDrop

type KeibiDrop struct {
	RelayEndoint *url.URL

	Identity    *identity.DeviceIdentity
	AddressBook *identity.AddressBook
	Incognito   bool

	IsFUSE         bool
	IsLocalMode    bool
	BridgeAddr     string // TCP bridge relay address for firewall traversal
	StrictMode     bool   // Disables the data relay fallback: direct connections only.
	ConnectionMode string // "lan", "direct", or "bridge". Set after a successful connection.
	OpInProgress   atomic.Int32

	PeerIPv6IP     string
	PeerLocalAddrs []string // LAN IPs from the relay registration, for same-network direct connect.

	LocalIPv6IP string

	// Filesystem.
	FS       *filesystem.FS
	KDSvc    *service.KeibidropServiceImpl
	KDClient bindings.KeibiServiceClient

	// Non-FUSE fallback.
	SyncTracker *synctracker.SyncTracker

	// Paths for the virtual mount point and the save folder.
	ToMount string
	ToSave  string

	// Collab sync options.
	PrefetchOnOpen bool
	PushOnWrite    bool
	// AutoCache enables the macFUSE auto_cache mount option, so a peer's same-size
	// in-place edit shows live. The caller sets it from config.LiveCollab. False = git-safe.
	AutoCache         bool
	PrefetchAutoMB    int // Files >= this many MB auto-prefetch on open. From config.PrefetchAutoMB. 0 = off.
	ReadAheadWindowMB int // Cap in MB for predictive sequential read-ahead. From config.ReadAheadWindowMB. 0 = off.

	Cancel context.CancelFunc // Exported so the FFI layer can call it for app exit.

	// Event callback. The FFI layer wires it to push events to the UI.
	OnEvent func(string)

	// OnPeerVerified fires with the peer's verified fingerprint when the handshake
	// confirms identity, before any files sync. setupFilesystem wires it to scope the
	// FUSE cache to the peer: drop another peer's view, keep the same peer's.
	OnPeerVerified func(fp string)

	// Connection resilience.
	HealthMonitor    *session.HealthMonitor
	ReconnectManager *session.ReconnectManager
	RelayKeepalive   *RelayKeepalive
	// contains filtered or unexported fields
}

func NewKeibiDrop

func NewKeibiDrop(ctx context.Context, logger *slog.Logger, isFuse bool, relayURL *url.URL, inboundPort int, defaultOutboundPort int, toMount string, toSave string, prefetchOnOpen bool, pushOnWrite bool) (*KeibiDrop, error)

NewKeibiDrop builds a KeibiDrop and probes the local global IPv6 address.

func NewKeibiDropWithIP

func NewKeibiDropWithIP(ctx context.Context, logger *slog.Logger, isFuse bool, relayURL *url.URL, inboundPort int, defaultOutboundPort int, toMount string, toSave string, prefetchOnOpen bool, pushOnWrite bool, ipv6Address string) (*KeibiDrop, error)

NewKeibiDropWithIP is NewKeibiDrop with an explicit IPv6 address instead of a network probe. It enables tests on machines without a global IPv6 address.

func (*KeibiDrop) AddFile

func (kd *KeibiDrop) AddFile(path string) error

Add a file to be tracked.

func (*KeibiDrop) AddFileAs

func (kd *KeibiDrop) AddFileAs(localPath string, remoteName string) error

AddFileAs adds a file with a custom remote name (preserving folder structure). Automatically sends ADD_DIR for any parent directories the peer may not have.

func (*KeibiDrop) AddPeerFingerprint

func (kd *KeibiDrop) AddPeerFingerprint(fp string) error

func (*KeibiDrop) CancelDownload

func (kd *KeibiDrop) CancelDownload(remoteName string) error

CancelDownload cancels an active download. The partial file and bitmap are preserved on disk so the next PullFile call resumes automatically.

func (*KeibiDrop) CheckContactPresence added in v0.2.0

func (kd *KeibiDrop) CheckContactPresence(fingerprint string) bool

CheckContactPresence reports whether the relay saw the contact online recently.

func (*KeibiDrop) Connect

func (kd *KeibiDrop) Connect() error

Connect determines the creator/joiner role automatically using deterministic fingerprint comparison and calls CreateRoom or JoinRoom. Lower fingerprint = creator (registers to relay, accepts inbound). Higher fingerprint = joiner (fetches from relay, dials out).

func (*KeibiDrop) ConnectToContact added in v0.2.0

func (kd *KeibiDrop) ConnectToContact(fingerprint string) error

ConnectToContact looks up a contact by fingerprint, registers it, and connects.

func (*KeibiDrop) ConnectionStatus

func (kd *KeibiDrop) ConnectionStatus() string

ConnectionStatus returns the current connection health status. It snapshots the monitor under kd.mu, because teardown nils the field under the same lock.

func (*KeibiDrop) CreateRoom

func (kd *KeibiDrop) CreateRoom() error

func (*KeibiDrop) DowngradeListenerIPv6Only

func (kd *KeibiDrop) DowngradeListenerIPv6Only() error

DowngradeListenerIPv6Only replaces the dual-stack listener with an IPv6-only listener when local mode ends.

func (*KeibiDrop) EnablePersistentIdentity added in v0.2.0

func (kd *KeibiDrop) EnablePersistentIdentity(configDir string, opts EnableOpts) error

EnablePersistentIdentity replaces ephemeral keys with a stable device identity. Call it before CreateRoom/JoinRoom. It loads or creates the identity in configDir, rebuilds the session with stable keys, and loads the address book.

func (*KeibiDrop) EnablePersistentIdentityDefault added in v0.2.0

func (kd *KeibiDrop) EnablePersistentIdentityDefault(configDir string) error

EnablePersistentIdentityDefault calls EnablePersistentIdentity with zero-value EnableOpts: keychain or file tier, no passphrase.

func (*KeibiDrop) ExportFingerprint

func (kd *KeibiDrop) ExportFingerprint() (string, error)

func (*KeibiDrop) GetDownloadProgress

func (kd *KeibiDrop) GetDownloadProgress(remoteName string) float64

GetDownloadProgress returns the download progress for a file as a fraction [0.0, 1.0]. Returns -1 if the file has no active or resumable download.

func (*KeibiDrop) GetPeerFingerprint

func (kd *KeibiDrop) GetPeerFingerprint() (string, error)

func (*KeibiDrop) InboundBlocked added in v0.4.0

func (kd *KeibiDrop) InboundBlocked() bool

InboundBlocked reports whether to advertise the listener as unreachable. The mark binds to the address that observed it. A new address is a new network and re-probes, so one bad network cannot pin the node to the relay.

func (*KeibiDrop) InboundPort

func (kd *KeibiDrop) InboundPort() int

InboundPort returns the port this instance listens on for incoming connections.

func (*KeibiDrop) InitConnectionResilience

func (kd *KeibiDrop) InitConnectionResilience() error

func (*KeibiDrop) IsPeerPersistent added in v0.2.0

func (kd *KeibiDrop) IsPeerPersistent() bool

IsPeerPersistent returns whether the currently connected peer has a stable identity.

func (*KeibiDrop) IsRunning

func (kd *KeibiDrop) IsRunning() bool

IsRunning returns whether the KeibiDrop instance is in a connected session.

func (*KeibiDrop) JoinRoom

func (kd *KeibiDrop) JoinRoom() error

func (*KeibiDrop) ListFiles

func (kd *KeibiDrop) ListFiles() (remote []string, local []string)

func (*KeibiDrop) MigrateQUICControl added in v0.4.0

func (kd *KeibiDrop) MigrateQUICControl(ctx context.Context) error

MigrateQUICControl moves the live QUIC control connection to a fresh local UDP socket without a drop: QUIC keys the connection on connection ID, not the 5-tuple. It pings after, so the peer migrates its send path. On error the channel demotes and the maintainer re-establishes.

func (*KeibiDrop) MountFilesystem

func (kd *KeibiDrop) MountFilesystem(toMount string, toSave string, isSecond bool) error

This is blocking.

func (*KeibiDrop) NotifyDisconnect

func (kd *KeibiDrop) NotifyDisconnect()

NotifyDisconnect sends a best-effort DISCONNECT notification to the peer so they can clean up immediately instead of waiting for health monitor timeout.

func (*KeibiDrop) PeerInboundBlocked added in v0.4.0

func (kd *KeibiDrop) PeerInboundBlocked() bool

PeerInboundBlocked reports whether the peer advertised its listener as unreachable.

func (*KeibiDrop) PingQUICControl added in v0.4.0

func (kd *KeibiDrop) PingQUICControl(ctx context.Context) error

PingQUICControl sends one control Ping over the QUIC channel, or errors if it is down.

func (*KeibiDrop) ProbeInboundReachability added in v0.4.0

func (kd *KeibiDrop) ProbeInboundReachability(ctx context.Context)

ProbeInboundReachability asks the relay to dial the local listener and caches the verdict per local address for probeCacheTTL. Any failure leaves the mark unchanged.

func (*KeibiDrop) PullFile

func (kd *KeibiDrop) PullFile(remoteName, localPath string) error

func (*KeibiDrop) PullFileWithParams

func (kd *KeibiDrop) PullFileWithParams(remoteName, localPath string, blockSize, nWorkers int) error

PullFileWithParams downloads remoteName to localPath using the specified blockSize (bytes per gRPC chunk) and nWorkers (parallel streams). Intended for benchmarking; production code uses PullFile with defaults.

func (*KeibiDrop) QUICControlConnected added in v0.4.0

func (kd *KeibiDrop) QUICControlConnected() bool

QUICControlConnected reports whether the outbound QUIC control channel is up. For tests.

func (*KeibiDrop) QUICKeibiClient added in v0.4.0

func (kd *KeibiDrop) QUICKeibiClient() bindings.KeibiServiceClient

QUICKeibiClient returns a KeibiService client over the QUIC control channel, or nil when it is down. The channel is transport-isolated from TCP bulk, so metadata never queues behind a prefetch.

func (*KeibiDrop) QUICMetadataSent added in v0.4.0

func (kd *KeibiDrop) QUICMetadataSent() uint64

QUICMetadataSent reports how many metadata RPCs rode the QUIC channel.

func (*KeibiDrop) QUICWriterEpoch added in v0.4.0

func (kd *KeibiDrop) QUICWriterEpoch() uint16

QUICWriterEpoch returns the highest writer key-epoch across the live QUIC control conns, or 0 when the channel is down. The QUIC lane ratchets independently of the TCP pair, so rekey observability must read both lanes.

func (*KeibiDrop) ReconnectionAttempts

func (kd *KeibiDrop) ReconnectionAttempts() int

ReconnectionAttempts returns the number of reconnection attempts.

func (*KeibiDrop) ReconnectionState

func (kd *KeibiDrop) ReconnectionState() string

ReconnectionState returns the current reconnection state. It snapshots the manager under kd.mu, because teardown nils the field under the same lock.

func (*KeibiDrop) Run

func (kd *KeibiDrop) Run()

Run is the main loop. Call it as a goroutine.

func (*KeibiDrop) SaveCurrentPeerAsContact added in v0.2.0

func (kd *KeibiDrop) SaveCurrentPeerAsContact(name string) error

SaveCurrentPeerAsContact saves the currently connected peer as a named contact.

func (*KeibiDrop) SetPeerDirectAddress

func (kd *KeibiDrop) SetPeerDirectAddress(addr string) error

SetPeerDirectAddress parses a direct LAN peer address (e.g. "fe80::1%eth0:26431"), stores the peer IP and port, and sets TOFU mode for the handshake.

func (*KeibiDrop) Shutdown

func (kd *KeibiDrop) Shutdown()

Shutdown permanently stops the Run goroutine. Use it for app exit. For a temporary disconnect, use Stop. Safe to call many times from any goroutine.

func (*KeibiDrop) Start

func (kd *KeibiDrop) Start()

Start signals the Run loop to begin a session.

func (*KeibiDrop) StartPresenceHeartbeat added in v0.2.0

func (kd *KeibiDrop) StartPresenceHeartbeat(ctx context.Context)

StartPresenceHeartbeat sends periodic presence heartbeats for all contacts. It runs until the caller cancels ctx. Call it after EnablePersistentIdentity.

func (*KeibiDrop) StartQUICControlChannel added in v0.4.0

func (kd *KeibiDrop) StartQUICControlChannel()

StartQUICControlChannel brings up the QUIC control pair alongside the TCP session: an inbound listener on the local UDP port and a background outbound dial to the peer. Any failure logs and leaves the session TCP-only. The dial never delays connect.

func (*KeibiDrop) Stop

func (kd *KeibiDrop) Stop()

Stop cleanly disconnects the current session. Run() continues after cleanup, ready for the next CreateRoom/JoinRoom. Thread-safe.

func (*KeibiDrop) StopConnectionResilience

func (kd *KeibiDrop) StopConnectionResilience()

StopConnectionResilience stops all resilience components. It snapshots the handles under kd.mu, because teardown nils the fields under the same lock and external callers run concurrently with it. Stop calls run outside the lock.

func (*KeibiDrop) StopQUICControlChannel added in v0.4.0

func (kd *KeibiDrop) StopQUICControlChannel()

StopQUICControlChannel tears down the QUIC control pair. It is safe when the pair never came up. The listener close also retires a waiting serveQUICControl goroutine.

func (*KeibiDrop) ToggleIncognito added in v0.2.0

func (kd *KeibiDrop) ToggleIncognito(incognito bool, configDir string) (string, error)

ToggleIncognito switches between persistent and ephemeral identity. Enabling generates fresh ephemeral keys. Disabling restores the persistent keys. It returns the new fingerprint.

func (*KeibiDrop) UnmountFilesystem

func (kd *KeibiDrop) UnmountFilesystem() error

func (*KeibiDrop) UnshareFile added in v0.3.0

func (kd *KeibiDrop) UnshareFile(name string) error

UnshareFile removes a file from the shared list and notifies the peer. Does NOT delete the file from disk.

func (*KeibiDrop) UpgradeListenerDualStack

func (kd *KeibiDrop) UpgradeListenerDualStack() error

UpgradeListenerDualStack replaces the IPv6-only listener with a dual-stack one. Local mode uses it: LAN discovery needs IPv4 connectivity.

func (*KeibiDrop) WriterEpoch added in v0.4.0

func (kd *KeibiDrop) WriterEpoch() uint16

WriterEpoch reports the in-band ratchet generation: the max writer epoch across both live directions, or 0 before a monitor exists. It snapshots the monitor under kd.mu, because teardown nils the field under the same lock; the snapshot's captured conns are immutable, so the epoch read itself is race-free.

type PeerRegistration

type PeerRegistration struct {
	Fingerprint string            `json:"fingerprint"`
	PublicKeys  map[string]string `json:"public_keys"` // base64 encoded
	Listen      *ConnectionHint   `json:"listen"`
	Reverse     *ConnectionHint   `json:"reverse,omitempty"`
	LocalAddrs  []string          `json:"local_addrs,omitempty"` // LAN IPs (192.168.x.x, fe80::x) for same-network detection
	Timestamp   int64             `json:"timestamp"`
}

type RelayKeepalive

type RelayKeepalive struct {

	// Configuration
	Interval time.Duration // Refresh interval. Must stay under relayEntryTTL.
	// contains filtered or unexported fields
}

RelayKeepalive refreshes the relay registration before the TTL expires, so peers can always find each other.

func NewRelayKeepalive

func NewRelayKeepalive(kd *KeibiDrop, logger *slog.Logger) *RelayKeepalive

NewRelayKeepalive creates a new relay keepalive manager.

func (*RelayKeepalive) CheckIPChange

func (rk *RelayKeepalive) CheckIPChange() error

CheckIPChange refreshes the relay registration when the local IP changes. Call it periodically or on network state change.

func (*RelayKeepalive) FailureCount

func (rk *RelayKeepalive) FailureCount() int

FailureCount returns the number of consecutive refresh failures.

func (*RelayKeepalive) ForceRefresh

func (rk *RelayKeepalive) ForceRefresh() error

ForceRefresh refreshes the relay registration immediately. Call it on IP change or reconnection.

func (*RelayKeepalive) LastRefresh

func (rk *RelayKeepalive) LastRefresh() time.Time

LastRefresh returns the timestamp of the last successful refresh.

func (*RelayKeepalive) Pause

func (rk *RelayKeepalive) Pause()

Pause disables refresh, for example while disconnected.

func (*RelayKeepalive) Resume

func (rk *RelayKeepalive) Resume()

Resume re-enables refresh.

func (*RelayKeepalive) Start

func (rk *RelayKeepalive) Start()

Start begins the background refresh loop.

func (*RelayKeepalive) Stop

func (rk *RelayKeepalive) Stop()

Stop halts the background refresh loop.

type TaskSignal

type TaskSignal int
const (
	Start TaskSignal = iota
	Stop
)

Jump to

Keyboard shortcuts

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