diff options
| author | Mikio Hara <mikioh.mikioh@gmail.com> | 2015-04-23 23:57:00 +0900 |
|---|---|---|
| committer | Mikio Hara <mikioh.mikioh@gmail.com> | 2015-05-13 01:04:23 +0000 |
| commit | 6f7961da28232c609f7c51b3bed7f15db7dd33e1 (patch) | |
| tree | a8a32603037c1e63e45c9361fd705076c1ee70ad /src/internal/syscall | |
| parent | 08ba7dbdfdf0a2824ee122a6214e0263431a6ff0 (diff) | |
| download | go-6f7961da28232c609f7c51b3bed7f15db7dd33e1.tar.xz | |
net, internal/syscall/unix: add SocketConn, SocketPacketConn
FileConn and FilePacketConn APIs accept user-configured socket
descriptors to make them work together with runtime-integrated network
poller, but there's a limitation. The APIs reject protocol sockets that
are not supported by standard library. It's very hard for the net,
syscall packages to look after all platform, feature-specific sockets.
This change allows various platform, feature-specific socket descriptors
to use runtime-integrated network poller by using SocketConn,
SocketPacketConn APIs that bridge between the net, syscall packages and
platforms.
New exposed APIs:
pkg net, func SocketConn(*os.File, SocketAddr) (Conn, error)
pkg net, func SocketPacketConn(*os.File, SocketAddr) (PacketConn, error)
pkg net, type SocketAddr interface { Addr, Raw }
pkg net, type SocketAddr interface, Addr([]uint8) Addr
pkg net, type SocketAddr interface, Raw(Addr) []uint8
Fixes #10565.
Change-Id: Iec57499b3d84bb5cb0bcf3f664330c535eec11e3
Reviewed-on: https://go-review.googlesource.com/9275
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/internal/syscall')
| -rw-r--r-- | src/internal/syscall/unix/socket.go | 39 | ||||
| -rw-r--r-- | src/internal/syscall/unix/socket_linux_386.go | 67 | ||||
| -rw-r--r-- | src/internal/syscall/unix/socket_linux_386.s | 11 | ||||
| -rw-r--r-- | src/internal/syscall/unix/socket_stub.go | 25 | ||||
| -rw-r--r-- | src/internal/syscall/unix/socket_unix.go | 59 |
5 files changed, 201 insertions, 0 deletions
diff --git a/src/internal/syscall/unix/socket.go b/src/internal/syscall/unix/socket.go new file mode 100644 index 0000000000..d7a9b9cb1d --- /dev/null +++ b/src/internal/syscall/unix/socket.go @@ -0,0 +1,39 @@ +// Copyright 2015 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. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package unix + +// Getsockname copies the binary encoding of the current address for s +// into addr. +func Getsockname(s int, addr []byte) error { + return getsockname(s, addr) +} + +// Getpeername copies the binary encoding of the peer address for s +// into addr. +func Getpeername(s int, addr []byte) error { + return getpeername(s, addr) +} + +var emptyPayload uintptr + +// Recvfrom receives a message from s, copying the message into b. +// The socket address addr must be large enough for storing the source +// address of the message. +// Flags must be operation control flags or 0. +// It retunrs the number of bytes copied into b. +func Recvfrom(s int, b []byte, flags int, addr []byte) (int, error) { + return recvfrom(s, b, flags, addr) +} + +// Sendto sends a message to the socket address addr, copying the +// message from b. +// The socket address addr must be suitable for s. +// Flags must be operation control flags or 0. +// It retunrs the number of bytes copied from b. +func Sendto(s int, b []byte, flags int, addr []byte) (int, error) { + return sendto(s, b, flags, addr) +} diff --git a/src/internal/syscall/unix/socket_linux_386.go b/src/internal/syscall/unix/socket_linux_386.go new file mode 100644 index 0000000000..47105e0b1d --- /dev/null +++ b/src/internal/syscall/unix/socket_linux_386.go @@ -0,0 +1,67 @@ +// Copyright 2015 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 unix + +import ( + "syscall" + "unsafe" +) + +const ( + sysGETSOCKNAME = 0x6 + sysGETPEERNAME = 0x7 + sysSENDTO = 0xb + sysRECVFROM = 0xc +) + +func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno) +func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno) + +func getsockname(s int, addr []byte) error { + l := uint32(len(addr)) + _, errno := rawsocketcall(sysGETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&l)), 0, 0, 0) + if errno != 0 { + return error(errno) + } + return nil +} + +func getpeername(s int, addr []byte) error { + l := uint32(len(addr)) + _, errno := rawsocketcall(sysGETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&l)), 0, 0, 0) + if errno != 0 { + return error(errno) + } + return nil +} + +func recvfrom(s int, b []byte, flags int, from []byte) (int, error) { + var p unsafe.Pointer + if len(b) > 0 { + p = unsafe.Pointer(&b[0]) + } else { + p = unsafe.Pointer(&emptyPayload) + } + l := uint32(len(from)) + n, errno := socketcall(sysRECVFROM, uintptr(s), uintptr(p), uintptr(len(b)), uintptr(flags), uintptr(unsafe.Pointer(&from[0])), uintptr(unsafe.Pointer(&l))) + if errno != 0 { + return int(n), error(errno) + } + return int(n), nil +} + +func sendto(s int, b []byte, flags int, to []byte) (int, error) { + var p unsafe.Pointer + if len(b) > 0 { + p = unsafe.Pointer(&b[0]) + } else { + p = unsafe.Pointer(&emptyPayload) + } + n, errno := socketcall(sysSENDTO, uintptr(s), uintptr(p), uintptr(len(b)), uintptr(flags), uintptr(unsafe.Pointer(&to[0])), uintptr(len(to))) + if errno != 0 { + return int(n), error(errno) + } + return int(n), nil +} diff --git a/src/internal/syscall/unix/socket_linux_386.s b/src/internal/syscall/unix/socket_linux_386.s new file mode 100644 index 0000000000..48e2094db5 --- /dev/null +++ b/src/internal/syscall/unix/socket_linux_386.s @@ -0,0 +1,11 @@ +// Copyright 2015 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. + +#include "textflag.h" + +TEXT ·socketcall(SB),NOSPLIT,$0-36 + JMP syscall·socketcall(SB) + +TEXT ·rawsocketcall(SB),NOSPLIT,$0-36 + JMP syscall·socketcall(SB) diff --git a/src/internal/syscall/unix/socket_stub.go b/src/internal/syscall/unix/socket_stub.go new file mode 100644 index 0000000000..1c89ed1820 --- /dev/null +++ b/src/internal/syscall/unix/socket_stub.go @@ -0,0 +1,25 @@ +// Copyright 2015 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. + +// +build nacl solaris + +package unix + +import "syscall" + +func getsockname(s int, addr []byte) error { + return syscall.EOPNOTSUPP +} + +func getpeername(s int, addr []byte) error { + return syscall.EOPNOTSUPP +} + +func recvfrom(s int, b []byte, flags int, from []byte) (int, error) { + return 0, syscall.EOPNOTSUPP +} + +func sendto(s int, b []byte, flags int, to []byte) (int, error) { + return 0, syscall.EOPNOTSUPP +} diff --git a/src/internal/syscall/unix/socket_unix.go b/src/internal/syscall/unix/socket_unix.go new file mode 100644 index 0000000000..a769bb38b6 --- /dev/null +++ b/src/internal/syscall/unix/socket_unix.go @@ -0,0 +1,59 @@ +// Copyright 2015 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. + +// +build darwin dragonfly freebsd linux,!386 netbsd openbsd + +package unix + +import ( + "syscall" + "unsafe" +) + +func getsockname(s int, addr []byte) error { + l := uint32(len(addr)) + _, _, errno := syscall.RawSyscall(syscall.SYS_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&l))) + if errno != 0 { + return error(errno) + } + return nil +} + +func getpeername(s int, addr []byte) error { + l := uint32(len(addr)) + _, _, errno := syscall.RawSyscall(syscall.SYS_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&l))) + if errno != 0 { + return error(errno) + } + return nil +} + +func recvfrom(s int, b []byte, flags int, from []byte) (int, error) { + var p unsafe.Pointer + if len(b) > 0 { + p = unsafe.Pointer(&b[0]) + } else { + p = unsafe.Pointer(&emptyPayload) + } + l := uint32(len(from)) + n, _, errno := syscall.Syscall6(syscall.SYS_RECVFROM, uintptr(s), uintptr(p), uintptr(len(b)), uintptr(flags), uintptr(unsafe.Pointer(&from[0])), uintptr(unsafe.Pointer(&l))) + if errno != 0 { + return int(n), error(errno) + } + return int(n), nil +} + +func sendto(s int, b []byte, flags int, to []byte) (int, error) { + var p unsafe.Pointer + if len(b) > 0 { + p = unsafe.Pointer(&b[0]) + } else { + p = unsafe.Pointer(&emptyPayload) + } + n, _, errno := syscall.Syscall6(syscall.SYS_SENDTO, uintptr(s), uintptr(p), uintptr(len(b)), uintptr(flags), uintptr(unsafe.Pointer(&to[0])), uintptr(len(to))) + if errno != 0 { + return int(n), error(errno) + } + return int(n), nil +} |
