diff --git a/node.gyp b/node.gyp index 60f3617457..d519324c1b 100644 --- a/node.gyp +++ b/node.gyp @@ -109,7 +109,6 @@ 'src/node_string.h', 'src/node_version.h', 'src/pipe_wrap.h', - 'src/platform.h', 'src/req_wrap.h', 'src/stream_wrap.h', 'src/v8_typed_array.h', @@ -152,9 +151,6 @@ [ 'OS=="win"', { 'sources': [ - 'src/platform_win32.cc', - # headers to make for a more pleasant IDE experience - 'src/platform_win32.h', 'tools/msvs/res/node.rc', ], 'defines': [ @@ -172,25 +168,21 @@ ] }], [ 'OS=="mac"', { - 'sources': [ 'src/platform_darwin.cc' ], 'libraries': [ '-framework Carbon' ], }], [ 'OS=="linux"', { - 'sources': [ 'src/platform_linux.cc' ], 'libraries': [ '-ldl', '-lutil' # needed for openpty ], }], [ 'OS=="freebsd"', { - 'sources': [ 'src/platform_freebsd.cc' ], 'libraries': [ '-lutil', '-lkvm', ], }], [ 'OS=="solaris"', { - 'sources': [ 'src/platform_sunos.cc' ], 'libraries': [ '-lkstat', ], diff --git a/src/node.cc b/src/node.cc index 26936f05d6..a73693d934 100644 --- a/src/node.cc +++ b/src/node.cc @@ -56,16 +56,11 @@ typedef int mode_t; #include #include -#if defined(__MINGW32__) || defined(_MSC_VER) -# include /* winapi_perror() */ -#endif - #ifdef __POSIX__ # include /* getpwnam() */ # include /* getgrnam() */ #endif -#include "platform.h" #include #ifdef __POSIX__ # include @@ -137,7 +132,7 @@ extern char **environ; #define module_load_list NODE_VAR(module_load_list) #define node_isolate NODE_VAR(node_isolate) #define debugger_running NODE_VAR(debugger_running) - +#define prog_start_time NODE_VAR(prog_start_time) namespace node { @@ -854,6 +849,30 @@ Local UVException(int errorno, #ifdef _WIN32 +// Does about the same as strerror(), +// but supports all windows error messages +static const char *winapi_strerror(const int errorno) { + char *errmsg = NULL; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL); + + if (errmsg) { + // Remove trailing newlines + for (int i = strlen(errmsg) - 1; + i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) { + errmsg[i] = '\0'; + } + + return errmsg; + } else { + // FormatMessage failed + return "Unknown error"; + } +} + + Local WinapiErrnoException(int errorno, const char* syscall, const char* msg, @@ -1485,17 +1504,19 @@ static void CheckStatus(uv_timer_t* watcher, int status) { } } + static Handle Uptime(const Arguments& args) { HandleScope scope; assert(args.Length() == 0); + double uptime; - double uptime = Platform::GetUptime(true); + uv_err_t err = uv_uptime(&uptime); - if (uptime < 0) { + if (err.code != UV_OK) { return Undefined(); } - return scope.Close(Number::New(uptime)); + return scope.Close(Number::New(uptime - prog_start_time)); } @@ -1537,10 +1558,10 @@ v8::Handle MemoryUsage(const v8::Arguments& args) { size_t rss; - int r = Platform::GetMemory(&rss); + uv_err_t err = uv_resident_set_memory(&rss); - if (r != 0) { - return ThrowException(Exception::Error(String::New(strerror(errno)))); + if (err.code != UV_OK) { + return ThrowException(UVException(err.code, "uv_resident_set_memory")); } Local info = Object::New(); @@ -1829,9 +1850,9 @@ static Handle Binding(const Arguments& args) { static Handle ProcessTitleGetter(Local property, const AccessorInfo& info) { HandleScope scope; - int len; - const char *s = Platform::GetProcessTitle(&len); - return scope.Close(s ? String::New(s, len) : String::Empty()); + char buffer[512]; + uv_get_process_title(buffer, sizeof(buffer)); + return scope.Close(String::New(buffer)); } @@ -1840,7 +1861,8 @@ static void ProcessTitleSetter(Local property, const AccessorInfo& info) { HandleScope scope; String::Utf8Value title(value->ToString()); - Platform::SetProcessTitle(*title); + // TODO: protect with a lock + uv_set_process_title(*title); } @@ -2490,8 +2512,11 @@ static Handle DebugProcess(const Arguments& args) { char** Init(int argc, char *argv[]) { + // Initialize prog_start_time to get relative uptime. + uv_uptime(&prog_start_time); + // Hack aroung with the argv pointer. Used for process.title = "blah". - argv = node::Platform::SetupArgs(argc, argv); + argv = uv_setup_args(argc, argv); // Parse a few arguments which are specific to Node. node::ParseArgs(argc, argv); diff --git a/src/node_buffer.cc b/src/node_buffer.cc index c5885bb725..71e7ff36cf 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -29,10 +29,6 @@ #include // malloc, free #include // memcpy -#ifdef __MINGW32__ -# include "platform.h" -#endif - #ifdef __POSIX__ # include // htons, htonl #endif diff --git a/src/node_constants.cc b/src/node_constants.cc index e924f9ed14..25ad02f8f9 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -32,10 +32,6 @@ #include #include -#if defined(__MINGW32__) || defined(_MSC_VER) -# include -#endif - #if HAVE_OPENSSL # include #endif diff --git a/src/node_file.cc b/src/node_file.cc index f3fd5f3fd1..7c46f3dd78 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -37,7 +37,6 @@ #if defined(__MINGW32__) || defined(_MSC_VER) # include -# include #endif diff --git a/src/node_os.cc b/src/node_os.cc index 287467531d..b854961132 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -22,7 +22,6 @@ #include #include -#include "platform.h" #include @@ -31,8 +30,6 @@ #ifdef __MINGW32__ # include - -# include #endif #ifdef __POSIX__ @@ -105,13 +102,39 @@ static Handle GetOSRelease(const Arguments& args) { static Handle GetCPUInfo(const Arguments& args) { HandleScope scope; - Local cpus; - int r = Platform::GetCPUInfo(&cpus); + uv_cpu_info_t* cpu_infos; + int count, i; - if (r < 0) { + uv_err_t err = uv_cpu_info(&cpu_infos, &count); + + if (err.code != UV_OK) { return Undefined(); } + Local cpus = Array::New(); + + for (i = 0; i < count; i++) { + Local times_info = Object::New(); + times_info->Set(String::New("user"), + Integer::New(cpu_infos[i].cpu_times.user)); + times_info->Set(String::New("nice"), + Integer::New(cpu_infos[i].cpu_times.nice)); + times_info->Set(String::New("sys"), + Integer::New(cpu_infos[i].cpu_times.sys)); + times_info->Set(String::New("idle"), + Integer::New(cpu_infos[i].cpu_times.idle)); + times_info->Set(String::New("irq"), + Integer::New(cpu_infos[i].cpu_times.irq)); + + Local cpu_info = Object::New(); + cpu_info->Set(String::New("model"), String::New(cpu_infos[i].model)); + cpu_info->Set(String::New("speed"), Integer::New(cpu_infos[i].speed)); + cpu_info->Set(String::New("times"), times_info); + (*cpus)->Set(i,cpu_info); + } + + uv_free_cpu_info(cpu_infos, count); + return scope.Close(cpus); } @@ -139,9 +162,11 @@ static Handle GetTotalMemory(const Arguments& args) { static Handle GetUptime(const Arguments& args) { HandleScope scope; - double uptime = Platform::GetUptime(); + double uptime; - if (uptime < 0) { + uv_err_t err = uv_uptime(&uptime); + + if (err.code != UV_OK) { return Undefined(); } @@ -163,7 +188,54 @@ static Handle GetLoadAvg(const Arguments& args) { static Handle GetInterfaceAddresses(const Arguments& args) { - return Platform::GetInterfaceAddresses(); + HandleScope scope; + uv_interface_address_t* interfaces; + int count, i; + char ip[INET6_ADDRSTRLEN]; + Local ret, o; + Local name, family; + Local ifarr; + + uv_err_t err = uv_interface_addresses(&interfaces, &count); + + if (err.code != UV_OK) { + return Undefined(); + } + + ret = Object::New(); + + for (i = 0; i < count; i++) { + name = String::New(interfaces[i].name); + if (ret->Has(name)) { + ifarr = Local::Cast(ret->Get(name)); + } else { + ifarr = Array::New(); + ret->Set(name, ifarr); + } + + if (interfaces[i].address.address4.sin_family == AF_INET) { + uv_ip4_name(&interfaces[i].address.address4,ip, sizeof(ip)); + family = String::New("IPv4"); + } else if (interfaces[i].address.address4.sin_family == AF_INET6) { + uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip)); + family = String::New("IPv6"); + } else { + strncpy(ip, "", INET6_ADDRSTRLEN); + family = String::New(""); + } + + o = Object::New(); + o->Set(String::New("address"), String::New(ip)); + o->Set(String::New("family"), family); + o->Set(String::New("internal"), interfaces[i].is_internal ? + True() : False()); + + ifarr->Set(ifarr->Length(), o); + } + + uv_free_interface_addresses(interfaces, count); + + return scope.Close(ret); } diff --git a/src/node_vars.h b/src/node_vars.h index e9fc3cf637..9b2dd8e8bc 100644 --- a/src/node_vars.h +++ b/src/node_vars.h @@ -70,8 +70,7 @@ struct globals { v8::Persistent module_load_list; v8::Isolate* node_isolate; volatile bool debugger_running; - - + double prog_start_time; // stream_wrap.cc size_t slab_used; @@ -176,13 +175,6 @@ struct globals { v8::Persistent write_sym; v8::Persistent buffer_constructor_template; - // platform*.cc - char* process_title; - struct { - char *str; - size_t len; - } linux_process_title; - // node_signal_watcher.cc v8::Persistent callback_symbol; v8::Persistent signal_watcher_constructor_template; diff --git a/src/platform.h b/src/platform.h deleted file mode 100644 index e89ebfaa6a..0000000000 --- a/src/platform.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef NODE_PLATFORM_H_ -#define NODE_PLATFORM_H_ - -#include - -namespace node { - -class Platform { - public: - static char** SetupArgs(int argc, char *argv[]); - static void SetProcessTitle(char *title); - static const char* GetProcessTitle(int *len); - - static int GetMemory(size_t *rss); - static int GetCPUInfo(v8::Local *cpus); - static double GetUptime(bool adjusted = false) - { - return adjusted ? GetUptimeImpl() - prog_start_time : GetUptimeImpl(); - } - static v8::Handle GetInterfaceAddresses(); - private: - static double GetUptimeImpl(); - static double prog_start_time; -}; - - -} // namespace node -#endif // NODE_PLATFORM_H_ diff --git a/src/platform_darwin.cc b/src/platform_darwin.cc deleted file mode 100644 index 391762cd5d..0000000000 --- a/src/platform_darwin.cc +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "node.h" -#include "platform.h" - -#include - -#include -#include -#include -#include /* PATH_MAX */ - -#include // sysconf -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#define process_title NODE_VAR(process_title) - - -namespace node { - -using namespace v8; - -double Platform::prog_start_time = Platform::GetUptime(); - -char** Platform::SetupArgs(int argc, char *argv[]) { - process_title = argc ? strdup(argv[0]) : NULL; - return argv; -} - - -// Platform::SetProcessTitle implemented in platform_darwin_proctitle.cc -} // namespace node -#include "platform_darwin_proctitle.cc" -namespace node { - - -const char* Platform::GetProcessTitle(int *len) { - if (process_title) { - *len = strlen(process_title); - return process_title; - } - *len = 0; - return NULL; -} - -// Researched by Tim Becker and Michael Knight -// http://blog.kuriositaet.de/?p=257 -int Platform::GetMemory(size_t *rss) { - struct task_basic_info t_info; - mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; - - int r = task_info(mach_task_self(), - TASK_BASIC_INFO, - (task_info_t)&t_info, - &t_info_count); - - if (r != KERN_SUCCESS) return -1; - - *rss = t_info.resident_size; - - return 0; -} - - -int Platform::GetCPUInfo(Local *cpus) { - Local cpuinfo; - Local cputimes; - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks); - char model[512]; - uint64_t cpuspeed; - size_t size; - - size = sizeof(model); - if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) { - return -1; - } - size = sizeof(cpuspeed); - if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0) < 0) { - return -1; - } - - natural_t numcpus; - mach_msg_type_number_t count; - processor_cpu_load_info_data_t *info; - if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus, - reinterpret_cast(&info), - &count) != KERN_SUCCESS) { - return -1; - } - *cpus = Array::New(numcpus); - for (unsigned int i = 0; i < numcpus; i++) { - cpuinfo = Object::New(); - cputimes = Object::New(); - cputimes->Set(String::New("user"), - Number::New((uint64_t)(info[i].cpu_ticks[0]) * multiplier)); - cputimes->Set(String::New("nice"), - Number::New((uint64_t)(info[i].cpu_ticks[3]) * multiplier)); - cputimes->Set(String::New("sys"), - Number::New((uint64_t)(info[i].cpu_ticks[1]) * multiplier)); - cputimes->Set(String::New("idle"), - Number::New((uint64_t)(info[i].cpu_ticks[2]) * multiplier)); - cputimes->Set(String::New("irq"), Number::New(0)); - - cpuinfo->Set(String::New("model"), String::New(model)); - cpuinfo->Set(String::New("speed"), Number::New(cpuspeed/1000000)); - - cpuinfo->Set(String::New("times"), cputimes); - (*cpus)->Set(i, cpuinfo); - } - vm_deallocate(mach_task_self(), (vm_address_t)info, count); - - return 0; -} - -double Platform::GetUptimeImpl() { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { - return -1; - } - now = time(NULL); - - return static_cast(now - info.tv_sec); -} - - -v8::Handle Platform::GetInterfaceAddresses() { - HandleScope scope; - struct ::ifaddrs *addrs, *ent; - struct ::sockaddr_in *in4; - struct ::sockaddr_in6 *in6; - char ip[INET6_ADDRSTRLEN]; - Local ret, o; - Local name, ipaddr, family; - Local ifarr; - - if (getifaddrs(&addrs) != 0) { - return ThrowException(ErrnoException(errno, "getifaddrs")); - } - - ret = Object::New(); - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - bzero(&ip, sizeof (ip)); - if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) { - continue; - } - - if (ent->ifa_addr == NULL) { - continue; - } - - /* - * On Mac OS X getifaddrs returns information related to Mac Addresses for - * various devices, such as firewire, etc. These are not relevant here. - */ - if (ent->ifa_addr->sa_family == AF_LINK) - continue; - - name = String::New(ent->ifa_name); - if (ret->Has(name)) { - ifarr = Local::Cast(ret->Get(name)); - } else { - ifarr = Array::New(); - ret->Set(name, ifarr); - } - - if (ent->ifa_addr->sa_family == AF_INET6) { - in6 = (struct sockaddr_in6 *)ent->ifa_addr; - inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN); - family = String::New("IPv6"); - } else if (ent->ifa_addr->sa_family == AF_INET) { - in4 = (struct sockaddr_in *)ent->ifa_addr; - inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN); - family = String::New("IPv4"); - } else { - (void) strlcpy(ip, "", INET6_ADDRSTRLEN); - family = String::New(""); - } - - o = Object::New(); - o->Set(String::New("address"), String::New(ip)); - o->Set(String::New("family"), family); - o->Set(String::New("internal"), ent->ifa_flags & IFF_LOOPBACK ? - True() : False()); - - ifarr->Set(ifarr->Length(), o); - - } - - freeifaddrs(addrs); - - return scope.Close(ret); -} - -} // namespace node diff --git a/src/platform_darwin_proctitle.cc b/src/platform_darwin_proctitle.cc deleted file mode 100644 index e6a1ddd371..0000000000 --- a/src/platform_darwin_proctitle.cc +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This code emanates from the Chromium project: -// http://src.chromium.org/viewvc/chrome/trunk/src/base/mac_util.mm - -#include -#include // Oh noes! See discussion blow at GetCurrentProcess -#ifndef NDEBUG - #include -#endif - -namespace node { - -void Platform::SetProcessTitle(char *title) { - static int symbol_lookup_status = 0; // 1=ok, 2=unavailable - if (symbol_lookup_status == 2) { - // feature is unavailable - return; - } - - if (process_title) free(process_title); - process_title = strdup(title); - - // Warning: here be dragons! This is SPI reverse-engineered from WebKit's - // plugin host, and could break at any time (although realistically it's only - // likely to break in a new major release). - // When 10.7 is available, check that this still works, and update this - // comment for 10.8. - - // Private CFType used in these LaunchServices calls. - typedef CFTypeRef PrivateLSASN; - typedef PrivateLSASN (*LSGetCurrentApplicationASNType)(); - typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN, - CFStringRef, - CFStringRef, - CFDictionaryRef*); - - static LSGetCurrentApplicationASNType ls_get_current_application_asn_func = - NULL; - static LSSetApplicationInformationItemType - ls_set_application_information_item_func = NULL; - static CFStringRef ls_display_name_key = NULL; - if (!symbol_lookup_status) { - CFBundleRef launch_services_bundle = - CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices")); - if (!launch_services_bundle) { -#ifndef NDEBUG - warnx("failed to look up LaunchServices bundle"); -#endif - symbol_lookup_status = 2; - return; - } - - ls_get_current_application_asn_func = - reinterpret_cast( - CFBundleGetFunctionPointerForName( - launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN"))); - if (!ls_get_current_application_asn_func) { -#ifndef NDEBUG - warnx("could not find _LSGetCurrentApplicationASN"); -#endif - symbol_lookup_status = 2; - return; - } - - ls_set_application_information_item_func = - reinterpret_cast( - CFBundleGetFunctionPointerForName( - launch_services_bundle, - CFSTR("_LSSetApplicationInformationItem"))); - if (!ls_set_application_information_item_func) { -#ifndef NDEBUG - warnx("Could not find _LSSetApplicationInformationItem"); -#endif - symbol_lookup_status = 2; - return; - } - - const CFStringRef* key_pointer = reinterpret_cast( - CFBundleGetDataPointerForName(launch_services_bundle, - CFSTR("_kLSDisplayNameKey"))); - ls_display_name_key = key_pointer ? *key_pointer : NULL; - if (!ls_display_name_key) { -#ifndef NDEBUG - warnx("Could not find _kLSDisplayNameKey"); -#endif - symbol_lookup_status = 2; - return; - } - - // Internally, this call relies on the Mach ports that are started up by the - // Carbon Process Manager. In debug builds this usually happens due to how - // the logging layers are started up; but in release, it isn't started in as - // much of a defined order. So if the symbols had to be loaded, go ahead - // and force a call to make sure the manager has been initialized and hence - // the ports are opened. - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - symbol_lookup_status = 1; // 1=ok - } - - PrivateLSASN asn = ls_get_current_application_asn_func(); - // Constant used by WebKit; what exactly it means is unknown. - const int magic_session_constant = -2; - CFStringRef process_name = - CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8); - OSErr err = - ls_set_application_information_item_func(magic_session_constant, asn, - ls_display_name_key, - process_name, - NULL /* optional out param */); -#ifndef NDEBUG - if (err) { - warnx("Call LSSetApplicationInformationItem failed"); - } -#endif -} - -} // namespace node diff --git a/src/platform_freebsd.cc b/src/platform_freebsd.cc deleted file mode 100644 index 77934274ac..0000000000 --- a/src/platform_freebsd.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "node.h" -#include "platform.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#define process_title NODE_VAR(process_title) - - -namespace node { - -using namespace v8; - -double Platform::prog_start_time = Platform::GetUptime(); - -char** Platform::SetupArgs(int argc, char *argv[]) { - process_title = argc ? strdup(argv[0]) : NULL; - return argv; -} - - -void Platform::SetProcessTitle(char *title) { - if (process_title) free(process_title); - process_title = strdup(title); - setproctitle(title); -} - -const char* Platform::GetProcessTitle(int *len) { - if (process_title) { - *len = strlen(process_title); - return process_title; - } - *len = 0; - return NULL; -} - -int Platform::GetMemory(size_t *rss) { - kvm_t *kd = NULL; - struct kinfo_proc *kinfo = NULL; - pid_t pid; - int nprocs; - size_t page_size = getpagesize(); - - pid = getpid(); - - kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); - if (kd == NULL) goto error; - - kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs); - if (kinfo == NULL) goto error; - - *rss = kinfo->ki_rssize * page_size; - - kvm_close(kd); - - return 0; - -error: - if (kd) kvm_close(kd); - return -1; -} - - -int Platform::GetCPUInfo(Local *cpus) { - Local cpuinfo; - Local cputimes; - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus, - cur = 0; - char model[512]; - int numcpus; - size_t size; - - size = sizeof(model); - if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) { - return -1; - } - size = sizeof(numcpus); - if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0) < 0) { - return -1; - } - - *cpus = Array::New(numcpus); - - size = sizeof(cpuspeed); - if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0) < 0) { - return -1; - } - // kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu - size = sizeof(maxcpus); - if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) { - return -1; - } - size = maxcpus * CPUSTATES * sizeof(long); - long cp_times[size]; - if (sysctlbyname("kern.cp_times", &cp_times, &size, NULL, 0) < 0) { - return -1; - } - for (int i = 0; i < numcpus; i++) { - cpuinfo = Object::New(); - cputimes = Object::New(); - cputimes->Set(String::New("user"), - Number::New((uint64_t)(cp_times[CP_USER+cur]) * multiplier)); - cputimes->Set(String::New("nice"), - Number::New((uint64_t)(cp_times[CP_NICE+cur]) * multiplier)); - cputimes->Set(String::New("sys"), - Number::New((uint64_t)(cp_times[CP_SYS+cur]) * multiplier)); - cputimes->Set(String::New("idle"), - Number::New((uint64_t)(cp_times[CP_IDLE+cur]) * multiplier)); - cputimes->Set(String::New("irq"), - Number::New((uint64_t)(cp_times[CP_INTR+cur]) * multiplier)); - - cpuinfo->Set(String::New("model"), String::New(model)); - cpuinfo->Set(String::New("speed"), Number::New(cpuspeed)); - - cpuinfo->Set(String::New("times"), cputimes); - (*cpus)->Set(i, cpuinfo); - cur+=CPUSTATES; - } - - return 0; -} - -double Platform::GetUptimeImpl() { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { - return -1; - } - now = time(NULL); - - return static_cast(now - info.tv_sec); -} - - -Handle Platform::GetInterfaceAddresses() { - HandleScope scope; - return scope.Close(Object::New()); -} - -} // namespace node diff --git a/src/platform_linux.cc b/src/platform_linux.cc deleted file mode 100644 index a64251e9fb..0000000000 --- a/src/platform_linux.cc +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "node.h" -#include "platform.h" - -#include - -#include // for MAXPATHLEN -#include // getpagesize, sysconf -#include // sscanf, snprintf - -/* SetProcessTitle */ -#include -#include -#include // free -#include // strdup - -/* GetInterfaceAddresses */ -#include -#include -#include -#include -#include -#include - -#include - -#ifndef CLOCK_MONOTONIC -# include -#endif - -#include -#define linux_process_title NODE_VAR(linux_process_title) -#define getbuf NODE_VAR(getbuf) - -extern char **environ; - -namespace node { - -using namespace v8; - -double Platform::prog_start_time = Platform::GetUptime(); - - -char** Platform::SetupArgs(int argc, char *argv[]) { - char **new_argv; - char **new_env; - size_t size; - int envc; - char *s; - int i; - - for (envc = 0; environ[envc]; envc++); - - s = envc ? environ[envc - 1] : argv[argc - 1]; - - linux_process_title.str = argv[0]; - linux_process_title.len = s + strlen(s) + 1 - argv[0]; - - size = linux_process_title.len; - size += (argc + 1) * sizeof(char **); - size += (envc + 1) * sizeof(char **); - - if ((s = (char *) malloc(size)) == NULL) { - linux_process_title.str = NULL; - linux_process_title.len = 0; - return argv; - } - - new_argv = (char **) s; - new_env = new_argv + argc + 1; - s = (char *) (new_env + envc + 1); - memcpy(s, linux_process_title.str, linux_process_title.len); - - for (i = 0; i < argc; i++) - new_argv[i] = s + (argv[i] - argv[0]); - new_argv[argc] = NULL; - - s += environ[0] - argv[0]; - - for (i = 0; i < envc; i++) - new_env[i] = s + (environ[i] - environ[0]); - new_env[envc] = NULL; - - environ = new_env; - return new_argv; -} - - -void Platform::SetProcessTitle(char *title) { - /* No need to terminate, last char is always '\0'. */ - if (linux_process_title.len) - strncpy(linux_process_title.str, title, linux_process_title.len - 1); -} - - -const char* Platform::GetProcessTitle(int *len) { - if (linux_process_title.str) { - *len = strlen(linux_process_title.str); - return linux_process_title.str; - } - else { - *len = 0; - return NULL; - } -} - - -int Platform::GetMemory(size_t *rss) { - FILE *f = fopen("/proc/self/stat", "r"); - if (!f) return -1; - - int itmp; - char ctmp; - size_t page_size = getpagesize(); - char *cbuf; - bool foundExeEnd; - - /* PID */ - if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Exec file */ - cbuf = getbuf; - foundExeEnd = false; - if (fscanf (f, "%c", cbuf++) == 0) goto error; // ( - while (1) { - if (fscanf(f, "%c", cbuf) == 0) goto error; - if (*cbuf == ')') { - foundExeEnd = true; - } else if (foundExeEnd && *cbuf == ' ') { - *cbuf = 0; - break; - } - - cbuf++; - } - /* State */ - if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */ - /* Parent process */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Process group */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Session id */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* TTY */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* TTY owner process group */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Flags */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Minor faults (no memory page) */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Minor faults, children */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Major faults (memory page faults) */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Major faults, children */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* utime */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* stime */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* utime, children */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* stime, children */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* jiffies remaining in current time slice */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* 'nice' value */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* jiffies until next timeout */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* jiffies until next SIGALRM */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* start time (jiffies since system boot) */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - - /* Virtual memory size */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - - /* Resident set size */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - *rss = (size_t) itmp * page_size; - - /* rlim */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Start of text */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* End of text */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - /* Start of stack */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - - fclose (f); - - return 0; - -error: - fclose (f); - return -1; -} - - -int Platform::GetCPUInfo(Local *cpus) { - HandleScope scope; - Local cpuinfo; - Local cputimes; - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks), cpuspeed; - int numcpus = 0, i = 0; - unsigned long long ticks_user, ticks_sys, ticks_idle, ticks_nice, ticks_intr; - char line[512], speedPath[256], model[512]; - FILE *fpStat = fopen("/proc/stat", "r"); - FILE *fpModel = fopen("/proc/cpuinfo", "r"); - FILE *fpSpeed; - - if (fpModel) { - while (fgets(line, 511, fpModel) != NULL) { - if (strncmp(line, "model name", 10) == 0) { - numcpus++; - if (numcpus == 1) { - char *p = strchr(line, ':') + 2; - strcpy(model, p); - model[strlen(model)-1] = 0; - } - } else if (strncmp(line, "cpu MHz", 7) == 0) { - if (numcpus == 1) { - sscanf(line, "%*s %*s : %u", &cpuspeed); - } - } - } - fclose(fpModel); - } - - *cpus = Array::New(numcpus); - - if (fpStat) { - while (fgets(line, 511, fpStat) != NULL) { - if (strncmp(line, "cpu ", 4) == 0) { - continue; - } else if (strncmp(line, "cpu", 3) != 0) { - break; - } - - sscanf(line, "%*s %llu %llu %llu %llu %*llu %llu", - &ticks_user, &ticks_nice, &ticks_sys, &ticks_idle, &ticks_intr); - snprintf(speedPath, sizeof(speedPath), - "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_max_freq", i); - - fpSpeed = fopen(speedPath, "r"); - - if (fpSpeed) { - if (fgets(line, 511, fpSpeed) != NULL) { - sscanf(line, "%u", &cpuspeed); - cpuspeed /= 1000; - } - fclose(fpSpeed); - } - - cpuinfo = Object::New(); - cputimes = Object::New(); - cputimes->Set(String::New("user"), Number::New(ticks_user * multiplier)); - cputimes->Set(String::New("nice"), Number::New(ticks_nice * multiplier)); - cputimes->Set(String::New("sys"), Number::New(ticks_sys * multiplier)); - cputimes->Set(String::New("idle"), Number::New(ticks_idle * multiplier)); - cputimes->Set(String::New("irq"), Number::New(ticks_intr * multiplier)); - - cpuinfo->Set(String::New("model"), String::New(model)); - cpuinfo->Set(String::New("speed"), Number::New(cpuspeed)); - - cpuinfo->Set(String::New("times"), cputimes); - (*cpus)->Set(i++, cpuinfo); - } - fclose(fpStat); - } - - return 0; -} - -double Platform::GetUptimeImpl() { -#ifdef CLOCK_MONOTONIC - struct timespec now; - if (0 == clock_gettime(CLOCK_MONOTONIC, &now)) { - double uptime = now.tv_sec; - uptime += (double)now.tv_nsec / 1000000000.0; - return uptime; - } - return -1; -#else - struct sysinfo info; - if (sysinfo(&info) < 0) { - return -1; - } - return static_cast(info.uptime); -#endif -} - - -bool IsInternal(struct ifaddrs* addr) { - return addr->ifa_flags & IFF_UP && - addr->ifa_flags & IFF_RUNNING && - addr->ifa_flags & IFF_LOOPBACK; -} - - -Handle Platform::GetInterfaceAddresses() { - HandleScope scope; - struct ::ifaddrs *addrs, *ent; - struct ::sockaddr_in *in4; - struct ::sockaddr_in6 *in6; - char ip[INET6_ADDRSTRLEN]; - Local ret, o; - Local name, ipaddr, family; - Local ifarr; - - if (getifaddrs(&addrs) != 0) { - return ThrowException(ErrnoException(errno, "getifaddrs")); - } - - ret = Object::New(); - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - bzero(&ip, sizeof (ip)); - if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) { - continue; - } - - if (ent->ifa_addr == NULL) { - continue; - } - - /* - * On Linux getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information. - */ - if (ent->ifa_addr->sa_family == PF_PACKET) - continue; - - name = String::New(ent->ifa_name); - if (ret->Has(name)) { - ifarr = Local::Cast(ret->Get(name)); - } else { - ifarr = Array::New(); - ret->Set(name, ifarr); - } - - if (ent->ifa_addr->sa_family == AF_INET6) { - in6 = (struct sockaddr_in6 *)ent->ifa_addr; - inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN); - family = String::New("IPv6"); - } else if (ent->ifa_addr->sa_family == AF_INET) { - in4 = (struct sockaddr_in *)ent->ifa_addr; - inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN); - family = String::New("IPv4"); - } else { - (void) strncpy(ip, "", INET6_ADDRSTRLEN); - family = String::New(""); - } - - o = Object::New(); - o->Set(String::New("address"), String::New(ip)); - o->Set(String::New("family"), family); - o->Set(String::New("internal"), ent->ifa_flags & IFF_LOOPBACK ? - True() : False()); - - ifarr->Set(ifarr->Length(), o); - - } - - freeifaddrs(addrs); - - return scope.Close(ret); -} - - -} // namespace node diff --git a/src/platform_none.cc b/src/platform_none.cc deleted file mode 100644 index ea6125719b..0000000000 --- a/src/platform_none.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "node.h" -#include "platform.h" - - -namespace node { - - -char** OS::SetupArgs(int argc, char *argv[]) { - return argv; -} - - -void OS::SetProcessTitle(char *title) { - ; -} - - -const char* OS::GetProcessTitle(int *len) { - *len = 0; - return NULL; -} - - -int OS::GetMemory(size_t *rss) { - // Not implemented - *rss = 0; - return 0; -} - - -} // namespace node diff --git a/src/platform_openbsd.cc b/src/platform_openbsd.cc deleted file mode 100644 index ce140bb7b5..0000000000 --- a/src/platform_openbsd.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "node.h" -#include "platform.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#define process_title NODE_VAR(process_title) - -namespace node { - -using namespace v8; - -double Platform::prog_start_time = Platform::GetUptime(); - -char** Platform::SetupArgs(int argc, char *argv[]) { - process_title = argc ? strdup(argv[0]) : NULL; - return argv; -} - - -void Platform::SetProcessTitle(char *title) { - if (process_title) free(process_title); - process_title = strdup(title); - setproctitle(title); -} - -const char* Platform::GetProcessTitle(int *len) { - if (process_title) { - *len = strlen(process_title); - return process_title; - } - *len = 0; - return NULL; -} - -int Platform::GetMemory(size_t *rss) { - kvm_t *kd = NULL; - struct kinfo_proc2 *kinfo = NULL; - pid_t pid; - int nprocs, max_size = sizeof(struct kinfo_proc2); - size_t page_size = getpagesize(); - - pid = getpid(); - - kd = kvm_open(NULL, _PATH_MEM, NULL, O_RDONLY, "kvm_open"); - if (kd == NULL) goto error; - - kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs); - if (kinfo == NULL) goto error; - - *rss = kinfo->p_vm_rssize * page_size; - - kvm_close(kd); - - return 0; - -error: - if (kd) kvm_close(kd); - return -1; -} - - -int Platform::GetCPUInfo(Local *cpus) { - Local cpuinfo; - Local cputimes; - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks), cpuspeed; - uint64_t info[CPUSTATES]; - char model[512]; - int numcpus = 1; - static int which[] = {CTL_HW, HW_MODEL, NULL}; - size_t size; - - size = sizeof(model); - if (sysctl(which, 2, &model, &size, NULL, 0) < 0) { - return -1; - } - which[1] = HW_NCPU; - size = sizeof(numcpus); - if (sysctl(which, 2, &numcpus, &size, NULL, 0) < 0) { - return -1; - } - - *cpus = Array::New(numcpus); - - which[1] = HW_CPUSPEED; - size = sizeof(cpuspeed); - if (sysctl(which, 2, &cpuspeed, &size, NULL, 0) < 0) { - return -1; - } - size = sizeof(info); - which[0] = CTL_KERN; - which[1] = KERN_CPTIME2; - for (int i = 0; i < numcpus; i++) { - which[2] = i; - size = sizeof(info); - if (sysctl(which, 3, &info, &size, NULL, 0) < 0) { - return -1; - } - cpuinfo = Object::New(); - cputimes = Object::New(); - cputimes->Set(String::New("user"), - Number::New((uint64_t)(info[CP_USER]) * multiplier)); - cputimes->Set(String::New("nice"), - Number::New((uint64_t)(info[CP_NICE]) * multiplier)); - cputimes->Set(String::New("sys"), - Number::New((uint64_t)(info[CP_SYS]) * multiplier)); - cputimes->Set(String::New("idle"), - Number::New((uint64_t)(info[CP_IDLE]) * multiplier)); - cputimes->Set(String::New("irq"), - Number::New((uint64_t)(info[CP_INTR]) * multiplier)); - - cpuinfo->Set(String::New("model"), String::New(model)); - cpuinfo->Set(String::New("speed"), Number::New(cpuspeed)); - - cpuinfo->Set(String::New("times"), cputimes); - (*cpus)->Set(i, cpuinfo); - } - return 0; -} - -double Platform::GetUptimeImpl() { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { - return -1; - } - now = time(NULL); - - return static_cast(now - info.tv_sec); -} - - -Handle Platform::GetInterfaceAddresses() { - HandleScope scope; - return scope.Close(Object::New()); -} - - -} // namespace node diff --git a/src/platform_sunos.cc b/src/platform_sunos.cc deleted file mode 100644 index 949e4e13f9..0000000000 --- a/src/platform_sunos.cc +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "node.h" -#include "platform.h" - - -#include /* getpagesize() */ -#include /* getexecname() */ -#include /* strncpy() */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef SUNOS_HAVE_IFADDRS -# include -#endif - - - -#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) -#define PROCFS_FILE_OFFSET_BITS_HACK 1 -#undef _FILE_OFFSET_BITS -#else -#define PROCFS_FILE_OFFSET_BITS_HACK 0 -#endif - -#include - -#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1) -#define _FILE_OFFSET_BITS 64 -#endif - - -namespace node { - -using namespace v8; - -double Platform::prog_start_time = Platform::GetUptime(); - -char** Platform::SetupArgs(int argc, char *argv[]) { - return argv; -} - - -void Platform::SetProcessTitle(char *title) { - ; -} - - -const char* Platform::GetProcessTitle(int *len) { - *len = 0; - return NULL; -} - - -int Platform::GetMemory(size_t *rss) { - pid_t pid = getpid(); - - char pidpath[1024]; - sprintf(pidpath, "/proc/%d/psinfo", pid); - - psinfo_t psinfo; - FILE *f = fopen(pidpath, "r"); - if (!f) return -1; - - if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) { - fclose (f); - return -1; - } - - /* XXX correct? */ - - *rss = (size_t) psinfo.pr_rssize * 1024; - - fclose (f); - - return 0; -} - - -static Handle data_named(kstat_named_t *knp) { - Handle val; - - switch (knp->data_type) { - case KSTAT_DATA_CHAR: - val = Number::New(knp->value.c[0]); - break; - case KSTAT_DATA_INT32: - val = Number::New(knp->value.i32); - break; - case KSTAT_DATA_UINT32: - val = Number::New(knp->value.ui32); - break; - case KSTAT_DATA_INT64: - val = Number::New(knp->value.i64); - break; - case KSTAT_DATA_UINT64: - val = Number::New(knp->value.ui64); - break; - case KSTAT_DATA_STRING: - val = String::New(KSTAT_NAMED_STR_PTR(knp)); - break; - default: - val = String::New("unrecognized data type"); - } - - return (val); -} - - -int Platform::GetCPUInfo(Local *cpus) { - HandleScope scope; - Local cpuinfo; - Local cputimes; - - int lookup_instance; - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *knp; - - if ((kc = kstat_open()) == NULL) - return -1; - - *cpus = Array::New(); - - lookup_instance = 0; - while (ksp = kstat_lookup(kc, (char *)"cpu_info", lookup_instance, NULL)){ - cpuinfo = Object::New(); - - if (kstat_read(kc, ksp, NULL) == -1) { - /* - * It is deeply annoying, but some kstats can return errors - * under otherwise routine conditions. (ACPI is one - * offender; there are surely others.) To prevent these - * fouled kstats from completely ruining our day, we assign - * an "error" member to the return value that consists of - * the strerror(). - */ - cpuinfo->Set(String::New("error"), String::New(strerror(errno))); - (*cpus)->Set(lookup_instance, cpuinfo); - } else { - knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clock_MHz"); - cpuinfo->Set(String::New("speed"), data_named(knp)); - knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"brand"); - cpuinfo->Set(String::New("model"), data_named(knp)); - (*cpus)->Set(lookup_instance, cpuinfo); - } - - lookup_instance++; - } - - lookup_instance = 0; - while (ksp = kstat_lookup(kc, (char *)"cpu", lookup_instance, (char *)"sys")){ - cpuinfo = (*cpus)->Get(lookup_instance)->ToObject(); - cputimes = Object::New(); - - if (kstat_read(kc, ksp, NULL) == -1) { - cputimes->Set(String::New("error"), String::New(strerror(errno))); - cpuinfo->Set(String::New("times"), cpuinfo); - } else { - knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_kernel"); - cputimes->Set(String::New("system"), data_named(knp)); - knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_user"); - cputimes->Set(String::New("user"), data_named(knp)); - knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_idle"); - cputimes->Set(String::New("idle"), data_named(knp)); - knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"intr"); - cputimes->Set(String::New("irq"), data_named(knp)); - - cpuinfo->Set(String::New("times"), cputimes); - } - - lookup_instance++; - } - - kstat_close(kc); - - return 0; -} - - -double Platform::GetUptimeImpl() { - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *knp; - - long hz = sysconf(_SC_CLK_TCK); - double clk_intr; - - if ((kc = kstat_open()) == NULL) - return -1; - - ksp = kstat_lookup(kc, (char *)"unix", 0, (char *)"system_misc"); - - if (kstat_read(kc, ksp, NULL) == -1) { - clk_intr = -1; - } else { - knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clk_intr"); - clk_intr = knp->value.ul / hz; - } - - kstat_close(kc); - - return clk_intr; -} - - -Handle Platform::GetInterfaceAddresses() { - HandleScope scope; - -#ifndef SUNOS_HAVE_IFADDRS - return ThrowException(Exception::Error(String::New( - "This version of sunos doesn't support getifaddrs"))); -#else - struct ::ifaddrs *addrs, *ent; - struct ::sockaddr_in *in4; - struct ::sockaddr_in6 *in6; - char ip[INET6_ADDRSTRLEN]; - Local ret, o; - Local name, ipaddr, family; - Local ifarr; - - if (getifaddrs(&addrs) != 0) { - return ThrowException(ErrnoException(errno, "getifaddrs")); - } - - ret = Object::New(); - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - bzero(&ip, sizeof (ip)); - if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) { - continue; - } - - if (ent->ifa_addr == NULL) { - continue; - } - - name = String::New(ent->ifa_name); - if (ret->Has(name)) { - ifarr = Local::Cast(ret->Get(name)); - } else { - ifarr = Array::New(); - ret->Set(name, ifarr); - } - - if (ent->ifa_addr->sa_family == AF_INET6) { - in6 = (struct sockaddr_in6 *)ent->ifa_addr; - inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN); - family = String::New("IPv6"); - } else if (ent->ifa_addr->sa_family == AF_INET) { - in4 = (struct sockaddr_in *)ent->ifa_addr; - inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN); - family = String::New("IPv4"); - } else { - (void) strlcpy(ip, "", INET6_ADDRSTRLEN); - family = String::New(""); - } - - o = Object::New(); - o->Set(String::New("address"), String::New(ip)); - o->Set(String::New("family"), family); - o->Set(String::New("internal"), ent->ifa_flags & IFF_PRIVATE || ent->ifa_flags & - IFF_LOOPBACK ? True() : False()); - - ifarr->Set(ifarr->Length(), o); - - } - - freeifaddrs(addrs); - - return scope.Close(ret); - -#endif // SUNOS_HAVE_IFADDRS -} - - -} // namespace node - diff --git a/src/platform_win32.cc b/src/platform_win32.cc deleted file mode 100644 index 11fe6dfb01..0000000000 --- a/src/platform_win32.cc +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - -#include -#include "platform.h" - -#include - -#include -#include -#if defined(__MINGW32__) -#include // for MAXPATHLEN -#include // getpagesize -#endif - -#include -#include - -#include -#define process_title NODE_VAR(process_title) - -namespace node { - -using namespace v8; - -double Platform::prog_start_time = Platform::GetUptime(); - - -// Does the about the same as strerror(), -// but supports all windows errror messages -const char *winapi_strerror(const int errorno) { - char *errmsg = NULL; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL); - - if (errmsg) { - // Remove trailing newlines - for (int i = strlen(errmsg) - 1; - i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) { - errmsg[i] = '\0'; - } - - return errmsg; - } else { - // FormatMessage failed - return "Unknown error"; - } -} - - -// Does the about the same as perror(), but for windows api functions -void winapi_perror(const char* prefix = NULL) { - DWORD errorno = GetLastError(); - const char *errmsg = NULL; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL); - - if (!errmsg) { - errmsg = "Unknown error\n"; - } - - // FormatMessage messages include a newline character - - if (prefix) { - fprintf(stderr, "%s: %s", prefix, errmsg); - } else { - fputs(errmsg, stderr); - } -} - - -char** Platform::SetupArgs(int argc, char *argv[]) { - return argv; -} - - -// Max title length; the only thing MSDN tells us about the maximum length -// of the console title is that it is smaller than 64K. However in practice -// it is much smaller, and there is no way to figure out what the exact length -// of the title is or can be, at least not on XP. To make it even more -// annoying, GetConsoleTitle failes when the buffer to be read into is bigger -// than the actual maximum length. So we make a conservative guess here; -// just don't put the novel you're writing in the title, unless the plot -// survives truncation. -#define MAX_TITLE_LENGTH 8192 - -void Platform::SetProcessTitle(char *title) { - // We need to convert _title_ to UTF-16 first, because that's what windows uses internally. - // It would be more efficient to use the UTF-16 value that we can obtain from v8, - // but it's not accessible from here. - - int length; - WCHAR *title_w; - - // Find out how big the buffer for the wide-char title must be - length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); - if (!length) { - winapi_perror("MultiByteToWideChar"); - return; - } - - // Convert to wide-char string - title_w = new WCHAR[length]; - length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length); - if (!length) { - winapi_perror("MultiByteToWideChar"); - delete title_w; - return; - }; - - // If the title must be truncated insert a \0 terminator there - if (length > MAX_TITLE_LENGTH) { - title_w[MAX_TITLE_LENGTH - 1] = *L"\0"; - } - - if (!SetConsoleTitleW(title_w)) { - winapi_perror("SetConsoleTitleW"); - } - - free(process_title); - process_title = strdup(title); - - delete title_w; -} - - -static inline char* _getProcessTitle() { - WCHAR title_w[MAX_TITLE_LENGTH]; - char *title; - int result, length; - - result = GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR)); - - if (result == 0) { - winapi_perror("GetConsoleTitleW"); - return NULL; - } - - // Find out what the size of the buffer is that we need - length = WideCharToMultiByte(CP_UTF8, 0, title_w, -1, NULL, 0, NULL, NULL); - if (!length) { - winapi_perror("WideCharToMultiByte"); - return NULL; - } - - title = (char *) malloc(length); - if (!title) { - perror("malloc"); - return NULL; - } - - // Do utf16 -> utf8 conversion here - if (!WideCharToMultiByte(CP_UTF8, 0, title_w, -1, title, length, NULL, NULL)) { - winapi_perror("WideCharToMultiByte"); - free(title); - return NULL; - } - - return title; -} - - -const char* Platform::GetProcessTitle(int *len) { - // If the process_title was never read before nor explicitly set, - // we must query it with getConsoleTitleW - if (!process_title) { - process_title = _getProcessTitle(); - } - - if (process_title) { - *len = strlen(process_title); - return process_title; - } else { - *len = 0; - return NULL; - } -} - - -int Platform::GetMemory(size_t *rss) { - - HANDLE current_process = GetCurrentProcess(); - PROCESS_MEMORY_COUNTERS pmc; - - if ( !GetProcessMemoryInfo( current_process, &pmc, sizeof(pmc)) ) - { - winapi_perror("GetProcessMemoryInfo"); - } - - *rss = pmc.WorkingSetSize; - - return 0; -} - -int Platform::GetCPUInfo(Local *cpus) { - - HandleScope scope; - *cpus = Array::New(); - - for (int i = 0; i < 32; i++) { - - char key[128] = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\"; - char processor_number[32]; - itoa(i, processor_number, 10); - strncat(key, processor_number, 2); - - HKEY processor_key = NULL; - - DWORD cpu_speed = 0; - DWORD cpu_speed_length = sizeof(cpu_speed); - - char cpu_brand[256]; - DWORD cpu_brand_length = sizeof(cpu_brand); - - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE, - &processor_key) != ERROR_SUCCESS) { - if (i == 0) { - winapi_perror("RegOpenKeyEx"); - return -1; - } - - continue; - } - - if (RegQueryValueEx(processor_key, "~MHz", NULL, NULL, - (LPBYTE)&cpu_speed, &cpu_speed_length) - != ERROR_SUCCESS) { - winapi_perror("RegQueryValueEx"); - return -1; - } - - if (RegQueryValueEx(processor_key, "ProcessorNameString", NULL, NULL, - (LPBYTE)&cpu_brand, &cpu_brand_length) - != ERROR_SUCCESS) { - winapi_perror("RegQueryValueEx"); - return -1; - } - - RegCloseKey(processor_key); - - Local times_info = Object::New(); // FIXME - find times on windows - times_info->Set(String::New("user"), Integer::New(0)); - times_info->Set(String::New("nice"), Integer::New(0)); - times_info->Set(String::New("sys"), Integer::New(0)); - times_info->Set(String::New("idle"), Integer::New(0)); - times_info->Set(String::New("irq"), Integer::New(0)); - - Local cpu_info = Object::New(); - cpu_info->Set(String::New("model"), String::New(cpu_brand)); - cpu_info->Set(String::New("speed"), Integer::New(cpu_speed)); - cpu_info->Set(String::New("times"), times_info); - (*cpus)->Set(i,cpu_info); - } - - return 0; -} - - -double Platform::GetUptimeImpl() { - return (double)GetTickCount()/1000.0; -} - -Handle Platform::GetInterfaceAddresses() { - HandleScope scope; - return scope.Close(Object::New()); -} - - -} // namespace node diff --git a/src/platform_win32.h b/src/platform_win32.h deleted file mode 100644 index 0a6a5d5bfe..0000000000 --- a/src/platform_win32.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef NODE_PLATFORM_WIN32_H_ -#define NODE_PLATFORM_WIN32_H_ - -// Require at least Windows XP SP1 -// (GetProcessId requires it) -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -#endif - -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN // implies NOCRYPT and NOGDI. -#endif - -#ifndef NOMINMAX -# define NOMINMAX -#endif - -#ifndef NOKERNEL -# define NOKERNEL -#endif - -#ifndef NOUSER -# define NOUSER -#endif - -#ifndef NOSERVICE -# define NOSERVICE -#endif - -#ifndef NOSOUND -# define NOSOUND -#endif - -#ifndef NOMCX -# define NOMCX -#endif - -#include -#include - -#if defined(_MSC_VER) -#define STDIN_FILENO 0 -#define STDOUT_FILENO 1 -#define STDERR_FILENO 2 -#endif - -namespace node { - -#define NO_IMPL_MSG(...) \ - fprintf(stderr, "Not implemented: %s\n", #__VA_ARGS__); - -const char *winapi_strerror(const int errorno); -void winapi_perror(const char* prefix); - -} - -#endif // NODE_PLATFORM_WIN32_H_ - diff --git a/test/simple/test-os.js b/test/simple/test-os.js index 4bed42eba8..92d1a264c1 100644 --- a/test/simple/test-os.js +++ b/test/simple/test-os.js @@ -72,4 +72,10 @@ switch (platform) { var expected = [{ address: '127.0.0.1', family: 'IPv4', internal: true }]; assert.deepEqual(actual, expected); break; + case 'win32': + var filter = function(e) { return e.address == '127.0.0.1'; }; + var actual = interfaces['Loopback Pseudo-Interface 1'].filter(filter); + var expected = [{ address: '127.0.0.1', family: 'IPv4', internal: true }]; + assert.deepEqual(actual, expected); + break; }