mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-04 23:17:47 +00:00
nets: new package with netdev redesign ideas
This commit is contained in:
+200
@@ -0,0 +1,200 @@
|
||||
package nets
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/netip"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:linkname UseNetdev net.useNetdev
|
||||
func UseNetdev(dev Stack)
|
||||
|
||||
// GethostByName() errors
|
||||
var (
|
||||
ErrHostUnknown = errors.New("host unknown")
|
||||
ErrMalAddr = errors.New("malformed address")
|
||||
)
|
||||
|
||||
// Socket errors
|
||||
var (
|
||||
ErrFamilyNotSupported = errors.New("address family not supported")
|
||||
ErrProtocolNotSupported = errors.New("socket protocol/type not supported")
|
||||
ErrStartingDHCPClient = errors.New("error starting DHPC client")
|
||||
ErrNoMoreSockets = errors.New("no more sockets")
|
||||
ErrClosingSocket = errors.New("error closing socket")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrConnected = errors.New("already connected")
|
||||
ErrConnectFailed = errors.New("connect failed")
|
||||
ErrConnectTimeout = errors.New("connect timed out")
|
||||
ErrMissingSSID = errors.New("missing WiFi SSID")
|
||||
ErrAuthFailure = errors.New("wifi authentication failure")
|
||||
ErrAuthTypeNoGood = errors.New("wifi authorization type not supported")
|
||||
ErrConnectModeNoGood = errors.New("connect mode not supported")
|
||||
ErrNotSupported = errors.New("not supported")
|
||||
)
|
||||
|
||||
const (
|
||||
AF_INET = 0x2
|
||||
SOCK_STREAM = 0x1
|
||||
SOCK_DGRAM = 0x2
|
||||
SOL_SOCKET = 0x1
|
||||
SO_KEEPALIVE = 0x9
|
||||
SOL_TCP = 0x6
|
||||
TCP_KEEPINTVL = 0x5
|
||||
IPPROTO_TCP = 0x6
|
||||
IPPROTO_UDP = 0x11
|
||||
// Made up, not a real IP protocol number. This is used to create a
|
||||
// TLS socket on the device, assuming the device supports mbed TLS.
|
||||
IPPROTO_TLS = 0xFE
|
||||
F_SETFL = 0x4
|
||||
)
|
||||
|
||||
// Link is the minimum interface that need be implemented by any network
|
||||
// device driver.
|
||||
type Link interface {
|
||||
// HardwareAddr6 returns the device's 6-byte [MAC address], a.k.a EUI-48.
|
||||
//
|
||||
// [MAC address]: https://en.wikipedia.org/wiki/MAC_address
|
||||
HardwareAddr6() ([6]byte, error)
|
||||
LinkStatus() LinkStatus
|
||||
}
|
||||
|
||||
type LinkWifi interface {
|
||||
Link
|
||||
// Connect device to network
|
||||
NetConnect(params WifiParams) error
|
||||
// Disconnect device from network
|
||||
NetDisconnect()
|
||||
// Notify to register callback for network events
|
||||
NetNotify(cb func(Event))
|
||||
}
|
||||
|
||||
type Stack interface {
|
||||
// GetHostByName returns the IP address of either a hostname or IPv4
|
||||
// address in standard dot notation
|
||||
GetHostByName(name string) (netip.Addr, error)
|
||||
|
||||
// Addr returns IP address assigned to the interface, either by
|
||||
// DHCP or statically
|
||||
Addr() (netip.Addr, error)
|
||||
|
||||
// Berkely Sockets-like interface, Go-ified. See man page for socket(2), etc.
|
||||
Socket(domain int, stype int, protocol int) (int, error)
|
||||
Bind(sockfd int, ip netip.AddrPort) error
|
||||
Connect(sockfd int, host string, ip netip.AddrPort) error
|
||||
Listen(sockfd int, backlog int) error
|
||||
Accept(sockfd int, ip netip.AddrPort) (int, error)
|
||||
Send(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
||||
Recv(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
||||
Close(sockfd int) error
|
||||
SetSockOpt(sockfd int, level int, opt int, value interface{}) error
|
||||
}
|
||||
|
||||
// Netdev is returned by `Probe` function.
|
||||
type Netdev interface {
|
||||
LinkWifi
|
||||
Stack
|
||||
}
|
||||
|
||||
type WifiParams struct {
|
||||
// Connect mode
|
||||
ConnectMode ConnectMode
|
||||
|
||||
// SSID of Wifi AP
|
||||
SSID string
|
||||
|
||||
// Passphrase of Wifi AP
|
||||
Passphrase string
|
||||
|
||||
// Wifi authorization type
|
||||
Auth AuthType
|
||||
|
||||
// Wifi country code as two-char string. E.g. "XX" for world-wide,
|
||||
// "US" for USA, etc.
|
||||
CountryCode string
|
||||
}
|
||||
|
||||
type Event int
|
||||
|
||||
// Network events
|
||||
const (
|
||||
// The device's network connection is now UP
|
||||
EventNetUp Event = iota
|
||||
// The device's network connection is now DOWN
|
||||
EventNetDown
|
||||
)
|
||||
|
||||
type ConnectMode int
|
||||
|
||||
// Connect modes
|
||||
const (
|
||||
ConnectModeSTA = iota // Connect as Wifi station (default)
|
||||
ConnectModeAP // Connect as Wifi Access Point
|
||||
)
|
||||
|
||||
type AuthType int
|
||||
|
||||
// Wifi authorization types. Used when setting up an access point, or
|
||||
// connecting to an access point
|
||||
const (
|
||||
AuthTypeWPA2 = iota // WPA2 authorization (default)
|
||||
AuthTypeOpen // No authorization required (open)
|
||||
AuthTypeWPA // WPA authorization
|
||||
AuthTypeWPA2Mixed // WPA2/WPA mixed authorization
|
||||
)
|
||||
|
||||
type LinkStatus uint8
|
||||
|
||||
const (
|
||||
LinkDown LinkStatus = iota
|
||||
LinkConnecting
|
||||
LinkUp
|
||||
)
|
||||
|
||||
type WifiAutoconnectParams struct {
|
||||
WifiParams
|
||||
// NOTE ON FIELDS BELOW: These fields seem like a leaky abstraction- they can
|
||||
// be implemented as an external "AutoConnect" function that is called in
|
||||
// a goroutine that performs auto connect and whatnot.
|
||||
|
||||
// Retries is how many attempts to connect before returning with a
|
||||
// "Connect failed" error. Zero means infinite retries.
|
||||
Retries int // Probably should be implemented as a function
|
||||
|
||||
// Timeout duration for each connection attempt. The default zero
|
||||
// value means 10sec.
|
||||
ConnectTimeout time.Duration
|
||||
|
||||
// Watchdog ticker duration. On tick, the watchdog will check for
|
||||
// downed connection or hardware fault and try to recover the
|
||||
// connection. Set to zero to disable watchodog.
|
||||
WatchdogTimeout time.Duration
|
||||
}
|
||||
|
||||
func StartWifiAutoconnect(dev Netdev, cfg WifiAutoconnectParams) error {
|
||||
if dev == nil {
|
||||
return ErrConnectModeNoGood
|
||||
}
|
||||
go func() {
|
||||
// Wifi autoconnect algorithm in one place,
|
||||
// no need to implement for every single netdever.
|
||||
RECONNECT:
|
||||
for i := 0; i < cfg.Retries; i++ {
|
||||
err := dev.NetConnect(cfg.WifiParams)
|
||||
if err != nil {
|
||||
time.Sleep(cfg.ConnectTimeout)
|
||||
goto RECONNECT
|
||||
}
|
||||
for cfg.WatchdogTimeout != 0 {
|
||||
time.Sleep(cfg.WatchdogTimeout)
|
||||
if dev.LinkStatus() == LinkDown {
|
||||
i = 0
|
||||
goto RECONNECT
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user