Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

breaking change ConnectToPort #88

Merged
merged 2 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ func (v *VirtioSocketDevice) Listen(port uint32) (*VirtioSocketListener, error)
return nil, ErrUnsupportedOSVersion
}

ch := make(chan accept, 1) // should I increase more caps?
ch := make(chan connResults, 1) // should I increase more caps?

handler := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
ch <- accept{conn, err}
ch <- connResults{conn, err}
})
ptr := C.newVZVirtioSocketListener(
unsafe.Pointer(&handler),
Expand Down Expand Up @@ -139,20 +139,26 @@ func connectionHandler(connPtr, errPtr, cgoHandlerPtr unsafe.Pointer) {
}
}

// ConnectToPort Initiates a connection to the specified port of the guest operating system.
// Connect Initiates a connection to the specified port of the guest operating system.
//
// This method initiates the connection asynchronously, and executes the completion handler when the results are available.
// If the guest operating system doesn’t listen for connections to the specifed port, this method does nothing.
//
// For a successful connection, this method sets the sourcePort property of the resulting VZVirtioSocketConnection object to a random port number.
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketdevice/3656677-connecttoport?language=objc
func (v *VirtioSocketDevice) ConnectToPort(port uint32, fn func(conn *VirtioSocketConnection, err error)) {
cgoHandler := cgo.NewHandle(fn)
func (v *VirtioSocketDevice) Connect(port uint32) (*VirtioSocketConnection, error) {
ch := make(chan connResults, 1)
cgoHandler := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
ch <- connResults{conn, err}
close(ch)
})
C.VZVirtioSocketDevice_connectToPort(v.Ptr(), v.dispatchQueue, C.uint32_t(port), unsafe.Pointer(&cgoHandler))
result := <-ch
runtime.KeepAlive(v)
return result.conn, result.err
}

type accept struct {
type connResults struct {
conn *VirtioSocketConnection
err error
}
Expand All @@ -165,7 +171,7 @@ type VirtioSocketListener struct {
vsockDevice *VirtioSocketDevice
handler cgo.Handle
port uint32
acceptch chan accept
acceptch chan connResults
closeOnce sync.Once
}

Expand Down
2 changes: 1 addition & 1 deletion virtualization.m
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ void VZVirtioSocketDevice_removeSocketListenerForPort(void *socketDevice, void *
void VZVirtioSocketDevice_connectToPort(void *socketDevice, void *vmQueue, uint32_t port, void *cgoHandlerPtr)
{
if (@available(macOS 11, *)) {
dispatch_sync((dispatch_queue_t)vmQueue, ^{
dispatch_async((dispatch_queue_t)vmQueue, ^{
[(VZVirtioSocketDevice *)socketDevice connectToPort:port
completionHandler:^(VZVirtioSocketConnection *connection, NSError *err) {
connectionHandler(connection, err, cgoHandlerPtr);
Expand Down
40 changes: 14 additions & 26 deletions virtualization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,6 @@ func newVirtualizationMachine(
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}

clientCh := make(chan *ssh.Client, 1)
errCh := make(chan error, 1)

// Workaround for macOS 11
//
// This is a workaround. This version of the API does not immediately return an error and
Expand All @@ -181,24 +178,8 @@ func newVirtualizationMachine(

RETRY:
for i := 1; ; i++ {
socketDevice.ConnectToPort(2222, func(vsockConn *vz.VirtioSocketConnection, err error) {
if err != nil {
errCh <- fmt.Errorf("failed to connect vsock: %w", err)
return
}

sshClient, err := newSshClient(vsockConn, ":22", sshConfig)
if err != nil {
vsockConn.Close()
errCh <- fmt.Errorf("failed to create a new ssh client: %w", err)
return
}
clientCh <- sshClient
close(clientCh)
})

select {
case err := <-errCh:
conn, err := socketDevice.Connect(2222)
if err != nil {
var nserr *vz.NSError
if !errors.As(err, &nserr) || i > 5 {
t.Fatal(err)
Expand All @@ -208,11 +189,18 @@ RETRY:
time.Sleep(time.Second)
continue RETRY
}
case sshClient := <-clientCh:
return &Container{
VirtualMachine: vm,
Client: sshClient,
}
t.Fatalf("failed to connect vsock: %v", err)
}

sshClient, err := newSshClient(conn, ":22", sshConfig)
if err != nil {
conn.Close()
t.Fatalf("failed to create a new ssh client: %v", err)
}

return &Container{
VirtualMachine: vm,
Client: sshClient,
}
}
}
Expand Down