Showing with 109 additions and 36 deletions.
  1. +3 −3 deps/uv/include/uv.h
  2. +4 −4 deps/uv/src/unix/tcp.c
  3. +35 −8 deps/uv/src/unix/tty.c
  4. +28 −2 deps/uv/test/runner-win.c
  5. +21 −19 lib/net.js
  6. +2 −0 src/node.js
  7. +10 −0 src/tcp_wrap.cc
  8. +6 −0 src/tty_wrap.cc
@@ -47,7 +47,7 @@ extern "C" {


#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 9
#define UV_VERSION_MINOR 10


#if defined(_MSC_VER) && _MSC_VER < 1600
@@ -660,12 +660,12 @@ UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
unsigned int delay);

/*
* This setting applies to Windows only.
* Enable/disable simultaneous asynchronous accept requests that are
* queued by the operating system when listening for new tcp connections.
* This setting is used to tune a tcp server for the desired performance.
* Having simultaneous accepts can significantly improve the rate of
* accepting connections (which is why it is enabled by default).
* accepting connections (which is why it is enabled by default) but
* may lead to uneven load distribution in multi-process setups.
*/
UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);

@@ -343,11 +343,11 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
}


int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int on) {
if (on)
handle->flags |= UV_TCP_SINGLE_ACCEPT;
else
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
if (enable)
handle->flags &= ~UV_TCP_SINGLE_ACCEPT;
else
handle->flags |= UV_TCP_SINGLE_ACCEPT;
return 0;
}

@@ -118,25 +118,52 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {


uv_handle_type uv_guess_handle(uv_file file) {
struct sockaddr sa;
struct stat s;
socklen_t len;
int type;

if (file < 0) {
if (file < 0)
return UV_UNKNOWN_HANDLE;
}

if (isatty(file)) {
if (isatty(file))
return UV_TTY;
}

if (fstat(file, &s)) {
if (fstat(file, &s))
return UV_UNKNOWN_HANDLE;
}

if (!S_ISSOCK(s.st_mode) && !S_ISFIFO(s.st_mode)) {
if (S_ISREG(s.st_mode))
return UV_FILE;

if (S_ISCHR(s.st_mode))
return UV_FILE; /* XXX UV_NAMED_PIPE? */

if (S_ISFIFO(s.st_mode))
return UV_NAMED_PIPE;

if (!S_ISSOCK(s.st_mode))
return UV_UNKNOWN_HANDLE;

len = sizeof(type);
if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len))
return UV_UNKNOWN_HANDLE;

len = sizeof(sa);
if (getsockname(file, &sa, &len))
return UV_UNKNOWN_HANDLE;

if (type == SOCK_DGRAM)
if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
return UV_UDP;

if (type == SOCK_STREAM) {
if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
return UV_TCP;
if (sa.sa_family == AF_UNIX)
return UV_NAMED_PIPE;
}

return UV_NAMED_PIPE;
return UV_UNKNOWN_HANDLE;
}


@@ -44,6 +44,11 @@

/* Do platform-specific initialization. */
void platform_init(int argc, char **argv) {
const char* tap;

tap = getenv("UV_TAP_OUTPUT");
tap_output = (tap != NULL && atoi(tap) > 0);

/* Disable the "application crashed" popup. */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
@@ -207,13 +212,34 @@ long int process_output_size(process_info_t *p) {
int process_copy_output(process_info_t *p, int fd) {
DWORD read;
char buf[1024];
char *line, *start;

if (SetFilePointer(p->stdio_out, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return -1;

if (tap_output)
write(fd, "#", 1);

while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) &&
read > 0)
write(fd, buf, read);
read > 0) {
if (tap_output) {
start = buf;

while ((line = strchr(start, '\n')) != NULL) {
write(fd, start, line - start + 1);
write(fd, "#", 1);
start = line + 1;
}

if (start < buf + read)
write(fd, start, buf + read - start);
} else {
write(fd, buf, read);
}
}

if (tap_output)
write(fd, "\n", 1);

if (GetLastError() != ERROR_HANDLE_EOF)
return -1;
@@ -42,6 +42,15 @@ function createTCP() {
}


function createHandle(fd) {
var tty = process.binding('tty_wrap');
var type = tty.guessHandleType(fd);
if (type === 'PIPE') return createPipe();
if (type === 'TCP') return createTCP();
throw new TypeError('Unsupported fd type: ' + type);
}


var debug;
if (process.env.NODE_DEBUG && /net/.test(process.env.NODE_DEBUG)) {
var pid = process.pid;
@@ -144,7 +153,7 @@ function Socket(options) {
if (options.handle) {
this._handle = options.handle; // private
} else if (typeof options.fd !== 'undefined') {
this._handle = createPipe();
this._handle = createHandle(options.fd);
this._handle.open(options.fd);
this.readable = options.readable !== false;
this.writable = options.writable !== false;
@@ -930,25 +939,18 @@ var createServerHandle = exports._createServerHandle =
var handle;

if (typeof fd === 'number' && fd >= 0) {
var tty_wrap = process.binding('tty_wrap');
var type = tty_wrap.guessHandleType(fd);
switch (type) {
case 'PIPE':
debug('listen pipe fd=' + fd);
// create a PipeWrap
handle = createPipe();
handle.open(fd);
handle.readable = true;
handle.writable = true;
break;

default:
// Not a fd we can listen on. This will trigger an error.
debug('listen invalid fd=' + fd + ' type=' + type);
process._errno = 'EINVAL'; // hack, callers expect that errno is set
handle = null;
break;
try {
handle = createHandle(fd);
}
catch (e) {
// Not a fd we can listen on. This will trigger an error.
debug('listen invalid fd=' + fd + ': ' + e.message);
process._errno = 'EINVAL'; // hack, callers expect that errno is set
return null;
}
handle.open(fd);
handle.readable = true;
handle.writable = true;
return handle;

} else if (port == -1 && addressType == -1) {
@@ -569,6 +569,7 @@
break;

case 'PIPE':
case 'TCP':
var net = NativeModule.require('net');
stream = new net.Socket({
fd: fd,
@@ -654,6 +655,7 @@
break;

case 'PIPE':
case 'TCP':
var net = NativeModule.require('net');
stdin = new net.Socket({
fd: fd,
@@ -104,6 +104,7 @@ void TCPWrap::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "writeUtf8String", StreamWrap::WriteUtf8String);
NODE_SET_PROTOTYPE_METHOD(t, "writeUcs2String", StreamWrap::WriteUcs2String);

NODE_SET_PROTOTYPE_METHOD(t, "open", Open);
NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen);
NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
@@ -256,6 +257,15 @@ Handle<Value> TCPWrap::SetSimultaneousAccepts(const Arguments& args) {
#endif


Handle<Value> TCPWrap::Open(const Arguments& args) {
HandleScope scope;
UNWRAP(TCPWrap)
int fd = args[0]->IntegerValue();
uv_tcp_open(&wrap->handle_, fd);
return Null();
}


Handle<Value> TCPWrap::Bind(const Arguments& args) {
HandleScope scope;

@@ -105,9 +105,15 @@ Handle<Value> TTYWrap::GuessHandleType(const Arguments& args) {
uv_handle_type t = uv_guess_handle(fd);

switch (t) {
case UV_TCP:
return scope.Close(String::New("TCP"));

case UV_TTY:
return scope.Close(String::New("TTY"));

case UV_UDP:
return scope.Close(String::New("UDP"));

case UV_NAMED_PIPE:
return scope.Close(String::New("PIPE"));