Start on net2
This commit is contained in:
parent
f219938b69
commit
c819abccb6
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <node_buffer.h>
|
#include <node_buffer.h>
|
||||||
#include <node_io_watcher.h>
|
#include <node_io_watcher.h>
|
||||||
|
#include <node_net2.h>
|
||||||
#include <node_events.h>
|
#include <node_events.h>
|
||||||
#include <node_dns.h>
|
#include <node_dns.h>
|
||||||
#include <node_net.h>
|
#include <node_net.h>
|
||||||
@ -856,6 +857,8 @@ static Local<Object> Load(int argc, char *argv[]) {
|
|||||||
Stat::Initialize(process); // stat.cc
|
Stat::Initialize(process); // stat.cc
|
||||||
SignalHandler::Initialize(process); // signal_handler.cc
|
SignalHandler::Initialize(process); // signal_handler.cc
|
||||||
|
|
||||||
|
InitNet2(process); // net2.cc
|
||||||
|
|
||||||
Stdio::Initialize(process); // stdio.cc
|
Stdio::Initialize(process); // stdio.cc
|
||||||
ChildProcess::Initialize(process); // child_process.cc
|
ChildProcess::Initialize(process); // child_process.cc
|
||||||
DefineConstants(process); // constants.cc
|
DefineConstants(process); // constants.cc
|
||||||
|
178
src/node_net2.cc
Normal file
178
src/node_net2.cc
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include <node_net2.h>
|
||||||
|
#include <v8.h>
|
||||||
|
|
||||||
|
#include <node.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <arpa/inet.h> /* inet_pton */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
|
||||||
|
using namespace v8;
|
||||||
|
|
||||||
|
static Persistent<String> errno_symbol;
|
||||||
|
static Persistent<String> syscall_symbol;
|
||||||
|
|
||||||
|
static inline Local<Value> ErrnoException(int errorno, const char *syscall, const char *msg = "") {
|
||||||
|
if (!msg[0]) msg = strerror(errorno);
|
||||||
|
Local<Value> e = Exception::Error(String::NewSymbol(msg));
|
||||||
|
Local<Object> obj = e->ToObject();
|
||||||
|
obj->Set(errno_symbol, Integer::New(errorno));
|
||||||
|
obj->Set(syscall_symbol, String::NewSymbol(syscall));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new non-blocking socket fd
|
||||||
|
// t.socket("TCP");
|
||||||
|
// t.socket("UNIX");
|
||||||
|
// t.socket("UDP");
|
||||||
|
static Handle<Value> Socket(const Arguments& args) {
|
||||||
|
HandleScope scope;
|
||||||
|
|
||||||
|
// default to TCP
|
||||||
|
int domain = PF_INET6;
|
||||||
|
int type = SOCK_STREAM;
|
||||||
|
|
||||||
|
if (args[0]->IsString()) {
|
||||||
|
String::Utf8Value t(args[0]->ToString());
|
||||||
|
if (0 == strcasecmp(*t, "TCP")) {
|
||||||
|
domain = PF_INET6;
|
||||||
|
type = SOCK_STREAM;
|
||||||
|
} else if (0 == strcasecmp(*t, "UDP")) {
|
||||||
|
domain = PF_INET6;
|
||||||
|
type = SOCK_DGRAM;
|
||||||
|
} else if (0 == strcasecmp(*t, "UNIX")) {
|
||||||
|
domain = PF_UNIX;
|
||||||
|
type = SOCK_STREAM;
|
||||||
|
} else {
|
||||||
|
return ThrowException(Exception::Error(
|
||||||
|
String::New("Unknown socket type.")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = socket(domain, type, 0);
|
||||||
|
|
||||||
|
if (fd < 0) return ThrowException(ErrnoException(errno, "socket"));
|
||||||
|
|
||||||
|
int fcntl_errno;
|
||||||
|
|
||||||
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
if (flags == -1) {
|
||||||
|
fcntl_errno = errno;
|
||||||
|
close(fd);
|
||||||
|
return ThrowException(ErrnoException(fcntl_errno, "fcntl"));
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
|
||||||
|
if (fcntl(fd, F_SETFL, flags) == -1) {
|
||||||
|
fcntl_errno = errno;
|
||||||
|
close(fd);
|
||||||
|
return ThrowException(ErrnoException(fcntl_errno, "fcntl"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return scope.Close(Integer::New(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 arguments means connect with unix
|
||||||
|
// t.connect(fd, "/tmp/socket")
|
||||||
|
//
|
||||||
|
// 3 arguments means connect with TCP or UDP
|
||||||
|
// t.connect(fd, "127.0.0.1", 80)
|
||||||
|
static Handle<Value> Connect(const Arguments& args) {
|
||||||
|
HandleScope scope;
|
||||||
|
|
||||||
|
if (!args[0]->IsInt32()) {
|
||||||
|
return ThrowException(Exception::TypeError(
|
||||||
|
String::New("First argument should be file descriptor")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Length() < 2) {
|
||||||
|
return ThrowException(Exception::TypeError(
|
||||||
|
String::New("Must have at least two args")));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = args[0]->Int32Value();
|
||||||
|
|
||||||
|
struct sockaddr *addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
|
||||||
|
if (args.Length() == 2) {
|
||||||
|
// UNIX
|
||||||
|
String::Utf8Value path(args[1]->ToString());
|
||||||
|
|
||||||
|
struct sockaddr_un un = {0};
|
||||||
|
|
||||||
|
if (path.length() > sizeof un.sun_path) {
|
||||||
|
return ThrowException(Exception::Error(String::New("Socket path too long")));
|
||||||
|
}
|
||||||
|
|
||||||
|
un.sun_family = AF_UNIX;
|
||||||
|
strcpy(un.sun_path, *path);
|
||||||
|
|
||||||
|
addr = (struct sockaddr*)&un;
|
||||||
|
addrlen = path.length() + sizeof(un.sun_family);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// TCP or UDP
|
||||||
|
String::Utf8Value ip(args[1]->ToString());
|
||||||
|
int port = args[2]->Int32Value();
|
||||||
|
|
||||||
|
struct sockaddr_in6 in6 = {0};
|
||||||
|
|
||||||
|
char ipv6[255] = "::FFFF:";
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, *ip, &(in6.sin6_addr)) > 0) {
|
||||||
|
// If this is an IPv4 address then we need to change it to the
|
||||||
|
// IPv4-mapped-on-IPv6 format which looks like
|
||||||
|
// ::FFFF:<IPv4 address>
|
||||||
|
// For more information see "Address Format" ipv6(7) and "BUGS" in
|
||||||
|
// inet_pton(3)
|
||||||
|
strcat(ipv6, *ip);
|
||||||
|
} else {
|
||||||
|
strcpy(ipv6, *ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET6, ipv6, &(in6.sin6_addr)) <= 0) {
|
||||||
|
return ThrowException(
|
||||||
|
ErrnoException(errno, "inet_pton", "Invalid IP Address"));
|
||||||
|
}
|
||||||
|
|
||||||
|
in6.sin6_family = AF_INET6;
|
||||||
|
in6.sin6_port = htons(port);
|
||||||
|
|
||||||
|
addr = (struct sockaddr*)&in6;
|
||||||
|
addrlen = sizeof in6;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = connect(fd, addr, addrlen);
|
||||||
|
|
||||||
|
if (r < 0 && errno != EINPROGRESS) {
|
||||||
|
return ThrowException(ErrnoException(errno, "connect"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InitNet2(Handle<Object> target) {
|
||||||
|
HandleScope scope;
|
||||||
|
|
||||||
|
NODE_SET_METHOD(target, "socket", Socket);
|
||||||
|
NODE_SET_METHOD(target, "connect", Connect);
|
||||||
|
|
||||||
|
errno_symbol = NODE_PSYMBOL("errno");
|
||||||
|
syscall_symbol = NODE_PSYMBOL("syscall");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace node
|
12
src/node_net2.h
Normal file
12
src/node_net2.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef NODE_NET2
|
||||||
|
#define NODE_NET2
|
||||||
|
|
||||||
|
#include <v8.h>
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
|
||||||
|
void InitNet2(v8::Handle<v8::Object> target);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NODE_NET2
|
1
wscript
1
wscript
@ -323,6 +323,7 @@ def build(bld):
|
|||||||
node.source = """
|
node.source = """
|
||||||
src/node.cc
|
src/node.cc
|
||||||
src/node_buffer.cc
|
src/node_buffer.cc
|
||||||
|
src/node_net2.cc
|
||||||
src/node_io_watcher.cc
|
src/node_io_watcher.cc
|
||||||
src/node_child_process.cc
|
src/node_child_process.cc
|
||||||
src/node_constants.cc
|
src/node_constants.cc
|
||||||
|
Loading…
x
Reference in New Issue
Block a user