PageRenderTime 59ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/src/platform_darwin.cc

https://github.com/rootslab/node
C++ | 227 lines | 156 code | 44 blank | 27 comment | 27 complexity | 80be32f006f1f70c43f1290bc83f8d03 MD5 | raw file
  1. // Copyright Joyent, Inc. and other Node contributors.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to permit
  8. // persons to whom the Software is furnished to do so, subject to the
  9. // following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included
  12. // in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #include "node.h"
  22. #include "platform.h"
  23. #include <v8.h>
  24. #include <mach/task.h>
  25. #include <mach/mach.h>
  26. #include <mach/mach_host.h>
  27. #include <limits.h> /* PATH_MAX */
  28. #include <unistd.h> // sysconf
  29. #include <sys/param.h>
  30. #include <sys/sysctl.h>
  31. #include <time.h>
  32. #include <sys/socket.h>
  33. #include <net/if.h>
  34. #include <netinet/in.h>
  35. #include <arpa/inet.h>
  36. #include <ifaddrs.h>
  37. namespace node {
  38. using namespace v8;
  39. static char *process_title;
  40. double Platform::prog_start_time = Platform::GetUptime();
  41. char** Platform::SetupArgs(int argc, char *argv[]) {
  42. process_title = argc ? strdup(argv[0]) : NULL;
  43. return argv;
  44. }
  45. // Platform::SetProcessTitle implemented in platform_darwin_proctitle.cc
  46. } // namespace node
  47. #include "platform_darwin_proctitle.cc"
  48. namespace node {
  49. const char* Platform::GetProcessTitle(int *len) {
  50. if (process_title) {
  51. *len = strlen(process_title);
  52. return process_title;
  53. }
  54. *len = 0;
  55. return NULL;
  56. }
  57. // Researched by Tim Becker and Michael Knight
  58. // http://blog.kuriositaet.de/?p=257
  59. int Platform::GetMemory(size_t *rss, size_t *vsize) {
  60. struct task_basic_info t_info;
  61. mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
  62. int r = task_info(mach_task_self(),
  63. TASK_BASIC_INFO,
  64. (task_info_t)&t_info,
  65. &t_info_count);
  66. if (r != KERN_SUCCESS) return -1;
  67. *rss = t_info.resident_size;
  68. *vsize = t_info.virtual_size;
  69. return 0;
  70. }
  71. int Platform::GetCPUInfo(Local<Array> *cpus) {
  72. Local<Object> cpuinfo;
  73. Local<Object> cputimes;
  74. unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
  75. multiplier = ((uint64_t)1000L / ticks);
  76. char model[512];
  77. uint64_t cpuspeed;
  78. size_t size;
  79. size = sizeof(model);
  80. if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
  81. return -1;
  82. }
  83. size = sizeof(cpuspeed);
  84. if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0) < 0) {
  85. return -1;
  86. }
  87. natural_t numcpus;
  88. mach_msg_type_number_t count;
  89. processor_cpu_load_info_data_t *info;
  90. if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
  91. reinterpret_cast<processor_info_array_t*>(&info),
  92. &count) != KERN_SUCCESS) {
  93. return -1;
  94. }
  95. *cpus = Array::New(numcpus);
  96. for (unsigned int i = 0; i < numcpus; i++) {
  97. cpuinfo = Object::New();
  98. cputimes = Object::New();
  99. cputimes->Set(String::New("user"),
  100. Number::New((uint64_t)(info[i].cpu_ticks[0]) * multiplier));
  101. cputimes->Set(String::New("nice"),
  102. Number::New((uint64_t)(info[i].cpu_ticks[3]) * multiplier));
  103. cputimes->Set(String::New("sys"),
  104. Number::New((uint64_t)(info[i].cpu_ticks[1]) * multiplier));
  105. cputimes->Set(String::New("idle"),
  106. Number::New((uint64_t)(info[i].cpu_ticks[2]) * multiplier));
  107. cputimes->Set(String::New("irq"), Number::New(0));
  108. cpuinfo->Set(String::New("model"), String::New(model));
  109. cpuinfo->Set(String::New("speed"), Number::New(cpuspeed/1000000));
  110. cpuinfo->Set(String::New("times"), cputimes);
  111. (*cpus)->Set(i, cpuinfo);
  112. }
  113. vm_deallocate(mach_task_self(), (vm_address_t)info, count);
  114. return 0;
  115. }
  116. double Platform::GetUptimeImpl() {
  117. time_t now;
  118. struct timeval info;
  119. size_t size = sizeof(info);
  120. static int which[] = {CTL_KERN, KERN_BOOTTIME};
  121. if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
  122. return -1;
  123. }
  124. now = time(NULL);
  125. return static_cast<double>(now - info.tv_sec);
  126. }
  127. v8::Handle<v8::Value> Platform::GetInterfaceAddresses() {
  128. HandleScope scope;
  129. struct ::ifaddrs *addrs, *ent;
  130. struct ::sockaddr_in *in4;
  131. struct ::sockaddr_in6 *in6;
  132. char ip[INET6_ADDRSTRLEN];
  133. Local<Object> ret, o;
  134. Local<String> name, ipaddr, family;
  135. Local<Array> ifarr;
  136. if (getifaddrs(&addrs) != 0) {
  137. return ThrowException(ErrnoException(errno, "getifaddrs"));
  138. }
  139. ret = Object::New();
  140. for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
  141. bzero(&ip, sizeof (ip));
  142. if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
  143. continue;
  144. }
  145. if (ent->ifa_addr == NULL) {
  146. continue;
  147. }
  148. /*
  149. * On Mac OS X getifaddrs returns information related to Mac Addresses for
  150. * various devices, such as firewire, etc. These are not relevant here.
  151. */
  152. if (ent->ifa_addr->sa_family == AF_LINK)
  153. continue;
  154. name = String::New(ent->ifa_name);
  155. if (ret->Has(name)) {
  156. ifarr = Local<Array>::Cast(ret->Get(name));
  157. } else {
  158. ifarr = Array::New();
  159. ret->Set(name, ifarr);
  160. }
  161. if (ent->ifa_addr->sa_family == AF_INET6) {
  162. in6 = (struct sockaddr_in6 *)ent->ifa_addr;
  163. inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN);
  164. family = String::New("IPv6");
  165. } else if (ent->ifa_addr->sa_family == AF_INET) {
  166. in4 = (struct sockaddr_in *)ent->ifa_addr;
  167. inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN);
  168. family = String::New("IPv4");
  169. } else {
  170. (void) strlcpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
  171. family = String::New("<unknown>");
  172. }
  173. o = Object::New();
  174. o->Set(String::New("address"), String::New(ip));
  175. o->Set(String::New("family"), family);
  176. o->Set(String::New("internal"), ent->ifa_flags & IFF_LOOPBACK ?
  177. True() : False());
  178. ifarr->Set(ifarr->Length(), o);
  179. }
  180. freeifaddrs(addrs);
  181. return scope.Close(ret);
  182. }
  183. } // namespace node