Early-stage software. Shurli is experimental and built with AI assistance. It will have bugs. Not recommended for production or safety-critical use. Read the disclaimer.

Go SDK

Package sdk provides the core P2P networking library for Shurli.

This package is the primary SDK surface for Go consumers. External code should depend on the interfaces defined here (PeerNetwork, Resolver, ServiceManager, Authorizer) rather than concrete types where possible.

import "github.com/shurlinet/shurli/pkg/sdk"

Architecture

The package is organized around these concepts:

  • Network: creates and manages a libp2p host with relay, NAT traversal, DHT discovery, and resource limits. Entry point: New().

  • Services: the plugin system. TCP proxy services (ExposeService) forward streams to local ports. Plugin services (RegisterHandler) process streams directly. All services are managed through ServiceRegistry.

  • Plugin Policies: transport-aware access control for plugins. By default, all plugins only operate over LAN and Direct connections. Relay transport is excluded unless explicitly allowed per-plugin. See PluginPolicy and DefaultPluginPolicy.

  • Events: the EventBus dispatches connection, service, and authorization events to registered handlers.

  • Naming: the NameResolver maps human-readable names to peer IDs, with support for fallback resolver chains.

  • Standalone: NewStandaloneHost and StandaloneResult.ResolveAndConnect provide a consolidated path for one-shot CLI commands that operate without a running daemon.

  • Bootstrap: BootstrapAndConnect handles DHT client-mode bootstrap, peer discovery, and relay circuit fallback.

  • Protocol IDs: ProtocolID and MustValidateProtocolIDs enforce valid protocol ID construction at init time.

Relay Separation

Relay server protocols (pairing, admin, MOTD, unseal) live in internal/relay and register directly on the libp2p host. They are architecturally separate from the plugin system in this package. Plugins are peer-to-peer only.

Thread Safety

All exported types are safe for concurrent use. The Network, ServiceRegistry, EventBus, NameResolver, and TransferService use internal locking.


QUIC Transport Performance

Shurli uses QUIC (RFC 9000) over UDP for all peer-to-peer data transport. QUIC performance varies across operating systems due to differences in kernel UDP handling, buffer defaults, and hardware offload support.

See QUIC-TRANSPORT.md for the full reference, including:

  • macOS UDP GSO limitation: macOS lacks Generic Segmentation Offload for UDP, causing ~17-27% lower LAN send throughput vs TCP. Measured, profiled, and documented with root cause analysis.
  • Linux UDP buffer tuning: default kernel limits are too small for high-throughput QUIC. Configuration guide included.
  • macOS Local Network Privacy: silent LAN connection blocking after binary replacement.
  • Elimination matrix: every hypothesis tested and the evidence for/against.

Constants

const DHTProtocolPrefix = "/shurli"
const ProtocolPrefix = "/shurli"
const PresenceProtocol = "/shurli/presence/1.0.0"
const RTTProbeProtocol = "/shurli/rtt-probe/1.0.0"

Transport Types

const (
    TransportLAN    TransportType = 1 << iota // private/link-local IP
    TransportDirect                            // public internet, non-relay
    TransportRelay                             // mediated through relay (p2p-circuit)
)

const DefaultTransport = TransportLAN | TransportDirect
const MaxHedgeFanOut = 3

DefaultTransport permits LAN and Direct connections. MaxHedgeFanOut caps the number of concurrent hedged stream attempts. Relay is excluded. This is the default for ALL plugins: no data flows through relays unless explicitly allowed per-plugin.

Event Types

const (
    EventPeerConnected    EventType = iota + 1
    EventPeerDisconnected
    EventServiceRegistered
    EventServiceRemoved
    EventStreamOpened
    EventStreamClosed
    EventAuthAllow
    EventAuthDeny
    EventTransferPending
)

NAT Types

type NATType string

const (
    NATNone              NATType = "none"
    NATFullCone          NATType = "full-cone"
    NATAddressRestricted NATType = "address-restricted"
    NATPortRestricted    NATType = "port-restricted"
    NATSymmetric         NATType = "symmetric"
    NATUnknown           NATType = "unknown"
)

Path Types

type PathType string

const (
    PathDirect  PathType = "DIRECT"
    PathRelayed PathType = "RELAYED"
)

Variables

var ErrServiceAlreadyRegistered = errors.New("service already registered")
var ErrServiceNotFound          = errors.New("service not found")
var ErrNameNotFound             = errors.New("name not found")
var ErrResponseTooLarge         = errors.New("response too large")

Core Interfaces

type PeerNetwork

type PeerNetwork interface {
    PeerID() peer.ID
    ExposeService(name, localAddress string, allowedPeers map[peer.ID]struct{}) error
    UnexposeService(name string) error
    ListServices() []*Service
    ConnectToService(peerID peer.ID, serviceName string) (ServiceConn, error)
    ConnectToServiceContext(ctx context.Context, peerID peer.ID, serviceName string) (ServiceConn, error)
    ResolveName(name string) (peer.ID, error)
    RegisterName(name string, peerID peer.ID) error
    OnEvent(handler EventHandler) func()
    Close() error
}

PeerNetwork is the top-level interface for interacting with a Shurli P2P network. Create a concrete *Network with sdk.New().

type Resolver

type Resolver interface {
    Resolve(name string) (peer.ID, error)
}

Resolver maps human-readable names to peer IDs. Supports chaining: local config, DNS, DHT, custom backends.

type ServiceManager

type ServiceManager interface {
    RegisterService(svc *Service) error
    UnregisterService(name string) error
    GetService(name string) (*Service, bool)
    ListServices() []*Service
    DialService(ctx context.Context, peerID peer.ID, protocolID string) (ServiceConn, error)
    Use(middleware ...StreamMiddleware)
}

ServiceManager manages service registration, discovery, and dialing. Supports stream middleware for cross-cutting concerns.

type Authorizer

type Authorizer interface {
    IsAuthorized(p peer.ID) bool
}

Authorizer makes authorization decisions about peers. Default implementation uses Shurli’s authorized_keys file.

type ServiceConn

type ServiceConn interface {
    io.ReadWriteCloser
    CloseWrite() error
}

ServiceConn is a connection to a remote service. Supports half-close for HTTP-style request/response patterns.

type RelayGrantChecker

type RelayGrantChecker interface {
    GrantStatus(relayID peer.ID) (remaining time.Duration, budget int64, sessionDuration time.Duration, ok bool)
    HasSufficientBudget(relayID peer.ID, fileSize int64, direction string) bool
    TrackCircuitBytes(relayID peer.ID, direction string, n int64)
    ResetCircuitCounters(relayID peer.ID)
}

RelayGrantChecker provides relay grant information for transfer budget/time checks. Used by the file transfer plugin to verify relay data grants before initiating transfers.

type RelaySource

type RelaySource interface {
    RelayAddrs() []string
}

RelaySource provides relay addresses for dial racing.

type HalfCloseConn

type HalfCloseConn interface {
    io.ReadWriteCloser
    CloseWrite() error
}

HalfCloseConn is a connection supporting half-close. Used by the proxy subsystem for bidirectional copy.


Type Aliases

type StreamMiddleware func(next network.StreamHandler) network.StreamHandler
type StreamHandler    func(serviceName string, s network.Stream)
type EventHandler     func(Event)
type EventType        int
type TransportType    int
type GrantChecker     func(peerID peer.ID, service string, transport TransportType) bool
type TokenVerifier    func(tokenBase64 string, peerID peer.ID, service string, transport TransportType) bool
type TokenLookup      func(peerID peer.ID, service string) string
type ConnectionRecorder func(peerID peer.ID)
type PeerFilter       func(peer.ID) bool
type NodeStateProvider func() *NodeAnnouncement

Network

type Config

type Config struct {
    KeyFile              string
    KeyPassword          string
    AuthorizedKeys       string
    Gater                *auth.AuthorizedPeerGater
    Config               *config.Config
    UserAgent            string
    EnableRelay          bool
    RelayAddrs           []string
    ForcePrivate         bool
    EnableNATPortMap     bool
    EnableHolePunching   bool
    Namespace            string
    Resolver             Resolver
    ResourceLimitsEnabled bool
    Metrics              *Metrics
    BandwidthTracker     *BandwidthTracker
}

Config holds configuration for creating a new P2P network.

type Network

type Network struct {
    // contains unexported fields
}

Network is the core P2P host. Implements PeerNetwork. Created with New().

func New

func New(cfg *Config) (*Network, error)

New creates a new P2P network instance with the given configuration.

func (*Network) PeerID

func (n *Network) PeerID() peer.ID

PeerID returns this node’s peer ID.

func (*Network) Host

func (n *Network) Host() host.Host

Host returns the underlying libp2p host.

func (*Network) ExposeService

func (n *Network) ExposeService(name, localAddress string, allowedPeers map[peer.ID]struct{}) error

ExposeService exposes a local TCP service over the P2P network.

func (*Network) UnexposeService

func (n *Network) UnexposeService(name string) error

UnexposeService removes a previously exposed service.

func (*Network) ListServices

func (n *Network) ListServices() []*Service

ListServices returns all registered services.

func (*Network) ConnectToService

func (n *Network) ConnectToService(peerID peer.ID, serviceName string) (ServiceConn, error)

ConnectToService connects to a remote peer’s exposed service.

func (*Network) ConnectToServiceContext

func (n *Network) ConnectToServiceContext(ctx context.Context, peerID peer.ID, serviceName string) (ServiceConn, error)

ConnectToServiceContext connects with a cancellable context.

func (*Network) ResolveName

func (n *Network) ResolveName(name string) (peer.ID, error)

ResolveName resolves a human-readable name to a peer ID.

func (*Network) RegisterName

func (n *Network) RegisterName(name string, peerID peer.ID) error

RegisterName registers a name-to-peer-ID mapping.

func (*Network) LoadNames

func (n *Network) LoadNames(names map[string]string) error

LoadNames loads peer name mappings from a string map.

func (*Network) OnEvent

func (n *Network) OnEvent(handler EventHandler) func()

OnEvent subscribes to network events. Returns an unsubscribe function.

func (*Network) AddRelayAddressesForPeer

func (n *Network) AddRelayAddressesForPeer(relayAddrs []string, target peer.ID) error

AddRelayAddressesForPeer adds relay circuit addresses for a target peer.

func (*Network) ResetBlackHoles

func (n *Network) ResetBlackHoles()

ResetBlackHoles resets the libp2p black hole detectors for both IPv4 and IPv6 UDP, allowing immediate retry after a network change.

func (*Network) ClearDialBackoffs

func (n *Network) ClearDialBackoffs(peers []peer.ID)

ClearDialBackoffs clears the swarm’s dial backoff for the given peers, enabling immediate reconnection.

func (*Network) GetPathProtector

func (n *Network) GetPathProtector() *PathProtector

GetPathProtector returns the path protector, if set.

func (*Network) SetPathProtector

func (n *Network) SetPathProtector(pp *PathProtector)

SetPathProtector sets the path protector for managed relay connections.

func (*Network) GetLANRegistry

func (n *Network) GetLANRegistry() *LANRegistry

GetLANRegistry returns the mDNS-verified LAN registry.

func (*Network) ServiceRegistry

func (n *Network) ServiceRegistry() *ServiceRegistry

ServiceRegistry returns the network’s service registry.

func (*Network) RegisterHandler

func (n *Network) RegisterHandler(name string, handler StreamHandler, allowedPeers map[peer.ID]struct{}) error

RegisterHandler registers a P2P stream handler for a named service. Uses default plugin policy (LAN + Direct, no relay).

func (*Network) RegisterHandlerRelayAllowed

func (n *Network) RegisterHandlerRelayAllowed(name string, handler StreamHandler, allowedPeers map[peer.ID]struct{}) error

RegisterHandlerRelayAllowed registers a handler that also accepts relay connections.

func (*Network) RegisterServiceQuery

func (n *Network) RegisterServiceQuery() error

RegisterServiceQuery registers the service-query protocol handler for remote service discovery.

func (*Network) OpenPluginStream

func (n *Network) OpenPluginStream(ctx context.Context, peerID peer.ID, serviceName string) (network.Stream, error)

OpenPluginStream opens a stream to a remote peer for a plugin service. Applies transport policy and grant verification.

func (*Network) OpenPluginStreamOnConn

func (n *Network) OpenPluginStreamOnConn(ctx context.Context, peerID peer.ID, serviceName string, conn network.Conn) (network.Stream, error)

OpenPluginStreamOnConn opens a plugin stream on a specific connection. Used by hedged open to target a particular path.

func (*Network) ReplaceNames

func (n *Network) ReplaceNames(names map[string]string) error

ReplaceNames replaces all name mappings atomically.

func (*Network) ListNames

func (n *Network) ListNames() map[string]peer.ID

ListNames returns all registered name-to-peer-ID mappings.

func (*Network) Events

func (n *Network) Events() *EventBus

Events returns the network’s event bus.

func (*Network) Close

func (n *Network) Close() error

Close shuts down the network and releases resources.

func ParseRelayAddrs

func ParseRelayAddrs(relayAddrs []string) ([]peer.AddrInfo, error)

ParseRelayAddrs parses multiaddr relay addresses into AddrInfo. Standalone function, not a Network method.

func DHTProtocolPrefixForNamespace

func DHTProtocolPrefixForNamespace(namespace string) string

DHTProtocolPrefixForNamespace returns DHT protocol prefix for a private namespace.

func HumanizeError

func HumanizeError(err string) string

HumanizeError translates libp2p stream errors into user-friendly messages.

func ValidateServiceName

func ValidateServiceName(name string) error

ValidateServiceName checks that a service name is safe for use in protocol IDs.


Service Registry

type Service

type Service struct {
    Name         string
    Protocol     string
    LocalAddress string
    Handler      StreamHandler
    Enabled      bool
    AllowedPeers map[peer.ID]struct{}
    Policy       *PluginPolicy
}

Service represents a service exposed over P2P.

type ServiceRegistry

type ServiceRegistry struct {
    // contains unexported fields
}

ServiceRegistry manages service registration, stream routing, and connection dialing.

func NewServiceRegistry

func NewServiceRegistry(h host.Host, metrics *Metrics) *ServiceRegistry

func (*ServiceRegistry) RegisterService

func (r *ServiceRegistry) RegisterService(svc *Service) error

func (*ServiceRegistry) UnregisterService

func (r *ServiceRegistry) UnregisterService(name string) error

func (*ServiceRegistry) GetService

func (r *ServiceRegistry) GetService(name string) (*Service, bool)

func (*ServiceRegistry) ListServices

func (r *ServiceRegistry) ListServices() []*Service

func (*ServiceRegistry) DialService

func (r *ServiceRegistry) DialService(ctx context.Context, peerID peer.ID, protocolID string) (ServiceConn, error)

func (*ServiceRegistry) Seal

func (r *ServiceRegistry) Seal()

Seal prevents further service registration. Called after daemon startup.

func (*ServiceRegistry) SetGrantChecker

func (r *ServiceRegistry) SetGrantChecker(checker GrantChecker)

func (*ServiceRegistry) SetTokenVerifier

func (r *ServiceRegistry) SetTokenVerifier(v TokenVerifier)

func (*ServiceRegistry) SetTokenLookup

func (r *ServiceRegistry) SetTokenLookup(l TokenLookup)

func (*ServiceRegistry) SetLANRegistry

func (r *ServiceRegistry) SetLANRegistry(lanReg *LANRegistry)

SetLANRegistry sets the LAN registry for mDNS-verified transport classification in stream handlers.

func (*ServiceRegistry) SetRelayGrantChecker

func (r *ServiceRegistry) SetRelayGrantChecker(checker RelayGrantChecker)

SetRelayGrantChecker sets the relay grant checker for verifying data access grants on relay streams.

func (*ServiceRegistry) Use

func (r *ServiceRegistry) Use(middleware ...StreamMiddleware)

Use adds stream middleware. Middleware wraps every stream handler in the order added (first added = outermost wrapper).


Events

type Event

type Event struct {
    Type        EventType
    PeerID      peer.ID
    ServiceName string
    Detail      string
}

type EventBus

type EventBus struct {
    // contains unexported fields
}

func NewEventBus

func NewEventBus() *EventBus

func (*EventBus) Subscribe

func (b *EventBus) Subscribe(handler EventHandler) func()

Subscribe registers an event handler. Returns an unsubscribe function.

func (*EventBus) Emit

func (b *EventBus) Emit(e Event)

Emit dispatches event to all registered handlers.


Name Resolution

type NameResolver

type NameResolver struct {
    // contains unexported fields
}

func NewNameResolver

func NewNameResolver() *NameResolver

func (*NameResolver) Register

func (r *NameResolver) Register(name string, peerID peer.ID) error

func (*NameResolver) Unregister

func (r *NameResolver) Unregister(name string)

func (*NameResolver) Resolve

func (r *NameResolver) Resolve(name string) (peer.ID, error)

func (*NameResolver) List

func (r *NameResolver) List() map[string]peer.ID

func (*NameResolver) LoadFromMap

func (r *NameResolver) LoadFromMap(names map[string]string) error

LoadFromMap adds name mappings from string map (additive).

func (*NameResolver) ReplaceFromMap

func (r *NameResolver) ReplaceFromMap(names map[string]string) error

ReplaceFromMap replaces all name mappings with the given map.


Byte Size Utilities

func ParseByteSize

func ParseByteSize(s string) (int64, error)

ParseByteSize parses a human-readable byte size string (e.g., “500MB”, “1GB”, “unlimited”).

func FormatBytes

func FormatBytes(b int64) string

FormatBytes formats a byte count for user-facing display (e.g. “1.2 GB”, “500 MB”).


Cryptographic Utilities

func Blake3Sum

func Blake3Sum(data []byte) [32]byte

Blake3Sum computes the BLAKE3-256 hash of data.

func MerkleRoot

func MerkleRoot(hashes [][32]byte) [32]byte

MerkleRoot computes the BLAKE3 Merkle root hash from a list of chunk hashes. Leaf nodes are chunk hashes (already BLAKE3). Internal nodes are BLAKE3(left || right). Odd nodes are promoted unchanged. Single hash is returned as-is. Empty list returns zero hash.


Relay Utilities

func RelayPeerFromAddr

func RelayPeerFromAddr(addr ma.Multiaddr) peer.ID

RelayPeerFromAddr extracts the relay peer ID from a circuit relay multiaddr. Returns empty peer.ID if the address is not a circuit relay address.

func RelayPeerFromAddrStr

func RelayPeerFromAddrStr(addrStr string) string

RelayPeerFromAddrStr extracts the relay peer ID string from a circuit relay multiaddr string. Returns empty string if the address is not a relay circuit.

func VerifiedTransport

func VerifiedTransport(s network.Stream, hasVerifiedLANConn func(peer.ID) bool) TransportType

VerifiedTransport classifies a stream using mDNS-verified LAN detection. Use for any trust-making decision (transport policy, erasure coding, bandwidth budgets).

Precedence: Limited (relay circuit) → TransportRelay; loopback or link-local remote → TransportLAN (cannot traverse routers); hasVerifiedLANConn returns true → TransportLAN; otherwise → TransportDirect.

Unlike ClassifyTransport, routable private IPv4 addresses (RFC 1918 / RFC 6598) are NOT classified as LAN unless mDNS has verified the peer. This avoids false positives from CGNAT, Docker bridge networks, VPN tunnels, and multi-WAN routed-private cross-links - only mDNS multicast (which cannot traverse routers) proves real LAN proximity.

A nil hasVerifiedLANConn callback still classifies loopback and link-local as LAN; for routable addresses it falls back to TransportDirect (conservative).

func (*Network) HasVerifiedLANConn

func (n *Network) HasVerifiedLANConn(id peer.ID) bool

Nil-safe convenience wrapper over the underlying mDNS-verified LAN registry. Returns true if the peer has at least one live non-relay connection whose remote IP was confirmed via mDNS multicast. This is the authoritative “is this peer on our LAN?” check; use it as the second argument to VerifiedTransport.


Connection Groups & Hedging

type ConnGroup

type ConnGroup struct {
    Type  string         // "DIRECT", "RELAYED", or relay peer ID
    Conns []network.Conn
}

ConnGroup groups a peer’s connections by transport path. Direct connections (LAN or WAN) are in one group, each relay circuit is its own group.

type HostNetwork

type HostNetwork interface {
    Network() network.Network
}

HostNetwork is satisfied by host.Host. Used by ConnGroups/AllConnGroups to access connection lists.

func ConnGroups

func ConnGroups(h HostNetwork, peerID peer.ID) []ConnGroup

ConnGroups groups all connections to a peer by transport type. Direct (non-relay) connections are grouped together; each relay circuit forms a separate group.

func AllConnGroups

func AllConnGroups(h HostNetwork, peerID peer.ID, pp *PathProtector) []ConnGroup

AllConnGroups returns connection groups including managed relay connections from the PathProtector that may not appear in the host’s connection list.

func OpenStreamOnConn

func OpenStreamOnConn(ctx context.Context, conn network.Conn, proto protocol.ID) (network.Stream, error)

OpenStreamOnConn opens a new stream on a specific connection using protocol negotiation. Used to target a particular network path (e.g., direct vs relay).

func HedgedOpenStream

func HedgedOpenStream(ctx context.Context, n *Network, peerID peer.ID, serviceName string) (network.Stream, error)

HedgedOpenStream opens a plugin stream using hedged racing across all available connection groups. Direct groups are tried first, then relay groups with staggered starts. First success wins, losers are cancelled. Capped at MaxHedgeFanOut concurrent attempts.


Path Protection

type PathProtector

type PathProtector struct {
    // contains unexported fields
}

PathProtector manages protected relay connections for peers. Prevents relay circuits from being garbage-collected by keeping them alive and tracked. Supports connection reaping and deauth callbacks.

const MaxProtectedPeers = 10
const MaxManagedRelayConns = 5

type ManagedPathInfo

type ManagedPathInfo struct {
    PeerID      peer.ID
    RelayPeerID peer.ID
    RemoteAddr  string
    Created     time.Time
    Streams     int
    Dead        bool
}

ManagedPathInfo describes a managed relay connection tracked by PathProtector.


LAN Registry

type LANRegistry

type LANRegistry struct {
    // contains unexported fields
}

LANRegistry tracks which peers have been verified as LAN-local via mDNS multicast. The authoritative source for “is this peer on our LAN?” decisions. Bare RFC 1918 matching is unreliable (CGNAT, Docker, VPN); only mDNS proves link-local proximity.

func StripNonLANAddrs

func StripNonLANAddrs(h host.Host, pid peer.ID, lanReg *LANRegistry)

StripNonLANAddrs removes non-LAN addresses from the peerstore for a peer that has a verified LAN connection, preventing mDNS-discovered peers from accumulating stale public addresses.

func IsLANMultiaddr

func IsLANMultiaddr(addr ma.Multiaddr) bool

IsLANMultiaddr returns true if the multiaddr points to a LAN address (private IPv4, link-local IPv6, loopback).


Grant Headers

func WriteGrantHeader

func WriteGrantHeader(s network.Stream, tokenBase64 string) error

WriteGrantHeader writes a grant token header onto a stream before the application payload. Used by relay-allowed protocols to present data access credentials.

func ReadGrantHeader

func ReadGrantHeader(s network.Stream) (string, error)

ReadGrantHeader reads a grant token header from a stream. Returns the base64-encoded token string.


Plugin Transport Policy

type PluginPolicy

type PluginPolicy struct {
    AllowedTransports TransportType
    AllowPeers        map[peer.ID]struct{}
    DenyPeers         map[peer.ID]struct{}
}

PluginPolicy defines transport restrictions and peer access control for plugin protocols.

func DefaultPluginPolicy

func DefaultPluginPolicy() *PluginPolicy

DefaultPluginPolicy returns a policy allowing LAN + Direct, no relay.

func (*PluginPolicy) RelayAllowed

func (p *PluginPolicy) RelayAllowed() bool

func (*PluginPolicy) PeerAllowed

func (p *PluginPolicy) PeerAllowed(id peer.ID) bool

func (*PluginPolicy) TransportAllowed

func (p *PluginPolicy) TransportAllowed(t TransportType) bool

func ClassifyTransport

func ClassifyTransport(s network.Stream) TransportType

ClassifyTransport determines the transport type of a stream. Limited connections are classified as TransportRelay. Private/loopback/link-local IPs are TransportLAN. Everything else is TransportDirect.


Protocol IDs

func ProtocolID

func ProtocolID(name, version string) string

ProtocolID constructs a validated Shurli protocol identifier: /shurli/<name>/<version>. Panics on invalid input (intended for init-time registration).

func ValidateProtocolID

func ValidateProtocolID(id string) error

ValidateProtocolID checks if a protocol ID is well-formed.

func MustValidateProtocolIDs

func MustValidateProtocolIDs(ids ...string)

MustValidateProtocolIDs validates a batch of protocol IDs at init time. Panics if any are malformed.


Bootstrap

type BootstrapConfig

type BootstrapConfig struct {
    Namespace      string
    BootstrapPeers []string
    RelayAddrs     []string
}

func BootstrapAndConnect

func BootstrapAndConnect(ctx context.Context, h host.Host, net *Network, target peer.ID, cfg BootstrapConfig) error

BootstrapAndConnect bootstraps the DHT and connects to a target peer.


Standalone Host

type StandaloneConfig

type StandaloneConfig struct {
    ConfigPath string
    Password   string
    UserAgent  string
}

type StandaloneResult

type StandaloneResult struct {
    Network    *Network
    NodeConfig *config.NodeConfig
    ConfigDir  string
}

func (*StandaloneResult) ResolveAndConnect

func (r *StandaloneResult) ResolveAndConnect(ctx context.Context, target string) (peer.ID, error)

ResolveAndConnect resolves a peer name or ID and connects.

func NewStandaloneHost

func NewStandaloneHost(cfg StandaloneConfig) (*StandaloneResult, error)

NewStandaloneHost creates a P2P Network from a config file. Used by CLI commands that need a network connection without running the full daemon.


Network Tools

Ping

type PingResult

type PingResult struct {
    Seq    int     `json:"seq"`
    PeerID string  `json:"peer_id"`
    RttMs  float64 `json:"rtt_ms"`
    Path   string  `json:"path"`
    Error  string  `json:"error,omitempty"`
}

type PingStats

type PingStats struct {
    Sent     int     `json:"sent"`
    Received int     `json:"received"`
    Lost     int     `json:"lost"`
    LossPct  float64 `json:"loss_pct"`
    MinMs    float64 `json:"min_ms"`
    AvgMs    float64 `json:"avg_ms"`
    MaxMs    float64 `json:"max_ms"`
}

func PingPeer

func PingPeer(ctx context.Context, h host.Host, peerID peer.ID, protocolID string, count int, interval time.Duration) <-chan PingResult

PingPeer sends pings to a peer and streams results on the returned channel.

func ComputePingStats

func ComputePingStats(results []PingResult) PingStats

Traceroute

type TraceHop

type TraceHop struct {
    Hop     int     `json:"hop"`
    PeerID  string  `json:"peer_id"`
    Name    string  `json:"name,omitempty"`
    Address string  `json:"address"`
    RttMs   float64 `json:"rtt_ms"`
    Error   string  `json:"error,omitempty"`
}

type TraceResult

type TraceResult struct {
    Target   string     `json:"target"`
    TargetID string     `json:"target_id"`
    Path     string     `json:"path"`
    Hops     []TraceHop `json:"hops"`
}

func TracePeer

func TracePeer(ctx context.Context, h host.Host, targetPeerID peer.ID) (*TraceResult, error)

TracePeer traces the network path to a peer.


Peer Management

type PeerManager

type PeerManager struct {
    // contains unexported fields
}

PeerManager maintains connections to watched peers with exponential backoff reconnection.

func NewPeerManager

func NewPeerManager(h host.Host, pd *PathDialer, m *Metrics, onReconnect ConnectionRecorder) *PeerManager

func (*PeerManager) Start

func (pm *PeerManager) Start(ctx context.Context)

func (*PeerManager) Close

func (pm *PeerManager) Close()

func (*PeerManager) SetWatchlist

func (pm *PeerManager) SetWatchlist(peerIDs []peer.ID)

func (*PeerManager) OnNetworkChange

func (pm *PeerManager) OnNetworkChange()

OnNetworkChange triggers immediate reconnection attempts.

func (*PeerManager) SetPathProtector

func (pm *PeerManager) SetPathProtector(pp *PathProtector)

SetPathProtector sets the path protector for managed relay connections.

func (*PeerManager) GetLANRegistry

func (pm *PeerManager) GetLANRegistry() *LANRegistry

GetLANRegistry returns the PeerManager’s LAN registry.

func (*PeerManager) ResetPeerBackoff

func (pm *PeerManager) ResetPeerBackoff(pid peer.ID)

ResetPeerBackoff clears the reconnection backoff for a specific peer, enabling immediate reconnection.

func (*PeerManager) CloseAllPeerConnections

func (pm *PeerManager) CloseAllPeerConnections()

CloseAllPeerConnections closes all connections to all watched peers. Used on network change to force path re-evaluation.

func (*PeerManager) GetManagedPeers

func (pm *PeerManager) GetManagedPeers() []ManagedPeerInfo

GetManagedPeers returns a snapshot of all watched peers and their state.

type ManagedPeerInfo

type ManagedPeerInfo struct {
    PeerID         string `json:"peer_id"`
    Connected      bool   `json:"connected"`
    LastSeen       string `json:"last_seen"`
    LastDialError  string `json:"last_dial_error,omitempty"`
    ConsecFailures int    `json:"consec_failures"`
    BackoffUntil   string `json:"backoff_until,omitempty"`
}

Path Dialer

type PathDialer

type PathDialer struct {
    // contains unexported fields
}

PathDialer connects to peers using parallel path racing across direct and relay paths.

func NewPathDialer

func NewPathDialer(h host.Host, kdht *dht.IpfsDHT, relaySource RelaySource, m *Metrics) *PathDialer

func (*PathDialer) DialPeer

func (pd *PathDialer) DialPeer(ctx context.Context, peerID peer.ID) (*DialResult, error)

type DialResult

type DialResult struct {
    PathType PathType
    Duration time.Duration
    Address  string
}

func PeerConnInfo

func PeerConnInfo(h host.Host, peerID peer.ID) (pathType string, addr string)

func ClassifyMultiaddr

func ClassifyMultiaddr(addr string) (pathType PathType, transport string, ipVersion string)

func AddRelayAddressesForPeerFunc

func AddRelayAddressesForPeerFunc(h host.Host, relayAddrs []string, target peer.ID) error

func RelayServiceCID

func RelayServiceCID(namespace string) cid.Cid

RelayServiceCID returns the DHT content ID used for relay service advertisement in a given namespace.


Path Tracker

type PathTracker

type PathTracker struct {
    // contains unexported fields
}

PathTracker monitors peer connections and tracks per-peer path quality.

func NewPathTracker

func NewPathTracker(h host.Host, m *Metrics) *PathTracker

func (*PathTracker) Start

func (pt *PathTracker) Start(ctx context.Context)

func (*PathTracker) UpdateRTT

func (pt *PathTracker) UpdateRTT(pid peer.ID, rttMs float64)

func (*PathTracker) GetPeerPath

func (pt *PathTracker) GetPeerPath(pid peer.ID) (*PeerPathInfo, bool)

func (*PathTracker) ListPeerPaths

func (pt *PathTracker) ListPeerPaths() []*PeerPathInfo

type PeerPathInfo

type PeerPathInfo struct {
    PeerID      string   `json:"peer_id"`
    PathType    PathType `json:"path_type"`
    Address     string   `json:"address"`
    ConnectedAt string   `json:"connected_at"`
    Transport   string   `json:"transport"`
    IPVersion   string   `json:"ip_version"`
    LastRTTMs   float64  `json:"last_rtt_ms"`
}

LAN Discovery

type MDNSDiscovery

type MDNSDiscovery struct {
    // contains unexported fields
}

MDNSDiscovery discovers peers on the local network via mDNS/Zeroconf.


Network Intelligence

type NetIntel

type NetIntel struct {
    // contains unexported fields
}

NetIntel manages the presence announcement protocol. Peers exchange presence info (NAT type, addresses, capabilities, uptime) at regular intervals.

func NewNetIntel

func NewNetIntel(h host.Host, m *Metrics, pf PeerFilter, sp NodeStateProvider, interval time.Duration) *NetIntel

func (*NetIntel) Start

func (ni *NetIntel) Start(ctx context.Context)

func (*NetIntel) Close

func (ni *NetIntel) Close()

func (*NetIntel) AnnounceNow

func (ni *NetIntel) AnnounceNow()

AnnounceNow triggers an immediate presence announcement to all connected peers.

func (*NetIntel) GetPeerState

func (ni *NetIntel) GetPeerState(pid peer.ID) *PeerAnnouncement

func (*NetIntel) GetAllPeerState

func (ni *NetIntel) GetAllPeerState() []PeerAnnouncement

type NodeAnnouncement

type NodeAnnouncement struct {
    Version       int    `json:"version"`
    From          string `json:"from"`
    Grade         string `json:"grade"`
    NATType       string `json:"nat_type"`
    HasIPv4       bool   `json:"has_ipv4"`
    HasIPv6       bool   `json:"has_ipv6"`
    BehindCGNAT   bool   `json:"behind_cgnat"`
    UptimeSec     int64  `json:"uptime_sec"`
    PeerCount     int    `json:"peer_count"`
    Timestamp     int64  `json:"timestamp"`
    Hops          int    `json:"hops"`
    AnonymousMode bool   `json:"anonymous_mode"`
    ZKPProof      []byte `json:"zkp_proof,omitempty"`
}

type PeerAnnouncement

type PeerAnnouncement struct {
    PeerID       peer.ID
    Announcement NodeAnnouncement
    ReceivedAt   time.Time
}

Network Monitor

type NetworkMonitor

type NetworkMonitor struct {
    // contains unexported fields
}

NetworkMonitor watches for OS-level network interface changes (WiFi switches, cable plug/unplug, VPN up/down).

func NewNetworkMonitor

func NewNetworkMonitor(onChange func(*NetworkChange), m *Metrics) *NetworkMonitor

func (*NetworkMonitor) Run

func (nm *NetworkMonitor) Run(ctx context.Context)

type NetworkChange

type NetworkChange struct {
    Added          []string
    Removed        []string
    IPv6Changed    bool
    IPv4Changed    bool
    TunnelChanged  bool
    GatewayChanged bool
}

Interface Discovery

type InterfaceSummary

type InterfaceSummary struct {
    Interfaces       []InterfaceInfo
    HasGlobalIPv6    bool
    HasGlobalIPv4    bool
    GlobalIPv6Addrs  []string
    GlobalIPv4Addrs  []string
    TunnelInterfaces []string
    DefaultGateway   string
}

type InterfaceInfo

type InterfaceInfo struct {
    Name       string
    IPv4Addrs  []string
    IPv6Addrs  []string
    IsLoopback bool
}

func DiscoverInterfaces

func DiscoverInterfaces() (*InterfaceSummary, error)

DiscoverInterfaces enumerates all network interfaces with their addresses, detecting IPv4/IPv6 global addresses, tunnels, and the default gateway.


STUN Prober

type STUNProber

type STUNProber struct {
    // contains unexported fields
}

STUNProber discovers external addresses via STUN servers and classifies NAT type.

func NewSTUNProber

func NewSTUNProber(servers []string, m *Metrics) *STUNProber

func (*STUNProber) Probe

func (sp *STUNProber) Probe(ctx context.Context) (*STUNResult, error)

func (*STUNProber) Result

func (sp *STUNProber) Result() *STUNResult

Result returns the most recent probe result.

type STUNResult

type STUNResult struct {
    Probes        []ProbeResult
    NATType       NATType
    ExternalAddrs []string
    ProbedAt      time.Time
    BehindCGNAT   bool
    CGNATNote     string
}

type ProbeResult

type ProbeResult struct {
    ServerAddr   string
    ExternalAddr string
    ExternalIP   string
    ExternalPort int
    Latency      time.Duration
    Error        string
}

func (NATType) HolePunchable

func (n NATType) HolePunchable() bool

HolePunchable returns true if the NAT type supports hole punching (full-cone, address-restricted, or port-restricted).


Relay Discovery

type RelayDiscovery

type RelayDiscovery struct {
    // contains unexported fields
}

RelayDiscovery manages static + DHT relay discovery with health-ranked ordering.

func NewRelayDiscovery

func NewRelayDiscovery(staticRelays []peer.AddrInfo, namespace string, m *Metrics) *RelayDiscovery

func (*RelayDiscovery) SetBudgetChecker

func (rd *RelayDiscovery) SetBudgetChecker(gc RelayGrantChecker)

SetBudgetChecker sets the grant checker for budget-aware relay ranking. Relay addresses are ranked by health score + budget bonus.

type StaticRelaySource

type StaticRelaySource struct {
    Addrs []string
}

StaticRelaySource wraps a fixed relay address list.

func (*StaticRelaySource) RelayAddrs

func (s *StaticRelaySource) RelayAddrs() []string

Relay Health

type RelayHealth

type RelayHealth struct {
    // contains unexported fields
}

RelayHealth tracks relay liveness and quality using EWMA-based health scoring.

func NewRelayHealth

func NewRelayHealth(h host.Host, m *Metrics) *RelayHealth

Peer Relay

type PeerRelay

type PeerRelay struct {
    // contains unexported fields
}

PeerRelay auto-enables relay functionality when a node has a public IP.

func NewPeerRelay

func NewPeerRelay(h host.Host, m *Metrics, cfg PeerRelayConfig) *PeerRelay

Proxy

type TCPListener

type TCPListener struct {
    // contains unexported fields
}

TCPListener is a TCP listener that forwards connections to a P2P service.

func NewTCPListener

func NewTCPListener(localAddr string, dialFunc func() (ServiceConn, error)) (*TCPListener, error)

func (*TCPListener) Serve

func (l *TCPListener) Serve() error

func (*TCPListener) Close

func (l *TCPListener) Close() error

func (*TCPListener) Addr

func (l *TCPListener) Addr() net.Addr

func (*TCPListener) ActiveConns

func (l *TCPListener) ActiveConns() int

ActiveConns returns the number of active proxied connections.

func (*TCPListener) GracefulClose

func (l *TCPListener) GracefulClose(timeout time.Duration)

GracefulClose stops accepting new connections, waits for active connections to drain (up to timeout), then closes.

func BidirectionalProxy

func BidirectionalProxy(a, b HalfCloseConn, logPrefix string)

BidirectionalProxy copies data between two connections with half-close propagation.

func InstrumentedBidirectionalProxy

func InstrumentedBidirectionalProxy(a, b HalfCloseConn, service string, metrics *Metrics)

func ProxyStreamToTCP

func ProxyStreamToTCP(stream network.Stream, tcpAddr string) error

ProxyStreamToTCP proxies a libp2p stream to a local TCP address.

func DialWithRetry

func DialWithRetry(dialFunc func() (ServiceConn, error), maxRetries int) func() (ServiceConn, error)

DialWithRetry wraps a dial function with exponential backoff retry.


Metrics

type Metrics

type Metrics struct {
    Registry                       *prometheus.Registry
    ProxyBytesTotal                *prometheus.CounterVec
    ProxyConnectionsTotal          *prometheus.CounterVec
    ProxyActiveConns               *prometheus.GaugeVec
    ProxyDurationSeconds           *prometheus.HistogramVec
    AuthDecisionsTotal             *prometheus.CounterVec
    HolePunchTotal                 *prometheus.CounterVec
    HolePunchDurationSeconds       *prometheus.HistogramVec
    DaemonRequestsTotal            *prometheus.CounterVec
    DaemonRequestDurationSeconds   *prometheus.HistogramVec
    PathDialTotal                  *prometheus.CounterVec
    PathDialDurationSeconds        *prometheus.HistogramVec
    ConnectedPeers                 *prometheus.GaugeVec
    NetworkChangeTotal             *prometheus.CounterVec
    STUNProbeTotal                 *prometheus.CounterVec
    MDNSDiscoveredTotal            *prometheus.CounterVec
    PeerManagerReconnectTotal      *prometheus.CounterVec
    NetIntelSentTotal              *prometheus.CounterVec
    NetIntelReceivedTotal          *prometheus.CounterVec
    InterfaceCount                 *prometheus.GaugeVec
    VaultSealed                    prometheus.Gauge
    VaultSealOpsTotal              *prometheus.CounterVec
    VaultUnsealTotal               *prometheus.CounterVec
    VaultUnsealLockedPeers         prometheus.Gauge
    DepositOpsTotal                *prometheus.CounterVec
    DepositPending                 prometheus.Gauge
    PairingTotal                   *prometheus.CounterVec
    MacaroonVerifyTotal            *prometheus.CounterVec
    AdminRequestTotal              *prometheus.CounterVec
    AdminRequestDurationSeconds    *prometheus.HistogramVec
    ZKPProveTotal                  *prometheus.CounterVec
    ZKPProveDurationSeconds        *prometheus.HistogramVec
    ZKPVerifyTotal                 *prometheus.CounterVec
    ZKPVerifyDurationSeconds       *prometheus.HistogramVec
    ZKPAuthTotal                   *prometheus.CounterVec
    ZKPTreeRebuildTotal            *prometheus.CounterVec
    ZKPTreeRebuildDurationSeconds  *prometheus.HistogramVec
    ZKPTreeLeaves                  prometheus.Gauge
    ZKPChallengesPending           prometheus.Gauge
    ZKPRangeProveTotal             *prometheus.CounterVec
    ZKPRangeProveDuration          *prometheus.HistogramVec
    ZKPRangeVerifyTotal            *prometheus.CounterVec
    ZKPRangeVerifyDuration         *prometheus.HistogramVec
    ZKPAnonAnnouncementsTotal      *prometheus.CounterVec
    PeerBandwidthBytesTotal        *prometheus.GaugeVec
    PeerBandwidthRate              *prometheus.GaugeVec
    ProtocolBandwidthBytesTotal    *prometheus.GaugeVec
    BandwidthBytesTotal            *prometheus.GaugeVec
    RelayHealthScore               *prometheus.GaugeVec
    RelayProbeTotal                *prometheus.CounterVec
    BuildInfo                      *prometheus.GaugeVec
}

Metrics holds all custom Shurli Prometheus metrics (50+ counters, gauges, histograms).

func NewMetrics

func NewMetrics(version, goVersion string) *Metrics

Audit Logger

type AuditLogger

type AuditLogger struct {
    // contains unexported fields
}

AuditLogger writes structured audit events for security-relevant actions. Nil-safe: all methods are no-ops on a nil receiver.

func NewAuditLogger

func NewAuditLogger(handler slog.Handler) *AuditLogger

func (*AuditLogger) AuthDecision

func (a *AuditLogger) AuthDecision(peerID, direction, result string)

func (*AuditLogger) ServiceACLDenied

func (a *AuditLogger) ServiceACLDenied(peerID, service string)

func (*AuditLogger) DaemonAPIAccess

func (a *AuditLogger) DaemonAPIAccess(method, path string, status int)

func (*AuditLogger) AuthChange

func (a *AuditLogger) AuthChange(action, peerID string)

Bandwidth Tracker

type BandwidthTracker

type BandwidthTracker struct {
    // contains unexported fields
}

BandwidthTracker wraps libp2p’s BandwidthCounter and bridges to Prometheus metrics.

func NewBandwidthTracker

func NewBandwidthTracker(prom *Metrics) *BandwidthTracker

func (*BandwidthTracker) Counter

func (bt *BandwidthTracker) Counter() *metrics.BandwidthCounter

Counter returns the underlying libp2p bandwidth counter for host construction.

func (*BandwidthTracker) PeerStats

func (bt *BandwidthTracker) PeerStats(p peer.ID) metrics.Stats

func (*BandwidthTracker) AllPeerStats

func (bt *BandwidthTracker) AllPeerStats() map[peer.ID]metrics.Stats

func (*BandwidthTracker) ProtocolStats

func (bt *BandwidthTracker) ProtocolStats(proto protocol.ID) metrics.Stats

func (*BandwidthTracker) Totals

func (bt *BandwidthTracker) Totals() metrics.Stats

func (*BandwidthTracker) PublishMetrics

func (bt *BandwidthTracker) PublishMetrics()

func (*BandwidthTracker) Start

func (bt *BandwidthTracker) Start(ctx context.Context, interval time.Duration)

Start begins periodic metric publishing.


Identity Utilities

func LoadOrCreateIdentity

func LoadOrCreateIdentity(path, password string) (crypto.PrivKey, error)

LoadOrCreateIdentity loads an Ed25519 private key from the given path, or creates one if it does not exist.

func PeerIDFromKeyFile

func PeerIDFromKeyFile(path, password string) (peer.ID, error)

PeerIDFromKeyFile reads a key file and returns the corresponding peer ID without loading the full network.


DNS Seeds

func ResolveDNSSeeds

func ResolveDNSSeeds(ctx context.Context, domain string) []peer.AddrInfo

ResolveDNSSeeds resolves DNS TXT records for peer bootstrap addresses.


STUN Utilities

func BuildSTUNBindingRequest

func BuildSTUNBindingRequest(txID [12]byte) []byte

BuildSTUNBindingRequest constructs a raw STUN Binding Request packet.

func BuildSTUNBindingResponse

func BuildSTUNBindingResponse(txID [12]byte, ip net.IP, port int) []byte

BuildSTUNBindingResponse constructs a raw STUN Binding Response packet with an XOR-MAPPED-ADDRESS attribute.


Verification Utilities

func ComputeFingerprint

func ComputeFingerprint(a, b peer.ID) (emoji string, numeric string)

ComputeFingerprint computes an OMEMO-style SAS fingerprint (4 emojis + 8 digits) from two peer IDs. Order-independent.

func FingerprintPrefix

func FingerprintPrefix(a, b peer.ID) string

FingerprintPrefix returns the short emoji fingerprint prefix for display in peer status.


Reachability

func ComputeReachabilityGrade

func ComputeReachabilityGrade(ifaces *InterfaceSummary, stun *STUNResult) ReachabilityGrade

ComputeReachabilityGrade computes a reachability grade (A-F) from interface discovery and STUN results. Grade A = globally reachable, Grade F = no connectivity.


Service Query

func HandleServiceQuery

func HandleServiceQuery(registry *ServiceRegistry) StreamHandler

HandleServiceQuery returns a stream handler for remote service discovery. Peers can query which services a node provides.


Errors

type RemoteError

type RemoteError struct {
    Message string
}

RemoteError wraps an error message received from a remote peer.

func (*RemoteError) Error

func (e *RemoteError) Error() string

Go Documentation

Full API reference with doc comments is available locally via pkgsite:

go install golang.org/x/pkgsite/cmd/pkgsite@latest
cd /path/to/shurli
pkgsite -open .

Then navigate to pkg/sdk and pkg/plugin for browsable documentation with full source links.