Browse Source

Merge branch 'v0.4'

Conflicts:
	lib/crypto.js
	lib/tls.js
v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
59274e8a33
  1. 56
      doc/api/http.markdown
  2. 28
      lib/crypto.js
  3. 46
      lib/tls.js
  4. 5
      src/node_buffer.cc
  5. 49
      src/platform_sunos.cc
  6. 6
      test/simple/test-buffer.js
  7. 93
      test/simple/test-http-upgrade-agent.js
  8. 5
      test/simple/test-tls-set-encoding.js

56
doc/api/http.markdown

@ -483,13 +483,59 @@ Options:
### Event: 'upgrade' ### Event: 'upgrade'
`function (request, socket, head)` `function (response, socket, head)`
Emitted each time a server responds to a request with an upgrade. If this
event isn't being listened for, clients receiving an upgrade header will have
their connections closed.
A client server pair that show you how to listen for the `upgrade` event using `http.getAgent`:
Emitted each time a server responds to a request with an upgrade. If this event var http = require('http');
isn't being listened for, clients receiving an upgrade header will have their var net = require('net');
connections closed.
// Create an HTTP server
var srv = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
srv.on('upgrade', function(req, socket, upgradeHead) {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n\r\n');
socket.ondata = function(data, start, end) {
socket.write(data.toString('utf8', start, end), 'utf8'); // echo back
};
});
// now that server is running
srv.listen(1337, '127.0.0.1', function() {
// make a request
var agent = http.getAgent('127.0.0.1', 1337);
var options = {
agent: agent,
port: 1337,
host: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket'
}
};
var req = http.request(options);
req.end();
agent.on('upgrade', function(res, socket, upgradeHead) {
console.log('got upgraded!');
socket.end();
process.exit(0);
});
});
See the description of the [upgrade event](http.html#event_upgrade_) for `http.Server` for further details.
### Event: 'continue' ### Event: 'continue'

28
lib/crypto.js

@ -37,7 +37,7 @@ try {
} }
function Credentials(secureProtocol, flags) { function Credentials(secureProtocol, flags, context) {
if (!(this instanceof Credentials)) { if (!(this instanceof Credentials)) {
return new Credentials(secureProtocol); return new Credentials(secureProtocol);
} }
@ -46,24 +46,32 @@ function Credentials(secureProtocol, flags) {
throw new Error('node.js not compiled with openssl crypto support.'); throw new Error('node.js not compiled with openssl crypto support.');
} }
this.context = new SecureContext(); if (context) {
this.context = context;
if (secureProtocol) {
this.context.init(secureProtocol);
} else { } else {
this.context.init(); this.context = new SecureContext();
}
if(flags) this.context.setOptions(flags); if (secureProtocol) {
this.context.init(secureProtocol);
} else {
this.context.init();
}
}
if (flags) this.context.setOptions(flags);
} }
exports.Credentials = Credentials; exports.Credentials = Credentials;
exports.createCredentials = function(options) { exports.createCredentials = function(options, context) {
if (!options) options = {}; if (!options) options = {};
var c = new Credentials(options.secureProtocol, options.secureOptions);
var c = new Credentials(options.secureProtocol,
options.secureOptions,
context);
if (context) return c;
if (options.key) c.context.setKey(options.key); if (options.key) c.context.setKey(options.key);

46
lib/tls.js

@ -244,9 +244,23 @@ CryptoStream.prototype._done = function() {
}; };
CryptoStream.prototype.fd = -1; // readyState is deprecated. Don't use it.
CryptoStream.prototype.__defineGetter__('readyState', Object.defineProperty(CryptoStream.prototype, 'readyState', {
net.Socket.prototype.__lookupGetter__('readyState')); get: function() {
if (this._connecting) {
return 'opening';
} else if (this.readable && this.writable) {
return 'open';
} else if (this.readable && !this.writable) {
return 'readOnly';
} else if (!this.readable && this.writable) {
return 'writeOnly';
} else {
return 'closed';
}
}
});
// Move decrypted, clear data out into the application. // Move decrypted, clear data out into the application.
// From the user's perspective this occurs as a 'data' event // From the user's perspective this occurs as a 'data' event
@ -750,18 +764,24 @@ function Server(/* [options], listener */) {
var self = this; var self = this;
// Handle option defaults:
this.setOptions(options);
var sharedCreds = crypto.createCredentials({
key: self.key,
cert: self.cert,
ca: self.ca,
ciphers: self.ciphers,
secureProtocol: self.secureProtocol,
secureOptions: self.secureOptions,
crl: self.crl
});
sharedCreds.context.setCiphers('RC4-SHA:AES128-SHA:AES256-SHA');
// constructor call // constructor call
net.Server.call(this, function(socket) { net.Server.call(this, function(socket) {
var creds = crypto.createCredentials({ var creds = crypto.createCredentials(null, sharedCreds.context);
key: self.key,
cert: self.cert,
ca: self.ca,
ciphers: self.ciphers,
secureProtocol: self.secureProtocol,
secureOptions: self.secureOptions,
crl: self.crl
});
creds.context.setCiphers('RC4-SHA:AES128-SHA:AES256-SHA');
var pair = new SecurePair(creds, var pair = new SecurePair(creds,
true, true,

5
src/node_buffer.cc

@ -702,6 +702,11 @@ Handle<Value> Buffer::ByteLength(const Arguments &args) {
Handle<Value> Buffer::MakeFastBuffer(const Arguments &args) { Handle<Value> Buffer::MakeFastBuffer(const Arguments &args) {
HandleScope scope; HandleScope scope;
if (!Buffer::HasInstance(args[0])) {
return ThrowException(Exception::TypeError(String::New(
"First argument must be a Buffer")));
}
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject()); Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
Local<Object> fast_buffer = args[1]->ToObject();; Local<Object> fast_buffer = args[1]->ToObject();;
uint32_t offset = args[2]->Uint32Value(); uint32_t offset = args[2]->Uint32Value();

49
src/platform_sunos.cc

@ -168,7 +168,7 @@ int Platform::GetCPUInfo(Local<Array> *cpus) {
*cpus = Array::New(); *cpus = Array::New();
lookup_instance = 0; lookup_instance = 0;
while (ksp = kstat_lookup(kc, "cpu_info", lookup_instance, NULL)){ while (ksp = kstat_lookup(kc, (char *)"cpu_info", lookup_instance, NULL)){
cpuinfo = Object::New(); cpuinfo = Object::New();
if (kstat_read(kc, ksp, NULL) == -1) { if (kstat_read(kc, ksp, NULL) == -1) {
@ -183,9 +183,9 @@ int Platform::GetCPUInfo(Local<Array> *cpus) {
cpuinfo->Set(String::New("error"), String::New(strerror(errno))); cpuinfo->Set(String::New("error"), String::New(strerror(errno)));
(*cpus)->Set(lookup_instance, cpuinfo); (*cpus)->Set(lookup_instance, cpuinfo);
} else { } else {
knp = (kstat_named_t *) kstat_data_lookup(ksp, "clock_MHz"); knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clock_MHz");
cpuinfo->Set(String::New("speed"), data_named(knp)); cpuinfo->Set(String::New("speed"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, "brand"); knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"brand");
cpuinfo->Set(String::New("model"), data_named(knp)); cpuinfo->Set(String::New("model"), data_named(knp));
(*cpus)->Set(lookup_instance, cpuinfo); (*cpus)->Set(lookup_instance, cpuinfo);
} }
@ -194,7 +194,7 @@ int Platform::GetCPUInfo(Local<Array> *cpus) {
} }
lookup_instance = 0; lookup_instance = 0;
while (ksp = kstat_lookup(kc, "cpu", lookup_instance, "sys")){ while (ksp = kstat_lookup(kc, (char *)"cpu", lookup_instance, (char *)"sys")){
cpuinfo = (*cpus)->Get(lookup_instance)->ToObject(); cpuinfo = (*cpus)->Get(lookup_instance)->ToObject();
cputimes = Object::New(); cputimes = Object::New();
@ -202,13 +202,13 @@ int Platform::GetCPUInfo(Local<Array> *cpus) {
cputimes->Set(String::New("error"), String::New(strerror(errno))); cputimes->Set(String::New("error"), String::New(strerror(errno)));
cpuinfo->Set(String::New("times"), cpuinfo); cpuinfo->Set(String::New("times"), cpuinfo);
} else { } else {
knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_kernel"); knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_kernel");
cputimes->Set(String::New("system"), data_named(knp)); cputimes->Set(String::New("system"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_user"); knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_user");
cputimes->Set(String::New("user"), data_named(knp)); cputimes->Set(String::New("user"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_idle"); knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_idle");
cputimes->Set(String::New("idle"), data_named(knp)); cputimes->Set(String::New("idle"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, "intr"); knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"intr");
cputimes->Set(String::New("irq"), data_named(knp)); cputimes->Set(String::New("irq"), data_named(knp));
cpuinfo->Set(String::New("times"), cputimes); cpuinfo->Set(String::New("times"), cputimes);
@ -224,12 +224,37 @@ int Platform::GetCPUInfo(Local<Array> *cpus) {
double Platform::GetFreeMemory() { double Platform::GetFreeMemory() {
return 0.0; kstat_ctl_t *kc;
kstat_t *ksp;
kstat_named_t *knp;
double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
ulong_t freemem;
if((kc = kstat_open()) == NULL)
throw "could not open kstat";
ksp = kstat_lookup(kc, (char *)"unix", 0, (char *)"system_pages");
if(kstat_read(kc, ksp, NULL) == -1){
throw "could not read kstat";
}
else {
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"freemem");
freemem = knp->value.ul;
}
kstat_close(kc);
return static_cast<double>(freemem)*pagesize;
} }
double Platform::GetTotalMemory() { double Platform::GetTotalMemory() {
return 0.0; double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
double pages = static_cast<double>(sysconf(_SC_PHYS_PAGES));
return pagesize*pages;
} }
double Platform::GetUptimeImpl() { double Platform::GetUptimeImpl() {
@ -243,12 +268,12 @@ double Platform::GetUptimeImpl() {
if ((kc = kstat_open()) == NULL) if ((kc = kstat_open()) == NULL)
throw "could not open kstat"; throw "could not open kstat";
ksp = kstat_lookup(kc, "unix", 0, "system_misc"); ksp = kstat_lookup(kc, (char *)"unix", 0, (char *)"system_misc");
if (kstat_read(kc, ksp, NULL) == -1) { if (kstat_read(kc, ksp, NULL) == -1) {
throw "unable to read kstat"; throw "unable to read kstat";
} else { } else {
knp = (kstat_named_t *) kstat_data_lookup(ksp, "clk_intr"); knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clk_intr");
clk_intr = knp->value.ul; clk_intr = knp->value.ul;
} }

6
test/simple/test-buffer.js

@ -577,3 +577,9 @@ assert.equal(0xee, b[0]);
assert.equal(0xad, b[1]); assert.equal(0xad, b[1]);
assert.equal(0xbe, b[2]); assert.equal(0xbe, b[2]);
assert.equal(0xef, b[3]); assert.equal(0xef, b[3]);
// This should not segfault the program.
assert.throws(function() {
new Buffer('"pong"', 0, 6, 8031, '127.0.0.1')
});

93
test/simple/test-http-upgrade-agent.js

@ -0,0 +1,93 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// Verify that the 'upgrade' header causes an 'upgrade' event to be emitted to
// the HTTP client. This test uses a raw TCP server to better control server
// behavior.
var common = require('../common');
var assert = require('assert');
var http = require('http');
var net = require('net');
// Create a TCP server
var srv = net.createServer(function(c) {
var data = '';
c.addListener('data', function(d) {
data += d.toString('utf8');
c.write('HTTP/1.1 101\r\n');
c.write('hello: world\r\n');
c.write('connection: upgrade\r\n');
c.write('upgrade: websocket\r\n');
c.write('\r\n');
c.write('nurtzo');
});
c.addListener('end', function() {
c.end();
});
});
var gotUpgrade = false;
srv.listen(common.PORT, '127.0.0.1', function() {
var agent = http.getAgent({
host: '127.0.0.1',
port: common.PORT
});
assert.ok(agent);
var options = {
port: common.PORT,
host: '127.0.0.1',
headers: {
'upgrade': 'websocket'
}
};
var req = http.request(options);
req.end();
agent.on('upgrade', function(res, socket, upgradeHead) {
// XXX: This test isn't fantastic, as it assumes that the entire response
// from the server will arrive in a single data callback
assert.equal(upgradeHead, 'nurtzo');
console.log(res.headers);
var expectedHeaders = { 'hello': 'world',
'connection': 'upgrade',
'upgrade': 'websocket' };
assert.deepEqual(expectedHeaders, res.headers);
socket.end();
srv.close();
gotUpgrade = true;
});
});
process.addListener('exit', function() {
assert.ok(gotUpgrade);
});

5
test/simple/test-tls-set-encoding.js

@ -54,6 +54,11 @@ server.listen(common.PORT, function() {
client.on('close', function() { client.on('close', function() {
// readyState is deprecated but we want to make
// sure this isn't triggering an assert in lib/net.js
// See issue #1069.
assert.equal('closed', client.readyState);
assert.equal(buffer, message); assert.equal(buffer, message);
console.log(message); console.log(message);
server.close(); server.close();

Loading…
Cancel
Save