Skip to content

Commit

Permalink
added attachmentWasDisconnectedWithError delegate in internal only
Browse files Browse the repository at this point in the history
  • Loading branch information
Code-Hex committed Nov 3, 2024
1 parent 46a19ee commit d49cd9f
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 10 deletions.
22 changes: 21 additions & 1 deletion virtualization_11.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "virtualization_helper.h"
#import <Virtualization/Virtualization.h>
#import <sys/utsname.h>

/* exported from cgo */
void connectionHandler(void *connection, void *err, uintptr_t cgoHandle);
Expand All @@ -18,13 +19,32 @@ bool shouldAcceptNewConnectionHandler(uintptr_t cgoHandle, void *connection, voi
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
@end

@interface VZVirtualMachineDelegateWrapper : NSObject <VZVirtualMachineDelegate>
@property (nonatomic, strong, readonly) NSHashTable<id<VZVirtualMachineDelegate>> *delegates;

- (instancetype)init;
- (void)addDelegate:(id<VZVirtualMachineDelegate>)delegate;
- (void)guestDidStopVirtualMachine:(VZVirtualMachine *)virtualMachine;
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine didStopWithError:(NSError *)error;
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine
networkDevice:(VZNetworkDevice *)networkDevice
attachmentWasDisconnectedWithError:(NSError *)error API_AVAILABLE(macos(12.0));
@end

@interface ObservableVZVirtualMachine : VZVirtualMachine
- (instancetype)initWithConfiguration:(VZVirtualMachineConfiguration *)configuration
queue:(dispatch_queue_t)queue
statusUpdateHandle:(uintptr_t)statusUpdateHandle;
- (void)dealloc;
@end

@interface VZVirtualMachineNetworkDeviceErrorHandler : NSObject <VZVirtualMachineDelegate>
- (instancetype)initWithHandle:(uintptr_t)cgoHandle;
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine
networkDevice:(VZNetworkDevice *)networkDevice
attachmentWasDisconnectedWithError:(NSError *)error API_AVAILABLE(macos(12.0));
@end

/* VZVirtioSocketListener */
@interface VZVirtioSocketListenerDelegateImpl : NSObject <VZVirtioSocketListenerDelegate>
- (instancetype)initWithHandle:(uintptr_t)cgoHandle;
Expand Down Expand Up @@ -88,7 +108,7 @@ void VZVirtioSocketDevice_removeSocketListenerForPort(void *socketDevice, void *
void VZVirtioSocketDevice_connectToPort(void *socketDevice, void *vmQueue, uint32_t port, uintptr_t cgoHandle);

/* VirtualMachine */
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t cgoHandle);
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t statusUpdateCgoHandle);
bool requestStopVirtualMachine(void *machine, void *queue, void **error);
void startWithCompletionHandler(void *machine, void *queue, uintptr_t cgoHandle);
void pauseWithCompletionHandler(void *machine, void *queue, uintptr_t cgoHandle);
Expand Down
127 changes: 119 additions & 8 deletions virtualization_11.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,133 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
}
@end

@implementation VZVirtualMachineDelegateWrapper
- (instancetype)init
{
self = [super init];
if (self) {
_delegates = [NSHashTable weakObjectsHashTable];
}
return self;
}

- (void)addDelegate:(id<VZVirtualMachineDelegate>)delegate
{
[self.delegates addObject:delegate];
}

- (void)guestDidStopVirtualMachine:(VZVirtualMachine *)virtualMachine
{
for (id<VZVirtualMachineDelegate> delegate in self.delegates) {
if ([delegate respondsToSelector:@selector(guestDidStopVirtualMachine:)]) {
[delegate guestDidStopVirtualMachine:virtualMachine];
}
}
}

- (void)virtualMachine:(VZVirtualMachine *)virtualMachine didStopWithError:(NSError *)error
{
for (id<VZVirtualMachineDelegate> delegate in self.delegates) {
if ([delegate respondsToSelector:@selector(virtualMachine:didStopWithError:)]) {
[delegate virtualMachine:virtualMachine didStopWithError:error];
}
}
}

- (void)virtualMachine:(VZVirtualMachine *)virtualMachine networkDevice:(VZNetworkDevice *)networkDevice
attachmentWasDisconnectedWithError:(NSError *)error
{
for (id<VZVirtualMachineDelegate> delegate in self.delegates) {
if ([delegate respondsToSelector:@selector(virtualMachine:networkDevice:attachmentWasDisconnectedWithError:)]) {
[delegate virtualMachine:virtualMachine networkDevice:networkDevice attachmentWasDisconnectedWithError:error];
}
}
}
@end

@implementation VZVirtualMachineNetworkDeviceErrorHandler {
uintptr_t _cgoHandle;
}

// TODO(codehex): Support the conditions under which the attachmentWasDisconnectedWithError method
// is executed as soon as they are known.
- (instancetype)initWithHandle:(uintptr_t)cgoHandle
{
self = [super init];
if (self) {
_cgoHandle = cgoHandle;
}
return self;
}

- (void)virtualMachine:(VZVirtualMachine *)virtualMachine
networkDevice:(VZNetworkDevice *)networkDevice
attachmentWasDisconnectedWithError:(NSError *)error
{
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
NSString *processName = [processInfo processName];
NSString *osVersion = [processInfo operatingSystemVersionString];
struct utsname systemInfo;
uname(&systemInfo);
NSString *architecture = [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];

NSLog(
@"If you see this message, please report the information about the OS (including the version) that you are running on the VM, "
@"along with the information displayed below, to https://github.com/Code-Hex/vz/issues.\n"
@"Process Information:\n"
@" Name: %@\n"
@" macOS: %@, %@\n"
@" networkDevice: %@\n"
@" networkDevice attachment: %@\n",
@" attachmentWasDisconnectedWithError: %@",
processName,
osVersion,
architecture,
networkDevice,
networkDevice.attachment,
error);
}
@end

@implementation ObservableVZVirtualMachine {
Observer *_observer;
VZVirtualMachineDelegateWrapper *_delegateWrapper;
};
- (instancetype)initWithConfiguration:(VZVirtualMachineConfiguration *)configuration
queue:(dispatch_queue_t)queue
statusUpdateHandle:(uintptr_t)statusUpdateHandle
{
self = [super initWithConfiguration:configuration queue:queue];
_observer = [[Observer alloc] init];
[self addObserver:_observer
forKeyPath:@"state"
options:NSKeyValueObservingOptionNew
context:(void *)statusUpdateHandle];
if (self) {
_observer = [[Observer alloc] init];
[self addObserver:_observer
forKeyPath:@"state"
options:NSKeyValueObservingOptionNew
context:(void *)statusUpdateHandle];
_delegateWrapper = [[VZVirtualMachineDelegateWrapper alloc] init];
[super setDelegate:_delegateWrapper];
}
return self;
}

- (void)setDelegate:(id<VZVirtualMachineDelegate>)delegate
{
if (delegate != _delegateWrapper) {
[_delegateWrapper addDelegate:delegate];
}
}

- (id<VZVirtualMachineDelegate>)delegate
{
return _delegateWrapper;
}

- (void)dealloc
{
[self removeObserver:_observer forKeyPath:@"state"];
[_observer release];
[_delegateWrapper release];
[super dealloc];
}
@end
Expand All @@ -48,7 +155,9 @@ @implementation VZVirtioSocketListenerDelegateImpl {
- (instancetype)initWithHandle:(uintptr_t)cgoHandle
{
self = [super init];
_cgoHandle = cgoHandle;
if (self) {
_cgoHandle = cgoHandle;
}
return self;
}

Expand Down Expand Up @@ -731,13 +840,15 @@ VZVirtioSocketConnectionFlat convertVZVirtioSocketConnection2Flat(void *connecti
Every operation on the virtual machine must be done on that queue. The callbacks and delegate methods are invoked on that queue.
If the queue is not serial, the behavior is undefined.
*/
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t cgoHandle)
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t statusUpdateCgoHandle)
{
if (@available(macOS 11, *)) {
ObservableVZVirtualMachine *vm = [[ObservableVZVirtualMachine alloc]
initWithConfiguration:(VZVirtualMachineConfiguration *)config
queue:(dispatch_queue_t)queue
statusUpdateHandle:cgoHandle];
statusUpdateHandle:statusUpdateCgoHandle];
VZVirtualMachineNetworkDeviceErrorHandler *delegate = [[[VZVirtualMachineNetworkDeviceErrorHandler alloc] init] autorelease];
[vm setDelegate:delegate];
return vm;
}

Expand Down
2 changes: 1 addition & 1 deletion virtualization_view.m
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ - (instancetype)initWithVirtualMachine:(VZVirtualMachine *)virtualMachine
{
self = [super init];
_virtualMachine = virtualMachine;
_virtualMachine.delegate = self;
[_virtualMachine setDelegate:self];

// Setup virtual machine view configs
VZVirtualMachineView *view = [[[VZVirtualMachineView alloc] init] autorelease];
Expand Down

0 comments on commit d49cd9f

Please sign in to comment.