mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-25 19:54:38 +00:00
go: vendor shared hvsock/vsock packages
These packages will be shared by a number of utilities so vendoring them in a shared place. Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
This commit is contained in:
parent
aeacb7b283
commit
124eb81ca2
71
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/LICENSE
generated
vendored
Normal file
71
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/LICENSE
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
Copyright 2016 Rolf Neugebauer <rolf.neugebauer@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Some of the code in ./go/hvsock.go, ./go/hvsock_windows.go, and
|
||||
zsyscall_windows.go is covered by the following licenses:
|
||||
==============================================================================
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
and
|
||||
===
|
||||
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
49
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/examples/client.go
generated
vendored
Normal file
49
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/examples/client.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"../"
|
||||
)
|
||||
|
||||
var (
|
||||
vmstr string
|
||||
portstr string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&vmstr, "vm", "", "Hyper-V VM to connect to")
|
||||
flag.StringVar(&portstr, "port", "23a432c2-537a-4291-bcb5-d62504644739", "Hyper-V sockets service/port")
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.LstdFlags)
|
||||
flag.Parse()
|
||||
|
||||
vmid, err := hvsock.GuidFromString(vmstr)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to parse GUID", vmstr, err)
|
||||
}
|
||||
svcid, err := hvsock.GuidFromString(portstr)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to parse GUID", portstr, err)
|
||||
}
|
||||
|
||||
c, err := hvsock.Dial(hvsock.HypervAddr{VmId: vmid, ServiceId: svcid})
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to Dial:\n", vmstr, portstr, err)
|
||||
}
|
||||
|
||||
fmt.Println("Send: hello")
|
||||
l, err := fmt.Fprintf(c, "hello\n")
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to send: ", err)
|
||||
}
|
||||
fmt.Println("Sent: %s bytes", l)
|
||||
|
||||
message, _ := bufio.NewReader(c).ReadString('\n')
|
||||
fmt.Println("From SVR: " + message)
|
||||
}
|
131
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/examples/hvgoecho.go
generated
vendored
Normal file
131
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/examples/hvgoecho.go
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"../hvsock"
|
||||
)
|
||||
|
||||
var (
|
||||
clientStr string
|
||||
serverMode bool
|
||||
|
||||
svcid, _ = hvsock.GuidFromString("3049197C-9A4E-4FBF-9367-97F792F16994")
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&clientStr, "c", "", "Client")
|
||||
flag.BoolVar(&serverMode, "s", false, "Start as a Server")
|
||||
}
|
||||
|
||||
func server() {
|
||||
l, err := hvsock.Listen(hvsock.HypervAddr{VmId: hvsock.GUID_WILDCARD, ServiceId: svcid})
|
||||
if err != nil {
|
||||
log.Fatalln("Listen():", err)
|
||||
}
|
||||
defer func() {
|
||||
l.Close()
|
||||
}()
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Fatalln("Accept(): ", err)
|
||||
}
|
||||
fmt.Printf("Received message %s -> %s \n", conn.RemoteAddr(), conn.LocalAddr())
|
||||
|
||||
go handleRequest(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handleRequest(c net.Conn) {
|
||||
defer func() {
|
||||
fmt.Printf("Closing\n")
|
||||
err := c.Close()
|
||||
if err != nil {
|
||||
log.Fatalln("Close():", err)
|
||||
}
|
||||
}()
|
||||
|
||||
n, err := io.Copy(c, c)
|
||||
if err != nil {
|
||||
log.Fatalln("Copy():", err)
|
||||
}
|
||||
fmt.Printf("Copied Bytes: %d\n", n)
|
||||
|
||||
fmt.Printf("Sending BYE message\n")
|
||||
// The '\n' is important as the client use ReadString()
|
||||
_, err = fmt.Fprintf(c, "Got %d bytes. Bye\n", n)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to send: ", err)
|
||||
}
|
||||
fmt.Printf("Sent bye\n")
|
||||
}
|
||||
|
||||
func client(vmid hvsock.GUID) {
|
||||
sa := hvsock.HypervAddr{VmId: vmid, ServiceId: svcid}
|
||||
c, err := hvsock.Dial(sa)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to Dial:\n", sa.VmId.String(), sa.ServiceId.String(), err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
fmt.Printf("Closing\n")
|
||||
c.Close()
|
||||
}()
|
||||
|
||||
fmt.Printf("Send: hello\n")
|
||||
// Note the '\n' is significant as we use ReadString below
|
||||
l, err := fmt.Fprintf(c, "hello\n")
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to send: ", err)
|
||||
}
|
||||
fmt.Printf("Sent: %d bytes\n", l)
|
||||
|
||||
message, err := bufio.NewReader(c).ReadString('\n')
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to receive: ", err)
|
||||
}
|
||||
fmt.Printf("From SVR: %s", message)
|
||||
|
||||
fmt.Printf("CloseWrite()\n")
|
||||
c.CloseWrite()
|
||||
|
||||
fmt.Printf("Waiting for Bye message\n")
|
||||
message, err = bufio.NewReader(c).ReadString('\n')
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to receive: ", err)
|
||||
}
|
||||
fmt.Printf("From SVR: %s", message)
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.LstdFlags)
|
||||
flag.Parse()
|
||||
|
||||
if serverMode {
|
||||
fmt.Printf("Starting server\n")
|
||||
server()
|
||||
}
|
||||
|
||||
vmid := hvsock.GUID_ZERO
|
||||
var err error
|
||||
if strings.Contains(clientStr, "-") {
|
||||
vmid, err = hvsock.GuidFromString(clientStr)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't parse GUID: ", clientStr)
|
||||
}
|
||||
} else if clientStr == "parent" {
|
||||
vmid = hvsock.GUID_PARENT
|
||||
} else {
|
||||
vmid = hvsock.GUID_LOOPBACK
|
||||
}
|
||||
fmt.Printf("Client connecting to %s", vmid.String())
|
||||
client(vmid)
|
||||
}
|
243
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/examples/hvgostress.go
generated
vendored
Normal file
243
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/examples/hvgostress.go
generated
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"crypto/md5"
|
||||
"math/rand"
|
||||
"sync/atomic"
|
||||
|
||||
"../hvsock"
|
||||
)
|
||||
|
||||
var (
|
||||
clientStr string
|
||||
serverMode bool
|
||||
maxDataLen int
|
||||
connections int
|
||||
sleepTime int
|
||||
verbose int
|
||||
exitOnError bool
|
||||
parallel int
|
||||
svcid, _ = hvsock.GuidFromString("3049197C-9A4E-4FBF-9367-97F792F16994")
|
||||
|
||||
connCounter int32
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&clientStr, "c", "", "Client")
|
||||
flag.BoolVar(&serverMode, "s", false, "Start as a Server")
|
||||
flag.IntVar(&maxDataLen, "l", 64*1024, "Maximum Length of data")
|
||||
flag.IntVar(&connections, "i", 100, "Total number of connections")
|
||||
flag.IntVar(&sleepTime, "w", 0, "Sleep time in seconds between new connections")
|
||||
flag.IntVar(¶llel, "p", 1, "Run n connections in parallel")
|
||||
flag.BoolVar(&exitOnError, "e", false, "Exit when an error occurs")
|
||||
flag.IntVar(&verbose, "v", 0, "Set the verbosity level")
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.LstdFlags)
|
||||
flag.Parse()
|
||||
|
||||
if verbose > 2 {
|
||||
hvsock.Debug = true
|
||||
}
|
||||
|
||||
if serverMode {
|
||||
fmt.Printf("Starting server\n")
|
||||
server()
|
||||
return
|
||||
}
|
||||
|
||||
// Client mode
|
||||
vmid := hvsock.GUID_ZERO
|
||||
var err error
|
||||
if strings.Contains(clientStr, "-") {
|
||||
vmid, err = hvsock.GuidFromString(clientStr)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't parse GUID: ", clientStr)
|
||||
}
|
||||
} else if clientStr == "parent" {
|
||||
vmid = hvsock.GUID_PARENT
|
||||
} else {
|
||||
vmid = hvsock.GUID_LOOPBACK
|
||||
}
|
||||
|
||||
if parallel <= 1 {
|
||||
// No parallelism, run in the main thread.
|
||||
fmt.Printf("Client connecting to %s\n", vmid.String())
|
||||
for i := 0; i < connections; i++ {
|
||||
client(vmid, i)
|
||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Parallel clients
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < parallel; i++ {
|
||||
wg.Add(1)
|
||||
go parClient(&wg, vmid)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func server() {
|
||||
l, err := hvsock.Listen(hvsock.HypervAddr{VmId: hvsock.GUID_WILDCARD, ServiceId: svcid})
|
||||
if err != nil {
|
||||
log.Fatalln("Listen():", err)
|
||||
}
|
||||
defer func() {
|
||||
l.Close()
|
||||
}()
|
||||
|
||||
connid := 0
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("Accept(): %s\n", err)
|
||||
}
|
||||
|
||||
prDebug("[%05d] accept(): %s -> %s \n", connid, conn.RemoteAddr(), conn.LocalAddr())
|
||||
go handleRequest(conn, connid)
|
||||
connid++
|
||||
}
|
||||
}
|
||||
|
||||
func handleRequest(c net.Conn, connid int) {
|
||||
defer func() {
|
||||
prDebug("[%05d] Closing\n", connid)
|
||||
err := c.Close()
|
||||
if err != nil {
|
||||
prError("[%05d] Close(): %s\n", connid, err)
|
||||
}
|
||||
}()
|
||||
|
||||
n, err := io.Copy(c, c)
|
||||
if err != nil {
|
||||
prError("[%05d] Copy(): %s", connid, err)
|
||||
return
|
||||
}
|
||||
prInfo("[%05d] Copied Bytes: %d\n", connid, n)
|
||||
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
prDebug("[%05d] Sending BYE message\n", connid)
|
||||
|
||||
// The '\n' is important as the client use ReadString()
|
||||
_, err = fmt.Fprintf(c, "Got %d bytes. Bye\n", n)
|
||||
if err != nil {
|
||||
prError("[%05d] Failed to send: %s", connid, err)
|
||||
return
|
||||
}
|
||||
prDebug("[%05d] Sent bye\n", connid)
|
||||
}
|
||||
|
||||
func parClient(wg *sync.WaitGroup, vmid hvsock.GUID) {
|
||||
connid := int(atomic.AddInt32(&connCounter, 1))
|
||||
for connid < connections {
|
||||
client(vmid, connid)
|
||||
connid = int(atomic.AddInt32(&connCounter, 1))
|
||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func client(vmid hvsock.GUID, conid int) {
|
||||
sa := hvsock.HypervAddr{VmId: vmid, ServiceId: svcid}
|
||||
c, err := hvsock.Dial(sa)
|
||||
if err != nil {
|
||||
prError("[%05d] Failed to Dial: %s:%s %s\n", conid, sa.VmId.String(), sa.ServiceId.String(), err)
|
||||
}
|
||||
|
||||
defer c.Close()
|
||||
|
||||
// Create buffer with random data and random length.
|
||||
// Make sure the buffer is not zero-length
|
||||
buflen := rand.Intn(maxDataLen-1) + 1
|
||||
txbuf := randBuf(buflen)
|
||||
csum0 := md5.Sum(txbuf)
|
||||
|
||||
prDebug("[%05d] TX: %d bytes, md5=%02x\n", conid, buflen, csum0)
|
||||
|
||||
w := make(chan int)
|
||||
go func() {
|
||||
l, err := c.Write(txbuf)
|
||||
if err != nil {
|
||||
prError("[%05d] Failed to send: %s\n", conid, err)
|
||||
}
|
||||
if l != buflen {
|
||||
prError("[%05d] Failed to send enough data: %d\n", conid, l)
|
||||
}
|
||||
|
||||
// Tell the other end that we are done
|
||||
c.CloseWrite()
|
||||
|
||||
w <- l
|
||||
}()
|
||||
|
||||
rxbuf := make([]byte, buflen)
|
||||
|
||||
n, err := io.ReadFull(bufio.NewReader(c), rxbuf)
|
||||
if err != nil {
|
||||
prError("[%05d] Failed to receive: %s\n", conid, err)
|
||||
return
|
||||
}
|
||||
csum1 := md5.Sum(rxbuf)
|
||||
|
||||
totalSent := <-w
|
||||
|
||||
prInfo("[%05d] RX: %d bytes, md5=%02x (sent=%d)\n", conid, n, csum1, totalSent)
|
||||
if csum0 != csum1 {
|
||||
prError("[%05d] Checksums don't match", conid)
|
||||
}
|
||||
|
||||
// Wait for Bye message
|
||||
message, err := bufio.NewReader(c).ReadString('\n')
|
||||
if err != nil {
|
||||
prError("[%05d] Failed to receive bye: %s\n", conid, err)
|
||||
}
|
||||
prDebug("[%05d] From SVR: %s", conid, message)
|
||||
}
|
||||
|
||||
func randBuf(n int) []byte {
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = byte(rand.Intn(255))
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func prError(format string, args ...interface{}) {
|
||||
if exitOnError {
|
||||
log.Fatalf(format, args...)
|
||||
} else {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func prInfo(format string, args ...interface{}) {
|
||||
if verbose > 0 {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func prDebug(format string, args ...interface{}) {
|
||||
if verbose > 1 {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
412
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock.go
generated
vendored
Normal file
412
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock.go
generated
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
package hvsock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// This package provides a Go interface to Hyper-V sockets both on
|
||||
// Windows and on Linux (assuming the appropriate Linux kernel patches
|
||||
// have been applied).
|
||||
//
|
||||
// Unfortunately, it is not easy/possible to extend the existing Go
|
||||
// socket implementations with new Address Families, so this module
|
||||
// wraps directly around system calls (and handles Windows'
|
||||
// asynchronous system calls).
|
||||
//
|
||||
// There is an additional wrinkle. Hyper-V sockets in currently
|
||||
// shipping versions of Windows don't support graceful and/or
|
||||
// unidirectional shutdown(). So we turn a stream based protocol into
|
||||
// message based protocol which allows to send in-line "messages" to
|
||||
// the other end. We then provide a stream based interface on top of
|
||||
// that. Yuk.
|
||||
//
|
||||
// The message interface is pretty simple. We first send a 32bit
|
||||
// message containing the size of the data in the following
|
||||
// message. Messages are limited to 'maxmsgsize'. Special message
|
||||
// (without data), `shutdownrd` and 'shutdownwr' are used to used to
|
||||
// signal a shutdown to the other end.
|
||||
|
||||
const (
|
||||
maxMsgSize = 32 * 1024 // Maximum message size
|
||||
)
|
||||
|
||||
// Hypper-V sockets use GUIDs for addresses and "ports"
|
||||
type GUID [16]byte
|
||||
|
||||
// Convert a GUID into a string
|
||||
func (g *GUID) String() string {
|
||||
/* XXX This assume little endian */
|
||||
return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
g[3], g[2], g[1], g[0],
|
||||
g[5], g[4],
|
||||
g[7], g[6],
|
||||
g[8], g[9],
|
||||
g[10], g[11], g[12], g[13], g[14], g[15])
|
||||
}
|
||||
|
||||
// Parse a GUID string
|
||||
func GuidFromString(s string) (GUID, error) {
|
||||
var g GUID
|
||||
var err error
|
||||
_, err = fmt.Sscanf(s, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
&g[3], &g[2], &g[1], &g[0],
|
||||
&g[5], &g[4],
|
||||
&g[7], &g[6],
|
||||
&g[8], &g[9],
|
||||
&g[10], &g[11], &g[12], &g[13], &g[14], &g[15])
|
||||
return g, err
|
||||
}
|
||||
|
||||
type HypervAddr struct {
|
||||
VmId GUID
|
||||
ServiceId GUID
|
||||
}
|
||||
|
||||
func (a HypervAddr) Network() string { return "hvsock" }
|
||||
|
||||
func (a HypervAddr) String() string {
|
||||
vmid := a.VmId.String()
|
||||
svc := a.ServiceId.String()
|
||||
|
||||
return vmid + ":" + svc
|
||||
}
|
||||
|
||||
var (
|
||||
Debug = false // Set to True to enable additional debug output
|
||||
|
||||
GUID_ZERO, _ = GuidFromString("00000000-0000-0000-0000-000000000000")
|
||||
GUID_WILDCARD, _ = GuidFromString("00000000-0000-0000-0000-000000000000")
|
||||
GUID_BROADCAST, _ = GuidFromString("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")
|
||||
GUID_CHILDREN, _ = GuidFromString("90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd")
|
||||
GUID_LOOPBACK, _ = GuidFromString("e0e16197-dd56-4a10-9195-5ee7a155a838")
|
||||
GUID_PARENT, _ = GuidFromString("a42e7cda-d03f-480c-9cc2-a4de20abb878")
|
||||
)
|
||||
|
||||
func Dial(raddr HypervAddr) (Conn, error) {
|
||||
fd, err := syscall.Socket(AF_HYPERV, syscall.SOCK_STREAM, SHV_PROTO_RAW)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = connect(fd, &raddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, err := newHVsockConn(fd, HypervAddr{VmId: GUID_ZERO, ServiceId: GUID_ZERO}, raddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v.wrlock = &sync.Mutex{}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func Listen(addr HypervAddr) (net.Listener, error) {
|
||||
|
||||
accept_fd, err := syscall.Socket(AF_HYPERV, syscall.SOCK_STREAM, SHV_PROTO_RAW)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = bind(accept_fd, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = syscall.Listen(accept_fd, syscall.SOMAXCONN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &hvsockListener{accept_fd, addr}, nil
|
||||
}
|
||||
|
||||
const (
|
||||
shutdownrd = 0xdeadbeef // Message for CloseRead()
|
||||
shutdownwr = 0xbeefdead // Message for CloseWrite()
|
||||
closemsg = 0xdeaddead // Message for Close()
|
||||
)
|
||||
|
||||
// Conn is a hvsock connection which support half-close.
|
||||
type Conn interface {
|
||||
net.Conn
|
||||
CloseRead() error
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
func (v *hvsockListener) Accept() (net.Conn, error) {
|
||||
var raddr HypervAddr
|
||||
fd, err := accept(v.accept_fd, &raddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a, err := newHVsockConn(fd, v.laddr, raddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.wrlock = &sync.Mutex{}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (v *hvsockListener) Close() error {
|
||||
// Note this won't cause the Accept to unblock.
|
||||
return syscall.Close(v.accept_fd)
|
||||
}
|
||||
|
||||
func (v *hvsockListener) Addr() net.Addr {
|
||||
return HypervAddr{VmId: v.laddr.VmId, ServiceId: v.laddr.ServiceId}
|
||||
}
|
||||
|
||||
/*
|
||||
* A wrapper around FileConn which supports CloseRead and CloseWrite
|
||||
*/
|
||||
|
||||
var (
|
||||
errSocketClosed = errors.New("HvSocket has already been closed")
|
||||
errSocketWriteClosed = errors.New("HvSocket has been closed for write")
|
||||
errSocketReadClosed = errors.New("HvSocket has been closed for read")
|
||||
errSocketMsgSize = errors.New("HvSocket message was of wrong size")
|
||||
errSocketMsgWrite = errors.New("HvSocket writing message")
|
||||
errSocketNotEnoughData = errors.New("HvSocket not enough data written")
|
||||
errSocketUnImplemented = errors.New("Function not implemented")
|
||||
)
|
||||
|
||||
type HVsockConn struct {
|
||||
hvsockConn
|
||||
|
||||
wrlock *sync.Mutex
|
||||
|
||||
writeClosed bool
|
||||
readClosed bool
|
||||
|
||||
bytesToRead int
|
||||
}
|
||||
|
||||
func (v *HVsockConn) LocalAddr() net.Addr {
|
||||
return v.local
|
||||
}
|
||||
|
||||
func (v *HVsockConn) RemoteAddr() net.Addr {
|
||||
return v.remote
|
||||
}
|
||||
|
||||
func (v *HVsockConn) Close() error {
|
||||
prDebug("Close\n")
|
||||
|
||||
v.readClosed = true
|
||||
v.writeClosed = true
|
||||
|
||||
prDebug("TX: Close\n")
|
||||
v.wrlock.Lock()
|
||||
err := v.sendMsg(closemsg)
|
||||
v.wrlock.Unlock()
|
||||
if err != nil {
|
||||
// chances are that the other end beat us to the close
|
||||
prDebug("Mmmm. %s\n", err)
|
||||
return v.close()
|
||||
}
|
||||
|
||||
// wait for reply/ignore errors
|
||||
// we may get a EOF because the other end closed,
|
||||
b := make([]byte, 4)
|
||||
_, _ = v.read(b)
|
||||
prDebug("close\n")
|
||||
return v.close()
|
||||
}
|
||||
|
||||
func (v *HVsockConn) CloseRead() error {
|
||||
if v.readClosed {
|
||||
return errSocketReadClosed
|
||||
}
|
||||
|
||||
prDebug("TX: Shutdown Read\n")
|
||||
v.wrlock.Lock()
|
||||
err := v.sendMsg(shutdownrd)
|
||||
v.wrlock.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.readClosed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *HVsockConn) CloseWrite() error {
|
||||
if v.writeClosed {
|
||||
return errSocketWriteClosed
|
||||
}
|
||||
|
||||
prDebug("TX: Shutdown Write\n")
|
||||
v.wrlock.Lock()
|
||||
err := v.sendMsg(shutdownwr)
|
||||
v.wrlock.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.writeClosed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Read into buffer. This function turns a stream interface into
|
||||
// messages and also handles the inband control messages.
|
||||
func (v *HVsockConn) Read(buf []byte) (int, error) {
|
||||
if v.readClosed {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
if v.bytesToRead == 0 {
|
||||
for {
|
||||
// wait for next message
|
||||
b := make([]byte, 4)
|
||||
|
||||
n, err := v.read(b)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if n != 4 {
|
||||
return n, errSocketMsgSize
|
||||
}
|
||||
|
||||
msg := int(binary.LittleEndian.Uint32(b))
|
||||
if msg == shutdownwr {
|
||||
// The other end shutdown write. No point reading more
|
||||
v.readClosed = true
|
||||
prDebug("RX: ShutdownWrite\n")
|
||||
return 0, io.EOF
|
||||
} else if msg == shutdownrd {
|
||||
// The other end shutdown read. No point writing more
|
||||
v.writeClosed = true
|
||||
prDebug("RX: ShutdownRead\n")
|
||||
} else if msg == closemsg {
|
||||
// Setting write close here forces a proper close
|
||||
v.writeClosed = true
|
||||
prDebug("RX: Close\n")
|
||||
v.Close()
|
||||
} else {
|
||||
v.bytesToRead = msg
|
||||
if v.bytesToRead == 0 {
|
||||
// XXX Something is odd. If I don't have this here, this
|
||||
// case is hit. However, with this code in place this
|
||||
// case never get's hit. Suspect overly eager GC...
|
||||
log.Printf("RX: Zero length %02x", b)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, we know there is v.bytesToRead worth of
|
||||
// data coming our way. Read it directly into to buffer passed
|
||||
// in by the caller making sure we do not read mode than we
|
||||
// should read by splicing the buffer.
|
||||
toRead := min(len(buf), v.bytesToRead)
|
||||
prDebug("READ: %d len=0x%x\n", int(v.fd), toRead)
|
||||
n, err := v.read(buf[:toRead])
|
||||
if err != nil || n == 0 {
|
||||
v.readClosed = true
|
||||
return n, err
|
||||
}
|
||||
v.bytesToRead -= n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (v *HVsockConn) Write(buf []byte) (int, error) {
|
||||
if v.writeClosed {
|
||||
return 0, errSocketWriteClosed
|
||||
}
|
||||
|
||||
var err error
|
||||
toWrite := len(buf)
|
||||
written := 0
|
||||
|
||||
prDebug("WRITE: %d Total len=%x\n", int(v.fd), len(buf))
|
||||
|
||||
for toWrite > 0 {
|
||||
if v.writeClosed {
|
||||
return 0, errSocketWriteClosed
|
||||
}
|
||||
|
||||
// We write batches of MSG + data which need to be
|
||||
// "atomic". We don't want to hold the lock for the
|
||||
// entire Write() in case some other threads wants to
|
||||
// send OOB data, e.g. for closing.
|
||||
|
||||
v.wrlock.Lock()
|
||||
|
||||
thisBatch := min(toWrite, maxMsgSize)
|
||||
prDebug("WRITE: %d len=%x\n", int(v.fd), thisBatch)
|
||||
// Write message header
|
||||
err = v.sendMsg(uint32(thisBatch))
|
||||
if err != nil {
|
||||
prDebug("Write MSG Error: %s\n", err)
|
||||
goto ErrOut
|
||||
}
|
||||
|
||||
// Write data
|
||||
n, err := v.write(buf[written : written+thisBatch])
|
||||
if err != nil {
|
||||
prDebug("Write Error 3\n")
|
||||
goto ErrOut
|
||||
}
|
||||
if n != thisBatch {
|
||||
prDebug("Write Error 4\n")
|
||||
err = errSocketNotEnoughData
|
||||
goto ErrOut
|
||||
}
|
||||
toWrite -= n
|
||||
written += n
|
||||
v.wrlock.Unlock()
|
||||
}
|
||||
|
||||
return written, nil
|
||||
|
||||
ErrOut:
|
||||
v.wrlock.Unlock()
|
||||
v.writeClosed = true
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// hvsockConn, SetDeadline(), SetReadDeadline(), and
|
||||
// SetWriteDeadline() are OS specific.
|
||||
|
||||
// Send a message to the other end
|
||||
// The Lock must be held to call this functions
|
||||
func (v *HVsockConn) sendMsg(msg uint32) error {
|
||||
b := make([]byte, 4)
|
||||
|
||||
binary.LittleEndian.PutUint32(b, msg)
|
||||
n, err := v.write(b)
|
||||
if err != nil {
|
||||
prDebug("Write Error 1\n")
|
||||
return err
|
||||
}
|
||||
if n != len(b) {
|
||||
return errSocketMsgWrite
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func prDebug(format string, args ...interface{}) {
|
||||
if Debug {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
69
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock_darwin.go
generated
vendored
Normal file
69
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock_darwin.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
// Dummy implementation to compile on Mac OSX
|
||||
|
||||
package hvsock
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
AF_HYPERV = 42
|
||||
SHV_PROTO_RAW = 1
|
||||
)
|
||||
|
||||
type hvsockListener struct {
|
||||
accept_fd int
|
||||
laddr HypervAddr
|
||||
}
|
||||
|
||||
//
|
||||
// System call wrapper
|
||||
//
|
||||
func connect(s int, a *HypervAddr) (err error) {
|
||||
return errors.New("connect() not implemented")
|
||||
}
|
||||
|
||||
func bind(s int, a HypervAddr) error {
|
||||
return errors.New("bind() not implemented")
|
||||
}
|
||||
|
||||
func accept(s int, a *HypervAddr) (int, error) {
|
||||
return 0, errors.New("accept() not implemented")
|
||||
}
|
||||
|
||||
// Internal representation. Complex mostly due to asynch send()/recv() syscalls.
|
||||
type hvsockConn struct {
|
||||
fd int
|
||||
local HypervAddr
|
||||
remote HypervAddr
|
||||
}
|
||||
|
||||
// Main constructor
|
||||
func newHVsockConn(fd int, local HypervAddr, remote HypervAddr) (*HVsockConn, error) {
|
||||
v := &hvsockConn{local: local, remote: remote}
|
||||
return &HVsockConn{hvsockConn: *v}, errors.New("newHVsockConn() not implemented")
|
||||
}
|
||||
|
||||
func (v *HVsockConn) close() error {
|
||||
return errors.New("close() not implemented")
|
||||
}
|
||||
|
||||
func (v *HVsockConn) read(buf []byte) (int, error) {
|
||||
return 0, errors.New("read() not implemented")
|
||||
}
|
||||
|
||||
func (v *HVsockConn) write(buf []byte) (int, error) {
|
||||
return 0, errors.New("write() not implemented")
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetReadDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetWriteDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
147
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock_linux.go
generated
vendored
Normal file
147
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock_linux.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
package hvsock
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
struct sockaddr_hv {
|
||||
unsigned short shv_family;
|
||||
unsigned short reserved;
|
||||
unsigned char shv_vm_id[16];
|
||||
unsigned char shv_service_id[16];
|
||||
};
|
||||
int bind_sockaddr_hv(int fd, const struct sockaddr_hv *sa_hv) {
|
||||
return bind(fd, (const struct sockaddr*)sa_hv, sizeof(*sa_hv));
|
||||
}
|
||||
int connect_sockaddr_hv(int fd, const struct sockaddr_hv *sa_hv) {
|
||||
return connect(fd, (const struct sockaddr*)sa_hv, sizeof(*sa_hv));
|
||||
}
|
||||
int accept_hv(int fd, struct sockaddr_hv *sa_hv, socklen_t *sa_hv_len) {
|
||||
return accept4(fd, (struct sockaddr *)sa_hv, sa_hv_len, 0);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
AF_HYPERV = 43
|
||||
SHV_PROTO_RAW = 1
|
||||
)
|
||||
|
||||
type hvsockListener struct {
|
||||
accept_fd int
|
||||
laddr HypervAddr
|
||||
}
|
||||
|
||||
//
|
||||
// System call wrapper
|
||||
//
|
||||
func connect(s int, a *HypervAddr) (err error) {
|
||||
sa := C.struct_sockaddr_hv{}
|
||||
sa.shv_family = AF_HYPERV
|
||||
sa.reserved = 0
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
sa.shv_vm_id[i] = C.uchar(a.VmId[i])
|
||||
}
|
||||
for i := 0; i < 16; i++ {
|
||||
sa.shv_service_id[i] = C.uchar(a.ServiceId[i])
|
||||
}
|
||||
|
||||
if ret := C.connect_sockaddr_hv(C.int(s), &sa); ret != 0 {
|
||||
return errors.New("connect() returned " + strconv.Itoa(int(ret)))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func bind(s int, a HypervAddr) error {
|
||||
sa := C.struct_sockaddr_hv{}
|
||||
sa.shv_family = AF_HYPERV
|
||||
sa.reserved = 0
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
// XXX this should take the address from `a` but Linux
|
||||
// currently only support 0s
|
||||
sa.shv_vm_id[i] = C.uchar(GUID_ZERO[i])
|
||||
}
|
||||
for i := 0; i < 16; i++ {
|
||||
sa.shv_service_id[i] = C.uchar(a.ServiceId[i])
|
||||
}
|
||||
|
||||
if ret := C.bind_sockaddr_hv(C.int(s), &sa); ret != 0 {
|
||||
return errors.New("bind() returned " + strconv.Itoa(int(ret)))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func accept(s int, a *HypervAddr) (int, error) {
|
||||
var accept_sa C.struct_sockaddr_hv
|
||||
var accept_sa_len C.socklen_t
|
||||
|
||||
accept_sa_len = C.sizeof_struct_sockaddr_hv
|
||||
fd, err := C.accept_hv(C.int(s), &accept_sa, &accept_sa_len)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
a.VmId = guidFromC(accept_sa.shv_vm_id)
|
||||
a.ServiceId = guidFromC(accept_sa.shv_service_id)
|
||||
|
||||
return int(fd), nil
|
||||
}
|
||||
|
||||
// Internal representation. Complex mostly due to asynch send()/recv() syscalls.
|
||||
type hvsockConn struct {
|
||||
fd int
|
||||
hvsock *os.File
|
||||
local HypervAddr
|
||||
remote HypervAddr
|
||||
}
|
||||
|
||||
// Main constructor
|
||||
func newHVsockConn(fd int, local HypervAddr, remote HypervAddr) (*HVsockConn, error) {
|
||||
hvsock := os.NewFile(uintptr(fd), fmt.Sprintf("hvsock:%d", fd))
|
||||
v := &hvsockConn{fd: fd, hvsock: hvsock, local: local, remote: remote}
|
||||
|
||||
return &HVsockConn{hvsockConn: *v}, nil
|
||||
}
|
||||
|
||||
func (v *HVsockConn) close() error {
|
||||
return v.hvsock.Close()
|
||||
}
|
||||
|
||||
func (v *HVsockConn) read(buf []byte) (int, error) {
|
||||
return v.hvsock.Read(buf)
|
||||
}
|
||||
|
||||
func (v *HVsockConn) write(buf []byte) (int, error) {
|
||||
return v.hvsock.Write(buf)
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetReadDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetWriteDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
||||
|
||||
func guidFromC(cg [16]C.uchar) GUID {
|
||||
var g GUID
|
||||
for i := 0; i < 16; i++ {
|
||||
g[i] = byte(cg[i])
|
||||
}
|
||||
return g
|
||||
}
|
309
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock_windows.go
generated
vendored
Normal file
309
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/hvsock_windows.go
generated
vendored
Normal file
@ -0,0 +1,309 @@
|
||||
package hvsock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Make sure Winsock2 is initialised
|
||||
func init() {
|
||||
e := syscall.WSAStartup(uint32(0x202), &wsaData)
|
||||
if e != nil {
|
||||
log.Fatal("WSAStartup", e)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
AF_HYPERV = 34
|
||||
SHV_PROTO_RAW = 1
|
||||
socket_error = uintptr(^uint32(0))
|
||||
)
|
||||
|
||||
// struck sockaddr equivalent
|
||||
type rawSockaddrHyperv struct {
|
||||
Family uint16
|
||||
Reserved uint16
|
||||
VmId GUID
|
||||
ServiceId GUID
|
||||
}
|
||||
|
||||
type hvsockListener struct {
|
||||
accept_fd syscall.Handle
|
||||
laddr HypervAddr
|
||||
}
|
||||
|
||||
// Internal representation. Complex mostly due to asynch send()/recv() syscalls.
|
||||
type hvsockConn struct {
|
||||
fd syscall.Handle
|
||||
local HypervAddr
|
||||
remote HypervAddr
|
||||
|
||||
wg sync.WaitGroup
|
||||
closing bool
|
||||
readDeadline time.Time
|
||||
writeDeadline time.Time
|
||||
}
|
||||
|
||||
// Used for async system calls
|
||||
const (
|
||||
cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
|
||||
cFILE_SKIP_SET_EVENT_ON_HANDLE = 2
|
||||
)
|
||||
|
||||
var (
|
||||
errTimeout = &timeoutError{}
|
||||
|
||||
wsaData syscall.WSAData
|
||||
)
|
||||
|
||||
type timeoutError struct{}
|
||||
|
||||
func (e *timeoutError) Error() string { return "i/o timeout" }
|
||||
func (e *timeoutError) Timeout() bool { return true }
|
||||
func (e *timeoutError) Temporary() bool { return true }
|
||||
|
||||
// Main constructor
|
||||
func newHVsockConn(h syscall.Handle, local HypervAddr, remote HypervAddr) (*HVsockConn, error) {
|
||||
ioInitOnce.Do(initIo)
|
||||
v := &hvsockConn{fd: h, local: local, remote: remote}
|
||||
|
||||
_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setFileCompletionNotificationModes(h,
|
||||
cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &HVsockConn{hvsockConn: *v}, nil
|
||||
}
|
||||
|
||||
// Utility function to build a struct sockaddr for syscalls.
|
||||
func (a HypervAddr) sockaddr(sa *rawSockaddrHyperv) (unsafe.Pointer, int32, error) {
|
||||
sa.Family = AF_HYPERV
|
||||
sa.Reserved = 0
|
||||
for i := 0; i < len(sa.VmId); i++ {
|
||||
sa.VmId[i] = a.VmId[i]
|
||||
}
|
||||
for i := 0; i < len(sa.ServiceId); i++ {
|
||||
sa.ServiceId[i] = a.ServiceId[i]
|
||||
}
|
||||
|
||||
return unsafe.Pointer(sa), int32(unsafe.Sizeof(*sa)), nil
|
||||
}
|
||||
|
||||
func connect(s syscall.Handle, a *HypervAddr) (err error) {
|
||||
var sa rawSockaddrHyperv
|
||||
ptr, n, err := a.sockaddr(&sa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sys_connect(s, ptr, n)
|
||||
}
|
||||
|
||||
func bind(s syscall.Handle, a HypervAddr) error {
|
||||
var sa rawSockaddrHyperv
|
||||
ptr, n, err := a.sockaddr(&sa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sys_bind(s, ptr, n)
|
||||
}
|
||||
|
||||
func accept(s syscall.Handle, a *HypervAddr) (syscall.Handle, error) {
|
||||
return 0, errors.New("accept(): Unimplemented")
|
||||
}
|
||||
|
||||
//
|
||||
// File IO/Socket interface
|
||||
//
|
||||
func (s *HVsockConn) close() error {
|
||||
s.closeHandle()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Underlying raw read() function.
|
||||
func (v *HVsockConn) read(buf []byte) (int, error) {
|
||||
var b syscall.WSABuf
|
||||
var bytes uint32
|
||||
var f uint32
|
||||
|
||||
b.Len = uint32(len(buf))
|
||||
b.Buf = &buf[0]
|
||||
|
||||
c, err := v.prepareIo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = syscall.WSARecv(v.fd, &b, 1, &bytes, &f, &c.o, nil)
|
||||
n, err := v.asyncIo(c, v.readDeadline, bytes, err)
|
||||
|
||||
// Handle EOF conditions.
|
||||
if err == nil && n == 0 && len(buf) != 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
if err == syscall.ERROR_BROKEN_PIPE {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Underlying raw write() function.
|
||||
func (v *HVsockConn) write(buf []byte) (int, error) {
|
||||
var b syscall.WSABuf
|
||||
var f uint32
|
||||
var bytes uint32
|
||||
|
||||
if len(buf) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
f = 0
|
||||
b.Len = uint32(len(buf))
|
||||
b.Buf = &buf[0]
|
||||
|
||||
c, err := v.prepareIo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err = syscall.WSASend(v.fd, &b, 1, &bytes, f, &c.o, nil)
|
||||
return v.asyncIo(c, v.writeDeadline, bytes, err)
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetReadDeadline(t time.Time) error {
|
||||
v.readDeadline = t
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetWriteDeadline(t time.Time) error {
|
||||
v.writeDeadline = t
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *HVsockConn) SetDeadline(t time.Time) error {
|
||||
v.SetReadDeadline(t)
|
||||
v.SetWriteDeadline(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// The code below here is adjusted from:
|
||||
// https://github.com/Microsoft/go-winio/blob/master/file.go
|
||||
|
||||
var ioInitOnce sync.Once
|
||||
var ioCompletionPort syscall.Handle
|
||||
|
||||
// ioResult contains the result of an asynchronous IO operation
|
||||
type ioResult struct {
|
||||
bytes uint32
|
||||
err error
|
||||
}
|
||||
|
||||
type ioOperation struct {
|
||||
o syscall.Overlapped
|
||||
ch chan ioResult
|
||||
}
|
||||
|
||||
func initIo() {
|
||||
h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ioCompletionPort = h
|
||||
go ioCompletionProcessor(h)
|
||||
}
|
||||
|
||||
func (v *hvsockConn) closeHandle() {
|
||||
if !v.closing {
|
||||
// cancel all IO and wait for it to complete
|
||||
v.closing = true
|
||||
cancelIoEx(v.fd, nil)
|
||||
v.wg.Wait()
|
||||
// at this point, no new IO can start
|
||||
syscall.Close(v.fd)
|
||||
v.fd = 0
|
||||
}
|
||||
}
|
||||
|
||||
// prepareIo prepares for a new IO operation
|
||||
func (s *hvsockConn) prepareIo() (*ioOperation, error) {
|
||||
s.wg.Add(1)
|
||||
if s.closing {
|
||||
return nil, errSocketClosed
|
||||
}
|
||||
c := &ioOperation{}
|
||||
c.ch = make(chan ioResult)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// ioCompletionProcessor processes completed async IOs forever
|
||||
func ioCompletionProcessor(h syscall.Handle) {
|
||||
// Set the timer resolution to 1. This fixes a performance regression in golang 1.6.
|
||||
timeBeginPeriod(1)
|
||||
for {
|
||||
var bytes uint32
|
||||
var key uintptr
|
||||
var op *ioOperation
|
||||
err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE)
|
||||
if op == nil {
|
||||
panic(err)
|
||||
}
|
||||
op.ch <- ioResult{bytes, err}
|
||||
}
|
||||
}
|
||||
|
||||
// asyncIo processes the return value from ReadFile or WriteFile, blocking until
|
||||
// the operation has actually completed.
|
||||
func (v *hvsockConn) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, err error) (int, error) {
|
||||
if err != syscall.ERROR_IO_PENDING {
|
||||
v.wg.Done()
|
||||
return int(bytes), err
|
||||
}
|
||||
|
||||
var r ioResult
|
||||
wait := true
|
||||
timedout := false
|
||||
if v.closing {
|
||||
cancelIoEx(v.fd, &c.o)
|
||||
} else if !deadline.IsZero() {
|
||||
now := time.Now()
|
||||
if !deadline.After(now) {
|
||||
timedout = true
|
||||
} else {
|
||||
timeout := time.After(deadline.Sub(now))
|
||||
select {
|
||||
case r = <-c.ch:
|
||||
wait = false
|
||||
case <-timeout:
|
||||
timedout = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if timedout {
|
||||
cancelIoEx(v.fd, &c.o)
|
||||
}
|
||||
if wait {
|
||||
r = <-c.ch
|
||||
}
|
||||
err = r.err
|
||||
if err == syscall.ERROR_OPERATION_ABORTED {
|
||||
if v.closing {
|
||||
err = errSocketClosed
|
||||
} else if timedout {
|
||||
err = errTimeout
|
||||
}
|
||||
}
|
||||
v.wg.Done()
|
||||
return int(r.bytes), err
|
||||
}
|
100
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/zsyscall_windows.go
generated
vendored
Normal file
100
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/hvsock/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
package hvsock
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modws2_32 = syscall.NewLazyDLL("ws2_32.dll")
|
||||
modwinmm = syscall.NewLazyDLL("winmm.dll")
|
||||
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
procConnect = modws2_32.NewProc("connect")
|
||||
procbind = modws2_32.NewProc("bind")
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod")
|
||||
)
|
||||
|
||||
func sys_connect(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socket_error {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func sys_bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socket_error {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
||||
newport = syscall.Handle(r0)
|
||||
if newport == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func timeBeginPeriod(period uint32) (n int32) {
|
||||
r0, _, _ := syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0)
|
||||
n = int32(r0)
|
||||
return
|
||||
}
|
171
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/vsock/vsock_linux.go
generated
vendored
Normal file
171
alpine/packages/go/vendor/github.com/rneugeba/virtsock/go/vsock/vsock_linux.go
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
package vsock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
/* No way to teach net or syscall about vsock sockaddr, so go right to C */
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
struct sockaddr_vm {
|
||||
sa_family_t svm_family;
|
||||
unsigned short svm_reserved1;
|
||||
unsigned int svm_port;
|
||||
unsigned int svm_cid;
|
||||
unsigned char svm_zero[sizeof(struct sockaddr) -
|
||||
sizeof(sa_family_t) - sizeof(unsigned short) -
|
||||
sizeof(unsigned int) - sizeof(unsigned int)];
|
||||
};
|
||||
|
||||
int bind_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) {
|
||||
return bind(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm));
|
||||
}
|
||||
int connect_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) {
|
||||
return connect(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm));
|
||||
}
|
||||
int accept_vm(int fd, struct sockaddr_vm *sa_vm, socklen_t *sa_vm_len) {
|
||||
return accept4(fd, (struct sockaddr *)sa_vm, sa_vm_len, 0);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
AF_VSOCK = 40
|
||||
VSOCK_CID_ANY = 4294967295 /* 2^32-1 */
|
||||
VSOCK_CID_SELF = 3
|
||||
)
|
||||
|
||||
// Listen returns a net.Listener which can accept connections on the given
|
||||
// vhan port.
|
||||
func Listen(port uint) (net.Listener, error) {
|
||||
accept_fd, err := syscall.Socket(AF_VSOCK, syscall.SOCK_STREAM, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sa := C.struct_sockaddr_vm{}
|
||||
sa.svm_family = AF_VSOCK
|
||||
sa.svm_port = C.uint(port)
|
||||
sa.svm_cid = VSOCK_CID_ANY
|
||||
|
||||
if ret := C.bind_sockaddr_vm(C.int(accept_fd), &sa); ret != 0 {
|
||||
return nil, errors.New(fmt.Sprintf("failed bind vsock connection to %08x.%08x, returned %d", sa.svm_cid, sa.svm_port, ret))
|
||||
}
|
||||
|
||||
err = syscall.Listen(accept_fd, syscall.SOMAXCONN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &vsockListener{accept_fd, port}, nil
|
||||
}
|
||||
|
||||
// Conn is a vsock connection which support half-close.
|
||||
type Conn interface {
|
||||
net.Conn
|
||||
CloseRead() error
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
type vsockListener struct {
|
||||
accept_fd int
|
||||
port uint
|
||||
}
|
||||
|
||||
func (v *vsockListener) Accept() (net.Conn, error) {
|
||||
var accept_sa C.struct_sockaddr_vm
|
||||
var accept_sa_len C.socklen_t
|
||||
|
||||
accept_sa_len = C.sizeof_struct_sockaddr_vm
|
||||
fd, err := C.accept_vm(C.int(v.accept_fd), &accept_sa, &accept_sa_len)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newVsockConn(uintptr(fd), v.port)
|
||||
}
|
||||
|
||||
func (v *vsockListener) Close() error {
|
||||
// Note this won't cause the Accept to unblock.
|
||||
return syscall.Close(v.accept_fd)
|
||||
}
|
||||
|
||||
type VsockAddr struct {
|
||||
Port uint
|
||||
}
|
||||
|
||||
func (a VsockAddr) Network() string {
|
||||
return "vsock"
|
||||
}
|
||||
|
||||
func (a VsockAddr) String() string {
|
||||
return fmt.Sprintf("%08x", a.Port)
|
||||
}
|
||||
|
||||
func (v *vsockListener) Addr() net.Addr {
|
||||
return VsockAddr{Port: v.port}
|
||||
}
|
||||
|
||||
// a wrapper around FileConn which supports CloseRead and CloseWrite
|
||||
type vsockConn struct {
|
||||
vsock *os.File
|
||||
fd uintptr
|
||||
local VsockAddr
|
||||
remote VsockAddr
|
||||
}
|
||||
|
||||
type VsockConn struct {
|
||||
vsockConn
|
||||
}
|
||||
|
||||
func newVsockConn(fd uintptr, localPort uint) (*VsockConn, error) {
|
||||
vsock := os.NewFile(fd, fmt.Sprintf("vsock:%d", fd))
|
||||
local := VsockAddr{Port: localPort}
|
||||
remote := VsockAddr{Port: uint(0)} // FIXME
|
||||
return &VsockConn{vsockConn{vsock: vsock, fd: fd, local: local, remote: remote}}, nil
|
||||
}
|
||||
|
||||
func (v *VsockConn) LocalAddr() net.Addr {
|
||||
return v.local
|
||||
}
|
||||
|
||||
func (v *VsockConn) RemoteAddr() net.Addr {
|
||||
return v.remote
|
||||
}
|
||||
|
||||
func (v *VsockConn) CloseRead() error {
|
||||
return syscall.Shutdown(int(v.fd), syscall.SHUT_RD)
|
||||
}
|
||||
|
||||
func (v *VsockConn) CloseWrite() error {
|
||||
return syscall.Shutdown(int(v.fd), syscall.SHUT_WR)
|
||||
}
|
||||
|
||||
func (v *VsockConn) Close() error {
|
||||
return v.vsock.Close()
|
||||
}
|
||||
|
||||
func (v *VsockConn) Read(buf []byte) (int, error) {
|
||||
return v.vsock.Read(buf)
|
||||
}
|
||||
|
||||
func (v *VsockConn) Write(buf []byte) (int, error) {
|
||||
return v.vsock.Write(buf)
|
||||
}
|
||||
|
||||
func (v *VsockConn) SetDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
||||
|
||||
func (v *VsockConn) SetReadDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
||||
|
||||
func (v *VsockConn) SetWriteDeadline(t time.Time) error {
|
||||
return nil // FIXME
|
||||
}
|
14
alpine/packages/go/vendor/manifest
vendored
Normal file
14
alpine/packages/go/vendor/manifest
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": 0,
|
||||
"dependencies": [
|
||||
{
|
||||
"importpath": "github.com/rneugeba/virtsock/go",
|
||||
"repository": "https://github.com/rneugeba/virtsock",
|
||||
"vcs": "git",
|
||||
"revision": "359bc27daab86588bfc7a304e78c6758b098d8e5",
|
||||
"branch": "master",
|
||||
"path": "/go",
|
||||
"notests": true
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user