1/*
2 *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#import "ARDUtilities.h"
12
13#import <mach/mach.h>
14
15#import <WebRTC/RTCLogging.h>
16
17@implementation NSDictionary (ARDUtilites)
18
19+ (NSDictionary *)dictionaryWithJSONString:(NSString *)jsonString {
20  NSParameterAssert(jsonString.length > 0);
21  NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
22  NSError *error = nil;
23  NSDictionary *dict =
24      [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
25  if (error) {
26    RTCLogError(@"Error parsing JSON: %@", error.localizedDescription);
27  }
28  return dict;
29}
30
31+ (NSDictionary *)dictionaryWithJSONData:(NSData *)jsonData {
32  NSError *error = nil;
33  NSDictionary *dict =
34      [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
35  if (error) {
36    RTCLogError(@"Error parsing JSON: %@", error.localizedDescription);
37  }
38  return dict;
39}
40
41@end
42
43@implementation NSURLConnection (ARDUtilities)
44
45+ (void)sendAsyncRequest:(NSURLRequest *)request
46       completionHandler:(void (^)(NSURLResponse *response,
47                                   NSData *data,
48                                   NSError *error))completionHandler {
49  // Kick off an async request which will call back on main thread.
50  NSURLSession *session = [NSURLSession sharedSession];
51  [[session dataTaskWithRequest:request
52              completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
53                if (completionHandler) {
54                  completionHandler(response, data, error);
55                }
56              }] resume];
57}
58
59// Posts data to the specified URL.
60+ (void)sendAsyncPostToURL:(NSURL *)url
61                  withData:(NSData *)data
62         completionHandler:(void (^)(BOOL succeeded,
63                                     NSData *data))completionHandler {
64  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
65  request.HTTPMethod = @"POST";
66  request.HTTPBody = data;
67  [[self class] sendAsyncRequest:request
68                completionHandler:^(NSURLResponse *response,
69                                    NSData *data,
70                                    NSError *error) {
71    if (error) {
72      RTCLogError(@"Error posting data: %@", error.localizedDescription);
73      if (completionHandler) {
74        completionHandler(NO, data);
75      }
76      return;
77    }
78    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
79    if (httpResponse.statusCode != 200) {
80      NSString *serverResponse = data.length > 0 ?
81          [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] :
82          nil;
83      RTCLogError(@"Received bad response: %@", serverResponse);
84      if (completionHandler) {
85        completionHandler(NO, data);
86      }
87      return;
88    }
89    if (completionHandler) {
90      completionHandler(YES, data);
91    }
92  }];
93}
94
95@end
96
97NSInteger ARDGetCpuUsagePercentage() {
98  // Create an array of thread ports for the current task.
99  const task_t task = mach_task_self();
100  thread_act_array_t thread_array;
101  mach_msg_type_number_t thread_count;
102  if (task_threads(task, &thread_array, &thread_count) != KERN_SUCCESS) {
103    return -1;
104  }
105
106  // Sum cpu usage from all threads.
107  float cpu_usage_percentage = 0;
108  thread_basic_info_data_t thread_info_data = {};
109  mach_msg_type_number_t thread_info_count;
110  for (size_t i = 0; i < thread_count; ++i) {
111    thread_info_count = THREAD_BASIC_INFO_COUNT;
112    kern_return_t ret = thread_info(thread_array[i],
113                                    THREAD_BASIC_INFO,
114                                    (thread_info_t)&thread_info_data,
115                                    &thread_info_count);
116    if (ret == KERN_SUCCESS) {
117      cpu_usage_percentage +=
118          100.f * (float)thread_info_data.cpu_usage / TH_USAGE_SCALE;
119    }
120  }
121
122  // Dealloc the created array.
123  vm_deallocate(task, (vm_address_t)thread_array,
124                sizeof(thread_act_t) * thread_count);
125  return lroundf(cpu_usage_percentage);
126}
127