ygg

package module
v0.4.5 Latest Latest
Warning

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

Go to latest
Published: Dec 6, 2025 License: MIT Imports: 34 Imported by: 0

README

Ygg

Ygg is a lightweight Go library that embeds a self-contained Yggdrasil node — allowing your Go application to automatically connect to the Yggdrasil network without running an external daemon.

Features

  • 🧩 Embedded Yggdrasil core — starts and manages an in-process Yggdrasil node.
  • ⚙️ Automatic configuration — generates or loads config.json automatically.
  • 🌐 Peer discovery — fetches peers from a public list and filters alive nodes.
  • 📡 Graceful shutdown — stop the node cleanly with node.Close().
  • 🪶 Library-friendly API — import and start with a single call.
  • 🔔 Connectivity events — receive callbacks when the node connects or disconnects.

Installation

go get github.com/svanichkin/ygg

Usage

package main

import (
    "log"
    ygg "github.com/svanichkin/ygg"
)

func main() {
    ygg.SetVerbose(true)

    ygg.SetConnectivityHandler(func(connected bool) {
        if connected {
            log.Println("[ygg] Connected to the network")
        } else {
            log.Println("[ygg] Disconnected from the network")
        }
    })

    // Pass a custom path or leave empty to auto-locate config.json
    node, err := ygg.New("")
    if err != nil {
        log.Fatal(err)
    }
    defer node.Close()

    log.Println("Connected to Yggdrasil!", node.Core.Address())
}

Configuration

When New() is called, the library automatically searches for config.json in:

  1. The same directory as the binary
  2. $HOME/.config/say/config.json

If none is found, a new configuration is generated.

Environment and Dependencies

  • Language: Go 1.21+
  • Dependencies:
    • github.com/yggdrasil-network/yggdrasil-go

API Overview

Function Description
New(cfgPath string) Initializes and starts a Yggdrasil node, returning *Node.
(*Node).Close() Gracefully stops the running node.
SetVerbose(v bool) Enables verbose logging.
SetMaxPeers(n int) Sets the maximum number of peers added at startup.
SetConnectivityHandler(func(connected bool)) Registers a callback for connection state changes.

Connectivity Events

The library can notify your application whenever the embedded node changes its connection status.

ygg.SetConnectivityHandler(func(connected bool) {
    if connected {
        log.Println("Yggdrasil network is up")
    } else {
        log.Println("Yggdrasil network is down")
    }
})

The callback runs in a background goroutine. The first notification reflects the current state at startup, and further calls are made only when the state changes.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNotConnected = errors.New("ygg: not connected")

ErrNotConnected is returned when an operation requires an active Ygg link (at least one Up peer), but the node currently has none.

Functions

func CollectPeers

func CollectPeers(static []string, timeout time.Duration, maxParallel int) ([]string, error)

func DialTCP

func DialTCP(peerIPv6 string, port int) (net.Conn, error)

DialTCP dials a peer over the current default node's user-space netstack.

func DialUDP

func DialUDP(peerIPv6 string, port int) (net.PacketConn, error)

DialUDP dials a peer over the current default node's user-space netstack and returns a connected PacketConn (Write/Read without specifying addr each time).

func FilterAlivePeers

func FilterAlivePeers(peers []string, timeout time.Duration, maxParallel int) []string

FilterAlivePeers checks peer availability and returns only those considered "alive". For http/https - perform HTTP GET with InsecureTLS; for other schemes - TCP dial to host:port.

func ListenTCP

func ListenTCP(port int) (net.Listener, error)

ListenTCP listens on the current default node's user-space netstack.

func ListenUDP

func ListenUDP(port int) (net.PacketConn, error)

ListenUDP listens on the current default node's user-space netstack and returns a PacketConn bound to our Ygg IPv6 on the given port. Packets can be ReadFrom/WriteTo.

func PrepareYggConfig

func PrepareYggConfig(app *AppConfig) (*ycfg.NodeConfig, error)

PrepareYggConfig generates or loads keys into ycfg.NodeConfig.

func SaveJSON

func SaveJSON(path string, v any) error

func SetConnectivityHandler

func SetConnectivityHandler(h ConnectivityHandler)

SetConnectivityHandler installs a callback for connectivity state changes. The callback is invoked on a background goroutine.

func SetMaxPeers

func SetMaxPeers(n int)

SetMaxPeers sets an upper bound on the number of peers to add at startup. If n <= 0, there is no limit.

func SetVerbose

func SetVerbose(v bool)

SetVerbose enables or disables verbose logging from this package.

Types

type AppConfig

type AppConfig struct {
	// Seed is the inline private key seed (empty => generate).
	Seed string `json:"seed,omitempty"`
	// Peers lists static peers (tcp://host:port, tls://..., quic://...).
	Peers []string `json:"peers"`
	// DialTimeoutSec controls connect timeouts.
	DialTimeoutSec int `json:"dial_timeout_sec,omitempty"`
	// contains filtered or unexported fields
}

func LoadOrInitAppConfig

func LoadOrInitAppConfig(path string) (*AppConfig, error)

func (*AppConfig) MarshalJSON

func (c *AppConfig) MarshalJSON() ([]byte, error)

func (*AppConfig) UnmarshalJSON

func (c *AppConfig) UnmarshalJSON(data []byte) error

type ConnectivityHandler

type ConnectivityHandler func(connected bool)

ConnectivityHandler is called whenever the node transitions between connected and disconnected states.

type Netstack

type Netstack struct {
	Stack *stack.Stack
	NICID tcpip.NICID
	// contains filtered or unexported fields
}

Netstack wraps an in-process gVisor TCP/IP stack bridged to the Yggdrasil core via ipv6rwc.

func (*Netstack) Addr

func (ns *Netstack) Addr() net.IP

Addr returns our Ygg IPv6 as net.IP.

func (*Netstack) AddrString

func (ns *Netstack) AddrString() string

AddrString returns our Ygg IPv6 as string.

func (*Netstack) Close

func (ns *Netstack) Close() error

Close stops pumps and releases resources.

func (*Netstack) DialTCP

func (ns *Netstack) DialTCP(peerIPv6 string, port int, timeout time.Duration) (net.Conn, error)

DialTCP dials a remote Ygg IPv6 + port through the in-process stack.

func (*Netstack) DialUDP

func (ns *Netstack) DialUDP(peerIPv6 string, port int, timeout time.Duration) (net.PacketConn, tcpip.FullAddress, error)

DialUDP dials a remote Ygg IPv6 + port using UDP.

func (*Netstack) ListenTCP

func (ns *Netstack) ListenTCP(port int) (net.Listener, error)

ListenTCP exposes a net.Listener-like API backed by netstack.

func (*Netstack) ListenUDP

func (ns *Netstack) ListenUDP(port int) (net.PacketConn, error)

ListenUDP returns an unconnected UDP PacketConn bound to our Ygg IPv6. In gonet, DialUDP with raddr=nil yields an unconnected socket that supports ReadFrom/WriteTo.

type Node

type Node struct {
	Core   *ycore.Core
	Config *ycfg.NodeConfig

	Net *Netstack
	// contains filtered or unexported fields
}

func New

func New(cfgPath string) (*Node, error)

New initializes (or loads) configuration from cfgPath, discovers peers, starts an embedded Yggdrasil core, connects to alive peers, and returns the Node. If cfgPath is empty, a default location is chosen (next to the binary or ~/.config/say/config.json). The caller owns the returned Node and may stop it by calling Close().

func StartAndConnect

func StartAndConnect(cfg *ycfg.NodeConfig, peers []string, logger ycore.Logger) (*Node, error)

StartAndConnect starts the core and connects to peers until the first one is up.

func (*Node) Close

func (n *Node) Close() error

Close attempts to gracefully stop the underlying core, if supported.

func (*Node) Connected

func (n *Node) Connected() bool

Connected reports whether the node currently has at least one Up peer.

func (*Node) DialTCP

func (n *Node) DialTCP(peerIPv6 string, port int) (net.Conn, error)

DialTCP dials a peer via this node's netstack with a default timeout.

func (*Node) ListenTCP

func (n *Node) ListenTCP(port int) (net.Listener, error)

ListenTCP exposes a netstack-backed listener from the node.

func (*Node) StartNetstack

func (n *Node) StartNetstack() (*Netstack, error)

StartNetstack wires the Yggdrasil core to the gVisor netstack via an ipv6rwc/channel endpoint.

func (*Node) WaitConnected

func (n *Node) WaitConnected(ctx context.Context, interval time.Duration) error

WaitConnected blocks until the node has at least one Up peer or the context is cancelled. The check runs at the given interval; if interval <= 0, 500ms is used. Returns nil when connected, ctx.Err() on cancellation/timeout.

Jump to

Keyboard shortcuts

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