blob: e08c04ad83ee9ed2aae9c2d868c93185337206f6 [file] [log] [blame]
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "DaemonUtilities.h"
#import <wtf/RetainPtr.h>
#import <wtf/cocoa/Entitlements.h>
namespace WebKit {
void startListeningForMachServiceConnections(const char* serviceName, const char* entitlement, void(*connectionAdded)(xpc_connection_t), void(*connectionRemoved)(xpc_connection_t), void(*eventHandler)(xpc_object_t))
{
static NeverDestroyed<RetainPtr<xpc_connection_t>> listener = xpc_connection_create_mach_service(serviceName, dispatch_get_main_queue(), XPC_CONNECTION_MACH_SERVICE_LISTENER);
xpc_connection_set_event_handler(listener.get().get(), ^(xpc_object_t peer) {
if (xpc_get_type(peer) != XPC_TYPE_CONNECTION)
return;
#if USE(APPLE_INTERNAL_SDK)
if (entitlement && !WTF::hasEntitlement(peer, entitlement)) {
NSLog(@"Connection attempted without required entitlement");
xpc_connection_cancel(peer);
return;
}
#endif
xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
if (event == XPC_ERROR_CONNECTION_INVALID) {
#if HAVE(XPC_CONNECTION_COPY_INVALIDATION_REASON)
auto reason = std::unique_ptr<char[]>(xpc_connection_copy_invalidation_reason(peer));
NSLog(@"Failed to start listening for connections to mach service %s, reason: %s", serviceName, reason.get());
#else
NSLog(@"Failed to start listening for connections to mach service %s, likely because it is not registered with launchd", serviceName);
#endif
NSLog(@"Removing peer connection %p", peer);
connectionRemoved(peer);
return;
}
if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
NSLog(@"Removing peer connection %p", peer);
connectionRemoved(peer);
return;
}
eventHandler(event);
});
xpc_connection_set_target_queue(peer, dispatch_get_main_queue());
xpc_connection_activate(peer);
NSLog(@"Adding peer connection %p", peer);
connectionAdded(peer);
});
xpc_connection_activate(listener.get().get());
}
RetainPtr<xpc_object_t> vectorToXPCData(Vector<uint8_t>&& vector)
{
auto bufferSize = vector.size();
auto rawPointer = vector.releaseBuffer().leakPtr();
auto dispatchData = adoptNS(dispatch_data_create(rawPointer, bufferSize, dispatch_get_main_queue(), ^{
fastFree(rawPointer);
}));
return adoptNS(xpc_data_create_with_dispatch_data(dispatchData.get()));
}
} // namespace WebKit