aboutsummaryrefslogtreecommitdiff
path: root/src/internal/syscall
diff options
context:
space:
mode:
authorMikio Hara <mikioh.mikioh@gmail.com>2015-04-23 23:57:00 +0900
committerMikio Hara <mikioh.mikioh@gmail.com>2015-05-13 01:04:23 +0000
commit6f7961da28232c609f7c51b3bed7f15db7dd33e1 (patch)
treea8a32603037c1e63e45c9361fd705076c1ee70ad /src/internal/syscall
parent08ba7dbdfdf0a2824ee122a6214e0263431a6ff0 (diff)
downloadgo-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.go39
-rw-r--r--src/internal/syscall/unix/socket_linux_386.go67
-rw-r--r--src/internal/syscall/unix/socket_linux_386.s11
-rw-r--r--src/internal/syscall/unix/socket_stub.go25
-rw-r--r--src/internal/syscall/unix/socket_unix.go59
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
+}