mirror of https://github.com/lukechilds/node.git
18 changed files with 130 additions and 1952 deletions
@ -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 <v8.h> |
|
||||
|
|
||||
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<v8::Array> *cpus); |
|
||||
static double GetUptime(bool adjusted = false) |
|
||||
{ |
|
||||
return adjusted ? GetUptimeImpl() - prog_start_time : GetUptimeImpl(); |
|
||||
} |
|
||||
static v8::Handle<v8::Value> GetInterfaceAddresses(); |
|
||||
private: |
|
||||
static double GetUptimeImpl(); |
|
||||
static double prog_start_time; |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
} // namespace node
|
|
||||
#endif // NODE_PLATFORM_H_
|
|
@ -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 <v8.h> |
|
||||
|
|
||||
#include <mach/task.h> |
|
||||
#include <mach/mach.h> |
|
||||
#include <mach/mach_host.h> |
|
||||
#include <limits.h> /* PATH_MAX */ |
|
||||
|
|
||||
#include <unistd.h> // sysconf |
|
||||
#include <sys/param.h> |
|
||||
#include <sys/sysctl.h> |
|
||||
#include <time.h> |
|
||||
#include <sys/socket.h> |
|
||||
#include <net/if.h> |
|
||||
#include <netinet/in.h> |
|
||||
#include <arpa/inet.h> |
|
||||
#include <ifaddrs.h> |
|
||||
|
|
||||
#include <node_vars.h> |
|
||||
#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<Array> *cpus) { |
|
||||
Local<Object> cpuinfo; |
|
||||
Local<Object> 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<processor_info_array_t*>(&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<double>(now - info.tv_sec); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
v8::Handle<v8::Value> Platform::GetInterfaceAddresses() { |
|
||||
HandleScope scope; |
|
||||
struct ::ifaddrs *addrs, *ent; |
|
||||
struct ::sockaddr_in *in4; |
|
||||
struct ::sockaddr_in6 *in6; |
|
||||
char ip[INET6_ADDRSTRLEN]; |
|
||||
Local<Object> ret, o; |
|
||||
Local<String> name, ipaddr, family; |
|
||||
Local<Array> 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<Array>::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, "<unknown sa family>", INET6_ADDRSTRLEN); |
|
||||
family = String::New("<unknown>"); |
|
||||
} |
|
||||
|
|
||||
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
|
|
@ -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 <CoreFoundation/CoreFoundation.h> |
|
||||
#include <Carbon/Carbon.h> // Oh noes! See discussion blow at GetCurrentProcess |
|
||||
#ifndef NDEBUG |
|
||||
#include <err.h> |
|
||||
#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<LSGetCurrentApplicationASNType>( |
|
||||
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<LSSetApplicationInformationItemType>( |
|
||||
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<const CFStringRef*>( |
|
||||
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
|
|
@ -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 <v8.h> |
|
||||
|
|
||||
#include <stdlib.h> |
|
||||
#include <kvm.h> |
|
||||
#include <sys/param.h> |
|
||||
#include <sys/sysctl.h> |
|
||||
#include <sys/user.h> |
|
||||
#include <sys/dkstat.h> |
|
||||
#include <vm/vm_param.h> |
|
||||
#include <string.h> |
|
||||
#include <paths.h> |
|
||||
#include <fcntl.h> |
|
||||
#include <unistd.h> |
|
||||
#include <time.h> |
|
||||
|
|
||||
#include <node_vars.h> |
|
||||
#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<Array> *cpus) { |
|
||||
Local<Object> cpuinfo; |
|
||||
Local<Object> 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<double>(now - info.tv_sec); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Handle<Value> Platform::GetInterfaceAddresses() { |
|
||||
HandleScope scope; |
|
||||
return scope.Close(Object::New()); |
|
||||
} |
|
||||
|
|
||||
} // namespace node
|
|
@ -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 <v8.h> |
|
||||
|
|
||||
#include <sys/param.h> // for MAXPATHLEN |
|
||||
#include <unistd.h> // getpagesize, sysconf |
|
||||
#include <stdio.h> // sscanf, snprintf |
|
||||
|
|
||||
/* SetProcessTitle */ |
|
||||
#include <sys/prctl.h> |
|
||||
#include <linux/prctl.h> |
|
||||
#include <stdlib.h> // free |
|
||||
#include <string.h> // strdup |
|
||||
|
|
||||
/* GetInterfaceAddresses */ |
|
||||
#include <arpa/inet.h> |
|
||||
#include <sys/types.h> |
|
||||
#include <ifaddrs.h> |
|
||||
#include <errno.h> |
|
||||
#include <sys/ioctl.h> |
|
||||
#include <net/if.h> |
|
||||
|
|
||||
#include <time.h> |
|
||||
|
|
||||
#ifndef CLOCK_MONOTONIC |
|
||||
# include <sys/sysinfo.h> |
|
||||
#endif |
|
||||
|
|
||||
#include <node_vars.h> |
|
||||
#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<Array> *cpus) { |
|
||||
HandleScope scope; |
|
||||
Local<Object> cpuinfo; |
|
||||
Local<Object> 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<double>(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<Value> Platform::GetInterfaceAddresses() { |
|
||||
HandleScope scope; |
|
||||
struct ::ifaddrs *addrs, *ent; |
|
||||
struct ::sockaddr_in *in4; |
|
||||
struct ::sockaddr_in6 *in6; |
|
||||
char ip[INET6_ADDRSTRLEN]; |
|
||||
Local<Object> ret, o; |
|
||||
Local<String> name, ipaddr, family; |
|
||||
Local<Array> 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<Array>::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, "<unknown sa family>", INET6_ADDRSTRLEN); |
|
||||
family = String::New("<unknown>"); |
|
||||
} |
|
||||
|
|
||||
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
|
|
@ -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
|
|
@ -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 <v8.h> |
|
||||
|
|
||||
#include <stdlib.h> |
|
||||
#include <kvm.h> |
|
||||
#include <sys/param.h> |
|
||||
#include <sys/sysctl.h> |
|
||||
#include <sys/user.h> |
|
||||
#include <sys/dkstat.h> |
|
||||
#include <uvm/uvm_param.h> |
|
||||
#include <string.h> |
|
||||
#include <paths.h> |
|
||||
#include <fcntl.h> |
|
||||
#include <unistd.h> |
|
||||
#include <time.h> |
|
||||
#include <stdio.h> |
|
||||
|
|
||||
#include <node_vars.h> |
|
||||
#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<Array> *cpus) { |
|
||||
Local<Object> cpuinfo; |
|
||||
Local<Object> 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<double>(now - info.tv_sec); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Handle<Value> Platform::GetInterfaceAddresses() { |
|
||||
HandleScope scope; |
|
||||
return scope.Close(Object::New()); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} // namespace node
|
|
@ -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 <unistd.h> /* getpagesize() */ |
|
||||
#include <stdlib.h> /* getexecname() */ |
|
||||
#include <strings.h> /* strncpy() */ |
|
||||
|
|
||||
#include <kstat.h> |
|
||||
#include <errno.h> |
|
||||
#include <inttypes.h> |
|
||||
#include <sys/types.h> |
|
||||
#include <sys/loadavg.h> |
|
||||
#include <sys/socket.h> |
|
||||
#include <net/if.h> |
|
||||
#include <netinet/in.h> |
|
||||
#include <arpa/inet.h> |
|
||||
|
|
||||
#ifdef SUNOS_HAVE_IFADDRS |
|
||||
# include <ifaddrs.h> |
|
||||
#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 <procfs.h> |
|
||||
|
|
||||
#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<Value> data_named(kstat_named_t *knp) { |
|
||||
Handle<Value> 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<Array> *cpus) { |
|
||||
HandleScope scope; |
|
||||
Local<Object> cpuinfo; |
|
||||
Local<Object> 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<Value> 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<Object> ret, o; |
|
||||
Local<String> name, ipaddr, family; |
|
||||
Local<Array> 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<Array>::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, "<unknown sa family>", INET6_ADDRSTRLEN); |
|
||||
family = String::New("<unknown>"); |
|
||||
} |
|
||||
|
|
||||
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
|
|
||||
|
|
@ -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 <node.h> |
|
||||
#include "platform.h" |
|
||||
|
|
||||
#include <v8.h> |
|
||||
|
|
||||
#include <errno.h> |
|
||||
#include <stdlib.h> |
|
||||
#if defined(__MINGW32__) |
|
||||
#include <sys/param.h> // for MAXPATHLEN |
|
||||
#include <unistd.h> // getpagesize |
|
||||
#endif |
|
||||
|
|
||||
#include <platform_win32.h> |
|
||||
#include <psapi.h> |
|
||||
|
|
||||
#include <node_vars.h> |
|
||||
#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<Array> *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<Object> 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<Object> 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<Value> Platform::GetInterfaceAddresses() { |
|
||||
HandleScope scope; |
|
||||
return scope.Close(Object::New()); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} // namespace node
|
|
@ -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 <windows.h> |
|
||||
#include <winsock2.h> |
|
||||
|
|
||||
#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_
|
|
||||
|
|
Loading…
Reference in new issue