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
- Variables
- func GetGlobalIPv6() (string, error)
- func GetJSONWithURL(client *http.Client, endpoint *url.URL, headers map[string]string, ...) (*http.Response, error)
- func GetLinkLocalAddress(port int) (string, error)
- func GetLocalAddrs() []string
- func GetLocalIPv6() (string, error)
- func NewSingleConnListener(conn net.Conn) net.Listener
- func ParsePeerDirectAddress(addr string) (ip string, zone string, port int, err error)
- func PostJSONWithURL(client *http.Client, endpoint *url.URL, headers map[string]string, ...) (*http.Response, error)
- func PrintBanner()
- func RegisterErrorMapper(statusCode int, err error) error
- func SanitizeLogContent(raw string) string
- func SanitizeLogs(logPath string) (string, error)
- func SanitizeLogsToFile(logPath, destPath string) error
- func ValidateFingerprint(fp string) error
- type ConnectionHint
- type EnableOpts
- type EncryptedRegistration
- type ErrorMapperFunc
- type ImplFileStreamProvider
- type ImplRemoteFileStream
- type KeibiDrop
- func (kd *KeibiDrop) AddFile(path string) error
- func (kd *KeibiDrop) AddFileAs(localPath string, remoteName string) error
- func (kd *KeibiDrop) AddPeerFingerprint(fp string) error
- func (kd *KeibiDrop) CancelDownload(remoteName string) error
- func (kd *KeibiDrop) CheckContactPresence(fingerprint string) bool
- func (kd *KeibiDrop) Connect() error
- func (kd *KeibiDrop) ConnectToContact(fingerprint string) error
- func (kd *KeibiDrop) ConnectionStatus() string
- func (kd *KeibiDrop) CreateRoom() error
- func (kd *KeibiDrop) DowngradeListenerIPv6Only() error
- func (kd *KeibiDrop) EnablePersistentIdentity(configDir string, opts EnableOpts) error
- func (kd *KeibiDrop) EnablePersistentIdentityDefault(configDir string) error
- func (kd *KeibiDrop) ExportFingerprint() (string, error)
- func (kd *KeibiDrop) GetDownloadProgress(remoteName string) float64
- func (kd *KeibiDrop) GetPeerFingerprint() (string, error)
- func (kd *KeibiDrop) InboundPort() int
- func (kd *KeibiDrop) InitConnectionResilience() error
- func (kd *KeibiDrop) IsPeerPersistent() bool
- func (kd *KeibiDrop) IsRunning() bool
- func (kd *KeibiDrop) JoinRoom() error
- func (kd *KeibiDrop) ListFiles() (remote []string, local []string)
- func (kd *KeibiDrop) MountFilesystem(toMount string, toSave string, isSecond bool) error
- func (kd *KeibiDrop) NotifyDisconnect()
- func (kd *KeibiDrop) PullFile(remoteName, localPath string) error
- func (kd *KeibiDrop) PullFileWithParams(remoteName, localPath string, blockSize, nWorkers int) error
- func (kd *KeibiDrop) ReconnectionAttempts() int
- func (kd *KeibiDrop) ReconnectionState() string
- func (kd *KeibiDrop) Run()
- func (kd *KeibiDrop) SaveCurrentPeerAsContact(name string) error
- func (kd *KeibiDrop) SetPeerDirectAddress(addr string) error
- func (kd *KeibiDrop) Shutdown()
- func (kd *KeibiDrop) Start()
- func (kd *KeibiDrop) StartPresenceHeartbeat(ctx context.Context)
- func (kd *KeibiDrop) Stop()
- func (kd *KeibiDrop) StopConnectionResilience()
- func (kd *KeibiDrop) ToggleIncognito(incognito bool, configDir string) (string, error)
- func (kd *KeibiDrop) UnmountFilesystem() error
- func (kd *KeibiDrop) UpgradeListenerDualStack() error
- type PeerRegistration
- type RelayKeepalive
- func (rk *RelayKeepalive) CheckIPChange() error
- func (rk *RelayKeepalive) FailureCount() int
- func (rk *RelayKeepalive) ForceRefresh() error
- func (rk *RelayKeepalive) LastRefresh() time.Time
- func (rk *RelayKeepalive) Pause()
- func (rk *RelayKeepalive) Resume()
- func (rk *RelayKeepalive) Start()
- func (rk *RelayKeepalive) Stop()
- type TaskSignal
Constants ¶
const Timeout = 10*60 - 5
Variables ¶
var ( Version = "0.0.0" CommitHash = "dev" // default fallback )
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") )
Functions ¶
func GetGlobalIPv6 ¶
GetGlobalIPv6 returns a stable (non-temporary) global IPv6 address. On macOS/Linux, privacy extensions (RFC 4941) generate temporary addresses that rotate periodically. Connections bound to a temporary address break when the OS deprecates it. This function prefers stable addresses by collecting all candidates and picking the best one.
func GetJSONWithURL ¶
func GetLinkLocalAddress ¶
GetLinkLocalAddress finds a link-local IPv6 address on this machine and returns it formatted as "ip%zone:port" for direct LAN peer connections. Falls back to loopback (::1) when no link-local interface is available.
func GetLocalAddrs ¶
func GetLocalAddrs() []string
GetLocalAddrs returns all private/link-local IP addresses for LAN discovery. These are included in the relay registration so peers on the same network can connect directly without going through the bridge relay.
func GetLocalIPv6 ¶
func ParsePeerDirectAddress ¶
ParsePeerDirectAddress parses a direct LAN peer address in the format "ip%zone:port" (link-local) or "ip:port" (loopback). Returns the IP, zone identifier, port number, and any error.
func PostJSONWithURL ¶
func PrintBanner ¶
func PrintBanner()
func RegisterErrorMapper ¶
func SanitizeLogContent ¶
SanitizeLogContent sanitizes log text in memory.
func SanitizeLogs ¶
SanitizeLogs reads a log file and returns sanitized content. Redacts file names (keeps extensions), fingerprints, and IP addresses. Keeps timestamps, log levels, method names, error types, sizes, and connection events.
func SanitizeLogsToFile ¶
SanitizeLogsToFile reads a log, sanitizes it, and writes to destPath.
func ValidateFingerprint ¶
Types ¶
type ConnectionHint ¶
type ConnectionHint struct {
IP string `json:"ip"` // public IP address (either v4 or v6)
Port int `json:"port"` // where peer is listening
IPv6 bool `json:"ipv6"` // does this prefer IPv6?
Proto string `json:"proto"` // e.g., "tcp"
Note string `json:"note,omitempty"` // optional: NAT behavior, etc.
}
type EnableOpts ¶ added in v0.2.0
EnableOpts controls how persistent identity is loaded:
- PassphraseProtect: opt into Tier 2 (passphrase-derived key). Requires PassphraseProvider to be non-nil.
- PassphraseProvider: called once when PassphraseProtect=true to obtain the user's passphrase. Typical sources: TTY prompt (CLI), stdin (rustbridge / FFI), 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 (opaque blob). The relay cannot read the contents - only the peers with the shared room password can decrypt it.
type ErrorMapperFunc ¶
Map server status errors to semantic errors.
type ImplFileStreamProvider ¶
type ImplFileStreamProvider struct {
// contains filtered or unexported fields
}
func NewImplStreamProvider ¶
func NewImplStreamProvider(cli bindings.KeibiServiceClient) *ImplFileStreamProvider
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 using the server-streaming StreamFile RPC.
type ImplRemoteFileStream ¶
type ImplRemoteFileStream struct {
// contains filtered or unexported fields
}
func NewImplRemoteFileStream ¶
func NewImplRemoteFileStream(stream grpc.BidiStreamingClient[bindings.ReadRequest, bindings.ReadResponse], inode uint64, path string) *ImplRemoteFileStream
func (*ImplRemoteFileStream) Close ¶
func (rfs *ImplRemoteFileStream) Close() 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 // Disable data relay fallback (direct connections only)
ConnectionMode string // "lan", "direct", "bridge" - set after successful connection
OpInProgress atomic.Int32
PeerIPv6IP string
PeerLocalAddrs []string // LAN IPs from 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 virtual mount point and for save folder.
ToMount string
ToSave string
// Collab sync options.
PrefetchOnOpen bool
PushOnWrite bool
Cancel context.CancelFunc // exported so FFI layer can call it for app exit
// Event callback (wired by FFI layer to push events to the UI).
OnEvent func(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)
Factory-style constructor
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 identical to NewKeibiDrop but accepts an explicit IPv6 address instead of probing the network. This enables testing on machines without a global IPv6 address.
func (*KeibiDrop) AddFileAs ¶
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 (*KeibiDrop) CancelDownload ¶
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
CheckContactPresence returns true if the contact was seen online recently.
func (*KeibiDrop) Connect ¶
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
ConnectToContact looks up a contact by fingerprint, registers it, and connects.
func (*KeibiDrop) ConnectionStatus ¶
ConnectionStatus returns the current connection health status.
func (*KeibiDrop) CreateRoom ¶
func (*KeibiDrop) DowngradeListenerIPv6Only ¶
DowngradeListenerIPv6Only replaces the dual-stack listener with an IPv6-only listener. Used when leaving local mode.
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. Must be called before CreateRoom/JoinRoom. Loads or creates identity from configDir, rebuilds the session with stable keys, and loads the address book.
func (*KeibiDrop) EnablePersistentIdentityDefault ¶ added in v0.2.0
EnablePersistentIdentityDefault is a convenience wrapper that uses zero-value EnableOpts (keychain or file tier, no passphrase).
func (*KeibiDrop) ExportFingerprint ¶
func (*KeibiDrop) GetDownloadProgress ¶
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 (*KeibiDrop) InboundPort ¶
InboundPort returns the port this instance listens on for incoming connections.
func (*KeibiDrop) InitConnectionResilience ¶
InitConnectionResilience sets up health monitoring, reconnection, and relay keepalive. Call this after the session is connected and gRPC client is ready.
func (*KeibiDrop) IsPeerPersistent ¶ added in v0.2.0
IsPeerPersistent returns whether the currently connected peer has a stable identity.
func (*KeibiDrop) IsRunning ¶
IsRunning returns whether the KeibiDrop instance is in a connected session.
func (*KeibiDrop) MountFilesystem ¶
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) 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) ReconnectionAttempts ¶
ReconnectionAttempts returns the number of reconnection attempts.
func (*KeibiDrop) ReconnectionState ¶
ReconnectionState returns the current reconnection state.
func (*KeibiDrop) SaveCurrentPeerAsContact ¶ added in v0.2.0
SaveCurrentPeerAsContact saves the currently connected peer as a named contact.
func (*KeibiDrop) SetPeerDirectAddress ¶
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 this for app exit. For temporary disconnects (peer left), use Stop() instead. Safe to call multiple times from any goroutine.
func (*KeibiDrop) StartPresenceHeartbeat ¶ added in v0.2.0
StartPresenceHeartbeat sends periodic presence heartbeats for all contacts. Runs until ctx is cancelled. Should be called after EnablePersistentIdentity.
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.
func (*KeibiDrop) ToggleIncognito ¶ added in v0.2.0
ToggleIncognito switches between persistent and ephemeral identity. When enabling incognito: generates fresh ephemeral keys. When disabling: restores persistent identity keys. Returns the new fingerprint.
func (*KeibiDrop) UnmountFilesystem ¶
func (*KeibiDrop) UpgradeListenerDualStack ¶
UpgradeListenerDualStack replaces the IPv6-only listener with a dual-stack listener that accepts both IPv4 and IPv6. Used when entering local mode (LAN discovery needs IPv4 connectivity).
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 (default 8 min, relay TTL is 10 min)
// contains filtered or unexported fields
}
RelayKeepalive maintains relay registration by periodically refreshing before the TTL expires. This ensures 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 detects if the local IP has changed and refreshes if needed. Call this 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 immediately refreshes the relay registration. Call this 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 temporarily disables refresh (e.g., when disconnected).
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.