mirror of https://github.com/golang/go.git
syscall: implement Unix Socket for Windows
Add implementation of AF_UNIX. This works only on Windows 10. https://blogs.msdn.microsoft.com/commandline/2017/12/19/af_unix-comes-to-windows/ Fixes #26072 Change-Id: I76a96a472385a17901885271622fbe55d66bb720 Reviewed-on: https://go-review.googlesource.com/125456 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
parent
ded9411580
commit
76c45877c9
|
|
@ -370,6 +370,7 @@ pkg syscall (windows-386), type CertContext struct, CertInfo uintptr
|
||||||
pkg syscall (windows-386), type CertRevocationInfo struct, CrlInfo uintptr
|
pkg syscall (windows-386), type CertRevocationInfo struct, CrlInfo uintptr
|
||||||
pkg syscall (windows-386), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
pkg syscall (windows-386), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||||
pkg syscall (windows-386), type CertSimpleChain struct, TrustListInfo uintptr
|
pkg syscall (windows-386), type CertSimpleChain struct, TrustListInfo uintptr
|
||||||
|
pkg syscall (windows-386), type RawSockaddrAny struct, Pad [96]int8
|
||||||
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983295
|
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983295
|
||||||
pkg syscall (windows-amd64), type AddrinfoW struct, Addr uintptr
|
pkg syscall (windows-amd64), type AddrinfoW struct, Addr uintptr
|
||||||
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
||||||
|
|
@ -378,3 +379,4 @@ pkg syscall (windows-amd64), type CertContext struct, CertInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
|
pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
||||||
|
pkg syscall (windows-amd64), type RawSockaddrAny struct, Pad [96]int8
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright 2018 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 windows
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/syscall/windows/registry"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isBuild17063() bool {
|
||||||
|
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.READ)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer k.Close()
|
||||||
|
|
||||||
|
s, _, err := k.GetStringValue("CurrentBuild")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ver, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return ver >= 17063
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnixConnLocalWindows(t *testing.T) {
|
||||||
|
if !isBuild17063() {
|
||||||
|
t.Skip("unix test")
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := func(ls *localServer, ln Listener) {}
|
||||||
|
for _, laddr := range []string{"", testUnixAddr()} {
|
||||||
|
laddr := laddr
|
||||||
|
taddr := testUnixAddr()
|
||||||
|
ta, err := ResolveUnixAddr("unix", taddr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ln, err := ListenUnix("unix", ta)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ls, err := (&streamListener{Listener: ln}).newLocalServer()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ls.teardown()
|
||||||
|
if err := ls.buildup(handler); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
la, err := ResolveUnixAddr("unix", laddr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c, err := DialUnix("unix", la, ta)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
c.Close()
|
||||||
|
if la != nil {
|
||||||
|
defer os.Remove(laddr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if laddr == "" {
|
||||||
|
laddr = "@"
|
||||||
|
}
|
||||||
|
var connAddrs = [3]struct{ got, want Addr }{
|
||||||
|
{ln.Addr(), ta},
|
||||||
|
{c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
|
||||||
|
{c.RemoteAddr(), ta},
|
||||||
|
}
|
||||||
|
for _, ca := range connAddrs {
|
||||||
|
if !reflect.DeepEqual(ca.got, ca.want) {
|
||||||
|
t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -634,7 +634,7 @@ type RawSockaddr struct {
|
||||||
|
|
||||||
type RawSockaddrAny struct {
|
type RawSockaddrAny struct {
|
||||||
Addr RawSockaddr
|
Addr RawSockaddr
|
||||||
Pad [96]int8
|
Pad [100]int8
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sockaddr interface {
|
type Sockaddr interface {
|
||||||
|
|
@ -683,19 +683,69 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
|
||||||
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
|
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RawSockaddrUnix struct {
|
||||||
|
Family uint16
|
||||||
|
Path [UNIX_PATH_MAX]int8
|
||||||
|
}
|
||||||
|
|
||||||
type SockaddrUnix struct {
|
type SockaddrUnix struct {
|
||||||
Name string
|
Name string
|
||||||
|
raw RawSockaddrUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
|
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
|
||||||
// TODO(brainman): implement SockaddrUnix.sockaddr()
|
name := sa.Name
|
||||||
return nil, 0, EWINDOWS
|
n := len(name)
|
||||||
|
if n > len(sa.raw.Path) {
|
||||||
|
return nil, 0, EINVAL
|
||||||
|
}
|
||||||
|
if n == len(sa.raw.Path) && name[0] != '@' {
|
||||||
|
return nil, 0, 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) {
|
func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
|
||||||
switch rsa.Addr.Family {
|
switch rsa.Addr.Family {
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
return nil, 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:
|
case AF_INET:
|
||||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
||||||
|
|
|
||||||
|
|
@ -1139,3 +1139,5 @@ const (
|
||||||
SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1
|
SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1
|
||||||
_SYMLINK_FLAG_RELATIVE = 1
|
_SYMLINK_FLAG_RELATIVE = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const UNIX_PATH_MAX = 108 // defined in afunix.h
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue