proxy: fix up the vsock interface

- don't try to create a `FileConn` because the Go library sees through
  the scam and rejects it
- explicitly keep a reference to the `ctl` file just in case the GC
  decides its dead and should be closed.

Signed-off-by: David Scott <dave.scott@docker.com>
This commit is contained in:
David Scott 2016-04-15 11:03:47 +01:00
parent 1d3b8b566e
commit 586d9c0598
3 changed files with 43 additions and 18 deletions

View File

@ -8,53 +8,57 @@ import (
"os"
"libproxy"
"strings"
"vsock"
)
func main() {
host, port, container := parseHostContainerAddrs()
err := exposePort(host, port)
ctl, err := exposePort(host, port)
if err != nil {
sendError(err)
}
p, err := libproxy.NewProxy(host, container)
p, err := libproxy.NewProxy(&vsock.VsockAddr{Port: uint(port)}, container)
if err != nil {
sendError(err)
}
go handleStopSignals(p)
sendOK()
p.Run()
ctl.Close() // ensure ctl remains alive and un-GCed until here
os.Exit(0)
}
func exposePort(host net.Addr, port int) error {
func exposePort(host net.Addr, port int) (*os.File, error) {
name := host.String()
log.Printf("exposePort %s\n", name)
err := os.Mkdir("/port/"+name, 0)
if err != nil {
log.Printf("Failed to mkdir /port/%s: %#v\n", name, err)
return err
return nil, err
}
ctl, err := os.OpenFile("/port/"+name+"/ctl", os.O_RDWR, 0)
if err != nil {
log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
return err
return nil, err
}
_, err = ctl.WriteString(fmt.Sprintf("%s:%08x", name, port))
if err != nil {
log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
return err
return nil, err
}
_, err = ctl.Seek(0, 0)
if err != nil {
log.Printf("Failed to seek on /port/%s/ctl: %#v\n", name, err)
return err
return nil, err
}
results := make([]byte, 100)
count, err := ctl.Read(results)
if err != nil {
log.Printf("Failed to read from /port/%s/ctl: %#v\n", name, err)
return err
return nil, err
}
// We deliberately keep the control file open since 9P clunk
// will trigger a shutdown on the host side.
@ -63,8 +67,8 @@ func exposePort(host net.Addr, port int) error {
if strings.HasPrefix(response, "ERROR ") {
os.Remove("/port/" + name + "/ctl")
response = strings.Trim(response[6:], " \t\r\n")
return errors.New(response)
return nil, errors.New(response)
}
return nil
// Hold on to a reference to prevent premature GC and close
return ctl, nil
}

View File

@ -39,7 +39,7 @@ func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) {
}
return NewTCPProxy(listener, backendAddr.(*net.TCPAddr))
case *vsock.VsockAddr:
listener, err := vsock.Listen(frontendAddr.(vsock.VsockAddr).Port)
listener, err := vsock.Listen(frontendAddr.(*vsock.VsockAddr).Port)
if err != nil {
return nil, err
}

View File

@ -6,6 +6,7 @@ import (
"net"
"os"
"syscall"
"time"
)
/* No way to teach net or syscall about vsock sockaddr, so go right to C */
@ -101,7 +102,7 @@ func (v *vsockListener) Addr() net.Addr {
// a wrapper around FileConn which supports CloseRead and CloseWrite
type vsockConn struct {
net.Conn
vsock *os.File
fd uintptr
local VsockAddr
remote VsockAddr
@ -113,13 +114,9 @@ type VsockConn struct {
func newVsockConn(fd uintptr, localPort uint) (*VsockConn, error) {
vsock := os.NewFile(fd, fmt.Sprintf("vsock:%d", fd))
conn, err := net.FileConn(vsock)
if err != nil {
return nil, err
}
local := VsockAddr{Port: localPort}
remote := VsockAddr{Port: uint(0)} // FIXME
return &VsockConn{vsockConn{Conn: conn, fd: fd, local: local, remote: remote}}, nil
return &VsockConn{vsockConn{vsock: vsock, fd: fd, local: local, remote: remote}}, nil
}
func (v *VsockConn) LocalAddr() net.Addr {
@ -137,3 +134,27 @@ func (v *VsockConn) CloseRead() error {
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
}