netdev

package
v1.1.0 Latest Latest
Warning

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

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

README

netdev — host Netdever for TinyGo

TinyGo’s net / net/http packages do not talk to the OS directly. They call a Netdever registered with UseNetdev. On microcontrollers that is usually Wi-Fi firmware (WiFiNINA, etc.). On a desktop host there is no default driver, which produces:

Netdev not set

This package implements a Netdever on Linux / macOS / Windows using the host TCP/IP stack, compatible with the interface in tinygo-org/drivers/netdev.

Usage

Blank-import the package before any net / net/http use (init registers the driver under TinyGo):

package main

import (
	"net/http"

	_ "github.com/shibukawa/tinygodriver/netdev"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("ok"))
	})
	http.ListenAndServe(":8080", nil)
}

Or register explicitly:

import "github.com/shibukawa/tinygodriver/netdev"

func main() {
	netdev.Use(netdev.New())
	// ...
}

Build

With TinyGo:

tinygo build -o server ./examples/httpserver
./server

Standard go build / go run also work: the driver is a no-op registrar because the stock net package does not use netdev.

go run ./examples/httpserver

Notes

  • IPv4 only (matches TinyGo’s net port).

  • Unix domain sockets (unix, unixgram, unixpacket) are not supported and will not be. TinyGo’s net rejects those networks before a driver is consulted, and the Netdever interface addresses sockets as netip.AddrPort, which cannot carry a filesystem path. Use tcp4 on 127.0.0.1 for local IPC.

  • Listening on port 0 works, but net.Listener.Addr() still reports port 0. The Netdever Bind signature returns only an error, so the port the OS picked cannot be handed back to TinyGo’s net. Read it from the driver instead:

    d := netdev.New()
    netdev.Use(d)
    fd, _ := d.Socket(netdev.AF_INET, netdev.SOCK_STREAM, netdev.IPPROTO_TCP)
    d.Bind(fd, netip.MustParseAddrPort("127.0.0.1:0"))
    laddr, _ := d.LocalAddr(fd) // 127.0.0.1:54321
    

    A full fix needs an upstream change in TinyGo’s listenTCP.

  • Socket errors are reported as the shared classes in netdev.Err* (ErrConnRefused, ErrAddrNotAvailable, …), so errors.Is works the same on Linux, macOS, and Windows.

  • IPPROTO_TLS uses Secure Transport on macOS, so a binary needs no Homebrew and no OpenSSL. Peer certificates and hostnames are verified against the system keychain; set SSL_CERT_FILE to add a private CA, which is read in Go and passed in as an extra anchor.

    Secure Transport is the only OS-provided option that fits this seam: it hands over an already connected descriptor, and an nw_connection owns DNS, TCP and TLS as one unit and cannot adopt one. The cost is that Secure Transport stops at TLS 1.2; the previous OpenSSL implementation negotiated 1.3.

  • IPPROTO_TLS uses Schannel on Windows, reached through SSPI. It ships with the OS, so there is nothing to install here either, and it reaches TLS 1.3 where the OS supports it. Peer certificates and hostnames are verified against the Windows certificate store; SSL_CERT_FILE adds a private CA the same way it does on macOS.

  • Standard Go Linux builds can exercise the same OpenSSL adapter. TinyGo Linux cannot safely call the distribution's shared OpenSSL because it bypasses glibc process initialization, so TinyGo Linux currently returns ErrProtocolNotSupported for IPPROTO_TLS.

  • OpenSSL 3 is a build and runtime dependency on host-Go Linux only (libssl-dev on Debian/Ubuntu). macOS and TinyGo Linux need neither it nor a package manager.

  • DNS uses /etc/hosts (or the Windows hosts file) plus a simple UDP A-record resolver.

  • Multiple goroutines may call socket methods concurrently; the driver serializes bookkeeping and relies on OS sockets for I/O.

Documentation

Overview

Package netdev implements a host OS Netdever for TinyGo.

TinyGo's net package routes all networking through a Netdever registered via UseNetdev. Embedded Wi-Fi drivers fill that role on microcontrollers; this package fills it on Linux, macOS, and Windows so the same net/http code can run under TinyGo on a desktop host.

Compatible with the Netdever interface described by https://github.com/tinygo-org/drivers/tree/dev/netdev

Usage:

import _ "github.com/shibukawa/tinygodriver/netdev"

The blank import registers the host driver during init.

Index

Constants

View Source
const (
	AF_INET       = 0x2
	SOCK_STREAM   = 0x1
	SOCK_DGRAM    = 0x2
	SOL_SOCKET    = 0x1
	SO_KEEPALIVE  = 0x9
	SO_LINGER     = 0xd
	SOL_TCP       = 0x6
	TCP_KEEPINTVL = 0x5
	IPPROTO_TCP   = 0x6
	IPPROTO_UDP   = 0x11
	// Made up; TLS is implemented by the host netdev on desktop targets.
	IPPROTO_TLS = 0xFE
	F_SETFL     = 0x4
)

BSD-socket style constants mirrored from tinygo-org/drivers/netdev. Values match the abstract constants TinyGo's net package passes to drivers (not always the host OS numeric values).

Variables

View Source
var (
	ErrHostUnknown          = errors.New("Host unknown")
	ErrMalAddr              = errors.New("Malformed address")
	ErrFamilyNotSupported   = errors.New("Address family not supported")
	ErrProtocolNotSupported = errors.New("Socket protocol/type not supported")
	ErrNoMoreSockets        = errors.New("No more sockets")
	ErrClosingSocket        = errors.New("Error closing socket")
	ErrNotSupported         = errors.New("Not supported")
	ErrInvalidSocketFd      = errors.New("Invalid socket fd")
	ErrTimeout              = &timeoutError{}
)

Errors aligned with tinygo-org/drivers/netdev.

View Source
var (
	ErrAddrNotAvailable = errors.New("can't assign requested address")
	ErrAddrInUse        = errors.New("address already in use")
	ErrConnRefused      = errors.New("connection refused")
	ErrConnReset        = errors.New("connection reset by peer")
	ErrNotConnected     = errors.New("socket is not connected")
	ErrConnTimedOut     = errors.New("connection timed out")
	ErrWouldBlock       = errors.New("resource temporarily unavailable")
	ErrSyscall          = errors.New("syscall error")
)

Socket error classes shared by the three backends. Each platform maps its native code onto one of these, so application and test code can branch with errors.Is regardless of the OS. Messages match the standard Go wording.

Functions

func Use

func Use(d *Device)

Use registers d as the process-wide TinyGo netdev.

Types

type Device

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

Device is a host OS implementation of Netdever.

func New

func New() *Device

New returns a host netdev driver. Prefer Use or the blank import.

func (*Device) Accept

func (d *Device) Accept(sockfd int) (int, netip.AddrPort, error)

func (*Device) Addr

func (d *Device) Addr() (netip.Addr, error)

func (*Device) Bind

func (d *Device) Bind(sockfd int, ip netip.AddrPort) error

func (*Device) Close

func (d *Device) Close(sockfd int) error

func (*Device) Connect

func (d *Device) Connect(sockfd int, host string, ip netip.AddrPort) error

func (*Device) GetHostByName

func (d *Device) GetHostByName(name string) (netip.Addr, error)

func (*Device) Listen

func (d *Device) Listen(sockfd int, backlog int) error

func (*Device) LocalAddr added in v1.0.5

func (d *Device) LocalAddr(sockfd int) (netip.AddrPort, error)

LocalAddr returns the address the OS assigned to sockfd, including the port chosen for a bind on port 0.

This is an extension beyond the Netdever interface. TinyGo's net.Listener keeps its own copy of the requested address and has no way to receive this value, so net.Listener.Addr() still reports port 0; see requirement:netdev-bound-port.

func (*Device) Recv

func (d *Device) Recv(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)

func (*Device) Send

func (d *Device) Send(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)

func (*Device) SetSockOpt

func (d *Device) SetSockOpt(sockfd int, level int, opt int, value interface{}) error

func (*Device) Socket

func (d *Device) Socket(domain int, stype int, protocol int) (int, error)

Jump to

Keyboard shortcuts

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