diff options
| author | Chris O'Hara <cohara87@gmail.com> | 2023-05-08 17:08:20 +1000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2023-05-25 00:12:41 +0000 |
| commit | a17de43ef12250cd9a0ffdd8ff2d05fb18fcf322 (patch) | |
| tree | 1a092d125865530314bfa393625262302029330e /src/syscall | |
| parent | c5c2184538411c8cf7abc4e536fbe7af8b0307f5 (diff) | |
| download | go-a17de43ef12250cd9a0ffdd8ff2d05fb18fcf322.tar.xz | |
net: implement wasip1 FileListener and FileConn
Implements net.FileListener and net.FileConn for wasip1.
net.FileListener can be used with a pre-opened socket. If the WASM
module knows the file descriptor, a listener can be constructed with:
l, err := net.FileListener(os.NewFile(fd, ""))
If the WASM module does not know the file descriptor, but knows that at
least one of the preopens is a socket, it can find the file descriptor
and construct a listener like so:
func findListener() (net.Listener, error) {
// We start looking for pre-opened sockets at fd=3 because 0, 1,
// and 2 are reserved for stdio. Pre-opened directories also
// start at fd=3, so we skip fds that aren't sockets. Once we
// reach EBADF we know there are no more pre-opens.
for preopenFd := uintptr(3); ; preopenFd++ {
l, err := net.FileListener(os.NewFile(preopenFd, ""))
var se syscall.Errno
switch errors.As(err, &se); se {
case syscall.ENOTSOCK:
continue
case syscall.EBADF:
err = nil
}
return l, err
}
}
A similar strategy can be used with net.FileConn and pre-opened
connection sockets.
The wasmtime runtime supports pre-opening listener sockets:
$ wasmtime --tcplisten 127.0.0.1:8080 module.wasm
Change-Id: Iec6ae4ffa84b3753cce4f56a2817e150445db643
Reviewed-on: https://go-review.googlesource.com/c/go/+/493358
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Auto-Submit: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/syscall')
| -rw-r--r-- | src/syscall/fs_wasip1.go | 12 | ||||
| -rw-r--r-- | src/syscall/net_fake.go | 63 | ||||
| -rw-r--r-- | src/syscall/net_js.go | 56 | ||||
| -rw-r--r-- | src/syscall/net_wasip1.go | 70 |
4 files changed, 89 insertions, 112 deletions
diff --git a/src/syscall/fs_wasip1.go b/src/syscall/fs_wasip1.go index 25cabf8234..d60ab0b53e 100644 --- a/src/syscall/fs_wasip1.go +++ b/src/syscall/fs_wasip1.go @@ -279,6 +279,12 @@ func fd_fdstat_get_flags(fd int) (uint32, error) { return uint32(stat.fdflags), errnoErr(errno) } +func fd_fdstat_get_type(fd int) (uint8, error) { + var stat fdstat + errno := fd_fdstat_get(int32(fd), unsafe.Pointer(&stat)) + return stat.filetype, errnoErr(errno) +} + type preopentype = uint8 const ( @@ -331,12 +337,12 @@ func init() { if errno == EBADF { break } + if errno == ENOTDIR || prestat.typ != preopentypeDir { + continue + } if errno != 0 { panic("fd_prestat: " + errno.Error()) } - if prestat.typ != preopentypeDir { - continue - } if int(prestat.dir.prNameLen) > len(dirNameBuf) { dirNameBuf = make([]byte, prestat.dir.prNameLen) } diff --git a/src/syscall/net_fake.go b/src/syscall/net_fake.go new file mode 100644 index 0000000000..689f6f8812 --- /dev/null +++ b/src/syscall/net_fake.go @@ -0,0 +1,63 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Fake networking for js/wasm and wasip1/wasm. +// This file only exists to make the compiler happy. + +//go:build (js && wasm) || wasip1 + +package syscall + +const ( + AF_UNSPEC = iota + AF_UNIX + AF_INET + AF_INET6 +) + +const ( + SOCK_STREAM = 1 + iota + SOCK_DGRAM + SOCK_RAW + SOCK_SEQPACKET +) + +const ( + IPPROTO_IP = 0 + IPPROTO_IPV4 = 4 + IPPROTO_IPV6 = 0x29 + IPPROTO_TCP = 6 + IPPROTO_UDP = 0x11 +) + +const ( + _ = iota + IPV6_V6ONLY + SOMAXCONN + SO_ERROR +) + +// Misc constants expected by package net but not supported. +const ( + _ = iota + F_DUPFD_CLOEXEC + SYS_FCNTL = 500 // unsupported +) + +type Sockaddr any + +type SockaddrInet4 struct { + Port int + Addr [4]byte +} + +type SockaddrInet6 struct { + Port int + ZoneId uint32 + Addr [16]byte +} + +type SockaddrUnix struct { + Name string +} diff --git a/src/syscall/net_js.go b/src/syscall/net_js.go index 2ed4e191bd..cba33dfd2e 100644 --- a/src/syscall/net_js.go +++ b/src/syscall/net_js.go @@ -2,66 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// js/wasm uses fake networking directly implemented in the net package. -// This file only exists to make the compiler happy. - //go:build js && wasm package syscall -const ( - AF_UNSPEC = iota - AF_UNIX - AF_INET - AF_INET6 -) - -const ( - SOCK_STREAM = 1 + iota - SOCK_DGRAM - SOCK_RAW - SOCK_SEQPACKET -) - -const ( - IPPROTO_IP = 0 - IPPROTO_IPV4 = 4 - IPPROTO_IPV6 = 0x29 - IPPROTO_TCP = 6 - IPPROTO_UDP = 0x11 -) - -const ( - _ = iota - IPV6_V6ONLY - SOMAXCONN - SO_ERROR -) - -// Misc constants expected by package net but not supported. -const ( - _ = iota - F_DUPFD_CLOEXEC - SYS_FCNTL = 500 // unsupported -) - -type Sockaddr any - -type SockaddrInet4 struct { - Port int - Addr [4]byte -} - -type SockaddrInet6 struct { - Port int - ZoneId uint32 - Addr [16]byte -} - -type SockaddrUnix struct { - Name string -} - func Socket(proto, sotype, unused int) (fd int, err error) { return 0, ENOSYS } diff --git a/src/syscall/net_wasip1.go b/src/syscall/net_wasip1.go index 896dd3e770..3918840a7e 100644 --- a/src/syscall/net_wasip1.go +++ b/src/syscall/net_wasip1.go @@ -2,66 +2,27 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// wasip1/wasm uses fake networking directly implemented in the net package. -// This file only exists to make the compiler happy. - //go:build wasip1 package syscall -const ( - AF_UNSPEC = iota - AF_UNIX - AF_INET - AF_INET6 -) +import "unsafe" const ( - SOCK_STREAM = 1 + iota - SOCK_DGRAM - SOCK_RAW - SOCK_SEQPACKET + SHUT_RD = 0x1 + SHUT_WR = 0x2 + SHUT_RDWR = SHUT_RD | SHUT_WR ) -const ( - IPPROTO_IP = 0 - IPPROTO_IPV4 = 4 - IPPROTO_IPV6 = 0x29 - IPPROTO_TCP = 6 - IPPROTO_UDP = 0x11 -) +type sdflags = uint32 -const ( - _ = iota - IPV6_V6ONLY - SOMAXCONN - SO_ERROR -) +//go:wasmimport wasi_snapshot_preview1 sock_accept +//go:noescape +func sock_accept(fd int32, flags fdflags, newfd unsafe.Pointer) Errno -// Misc constants expected by package net but not supported. -const ( - _ = iota - F_DUPFD_CLOEXEC - SYS_FCNTL = 500 // unsupported; same value as net_nacl.go -) - -type Sockaddr interface { -} - -type SockaddrInet4 struct { - Port int - Addr [4]byte -} - -type SockaddrInet6 struct { - Port int - ZoneId uint32 - Addr [16]byte -} - -type SockaddrUnix struct { - Name string -} +//go:wasmimport wasi_snapshot_preview1 sock_shutdown +//go:noescape +func sock_shutdown(fd int32, flags sdflags) Errno func Socket(proto, sotype, unused int) (fd int, err error) { return 0, ENOSYS @@ -79,8 +40,10 @@ func Listen(fd int, backlog int) error { return ENOSYS } -func Accept(fd int) (newfd int, sa Sockaddr, err error) { - return 0, nil, ENOSYS +func Accept(fd int) (int, Sockaddr, error) { + var newfd int32 + errno := sock_accept(int32(fd), 0, unsafe.Pointer(&newfd)) + return int(newfd), nil, errnoErr(errno) } func Connect(fd int, sa Sockaddr) error { @@ -120,5 +83,6 @@ func SetWriteDeadline(fd int, t int64) error { } func Shutdown(fd int, how int) error { - return ENOSYS + errno := sock_shutdown(int32(fd), sdflags(how)) + return errnoErr(errno) } |
