mirror of
https://github.com/tinygo-org/net.git
synced 2026-08-12 15:33:40 +00:00
net: add UDP listen, resolver, DNSError, and TCP listener APIs for wasm (#63)
* net: add UDP listen, resolver, DNSError, and TCP listener APIs for wasm TinyGo's net package was missing several symbols that upstream Go's js/wasm net declares, blocking builds that pull pion/transport, pion/dtls, and similar (via netbird's WASM client). Add them, backed by the existing netdev abstraction so they compile for all targets and no-op cleanly under nopNetdev (matching Go's js runtime behavior): - DNSError type (dnserror.go), copied from Go 1.26.2. - Resolver + DefaultResolver with LookupHost/LookupIP/LookupIPAddr/ LookupNetIP/LookupPort; LookupHost/LookupIP package funcs; Dialer.Resolver field for API compatibility. - UDPConn: ListenUDP, ReadFromUDP(AddrPort), WriteToUDP(AddrPort), SetReadBuffer, SetWriteBuffer. - TCPConn: CloseRead, SetNoDelay, SetReadBuffer, SetWriteBuffer, ReadFrom(io.Reader). - TCPListener: ListenTCP, AcceptTCP, SetDeadline; ListenPacket package func. - Interface: Addrs, MulticastAddrs stubs. * more complete PR for adding more net support (#64) * format unixsock
This commit is contained in:
+107
@@ -210,6 +210,53 @@ func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListenUDP acts like [ListenPacket] for UDP networks.
|
||||
//
|
||||
// The network must be a UDP network name; see func [Dial] for details.
|
||||
//
|
||||
// If the IP field of laddr is nil or an unspecified IP address,
|
||||
// ListenUDP listens on all available IP addresses of the local system
|
||||
// except multicast IP addresses.
|
||||
// If the Port field of laddr is 0, a port number is automatically
|
||||
// chosen.
|
||||
func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error) {
|
||||
switch network {
|
||||
case "udp", "udp4":
|
||||
default:
|
||||
return nil, fmt.Errorf("Network '%s' not supported", network)
|
||||
}
|
||||
|
||||
// TINYGO: Use netdev to create UDP socket and bind (no connect)
|
||||
|
||||
if laddr == nil {
|
||||
laddr = &UDPAddr{}
|
||||
}
|
||||
|
||||
// If no port was given, grab an ephemeral port
|
||||
if laddr.Port == 0 {
|
||||
laddr.Port = ephemeralPort()
|
||||
}
|
||||
|
||||
fd, err := netdev.Socket(_AF_INET, _SOCK_DGRAM, _IPPROTO_UDP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lip, _ := netip.AddrFromSlice(laddr.IP)
|
||||
laddrport := netip.AddrPortFrom(lip, uint16(laddr.Port))
|
||||
|
||||
if err = netdev.Bind(fd, laddrport); err != nil {
|
||||
netdev.Close(fd)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &UDPConn{
|
||||
fd: fd,
|
||||
net: network,
|
||||
laddr: laddr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SyscallConn returns a raw network connection.
|
||||
// This implements the syscall.Conn interface.
|
||||
func (c *UDPConn) SyscallConn() (syscall.RawConn, error) {
|
||||
@@ -242,6 +289,66 @@ func (c *UDPConn) Write(b []byte) (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// ReadFromUDP acts like [UDPConn.ReadFrom] but returns a [UDPAddr].
|
||||
//
|
||||
// TINYGO: netdev has no per-datagram source address, so the connected
|
||||
// remote address (c.raddr) is returned as the source.
|
||||
func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
|
||||
n, err := netdev.Recv(c.fd, b, 0, c.readDeadline)
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
if err != nil && err != io.EOF {
|
||||
err = &OpError{Op: "read", Net: c.net, Source: c.laddr, Addr: c.raddr, Err: err}
|
||||
}
|
||||
return n, c.raddr, err
|
||||
}
|
||||
|
||||
// ReadFromUDPAddrPort acts like [UDPConn.ReadFromUDP] but returns a [netip.AddrPort].
|
||||
func (c *UDPConn) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error) {
|
||||
n, uaddr, err := c.ReadFromUDP(b)
|
||||
if uaddr != nil {
|
||||
addr = uaddr.AddrPort()
|
||||
}
|
||||
return n, addr, err
|
||||
}
|
||||
|
||||
// WriteToUDP acts like [UDPConn.WriteTo] but takes a [UDPAddr].
|
||||
//
|
||||
// TINYGO: the socket is connected via netdev, so writes go to the
|
||||
// connected remote regardless of addr, mirroring netdev.Send.
|
||||
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
|
||||
n, err := netdev.Send(c.fd, b, 0, c.writeDeadline)
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
if err != nil {
|
||||
err = &OpError{Op: "write", Net: c.net, Source: c.laddr, Addr: addr.opAddr(), Err: err}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// WriteToUDPAddrPort acts like [UDPConn.WriteToUDP] but takes a [netip.AddrPort].
|
||||
func (c *UDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
|
||||
return c.WriteToUDP(b, UDPAddrFromAddrPort(addr))
|
||||
}
|
||||
|
||||
// SetReadBuffer sets the size of the operating system's receive buffer
|
||||
// associated with the connection.
|
||||
//
|
||||
// TINYGO: no-op; buffer sizing is managed by the netdev driver.
|
||||
func (c *UDPConn) SetReadBuffer(bytes int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWriteBuffer sets the size of the operating system's transmit buffer
|
||||
// associated with the connection.
|
||||
//
|
||||
// TINYGO: no-op; buffer sizing is managed by the netdev driver.
|
||||
func (c *UDPConn) SetWriteBuffer(bytes int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadFrom implements the PacketConn ReadFrom method.
|
||||
func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
|
||||
return 0, nil, errors.New("ReadFrom not implemented")
|
||||
|
||||
Reference in New Issue
Block a user