/*
- * Copyright (c) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2013-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/queue.h>
#include <CoreFoundation/CFRunLoop.h>
#include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
+#include <SystemConfiguration/SCPrivate.h>
#include "IPMonitorControlServer.h"
#include "symbol_scope.h"
#include "IPMonitorControlPrivate.h"
-#include <SystemConfiguration/SCPrivate.h>
+#include "IPMonitorAWDReport.h"
#ifdef TEST_IPMONITOR_CONTROL
-#define my_log(__level, fmt, ...) SCPrint(TRUE, stdout, CFSTR(fmt "\n"), ## __VA_ARGS__)
+#define my_log(__level, __format, ...) SCPrint(TRUE, stdout, CFSTR(__format "\n"), ## __VA_ARGS__)
#else /* TEST_IPMONITOR_CONTROL */
#include "ip_plugin.h"
struct ControlSession {
LIST_ENTRY_ControlSession link;
xpc_connection_t connection;
+
CFMutableDictionaryRef assertions; /* ifname<string> = rank<number> */
+ CFMutableDictionaryRef advisories; /* ifname<string> = advisory<number> */
};
/**
STATIC CFMutableArrayRef S_if_changes;
STATIC CFRange S_if_changes_range;
+STATIC CFNumberRef
+RankLastNumberGet(void)
+{
+ STATIC CFNumberRef rank_last;
+
+ if (rank_last == NULL) {
+ SCNetworkServicePrimaryRank rank;
+
+ rank = kSCNetworkServicePrimaryRankLast;
+ rank_last = CFNumberCreate(NULL, kCFNumberSInt32Type, &rank);
+ }
+ return (rank_last);
+}
+
STATIC void
InterfaceChangedListAddInterface(CFStringRef ifname)
{
CFArrayAppendValue(S_if_changes, ifname);
S_if_changes_range.length = 1;
}
- else if (CFArrayContainsValue(S_if_changes, S_if_changes_range,
- ifname) == FALSE) {
+ else if (!CFArrayContainsValue(S_if_changes, S_if_changes_range, ifname)) {
CFArrayAppendValue(S_if_changes, ifname);
S_if_changes_range.length++;
}
= CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(*assertions_p, key, value);
+ CFDictionarySetValue(*assertions_p, key, rank);
return;
}
existing_rank = CFDictionaryGetValue(*assertions_p, key);
if (existing_rank == NULL
|| (CFNumberCompare(rank, existing_rank, NULL)
== kCFCompareGreaterThan)) {
- CFDictionarySetValue(*assertions_p, key, value);
+ CFDictionarySetValue(*assertions_p, key, rank);
+ }
+ return;
+}
+
+STATIC void
+InterfaceAdvisoryAdd(const void * key, const void * value, void * context)
+{
+#pragma unused(value)
+ CFMutableDictionaryRef * assertions_p;
+ CFNumberRef existing_rank;
+ CFNumberRef rank;
+
+ /* an interface advisory implies RankLast */
+ rank = RankLastNumberGet();
+ assertions_p = (CFMutableDictionaryRef *)context;
+ if (*assertions_p == NULL) {
+ *assertions_p
+ = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(*assertions_p, key, rank);
+ return;
+ }
+ existing_rank = CFDictionaryGetValue(*assertions_p, key);
+ if (existing_rank == NULL
+ || (CFNumberCompare(rank, existing_rank, NULL)
+ == kCFCompareGreaterThan)) {
+ CFDictionarySetValue(*assertions_p, key, rank);
}
return;
}
ControlSessionRef session;
LIST_FOREACH(session, &S_ControlSessions, link) {
- if (session->assertions == NULL) {
- continue;
+ if (session->advisories != NULL) {
+ CFDictionaryApplyFunction(session->advisories,
+ InterfaceAdvisoryAdd,
+ &assertions);
+ }
+ if (session->assertions != NULL) {
+ CFDictionaryApplyFunction(session->assertions,
+ InterfaceRankAssertionAdd,
+ &assertions);
}
- CFDictionaryApplyFunction(session->assertions,
- InterfaceRankAssertionAdd,
- &assertions);
}
return (assertions);
}
+STATIC Boolean
+InterfaceHasAdvisories(CFStringRef ifname)
+{
+ ControlSessionRef session;
+
+ LIST_FOREACH(session, &S_ControlSessions, link) {
+ if (session->advisories != NULL
+ && CFDictionaryContainsKey(session->advisories, ifname)) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+
+STATIC AWDIPMonitorInterfaceAdvisoryReport_Flags
+advisory_to_flags(SCNetworkInterfaceAdvisory advisory)
+{
+ AWDIPMonitorInterfaceAdvisoryReport_Flags flags;
+
+ switch (advisory) {
+ case kSCNetworkInterfaceAdvisoryNone:
+ default:
+ flags = 0;
+ break;
+ case kSCNetworkInterfaceAdvisoryLinkLayerIssue:
+ flags = AWDIPMonitorInterfaceAdvisoryReport_Flags_LINK_LAYER_ISSUE;
+ break;
+ case kSCNetworkInterfaceAdvisoryUplinkIssue:
+ flags = AWDIPMonitorInterfaceAdvisoryReport_Flags_UPLINK_ISSUE;
+ break;
+ }
+ return (flags);
+}
+
+STATIC AWDIPMonitorInterfaceAdvisoryReport_Flags
+InterfaceGetAdvisoryFlags(CFStringRef ifname,
+ ControlSessionRef exclude_session,
+ uint32_t * ret_count)
+{
+ uint32_t count;
+ AWDIPMonitorInterfaceAdvisoryReport_Flags flags = 0;
+ ControlSessionRef session;
+
+ count = 0;
+ LIST_FOREACH(session, &S_ControlSessions, link) {
+ SCNetworkInterfaceAdvisory advisory = 0;
+ CFNumberRef advisory_cf;
+
+ if (session->advisories == NULL) {
+ continue;
+ }
+ if (exclude_session != NULL && exclude_session == session) {
+ continue;
+ }
+ advisory_cf = CFDictionaryGetValue(session->advisories, ifname);
+ if (advisory_cf == NULL) {
+ /* session has no advisories for this interface */
+ continue;
+ }
+ (void)CFNumberGetValue(advisory_cf, kCFNumberSInt32Type, &advisory);
+ flags |= advisory_to_flags(advisory);
+ count++;
+ }
+ *ret_count = count;
+ return (flags);
+}
+
+STATIC Boolean
+AnyInterfaceHasAdvisories(void)
+{
+ ControlSessionRef session;
+
+ LIST_FOREACH(session, &S_ControlSessions, link) {
+ if (session->advisories != NULL) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
STATIC CFRunLoopRef S_runloop;
STATIC CFRunLoopSourceRef S_signal_source;
}
STATIC void
-GenerateNotification(void)
+NotifyIPMonitor(void)
{
if (S_signal_source != NULL) {
CFRunLoopSourceSignal(S_signal_source);
return;
}
+STATIC void
+NotifyInterfaceAdvisory(CFStringRef ifname)
+{
+ CFStringRef key;
+
+ key = _IPMonitorControlCopyInterfaceAdvisoryNotificationKey(ifname);
+ SCDynamicStoreNotifyValue(NULL, key);
+ CFRelease(key);
+ return;
+}
+
+STATIC void
+SubmitInterfaceAdvisoryMetric(CFStringRef ifname,
+ AWDIPMonitorInterfaceAdvisoryReport_Flags flags,
+ uint32_t count)
+{
+ InterfaceAdvisoryReportRef report;
+ AWDIPMonitorInterfaceType type;
+
+ /* XXX need to actually figure out what the interface type is */
+ if (CFStringHasPrefix(ifname, CFSTR("pdp"))) {
+ type = AWDIPMonitorInterfaceType_IPMONITOR_INTERFACE_TYPE_CELLULAR;
+ }
+ else {
+ type = AWDIPMonitorInterfaceType_IPMONITOR_INTERFACE_TYPE_WIFI;
+ }
+ report = InterfaceAdvisoryReportCreate(type);
+ if (report == NULL) {
+ return;
+ }
+ InterfaceAdvisoryReportSetFlags(report, flags);
+ InterfaceAdvisoryReportSetAdvisoryCount(report, count);
+ InterfaceAdvisoryReportSubmit(report);
+ my_log(LOG_NOTICE, "%@: submitted AWD report %@", ifname, report);
+ CFRelease(report);
+}
+
/**
** ControlSession
**/
STATIC void
AddChangedInterface(const void * key, const void * value, void * context)
{
+#pragma unused(value)
+#pragma unused(context)
+ InterfaceChangedListAddInterface((CFStringRef)key);
+ return;
+}
+
+STATIC void
+AddChangedInterfaceNotify(const void * key, const void * value, void * context)
+{
+#pragma unused(value)
+#pragma unused(context)
InterfaceChangedListAddInterface((CFStringRef)key);
+ NotifyInterfaceAdvisory((CFStringRef)key);
return;
}
+STATIC void
+GenerateMetricForInterfaceAtSessionClose(const void * key, const void * value,
+ void * context)
+{
+ uint32_t count_after;
+ uint32_t count_before;
+ AWDIPMonitorInterfaceAdvisoryReport_Flags flags_after;
+ AWDIPMonitorInterfaceAdvisoryReport_Flags flags_before;
+ CFStringRef ifname = (CFStringRef)key;
+ ControlSessionRef session = (ControlSessionRef)context;
+
+#pragma unused(value)
+ /*
+ * Get the flags and count including this session, then again
+ * excluding this session. If either flags or count are different,
+ * generate the metric.
+ */
+ flags_before = InterfaceGetAdvisoryFlags(ifname, NULL, &count_before);
+ flags_after = InterfaceGetAdvisoryFlags(ifname, session, &count_after);
+ if (flags_before != flags_after || count_before != count_after) {
+ SubmitInterfaceAdvisoryMetric(ifname, flags_after, count_after);
+ }
+ return;
+}
+
+STATIC void
+ControlSessionGenerateMetricsAtClose(ControlSessionRef session)
+{
+ if (session->advisories == NULL) {
+ return;
+ }
+ CFDictionaryApplyFunction(session->advisories,
+ GenerateMetricForInterfaceAtSessionClose,
+ session);
+}
+
STATIC void
ControlSessionInvalidate(ControlSessionRef session)
{
my_log(LOG_DEBUG, "Invalidating %p", session);
+ ControlSessionGenerateMetricsAtClose(session);
LIST_REMOVE(session, link);
- if (session->assertions != NULL) {
- my_log(LOG_DEBUG,
- "IPMonitorControlServer: %p pid %d removing assertions %@",
- session->connection,
- xpc_connection_get_pid(session->connection),
- session->assertions);
- CFDictionaryApplyFunction(session->assertions, AddChangedInterface,
- NULL);
- CFRelease(session->assertions);
- session->assertions = NULL;
- GenerateNotification();
+ if (session->assertions != NULL || session->advisories != NULL) {
+ if (session->advisories != NULL) {
+ my_log(LOG_NOTICE,
+ "pid %d removing advisories %@",
+ xpc_connection_get_pid(session->connection),
+ session->advisories);
+ CFDictionaryApplyFunction(session->advisories,
+ AddChangedInterfaceNotify,
+ NULL);
+ my_CFRelease(&session->advisories);
+ }
+ if (session->assertions != NULL) {
+ my_log(LOG_NOTICE,
+ "pid %d removing assertions %@",
+ xpc_connection_get_pid(session->connection),
+ session->assertions);
+ CFDictionaryApplyFunction(session->assertions, AddChangedInterface,
+ NULL);
+ my_CFRelease(&session->assertions);
+ }
+ NotifyIPMonitor();
}
return;
}
ControlSessionRef session;
session = (ControlSessionRef)malloc(sizeof(*session));
- bzero(session, sizeof(*session));
+ memset(session, 0, sizeof(*session));
session->connection = connection;
xpc_connection_set_finalizer_f(connection, ControlSessionRelease);
xpc_connection_set_context(connection, session);
}
STATIC ControlSessionRef
-ControlSessionGet(xpc_connection_t connection)
+ControlSessionForConnection(xpc_connection_t connection)
{
ControlSessionRef session;
CFRelease(rank_cf);
}
InterfaceChangedListAddInterface(ifname_cf);
- GenerateNotification();
+ NotifyIPMonitor();
CFRelease(ifname_cf);
return;
}
return (rank);
}
+STATIC void
+ControlSessionSetInterfaceAdvisory(ControlSessionRef session,
+ const char * ifname,
+ SCNetworkInterfaceAdvisory advisory)
+{
+ uint32_t count_after;
+ uint32_t count_before;
+ AWDIPMonitorInterfaceAdvisoryReport_Flags flags_after;
+ AWDIPMonitorInterfaceAdvisoryReport_Flags flags_before;
+ CFStringRef ifname_cf;
+
+ if (session->advisories == NULL) {
+ if (advisory == kSCNetworkInterfaceAdvisoryNone) {
+ /* no advisories, no need to store advisory */
+ return;
+ }
+ session->advisories
+ = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ ifname_cf = CFStringCreateWithCString(NULL, ifname,
+ kCFStringEncodingUTF8);
+ flags_before = InterfaceGetAdvisoryFlags(ifname_cf, NULL, &count_before);
+ if (advisory == kSCNetworkInterfaceAdvisoryNone) {
+ CFDictionaryRemoveValue(session->advisories, ifname_cf);
+ if (CFDictionaryGetCount(session->advisories) == 0) {
+ CFRelease(session->advisories);
+ session->advisories = NULL;
+ }
+ }
+ else {
+ CFNumberRef advisory_cf;
+
+ advisory_cf = CFNumberCreate(NULL, kCFNumberSInt32Type, &advisory);
+ CFDictionarySetValue(session->advisories, ifname_cf, advisory_cf);
+ CFRelease(advisory_cf);
+ }
+ flags_after = InterfaceGetAdvisoryFlags(ifname_cf, NULL, &count_after);
+ if (flags_before != flags_after || count_before != count_after) {
+ SubmitInterfaceAdvisoryMetric(ifname_cf, flags_after, count_after);
+ }
+ InterfaceChangedListAddInterface(ifname_cf);
+ NotifyInterfaceAdvisory(ifname_cf);
+ NotifyIPMonitor();
+ CFRelease(ifname_cf);
+ return;
+}
+
/**
** IPMonitorControlServer
**/
+
+STATIC const char *
+get_process_name(xpc_object_t request)
+{
+ const char * process_name;
+
+ process_name
+ = xpc_dictionary_get_string(request,
+ kIPMonitorControlRequestKeyProcessName);
+ if (process_name == NULL) {
+ process_name = "<unknown>";
+ }
+ return (process_name);
+}
+
STATIC Boolean
-IPMonitorControlServerValidateConnection(xpc_connection_t connection)
+IPMonitorControlServerConnectionIsRoot(xpc_connection_t connection)
{
uid_t uid;
return (uid == 0);
}
+STATIC Boolean
+IPMonitorControlServerConnectionHasEntitlement(xpc_connection_t connection,
+ const char * entitlement)
+{
+ Boolean entitled = FALSE;
+ xpc_object_t val;
+
+ val = xpc_connection_copy_entitlement_value(connection, entitlement);
+ if (val != NULL) {
+ if (xpc_get_type(val) == XPC_TYPE_BOOL) {
+ entitled = xpc_bool_get_value(val);
+ }
+ xpc_release(val);
+ }
+ return (entitled);
+}
+
+STATIC const char *
+get_rank_str(SCNetworkServicePrimaryRank rank)
+{
+ const char * str = NULL;
+
+ switch (rank) {
+ case kSCNetworkServicePrimaryRankDefault:
+ str = "Default";
+ break;
+ case kSCNetworkServicePrimaryRankFirst:
+ str = "First";
+ break;
+ case kSCNetworkServicePrimaryRankLast:
+ str = "Last";
+ break;
+ case kSCNetworkServicePrimaryRankNever:
+ str = "Never";
+ break;
+ case kSCNetworkServicePrimaryRankScoped:
+ str = "Scoped";
+ break;
+ default:
+ break;
+ }
+ return (str);
+}
+
STATIC int
-IPMonitorControlServerHandleSetInterfaceRank(xpc_connection_t connection,
- xpc_object_t request,
- xpc_object_t reply)
+HandleSetInterfaceRank(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
{
+#pragma unused(reply)
const char * ifname;
SCNetworkServicePrimaryRank rank;
+ const char * rank_str;
ControlSessionRef session;
- if (IPMonitorControlServerValidateConnection(connection) == FALSE) {
+ if (!IPMonitorControlServerConnectionIsRoot(connection)) {
my_log(LOG_INFO, "connection %p pid %d permission denied",
connection, xpc_connection_get_pid(connection));
return (EPERM);
rank = (SCNetworkServicePrimaryRank)
xpc_dictionary_get_uint64(request,
kIPMonitorControlRequestKeyPrimaryRank);
- switch (rank) {
- case kSCNetworkServicePrimaryRankDefault:
- case kSCNetworkServicePrimaryRankFirst:
- case kSCNetworkServicePrimaryRankLast:
- case kSCNetworkServicePrimaryRankNever:
- case kSCNetworkServicePrimaryRankScoped:
- break;
- default:
+ rank_str = get_rank_str(rank);
+ if (rank_str == NULL) {
return (EINVAL);
}
- session = ControlSessionGet(connection);
+ session = ControlSessionForConnection(connection);
ControlSessionSetInterfaceRank(session, ifname, rank);
- my_log(LOG_INFO, "connection %p pid %d set %s %u",
- connection, xpc_connection_get_pid(connection), ifname, rank);
+ my_log(LOG_NOTICE, "%s[%d] SetInterfaceRank(%s) = %s (%u)",
+ get_process_name(request),
+ xpc_connection_get_pid(connection), ifname, rank_str, rank);
return (0);
}
STATIC int
-IPMonitorControlServerHandleGetInterfaceRank(xpc_connection_t connection,
- xpc_object_t request,
- xpc_object_t reply)
+HandleGetInterfaceRank(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
{
const char * ifname;
SCNetworkServicePrimaryRank rank;
return (0);
}
+STATIC const char *
+get_advisory_str(SCNetworkInterfaceAdvisory advisory)
+{
+ const char * str = NULL;
+
+ switch (advisory) {
+ case kSCNetworkInterfaceAdvisoryNone:
+ str = "None";
+ break;
+ case kSCNetworkInterfaceAdvisoryLinkLayerIssue:
+ str = "LinkLayerIssue";
+ break;
+ case kSCNetworkInterfaceAdvisoryUplinkIssue:
+ str = "UplinkIssue";
+ break;
+ default:
+ break;
+ }
+ return (str);
+}
+
+STATIC int
+HandleSetInterfaceAdvisory(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
+{
+#pragma unused(reply)
+ SCNetworkInterfaceAdvisory advisory;
+ const char * advisory_str;
+ const char * ifname;
+ const char * reason;
+ ControlSessionRef session;
+
+#define ENTITLEMENT "com.apple.SystemConfiguration.SCNetworkInterfaceSetAdvisory"
+ if (!IPMonitorControlServerConnectionIsRoot(connection)
+ && !IPMonitorControlServerConnectionHasEntitlement(connection,
+ ENTITLEMENT)) {
+ my_log(LOG_INFO, "connection %p pid %d permission denied",
+ connection, xpc_connection_get_pid(connection));
+ return (EPERM);
+ }
+ ifname
+ = xpc_dictionary_get_string(request,
+ kIPMonitorControlRequestKeyInterfaceName);
+ if (ifname == NULL) {
+ return (EINVAL);
+ }
+ reason
+ = xpc_dictionary_get_string(request,
+ kIPMonitorControlRequestKeyReason);
+ advisory = (SCNetworkInterfaceAdvisory)
+ xpc_dictionary_get_uint64(request, kIPMonitorControlRequestKeyAdvisory);
+
+ /* validate the advisory code */
+ advisory_str = get_advisory_str(advisory);
+ if (advisory_str == NULL) {
+ return (EINVAL);
+ }
+ session = ControlSessionForConnection(connection);
+ ControlSessionSetInterfaceAdvisory(session, ifname, advisory);
+ my_log(LOG_NOTICE, "%s[%d] SetInterfaceAdvisory(%s) = %s (%u) reason='%s'",
+ get_process_name(request),
+ xpc_connection_get_pid(connection), ifname, advisory_str, advisory,
+ reason != NULL ? reason : "" );
+ return (0);
+}
+
+STATIC int
+HandleInterfaceAdvisoryIsSet(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
+{
+#pragma unused(connection)
+ const char * ifname;
+ CFStringRef ifname_cf;
+
+ if (reply == NULL) {
+ /* no point in processing the request if we can't provide an answer */
+ return (EINVAL);
+ }
+ ifname
+ = xpc_dictionary_get_string(request,
+ kIPMonitorControlRequestKeyInterfaceName);
+ if (ifname == NULL) {
+ return (EINVAL);
+ }
+ ifname_cf = CFStringCreateWithCString(NULL, ifname,
+ kCFStringEncodingUTF8);
+ xpc_dictionary_set_bool(reply,
+ kIPMonitorControlResponseKeyAdvisoryIsSet,
+ InterfaceHasAdvisories(ifname_cf));
+ CFRelease(ifname_cf);
+ return (0);
+}
+
+STATIC int
+HandleAnyInterfaceAdvisoryIsSet(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
+{
+#pragma unused(connection)
+#pragma unused(request)
+ if (reply == NULL) {
+ /* no point in processing the request if we can't provide an answer */
+ return (EINVAL);
+ }
+ xpc_dictionary_set_bool(reply,
+ kIPMonitorControlResponseKeyAdvisoryIsSet,
+ AnyInterfaceHasAdvisories());
+ return (0);
+}
+
STATIC void
IPMonitorControlServerHandleDisconnect(xpc_connection_t connection)
{
ControlSessionRef session;
- my_log(LOG_DEBUG, "IPMonitorControlServer: client %p went away", connection);
+ my_log(LOG_DEBUG, "IPMonitorControlServer: client %p went away",
+ connection);
session = ControlSessionLookup(connection);
if (session == NULL) {
/* never asserted anything */
reply = xpc_dictionary_create_reply(request);
switch (request_type) {
case kIPMonitorControlRequestTypeSetInterfaceRank:
- error = IPMonitorControlServerHandleSetInterfaceRank(connection,
- request,
- reply);
+ error = HandleSetInterfaceRank(connection, request, reply);
break;
case kIPMonitorControlRequestTypeGetInterfaceRank:
- error = IPMonitorControlServerHandleGetInterfaceRank(connection,
- request,
- reply);
+ error = HandleGetInterfaceRank(connection, request, reply);
+ break;
+ case kIPMonitorControlRequestTypeSetInterfaceAdvisory:
+ error = HandleSetInterfaceAdvisory(connection, request, reply);
+ break;
+ case kIPMonitorControlRequestTypeInterfaceAdvisoryIsSet:
+ error = HandleInterfaceAdvisoryIsSet(connection, request, reply);
+ break;
+ case kIPMonitorControlRequestTypeAnyInterfaceAdvisoryIsSet:
+ error = HandleAnyInterfaceAdvisoryIsSet(connection, request, reply);
break;
default:
error = EINVAL;
xpc_handler_t handler;
handler = ^(xpc_object_t event) {
- os_activity_t activity_id;
-
- activity_id = os_activity_start("processing IPMonitor [rank] request",
- OS_ACTIVITY_FLAG_DEFAULT);
-
IPMonitorControlServerHandleRequest(connection, event);
-
- os_activity_end(activity_id);
};
xpc_connection_set_event_handler(connection, handler);
+ xpc_connection_set_target_queue(connection, S_IPMonitorControlServerQueue);
xpc_connection_resume(connection);
return;
}
return (NULL);
}
handler = ^(xpc_object_t event) {
- os_activity_t activity_id;
xpc_type_t type;
- activity_id = os_activity_start("processing IPMonitor [rank] connection request",
- OS_ACTIVITY_FLAG_DEFAULT);
-
type = xpc_get_type(event);
if (type == XPC_TYPE_CONNECTION) {
IPMonitorControlServerHandleNewConnection(event);
else {
my_log(LOG_NOTICE, "unknown event %p", type);
}
-
- os_activity_end(activity_id);
};
S_IPMonitorControlServerQueue = queue;
xpc_connection_set_event_handler(connection, handler);
IPMonitorControlServerStart(CFRunLoopRef runloop, CFRunLoopSourceRef rls,
Boolean * verbose)
{
+#pragma unused(verbose)
dispatch_queue_t q;
xpc_connection_t connection;