diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index 022274fbb..d9787a8f0 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -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 } diff --git a/alpine/packages/proxy/vendor/libproxy/proxy.go b/alpine/packages/proxy/vendor/libproxy/proxy.go index d0098502d..7e72057fb 100644 --- a/alpine/packages/proxy/vendor/libproxy/proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/proxy.go @@ -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 } diff --git a/alpine/packages/proxy/vendor/vsock/vsock.go b/alpine/packages/proxy/vendor/vsock/vsock.go index 91dca0cb3..b0f734b99 100644 --- a/alpine/packages/proxy/vendor/vsock/vsock.go +++ b/alpine/packages/proxy/vendor/vsock/vsock.go @@ -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 +}