common

package
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2026 License: MPL-2.0 Imports: 44 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/.

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.

View Source
const TokenUnitBytes int64 = 10 << 20

TokenUnitBytes is the bandwidth one chain step buys. PROTOCOL CONSTANT shared with the relay ledger, the bridge and the token service.

View Source
const TokensBuyURL = "https://tokens.keibidrop.com/buy" //nolint:gosec // G101: URL, not a credential

TokensBuyURL is where money changes hands. Prices live on that page and in the token service's pack table, never in this binary.

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 BridgeStatus added in v0.4.1

type BridgeStatus struct {
	Addr       string  `json:"addr,omitempty"` // bridge host:port this session dials
	Via        string  `json:"via,omitempty"`  // display form: bridge hostname
	Paid       bool    `json:"paid"`           // bridge acked paid priority for this session
	Contention bool    `json:"contention"`     // bridge signaled contention in its ack
	Busy       bool    `json:"busy"`           // relay flagged the assigned bridge busy
	Notice     string  `json:"notice,omitempty"`
	WalletGB   float64 `json:"wallet_gb"`  // prepaid value left across chains
	SessionGB  float64 `json:"session_gb"` // bytes this session moved via the bridge, both directions
}

BridgeStatus is the relay-visibility surface: which bridge a session rides, whether it holds paid priority, and what the relay says about load. Shown by the CLI status, the kd daemon and the desktop UI.

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 CreditStatus added in v0.4.1

type CreditStatus struct {
	WalletGB float64 `json:"wallet_gb"`
	Level    string  `json:"level"` // "ok", "low", "critical", "empty"
	Notice   string  `json:"notice,omitempty"`
	BuyURL   string  `json:"buy_url"`
}

CreditStatus is the level-readable relay credit state. Events are edges; agents and frontends poll this for the current level.

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)
	Busy   bool   `json:"busy,omitempty"`   // assigned bridge is in contention right now
	Notice string `json:"notice,omitempty"` // server-controlled text shown to the user with busy
}

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.
	ScanSharedOnStart bool   // Announce files already in ToSave when a session starts. From config.ScanSharedOnStart.
	AutoConnectPeer   string // Saved contact to connect to on startup, with retry. From config.AutoConnectPeer.
	ShareReadOnly     bool   // Refuse every inbound peer mutation at the service layer. From config.ShareReadOnly.
	MountReadOnly     bool   // Local FUSE mount returns EROFS on write ops. From config.MountReadOnly.
	PreserveMetadata  bool   // Apply the origin's mode and times to files saved on disk. From config.PreserveMetadata.

	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) BackfillRemoteFilesIntoFS added in v0.4.1

func (kd *KeibiDrop) BackfillRemoteFilesIntoFS()

BackfillRemoteFilesIntoFS adds tracker-known remote files to the FUSE tree. ADD_FILE notifies that arrive before the first SetFS land only in SyncTracker.RemoteFiles; without this they never appear in the mount. Run calls it right after it publishes the mounted FS. Files already in the tree are left alone.

func (*KeibiDrop) BridgeInfo added in v0.4.1

func (kd *KeibiDrop) BridgeInfo() BridgeStatus

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 and VERIFIED: the client is published only after a control Ping the peer answered.

func (*KeibiDrop) QUICInboundAccepted added in v0.4.1

func (kd *KeibiDrop) QUICInboundAccepted() uint64

QUICInboundAccepted reports how many inbound QUIC control conns this peer accepted. The outbound half can be up while this stays 0, which is a one-directional lane.

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) QUICLaneStatus added in v0.4.1

func (kd *KeibiDrop) QUICLaneStatus() string

QUICLaneStatus reports the outbound lane as "up", or "down (<reason>)". kd status and peer-info show it, so a silently dead lane is visible without reading DEBUG logs.

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) ResolveContact added in v0.4.1

func (kd *KeibiDrop) ResolveContact(nameOrFingerprint string) (string, error)

ResolveContact maps a saved contact name (case-insensitive) or fingerprint to the contact's fingerprint.

func (*KeibiDrop) RevealHealth added in v0.4.1

func (kd *KeibiDrop) RevealHealth() map[string]any

RevealHealth reports the payment-reveal state for kd status: accepted count, consecutive failures, and the last error. Empty when the session is not funded.

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) ScanAndShareSaveDir added in v0.4.1

func (kd *KeibiDrop) ScanAndShareSaveDir(ctx context.Context) (int, error)

ScanAndShareSaveDir walks the save folder breadth-first and announces every regular file that is not yet tracked, over the same announce path AddFile uses: upsert LocalFiles, send ADD_FILE (in capped batches), persist to the shared store. Breadth-first, so the peer sees the top of the tree before deep subtrees. Nested files keep their save-root-relative path. Idempotent: tracked files are skipped, so restore, watcher events, and repeated scans compose. Returns the number of files announced. On a send error the walk stops; the next session's scan announces the rest.

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) StartAutoConnect added in v0.4.1

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

StartAutoConnect resolves AutoConnectPeer and arms the connect watchdog. A no-op when the field is empty. Returns an error when the value does not resolve to a saved contact, so frontends can surface a clear message at startup instead of a silent dead loop.

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) TokensAdd added in v0.4.1

func (kd *KeibiDrop) TokensAdd(code string) (float64, error)

TokensAdd pastes a code into the wallet and returns its spendable size in GB. The ledger is asked once so a spent or never-minted code is refused at paste time instead of at first spend. No ledger answer keeps the add: the wallet is a cache and pasting offline must keep working.

func (*KeibiDrop) TokensBuyStart added in v0.4.1

func (kd *KeibiDrop) TokensBuyStart() string

TokensBuyStart returns the buy page URL to open in a browser, carrying a fresh claim ref, and starts a background poll that adds the purchased code to the wallet the moment the payment lands. No copy-paste, no account: the claim is a random one-shot ID, generated here, tied to nothing. Starting a new purchase replaces the previous poll.

func (*KeibiDrop) TokensCreditStatus added in v0.4.1

func (kd *KeibiDrop) TokensCreditStatus() CreditStatus

TokensCreditStatus reports remaining relay credit against the same thresholds noteCreditLevel uses. The copy stays honest: dry credit means the free tier on bridged transfers, slower only under contention, never a cutoff, and direct connections are never affected.

func (*KeibiDrop) TokensRefreshBalances added in v0.4.1

func (kd *KeibiDrop) TokensRefreshBalances() []TokenChainSummary

TokensRefreshBalances asks the relay ledger for each chain's remaining units and adopts its view (it is authoritative; the local count only lags).

func (*KeibiDrop) TokensSummaries added in v0.4.1

func (kd *KeibiDrop) TokensSummaries() []TokenChainSummary

TokensSummaries lists wallet chains for display.

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) Wallet added in v0.4.1

func (kd *KeibiDrop) Wallet() *TokenWallet

Wallet lazily opens the machine-wide token wallet. Identity-independent by design: prepaid chains are bearer instruments, usable in incognito too.

func (*KeibiDrop) WireStats added in v0.4.1

func (kd *KeibiDrop) WireStats() (bytesSent, bytesRecv uint64)

WireStats sums bytes over the session's two TCP conns plus the QUIC control lanes (on-demand reads ride there when the lane is up). Counters reset on rekey. For tests and benchmarks.

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
)

type TokenChainSummary added in v0.4.1

type TokenChainSummary struct {
	Code      string  `json:"code"`
	GBTotal   float64 `json:"gb_total"`
	GBLeft    float64 `json:"gb_left"`
	UnitsLeft int     `json:"units_left"`
	Dead      bool    `json:"dead"`
	AddedAt   int64   `json:"added_at"`
}

TokenChainSummary is what CLIs and UIs display.

type TokenWallet added in v0.4.1

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

TokenWallet is the on-disk stash of prepaid chains. Plaintext JSON at 0600: the seeds ARE cash by design, and the user was warned to back up the codes.

func (*TokenWallet) Add added in v0.4.1

func (w *TokenWallet) Add(code string) (*walletChain, error)

Add validates a pasted code and stores its chain. Duplicate anchors merge.

func (*TokenWallet) Summaries added in v0.4.1

func (w *TokenWallet) Summaries() []TokenChainSummary

Jump to

Keyboard shortcuts

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