|
21 | 21 | Software Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. |
22 | 22 | */ |
23 | 23 |
|
| 24 | +#import "common.h" |
24 | 25 | #import "Foundation/NSXPCConnection.h" |
25 | 26 | #import "GNUstepBase/NSObject+GNUstepBase.h" |
| 27 | +#import "GNUstepBase/GSConfig.h" |
| 28 | + |
| 29 | +#if GS_USE_LIBXPC |
| 30 | +#include <xpc/xpc.h> |
| 31 | +#endif |
| 32 | + |
| 33 | +@interface NSXPCConnection () |
| 34 | +{ |
| 35 | + NSString *_serviceName; |
| 36 | + NSXPCListenerEndpoint *_endpoint; |
| 37 | + NSXPCInterface *_exportedInterface; |
| 38 | + NSXPCInterface *_remoteObjectInterface; |
| 39 | + id _remoteObjectProxy; |
| 40 | + GSXPCInterruptionHandler _interruptionHandler; |
| 41 | + GSXPCInvalidationHandler _invalidationHandler; |
| 42 | + NSXPCConnectionOptions _options; |
| 43 | + BOOL _resumed; |
| 44 | + BOOL _invalidated; |
| 45 | +#if GS_USE_LIBXPC |
| 46 | + xpc_connection_t _xpcConnection; |
| 47 | +#endif |
| 48 | +} |
| 49 | + |
| 50 | +- (void) _setupLibXPCConnectionIfPossible; |
| 51 | +@end |
26 | 52 |
|
27 | 53 | @implementation NSXPCConnection |
28 | 54 |
|
| 55 | +- (instancetype) init |
| 56 | +{ |
| 57 | + return [self initWithServiceName: nil]; |
| 58 | +} |
| 59 | + |
| 60 | +- (void) dealloc |
| 61 | +{ |
| 62 | + [self invalidate]; |
| 63 | + DESTROY(_serviceName); |
| 64 | + DESTROY(_endpoint); |
| 65 | + DESTROY(_exportedInterface); |
| 66 | + DESTROY(_remoteObjectInterface); |
| 67 | + DESTROY(_remoteObjectProxy); |
| 68 | + DESTROY(_interruptionHandler); |
| 69 | + DESTROY(_invalidationHandler); |
| 70 | + [super dealloc]; |
| 71 | +} |
| 72 | + |
| 73 | +- (void) _setupLibXPCConnectionIfPossible |
| 74 | +{ |
| 75 | +#if GS_USE_LIBXPC |
| 76 | + uint64_t flags = 0; |
| 77 | + NSXPCConnection *connection = self; |
| 78 | + |
| 79 | + if (_xpcConnection != NULL || _serviceName == nil || _invalidated == YES) |
| 80 | + { |
| 81 | + return; |
| 82 | + } |
| 83 | +#ifdef XPC_CONNECTION_MACH_SERVICE_PRIVILEGED |
| 84 | + if ((_options & NSXPCConnectionPrivileged) == NSXPCConnectionPrivileged) |
| 85 | + { |
| 86 | + flags |= XPC_CONNECTION_MACH_SERVICE_PRIVILEGED; |
| 87 | + } |
| 88 | +#endif |
| 89 | + _xpcConnection = xpc_connection_create_mach_service([_serviceName UTF8String], |
| 90 | + NULL, flags); |
| 91 | + if (_xpcConnection == NULL) |
| 92 | + { |
| 93 | + return; |
| 94 | + } |
| 95 | + |
| 96 | + xpc_connection_set_event_handler(_xpcConnection, ^(xpc_object_t event) { |
| 97 | + if (event == XPC_ERROR_CONNECTION_INTERRUPTED) |
| 98 | + { |
| 99 | + if (connection->_interruptionHandler != NULL) |
| 100 | + { |
| 101 | + connection->_interruptionHandler(); |
| 102 | + } |
| 103 | + } |
| 104 | + else if (event == XPC_ERROR_CONNECTION_INVALID) |
| 105 | + { |
| 106 | + connection->_invalidated = YES; |
| 107 | + if (connection->_invalidationHandler != NULL) |
| 108 | + { |
| 109 | + connection->_invalidationHandler(); |
| 110 | + } |
| 111 | + } |
| 112 | + }); |
| 113 | + |
| 114 | + if (_resumed == YES) |
| 115 | + { |
| 116 | + xpc_connection_resume(_xpcConnection); |
| 117 | + } |
| 118 | +#endif |
| 119 | +} |
| 120 | + |
29 | 121 | - (instancetype) initWithServiceName:(NSString *)serviceName |
30 | 122 | { |
31 | | - return [self notImplemented: _cmd]; |
| 123 | + return [self initWithMachServiceName: serviceName options: 0]; |
32 | 124 | } |
33 | 125 |
|
34 | 126 | - (NSString *) serviceName |
35 | 127 | { |
36 | | - return [self notImplemented: _cmd]; |
| 128 | + return _serviceName; |
37 | 129 | } |
38 | 130 |
|
39 | 131 | - (void) setServiceName: (NSString *)serviceName |
40 | 132 | { |
41 | | - [self notImplemented: _cmd]; |
| 133 | + ASSIGNCOPY(_serviceName, serviceName); |
| 134 | + [self _setupLibXPCConnectionIfPossible]; |
42 | 135 | } |
43 | 136 |
|
44 | 137 | - (instancetype) initWithMachServiceName: (NSString *)name |
45 | 138 | options: (NSXPCConnectionOptions)options |
46 | 139 | { |
47 | | - return [self notImplemented: _cmd]; |
| 140 | + if ((self = [super init]) != nil) |
| 141 | + { |
| 142 | + _options = options; |
| 143 | + [self setServiceName: name]; |
| 144 | + } |
| 145 | + return self; |
48 | 146 | } |
49 | 147 |
|
50 | 148 | - (instancetype) initWithListenerEndpoint: (NSXPCListenerEndpoint *)endpoint |
51 | 149 | { |
52 | | - return [self notImplemented: _cmd]; |
| 150 | + if ((self = [super init]) != nil) |
| 151 | + { |
| 152 | + ASSIGN(_endpoint, endpoint); |
| 153 | + } |
| 154 | + return self; |
53 | 155 | } |
54 | 156 |
|
55 | 157 |
|
56 | 158 | - (NSXPCListenerEndpoint *) endpoint |
57 | 159 | { |
58 | | - return [self notImplemented: _cmd]; |
| 160 | + return _endpoint; |
59 | 161 | } |
60 | 162 |
|
61 | 163 | - (void) setEndpoint: (NSXPCListenerEndpoint *) endpoint |
62 | 164 | { |
63 | | - [self notImplemented: _cmd]; |
| 165 | + ASSIGN(_endpoint, endpoint); |
64 | 166 | } |
65 | 167 |
|
66 | 168 | - (NSXPCInterface *) exportedInterface |
67 | 169 | { |
68 | | - return [self notImplemented: _cmd]; |
| 170 | + return _exportedInterface; |
69 | 171 | } |
70 | 172 |
|
71 | 173 | - (void) setExportInterface: (NSXPCInterface *)exportedInterface |
72 | 174 | { |
73 | | - [self notImplemented: _cmd]; |
| 175 | + ASSIGN(_exportedInterface, exportedInterface); |
74 | 176 | } |
75 | 177 |
|
76 | 178 | - (NSXPCInterface *) remoteObjectInterface |
77 | 179 | { |
78 | | - return [self notImplemented: _cmd]; |
| 180 | + return _remoteObjectInterface; |
79 | 181 | } |
80 | 182 |
|
81 | 183 | - (void) setRemoteObjectInterface: (NSXPCInterface *)remoteObjectInterface |
82 | 184 | { |
83 | | - [self notImplemented: _cmd]; |
| 185 | + ASSIGN(_remoteObjectInterface, remoteObjectInterface); |
84 | 186 | } |
85 | 187 |
|
86 | 188 | - (id) remoteObjectProxy |
87 | 189 | { |
88 | | - return [self notImplemented: _cmd]; |
| 190 | + return _remoteObjectProxy; |
89 | 191 | } |
90 | 192 |
|
91 | 193 | - (void) setRemoteObjectProxy: (id)remoteObjectProxy |
92 | 194 | { |
93 | | - [self notImplemented: _cmd]; |
| 195 | + ASSIGN(_remoteObjectProxy, remoteObjectProxy); |
94 | 196 | } |
95 | 197 |
|
96 | 198 | - (id) remoteObjectProxyWithErrorHandler:(GSXPCProxyErrorHandler)handler |
97 | 199 | { |
98 | | - return [self notImplemented: _cmd]; |
| 200 | + return [self remoteObjectProxy]; |
99 | 201 | } |
100 | 202 |
|
101 | 203 | - (id) synchronousRemoteObjectProxyWithErrorHandler: |
102 | 204 | (GSXPCProxyErrorHandler)handler |
103 | 205 | { |
104 | | - return [self notImplemented: _cmd]; |
| 206 | + return [self remoteObjectProxy]; |
105 | 207 | } |
106 | 208 |
|
107 | 209 | - (GSXPCInterruptionHandler) interruptionHandler |
108 | 210 | { |
109 | | - return NULL; |
| 211 | + return _interruptionHandler; |
110 | 212 | } |
111 | 213 |
|
112 | 214 | - (void) setInterruptionHandler: (GSXPCInterruptionHandler)handler |
113 | 215 | { |
114 | | - [self notImplemented: _cmd]; |
| 216 | + ASSIGNCOPY(_interruptionHandler, handler); |
115 | 217 | } |
116 | 218 |
|
117 | 219 | - (GSXPCInvalidationHandler) invalidationHandler |
118 | 220 | { |
119 | | - return NULL; |
| 221 | + return _invalidationHandler; |
120 | 222 | } |
121 | 223 |
|
122 | 224 | - (void) setInvalidationHandler: (GSXPCInvalidationHandler)handler |
123 | 225 | { |
124 | | - [self notImplemented: _cmd]; |
| 226 | + ASSIGNCOPY(_invalidationHandler, handler); |
125 | 227 | } |
126 | 228 |
|
127 | 229 | - (void) resume |
128 | 230 | { |
129 | | - [self notImplemented: _cmd]; |
| 231 | + _resumed = YES; |
| 232 | + [self _setupLibXPCConnectionIfPossible]; |
| 233 | +#if GS_USE_LIBXPC |
| 234 | + if (_xpcConnection != NULL) |
| 235 | + { |
| 236 | + xpc_connection_resume(_xpcConnection); |
| 237 | + } |
| 238 | +#endif |
130 | 239 | } |
131 | 240 |
|
132 | 241 | - (void) suspend |
133 | 242 | { |
134 | | - [self notImplemented: _cmd]; |
| 243 | + _resumed = NO; |
| 244 | +#if GS_USE_LIBXPC |
| 245 | + if (_xpcConnection != NULL) |
| 246 | + { |
| 247 | + xpc_connection_suspend(_xpcConnection); |
| 248 | + } |
| 249 | +#endif |
135 | 250 | } |
136 | 251 |
|
137 | 252 | - (void) invalidate |
138 | 253 | { |
139 | | - [self notImplemented: _cmd]; |
| 254 | + BOOL wasInvalidated = _invalidated; |
| 255 | + |
| 256 | + _invalidated = YES; |
| 257 | +#if GS_USE_LIBXPC |
| 258 | + if (_xpcConnection != NULL) |
| 259 | + { |
| 260 | + xpc_connection_cancel(_xpcConnection); |
| 261 | + xpc_release(_xpcConnection); |
| 262 | + _xpcConnection = NULL; |
| 263 | + } |
| 264 | +#endif |
| 265 | + if (wasInvalidated == NO && _invalidationHandler != NULL) |
| 266 | + { |
| 267 | + _invalidationHandler(); |
| 268 | + } |
140 | 269 | } |
141 | 270 |
|
142 | 271 | - (NSUInteger) auditSessionIdentifier |
143 | 272 | { |
144 | | - return (NSUInteger)[self notImplemented: _cmd]; |
| 273 | + return 0; |
145 | 274 | } |
146 | 275 | - (pid_t) processIdentifier |
147 | 276 | { |
148 | | - return (pid_t)(uintptr_t)[self notImplemented: _cmd]; |
| 277 | +#if GS_USE_LIBXPC |
| 278 | + if (_xpcConnection != NULL) |
| 279 | + { |
| 280 | + return xpc_connection_get_pid(_xpcConnection); |
| 281 | + } |
| 282 | +#endif |
| 283 | + return 0; |
149 | 284 | } |
150 | 285 | - (uid_t) effectiveUserIdentifier |
151 | 286 | { |
152 | | - return (uid_t)(uintptr_t)[self notImplemented: _cmd]; |
| 287 | +#if GS_USE_LIBXPC |
| 288 | + if (_xpcConnection != NULL) |
| 289 | + { |
| 290 | + return xpc_connection_get_euid(_xpcConnection); |
| 291 | + } |
| 292 | +#endif |
| 293 | + return (uid_t)0; |
153 | 294 | } |
154 | 295 | - (gid_t) effectiveGroupIdentifier |
155 | 296 | { |
156 | | - return (gid_t)(uintptr_t)[self notImplemented: _cmd]; |
| 297 | +#if GS_USE_LIBXPC |
| 298 | + if (_xpcConnection != NULL) |
| 299 | + { |
| 300 | + return xpc_connection_get_egid(_xpcConnection); |
| 301 | + } |
| 302 | +#endif |
| 303 | + return (gid_t)0; |
157 | 304 | } |
158 | 305 | @end |
159 | 306 |
|
|
0 commit comments