Browse Source

Start on net2

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
c819abccb6
  1. 3
      src/node.cc
  2. 178
      src/node_net2.cc
  3. 12
      src/node_net2.h
  4. 1
      wscript

3
src/node.cc

@ -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

@ -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

@ -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

@ -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…
Cancel
Save