Skip to content

Commit

Permalink
internal/socket: support building with gccgo
Browse files Browse the repository at this point in the history
Update x/sys to permit calling RecvmsgBuffers and SendmsgBuffers.

The zos changes are wholly untested.

Fixes golang/go#52512

Change-Id: I8fae9f4db2e0b83c99a7c0f3cadc83b5868683e6
Reviewed-on: https://go-review.googlesource.com/c/net/+/419175
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
  • Loading branch information
WeiminShang authored and gopherbot committed Jul 25, 2022
1 parent d593179 commit e65d741
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 56 deletions.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -3,7 +3,7 @@ module golang.org/x/net
go 1.17

require (
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/text v0.3.7
)
4 changes: 2 additions & 2 deletions go.sum
@@ -1,6 +1,6 @@
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
Expand Down
48 changes: 17 additions & 31 deletions internal/socket/rawconn_msg.go
Expand Up @@ -8,22 +8,21 @@
package socket

import (
"net"
"os"
)

func (c *Conn) recvMsg(m *Message, flags int) error {
m.raceWrite()
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte
if c.network != "tcp" {
sa = make([]byte, sizeofSockaddrInet6)
}
h.pack(vs, m.Buffers, m.OOB, sa)
var operr error
var n int
var (
operr error
n int
oobn int
recvflags int
from net.Addr
)
fn := func(s uintptr) bool {
n, operr = recvmsg(s, &h, flags)
n, oobn, recvflags, from, operr = recvmsg(s, m.Buffers, m.OOB, flags, c.network)
return ioComplete(flags, operr)
}
if err := c.c.Read(fn); err != nil {
Expand All @@ -32,34 +31,21 @@ func (c *Conn) recvMsg(m *Message, flags int) error {
if operr != nil {
return os.NewSyscallError("recvmsg", operr)
}
if c.network != "tcp" {
var err error
m.Addr, err = parseInetAddr(sa[:], c.network)
if err != nil {
return err
}
}
m.Addr = from
m.N = n
m.NN = h.controllen()
m.Flags = h.flags()
m.NN = oobn
m.Flags = recvflags
return nil
}

func (c *Conn) sendMsg(m *Message, flags int) error {
m.raceRead()
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte
if m.Addr != nil {
var a [sizeofSockaddrInet6]byte
n := marshalInetAddr(m.Addr, a[:])
sa = a[:n]
}
h.pack(vs, m.Buffers, m.OOB, sa)
var operr error
var n int
var (
operr error
n int
)
fn := func(s uintptr) bool {
n, operr = sendmsg(s, &h, flags)
n, operr = sendmsg(s, m.Buffers, m.OOB, m.Addr, flags)
return ioComplete(flags, operr)
}
if err := c.c.Write(fn); err != nil {
Expand Down
3 changes: 3 additions & 0 deletions internal/socket/socket_test.go
Expand Up @@ -444,6 +444,9 @@ func main() {
if !platforms[runtime.GOOS+"/"+runtime.GOARCH] {
t.Skip("skipping test on non-race-enabled host.")
}
if runtime.Compiler == "gccgo" {
t.Skip("skipping race test when built with gccgo")
}
dir, err := ioutil.TempDir("", "testrace")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
Expand Down
6 changes: 3 additions & 3 deletions internal/socket/sys_stub.go
Expand Up @@ -36,11 +36,11 @@ func setsockopt(s uintptr, level, name int, b []byte) error {
return errNotImplemented
}

func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
return 0, errNotImplemented
func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network string) (n, oobn int, recvflags int, from net.Addr, err error) {
return 0, 0, 0, nil, errNotImplemented
}

func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags int) (int, error) {
return 0, errNotImplemented
}

Expand Down
101 changes: 90 additions & 11 deletions internal/socket/sys_unix.go
Expand Up @@ -8,8 +8,10 @@
package socket

import (
"syscall"
"net"
"unsafe"

"golang.org/x/sys/unix"
)

//go:linkname syscall_getsockopt syscall.getsockopt
Expand All @@ -18,12 +20,6 @@ func syscall_getsockopt(s, level, name int, val unsafe.Pointer, vallen *uint32)
//go:linkname syscall_setsockopt syscall.setsockopt
func syscall_setsockopt(s, level, name int, val unsafe.Pointer, vallen uintptr) error

//go:linkname syscall_recvmsg syscall.recvmsg
func syscall_recvmsg(s int, msg *syscall.Msghdr, flags int) (int, error)

//go:linkname syscall_sendmsg syscall.sendmsg
func syscall_sendmsg(s int, msg *syscall.Msghdr, flags int) (int, error)

func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
l := uint32(len(b))
err := syscall_getsockopt(int(s), level, name, unsafe.Pointer(&b[0]), &l)
Expand All @@ -34,10 +30,93 @@ func setsockopt(s uintptr, level, name int, b []byte) error {
return syscall_setsockopt(int(s), level, name, unsafe.Pointer(&b[0]), uintptr(len(b)))
}

func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
return syscall_recvmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network string) (n, oobn int, recvflags int, from net.Addr, err error) {
var unixFrom unix.Sockaddr
n, oobn, recvflags, unixFrom, err = unix.RecvmsgBuffers(int(s), buffers, oob, flags)
if unixFrom != nil {
from = sockaddrToAddr(unixFrom, network)
}
return
}

func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
return syscall_sendmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags int) (int, error) {
var unixTo unix.Sockaddr
if to != nil {
unixTo = addrToSockaddr(to)
}
return unix.SendmsgBuffers(int(s), buffers, oob, unixTo, flags)
}

// addrToSockaddr converts a net.Addr to a unix.Sockaddr.
func addrToSockaddr(a net.Addr) unix.Sockaddr {
var (
ip net.IP
port int
zone string
)
switch a := a.(type) {
case *net.TCPAddr:
ip = a.IP
port = a.Port
zone = a.Zone
case *net.UDPAddr:
ip = a.IP
port = a.Port
zone = a.Zone
case *net.IPAddr:
ip = a.IP
zone = a.Zone
default:
return nil
}

if ip4 := ip.To4(); ip4 != nil {
sa := unix.SockaddrInet4{Port: port}
copy(sa.Addr[:], ip4)
return &sa
}

if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil {
sa := unix.SockaddrInet6{Port: port}
copy(sa.Addr[:], ip6)
if zone != "" {
sa.ZoneId = uint32(zoneCache.index(zone))
}
return &sa
}

return nil
}

// sockaddrToAddr converts a unix.Sockaddr to a net.Addr.
func sockaddrToAddr(sa unix.Sockaddr, network string) net.Addr {
var (
ip net.IP
port int
zone string
)
switch sa := sa.(type) {
case *unix.SockaddrInet4:
ip = make(net.IP, net.IPv4len)
copy(ip, sa.Addr[:])
port = sa.Port
case *unix.SockaddrInet6:
ip = make(net.IP, net.IPv6len)
copy(ip, sa.Addr[:])
port = sa.Port
if sa.ZoneId > 0 {
zone = zoneCache.name(int(sa.ZoneId))
}
default:
return nil
}

switch network {
case "tcp", "tcp4", "tcp6":
return &net.TCPAddr{IP: ip, Port: port, Zone: zone}
case "udp", "udp4", "udp6":
return &net.UDPAddr{IP: ip, Port: port, Zone: zone}
default:
return &net.IPAddr{IP: ip, Zone: zone}
}
}
7 changes: 4 additions & 3 deletions internal/socket/sys_windows.go
Expand Up @@ -5,6 +5,7 @@
package socket

import (
"net"
"syscall"
"unsafe"

Expand Down Expand Up @@ -37,11 +38,11 @@ func setsockopt(s uintptr, level, name int, b []byte) error {
return syscall.Setsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(unsafe.Pointer(&b[0])), int32(len(b)))
}

func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
return 0, errNotImplemented
func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network string) (n, oobn int, recvflags int, from net.Addr, err error) {
return 0, 0, 0, nil, errNotImplemented
}

func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags int) (int, error) {
return 0, errNotImplemented
}

Expand Down
37 changes: 32 additions & 5 deletions internal/socket/sys_zos_s390x.go
Expand Up @@ -27,12 +27,39 @@ func setsockopt(s uintptr, level, name int, b []byte) error {
return errnoErr(errno)
}

func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
n, _, errno := syscall_syscall(syscall.SYS___RECVMSG_A, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
return int(n), errnoErr(errno)
func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network string) (n, oobn int, recvflags int, from net.Addr, err error) {
var h msghdr
vs := make([]iovec, len(buffers))
var sa []byte
if network != "tcp" {
sa = make([]byte, sizeofSockaddrInet6)
}
h.pack(vs, buffers, oob, sa)
sn, _, errno := syscall_syscall(syscall.SYS___RECVMSG_A, s, uintptr(unsafe.Pointer(&h)), uintptr(flags))
n = int(sn)
oobn = h.controllen()
recvflags = h.flags()
err = errnoErr(errno)
if network != "tcp" {
var err2 error
from, err2 = parseInetAddr(sa, network)
if err2 != nil && err == nil {
err = err2
}
}
return
}

func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
n, _, errno := syscall_syscall(syscall.SYS___SENDMSG_A, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags int) (int, error) {
var h msghdr
vs := make([]iovec, len(buffers))
var sa []byte
if to != nil {
var a [sizeofSockaddrInet6]byte
n := marshalInetAddr(to, a[:])
sa = a[:n]
}
h.pack(vs, buffers, oob, sa)
n, _, errno := syscall_syscall(syscall.SYS___SENDMSG_A, s, uintptr(unsafe.Pointer(&h)), uintptr(flags))
return int(n), errnoErr(errno)
}

0 comments on commit e65d741

Please sign in to comment.