mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Add some code comments to net.cc
This commit is contained in:
52
src/net.cc
52
src/net.cc
@@ -47,14 +47,18 @@ static const struct addrinfo client_tcp_hints =
|
||||
|
||||
Persistent<FunctionTemplate> Connection::constructor_template;
|
||||
|
||||
// Initialize the tcp.Connection object.
|
||||
void Connection::Initialize(v8::Handle<v8::Object> target) {
|
||||
HandleScope scope;
|
||||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(New);
|
||||
|
||||
constructor_template = Persistent<FunctionTemplate>::New(t);
|
||||
// Inherits from node.EventEmitter
|
||||
constructor_template->Inherit(EventEmitter::constructor_template);
|
||||
// All native node objects have 1 internal field (required by ObjectWrap)
|
||||
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
// Set class name for debugging output
|
||||
constructor_template->SetClassName(String::NewSymbol("Connection"));
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "connect", Connect);
|
||||
@@ -67,16 +71,19 @@ void Connection::Initialize(v8::Handle<v8::Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "setTimeout", SetTimeout);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "setNoDelay", SetNoDelay);
|
||||
|
||||
// Getter for connection.readyState
|
||||
constructor_template->PrototypeTemplate()->SetAccessor(
|
||||
READY_STATE_SYMBOL,
|
||||
ReadyStateGetter);
|
||||
|
||||
// Assign class to its place as tcp.Connection
|
||||
target->Set(String::NewSymbol("Connection"),
|
||||
constructor_template->GetFunction());
|
||||
}
|
||||
|
||||
Handle<Value> Connection::ReadyStateGetter(Local<String> property,
|
||||
const AccessorInfo& info) {
|
||||
// Unwrap the javascript object to get the C++ object
|
||||
Connection *connection = ObjectWrap::Unwrap<Connection>(info.This());
|
||||
assert(connection);
|
||||
|
||||
@@ -84,8 +91,12 @@ Handle<Value> Connection::ReadyStateGetter(Local<String> property,
|
||||
|
||||
assert(property == READY_STATE_SYMBOL);
|
||||
|
||||
// Resolving is not done in evcom, it's done in this file. Thus we add
|
||||
// this "opening" symbol to the native EVCOM ready states. "opening"
|
||||
// really means "resolving".
|
||||
if (connection->resolving_) return scope.Close(OPENING_SYMBOL);
|
||||
|
||||
// Map between the evcom enum and V8 strings:
|
||||
switch (evcom_stream_state(&connection->stream_)) {
|
||||
case EVCOM_INITIALIZED: return scope.Close(CLOSED_SYMBOL);
|
||||
case EVCOM_CONNECTING: return scope.Close(OPENING_SYMBOL);
|
||||
@@ -101,6 +112,9 @@ Handle<Value> Connection::ReadyStateGetter(Local<String> property,
|
||||
String::New("This shouldn't happen.")));
|
||||
}
|
||||
|
||||
// Constructor - these actions are not taken in the normal constructor
|
||||
// (Connection::Connection) because sometimes the Connection needs to be
|
||||
// reinitialized without destroying the object.
|
||||
void Connection::Init() {
|
||||
resolving_ = false;
|
||||
evcom_stream_init(&stream_);
|
||||
@@ -116,27 +130,39 @@ Connection::~Connection() {
|
||||
assert(stream_.sendfd < 0 && "garbage collecting open Connection");
|
||||
}
|
||||
|
||||
// V8 contstructor
|
||||
Handle<Value> Connection::New(const Arguments& args) {
|
||||
HandleScope scope;
|
||||
|
||||
// All constructors in node look similar to this.
|
||||
|
||||
// allocate the C++ object
|
||||
Connection *connection = new Connection();
|
||||
|
||||
// Use ObjectWrap::Wrap to assign it to the internal field in the V8
|
||||
// object.
|
||||
connection->Wrap(args.This());
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
// Open a connection. Starts resolving the hostname in the libeio
|
||||
// thread pool, when that completes in Connection::AfterResolve, actually
|
||||
// open the connection.
|
||||
Handle<Value> Connection::Connect(const Arguments& args) {
|
||||
// Unwrap V8 object into C++ object
|
||||
Connection *connection = ObjectWrap::Unwrap<Connection>(args.Holder());
|
||||
|
||||
assert(connection);
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
// If the connection is closed, reinitialize it.
|
||||
if (connection->ReadyState() == EVCOM_CLOSED) {
|
||||
connection->Init(); // in case we're reusing the socket
|
||||
assert(connection->ReadyState() == EVCOM_INITIALIZED);
|
||||
}
|
||||
|
||||
// If connect() is called on an open connection, raise an error.
|
||||
if (connection->ReadyState() != EVCOM_INITIALIZED) {
|
||||
Local<Value> exception = Exception::Error(
|
||||
String::New("Socket is not in CLOSED state."));
|
||||
@@ -146,39 +172,51 @@ Handle<Value> Connection::Connect(const Arguments& args) {
|
||||
assert(connection->stream_.recvfd < 0);
|
||||
assert(connection->stream_.sendfd < 0);
|
||||
|
||||
// Make sure we have at least one argument (a port)
|
||||
if (args.Length() == 0) {
|
||||
Local<Value> exception = Exception::TypeError(
|
||||
String::New("First argument must be a port number"));
|
||||
return ThrowException(exception);
|
||||
}
|
||||
|
||||
// We need the port as a string for getaddrinfo().
|
||||
// Thus cast it to a string. The strdup()'d value will be freed in
|
||||
// Resolve().
|
||||
String::AsciiValue port_sv(args[0]->ToString());
|
||||
assert(connection->port_ == NULL);
|
||||
connection->port_ = strdup(*port_sv);
|
||||
|
||||
// Get the host, if any is present.
|
||||
assert(connection->host_ == NULL);
|
||||
if (args.Length() > 1 && args[1]->IsString()) {
|
||||
String::Utf8Value host_sv(args[1]->ToString());
|
||||
connection->host_ = strdup(*host_sv);
|
||||
}
|
||||
|
||||
connection->resolving_ = true;
|
||||
connection->resolving_ = true; // This is done so that readyState can return
|
||||
// "opening" while getaddinfo() runs.
|
||||
|
||||
// There will not be any active watchers from this object on the event
|
||||
// loop while getaddrinfo() runs. If the only thing happening in the
|
||||
// script was this hostname resolution, then the event loop would drop
|
||||
// out. Thus we need to add ev_ref() until AfterResolve().
|
||||
ev_ref(EV_DEFAULT_UC);
|
||||
|
||||
// Attach the object so it doesn't get garbage collected.
|
||||
connection->Attach();
|
||||
|
||||
/* For the moment I will do DNS lookups in the eio thread pool. This is
|
||||
* sub-optimal and cannot handle massive numbers of requests.
|
||||
* In the future I will move to a system using adns or udns:
|
||||
* http://lists.schmorp.de/pipermail/libev/2009q1/000632.html
|
||||
*/
|
||||
// For the moment I will do DNS lookups in the eio thread pool. This is
|
||||
// sub-optimal and cannot handle massive numbers of requests.
|
||||
// In the future I will move to a system using adns or udns:
|
||||
// http://lists.schmorp.de/pipermail/libev/2009q1/000632.html
|
||||
eio_custom(Connection::Resolve, EIO_PRI_DEFAULT, Connection::AfterResolve,
|
||||
connection);
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
// This function is executed in the thread pool. It cannot modify any
|
||||
// members of the connection object.
|
||||
int Connection::Resolve(eio_req *req) {
|
||||
Connection *connection = static_cast<Connection*> (req->data);
|
||||
struct addrinfo *address = NULL;
|
||||
|
||||
Reference in New Issue
Block a user