diff --git a/internal/syscall/errno_wasip1.go b/internal/syscall/errno_wasip1.go deleted file mode 100644 index 8343acf..0000000 --- a/internal/syscall/errno_wasip1.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -package syscall - -import "syscall" - -type Errno = syscall.Errno - -const ( - EAGAIN = syscall.EAGAIN - EINPROGRESS = syscall.EINPROGRESS - EINTR = syscall.EINTR - EISCONN = syscall.EISCONN - ENOSYS = syscall.ENOSYS - ENOTSUP = syscall.ENOTSUP -) - -// Do the interface allocations only once for common -// Errno values. -var errEAGAIN error = EAGAIN - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -// -// We set both noinline and nosplit to reduce code size, this function has many -// call sites in the syscall package, inlining it causes a significant increase -// of the compiled code; the function call ultimately does not make a difference -// in the performance of syscall functions since the time is dominated by calls -// to the imports and path resolution. -// -//go:noinline -//go:nosplit -func errnoErr(e Errno) error { - switch e { - case 0: - return nil - case EAGAIN: - return errEAGAIN - } - return e -} diff --git a/internal/syscall/fs_wasip1.go b/internal/syscall/fs_wasip1.go deleted file mode 100644 index 5b026cc..0000000 --- a/internal/syscall/fs_wasip1.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -package syscall - -import "syscall" - -func Close(fd int) error { - return syscall.Close(fd) -} - -func SetNonblock(fd int, nonblocking bool) error { - return syscall.SetNonblock(fd, nonblocking) -} diff --git a/wasip1/dial_wasip1.go b/wasip1/dial_wasip1.go index 6ab6163..19cea86 100644 --- a/wasip1/dial_wasip1.go +++ b/wasip1/dial_wasip1.go @@ -4,8 +4,7 @@ import ( "context" "net" "os" - - "github.com/stealthrocket/net/internal/syscall" + "syscall" ) // Dial connects to the address on the named network. @@ -41,7 +40,7 @@ func dialAddr(addr net.Addr) (net.Conn, error) { proto := family(addr) sotype := socketType(addr) - fd, err := syscall.Socket(proto, sotype, 0) + fd, err := socket(proto, sotype, 0) if err != nil { return nil, os.NewSyscallError("socket", err) } @@ -51,8 +50,8 @@ func dialAddr(addr net.Addr) (net.Conn, error) { return nil, os.NewSyscallError("setnonblock", err) } - if sotype == syscall.SOCK_DGRAM && proto != syscall.AF_UNIX { - if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil { + if sotype == SOCK_DGRAM && proto != AF_UNIX { + if err := setsockopt(fd, SOL_SOCKET, SO_BROADCAST, 1); err != nil { syscall.Close(fd) return nil, os.NewSyscallError("setsockopt", err) } @@ -64,7 +63,7 @@ func dialAddr(addr net.Addr) (net.Conn, error) { } var inProgress bool - switch err := syscall.Connect(fd, connectAddr); err { + switch err := connect(fd, connectAddr); err { case nil: case syscall.EINPROGRESS: inProgress = true @@ -83,7 +82,7 @@ func dialAddr(addr net.Addr) (net.Conn, error) { } rawConnErr := rawConn.Write(func(fd uintptr) bool { var value int - value, err = syscall.GetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_ERROR) + value, err = getsockopt(int(fd), SOL_SOCKET, SO_ERROR) if err != nil { return true // done } @@ -96,7 +95,7 @@ func dialAddr(addr net.Addr) (net.Conn, error) { case syscall.Errno(0): // The net poller can wake up spuriously. Check that we are // are really connected. - _, err := syscall.Getpeername(int(fd)) + _, err := getpeername(int(fd)) return err == nil default: return true @@ -123,7 +122,7 @@ func family(addr net.Addr) int { var ip net.IP switch a := addr.(type) { case *net.UnixAddr: - return syscall.AF_UNIX + return AF_UNIX case *net.TCPAddr: ip = a.IP case *net.UDPAddr: @@ -132,30 +131,30 @@ func family(addr net.Addr) int { ip = a.IP } if ip.To4() != nil { - return syscall.AF_INET + return AF_INET } else if len(ip) == net.IPv6len { - return syscall.AF_INET6 + return AF_INET6 } - return syscall.AF_INET + return AF_INET } func socketType(addr net.Addr) int { switch addr.Network() { case "tcp", "unix": - return syscall.SOCK_STREAM + return SOCK_STREAM case "udp", "unixgram": - return syscall.SOCK_DGRAM + return SOCK_DGRAM default: panic("not implemented") } } -func socketAddress(addr net.Addr) (syscall.Sockaddr, error) { +func socketAddress(addr net.Addr) (sockaddr, error) { var ip net.IP var port int switch a := addr.(type) { case *net.UnixAddr: - return &syscall.SockaddrUnix{Name: a.Name}, nil + return &sockaddrUnix{name: a.Name}, nil case *net.TCPAddr: ip, port = a.IP, a.Port case *net.UDPAddr: @@ -164,9 +163,9 @@ func socketAddress(addr net.Addr) (syscall.Sockaddr, error) { ip = a.IP } if ipv4 := ip.To4(); ipv4 != nil { - return &syscall.SockaddrInet4{Addr: ([4]byte)(ipv4), Port: port}, nil + return &sockaddrInet4{addr: ([4]byte)(ipv4), port: port}, nil } else if len(ip) == net.IPv6len { - return &syscall.SockaddrInet6{Addr: ([16]byte)(ip), Port: port}, nil + return &sockaddrInet6{addr: ([16]byte)(ip), port: port}, nil } else { return nil, &net.AddrError{ Err: "unsupported address type", diff --git a/wasip1/listen_wasip1.go b/wasip1/listen_wasip1.go index 598a33e..855bc2f 100644 --- a/wasip1/listen_wasip1.go +++ b/wasip1/listen_wasip1.go @@ -3,8 +3,7 @@ package wasip1 import ( "net" "os" - - "github.com/stealthrocket/net/internal/syscall" + "syscall" ) // Listen announces on the local network address. @@ -26,7 +25,7 @@ func listenErr(addr net.Addr, err error) error { } func listenAddr(addr net.Addr) (net.Listener, error) { - fd, err := syscall.Socket(family(addr), socketType(addr), 0) + fd, err := socket(family(addr), socketType(addr), 0) if err != nil { return nil, os.NewSyscallError("socket", err) } @@ -35,7 +34,7 @@ func listenAddr(addr net.Addr) (net.Listener, error) { syscall.Close(fd) return nil, os.NewSyscallError("setnonblock", err) } - if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { + if err := setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1); err != nil { syscall.Close(fd) return nil, os.NewSyscallError("setsockopt", err) } @@ -45,13 +44,13 @@ func listenAddr(addr net.Addr) (net.Listener, error) { return nil, os.NewSyscallError("bind", err) } - if err := syscall.Bind(fd, listenAddr); err != nil { + if err := bind(fd, listenAddr); err != nil { syscall.Close(fd) return nil, os.NewSyscallError("bind", err) } const backlog = 64 // TODO: configurable? - if err := syscall.Listen(fd, backlog); err != nil { + if err := listen(fd, backlog); err != nil { syscall.Close(fd) return nil, os.NewSyscallError("listen", err) } diff --git a/wasip1/lookup_wasip1.go b/wasip1/lookup_wasip1.go index 841a9c1..22058b4 100644 --- a/wasip1/lookup_wasip1.go +++ b/wasip1/lookup_wasip1.go @@ -5,19 +5,17 @@ package wasip1 import ( "net" "os" - - "github.com/stealthrocket/net/internal/syscall" ) func lookupAddr(op, network, address string) (net.Addr, error) { - var hints syscall.AddrInfo + var hints addrInfo switch network { case "tcp", "tcp4", "tcp6": - hints.SocketType = syscall.SOCK_STREAM - hints.Protocol = syscall.IPPROTO_TCP + hints.socketType = SOCK_STREAM + hints.protocol = IPPROTO_TCP case "udp", "udp4", "udp6": - hints.SocketType = syscall.SOCK_DGRAM - hints.Protocol = syscall.IPPROTO_UDP + hints.socketType = SOCK_DGRAM + hints.protocol = IPPROTO_UDP case "unix", "unixgram": return &net.UnixAddr{Name: address, Net: network}, nil default: @@ -25,22 +23,22 @@ func lookupAddr(op, network, address string) (net.Addr, error) { } switch network { case "tcp", "udp": - hints.Family = syscall.AF_UNSPEC + hints.family = AF_UNSPEC case "tcp4", "udp4": - hints.Family = syscall.AF_INET + hints.family = AF_INET case "tcp6", "udp6": - hints.Family = syscall.AF_INET6 + hints.family = AF_INET6 } hostname, service, err := net.SplitHostPort(address) if err != nil { return nil, net.InvalidAddrError(address) } if op == "listen" && hostname == "" { - hints.Flags |= syscall.AI_PASSIVE + hints.flags |= AI_PASSIVE } - results := make([]syscall.AddrInfo, 16) - n, err := syscall.Getaddrinfo(hostname, service, hints, results) + results := make([]addrInfo, 16) + n, err := getaddrinfo(hostname, service, &hints, results) if err != nil { addr := &netAddr{network, address} return nil, newOpError(op, addr, os.NewSyscallError("getaddrinfo", err)) @@ -49,13 +47,13 @@ func lookupAddr(op, network, address string) (net.Addr, error) { for _, r := range results { var ip net.IP var port int - switch a := r.Address.(type) { - case *syscall.SockaddrInet4: - ip = a.Addr[:] - port = a.Port - case *syscall.SockaddrInet6: - ip = a.Addr[:] - port = a.Port + switch a := r.address.(type) { + case *sockaddrInet4: + ip = a.addr[:] + port = a.port + case *sockaddrInet6: + ip = a.addr[:] + port = a.port } switch network { case "tcp", "tcp4", "tcp6": diff --git a/wasip1/net_wasip1.go b/wasip1/net_wasip1.go index 7943d03..ab067f3 100644 --- a/wasip1/net_wasip1.go +++ b/wasip1/net_wasip1.go @@ -37,10 +37,7 @@ func newOpError(op string, addr net.Addr, err error) error { } } -type netAddr struct { - network string - address string -} +type netAddr struct{ network, address string } func (na *netAddr) Network() string { return na.address } func (na *netAddr) String() string { return na.address } diff --git a/internal/syscall/net_wasip1.go b/wasip1/syscall_wasmedge_wasip1.go similarity index 53% rename from internal/syscall/net_wasip1.go rename to wasip1/syscall_wasmedge_wasip1.go index fea0da9..521306f 100644 --- a/internal/syscall/net_wasip1.go +++ b/wasip1/syscall_wasmedge_wasip1.go @@ -1,12 +1,13 @@ -// 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. +package wasip1 -package syscall +// This file contains the definition of host imports compatible with the socket +// extensions from wasmedge v0.12+. import ( "encoding/binary" "runtime" + "strings" + "syscall" "unsafe" ) @@ -48,58 +49,56 @@ const ( IPPROTO_UDP ) -type Sockaddr interface { +type sockaddr interface { sockaddr() (unsafe.Pointer, error) sockport() int } -type SockaddrInet4 struct { - Port int - Addr [4]byte - - raw addressBuffer +type sockaddrInet4 struct { + port int + addr [4]byte + raw addressBuffer } -func (s *SockaddrInet4) sockaddr() (unsafe.Pointer, error) { +func (s *sockaddrInet4) sockaddr() (unsafe.Pointer, error) { s.raw.bufLen = 4 - s.raw.buf = uintptr32(uintptr(unsafe.Pointer(&s.Addr))) + s.raw.buf = uintptr32(uintptr(unsafe.Pointer(&s.addr))) return unsafe.Pointer(&s.raw), nil } -func (s *SockaddrInet4) sockport() int { - return s.Port +func (s *sockaddrInet4) sockport() int { + return s.port } -type SockaddrInet6 struct { - Port int +type sockaddrInet6 struct { + port int ZoneId uint32 - Addr [16]byte - - raw addressBuffer + addr [16]byte + raw addressBuffer } -func (s *SockaddrInet6) sockaddr() (unsafe.Pointer, error) { +func (s *sockaddrInet6) sockaddr() (unsafe.Pointer, error) { if s.ZoneId != 0 { - return nil, ENOTSUP + return nil, syscall.ENOTSUP } s.raw.bufLen = 16 - s.raw.buf = uintptr32(uintptr(unsafe.Pointer(&s.Addr))) + s.raw.buf = uintptr32(uintptr(unsafe.Pointer(&s.addr))) return unsafe.Pointer(&s.raw), nil } -func (s *SockaddrInet6) sockport() int { - return s.Port +func (s *sockaddrInet6) sockport() int { + return s.port } -type SockaddrUnix struct { - Name string +type sockaddrUnix struct { + name string } -func (s *SockaddrUnix) sockaddr() (unsafe.Pointer, error) { - return nil, ENOSYS +func (s *sockaddrUnix) sockaddr() (unsafe.Pointer, error) { + return nil, syscall.ENOSYS } -func (s *SockaddrUnix) sockport() int { +func (s *sockaddrUnix) sockport() int { return 0 } @@ -111,42 +110,42 @@ type addressBuffer struct { bufLen size } -type RawSockaddrAny struct { +type rawSockaddrAny struct { family uint16 addr [126]byte } //go:wasmimport wasi_snapshot_preview1 sock_open //go:noescape -func sock_open(af int32, socktype int32, fd unsafe.Pointer) Errno +func sock_open(af int32, socktype int32, fd unsafe.Pointer) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_bind //go:noescape -func sock_bind(fd int32, addr unsafe.Pointer, port uint32) Errno +func sock_bind(fd int32, addr unsafe.Pointer, port uint32) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_listen //go:noescape -func sock_listen(fd int32, backlog int32) Errno +func sock_listen(fd int32, backlog int32) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_connect //go:noescape -func sock_connect(fd int32, addr unsafe.Pointer, port uint32) Errno +func sock_connect(fd int32, addr unsafe.Pointer, port uint32) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_getsockopt //go:noescape -func sock_getsockopt(fd int32, level uint32, name uint32, value unsafe.Pointer, valueLen uint32) Errno +func sock_getsockopt(fd int32, level uint32, name uint32, value unsafe.Pointer, valueLen uint32) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_setsockopt //go:noescape -func sock_setsockopt(fd int32, level uint32, name uint32, value unsafe.Pointer, valueLen uint32) Errno +func sock_setsockopt(fd int32, level uint32, name uint32, value unsafe.Pointer, valueLen uint32) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_getlocaladdr //go:noescape -func sock_getlocaladdr(fd int32, addr unsafe.Pointer, port unsafe.Pointer) Errno +func sock_getlocaladdr(fd int32, addr unsafe.Pointer, port unsafe.Pointer) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_getpeeraddr //go:noescape -func sock_getpeeraddr(fd int32, addr unsafe.Pointer, port unsafe.Pointer) Errno +func sock_getpeeraddr(fd int32, addr unsafe.Pointer, port unsafe.Pointer) syscall.Errno //go:wasmimport wasi_snapshot_preview1 sock_getaddrinfo //go:noescape @@ -159,53 +158,70 @@ func sock_getaddrinfo( res unsafe.Pointer, maxResLen uint32, resLen unsafe.Pointer, -) uint32 +) syscall.Errno -func Socket(proto, sotype, unused int) (fd int, err error) { +func socket(proto, sotype, unused int) (fd int, err error) { var newfd int32 errno := sock_open(int32(proto), int32(sotype), unsafe.Pointer(&newfd)) - return int(newfd), errnoErr(errno) + if errno != 0 { + return -1, errno + } + return int(newfd), nil } -func Bind(fd int, sa Sockaddr) error { +func bind(fd int, sa sockaddr) error { rawaddr, err := sa.sockaddr() if err != nil { return err } errno := sock_bind(int32(fd), rawaddr, uint32(sa.sockport())) runtime.KeepAlive(sa) - return errnoErr(errno) + if errno != 0 { + return errno + } + return nil } -func Listen(fd int, backlog int) error { - errno := sock_listen(int32(fd), int32(backlog)) - return errnoErr(errno) +func listen(fd int, backlog int) error { + if errno := sock_listen(int32(fd), int32(backlog)); errno != 0 { + return errno + } + return nil } -func Connect(fd int, sa Sockaddr) error { +func connect(fd int, sa sockaddr) error { rawaddr, err := sa.sockaddr() if err != nil { return err } errno := sock_connect(int32(fd), rawaddr, uint32(sa.sockport())) runtime.KeepAlive(sa) - return errnoErr(errno) + if errno != 0 { + return errno + } + return nil } -func GetsockoptInt(fd, level, opt int) (value int, err error) { +func getsockopt(fd, level, opt int) (value int, err error) { var n int32 errno := sock_getsockopt(int32(fd), uint32(level), uint32(opt), unsafe.Pointer(&n), 4) - return int(n), errnoErr(errno) + if errno != 0 { + return 0, errno + } + return int(n), nil } -func SetsockoptInt(fd, level, opt int, value int) error { +func setsockopt(fd, level, opt int, value int) error { var n = int32(value) errno := sock_setsockopt(int32(fd), uint32(level), uint32(opt), unsafe.Pointer(&n), 4) - return errnoErr(errno) + if errno != 0 { + return errno + } + return nil } -func Getsockname(fd int) (sa Sockaddr, err error) { - var rsa RawSockaddrAny +func getsockname(fd int) (sa sockaddr, err error) { + var rsa rawSockaddrAny buf := addressBuffer{ buf: uintptr32(uintptr(unsafe.Pointer(&rsa))), bufLen: uint32(unsafe.Sizeof(rsa)), @@ -213,13 +229,13 @@ func Getsockname(fd int) (sa Sockaddr, err error) { var port uint32 errno := sock_getlocaladdr(int32(fd), unsafe.Pointer(&buf), unsafe.Pointer(&port)) if errno != 0 { - return nil, errnoErr(errno) + return nil, errno } return anyToSockaddr(&rsa, int(port)) } -func Getpeername(fd int) (Sockaddr, error) { - var rsa RawSockaddrAny +func getpeername(fd int) (sockaddr, error) { + var rsa rawSockaddrAny buf := addressBuffer{ buf: uintptr32(uintptr(unsafe.Pointer(&rsa))), bufLen: uint32(unsafe.Sizeof(rsa)), @@ -227,28 +243,28 @@ func Getpeername(fd int) (Sockaddr, error) { var port uint32 errno := sock_getpeeraddr(int32(fd), unsafe.Pointer(&buf), unsafe.Pointer(&port)) if errno != 0 { - return nil, errnoErr(errno) + return nil, errno } return anyToSockaddr(&rsa, int(port)) } -func anyToSockaddr(rsa *RawSockaddrAny, port int) (Sockaddr, error) { +func anyToSockaddr(rsa *rawSockaddrAny, port int) (sockaddr, error) { switch rsa.family { case AF_INET: - addr := SockaddrInet4{Port: port} - copy(addr.Addr[:], rsa.addr[:]) + addr := sockaddrInet4{port: port} + copy(addr.addr[:], rsa.addr[:]) return &addr, nil case AF_INET6: - addr := SockaddrInet6{Port: port} - copy(addr.Addr[:], rsa.addr[:]) + addr := sockaddrInet6{port: port} + copy(addr.addr[:], rsa.addr[:]) return &addr, nil default: - return nil, ENOTSUP + return nil, syscall.ENOTSUP } } // https://github.com/WasmEdge/WasmEdge/blob/434e1fb4690/thirdparty/wasi/api.hpp#L1885 -type addrInfo struct { +type sockAddrInfo struct { ai_flags uint16 ai_family uint8 ai_socktype uint8 @@ -257,7 +273,7 @@ type addrInfo struct { ai_addr uintptr32 // *sockAddr ai_canonname uintptr32 // null-terminated string ai_canonnamelen uint32 - ai_next uintptr32 // *addrInfo + ai_next uintptr32 // *sockAddrInfo } type sockAddr struct { @@ -267,44 +283,36 @@ type sockAddr struct { _ [4]byte } -type AddrInfo struct { - Flags int - Family int - SocketType int - Protocol int - Address Sockaddr - CanonicalName string - - addrInfo +type addrInfo struct { + flags int + family int + socketType int + protocol int + address sockaddr + // canonicalName string + + sockAddrInfo sockAddr sockData [26]byte cannoname [30]byte - inet4addr SockaddrInet4 - inet6addr SockaddrInet6 + inet4addr sockaddrInet4 + inet6addr sockaddrInet6 } -func Getaddrinfo(name, service string, hints AddrInfo, results []AddrInfo) (int, error) { - // For compatibility with WasmEdge, make sure strings are null-terminated. - if len(name) > 0 && name[len(name)-1] != 0 { - name = string(append([]byte(name), 0)) - } - if len(service) > 0 && service[len(service)-1] != 0 { - service = string(append([]byte(service), 0)) - } - - hints.addrInfo = addrInfo{ - ai_flags: uint16(hints.Flags), - ai_family: uint8(hints.Family), - ai_socktype: uint8(hints.SocketType), - ai_protocol: uint32(hints.Protocol), +func getaddrinfo(name, service string, hints *addrInfo, results []addrInfo) (int, error) { + hints.sockAddrInfo = sockAddrInfo{ + ai_flags: uint16(hints.flags), + ai_family: uint8(hints.family), + ai_socktype: uint8(hints.socketType), + ai_protocol: uint32(hints.protocol), } for i := range results { results[i].sockAddr = sockAddr{ sa_family: 0, - sa_data_len: uint32(unsafe.Sizeof(AddrInfo{}.sockData)), + sa_data_len: uint32(unsafe.Sizeof(addrInfo{}.sockData)), sa_data: uintptr32(uintptr(unsafe.Pointer(&results[i].sockData))), } - results[i].addrInfo = addrInfo{ + results[i].sockAddrInfo = sockAddrInfo{ ai_flags: 0, ai_family: 0, ai_socktype: 0, @@ -312,28 +320,31 @@ func Getaddrinfo(name, service string, hints AddrInfo, results []AddrInfo) (int, ai_addrlen: uint32(unsafe.Sizeof(sockAddr{})), ai_addr: uintptr32(uintptr(unsafe.Pointer(&results[i].sockAddr))), ai_canonname: uintptr32(uintptr(unsafe.Pointer(&results[i].cannoname))), - ai_canonnamelen: uint32(unsafe.Sizeof(AddrInfo{}.cannoname)), + ai_canonnamelen: uint32(unsafe.Sizeof(addrInfo{}.cannoname)), } if i > 0 { - results[i-1].addrInfo.ai_next = uintptr32(uintptr(unsafe.Pointer(&results[i-1].addrInfo))) + results[i-1].sockAddrInfo.ai_next = uintptr32(uintptr(unsafe.Pointer(&results[i-1].sockAddrInfo))) } } - resPtr := uintptr32(uintptr(unsafe.Pointer(&results[0].addrInfo))) + resPtr := uintptr32(uintptr(unsafe.Pointer(&results[0].sockAddrInfo))) + // For compatibility with WasmEdge, make sure strings are null-terminated. + namePtr, nameLen := nullTerminatedString(name) + servPtr, servLen := nullTerminatedString(service) var n uint32 errno := sock_getaddrinfo( - unsafe.Pointer(unsafe.StringData(name)), - uint32(len(name)), - unsafe.Pointer(unsafe.StringData(service)), - uint32(len(service)), - unsafe.Pointer(&hints.addrInfo), + unsafe.Pointer(namePtr), + uint32(nameLen), + unsafe.Pointer(servPtr), + uint32(servLen), + unsafe.Pointer(&hints.sockAddrInfo), unsafe.Pointer(&resPtr), uint32(len(results)), unsafe.Pointer(&n), ) if errno != 0 { - return 0, errnoErr(Errno(errno)) + return 0, errno } for i := range results[:n] { @@ -341,17 +352,27 @@ func Getaddrinfo(name, service string, hints AddrInfo, results []AddrInfo) (int, port := binary.BigEndian.Uint16(results[i].sockData[:2]) switch results[i].sockAddr.sa_family { case AF_INET: - r.inet4addr.Port = int(port) - copy(r.inet4addr.Addr[:], results[i].sockData[2:]) - r.Address = &r.inet4addr + r.inet4addr.port = int(port) + copy(r.inet4addr.addr[:], results[i].sockData[2:]) + r.address = &r.inet4addr case AF_INET6: - r.inet6addr.Port = int(port) - r.Address = &r.inet6addr - copy(r.inet4addr.Addr[:], results[i].sockData[2:]) + r.inet6addr.port = int(port) + r.address = &r.inet6addr + copy(r.inet4addr.addr[:], results[i].sockData[2:]) default: - r.Address = nil + r.address = nil } // TODO: canonical names } return int(n), nil } + +func nullTerminatedString(s string) (*byte, int) { + if n := strings.IndexByte(s, 0); n >= 0 { + s = s[:n+1] + return unsafe.StringData(s), len(s) + } else { + b := append([]byte(s), 0) + return unsafe.SliceData(b), len(b) + } +}