spiderw

package module
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

README

spiderw

CI OpenSSF Scorecard Go Reference Go Report Card

spiderw is a Go-based library and development environment for working with Wi-Fi interfaces, iwd, and mockable runtime behavior. It provides:

  • A clean, strongly typed Go API for interacting with iwd
  • A fully containerized and editor-agnostic development workflow
  • A Go-based iwd mock for integration testing without real iwd, Wi-Fi hardware, or kernel modules
  • Utilities and automation to ensure consistent behavior across environments

Project status: early development (pre-v1). The public API is unstable and may change without notice until the first tagged release. The implemented surface today covers Client, Daemon, Adapter, Device, Station, BasicServiceSet, Network, KnownNetwork, and the credentials Agent (identity, powered/mode state, supported modes, property subscriptions, station connection state and scanning, connecting to open, already-known, and secured (PSK) networks via a registered agent, and managing saved networks) - with much more of the iwd API planned. It is developed and tested against iwd 3.12 (see Compatibility & Requirements). Issues are welcome; pull requests for new features are not being accepted yet (see CONTRIBUTING).

Pronunciation: spider double u.

Written: spiderw Spoken: spider double u

The name keeps the Wi-Fi/Wireless w visible in writing and pronunciation without changing the Go module path.


License

spiderw is licensed under the Apache License, Version 2.0. See LICENSE.


Compatibility & Requirements

  • iwd: Developed and tested against iwd 3.12. spiderw targets iwd 3.12 and newer, not a range of older releases. It talks to iwd over the net.connman.iwd D-Bus API using runtime introspection rather than compiled-in interface definitions, so newer iwd releases that keep a compatible D-Bus surface are expected to work without changes. Older releases are not supported: they may be missing interfaces or properties spiderw uses (for example the BasicServiceSet interface and the Network.ExtendedServiceSet property are absent on iwd too old to have that feature), and spiderw will fail clearly rather than silently degrade. iwd 3.12 is the reference version the project targets and validates against; the bundled mock's introspection XML is modeled on it.
  • Supported iwd interfaces: Daemon, Adapter, Device, Station, AccessPoint, BasicServiceSet, Network, KnownNetwork, SimpleConfiguration (WSC/WPS), SignalLevelAgent, and the credentials Agent (net.connman.iwd.Agent / AgentManager). Station exposes connection state (State, Scanning, ConnectedNetwork, and the experimental ConnectedAccessPoint / Affinities) with change subscriptions, scanning (Scan, OrderedNetworks), writing Affinities (SetAffinities), Disconnect, connecting to a hidden network (ConnectHiddenNetwork, which drives the credentials agent for secured hidden networks), and listing hidden access points (HiddenAccessPoints). Network Connect() works for open and already-known networks with no agent; connecting to a not-yet-known secured network requires a registered agent (Client.RegisterAgent) to supply credentials - without one, Connect() surfaces an error matching spiderw.ErrNoAgent. The agent's PSK passphrase path is implemented and tested end to end. The 802.1x credential callbacks (username/password and private-key passphrase) are wired through every layer but are not yet tested against the mock or validated on hardware - treat them as experimental. Provisioning a brand-new 802.1x network (NetworkConfigurationAgent) is not implemented. KnownNetwork supports inspecting saved networks, toggling auto-connect, and forgetting them. AccessPoint runs a device in AP mode: starting a PSK network (Start) or one from a stored profile (StartProfile), stopping it (Stop), scanning (Scan, OrderedNetworks), and reading the hosted-network properties (Started, SSID, Frequency, ciphers) with change subscriptions; the companion AccessPointDiagnostic interface is not yet covered. More of the iwd API is planned - see the Roadmap.
  • Operating system: Linux only. iwd is a Linux wireless daemon; spiderw has no support for other platforms.
  • D-Bus: Requires access to a D-Bus bus. Real iwd runs on the system bus (the default); the bundled Go mock runs on the session bus (pass --session on the CLI, or spiderw.SessionBus in the library).
  • Go: Built with the toolchain declared in go.mod (currently Go 1.26+).
  • Runtime dependency: github.com/godbus/dbus/v5.

Features

  • Strongly typed Go API D-Bus values are validated and converted into concrete Go types. Callers never handle dbus.Variant or weakly typed maps.

  • Property-change subscriptions Every iwd object with properties exposes a generic SubscribePropertiesChanged plus typed convenience subscriptions, so state is observed as events rather than polled - including roaming, which is only visible as a change of the station's associated access point while its state stays connected.

  • Structured errors Public errors expose a stable category, resource, operation, and wrapped cause, so callers can use errors.Is, errors.As, and errors.AsType without parsing text.

  • Mockable runtime A pure-Go iwd mock enables end-to-end and integration testing without requiring system iwd or root access.

  • Containerized development environment Development runs inside an isolated Docker environment so contributors can use any editor on any Linux system without host-side dependencies.

  • Makefile-driven workflow Common tasks (make dev, make preflight, make lint-check, etc.) ensure a consistent workflow across contributors.

  • Preflight validation Host and container environments are checked for correctness before development begins.

  • Optional radio simulation via mac80211_hwsim The current mock integration suite does not require Wi-Fi hardware, real iwd, root access, or mac80211_hwsim. If you are doing separate radio-level experiments against simulated Wi-Fi hardware, enable the Linux kernel module:

    sudo modprobe mac80211_hwsim
    

    Without the module, hardware-level Wi-Fi simulation workflows will be unavailable.


Current Automation Status

GitHub Actions CI runs on every push to main and every pull request targeting it. The pipeline:

  • builds and vets the module, and cross-compiles the CLI for each supported architecture;
  • runs golangci-lint, codespell, and an ASCII check (this project writes plain ASCII - no em dashes, ellipses, or arrows, anywhere);
  • executes the unit, stress, regression, benchmark, and fuzz suites natively;
  • runs the race and mock integration suites, and the stress suite under the race detector, on a D-Bus session bus;
  • and gates the whole thing behind a final job that fails unless every suite above passed.

Fuzzing is bounded and advisory - it does not gate a release, but it runs so that a fuzz target which stops compiling cannot rot unnoticed behind its build tag.

The same checks are available locally through the dev-container Makefile workflow (formatting, linting, and the full test matrix). Before publishing a release, run the relevant local targets from TESTING.md.


Design Philosophy

spiderw prioritizes correctness, safety, and clarity over raw performance.

Key principles:

  • All weakly typed D-Bus data is validated and normalized at the boundary
  • Concurrency correctness is treated as a first-class concern
  • Public APIs expose only strongly typed, stable interfaces
  • Performance is monitored, but never optimized at the expense of correctness

User Quick Start

go get github.com/chrispypip/spiderw

Example snippet:

ctx := context.Background()

// SystemBus is the default; pass spiderw.SessionBus for the session bus.
client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
if err != nil {
    log.Fatal(err)
}
defer client.Close()

info, err := client.Daemon().Info(ctx)
if err != nil {
    log.Fatal(err)
}

fmt.Println(info.Version)
Error Handling

spiderw returns structured public errors when it can classify a failure. Use the generic sentinel for the category and inspect the resource when the caller needs to distinguish daemon, adapter, network, or client failures.

info, err := client.Daemon().Info(ctx)
if err != nil {
    if swerr, ok := errors.AsType[*spiderw.Error](err); ok {
        switch {
        case errors.Is(err, spiderw.ErrUnavailable) &&
            swerr.Resource == spiderw.ResourceDaemon:
            log.Printf("iwd daemon is unavailable: %v", err)
        case errors.Is(err, spiderw.ErrInvalidState):
            log.Printf("spiderw observed invalid daemon state: %v", err)
        default:
            log.Printf("spiderw error in %s: %v", swerr.Op, err)
        }
        return
    }
    log.Fatal(err)
}

The public error categories are KindUnavailable, KindInvalidState, KindInvalidArgument, and KindInternal. Resource values are ResourceClient, ResourceDaemon, ResourceAdapter, ResourceDevice, ResourceBasicServiceSet, ResourceStation, ResourceAccessPoint, ResourceSimpleConfiguration (WSC), ResourceNetwork, ResourceKnownNetwork, and ResourceAgent; ResourceUnknown is the zero value, meaning no specific resource.

Some operations also map specific iwd D-Bus errors to matchable sentinels, so you can react to a precise outcome without parsing text. For example, Network.Connect surfaces spiderw.ErrNoAgent (no credentials agent registered), spiderw.ErrBusy, spiderw.ErrInProgress, spiderw.ErrFailed, spiderw.ErrTimeout, spiderw.ErrAborted, spiderw.ErrNotSupported, and spiderw.ErrNotConfigured; registering an agent can surface spiderw.ErrAlreadyExists (another agent already owns the connection). These join the rest of iwd's named errors (spiderw.ErrNotFound, spiderw.ErrInvalidArguments, ...) - all usable with errors.Is.

A few interfaces add their own scoped sentinels. WSC enrollment surfaces spiderw.ErrWSCWalkTimeExpired (nobody pressed the button in time), spiderw.ErrWSCNoCredentials, spiderw.ErrWSCSessionOverlap (two enrollments racing), spiderw.ErrWSCNotReachable, and spiderw.ErrWSCTimeExpired. See the godoc for the full set.


Development Quick Start

spiderw contains a development container for easy development and testing. The development container provides:

  • Go toolchain
  • D-Bus session environment
  • iwd mock tooling
  • Testing dependencies

It intentionally does not install any specific editor or IDE tooling. Developers may use their preferred tools locally or view remote container workflows. Ensure all guidelines from CONTRIBUTING.md are followed.

To set up the development container and prepare for development, follow these steps:

1. Install Dependencies

Ensure you have:

  • Docker
  • Docker Compose V2
  • Make
2. Optional: Enable mac80211_hwsim (for radio simulation)

The normal mock integration suite does not need mac80211_hwsim. Enable it only if you plan to run separate radio simulation workflows:

sudo modprobe mac80211_hwsim
3. Ensure You Have Everything You Need

This validates:

On the host:

  • Docker available without sudo
  • docker-compose V2 installed

In the container:

  • D-Bus session bus availability
  • iwd mock functional
  • Required system utilities present
make preflight
4. Enter the Development Environment
make dev

This opens an isolated shell containing the full toolchain and starts a D-Bus session.

5. Build & Test

Inside the dev shell:

go build ./...
go test ./... -tags=unit

From the host, the equivalent Makefile targets are:

make test-unit
make lint-check

More testing and benchmarking commands are in TESTING.md and BENCHMARKS.md.


Repository Structure

*.go                     -> The public spiderw library (package spiderw)
dev/                     -> Development files
    Dockerfile.dev       -> Dev container runtime definition
    docker-compose.yml   -> Orchestration for development environment
    dev.sh               -> Entry point for dev shell
cmd/                     -> Tooling and CLI utilities
examples/                -> Runnable example programs (see examples/README.md)
internal/connect         -> D-Bus connection and typed object wiring
internal/core            -> Validation, normalization, and core error wrapping
internal/failure         -> Shared error kind/resource taxonomy
internal/iwdbus          -> Strongly typed D-Bus/iwd bindings
internal/iwdvalue        -> Shared canonical iwd value parsing and formatting
internal/logging         -> Lightweight structured logging helpers
scripts/                 -> Developer/CI scripts (bounded fuzzing, ASCII check)
tools/test-mocks/        -> Go-based iwd mock and introspection XML fixtures
tests/                   -> Integration tests and test utilities

Strongly Typed API

Although iwd and D-Bus expose weakly typed values (dbus.Variant, map[string]interface{}, etc.), spiderw intentionally exposes a strongly typed Go API.

This ensures:

  • Predictable types for all public methods
  • Early detection of schema changes or D-Bus inconsistencies
  • No Variant handling in user code
  • Easier testing and API stability

D-Bus decoding is handled internally; public methods return standard Go types (string, bool, []int, etc.).


CLI Quick Start

The spiderw command can query the daemon, adapters, devices, stations, access points, basic service sets, networks, and known networks through the same public API used by library callers. It uses the system bus by default, which is where real iwd runs, so the examples below need no bus flag. The Go mock registers on the session bus, so pass --session when testing against iwdmock.

Global flags may be placed anywhere in the command:

  • --session uses the session D-Bus bus instead of the default system bus.
  • --json emits JSON for commands with structured output.
  • --help prints command help.

Daemon examples:

spiderw daemon info
spiderw daemon version
spiderw daemon state-dir
spiderw daemon net-conf

List adapters, or print a full snapshot for every adapter:

spiderw adapter list
spiderw adapter status

Use the adapter name or path from adapter list as the adapter reference:

spiderw adapter phy0 status
spiderw adapter phy0 powered
spiderw adapter phy0 powered true
spiderw adapter phy0 name
spiderw adapter phy0 model
spiderw adapter phy0 vendor
spiderw adapter phy0 supported-modes
spiderw adapter phy0 supports-mode station
spiderw adapter phy0 supports-station
spiderw adapter phy0 supports-ap
spiderw adapter phy0 supports-ad-hoc
spiderw adapter phy0 monitor powered

List devices, or print a full snapshot for every device:

spiderw device list
spiderw device status

Use the device name or path from device list as the device reference:

spiderw device wlan0 status
spiderw device wlan0 powered
spiderw device wlan0 powered false
spiderw device wlan0 mode
spiderw device wlan0 mode ap
spiderw device wlan0 name
spiderw device wlan0 address
spiderw device wlan0 adapter
spiderw device wlan0 monitor powered
spiderw device wlan0 monitor mode

Inspect, scan, and control stations (devices in station mode). status shows State, Scanning, and the connected network/AP; scan triggers a scan (waiting for it to finish, then listing results, unless --no-wait; --timeout bounds the wait); networks lists the last scan's results by signal; disconnect and connect-hidden control the connection (a secured hidden network prompts for, or takes, a passphrase); hidden-aps lists hidden access points; wsc joins an access point without a passphrase via WSC (WPS) push-button or PIN. Networks render as their SSID and access points as their MAC (object paths are still available with --json). A station is referenced by its device name (e.g. wlan0) or object path:

spiderw station list
spiderw station status
spiderw station wlan0 status
spiderw station wlan0 scan --timeout=30s
spiderw station wlan0 networks
spiderw station wlan0 disconnect
spiderw station wlan0 connect-hidden MyHidden --passphrase=secret
spiderw station wlan0 hidden-aps
spiderw station wlan0 affinities
spiderw station wlan0 affinities set de:ad:be:ef:ca:fe   # a BSS MAC or object path
spiderw station wlan0 affinities clear
spiderw station wlan0 wsc push-button                    # press the AP's WPS button first
spiderw station wlan0 wsc pin                            # generates and prints a PIN to enter at the AP
spiderw station wlan0 monitor state                      # stream a property until Ctrl-C
spiderw station wlan0 monitor network                    # the connected network's SSID
spiderw station wlan0 monitor access-point               # the associated BSS - this is how a roam is watched
spiderw station wlan0 monitor affinities
spiderw station wlan0 monitor-signal -60 -70 -80         # RSSI thresholds, highest first

monitor access-point is the only way to observe a roam: the station moves between access points of the same network, so the BSS changes while the state stays connected and the network does not change at all. A reconnect looks different - the BSS drops to none in between.

Inspect and control access points (devices in AP mode). status shows Started, Scanning, and - while running - the hosted SSID, Frequency, and ciphers; start brings up a PSK network, start-profile one from a stored profile, stop tears it down. scan triggers a scan (waiting for it to finish, then listing results, unless --no-wait; --timeout bounds the wait), and networks lists the last scan's results by signal. An access point is referenced by its device name (e.g. wlan1) or object path:

spiderw access-point list
spiderw access-point status
spiderw access-point wlan1 status
spiderw access-point wlan1 start MyAP s3cretpass
spiderw access-point wlan1 start-profile MyProfile
spiderw access-point wlan1 scan --timeout=30s
spiderw access-point wlan1 networks
spiderw access-point wlan1 stop
spiderw access-point wlan1 monitor started               # stream a property until Ctrl-C
spiderw access-point wlan1 monitor scanning

List basic service sets (BSSes), or print a full snapshot for every BSS. A device usually sees many BSSes - one per access point/radio heard during a scan:

spiderw bss list
spiderw bss status

Use the address or path from bss list as the BSS reference:

spiderw bss 11:22:33:44:55:66 status
spiderw bss 11:22:33:44:55:66 address

List networks, or print a full snapshot for every network:

spiderw network list
spiderw network status

Use the SSID or path from network list as the network reference:

spiderw network OpenNet status
spiderw network OpenNet connect
spiderw network OpenNet connected
spiderw network OpenNet type
spiderw network OpenNet device
spiderw network OpenNet known-network
spiderw network OpenNet bsses
spiderw network OpenNet monitor connected
spiderw network OpenNet monitor known-network            # fires when the network is saved or forgotten
spiderw network OpenNet monitor bsses

connect joins open and already-known networks directly. For a not-yet-known secured (PSK) network it registers a temporary credentials agent and supplies the passphrase from --passphrase, --passphrase-stdin, or an interactive no-echo prompt:

spiderw network MyWifi connect                       # prompts: Passphrase: ******
spiderw network MyWifi connect --passphrase=hunter2  # non-interactive
echo hunter2 | spiderw network MyWifi connect --passphrase-stdin

List known (saved) networks, or print a full snapshot for every one:

spiderw known-network list
spiderw known-network status

Use the name or path from known-network list as the reference:

spiderw known-network KnownNet status
spiderw known-network KnownNet type
spiderw known-network KnownNet hidden
spiderw known-network KnownNet last-connected
spiderw known-network KnownNet autoconnect
spiderw known-network KnownNet autoconnect false
spiderw known-network KnownNet forget
spiderw known-network KnownNet monitor autoconnect
spiderw known-network KnownNet monitor hidden
spiderw known-network KnownNet monitor last-connected    # fires on each successful connect

To target the Go mock instead of a real daemon, add --session:

spiderw --session daemon info

Monitor commands print the property's current value, then stream each change until interrupted (Ctrl-C). <resource> <ref> monitor --help lists what that resource can monitor. With --json, each change is emitted as its own object, one per line, so the stream can be piped into a consumer.


Contributing

See CONTRIBUTING.md for contribution policy and development instructions. Participation in project spaces is covered by the Code of Conduct.


Support

spiderw is developed and maintained in my spare time. If you find it useful and would like to support the project, sponsorships are appreciated but never expected.


Further Reading

Documentation

Overview

Package spiderw provides a safe, strongly typed Go API for interacting with the iwd daemon (net.connman.iwd) over D-Bus.

Public callers start with Client, then reach the daemon, adapters, devices, stations, access points, networks, known networks, and basic service sets through typed wrappers. The package normalizes raw D-Bus values, avoids exposing D-Bus types in the public API, and maps lower-level failures into stable public error categories.

State can be observed as events rather than polled: every object with properties offers a generic SubscribePropertiesChanged plus typed convenience subscriptions. An absent value arrives as nil - iwd signals that an object is gone by invalidating the property rather than sending a null path - so a disconnected station reports a nil connected network, and a forgotten network a nil known network. Watching a station's connected access point is the only way to observe a roam: the associated BSS changes while the state stays StationStateConnected and the connected network does not change at all.

Credentials are supplied by registering an Agent (Client.RegisterAgent), and RSSI thresholds by a signal-level agent (Station.MonitorSignalLevel).

Example (ErrorHandling)

Example_errorHandling shows how to classify a failure with the public error sentinels and inspect its structured fields.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	_, err = client.Daemon().Info(ctx)
	if err != nil {
		// Match a category with the sentinel.
		if errors.Is(err, spiderw.ErrUnavailable) {
			fmt.Println("iwd is unavailable")
		}

		// Inspect the structured fields with errors.AsType.
		if swErr, ok := errors.AsType[*spiderw.Error](err); ok && swErr.Resource == spiderw.ResourceDaemon {
			fmt.Printf("daemon error in %s: %v\n", swErr.Op, err)
		}

	}
}

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnavailable matches errors whose public kind is KindUnavailable.
	ErrUnavailable = errors.New("unavailable")

	// ErrInvalidState matches errors whose public kind is KindInvalidState.
	ErrInvalidState = errors.New("invalid state")

	// ErrInternal matches errors whose public kind is KindInternal.
	ErrInternal = errors.New("internal error")

	// ErrInvalidArgument matches errors whose public kind is KindInvalidArgument.
	ErrInvalidArgument = errors.New("invalid argument")

	// ErrSpiderw matches all structured errors returned by the public API.
	ErrSpiderw = errors.New("spiderw api error")

	// ErrNoAgent matches errors caused by iwd rejecting an operation because no
	// credentials agent is registered. Connecting to a secured network that is
	// not already known requires a registered agent; until then, Network.Connect
	// returns an error matching ErrNoAgent.
	ErrNoAgent = core.ErrNoAgent

	// The following sentinels match named iwd D-Bus errors surfaced by operations
	// such as Network.Connect. Use errors.Is to react to a specific iwd outcome
	// (for example, retry on ErrInProgress, give up on ErrNotSupported) without
	// parsing error text. Note: current iwd reports a busy/in-progress condition
	// as ErrInProgress; ErrBusy and ErrTimeout are retained for compatibility but
	// are not emitted by iwd today.
	ErrAborted       = core.ErrAborted
	ErrBusy          = core.ErrBusy
	ErrFailed        = core.ErrFailed
	ErrNotSupported  = core.ErrNotSupported
	ErrTimeout       = core.ErrTimeout
	ErrInProgress    = core.ErrInProgress
	ErrNotConfigured = core.ErrNotConfigured

	// ErrNotFound and ErrAlreadyExists are surfaced by the agent manager
	// (UnregisterAgent on an unregistered agent; RegisterAgent when another agent
	// already owns the connection), among other operations.
	ErrNotFound      = core.ErrNotFound
	ErrAlreadyExists = core.ErrAlreadyExists
	// ErrInvalidArguments matches iwd's named net.connman.iwd.InvalidArguments
	// error. It is distinct from ErrInvalidArgument (singular), which matches any
	// public KindInvalidArgument error spiderw itself raises.
	ErrInvalidArguments   = core.ErrInvalidArguments
	ErrInvalidFormat      = core.ErrInvalidFormat
	ErrNotConnected       = core.ErrNotConnected
	ErrNotImplemented     = core.ErrNotImplemented
	ErrServiceSetOverlap  = core.ErrServiceSetOverlap
	ErrAlreadyProvisioned = core.ErrAlreadyProvisioned
	ErrNotHidden          = core.ErrNotHidden
	ErrNotAvailable       = core.ErrNotAvailable
	// ErrPermissionDenied matches iwd's net.connman.iwd.PermissionDenied, returned
	// when the caller lacks permission for a privileged operation.
	ErrPermissionDenied = core.ErrPermissionDenied

	// The following match iwd's WSC (SimpleConfiguration) enrollment errors, so a
	// caller can react to a specific WSC outcome with errors.Is. ErrWSCSessionOverlap
	// means more than one access point was in PushButton mode; ErrWSCWalkTimeExpired
	// and ErrWSCTimeExpired mean no access point was found in PushButton / PIN mode
	// within the allotted time.
	ErrWSCSessionOverlap  = core.ErrWSCSessionOverlap
	ErrWSCNoCredentials   = core.ErrWSCNoCredentials
	ErrWSCNotReachable    = core.ErrWSCNotReachable
	ErrWSCWalkTimeExpired = core.ErrWSCWalkTimeExpired
	ErrWSCTimeExpired     = core.ErrWSCTimeExpired
)

Error sentinels support errors.Is checks against public error categories.

Functions

This section is empty.

Types

type AccessPoint added in v0.13.0

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

AccessPoint is a device running in AP mode, hosting a network. Obtain one with Client.AccessPoint or Client.AllAccessPoints.

func (*AccessPoint) Frequency added in v0.13.0

func (a *AccessPoint) Frequency(ctx context.Context) (*uint32, error)

Frequency returns the operating frequency in MHz, or nil when not running.

func (*AccessPoint) GroupCipher added in v0.13.0

func (a *AccessPoint) GroupCipher(ctx context.Context) (*string, error)

GroupCipher returns the broadcast/multicast cipher, or nil when not running.

func (*AccessPoint) Name added in v0.13.0

func (a *AccessPoint) Name() string

Name returns the underlying device's name (e.g. "wlan1"). This is the device identity, not the hosted network's SSID - see SSID.

func (*AccessPoint) OrderedNetworks added in v0.13.0

func (a *AccessPoint) OrderedNetworks(ctx context.Context) ([]AccessPointOrderedNetwork, error)

OrderedNetworks returns the networks from the most recent access-point scan, ordered by signal strength.

func (*AccessPoint) PairwiseCiphers added in v0.13.0

func (a *AccessPoint) PairwiseCiphers(ctx context.Context) ([]string, error)

PairwiseCiphers returns the negotiated unicast ciphers, or nil when not running.

func (*AccessPoint) Path added in v0.13.0

func (a *AccessPoint) Path() string

Path returns the access point's D-Bus object path (a device path).

func (*AccessPoint) Properties added in v0.13.0

func (a *AccessPoint) Properties(ctx context.Context) (*AccessPointProperties, error)

Properties returns a snapshot of every access-point property in one call.

func (*AccessPoint) SSID added in v0.13.0

func (a *AccessPoint) SSID(ctx context.Context) (*string, error)

SSID returns the hosted network's SSID (iwd's "Name" property), or nil when the access point is not running.

func (*AccessPoint) Scan added in v0.13.0

func (a *AccessPoint) Scan(ctx context.Context) error

Scan schedules an access-point scan. It is asynchronous; the Scanning property tracks progress.

func (*AccessPoint) Scanning added in v0.13.0

func (a *AccessPoint) Scanning(ctx context.Context) (bool, error)

Scanning reports whether the access point is scanning.

func (*AccessPoint) Start added in v0.13.0

func (a *AccessPoint) Start(ctx context.Context, ssid, psk string) error

Start starts a PSK-secured access point advertising ssid with passphrase psk (SSID 1-32 bytes, passphrase 8-63 characters). It blocks until iwd reports the outcome. iwd returns an error matching ErrAlreadyExists when an AP is already running.

func (*AccessPoint) StartProfile added in v0.13.0

func (a *AccessPoint) StartProfile(ctx context.Context, ssid string) error

StartProfile starts an access point from the stored profile named ssid, which may configure security modes beyond PSK. iwd returns an error matching ErrNotFound when no such profile exists.

func (*AccessPoint) Started added in v0.13.0

func (a *AccessPoint) Started(ctx context.Context) (bool, error)

Started reports whether the access point is running.

func (*AccessPoint) Stop added in v0.13.0

func (a *AccessPoint) Stop(ctx context.Context) error

Stop stops the running access point.

func (*AccessPoint) SubscribePropertiesChanged added in v0.13.0

func (a *AccessPoint) SubscribePropertiesChanged(ctx context.Context, fn func(AccessPointPropertiesChanged)) (UnsubscribeFunc, error)

SubscribePropertiesChanged registers fn for access-point property changes.

func (*AccessPoint) SubscribeScanningChanged added in v0.13.0

func (a *AccessPoint) SubscribeScanningChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribeScanningChanged registers fn for changes to the Scanning state.

func (*AccessPoint) SubscribeStartedChanged added in v0.13.0

func (a *AccessPoint) SubscribeStartedChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribeStartedChanged registers fn for changes to the Started state.

type AccessPointOrderedNetwork added in v0.13.0

type AccessPointOrderedNetwork struct {
	// Name is the scanned network's SSID.
	Name string

	// SignalStrength is the signal strength in dBm (e.g. -60.5). iwd reports it in
	// units of 100 * dBm; spiderw exposes it as dBm here.
	SignalStrength float64

	// Type is the network security type.
	Type NetworkType
}

AccessPointOrderedNetwork is one network an access point heard while scanning.

type AccessPointProperties added in v0.13.0

type AccessPointProperties struct {
	// Started reports whether the access point is running.
	Started bool

	// Scanning reports whether the access point is scanning. iwd only exposes this
	// while the AP is started, so it reads false when the AP is not running.
	Scanning bool

	// SSID is the hosted network's SSID (iwd's "Name" property), or nil when the
	// AP is not running.
	SSID *string

	// Frequency is the operating frequency in MHz, or nil when not running.
	Frequency *uint32

	// PairwiseCiphers are the negotiated unicast ciphers (e.g. "CCMP"), or nil.
	PairwiseCiphers []string

	// GroupCipher is the broadcast/multicast cipher, or nil.
	GroupCipher *string
}

AccessPointProperties is a snapshot of an access point's state. Started is always present; the rest are absent (nil, or false for Scanning) while the AP is not running.

type AccessPointPropertiesChanged added in v0.13.0

type AccessPointPropertiesChanged struct {
	// Changed holds the changed property values keyed by name.
	Changed map[string]any

	// Invalidated names properties whose values should be re-read if needed.
	Invalidated []string
}

AccessPointPropertiesChanged is a normalized access-point property-change event.

type AccessPointRef added in v0.13.0

type AccessPointRef struct {
	// Path is the canonical D-Bus object path for the access point (a device
	// path).
	Path string

	// Name is the co-located device's Name (best-effort; empty if unavailable).
	Name string
}

AccessPointRef is a lightweight reference to an access point (a device in AP mode). Name is the co-located device's Name (e.g. "wlan1"), not the hosted network's SSID.

type Adapter

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

Adapter provides high-level operations for a specific iwd adapter object.

func (*Adapter) Model

func (a *Adapter) Model(ctx context.Context) (*string, error)

Model returns the adapter model, or nil when iwd does not report one.

func (*Adapter) Name

func (a *Adapter) Name(ctx context.Context) (string, error)

Name returns the adapter name.

func (*Adapter) Path added in v0.2.0

func (a *Adapter) Path() string

Path returns the D-Bus object path the adapter was constructed from.

Path is static adapter identity, not an iwd property: it requires no D-Bus round-trip and never fails. Path returns "" for a nil receiver.

func (*Adapter) Powered

func (a *Adapter) Powered(ctx context.Context) (bool, error)

Powered reports whether the adapter is currently powered.

func (*Adapter) Properties added in v0.2.0

func (a *Adapter) Properties(ctx context.Context) (*AdapterProperties, error)

Properties reads every adapter property in a single D-Bus call (Properties.GetAll) instead of one call per property. Prefer it when you need several properties at once, such as building an overview of an adapter.

Example

ExampleAdapter_Properties reads every adapter property in a single Properties.GetAll call instead of one D-Bus call per property.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Adapters(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no adapters found")
	}

	adapter, err := client.Adapter(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	// One round-trip fetches Powered, Name, Model, Vendor, and SupportedModes
	// together. Model and Vendor are nil when iwd does not report them.
	props, err := adapter.Properties(ctx)
	if err != nil {
		log.Fatal(err)
	}

	model := "unknown"
	if props.Model != nil {
		model = *props.Model
	}
	fmt.Printf("%s powered=%t model=%s modes=%v\n",
		props.Name, props.Powered, model, props.SupportedModes)
}

func (*Adapter) SetPowered

func (a *Adapter) SetPowered(ctx context.Context, powered bool) error

SetPowered changes whether the adapter is powered.

func (*Adapter) SubscribePoweredChanged

func (a *Adapter) SubscribePoweredChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribePoweredChanged registers fn for adapter powered-state changes and returns a handle that unregisters the callback.

Example

ExampleAdapter_SubscribePoweredChanged registers a callback for powered-state changes and unsubscribes when finished.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Adapters(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no adapters found")
	}

	adapter, err := client.Adapter(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	unsubscribe, err := adapter.SubscribePoweredChanged(ctx, func(powered bool) {
		fmt.Println("powered changed:", powered)
	})
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = unsubscribe.Unsubscribe() }()

	// ... do work while the subscription is active ...
}

func (*Adapter) SubscribePropertiesChanged

func (a *Adapter) SubscribePropertiesChanged(ctx context.Context, fn func(AdapterPropertiesChanged)) (UnsubscribeFunc, error)

SubscribePropertiesChanged registers fn for adapter property-change signals and returns a handle that unregisters the callback.

func (*Adapter) SupportedModes

func (a *Adapter) SupportedModes(ctx context.Context) ([]Mode, error)

SupportedModes returns the adapter modes currently reported by iwd.

func (*Adapter) SupportsAP

func (a *Adapter) SupportsAP(ctx context.Context) (bool, error)

SupportsAP reports whether the adapter supports access point mode.

func (*Adapter) SupportsAdHoc

func (a *Adapter) SupportsAdHoc(ctx context.Context) (bool, error)

SupportsAdHoc reports whether the adapter supports ad-hoc mode.

func (*Adapter) SupportsMode

func (a *Adapter) SupportsMode(ctx context.Context, mode Mode) (bool, error)

SupportsMode reports whether the adapter supports the provided mode.

Example

ExampleAdapter_SupportsMode checks whether an adapter supports station mode.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Adapters(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no adapters found")
	}

	adapter, err := client.Adapter(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	ok, err := adapter.SupportsMode(ctx, spiderw.ModeStation)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("supports station mode:", ok)
}

func (*Adapter) SupportsStation

func (a *Adapter) SupportsStation(ctx context.Context) (bool, error)

SupportsStation reports whether the adapter supports station mode.

func (*Adapter) Vendor

func (a *Adapter) Vendor(ctx context.Context) (*string, error)

Vendor returns the adapter vendor, or nil when iwd does not report one.

type AdapterProperties added in v0.2.0

type AdapterProperties struct {
	// Powered reports whether the adapter is currently powered.
	Powered bool

	// Name is the adapter's human-friendly Name property.
	Name string

	// Model is the adapter's Model property, or nil when not reported.
	Model *string

	// Vendor is the adapter's Vendor property, or nil when not reported.
	Vendor *string

	// SupportedModes lists the adapter's supported operating modes.
	SupportedModes []Mode
}

AdapterProperties is a snapshot of all adapter properties read in a single D-Bus call. Model and Vendor are nil when iwd does not report them.

type AdapterPropertiesChanged

type AdapterPropertiesChanged struct {
	// Changed contains new property values keyed by property name.
	Changed map[string]any

	// Invalidated contains property names whose values should be re-read if needed.
	Invalidated []string
}

AdapterPropertiesChanged describes adapter properties reported by a D-Bus PropertiesChanged signal. Changed contains the new values by property name; Invalidated contains property names whose values should be re-read if needed.

type AdapterRef

type AdapterRef struct {
	// Path is the canonical D-Bus object path for the adapter.
	Path string

	// Name is the adapter's human-friendly Name property.
	Name string
}

AdapterRef is a lightweight reference to an adapter discovered by the iwd daemon.

type Agent added in v0.6.0

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

Agent is a registered credentials agent handle returned by Client.RegisterAgent. Call Unregister when the agent is no longer needed; the owning Client also unregisters it on Close.

func (*Agent) Unregister added in v0.6.0

func (a *Agent) Unregister(ctx context.Context) error

Unregister unregisters the agent from iwd and releases its resources. It is idempotent and safe to call even after the owning Client has been closed.

type AgentConfig added in v0.6.0

type AgentConfig struct {
	// Passphrase supplies the passphrase for a PSK network.
	Passphrase func(ctx context.Context, networkPath string) (string, error)

	// PrivateKeyPassphrase supplies the passphrase protecting an 802.1x private
	// key.
	PrivateKeyPassphrase func(ctx context.Context, networkPath string) (string, error)

	// UserNameAndPassword supplies the username and password for an 802.1x
	// network.
	UserNameAndPassword func(ctx context.Context, networkPath string) (user, password string, err error)

	// UserPassword supplies the password for an 802.1x network whose username iwd
	// already knows.
	UserPassword func(ctx context.Context, networkPath, user string) (string, error)

	// OnCancel is called when iwd aborts a pending request. reason is one of
	// iwd's cancel reasons (for example "out-of-range", "user-canceled",
	// "timed-out").
	OnCancel func(reason string)

	// OnRelease is called when iwd no longer needs the agent (it was unregistered
	// or replaced).
	OnRelease func()
}

AgentConfig supplies the callbacks iwd invokes when it needs credentials to connect to a secured network that is not already known. Register it with Client.RegisterAgent.

Each request callback returns the requested credential, or a non-nil error to decline; a nil callback also declines (iwd receives a Canceled reply). At least one request callback (Passphrase, PrivateKeyPassphrase, UserNameAndPassword, or UserPassword) must be set, or RegisterAgent returns an invalid-argument error.

networkPath is the iwd Network object path the request concerns; resolve it to a handle with Client.Network if you need network details. The supplied context is canceled if the request is aborted (for example by iwd's Cancel or by Agent.Unregister), so long-running callbacks such as interactive prompts should honor it. OnCancel and OnRelease are optional notifications.

Testing status: the Passphrase (PSK) path is tested end to end against the iwd mock. The 802.1x callbacks (PrivateKeyPassphrase, UserNameAndPassword, UserPassword) are wired through every layer but are not yet exercised against the mock or validated on hardware; treat them as experimental.

type BasicServiceSet added in v0.4.0

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

BasicServiceSet provides high-level operations for a specific iwd basic service set (BSS) object.

A BSS is a single access point or peer that the radio can see; iwd exposes it as a read-only object whose only property is its Address (BSSID).

func (*BasicServiceSet) Address added in v0.4.0

func (b *BasicServiceSet) Address(ctx context.Context) (string, error)

Address returns the BSS's hardware (BSSID) address.

func (*BasicServiceSet) Path added in v0.4.0

func (b *BasicServiceSet) Path() string

Path returns the D-Bus object path the BSS was constructed from.

Path is static object identity, not an iwd property: it requires no D-Bus round-trip and never fails. Path returns "" for a nil receiver.

func (*BasicServiceSet) Properties added in v0.4.0

Properties reads every BSS property in a single D-Bus call (Properties.GetAll). The iwd BasicServiceSet interface exposes only Address.

type BasicServiceSetProperties added in v0.4.0

type BasicServiceSetProperties struct {
	// Address is the BSS's hardware (BSSID) address.
	Address string
}

BasicServiceSetProperties is a snapshot of all BSS properties read in a single D-Bus call. The iwd BasicServiceSet interface exposes only Address.

type BasicServiceSetRef added in v0.4.0

type BasicServiceSetRef struct {
	// Path is the canonical D-Bus object path for the BSS.
	Path string

	// Address is the BSS's hardware (BSSID) address.
	Address string
}

BasicServiceSetRef is a lightweight reference to a basic service set (BSS) discovered by the iwd daemon.

type Bus

type Bus bool

Bus selects which D-Bus message bus a Client connects to.

Bus is a defined boolean type, so call sites may pass the named constants (SystemBus / SessionBus) for clarity or a bare bool literal interchangeably. The zero value is SystemBus.

const (
	// SystemBus connects to the system bus. This is the default, and is what
	// real iwd deployments use.
	SystemBus Bus = false

	// SessionBus connects to the session bus, which is primarily useful for
	// tests and mocks.
	SessionBus Bus = true
)

func (Bus) String

func (b Bus) String() string

String returns "system" or "session".

type Client

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

Client is the root of the public spiderw API.

A Client owns one D-Bus connection and the wiring derived from it. Call Close when the client is no longer needed.

func NewClient

func NewClient(ctx context.Context, bus Bus) (*Client, error)

NewClient connects to iwd over D-Bus and initializes a Client.

By default NewClient connects to the system bus (SystemBus), which is what real iwd deployments use. Pass SessionBus to connect to the session bus instead, which is primarily useful for tests and mocks.

Example

ExampleNewClient connects to iwd and reads the daemon version.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	// SystemBus is the default and is what real iwd deployments use; pass
	// spiderw.SessionBus to talk to an iwd mock on the session bus instead.
	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	version, err := client.Daemon().Version(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(version)
}

func (*Client) AccessPoint added in v0.13.0

func (c *Client) AccessPoint(ctx context.Context, path string) (*AccessPoint, error)

AccessPoint resolves the access point (a device in AP mode) at the given iwd object path (a device path).

func (*Client) Adapter

func (c *Client) Adapter(ctx context.Context, path string) (*Adapter, error)

Adapter creates an Adapter wrapper for a specific iwd adapter object path.

Use Daemon.Adapters to discover valid adapter paths.

Example

ExampleClient_Adapter discovers an adapter and reads its powered state.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Adapters(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no adapters found")
	}

	adapter, err := client.Adapter(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	powered, err := adapter.Powered(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s powered: %t\n", refs[0].Name, powered)
}

func (*Client) AllAccessPoints added in v0.13.0

func (c *Client) AllAccessPoints(ctx context.Context) ([]*AccessPoint, error)

AllAccessPoints returns every access point (device currently in AP mode) exposed by iwd.

func (*Client) AllAdapters added in v0.2.0

func (c *Client) AllAdapters(ctx context.Context) ([]*Adapter, error)

AllAdapters mints live Adapter handles for every adapter iwd currently exposes.

It enumerates adapters via the daemon, then constructs a handle for each, preserving the daemon's enumeration order. Use Adapter to obtain a single adapter by path, or Daemon.Adapters for lightweight references without constructing handles.

Example

ExampleClient_AllAdapters constructs a handle for every adapter iwd exposes and reports each one's powered state.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// AllAdapters enumerates via the daemon and returns a live handle per
	// adapter, in enumeration order. Use it when you want to operate on every
	// adapter; use Daemon.Adapters for lightweight references only.
	adapters, err := client.AllAdapters(ctx)
	if err != nil {
		log.Fatal(err)
	}

	for _, adapter := range adapters {
		name, err := adapter.Name(ctx)
		if err != nil {
			log.Fatal(err)
		}
		powered, err := adapter.Powered(ctx)
		if err != nil {
			log.Fatal(err)
		}
		// Path is static identity and needs no D-Bus call.
		fmt.Printf("%s (%s) powered: %t\n", name, adapter.Path(), powered)
	}
}

func (*Client) AllBasicServiceSets added in v0.4.0

func (c *Client) AllBasicServiceSets(ctx context.Context) ([]*BasicServiceSet, error)

AllBasicServiceSets mints live BasicServiceSet handles for every BSS iwd currently exposes.

It enumerates BSSes via the daemon, then constructs a handle for each, preserving the daemon's enumeration order. Use BasicServiceSet to obtain a single BSS by path, or Daemon.BasicServiceSets for lightweight references without constructing handles.

Example

ExampleClient_AllBasicServiceSets constructs a handle for every basic service set iwd exposes and prints each one's address. A device typically sees many BSSes - one per access point/radio heard during a scan.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// AllBasicServiceSets enumerates via the daemon and returns a live handle per
	// BSS, in enumeration order. Use Daemon.BasicServiceSets for lightweight
	// references only.
	bsses, err := client.AllBasicServiceSets(ctx)
	if err != nil {
		log.Fatal(err)
	}

	for _, bss := range bsses {
		address, err := bss.Address(ctx)
		if err != nil {
			log.Fatal(err)
		}
		// Path is static identity and needs no D-Bus call.
		fmt.Printf("%s (%s)\n", address, bss.Path())
	}
}

func (*Client) AllDevices added in v0.3.0

func (c *Client) AllDevices(ctx context.Context) ([]*Device, error)

AllDevices mints live Device handles for every device iwd currently exposes.

It enumerates devices via the daemon, then constructs a handle for each, preserving the daemon's enumeration order. Use Device to obtain a single device by path, or Daemon.Devices for lightweight references without constructing handles.

func (*Client) AllKnownNetworks added in v0.5.0

func (c *Client) AllKnownNetworks(ctx context.Context) ([]*KnownNetwork, error)

AllKnownNetworks mints live KnownNetwork handles for every known network iwd currently exposes.

It enumerates known networks via the daemon, then constructs a handle for each, preserving the daemon's enumeration order. Use KnownNetwork to obtain a single known network by path, or Daemon.KnownNetworks for lightweight references without constructing handles.

func (*Client) AllNetworks added in v0.4.0

func (c *Client) AllNetworks(ctx context.Context) ([]*Network, error)

AllNetworks mints live Network handles for every network iwd currently exposes.

It enumerates networks via the daemon, then constructs a handle for each, preserving the daemon's enumeration order. Use Network to obtain a single network by path, or Daemon.Networks for lightweight references without constructing handles.

func (*Client) AllStations added in v0.7.0

func (c *Client) AllStations(ctx context.Context) ([]*Station, error)

AllStations mints live Station handles for every station iwd currently exposes.

It enumerates stations via the daemon, then constructs a handle for each, preserving the daemon's enumeration order. Use Station to obtain a single station by path, or Daemon.Stations for lightweight references without constructing handles.

func (*Client) BasicServiceSet added in v0.4.0

func (c *Client) BasicServiceSet(ctx context.Context, path string) (*BasicServiceSet, error)

BasicServiceSet creates a BasicServiceSet wrapper for a specific iwd BSS object path.

Use Daemon.BasicServiceSets to discover valid BSS paths.

Example

ExampleClient_BasicServiceSet discovers a basic service set (BSS) and reads its address. A BSS is a single access point/radio the device can see; iwd reports one per detected AP.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().BasicServiceSets(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no basic service sets found")
	}

	bss, err := client.BasicServiceSet(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	address, err := bss.Address(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(address)
}

func (*Client) Close

func (c *Client) Close() error

Close releases resources owned by the client.

Close is idempotent. After Close, Daemon returns nil and Adapter returns an invalid-state error.

func (*Client) Daemon

func (c *Client) Daemon() *Daemon

Daemon returns the singleton iwd daemon wrapper for this client.

Daemon returns nil after the client has been closed.

func (*Client) Device added in v0.3.0

func (c *Client) Device(ctx context.Context, path string) (*Device, error)

Device creates a Device wrapper for a specific iwd device object path.

Use Daemon.Devices to discover valid device paths.

Example

ExampleClient_Device discovers a device and reads its current status.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Devices(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no devices found")
	}

	device, err := client.Device(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	props, err := device.Properties(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s (%s) mode=%s powered=%t adapter=%s\n",
		props.Name, props.Address, props.Mode, props.Powered, props.Adapter)
}

func (*Client) KnownNetwork added in v0.5.0

func (c *Client) KnownNetwork(ctx context.Context, path string) (*KnownNetwork, error)

KnownNetwork creates a KnownNetwork wrapper for a specific iwd known-network object path.

Use Daemon.KnownNetworks to discover valid known-network paths.

Example

ExampleClient_KnownNetwork discovers a saved (known) network and reads its properties.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().KnownNetworks(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no known networks found")
	}

	known, err := client.KnownNetwork(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	props, err := known.Properties(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s type=%s autoConnect=%t\n", props.Name, props.Type, props.AutoConnect)
}

func (*Client) Network added in v0.4.0

func (c *Client) Network(ctx context.Context, path string) (*Network, error)

Network creates a Network wrapper for a specific iwd network object path.

Use Daemon.Networks to discover valid network paths.

Example

ExampleClient_Network discovers a network and reads its properties.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Networks(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no networks found")
	}

	network, err := client.Network(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	props, err := network.Properties(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s type=%s connected=%t\n", props.Name, props.Type, props.Connected)
}

func (*Client) RegisterAgent added in v0.6.0

func (c *Client) RegisterAgent(ctx context.Context, cfg AgentConfig) (*Agent, error)

RegisterAgent registers a credentials agent so iwd can request credentials when connecting to a secured network that is not already known. Without a registered agent, Network.Connect on such a network fails (ErrUnavailable, with iwd's ErrNoAgent in the chain).

At least one request callback in cfg must be set, or RegisterAgent returns an invalid-argument error. A Client owns a single agent: RegisterAgent returns an invalid-state error if one is already registered, so Unregister the previous agent first. The returned Agent is also unregistered automatically on Close.

Example

ExampleClient_RegisterAgent connects to a secured (PSK) network by registering a credentials agent that supplies the passphrase when iwd asks for it.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// iwd calls Passphrase only when it actually needs credentials (a secured
	// network that is not already known). networkPath identifies the network;
	// resolve it with client.Network if you need its details.
	agent, err := client.RegisterAgent(ctx, spiderw.AgentConfig{
		Passphrase: func(ctx context.Context, networkPath string) (string, error) {
			return lookupPassphraseFor(networkPath), nil
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = agent.Unregister(ctx) }()

	refs, err := client.Daemon().Networks(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no networks found")
	}

	network, err := client.Network(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	if err := network.Connect(ctx); err != nil {
		log.Fatal(err)
	}
	fmt.Println("connected")
}

// lookupPassphraseFor stands in for however an application supplies credentials
// (a keyring, a config file, an interactive prompt, ...). It is used by
// ExampleClient_RegisterAgent.
func lookupPassphraseFor(networkPath string) string {
	return networkPath + ": correct horse battery staple"
}

func (*Client) Station added in v0.7.0

func (c *Client) Station(ctx context.Context, path string) (*Station, error)

Station creates a Station wrapper for a specific iwd station object path.

A station shares its object with a device (a device in station mode), so path is a device object path. Use Daemon.Stations to discover valid station paths.

Example

ExampleClient_Station discovers a station (a device in station mode) and reads its read-only connection state. ConnectedNetwork is nil when the station is not connected.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	stations, err := client.AllStations(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(stations) == 0 {
		log.Fatal("no stations found")
	}

	station := stations[0]
	props, err := station.Properties(ctx)
	if err != nil {
		log.Fatal(err)
	}

	connected := "<none>"
	if props.ConnectedNetwork != nil {
		connected = props.ConnectedNetwork.Name // resolved SSID
	}
	fmt.Printf("%s: state=%s scanning=%t connected=%s\n",
		station.Path(), props.State, props.Scanning, connected)
}

type Daemon

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

Daemon provides high-level operations for the singleton iwd daemon object.

func (*Daemon) AccessPoints added in v0.13.0

func (d *Daemon) AccessPoints(ctx context.Context) ([]AccessPointRef, error)

AccessPoints returns lightweight references to the access points (devices in AP mode) currently exposed by iwd. Resolve one with Client.AccessPoint.

func (*Daemon) Adapters

func (d *Daemon) Adapters(ctx context.Context) ([]AdapterRef, error)

Adapters returns lightweight references to the adapters currently exposed by iwd.

Example

ExampleDaemon_Adapters lists the adapters iwd currently exposes.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Adapters(ctx)
	if err != nil {
		log.Fatal(err)
	}
	for _, ref := range refs {
		fmt.Printf("%s (%s)\n", ref.Name, ref.Path)
	}
}

func (*Daemon) BasicServiceSets added in v0.4.0

func (d *Daemon) BasicServiceSets(ctx context.Context) ([]BasicServiceSetRef, error)

BasicServiceSets returns lightweight references to the basic service sets currently exposed by iwd.

func (*Daemon) Devices added in v0.3.0

func (d *Daemon) Devices(ctx context.Context) ([]DeviceRef, error)

Devices returns lightweight references to the devices currently exposed by iwd.

func (*Daemon) Info

func (d *Daemon) Info(ctx context.Context) (*DaemonInfo, error)

Info returns the daemon metadata reported by iwd.

Example

ExampleDaemon_Info reads the iwd daemon metadata.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	info, err := client.Daemon().Info(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("version=%s stateDir=%s netConfig=%t\n",
		info.Version, info.StateDirectory, info.NetworkConfigurationEnabled)
}

func (*Daemon) KnownNetworks added in v0.5.0

func (d *Daemon) KnownNetworks(ctx context.Context) ([]KnownNetworkRef, error)

KnownNetworks returns lightweight references to the known networks currently exposed by iwd.

func (*Daemon) NetworkConfigurationEnabled

func (d *Daemon) NetworkConfigurationEnabled(ctx context.Context) (bool, error)

NetworkConfigurationEnabled reports whether iwd manages network configuration.

func (*Daemon) Networks added in v0.4.0

func (d *Daemon) Networks(ctx context.Context) ([]NetworkRef, error)

Networks returns lightweight references to the networks currently exposed by iwd.

func (*Daemon) StateDirectory

func (d *Daemon) StateDirectory(ctx context.Context) (string, error)

StateDirectory returns the daemon's persistent state directory.

func (*Daemon) Stations added in v0.7.0

func (d *Daemon) Stations(ctx context.Context) ([]StationRef, error)

Stations returns lightweight references to the stations (station-mode devices) currently exposed by iwd. Resolve one with Client.Station.

func (*Daemon) Version

func (d *Daemon) Version(ctx context.Context) (string, error)

Version returns the iwd daemon version.

type DaemonInfo

type DaemonInfo struct {
	// Version is the iwd daemon version string.
	Version string

	// StateDirectory is the daemon's persistent state directory.
	StateDirectory string

	// NetworkConfigurationEnabled reports whether iwd manages network configuration.
	NetworkConfigurationEnabled bool
}

DaemonInfo is the public API view of the iwd daemon metadata.

This intentionally mirrors core.DaemonInfo but is separate to avoid leaking internal types into the API surface. Future evolution of the internal/core types will not affect public clients.

func (*DaemonInfo) String

func (d *DaemonInfo) String() string

String returns a human-readable multiline representation of the daemon info.

type Device added in v0.3.0

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

Device provides high-level operations for a specific iwd device object.

func (*Device) Adapter added in v0.3.0

func (d *Device) Adapter(ctx context.Context) (string, error)

Adapter returns the object path of the adapter that owns this device.

Resolve it to a handle with Client.Adapter.

func (*Device) Address added in v0.3.0

func (d *Device) Address(ctx context.Context) (string, error)

Address returns the device's hardware (MAC) address.

func (*Device) Mode added in v0.3.0

func (d *Device) Mode(ctx context.Context) (Mode, error)

Mode returns the device's current operating mode.

func (*Device) Name added in v0.3.0

func (d *Device) Name(ctx context.Context) (string, error)

Name returns the device name.

func (*Device) Path added in v0.3.0

func (d *Device) Path() string

Path returns the D-Bus object path the device was constructed from.

Path is static device identity, not an iwd property: it requires no D-Bus round-trip and never fails. Path returns "" for a nil receiver.

func (*Device) Powered added in v0.3.0

func (d *Device) Powered(ctx context.Context) (bool, error)

Powered reports whether the device is currently powered.

func (*Device) Properties added in v0.3.0

func (d *Device) Properties(ctx context.Context) (*DeviceProperties, error)

Properties reads every device property in a single D-Bus call (Properties.GetAll) instead of one call per property. Prefer it when you need several properties at once, such as building an overview of a device.

func (*Device) SetMode added in v0.3.0

func (d *Device) SetMode(ctx context.Context, mode Mode) error

SetMode changes the device's operating mode. An unrecognized mode is rejected at the public boundary as an invalid argument.

func (*Device) SetPowered added in v0.3.0

func (d *Device) SetPowered(ctx context.Context, powered bool) error

SetPowered changes whether the device is powered.

func (*Device) SubscribeModeChanged added in v0.3.0

func (d *Device) SubscribeModeChanged(ctx context.Context, fn func(Mode)) (UnsubscribeFunc, error)

SubscribeModeChanged registers fn for device operating-mode changes and returns a handle that unregisters the callback.

func (*Device) SubscribePoweredChanged added in v0.3.0

func (d *Device) SubscribePoweredChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribePoweredChanged registers fn for device powered-state changes and returns a handle that unregisters the callback.

func (*Device) SubscribePropertiesChanged added in v0.3.0

func (d *Device) SubscribePropertiesChanged(ctx context.Context, fn func(DevicePropertiesChanged)) (UnsubscribeFunc, error)

SubscribePropertiesChanged registers fn for device property-change signals and returns a handle that unregisters the callback.

type DeviceProperties added in v0.3.0

type DeviceProperties struct {
	// Name is the device's human-friendly Name property.
	Name string

	// Address is the device's hardware (MAC) address.
	Address string

	// Powered reports whether the device is currently powered.
	Powered bool

	// Mode is the device's current operating mode.
	Mode Mode

	// Adapter references the adapter that owns this device (Path + resolved Name).
	Adapter AdapterRef
}

DeviceProperties is a snapshot of all device properties read in a single D-Bus call. iwd reports all of these for every device.

type DevicePropertiesChanged added in v0.3.0

type DevicePropertiesChanged struct {
	// Changed contains new property values keyed by property name.
	Changed map[string]any

	// Invalidated contains property names whose values should be re-read if needed.
	Invalidated []string
}

DevicePropertiesChanged describes device properties reported by a D-Bus PropertiesChanged signal. Changed contains the new values by property name; Invalidated contains property names whose values should be re-read if needed.

type DeviceRef added in v0.3.0

type DeviceRef struct {
	// Path is the canonical D-Bus object path for the device.
	Path string

	// Name is the device's human-friendly Name property.
	Name string
}

DeviceRef is a lightweight reference to a device discovered by the iwd daemon.

type Error

type Error struct {
	Kind     Kind     // stable API category
	Resource Resource // public object/subsystem involved, when known
	Op       string   // public-facing operation name (for example, "Daemon.Version")
	Details  string   // optional human-friendly text
	Err      error    // wrapped core.Error or raw error
}

Error is the structured error type returned by the public API.

Underlying core and D-Bus errors remain discoverable via errors.Is, errors.As, and errors.AsType.

Example:

v, err := client.Daemon().Version(ctx)
if errors.Is(err, spiderw.ErrUnavailable) { ... }

func (*Error) Error

func (e *Error) Error() string

Error returns a human-readable public API error string.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap exposes:

  • ErrSpiderw (public indication this came from spiderw)
  • the sentinel for this Kind
  • the underlying wrapped error

type HiddenAccessPoint added in v0.9.0

type HiddenAccessPoint struct {
	// Address is the BSS hardware (BSSID) address.
	Address string

	// SignalStrength is the signal strength in dBm (e.g. -60.5). iwd reports it in
	// units of 100 * dBm; spiderw exposes it as dBm here.
	SignalStrength float64

	// Type is the network security type.
	Type NetworkType
}

HiddenAccessPoint is one hidden access point found in the last scan, as returned by HiddenAccessPoints.

type Kind

type Kind string

Kind identifies a stable public spiderw error category.

const (
	// KindUnavailable indicates that the requested resource or subsystem could
	// not be reached or did not expose the expected API.
	KindUnavailable Kind = Kind(failure.KindUnavailable)

	// KindInvalidState indicates that spiderw observed an invalid or
	// inconsistent state from iwd or its own wrappers.
	KindInvalidState Kind = Kind(failure.KindInvalidState)

	// KindInvalidArgument indicates that a caller supplied an invalid argument
	// to the public API.
	KindInvalidArgument Kind = Kind(failure.KindInvalidArgument)

	// KindInternal indicates an uncategorized internal spiderw failure.
	KindInternal Kind = Kind(failure.KindInternal)
)

Kind constants are stable public error categories.

type KnownNetwork added in v0.5.0

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

KnownNetwork provides high-level operations for a specific iwd known-network object.

A known network is one iwd has stored configuration for (a previously connected or provisioned network).

func (*KnownNetwork) AutoConnect added in v0.5.0

func (k *KnownNetwork) AutoConnect(ctx context.Context) (bool, error)

AutoConnect reports whether the known network is a candidate for automatic connection.

func (*KnownNetwork) Forget added in v0.5.0

func (k *KnownNetwork) Forget(ctx context.Context) error

Forget removes the known network from iwd, disconnecting it first if currently connected.

func (*KnownNetwork) Hidden added in v0.5.0

func (k *KnownNetwork) Hidden(ctx context.Context) (bool, error)

Hidden reports whether the known network is hidden.

func (*KnownNetwork) LastConnectedTime added in v0.5.0

func (k *KnownNetwork) LastConnectedTime(ctx context.Context) (*string, error)

LastConnectedTime returns the ISO 8601 timestamp of the last successful connection, or nil when the network has never been connected to.

func (*KnownNetwork) Name added in v0.5.0

func (k *KnownNetwork) Name(ctx context.Context) (string, error)

Name returns the known network's name (usually the SSID).

func (*KnownNetwork) Path added in v0.5.0

func (k *KnownNetwork) Path() string

Path returns the D-Bus object path the known network was constructed from.

Path is static object identity, not an iwd property: it requires no D-Bus round-trip and never fails. Path returns "" for a nil receiver.

func (*KnownNetwork) Properties added in v0.5.0

func (k *KnownNetwork) Properties(ctx context.Context) (*KnownNetworkProperties, error)

Properties reads every known-network property in a single D-Bus call (Properties.GetAll) instead of one call per property.

func (*KnownNetwork) SetAutoConnect added in v0.5.0

func (k *KnownNetwork) SetAutoConnect(ctx context.Context, autoConnect bool) error

SetAutoConnect changes whether the known network is a candidate for automatic connection.

Example

ExampleKnownNetwork_SetAutoConnect disables automatic connection for a saved network without forgetting it.

package main

import (
	"context"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().KnownNetworks(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no known networks found")
	}

	known, err := client.KnownNetwork(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	if err := known.SetAutoConnect(ctx, false); err != nil {
		log.Fatal(err)
	}
	// Use known.Forget(ctx) to remove the saved network entirely.
}

func (*KnownNetwork) SubscribeAutoConnectChanged added in v0.5.0

func (k *KnownNetwork) SubscribeAutoConnectChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribeAutoConnectChanged registers fn for known-network auto-connect changes and returns a handle that unregisters the callback.

func (*KnownNetwork) SubscribeHiddenChanged added in v0.13.0

func (k *KnownNetwork) SubscribeHiddenChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribeHiddenChanged registers fn for changes to the Hidden property.

func (*KnownNetwork) SubscribeLastConnectedTimeChanged added in v0.13.0

func (k *KnownNetwork) SubscribeLastConnectedTimeChanged(ctx context.Context, fn func(*string)) (UnsubscribeFunc, error)

SubscribeLastConnectedTimeChanged registers fn for changes to LastConnectedTime, an ISO 8601 timestamp. iwd updates it on each successful connection, so this fires once per connect to the network.

func (*KnownNetwork) SubscribePropertiesChanged added in v0.5.0

func (k *KnownNetwork) SubscribePropertiesChanged(ctx context.Context, fn func(KnownNetworkPropertiesChanged)) (UnsubscribeFunc, error)

SubscribePropertiesChanged registers fn for known-network property-change signals and returns a handle that unregisters the callback.

func (*KnownNetwork) Type added in v0.5.0

func (k *KnownNetwork) Type(ctx context.Context) (NetworkType, error)

Type returns the known network's type.

type KnownNetworkProperties added in v0.5.0

type KnownNetworkProperties struct {
	// Name is the known network's name (usually the SSID).
	Name string

	// Type is the known network's type.
	Type NetworkType

	// Hidden reports whether the network is hidden.
	Hidden bool

	// LastConnectedTime is the ISO 8601 timestamp of the last successful
	// connection, or nil when the network has never been connected to.
	LastConnectedTime *string

	// AutoConnect reports whether the network is a candidate for automatic
	// connection.
	AutoConnect bool
}

KnownNetworkProperties is a snapshot of all known-network properties read in a single D-Bus call. LastConnectedTime is nil when the network has never been successfully connected to.

type KnownNetworkPropertiesChanged added in v0.5.0

type KnownNetworkPropertiesChanged struct {
	// Changed contains new property values keyed by property name.
	Changed map[string]any

	// Invalidated contains property names whose values should be re-read if needed.
	Invalidated []string
}

KnownNetworkPropertiesChanged describes known-network properties reported by a D-Bus PropertiesChanged signal. Changed contains the new values by property name; Invalidated contains property names whose values should be re-read if needed.

type KnownNetworkRef added in v0.5.0

type KnownNetworkRef struct {
	// Path is the canonical D-Bus object path for the known network.
	Path string

	// Name is the known network's name (usually the SSID).
	Name string
}

KnownNetworkRef is a lightweight reference to a known network discovered by the iwd daemon.

type Mode added in v0.3.0

type Mode string

Mode identifies an iwd operating mode exposed by spiderw.

const (
	// ModeUnknown represents an invalid or unrecognized mode.
	ModeUnknown Mode = Mode(iwdvalue.ModeUnknown)

	// ModeStation is the iwd station mode.
	ModeStation Mode = Mode(iwdvalue.ModeStation)

	// ModeAP is the iwd access point mode.
	ModeAP Mode = Mode(iwdvalue.ModeAP)

	// ModeAdHoc is the iwd ad-hoc mode.
	ModeAdHoc Mode = Mode(iwdvalue.ModeAdHoc)
)

Mode constants identify the supported iwd modes. ModeUnknown is reserved for invalid or unrecognized values.

func ParseMode added in v0.3.0

func ParseMode(s string) (Mode, error)

ParseMode converts a canonical iwd mode string to an Mode.

func (Mode) String added in v0.3.0

func (m Mode) String() string

String returns the canonical iwd string for the mode.

type Network added in v0.4.0

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

Network provides high-level operations for a specific iwd network object.

A network represents an SSID the owning device can see. Its ExtendedServiceSet lists the basic service sets (access points) that serve it.

func (*Network) Connect added in v0.4.0

func (n *Network) Connect(ctx context.Context) error

Connect requests that the owning device connect to this network.

Open networks and networks iwd already knows connect without a credentials agent. Connecting to a secured network that is not already known fails with an error matching ErrNoAgent until an agent is registered to supply credentials.

Example

ExampleNetwork_Connect connects to a network. Open and already-known networks connect without a credentials agent; a not-yet-known secured network fails with an error matching spiderw.ErrNoAgent.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Networks(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no networks found")
	}

	network, err := client.Network(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	switch err := network.Connect(ctx); {
	case err == nil:
		fmt.Println("connected")
	case errors.Is(err, spiderw.ErrNoAgent):
		// Connecting to this secured network needs a credentials agent.
		fmt.Println("a credentials agent is required to connect to this network")
	default:
		log.Fatal(err)
	}
}

func (*Network) Connected added in v0.4.0

func (n *Network) Connected(ctx context.Context) (bool, error)

Connected reports whether the network is currently connected or connecting.

func (*Network) Device added in v0.4.0

func (n *Network) Device(ctx context.Context) (string, error)

Device returns the object path of the device/station the network belongs to.

Resolve it to a handle with Client.Device.

func (*Network) ExtendedServiceSet added in v0.4.0

func (n *Network) ExtendedServiceSet(ctx context.Context) ([]string, error)

ExtendedServiceSet returns the object paths of the basic service sets (BSSes) that make up this network. Resolve each with Client.BasicServiceSet.

Example

ExampleNetwork_ExtendedServiceSet lists the basic service sets (access points) that make up a network and resolves each path to a live BasicServiceSet handle.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	refs, err := client.Daemon().Networks(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no networks found")
	}

	network, err := client.Network(ctx, refs[0].Path)
	if err != nil {
		log.Fatal(err)
	}

	// ExtendedServiceSet returns BSS object paths; resolve each with
	// Client.BasicServiceSet. A single network may be served by several BSSes
	// (for example a 2.4 GHz and a 5 GHz radio).
	paths, err := network.ExtendedServiceSet(ctx)
	if err != nil {
		log.Fatal(err)
	}
	for _, path := range paths {
		bss, err := client.BasicServiceSet(ctx, path)
		if err != nil {
			log.Fatal(err)
		}
		address, err := bss.Address(ctx)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(address)
	}
}

func (*Network) KnownNetwork added in v0.4.0

func (n *Network) KnownNetwork(ctx context.Context) (*string, error)

KnownNetwork returns the object path of the network's known-network record, or nil when the network is not known/provisioned.

Resolve it to a handle with Client.KnownNetwork.

func (*Network) Name added in v0.4.0

func (n *Network) Name(ctx context.Context) (string, error)

Name returns the network SSID.

func (*Network) Path added in v0.4.0

func (n *Network) Path() string

Path returns the D-Bus object path the network was constructed from.

Path is static object identity, not an iwd property: it requires no D-Bus round-trip and never fails. Path returns "" for a nil receiver.

func (*Network) Properties added in v0.4.0

func (n *Network) Properties(ctx context.Context) (*NetworkProperties, error)

Properties reads every network property in a single D-Bus call (Properties.GetAll) instead of one call per property.

func (*Network) SubscribeConnectedChanged added in v0.4.0

func (n *Network) SubscribeConnectedChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribeConnectedChanged registers fn for network connected-state changes and returns a handle that unregisters the callback.

func (*Network) SubscribeExtendedServiceSetChanged added in v0.13.0

func (n *Network) SubscribeExtendedServiceSetChanged(ctx context.Context, fn func([]string)) (UnsubscribeFunc, error)

SubscribeExtendedServiceSetChanged registers fn for changes to the network's BSS list. fn receives the BSS object paths, which change as access points for the network come and go across scans.

func (*Network) SubscribeKnownNetworkChanged added in v0.13.0

func (n *Network) SubscribeKnownNetworkChanged(ctx context.Context, fn func(*string)) (UnsubscribeFunc, error)

SubscribeKnownNetworkChanged registers fn for changes to the network's known-network association. fn receives the known-network object path, or nil when the network is not known.

This is how a network being saved or forgotten is observed: provisioning gives the network a known-network record, and forgetting it takes it away.

func (*Network) SubscribePropertiesChanged added in v0.4.0

func (n *Network) SubscribePropertiesChanged(ctx context.Context, fn func(NetworkPropertiesChanged)) (UnsubscribeFunc, error)

SubscribePropertiesChanged registers fn for network property-change signals and returns a handle that unregisters the callback.

func (*Network) Type added in v0.4.0

func (n *Network) Type(ctx context.Context) (NetworkType, error)

Type returns the network's network type.

type NetworkProperties added in v0.4.0

type NetworkProperties struct {
	// Name is the network's SSID.
	Name string

	// Connected reports whether the network is currently connected or connecting.
	Connected bool

	// Device references the device/station the network belongs to (Path + resolved
	// Name).
	Device DeviceRef

	// Type is the network's network type.
	Type NetworkType

	// KnownNetwork is the object path of the network's known-network record, or
	// nil when the network is not known/provisioned. Unlike the other bundle
	// cross-references this stays a bare path: a known network's Name is always
	// this network's own SSID, so resolving it would be redundant. Resolve it to a
	// handle with Client.KnownNetwork.
	KnownNetwork *string

	// ExtendedServiceSet references the basic service sets (BSSes) that make up
	// this network (Path + resolved Address).
	ExtendedServiceSet []BasicServiceSetRef
}

NetworkProperties is a snapshot of all network properties read in a single D-Bus call. KnownNetwork is nil when the network has no known-network record.

type NetworkPropertiesChanged added in v0.4.0

type NetworkPropertiesChanged struct {
	// Changed contains new property values keyed by property name.
	Changed map[string]any

	// Invalidated contains property names whose values should be re-read if needed.
	Invalidated []string
}

NetworkPropertiesChanged describes network properties reported by a D-Bus PropertiesChanged signal. Changed contains the new values by property name; Invalidated contains property names whose values should be re-read if needed.

type NetworkRef added in v0.4.0

type NetworkRef struct {
	// Path is the canonical D-Bus object path for the network.
	Path string

	// Name is the network's SSID.
	Name string
}

NetworkRef is a lightweight reference to a network discovered by the iwd daemon.

type NetworkType added in v0.5.0

type NetworkType string

NetworkType identifies the network type of an iwd network.

const (
	// NetworkTypeUnknown represents an invalid or unrecognized network type.
	NetworkTypeUnknown NetworkType = NetworkType(iwdvalue.NetworkTypeUnknown)

	// NetworkTypeOpen is an open (unsecured) network.
	NetworkTypeOpen NetworkType = NetworkType(iwdvalue.NetworkTypeOpen)

	// NetworkTypeWEP is a WEP network.
	NetworkTypeWEP NetworkType = NetworkType(iwdvalue.NetworkTypeWEP)

	// NetworkTypePSK is a pre-shared-key (WPA-Personal) network.
	NetworkTypePSK NetworkType = NetworkType(iwdvalue.NetworkTypePSK)

	// NetworkType8021x is an 802.1x (EAP / WPA-Enterprise) network.
	NetworkType8021x NetworkType = NetworkType(iwdvalue.NetworkType8021x)

	// NetworkTypeHotspot is a hotspot network (reported only for a KnownNetwork).
	NetworkTypeHotspot NetworkType = NetworkType(iwdvalue.NetworkTypeHotspot)
)

NetworkType constants identify the supported iwd network types. NetworkTypeUnknown is reserved for invalid or unrecognized values.

func (NetworkType) String added in v0.5.0

func (s NetworkType) String() string

String returns the canonical iwd string for the network type.

type OrderedNetwork added in v0.8.0

type OrderedNetwork struct {
	NetworkRef

	// SignalStrength is the signal strength in dBm (e.g. -60.5). iwd reports it in
	// units of 100 * dBm; spiderw exposes it as dBm here.
	SignalStrength float64
}

OrderedNetwork is one scanned network and its signal strength, as returned by OrderedNetworks. It embeds NetworkRef, so Path is the network object path and Name is its resolved SSID.

type Resource

type Resource string

Resource identifies which public spiderw object or subsystem an error applies to.

const (
	// ResourceUnknown indicates that no specific resource is known.
	ResourceUnknown Resource = Resource(failure.ResourceUnknown)

	// ResourceClient identifies client-level failures.
	ResourceClient Resource = Resource(failure.ResourceClient)

	// ResourceDaemon identifies failures involving the iwd daemon object.
	ResourceDaemon Resource = Resource(failure.ResourceDaemon)

	// ResourceAdapter identifies failures involving an iwd adapter object.
	ResourceAdapter Resource = Resource(failure.ResourceAdapter)

	// ResourceDevice identifies failures involving an iwd device object.
	ResourceDevice Resource = Resource(failure.ResourceDevice)

	// ResourceBasicServiceSet identifies failures involving an iwd basic service
	// set (BSS) object.
	ResourceBasicServiceSet Resource = Resource(failure.ResourceBasicServiceSet)

	// ResourceStation identifies failures involving an iwd station object.
	ResourceStation Resource = Resource(failure.ResourceStation)

	// ResourceSimpleConfiguration identifies failures involving iwd's WSC (Wi-Fi
	// Simple Configuration / WPS) interface, reached via Station.SimpleConfiguration.
	ResourceSimpleConfiguration Resource = Resource(failure.ResourceSimpleConfiguration)

	// ResourceNetwork identifies failures involving an iwd network object.
	ResourceNetwork Resource = Resource(failure.ResourceNetwork)

	// ResourceKnownNetwork identifies failures involving an iwd known-network
	// object.
	ResourceKnownNetwork Resource = Resource(failure.ResourceKnownNetwork)

	// ResourceAgent identifies failures involving the iwd credentials agent or
	// agent manager.
	ResourceAgent Resource = Resource(failure.ResourceAgent)

	// ResourceAccessPoint identifies failures involving an iwd access point (a
	// device running in AP mode).
	ResourceAccessPoint Resource = Resource(failure.ResourceAccessPoint)
)

Resource constants classify public errors by target object/subsystem.

type SignalLevelAgent added in v0.11.0

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

SignalLevelAgent is a handle to an active signal-level monitor registered on a station. Call Unregister to stop monitoring and release it.

func (*SignalLevelAgent) Unregister added in v0.11.0

func (a *SignalLevelAgent) Unregister(ctx context.Context) error

Unregister stops the monitor: it unregisters the agent from iwd and removes the exported object. It is idempotent.

type SignalLevelConfig added in v0.11.0

type SignalLevelConfig struct {
	// Thresholds are RSSI levels in dBm that trigger Changed when crossed. They
	// must be non-empty and in strictly descending order (for example
	// []int{-60, -70, -80}). Required.
	Thresholds []int

	// Changed is called with the signal band index each time the connected
	// network's RSSI crosses a threshold. N thresholds define N+1 bands, so level
	// ranges over [0, N]: 0 is the strongest band (above the first threshold) and
	// N is the weakest (below the last). Required.
	//
	// The band is derived entirely by iwd from its own RSSI measurement, which is
	// averaged and driver-dependent. It will not match an instantaneous reading
	// such as "iw dev link" exactly: transitions can occur several dBm away from
	// the nominal thresholds, more so while the signal is actively changing. iwd
	// reports a band only when the index changes, so a band the signal passes
	// through quickly may be skipped, and some drivers (notably brcmfmac) support
	// only coarse threshold monitoring. Treat level as a coarse, hysteresis-
	// smoothed indicator rather than an exact dBm boundary.
	Changed func(level int)

	// Released is called when iwd releases the agent (the monitor was
	// unregistered or the station went away). Optional.
	Released func()
}

SignalLevelConfig configures signal-strength monitoring for a station. iwd invokes Changed whenever the connected network's RSSI crosses one of the configured thresholds.

type SimpleConfiguration added in v0.12.0

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

SimpleConfiguration is a handle to a station's WSC (Wi-Fi Simple Configuration, formerly WPS) enrollment interface, obtained from Station.SimpleConfiguration. It joins the station to an access point without a passphrase, via either PushButton (PBC) or a PIN.

func (*SimpleConfiguration) Cancel added in v0.12.0

func (c *SimpleConfiguration) Cancel(ctx context.Context) error

Cancel aborts an in-progress PushButton or StartPin enrollment.

func (*SimpleConfiguration) GeneratePin added in v0.12.0

func (c *SimpleConfiguration) GeneratePin(ctx context.Context) (string, error)

GeneratePin returns a fresh 8-digit WSC PIN (with a valid check digit) to enter at the access point's registrar, for use with StartPin.

func (*SimpleConfiguration) PushButton added in v0.12.0

func (c *SimpleConfiguration) PushButton(ctx context.Context) error

PushButton starts WSC enrollment in PushButton (PBC) mode: press the WPS button on the access point, then call this within its walk window. It blocks until iwd reports the outcome, so pass a context with a deadline. If more than one access point is in PushButton mode the target is ambiguous and iwd returns an error matching ErrWSCSessionOverlap.

func (*SimpleConfiguration) StartPin added in v0.12.0

func (c *SimpleConfiguration) StartPin(ctx context.Context, pin string) error

StartPin starts WSC enrollment in PIN mode using pin (typically one from GeneratePin, entered at the access point's registrar). Spaces and hyphens are ignored; the PIN must be 4 or 8 digits, and iwd validates the 8-digit check digit (surfaced as an error matching ErrInvalidFormat). It blocks until iwd reports the outcome.

type Station added in v0.7.0

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

Station provides high-level operations for a specific iwd station object.

A station is a device operating in station (client) mode; it shares its object path with the Device. Station covers connection state and scanning; connecting to a network is done through Network.Connect.

func (*Station) Affinities added in v0.7.0

func (s *Station) Affinities(ctx context.Context) ([]string, error)

Affinities returns the object paths of the BSSes the station has a roaming affinity for, or nil when unreported. iwd marks this property experimental.

func (*Station) ConnectHiddenNetwork added in v0.9.0

func (s *Station) ConnectHiddenNetwork(ctx context.Context, name string) error

ConnectHiddenNetwork connects to a hidden network by SSID. A secured hidden network requires a registered credentials agent (register one with Client.RegisterAgent before calling); without one, iwd surfaces an error matching ErrNoAgent.

Example

ExampleStation_ConnectHiddenNetwork connects to a secured hidden network. iwd invokes the registered agent's Passphrase callback for the credentials, so register an agent before connecting.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// Supply the passphrase for a secured hidden network via a credentials agent.
	agent, err := client.RegisterAgent(ctx, spiderw.AgentConfig{
		Passphrase: func(ctx context.Context, networkPath string) (string, error) {
			return "hunter2", nil
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = agent.Unregister(ctx) }()

	stations, err := client.AllStations(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(stations) == 0 {
		log.Fatal("no stations found")
	}

	if err := stations[0].ConnectHiddenNetwork(ctx, "MyHiddenSSID"); err != nil {
		log.Fatal(err)
	}
	fmt.Println("connected")
}

func (*Station) ConnectedAccessPoint added in v0.7.0

func (s *Station) ConnectedAccessPoint(ctx context.Context) (*string, error)

ConnectedAccessPoint returns the object path of the BSS the station is connected to, or nil when disconnected or unreported.

Resolve it to a handle with Client.BasicServiceSet. iwd marks this property experimental.

func (*Station) ConnectedNetwork added in v0.7.0

func (s *Station) ConnectedNetwork(ctx context.Context) (*string, error)

ConnectedNetwork returns the object path of the network the station is connected to, or nil when the station is not connected.

Resolve it to a handle with Client.Network.

func (*Station) Disconnect added in v0.9.0

func (s *Station) Disconnect(ctx context.Context) error

Disconnect disconnects the station from its current network.

func (*Station) HiddenAccessPoints added in v0.9.0

func (s *Station) HiddenAccessPoints(ctx context.Context) ([]HiddenAccessPoint, error)

HiddenAccessPoints returns the hidden access points found in the most recent scan. It is an experimental iwd operation: hardware that cannot provide it makes iwd reject the call, and the returned error matches ErrNotSupported via errors.Is.

func (*Station) MonitorSignalLevel added in v0.11.0

func (s *Station) MonitorSignalLevel(ctx context.Context, cfg SignalLevelConfig) (*SignalLevelAgent, error)

MonitorSignalLevel starts monitoring the station's connected-network signal strength, invoking cfg.Changed whenever the RSSI crosses one of cfg.Thresholds (dBm, strictly descending). It returns a handle whose Unregister stops monitoring. iwd supports a single signal-level monitor per station.

func (*Station) Name added in v0.10.0

func (s *Station) Name() string

Name returns the station's human-friendly name - the Name of the device it shares an object with (e.g. "wlan0"). A station has no Name property of its own, so this is resolved when the station is constructed (best-effort) and may be "" if it could not be resolved or for a nil receiver. Like Path, it is cached identity: no D-Bus round-trip and never fails.

func (*Station) OrderedNetworks added in v0.8.0

func (s *Station) OrderedNetworks(ctx context.Context) ([]OrderedNetwork, error)

OrderedNetworks returns the networks from the most recent scan, ordered by iwd with the strongest signal first. No scan is required to read the last results.

func (*Station) Path added in v0.7.0

func (s *Station) Path() string

Path returns the D-Bus object path the station was constructed from.

Path is static station identity, not an iwd property: it requires no D-Bus round-trip and never fails. Path returns "" for a nil receiver.

func (*Station) Properties added in v0.7.0

func (s *Station) Properties(ctx context.Context) (*StationProperties, error)

Properties reads every station property in a single D-Bus call (Properties.GetAll) instead of one call per property. Prefer it when you need several properties at once, such as building an overview of a station.

func (*Station) Scan added in v0.8.0

func (s *Station) Scan(ctx context.Context) error

Scan schedules a network scan on the station. It is asynchronous: the call returns once the scan is scheduled, and the station's Scanning property tracks progress. Subscribe with SubscribeScanningChanged to observe completion, then read results with OrderedNetworks.

Example

ExampleStation_Scan triggers a scan and lists the resulting networks by signal strength. Scan is asynchronous; subscribe to Scanning (or poll it) to know when results are ready. This example reads the last results immediately.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chrispypip/spiderw"
)

func main() {
	ctx := context.Background()

	client, err := spiderw.NewClient(ctx, spiderw.SystemBus)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	stations, err := client.AllStations(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if len(stations) == 0 {
		log.Fatal("no stations found")
	}
	station := stations[0]

	if err := station.Scan(ctx); err != nil {
		log.Fatal(err)
	}

	networks, err := station.OrderedNetworks(ctx)
	if err != nil {
		log.Fatal(err)
	}
	for _, n := range networks {
		fmt.Printf("%s: %.0f dBm\n", n.Name, n.SignalStrength) // n.Name is the SSID
	}
}

func (*Station) Scanning added in v0.7.0

func (s *Station) Scanning(ctx context.Context) (bool, error)

Scanning reports whether the station is currently scanning for networks.

func (*Station) SetAffinities added in v0.8.0

func (s *Station) SetAffinities(ctx context.Context, paths []string) error

SetAffinities sets the BSS object paths the station should stay affine to (an experimental iwd property). Each path must be a non-empty absolute object path, and should be a BSS of the currently connected network (see Network.ExtendedServiceSet). Passing an empty slice clears all affinities.

Affinities depends on driver support: on hardware that cannot honor it, iwd rejects the write and the returned error matches ErrNotSupported via errors.Is.

func (*Station) SimpleConfiguration added in v0.12.0

func (s *Station) SimpleConfiguration(ctx context.Context) (*SimpleConfiguration, error)

SimpleConfiguration returns a handle to the station's WSC (WPS) enrollment interface, for joining an access point without a passphrase via PushButton or PIN. It is available only when the device is in station mode and the driver supports WSC.

func (*Station) State added in v0.7.0

func (s *Station) State(ctx context.Context) (StationState, error)

State returns the station's current connection state.

func (*Station) SubscribeAffinitiesChanged added in v0.13.0

func (s *Station) SubscribeAffinitiesChanged(ctx context.Context, fn func([]string)) (UnsubscribeFunc, error)

SubscribeAffinitiesChanged registers fn for changes to the station's roaming affinities. Affinities are writable, so they can change without this process doing anything: another client may set them, or iwd may clear them. This is the only way to observe that.

func (*Station) SubscribeConnectedAccessPointChanged added in v0.13.0

func (s *Station) SubscribeConnectedAccessPointChanged(ctx context.Context, fn func(*string)) (UnsubscribeFunc, error)

SubscribeConnectedAccessPointChanged registers fn for changes to the BSS the station is associated with. fn receives the BSS object path, or nil when not associated.

This is how a roam is observed: the station moves between access points of the same network, so the BSS changes while State stays StationStateConnected and the connected network does not change at all.

func (*Station) SubscribeConnectedNetworkChanged added in v0.13.0

func (s *Station) SubscribeConnectedNetworkChanged(ctx context.Context, fn func(*string)) (UnsubscribeFunc, error)

SubscribeConnectedNetworkChanged registers fn for changes to the network the station is connected to. fn receives the network's object path, or nil when the station is not connected to one.

func (*Station) SubscribePropertiesChanged added in v0.7.0

func (s *Station) SubscribePropertiesChanged(ctx context.Context, fn func(StationPropertiesChanged)) (UnsubscribeFunc, error)

SubscribePropertiesChanged registers fn for station property-change signals and returns a handle that unregisters the callback.

func (*Station) SubscribeScanningChanged added in v0.7.0

func (s *Station) SubscribeScanningChanged(ctx context.Context, fn func(bool)) (UnsubscribeFunc, error)

SubscribeScanningChanged registers fn for station scanning-state changes and returns a handle that unregisters the callback.

func (*Station) SubscribeStateChanged added in v0.7.0

func (s *Station) SubscribeStateChanged(ctx context.Context, fn func(StationState)) (UnsubscribeFunc, error)

SubscribeStateChanged registers fn for station connection-state changes and returns a handle that unregisters the callback.

type StationProperties added in v0.7.0

type StationProperties struct {
	// State is the station's current connection state.
	State StationState

	// Scanning reports whether the station is currently scanning.
	Scanning bool

	// ConnectedNetwork references the network the station is connected to (Path +
	// resolved SSID Name), or nil when not connected.
	ConnectedNetwork *NetworkRef

	// ConnectedAccessPoint references the BSS the station is connected to (Path +
	// resolved Address), or nil when disconnected or unreported. iwd marks this
	// property experimental.
	ConnectedAccessPoint *BasicServiceSetRef

	// Affinities references the BSSes the station has a roaming affinity for (Path
	// + resolved Address), or nil when unreported. iwd marks this property
	// experimental.
	Affinities []BasicServiceSetRef
}

StationProperties is a snapshot of all station properties read in a single D-Bus call. State and Scanning are always reported; the remaining fields are nil when absent.

type StationPropertiesChanged added in v0.7.0

type StationPropertiesChanged struct {
	// Changed contains new property values keyed by property name.
	Changed map[string]any

	// Invalidated contains property names whose values should be re-read if needed.
	Invalidated []string
}

StationPropertiesChanged describes station properties reported by a D-Bus PropertiesChanged signal. Changed contains the new values by property name; Invalidated contains property names whose values should be re-read if needed.

type StationRef added in v0.7.0

type StationRef struct {
	// Path is the canonical D-Bus object path for the station (a device path).
	Path string

	// Name is the co-located device's Name (best-effort; empty if unavailable).
	Name string
}

StationRef is a lightweight reference to a station discovered by the iwd daemon. A station shares its object with a device and has no Name of its own, so Name is the co-located device's Name (e.g. "wlan0"), resolved best-effort. Resolve the handle with Client.Station.

type StationState added in v0.7.0

type StationState string

StationState identifies an iwd station's connection state exposed by spiderw.

const (
	// StationStateUnknown represents an invalid or unrecognized station state.
	StationStateUnknown StationState = StationState(iwdvalue.StationStateUnknown)

	// StationStateConnected means the station is connected to a network.
	StationStateConnected StationState = StationState(iwdvalue.StationStateConnected)

	// StationStateDisconnected means the station is not connected.
	StationStateDisconnected StationState = StationState(iwdvalue.StationStateDisconnected)

	// StationStateConnecting means the station is establishing a connection.
	StationStateConnecting StationState = StationState(iwdvalue.StationStateConnecting)

	// StationStateDisconnecting means the station is tearing down a connection.
	StationStateDisconnecting StationState = StationState(iwdvalue.StationStateDisconnecting)

	// StationStateRoaming means the station is roaming between access points.
	StationStateRoaming StationState = StationState(iwdvalue.StationStateRoaming)
)

StationState constants identify the station connection states. StationStateUnknown is reserved for invalid or unrecognized values.

func (StationState) String added in v0.7.0

func (s StationState) String() string

String returns the canonical iwd string for the station state.

type UnsubscribeFunc

type UnsubscribeFunc func() error

UnsubscribeFunc unregisters a previously registered subscription callback.

It is safe for implementations to make repeated calls no-ops.

func (UnsubscribeFunc) Unsubscribe

func (u UnsubscribeFunc) Unsubscribe() error

Unsubscribe unregisters the subscription callback.

Calling Unsubscribe on a nil UnsubscribeFunc is a no-op.

Directories

Path Synopsis
cmd
spiderw command
Command spiderw is a small CLI for interacting with iwd through the spiderw public API.
Command spiderw is a small CLI for interacting with iwd through the spiderw public API.
spiderw/cli
Package cli implements the spiderw command-line interface for interacting with iwd through the spiderw public API.
Package cli implements the spiderw command-line interface for interacting with iwd through the spiderw public API.
examples
access-point-start command
Command access-point-start runs a device in AP mode as a PSK-secured access point using AccessPoint.Start, where you supply the SSID and passphrase inline.
Command access-point-start runs a device in AP mode as a PSK-secured access point using AccessPoint.Start, where you supply the SSID and passphrase inline.
access-point-start-profile command
Command access-point-start-profile runs a device in AP mode from a stored iwd provisioning profile using AccessPoint.StartProfile.
Command access-point-start-profile runs a device in AP mode from a stored iwd provisioning profile using AccessPoint.StartProfile.
bring-up command
Command bring-up takes a wireless device from cold to ready for station work: it powers on the device's adapter, powers on the device, switches it to station mode, then scans to confirm the station is usable.
Command bring-up takes a wireless device from cold to ready for station work: it powers on the device's adapter, powers on the device, switches it to station mode, then scans to confirm the station is usable.
connect-hidden command
Command connect-hidden joins a hidden network - one that does not broadcast its SSID and so never appears in scan results.
Command connect-hidden joins a hidden network - one that does not broadcast its SSID and so never appears in scan results.
known-networks command
Command known-networks lists the networks iwd has stored credentials for and can optionally manage one: toggle its autoconnect flag or forget it entirely.
Command known-networks lists the networks iwd has stored credentials for and can optionally manage one: toggle its autoconnect flag or forget it entirely.
monitor command
Command monitor watches the first station and prints its state, scanning, connected-network, and associated-access-point changes live, until interrupted with Ctrl-C. It demonstrates the subscription API and how signals flow through spiderw.
Command monitor watches the first station and prints its state, scanning, connected-network, and associated-access-point changes live, until interrupted with Ctrl-C. It demonstrates the subscription API and how signals flow through spiderw.
scan-and-connect command
Command scan-and-connect runs the full "join a network" flow against the first station: trigger a scan, wait for it to finish, list the visible networks by signal strength, and - if -ssid is given - connect to one, supplying a passphrase through a credentials agent when needed.
Command scan-and-connect runs the full "join a network" flow against the first station: trigger a scan, wait for it to finish, list the visible networks by signal strength, and - if -ssid is given - connect to one, supplying a passphrase through a credentials agent when needed.
signal-monitor command
Command signal-monitor watches the connected network's signal strength on the first station and prints a line each time the RSSI crosses one of the given dBm thresholds, until interrupted with Ctrl-C. It demonstrates the SignalLevelAgent (Station.MonitorSignalLevel) and changes nothing.
Command signal-monitor watches the connected network's signal strength on the first station and prints a line each time the RSSI crosses one of the given dBm thresholds, until interrupted with Ctrl-C. It demonstrates the SignalLevelAgent (Station.MonitorSignalLevel) and changes nothing.
status command
Command status prints a read-only overview of the local iwd state: daemon metadata plus every adapter, device, station, and known network.
Command status prints a read-only overview of the local iwd state: daemon metadata plus every adapter, device, station, and known network.
wsc-pin command
Command wsc-pin joins the first station to an access point via WSC (Wi-Fi Simple Configuration, formerly WPS) PIN mode, without typing a passphrase.
Command wsc-pin joins the first station to an access point via WSC (Wi-Fi Simple Configuration, formerly WPS) PIN mode, without typing a passphrase.
wsc-push-button command
Command wsc-push-button joins the first station to an access point via WSC (Wi-Fi Simple Configuration, formerly WPS) PushButton mode, without typing a passphrase.
Command wsc-push-button joins the first station to an access point via WSC (Wi-Fi Simple Configuration, formerly WPS) PushButton mode, without typing a passphrase.
internal
connect
Package connect wires together the layered spiderw implementation.
Package connect wires together the layered spiderw implementation.
core
Package core normalizes raw D-Bus data from internal/iwdbus into strongly typed domain values and enforces invariants.
Package core normalizes raw D-Bus data from internal/iwdbus into strongly typed domain values and enforces invariants.
core/testutil
Package testutil provides core-layer test fakes and embeddable stubs.
Package testutil provides core-layer test fakes and embeddable stubs.
failure
Package failure defines shared error kinds and resource labels used at spiderw layer boundaries.
Package failure defines shared error kinds and resource labels used at spiderw layer boundaries.
iwdbus
Package iwdbus is the low-level D-Bus boundary for spiderw.
Package iwdbus is the low-level D-Bus boundary for spiderw.
iwdbus/testutil
Package testutil provides iwdbus test fakes and embeddable stubs.
Package testutil provides iwdbus test fakes and embeddable stubs.
iwdvalue
Package iwdvalue defines canonical iwd values shared across spiderw layers.
Package iwdvalue defines canonical iwd values shared across spiderw layers.
logging
Package logging defines the internal logging abstractions used throughout spiderw.
Package logging defines the internal logging abstractions used throughout spiderw.
tests
integration
Package integration documents the conventions for the spiderw integration test suite.
Package integration documents the conventions for the spiderw integration test suite.
integration/iwdbus
Package integration contains the spiderw integration test suite.
Package integration contains the spiderw integration test suite.
testutil/iwdmock
Package iwdmock provides helpers for integration tests that need a deterministic mock of the iwd D-Bus API.
Package iwdmock provides helpers for integration tests that need a deterministic mock of the iwd D-Bus API.
tools
test-mocks/iwdmock command
The iwdmock command is a minimal, Go-based mock of enough of the net.connman.iwd D-Bus API to support spiderw's integration tests.
The iwdmock command is a minimal, Go-based mock of enough of the net.connman.iwd D-Bus API to support spiderw's integration tests.
test-mocks/iwdmock/internal/mock
Package mock implements the D-Bus objects exported by the iwdmock test service.
Package mock implements the D-Bus objects exported by the iwdmock test service.

Jump to

Keyboard shortcuts

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