embedded

package
v0.0.0-...-575c348 Latest Latest
Warning

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

Go to latest
Published: Feb 1, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package embedded provides an embeddable i2plan VPN API for third-party applications.

Package embedded provides an embeddable i2plan VPN API for third-party applications.

This package wraps the core i2plan mesh VPN functionality in a simple, developer-friendly API suitable for embedding in desktop applications, mobile apps, daemons, or any Go program that needs VPN capabilities.

Quick Start

Basic usage requires just a few lines of code:

vpn, err := embedded.New(embedded.Config{
    NodeName: "my-app-vpn",
    DataDir:  "/path/to/data",
})
if err != nil {
    log.Fatal(err)
}
defer vpn.Close()

if err := vpn.Start(context.Background()); err != nil {
    log.Fatal(err)
}

// VPN is now running
fmt.Println("Tunnel IP:", vpn.TunnelIP())
fmt.Println("I2P Address:", vpn.I2PAddress())

Configuration

The Config struct provides all configuration options with sensible defaults. Zero values are replaced with defaults, so minimal configuration is needed:

// Minimal config - uses all defaults
vpn, _ := embedded.New(embedded.Config{})

// Custom config
vpn, _ := embedded.New(embedded.Config{
    NodeName:     "custom-node",
    DataDir:      "/var/lib/my-vpn",
    SAMAddress:   "127.0.0.1:7656",
    TunnelSubnet: "10.42.0.0/16",
    MaxPeers:     100,
    EnableRPC:    true,
    Logger:       slog.Default(),
})

Alternatively, use functional options for a fluent API:

vpn, _ := embedded.NewWithOptions(
    embedded.WithNodeName("my-node"),
    embedded.WithDataDir("/path/to/data"),
    embedded.WithLogger(logger),
)

Lifecycle Management

The VPN follows a simple lifecycle: Initial → Starting → Running → Stopping → Stopped.

Events

Subscribe to VPN events for real-time status updates:

go func() {
    for event := range vpn.Events() {
        switch event.Type {
        case embedded.EventPeerConnected:
            fmt.Printf("Peer connected: %s\n", event.Peer.NodeID)
        case embedded.EventError:
            fmt.Printf("Error: %v\n", event.Error)
        }
    }
}()

Events are delivered on a buffered channel. If the channel fills up (consumer is slow), newer events are dropped. Use VPN.DroppedEventCount to check if any events have been dropped.

Peer Management

List connected peers and their status:

for _, peer := range vpn.Peers() {
    fmt.Printf("%s: %s (%s)\n", peer.NodeID, peer.TunnelIP, peer.State)
}

Invites

Create invite codes to allow others to join your network:

code, err := vpn.CreateInvite(24*time.Hour, 1) // expires in 24h, single use
if err != nil {
    log.Fatal(err)
}
fmt.Println("Share this invite code:", code)

Accept an invite to join another network:

err := vpn.AcceptInvite(ctx, inviteCode)

Thread Safety

All methods on VPN are safe for concurrent use.

Integration with CLI

The i2plan CLI tool uses this package internally. If you're building a custom interface, you can use VPN.Node to access lower-level functionality when needed.

Package embedded logging configuration

Index

Constants

View Source
const (
	DefaultSAMAddress   = "127.0.0.1:7656"
	DefaultTunnelSubnet = "10.42.0.0/16"
	DefaultWebListen    = "127.0.0.1:8080"
)

Default configuration values for embedded VPN.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// NodeName is a human-readable identifier for this node.
	// Default: hostname or "embedded-node"
	NodeName string

	// DataDir is where persistent data (identity, config) is stored.
	// Default: OS-specific temp directory with unique suffix
	DataDir string

	// SAMAddress is the I2P SAM bridge address.
	// Default: "127.0.0.1:7656"
	SAMAddress string

	// TunnelSubnet is the mesh IP range (CIDR notation).
	// Default: "10.42.0.0/16"
	TunnelSubnet string

	// TunnelLength is the number of I2P tunnel hops (0-7).
	// Lower values are faster but less anonymous.
	// Default: 1 (optimized for trusted mesh networks)
	// Use 2-3 if anonymity between mesh peers is required.
	TunnelLength int

	// MaxPeers is the maximum number of peers to connect with.
	// Default: 50
	MaxPeers int

	// EnableRPC starts the RPC server for external control.
	// Default: false (embedded apps typically control directly)
	EnableRPC bool

	// RPCSocket is the path to the Unix socket for RPC (relative to DataDir).
	// Default: "rpc.sock"
	RPCSocket string

	// EnableWeb starts the web UI server.
	// Default: false
	EnableWeb bool

	// WebListenAddr is the address for the web server if enabled.
	// Default: "127.0.0.1:8080"
	WebListenAddr string

	// EventBufferSize is the size of the event channel buffer.
	// Default: 100
	EventBufferSize int
}

Config configures an embedded VPN instance. Fields with zero values use sensible defaults.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config with sensible defaults.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks the configuration for errors.

type Event

type Event struct {
	// Type is the category of this event.
	Type EventType

	// Timestamp is when the event occurred.
	Timestamp time.Time

	// Peer contains peer information for peer-related events.
	// Nil for non-peer events.
	Peer *PeerInfo

	// Error contains the error for EventError events.
	// Nil for non-error events.
	Error error

	// Message is a human-readable description of the event.
	Message string

	// Data contains event-specific additional data.
	// For EventStateChanged: map[string]any{"old": State, "new": State}
	// For EventRouteAdded/Removed: RouteInfo
	// For EventInviteUsed: map[string]any{"peer_id": string}
	Data any
}

Event represents a VPN lifecycle or network event.

type EventType

type EventType int

EventType categorizes VPN events.

const (
	// EventStarted is emitted when the VPN starts successfully.
	EventStarted EventType = iota
	// EventStopped is emitted when the VPN stops.
	EventStopped
	// EventPeerConnected is emitted when a peer handshake completes.
	EventPeerConnected
	// EventPeerDisconnected is emitted when a peer connection is lost.
	EventPeerDisconnected
	// EventPeerDiscovered is emitted when a new peer is discovered via gossip.
	EventPeerDiscovered
	// EventInviteAccepted is emitted when we successfully join via an invite.
	EventInviteAccepted
	// EventInviteUsed is emitted when someone uses our invite to join.
	EventInviteUsed
	// EventInviteCreated is emitted when we create a new invite code.
	EventInviteCreated
	// EventInviteRevoked is emitted when we revoke an invite code.
	EventInviteRevoked
	// EventRouteAdded is emitted when a new route is learned.
	EventRouteAdded
	// EventRouteRemoved is emitted when a route expires or is removed.
	EventRouteRemoved
	// EventError is emitted when a recoverable error occurs.
	EventError
	// EventStateChanged is emitted when the VPN state changes.
	EventStateChanged
)

func (EventType) String

func (t EventType) String() string

String returns a human-readable name for the event type.

type InviteInfo

type InviteInfo struct {
	// Code is the full invite code string.
	Code string
	// ExpiresAt is when the invite expires.
	ExpiresAt time.Time
	// MaxUses is the maximum number of times this invite can be used.
	MaxUses int
	// UsesRemaining is how many times the invite can still be used.
	UsesRemaining int
	// NetworkID is the network this invite is for.
	NetworkID string
}

InviteInfo contains information about an invite code.

type Option

type Option func(*Config)

Option is a functional option for configuring a VPN.

func WithDataDir

func WithDataDir(dir string) Option

WithDataDir sets the data directory.

func WithEventBufferSize

func WithEventBufferSize(size int) Option

WithEventBufferSize sets the event channel buffer size.

func WithMaxPeers

func WithMaxPeers(max int) Option

WithMaxPeers sets the maximum peer count.

func WithNodeName

func WithNodeName(name string) Option

WithNodeName sets the node name.

func WithRPC

func WithRPC(enabled bool) Option

WithRPC enables the RPC server.

func WithSAMAddress

func WithSAMAddress(addr string) Option

WithSAMAddress sets the SAM bridge address.

func WithTunnelLength

func WithTunnelLength(length int) Option

WithTunnelLength sets the I2P tunnel hop count.

func WithTunnelSubnet

func WithTunnelSubnet(subnet string) Option

WithTunnelSubnet sets the mesh tunnel subnet.

func WithWeb

func WithWeb(enabled bool, listenAddr string) Option

WithWeb enables the web UI server.

type PeerInfo

type PeerInfo struct {
	// NodeID is the unique identifier for this peer.
	NodeID string
	// TunnelIP is the peer's mesh tunnel IP address.
	TunnelIP netip.Addr
	// I2PDest is the peer's I2P destination (base32).
	I2PDest string
	// State is the peer's connection state (connected, disconnected, etc.).
	State string
	// LastSeen is when we last received data from this peer.
	LastSeen time.Time
	// ConnectedAt is when the peer connection was established.
	ConnectedAt time.Time
	// Latency is the estimated round-trip time to this peer.
	Latency time.Duration
}

PeerInfo contains information about a connected or known peer.

type RouteInfo

type RouteInfo struct {
	// TunnelIP is the destination IP for this route.
	TunnelIP netip.Addr
	// NodeID is the node ID of the destination.
	NodeID string
	// ViaNodeID is the next-hop node ID (empty for direct routes).
	ViaNodeID string
	// HopCount is the number of hops to reach this destination.
	HopCount int
	// LastSeen is when this route was last verified.
	LastSeen time.Time
}

RouteInfo contains information about a mesh route.

type State

type State string

State represents the VPN lifecycle state.

const (
	// StateInitial is the state before Start is called.
	StateInitial State = "initial"
	// StateStarting means the VPN is initializing.
	StateStarting State = "starting"
	// StateRunning means the VPN is fully operational.
	StateRunning State = "running"
	// StateStopping means the VPN is shutting down.
	StateStopping State = "stopping"
	// StateStopped means the VPN has been stopped.
	StateStopped State = "stopped"
)

type Status

type Status struct {
	// State is the current VPN lifecycle state.
	State State
	// NodeID is the unique identifier for this node.
	NodeID string
	// NodeName is the human-readable node name.
	NodeName string
	// TunnelIP is this node's mesh tunnel IP address.
	TunnelIP netip.Addr
	// I2PDestination is the full I2P destination (base64).
	I2PDestination string
	// I2PAddress is the short I2P address (base32.b32.i2p).
	I2PAddress string
	// PeerCount is the number of connected peers.
	PeerCount int
	// Uptime is how long the VPN has been running.
	Uptime time.Duration
	// StartedAt is when the VPN was started.
	StartedAt time.Time
	// Version is the software version.
	Version string
}

Status contains current VPN status information.

type VPN

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

VPN is the main embedded VPN controller. It provides a high-level API for VPN lifecycle and operations.

func New

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

New creates a new embedded VPN instance with the given configuration. The VPN is not started until Start() is called.

func NewWithOptions

func NewWithOptions(opts ...Option) (*VPN, error)

NewWithOptions creates a VPN with functional options. This is an alternative to New(Config{...}) for more ergonomic usage.

func (*VPN) AcceptInvite

func (v *VPN) AcceptInvite(ctx context.Context, inviteCode string) error

AcceptInvite connects to a network using an invite code. This will establish a connection to the inviting peer and join their mesh network.

func (*VPN) BanPeer

func (v *VPN) BanPeer(nodeID, reason string, duration time.Duration) error

BanPeer adds a peer to the ban list.

func (*VPN) Close

func (v *VPN) Close() error

Close is an alias for Stop with a default 30-second timeout. Suitable for use with defer.

func (*VPN) Config

func (v *VPN) Config() Config

Config returns the VPN configuration (read-only copy).

func (*VPN) CreateInvite

func (v *VPN) CreateInvite(expiry time.Duration, maxUses int) (string, error)

CreateInvite generates an invite code for a new peer to join the network. The invite expires after the specified duration and can be used up to maxUses times. Use identity.UnlimitedUses (-1) for unlimited uses (not recommended for security). maxUses=0 is invalid and will return an error.

func (*VPN) Done

func (v *VPN) Done() <-chan struct{}

Done returns a channel that is closed when the VPN stops.

func (*VPN) DroppedEventCount

func (v *VPN) DroppedEventCount() uint64

DroppedEventCount returns the total number of events dropped due to a full buffer. If this value is non-zero, the event consumer is not keeping up with event emission. This can help detect missed critical events.

func (*VPN) Events

func (v *VPN) Events() <-chan Event

Events returns a channel that receives VPN events. The channel is buffered and may drop events if not consumed. Use DroppedEventCount() to check if events have been dropped. Close the VPN to close this channel.

func (*VPN) GetPeer

func (v *VPN) GetPeer(nodeID string) *PeerInfo

func (*VPN) I2PAddress

func (v *VPN) I2PAddress() string

I2PAddress returns this node's short I2P address (base32.b32.i2p). Returns empty string if the VPN is not running.

func (*VPN) I2PDestination

func (v *VPN) I2PDestination() string

I2PDestination returns this node's full I2P destination. Returns empty string if the VPN is not running.

func (*VPN) ListInvites

func (v *VPN) ListInvites() []InviteInfo

ListInvites returns a list of active invites created by this node.

func (*VPN) Node

func (v *VPN) Node() *core.Node

Node returns the underlying core.Node for advanced operations. Returns nil if the VPN is not started. Use with caution - direct manipulation may cause unexpected behavior.

func (*VPN) NodeID

func (v *VPN) NodeID() string

NodeID returns this node's unique identifier. Returns empty string if the VPN is not running.

func (*VPN) PeerCount

func (v *VPN) PeerCount() int

PeerCount returns the number of connected peers.

func (*VPN) Peers

func (v *VPN) Peers() []PeerInfo

func (*VPN) RevokeInvite

func (v *VPN) RevokeInvite(inviteCode string) error

RevokeInvite revokes an invite code so it can no longer be used.

func (*VPN) RouteCount

func (v *VPN) RouteCount() int

RouteCount returns the number of known routes.

func (*VPN) Routes

func (v *VPN) Routes() []RouteInfo

Routes returns a list of all known routes.

func (*VPN) Start

func (v *VPN) Start(ctx context.Context) error

Start initializes and starts the VPN. This includes:

  • Creating/loading identity
  • Opening I2P transport
  • Starting WireGuard device
  • Joining mesh network (if previously connected)

The context controls the startup timeout, not the VPN lifetime.

func (*VPN) State

func (v *VPN) State() State

State returns the current VPN state.

func (*VPN) Status

func (v *VPN) Status() Status

Status returns current VPN status.

func (*VPN) Stop

func (v *VPN) Stop(ctx context.Context) error

Stop gracefully shuts down the VPN. It notifies peers, saves state, and closes connections. The context controls the shutdown timeout.

func (*VPN) TunnelIP

func (v *VPN) TunnelIP() netip.Addr

TunnelIP returns this node's mesh tunnel IP address. Returns an invalid address if the VPN is not running.

func (*VPN) UnbanPeer

func (v *VPN) UnbanPeer(nodeID string) error

UnbanPeer removes a peer from the ban list.

Directories

Path Synopsis
Example demonstrates basic usage of the embedded VPN API.
Example demonstrates basic usage of the embedded VPN API.

Jump to

Keyboard shortcuts

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