From fa5fdf94c78965f1aa8423f0cc50b8b8d728b05a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 31 Aug 2018 10:14:39 +0200 Subject: [PATCH] windows: add support for AF_UNIX sockets CL 125456 added the implementation of AF_UNIX to the syscall package. Add the same implementation to golang.org/x/sys/windows as well. This works only on Windows 10. https://blogs.msdn.microsoft.com/commandline/2017/12/19/af_unix-comes-to-windows/ Updates golang/go#26072 Change-Id: Ibd4a17342ed4f9f4f2b16b82c7b02834e681b7b4 Reviewed-on: https://go-review.googlesource.com/132555 Run-TryBot: Tobias Klauser TryBot-Result: Gobot Gobot Reviewed-by: Yasuhiro MATSUMOTO Reviewed-by: Alex Brainman --- windows/syscall_windows.go | 58 +++++++++++++++++++++++++++++++++++--- windows/types_windows.go | 2 ++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index fd89e08e..8a00b71f 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -655,7 +655,7 @@ type RawSockaddr struct { type RawSockaddrAny struct { Addr RawSockaddr - Pad [96]int8 + Pad [100]int8 } type Sockaddr interface { @@ -704,19 +704,69 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } +type RawSockaddrUnix struct { + Family uint16 + Path [UNIX_PATH_MAX]int8 +} + type SockaddrUnix struct { Name string + raw RawSockaddrUnix } func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { - // TODO(brainman): implement SockaddrUnix.sockaddr() - return nil, 0, syscall.EWINDOWS + name := sa.Name + n := len(name) + if n > len(sa.raw.Path) { + return nil, 0, syscall.EINVAL + } + if n == len(sa.raw.Path) && name[0] != '@' { + return nil, 0, syscall.EINVAL + } + sa.raw.Family = AF_UNIX + for i := 0; i < n; i++ { + sa.raw.Path[i] = int8(name[i]) + } + // length is family (uint16), name, NUL. + sl := int32(2) + if n > 0 { + sl += int32(n) + 1 + } + if sa.raw.Path[0] == '@' { + sa.raw.Path[0] = 0 + // Don't count trailing NUL for abstract address. + sl-- + } + + return unsafe.Pointer(&sa.raw), sl, nil } func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { switch rsa.Addr.Family { case AF_UNIX: - return nil, syscall.EWINDOWS + pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) + sa := new(SockaddrUnix) + if pp.Path[0] == 0 { + // "Abstract" Unix domain socket. + // Rewrite leading NUL as @ for textual display. + // (This is the standard convention.) + // Not friendly to overwrite in place, + // but the callers below don't care. + pp.Path[0] = '@' + } + + // Assume path ends at NUL. + // This is not technically the Linux semantics for + // abstract Unix domain sockets--they are supposed + // to be uninterpreted fixed-size binary blobs--but + // everyone uses this convention. + n := 0 + for n < len(pp.Path) && pp.Path[n] != 0 { + n++ + } + bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] + sa.Name = string(bytes) + return sa, nil case AF_INET: pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) diff --git a/windows/types_windows.go b/windows/types_windows.go index 7f8b3af4..4d0402a3 100644 --- a/windows/types_windows.go +++ b/windows/types_windows.go @@ -1465,3 +1465,5 @@ type ConsoleScreenBufferInfo struct { Window SmallRect MaximumWindowSize Coord } + +const UNIX_PATH_MAX = 108 // defined in afunix.h