1 #import <TargetConditionals.h>
5 #import <Foundation/Foundation.h>
8 #import <Security/SecXPCHelper.h>
10 #import "keychain/categories/NSError+UsefulConstructors.h"
12 #import "OTPairingClient.h"
13 #import "OTPairingConstants.h"
16 OTPairingInitiateWithCompletion(dispatch_queue_t queue, void (^completion)(bool success, NSError *))
18 xpc_connection_t connection;
21 connection = xpc_connection_create_mach_service(OTPairingMachServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
22 xpc_connection_set_event_handler(connection, ^(__unused xpc_object_t event) {
24 xpc_connection_activate(connection);
26 message = xpc_dictionary_create(NULL, NULL, 0);
27 xpc_dictionary_set_uint64(message, OTPairingXPCKeyOperation, OTPairingOperationInitiate);
29 xpc_connection_send_message_with_reply(connection, message, queue, ^(xpc_object_t reply) {
30 if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
31 bool success = xpc_dictionary_get_bool(reply, OTPairingXPCKeySuccess);
33 const void *errptr = xpc_dictionary_get_data(reply, OTPairingXPCKeyError, &errlen);
38 errordata = [NSData dataWithBytesNoCopy:(void *)errptr length:errlen freeWhenDone:NO];
39 nserr = [SecXPCHelper errorFromEncodedData:errordata];
42 completion(success, nserr);
43 } else if (reply == XPC_ERROR_CONNECTION_INVALID) {
44 // This error is expected; otpaird is a NanoLaunchDaemon, only loaded when companion is paired.
45 os_log(OS_LOG_DEFAULT, "otpaird connection invalid (daemon unloaded?)");
46 completion(true, nil);
49 NSDictionary *userInfo = nil;
51 desc = xpc_copy_description(reply);
52 userInfo = @{ NSLocalizedDescriptionKey : [NSString stringWithUTF8String:desc] };
55 completion(false, [NSError errorWithDomain:OTPairingErrorDomain code:OTPairingErrorTypeXPC userInfo:userInfo]);
60 #endif /* TARGET_OS_WATCH */