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 "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  [NSURLConnection sendAsynchronousRequest:request
51                                     queue:[NSOperationQueue mainQueue]
52                         completionHandler:^(NSURLResponse *response,
53                                             NSData *data,
54                                             NSError *error) {
55    if (completionHandler) {
56      completionHandler(response, data, error);
57    }
58  }];
59}
60
61// Posts data to the specified URL.
62+ (void)sendAsyncPostToURL:(NSURL *)url
63                  withData:(NSData *)data
64         completionHandler:(void (^)(BOOL succeeded,
65                                     NSData *data))completionHandler {
66  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
67  request.HTTPMethod = @"POST";
68  request.HTTPBody = data;
69  [[self class] sendAsyncRequest:request
70                completionHandler:^(NSURLResponse *response,
71                                    NSData *data,
72                                    NSError *error) {
73    if (error) {
74      RTCLogError(@"Error posting data: %@", error.localizedDescription);
75      if (completionHandler) {
76        completionHandler(NO, data);
77      }
78      return;
79    }
80    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
81    if (httpResponse.statusCode != 200) {
82      NSString *serverResponse = data.length > 0 ?
83          [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] :
84          nil;
85      RTCLogError(@"Received bad response: %@", serverResponse);
86      if (completionHandler) {
87        completionHandler(NO, data);
88      }
89      return;
90    }
91    if (completionHandler) {
92      completionHandler(YES, data);
93    }
94  }];
95}
96
97@end
98
99NSInteger ARDGetCpuUsagePercentage() {
100  // Create an array of thread ports for the current task.
101  const task_t task = mach_task_self();
102  thread_act_array_t thread_array;
103  mach_msg_type_number_t thread_count;
104  if (task_threads(task, &thread_array, &thread_count) != KERN_SUCCESS) {
105    return -1;
106  }
107
108  // Sum cpu usage from all threads.
109  float cpu_usage_percentage = 0;
110  thread_basic_info_data_t thread_info_data = {};
111  mach_msg_type_number_t thread_info_count;
112  for (size_t i = 0; i < thread_count; ++i) {
113    thread_info_count = THREAD_BASIC_INFO_COUNT;
114    kern_return_t ret = thread_info(thread_array[i],
115                                    THREAD_BASIC_INFO,
116                                    (thread_info_t)&thread_info_data,
117                                    &thread_info_count);
118    if (ret == KERN_SUCCESS) {
119      cpu_usage_percentage +=
120          100.f * (float)thread_info_data.cpu_usage / TH_USAGE_SCALE;
121    }
122  }
123
124  // Dealloc the created array.
125  vm_deallocate(task, (vm_address_t)thread_array,
126                sizeof(thread_act_t) * thread_count);
127  return lroundf(cpu_usage_percentage);
128}
129