Loading...
--- xnu/xnu-12377.101.15/libkern/coreanalytics/coreanalytics_shim.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2021 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#define IOKIT_ENABLE_SHARED_PTR
-#include <kern/debug.h>
-#include <libkern/coreanalytics/coreanalytics.h>
-#include <libkern/coreanalytics/coreanalytics_shim.h>
-#include <libkern/c++/OSBoolean.h>
-#include <libkern/c++/OSDictionary.h>
-#include <libkern/c++/OSNumber.h>
-#include <libkern/c++/OSMetaClass.h>
-#include <libkern/c++/OSString.h>
-#include <os/atomic.h>
-#include <os/log.h>
-#include <sys/errno.h>
-
-/* Pulled from CoreAnalyticsHub.h in CoreAnalytics project */
-static const char *kCoreAnalyticsMatchingClassName = "CoreAnalyticsHub";
-
-core_analytics_hub_functions_t *core_analytics_hub_functions = NULL;
-
-core_analytics_family_service_t *
-core_analytics_family_match()
-{
- OSSharedPtr<OSDictionary> dict = IOService::serviceMatching(kCoreAnalyticsMatchingClassName);
- OSSharedPtr<IOService> service = nullptr;
- if (dict) {
- service = IOService::waitForMatchingService(dict.get());
- } else {
- os_log_with_startup_serial(OS_LOG_DEFAULT, "No service matching %s\n", kCoreAnalyticsMatchingClassName);
- }
- if (service) {
- return service.detach();
- } else {
- os_log_with_startup_serial(OS_LOG_DEFAULT, "Unable to match CoreAnalyticsHub\n");
- return nullptr;
- }
-}
-
-void
-core_analytics_family_release(core_analytics_family_service_t *service)
-{
- service->release();
-}
-
-typedef struct core_analytics_serialized_event_s {
- OSSharedPtr<OSString> case_event_name;
- OSSharedPtr<OSDictionary> case_event;
-} core_analytics_serialized_event_t;
-
-/*
- * Stringifying CA_BOOL is different in C vs. C++ b/c the underlying
- * bool typename is different (_Bool vs bool).
- * We want to support both since the event may have been defined in C or C++ code.
- */
-extern const char *core_analytics_ca_bool_c_stringified;
-const char *core_analytics_ca_bool_cpp_stringified = _CA_STRINGIFY_EXPAND(CA_BOOL);
-
-static OSSharedPtr<OSObject>
-serialize_event_field(const char **field_spec, ptrdiff_t *event, OSSharedPtr<const OSSymbol> *key)
-{
- OSSharedPtr<OSObject> field = nullptr;
- ptrdiff_t field_value = (ptrdiff_t) *event;
- uint64_t number_value;
- const char *str_value;
- size_t str_len = 0;
- bool bool_value;
-
- if (strcmp(*field_spec, _CA_STRINGIFY_EXPAND(CA_INT)) == 0) {
- number_value = *(const uint64_t *)field_value;
- field = OSNumber::withNumber(number_value, sizeof(uint64_t) * 8);
- *event += sizeof(const uint64_t);
- } else if (strcmp(*field_spec, core_analytics_ca_bool_cpp_stringified) == 0 ||
- strcmp(*field_spec, core_analytics_ca_bool_c_stringified) == 0) {
- bool_value = *(const bool *)field_value;
- field = OSBoolean::withBoolean(bool_value);
- *event += sizeof(const bool);
- } else if ((str_len = core_analytics_field_is_string(*field_spec)) != 0) {
- str_value = (const char *) field_value;
- assert(strlen(str_value) < str_len);
- if (strlen(str_value) < str_len) {
- field = OSString::withCString(str_value);
- } else {
- field = nullptr;
- }
- *event += str_len;
- } else {
- panic("Unknown CoreAnalytics event type: %s.", *field_spec);
- }
- *field_spec += strlen(*field_spec) + 1;
-
- *key = OSSymbol::withCString(*field_spec);
- assert(*key != nullptr);
- if (!*key) {
- return nullptr;
- }
- *field_spec += strlen(*field_spec) + 1;
- return field;
-}
-
-static int
-core_analytics_serialize_event(const char *event_spec,
- const ca_event_t event,
- core_analytics_serialized_event_t *serialized_event)
-{
- serialized_event->case_event_name = nullptr;
- serialized_event->case_event = nullptr;
- OSSharedPtr<OSDictionary> dict = nullptr;
- bool success;
- OSSharedPtr<OSString> name = OSString::withCStringNoCopy(event_spec);
- if (!name) {
- return ENOMEM;
- }
- dict = OSDictionary::withCapacity(1);
- if (!dict) {
- return ENOMEM;
- }
- const char *spec_curr = event_spec + strlen(event_spec) + 1;
- ptrdiff_t event_curr = (ptrdiff_t) event->data;
- while (strlen(spec_curr) != 0) {
- OSSharedPtr<const OSSymbol> key = NULL;
- OSSharedPtr<OSObject> object = serialize_event_field(&spec_curr, &event_curr, &key);
- if (!object) {
- return ENOMEM;
- }
- success = dict->setObject(key, object);
- if (!success) {
- return ENOMEM;
- }
- }
-
- serialized_event->case_event_name = name;
- serialized_event->case_event = dict;
- return 0;
-}
-
-int
-core_analytics_send_event_lazy(
- core_analytics_family_service_t *core_analytics_hub,
- const char *event_spec, const ca_event_t event)
-{
- int ret = 0;
- bool success;
- static constexpr size_t kMaxRetries = 5;
- static constexpr uint64_t kDelayBetweenRetries = 1000; // microseconds
- core_analytics_serialized_event_t serialized;
- if (!core_analytics_hub_functions) {
- return EAGAIN;
- }
-
- ret = core_analytics_serialize_event(event_spec, event, &serialized);
- if (ret != 0) {
- return ret;
- }
- for (size_t i = 0; i < kMaxRetries; i++) {
- success = core_analytics_hub_functions->analytics_send_event_lazy(core_analytics_hub, serialized.case_event_name.get(), serialized.case_event.get());
- if (success) {
- break;
- } else {
- if (i != kMaxRetries - 1) {
- delay(kDelayBetweenRetries);
- } else {
- ret = EAGAIN;
- break;
- }
- }
- }
- return ret;
-}
-
-void
-core_analytics_hub_register(core_analytics_hub_functions_t *fns)
-{
- if (fns->version != CORE_ANALYTICS_FUNCTIONS_TABLE_VERSION) {
- panic("CoreAnalyticsHub is out of sync with xnu. CoreAnalyticsHub table version: %d. xnu table version: %d", fns->version, CORE_ANALYTICS_FUNCTIONS_TABLE_VERSION);
- }
- core_analytics_hub_functions = fns;
- os_log_with_startup_serial(OS_LOG_DEFAULT, "Registered CoreAnalyticsHub functions with xnu.\n");
-}