mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
e7931c6a22
wifinina driver was not handling concurrent socket connections
correctly. When trying to make multiple socket connections, the sockfd
returned by the first Socket() call would be the same sockfd returned by
subsequent Socket() calls. The problem is the sockfd returned by
Socket() isn't used until Connect() (or Appect()). This would result in
Connect() trying to use the same sockfd for multiple connections,
causing wifinina fw to lock up.
The solution in this PR is to create a new sockfd space managed by the
driver that gives the app a unique, safe sockfd for each connection.
The real underlying sock fd returned by fw is set on Connect() (or
Accept()), and mapped back to the apps sockfd using a map:
sockets map[int]*Socket // keyed by sockfd
Where Socket has a reference to the fw sock:
type Socket struct {
protocol int
clientConnected bool
laddr netip.AddrPort // Set in Bind()
raddr netip.AddrPort // Set in Connect()
sock // Device socket, as returned from w.getSocket()
}
92 lines
2.9 KiB
Go
92 lines
2.9 KiB
Go
// L3/L4 network/transport layer
|
|
|
|
package netdev
|
|
|
|
import (
|
|
"errors"
|
|
"net/netip"
|
|
"time"
|
|
_ "unsafe" // to use go:linkname
|
|
)
|
|
|
|
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
|
|
)
|
|
|
|
// 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")
|
|
ErrNotSupported = errors.New("Not supported")
|
|
ErrInvalidSocketFd = errors.New("Invalid socket fd")
|
|
)
|
|
|
|
// Duplicate of non-exported net.errTimeout
|
|
var ErrTimeout error = &timeoutError{}
|
|
|
|
type timeoutError struct{}
|
|
|
|
func (e *timeoutError) Error() string { return "i/o timeout" }
|
|
func (e *timeoutError) Timeout() bool { return true }
|
|
func (e *timeoutError) Temporary() bool { return true }
|
|
|
|
//go:linkname UseNetdev net.useNetdev
|
|
func UseNetdev(dev Netdever)
|
|
|
|
// Netdever is TinyGo's OSI L3/L4 network/transport layer interface. Network
|
|
// drivers implement the Netdever interface, providing a common network L3/L4
|
|
// interface to TinyGo's "net" package. net.Conn implementations (TCPConn,
|
|
// UDPConn, and TLSConn) use the Netdever interface for device I/O access.
|
|
//
|
|
// A Netdever is passed to the "net" package using UseNetdev().
|
|
//
|
|
// Just like a net.Conn, multiple goroutines may invoke methods on a Netdever
|
|
// simultaneously.
|
|
//
|
|
// NOTE: The Netdever interface is mirrored in tinygo/src/net/netdev.go.
|
|
// NOTE: If making changes to this interface, mirror the changes in
|
|
// NOTE: tinygo/src/net/netdev.go, and vice-versa.
|
|
|
|
type Netdever 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) (int, netip.AddrPort, 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
|
|
}
|