Browse Source

[net2] Do hostname lookups in connect and listen

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
2582560f91
  1. 126
      lib/net.js
  2. 8
      src/node_net2.cc
  3. 4
      test-net-server.js

126
lib/net.js

@ -283,48 +283,55 @@ Socket.prototype.connect = function () {
var self = this;
if (self.fd) throw new Error('Socket already opened');
function doConnect () {
try {
connect(self.fd, arguments[0], arguments[1]);
} catch (e) {
close(self.fd);
throw e;
}
// Don't start the read watcher until connection is established
self.readWatcher.set(self.fd, true, false);
// How to connect on POSIX: Wait for fd to become writable, then call
// socketError() if there isn't an error, we're connected. AFAIK this a
// platform independent way determining when a non-blocking connection
// is established, but I have only seen it documented in the Linux
// Manual Page connect(2) under the error code EINPROGRESS.
self.writeWatcher.set(self.fd, false, true);
self.writeWatcher.start();
self.writeWatcher.callback = function () {
var errno = socketError(self.fd);
if (errno == 0) {
// connection established
self.readWatcher.start();
self.readable = true;
self.writable = true;
self.writeWatcher.callback = self._doFlush;
self.emit('connect');
} else if (errno != EINPROGRESS) {
var e = new Error('connection error');
e.errno = errno;
self.forceClose(e);
}
};
}
if (typeof(arguments[0]) == 'string' && arguments.length == 1) {
self.fd = socket('unix');
self.type = 'unix';
// TODO check if sockfile exists?
doConnect(arguments[0]);
} else {
self.fd = socket('tcp');
self.type = 'tcp';
// TODO dns resolution on arguments[1]
var port = arguments[0];
lookupDomainName(arguments[1], function (ip) {
doConnect(port, ip);
});
}
try {
connect(self.fd, arguments[0], arguments[1]);
} catch (e) {
close(self.fd);
throw e;
}
// Don't start the read watcher until connection is established
self.readWatcher.set(self.fd, true, false);
// How to connect on POSIX: Wait for fd to become writable, then call
// socketError() if there isn't an error, we're connected. AFAIK this a
// platform independent way determining when a non-blocking connection
// is established, but I have only seen it documented in the Linux
// Manual Page connect(2) under the error code EINPROGRESS.
self.writeWatcher.set(self.fd, false, true);
self.writeWatcher.start();
self.writeWatcher.callback = function () {
var errno = socketError(self.fd);
if (errno == 0) {
// connection established
self.readWatcher.start();
self.readable = true;
self.writable = true;
self.writeWatcher.callback = self._doFlush;
self.emit('connect');
} else if (errno != EINPROGRESS) {
var e = new Error('connection error');
e.errno = errno;
self.forceClose(e);
}
};
};
@ -387,6 +394,34 @@ exports.createServer = function (listener) {
return new Server(listener);
};
/* This function does both an ipv4 and ipv6 look up.
* It first tries the ipv4 look up, if that fails, then it does the ipv6.
*/
function lookupDomainName (dn, callback) {
if (!needsLookup(dn)) {
callback(dn);
} else {
debug("getaddrinfo 4 " + dn);
getaddrinfo(dn, 4, function (r4) {
if (r4 instanceof Error) throw r4;
if (r4.length > 0) {
debug("getaddrinfo 4 found " + r4);
callback(r4[0]);
} else {
debug("getaddrinfo 6 " + dn);
getaddrinfo(dn, 6, function (r6) {
if (r6 instanceof Error) throw r6;
if (r6.length < 0) {
throw new Error("No address associated with hostname " + dn);
}
debug("getaddrinfo 6 found " + r6);
callback(r6[0]);
});
}
});
}
}
// Listen on a UNIX socket
// server.listen("/tmp/socket");
@ -400,6 +435,13 @@ Server.prototype.listen = function () {
var self = this;
if (self.fd) throw new Error('Server already opened');
function doListen () {
listen(self.fd, 128);
self.watcher.set(self.fd, true, false);
self.watcher.start();
self.emit("listening");
}
if (typeof(arguments[0]) == 'string' && arguments.length == 1) {
// the first argument specifies a path
self.fd = socket('unix');
@ -415,23 +457,17 @@ Server.prototype.listen = function () {
self.type = 'tcp';
// Don't bind(). OS will assign a port with INADDR_ANY. The port will be
// passed to the 'listening' event.
doListen();
} else {
// the first argument is the port, the second an IP
self.fd = socket('tcp');
self.type = 'tcp';
if (needsLookup(arguments[1])) {
getaddrinfo(arguments[1], function (ip) {
});
}
// TODO dns resolution on arguments[1]
bind(self.fd, arguments[0], arguments[1]);
var port = arguments[0];
lookupDomainName(arguments[1], function (ip) {
bind(self.fd, port, ip);
doListen();
});
}
listen(self.fd, 128);
self.emit("listening");
self.watcher.set(self.fd, true, false);
self.watcher.start();
};

8
src/node_net2.cc

@ -559,7 +559,13 @@ static int AfterResolve(eio_req *req) {
Local<Value> argv[1];
if (req->result != 0) {
argv[0] = ErrnoException(errno, "getaddrinfo");
if (req->result == EAI_NODATA) {
argv[0] = Array::New();
} else {
argv[0] = ErrnoException(req->result,
"getaddrinfo",
gai_strerror(req->result));
}
} else {
struct addrinfo *address;
int n = 0;

4
test-net-server.js

@ -28,11 +28,11 @@ var server = new net.Server(function (socket) {
sys.puts("server-side socket drain");
});
});
server.listen(8000);
server.listen(8000, "localhost");
sys.puts("server fd: " + server.fd);
var c = net.createConnection(8000);
var c = net.createConnection(8000, "localhost");
c.addListener('connect', function () {
sys.puts("!!!client connected");
c.send("hello\n");

Loading…
Cancel
Save