Skip to content

Commit 8e9c1ff

Browse files
committed
added attachmentWasDisconnectedWithError delegate in internal only
1 parent 46a19ee commit 8e9c1ff

File tree

3 files changed

+141
-10
lines changed

3 files changed

+141
-10
lines changed

virtualization_11.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#import "virtualization_helper.h"
1010
#import <Virtualization/Virtualization.h>
11+
#import <sys/utsname.h>
1112

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

22+
@interface VZVirtualMachineDelegateWrapper : NSObject <VZVirtualMachineDelegate>
23+
@property (nonatomic, strong, readonly) NSHashTable<id<VZVirtualMachineDelegate>> *delegates;
24+
25+
- (instancetype)init;
26+
- (void)addDelegate:(id<VZVirtualMachineDelegate>)delegate;
27+
- (void)guestDidStopVirtualMachine:(VZVirtualMachine *)virtualMachine;
28+
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine didStopWithError:(NSError *)error;
29+
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine
30+
networkDevice:(VZNetworkDevice *)networkDevice
31+
attachmentWasDisconnectedWithError:(NSError *)error API_AVAILABLE(macos(12.0));
32+
@end
33+
2134
@interface ObservableVZVirtualMachine : VZVirtualMachine
2235
- (instancetype)initWithConfiguration:(VZVirtualMachineConfiguration *)configuration
2336
queue:(dispatch_queue_t)queue
2437
statusUpdateHandle:(uintptr_t)statusUpdateHandle;
2538
- (void)dealloc;
2639
@end
2740

41+
@interface VZVirtualMachineNetworkDeviceErrorHandler : NSObject <VZVirtualMachineDelegate>
42+
- (instancetype)initWithHandle:(uintptr_t)cgoHandle;
43+
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine
44+
networkDevice:(VZNetworkDevice *)networkDevice
45+
attachmentWasDisconnectedWithError:(NSError *)error API_AVAILABLE(macos(12.0));
46+
@end
47+
2848
/* VZVirtioSocketListener */
2949
@interface VZVirtioSocketListenerDelegateImpl : NSObject <VZVirtioSocketListenerDelegate>
3050
- (instancetype)initWithHandle:(uintptr_t)cgoHandle;
@@ -88,7 +108,7 @@ void VZVirtioSocketDevice_removeSocketListenerForPort(void *socketDevice, void *
88108
void VZVirtioSocketDevice_connectToPort(void *socketDevice, void *vmQueue, uint32_t port, uintptr_t cgoHandle);
89109

90110
/* VirtualMachine */
91-
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t cgoHandle);
111+
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t statusUpdateCgoHandle);
92112
bool requestStopVirtualMachine(void *machine, void *queue, void **error);
93113
void startWithCompletionHandler(void *machine, void *queue, uintptr_t cgoHandle);
94114
void pauseWithCompletionHandler(void *machine, void *queue, uintptr_t cgoHandle);

virtualization_11.m

Lines changed: 119 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,133 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
1717
}
1818
@end
1919

20+
@implementation VZVirtualMachineDelegateWrapper
21+
- (instancetype)init
22+
{
23+
self = [super init];
24+
if (self) {
25+
_delegates = [NSHashTable weakObjectsHashTable];
26+
}
27+
return self;
28+
}
29+
30+
- (void)addDelegate:(id<VZVirtualMachineDelegate>)delegate
31+
{
32+
[self.delegates addObject:delegate];
33+
}
34+
35+
- (void)guestDidStopVirtualMachine:(VZVirtualMachine *)virtualMachine
36+
{
37+
for (id<VZVirtualMachineDelegate> delegate in self.delegates) {
38+
if ([delegate respondsToSelector:@selector(guestDidStopVirtualMachine:)]) {
39+
[delegate guestDidStopVirtualMachine:virtualMachine];
40+
}
41+
}
42+
}
43+
44+
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine didStopWithError:(NSError *)error
45+
{
46+
for (id<VZVirtualMachineDelegate> delegate in self.delegates) {
47+
if ([delegate respondsToSelector:@selector(virtualMachine:didStopWithError:)]) {
48+
[delegate virtualMachine:virtualMachine didStopWithError:error];
49+
}
50+
}
51+
}
52+
53+
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine networkDevice:(VZNetworkDevice *)networkDevice
54+
attachmentWasDisconnectedWithError:(NSError *)error
55+
{
56+
for (id<VZVirtualMachineDelegate> delegate in self.delegates) {
57+
if ([delegate respondsToSelector:@selector(virtualMachine:networkDevice:attachmentWasDisconnectedWithError:)]) {
58+
[delegate virtualMachine:virtualMachine networkDevice:networkDevice attachmentWasDisconnectedWithError:error];
59+
}
60+
}
61+
}
62+
@end
63+
64+
@implementation VZVirtualMachineNetworkDeviceErrorHandler {
65+
uintptr_t _cgoHandle;
66+
}
67+
68+
// TODO(codehex): Support the conditions under which the attachmentWasDisconnectedWithError method
69+
// is executed as soon as they are known.
70+
- (instancetype)initWithHandle:(uintptr_t)cgoHandle
71+
{
72+
self = [super init];
73+
if (self) {
74+
_cgoHandle = cgoHandle;
75+
}
76+
return self;
77+
}
78+
79+
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine
80+
networkDevice:(VZNetworkDevice *)networkDevice
81+
attachmentWasDisconnectedWithError:(NSError *)error
82+
{
83+
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
84+
NSString *processName = [processInfo processName];
85+
NSString *osVersion = [processInfo operatingSystemVersionString];
86+
struct utsname systemInfo;
87+
uname(&systemInfo);
88+
NSString *architecture = [NSString stringWithCString:systemInfo.machine
89+
encoding:NSUTF8StringEncoding];
90+
91+
NSLog(
92+
@"If you see this message, please report the information about the OS (including the version) that you are running on the VM, "
93+
@"along with the information displayed below, to https://github.com/Code-Hex/vz/issues.\n"
94+
@"Process Information:\n"
95+
@" Name: %@\n"
96+
@" macOS: %@, %@\n"
97+
@" networkDevice: %@\n"
98+
@" networkDevice attachment: %@\n"
99+
@" attachmentWasDisconnectedWithError: %@",
100+
processName,
101+
osVersion,
102+
architecture,
103+
networkDevice,
104+
networkDevice.attachment,
105+
error);
106+
}
107+
@end
108+
20109
@implementation ObservableVZVirtualMachine {
21110
Observer *_observer;
111+
VZVirtualMachineDelegateWrapper *_delegateWrapper;
22112
};
23113
- (instancetype)initWithConfiguration:(VZVirtualMachineConfiguration *)configuration
24114
queue:(dispatch_queue_t)queue
25115
statusUpdateHandle:(uintptr_t)statusUpdateHandle
26116
{
27117
self = [super initWithConfiguration:configuration queue:queue];
28-
_observer = [[Observer alloc] init];
29-
[self addObserver:_observer
30-
forKeyPath:@"state"
31-
options:NSKeyValueObservingOptionNew
32-
context:(void *)statusUpdateHandle];
118+
if (self) {
119+
_observer = [[Observer alloc] init];
120+
[self addObserver:_observer
121+
forKeyPath:@"state"
122+
options:NSKeyValueObservingOptionNew
123+
context:(void *)statusUpdateHandle];
124+
_delegateWrapper = [[VZVirtualMachineDelegateWrapper alloc] init];
125+
[super setDelegate:_delegateWrapper];
126+
}
33127
return self;
34128
}
35129

130+
- (void)setDelegate:(id<VZVirtualMachineDelegate>)delegate
131+
{
132+
if (delegate != _delegateWrapper) {
133+
[_delegateWrapper addDelegate:delegate];
134+
}
135+
}
136+
137+
- (id<VZVirtualMachineDelegate>)delegate
138+
{
139+
return _delegateWrapper;
140+
}
141+
36142
- (void)dealloc
37143
{
38144
[self removeObserver:_observer forKeyPath:@"state"];
39145
[_observer release];
146+
[_delegateWrapper release];
40147
[super dealloc];
41148
}
42149
@end
@@ -48,7 +155,9 @@ @implementation VZVirtioSocketListenerDelegateImpl {
48155
- (instancetype)initWithHandle:(uintptr_t)cgoHandle
49156
{
50157
self = [super init];
51-
_cgoHandle = cgoHandle;
158+
if (self) {
159+
_cgoHandle = cgoHandle;
160+
}
52161
return self;
53162
}
54163

@@ -731,13 +840,15 @@ VZVirtioSocketConnectionFlat convertVZVirtioSocketConnection2Flat(void *connecti
731840
Every operation on the virtual machine must be done on that queue. The callbacks and delegate methods are invoked on that queue.
732841
If the queue is not serial, the behavior is undefined.
733842
*/
734-
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t cgoHandle)
843+
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t statusUpdateCgoHandle)
735844
{
736845
if (@available(macOS 11, *)) {
737846
ObservableVZVirtualMachine *vm = [[ObservableVZVirtualMachine alloc]
738847
initWithConfiguration:(VZVirtualMachineConfiguration *)config
739848
queue:(dispatch_queue_t)queue
740-
statusUpdateHandle:cgoHandle];
849+
statusUpdateHandle:statusUpdateCgoHandle];
850+
VZVirtualMachineNetworkDeviceErrorHandler *delegate = [[[VZVirtualMachineNetworkDeviceErrorHandler alloc] init] autorelease];
851+
[vm setDelegate:delegate];
741852
return vm;
742853
}
743854

virtualization_view.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ - (instancetype)initWithVirtualMachine:(VZVirtualMachine *)virtualMachine
178178
{
179179
self = [super init];
180180
_virtualMachine = virtualMachine;
181-
_virtualMachine.delegate = self;
181+
[_virtualMachine setDelegate:self];
182182

183183
// Setup virtual machine view configs
184184
VZVirtualMachineView *view = [[[VZVirtualMachineView alloc] init] autorelease];

0 commit comments

Comments
 (0)