|
|
@ -257,6 +257,7 @@ var securePool = null; |
|
|
|
function allocNewSecurePool () { |
|
|
|
securePool = new Buffer(40*1024); |
|
|
|
} |
|
|
|
|
|
|
|
var emptyBuffer = null; |
|
|
|
function allocEmptyBuffer () { |
|
|
|
emptyBuffer = new Buffer(1); |
|
|
@ -292,25 +293,27 @@ function initStream (self) { |
|
|
|
|
|
|
|
try { |
|
|
|
if (self.secure) { |
|
|
|
if (!securePool) allocNewSecurePool(); |
|
|
|
secureBytesRead = read(self.fd, securePool, 0, securePool.length); |
|
|
|
self.secureStream.readInject(securePool, 0, secureBytesRead); |
|
|
|
bytesRead = self.secureStream.readExtract(pool, pool.used, pool.length - pool.used); |
|
|
|
if(!self.secureEstablished) { |
|
|
|
if (self.secureStream.isInitFinished()) { |
|
|
|
self.secureEstablished = true; |
|
|
|
if (self._events && self._events['secure']) self.emit('secure'); |
|
|
|
} |
|
|
|
} |
|
|
|
if (secureBytesRead === null && !self.server) { |
|
|
|
// Client needs to write as part of handshake
|
|
|
|
this._writeWatcher.start(); |
|
|
|
} |
|
|
|
if (!securePool) allocNewSecurePool(); |
|
|
|
secureBytesRead = read(self.fd, securePool, 0, securePool.length); |
|
|
|
self.secureStream.readInject(securePool, 0, secureBytesRead); |
|
|
|
bytesRead = self.secureStream.readExtract(pool, |
|
|
|
pool.used, |
|
|
|
pool.length - pool.used); |
|
|
|
if (!self.secureEstablished) { |
|
|
|
if (self.secureStream.isInitFinished()) { |
|
|
|
self.secureEstablished = true; |
|
|
|
if (self._events && self._events['secure']) self.emit('secure'); |
|
|
|
} |
|
|
|
} |
|
|
|
if (secureBytesRead === null && !self.server) { |
|
|
|
// Client needs to write as part of handshake
|
|
|
|
this._writeWatcher.start(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
bytesRead = read(self.fd, |
|
|
|
pool, |
|
|
|
pool.used, |
|
|
|
pool.length - pool.used); |
|
|
|
pool.length - pool.used); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (this.forceClose) this.forceClose(e); |
|
|
@ -319,14 +322,17 @@ function initStream (self) { |
|
|
|
|
|
|
|
//debug('bytesRead ' + bytesRead + '\n');
|
|
|
|
|
|
|
|
if (self.secure && bytesRead == 0 && secureBytesRead >0){ |
|
|
|
// Deal with SSL handshake
|
|
|
|
if (self.server) { |
|
|
|
self._checkForSecureHandshake(); |
|
|
|
} else { |
|
|
|
if (self.secureEstablised) self.flush(); |
|
|
|
else self._checkForSecureHandshake(); |
|
|
|
} |
|
|
|
if (self.secure && bytesRead == 0 && secureBytesRead > 0){ |
|
|
|
// Deal with SSL handshake
|
|
|
|
if (self.server) { |
|
|
|
self._checkForSecureHandshake(); |
|
|
|
} else { |
|
|
|
if (self.secureEstablised) { |
|
|
|
self.flush(); |
|
|
|
} else { |
|
|
|
self._checkForSecureHandshake(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (bytesRead === 0) { |
|
|
|
self.readable = false; |
|
|
|
self._readWatcher.stop(); |
|
|
@ -398,12 +404,12 @@ exports.createCredentials = function(cred) { |
|
|
|
if (cred.key) c.context.setKey(cred.key); |
|
|
|
if (cred.cert) c.context.setCert(cred.cert); |
|
|
|
if (cred.ca) { |
|
|
|
if ( (typeof(cred.ca) == 'object') && cred.ca.length ) { |
|
|
|
for(var i=0; i<cred.ca.length; i++) |
|
|
|
c.context.addCACert(cred.ca[i]); |
|
|
|
} else { |
|
|
|
c.context.addCACert(cred.ca); |
|
|
|
} |
|
|
|
if ( (typeof(cred.ca) == 'object') && cred.ca.length ) { |
|
|
|
for(var i=0; i<cred.ca.length; i++) |
|
|
|
c.context.addCACert(cred.ca[i]); |
|
|
|
} else { |
|
|
|
c.context.addCACert(cred.ca); |
|
|
|
} |
|
|
|
} |
|
|
|
return c; |
|
|
|
} |
|
|
@ -424,7 +430,7 @@ exports.Stream = Stream; |
|
|
|
|
|
|
|
Stream.prototype.setSecure = function(credentials) { |
|
|
|
if (!crypto) { |
|
|
|
throw new Error('node.js not compiled with openssl crypto support.'); |
|
|
|
throw new Error('node.js not compiled with openssl crypto support.'); |
|
|
|
} |
|
|
|
this.secure = true; |
|
|
|
this.secureEstablished = false; |
|
|
@ -434,36 +440,39 @@ Stream.prototype.setSecure = function(credentials) { |
|
|
|
} else { |
|
|
|
this.credentials = credentials; |
|
|
|
} |
|
|
|
this.secureStream = new SecureStream(this.credentials.context, this.server?1:0); |
|
|
|
|
|
|
|
this.secureStream = new SecureStream(this.credentials.context, this.server ? 1 : 0); |
|
|
|
|
|
|
|
if (!this.server) { |
|
|
|
// If client, trigger handshake
|
|
|
|
this._checkForSecureHandshake(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Stream.prototype.verifyPeer = function() { |
|
|
|
if (!this.secure) { |
|
|
|
throw new Error('Stream is not a secure stream.'); |
|
|
|
throw new Error('Stream is not a secure stream.'); |
|
|
|
} |
|
|
|
return this.secureStream.verifyPeer(this.credentials.context); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Stream.prototype._checkForSecureHandshake = function() { |
|
|
|
// Do an empty write to see if we need to write out as part of handshake
|
|
|
|
if (!emptyBuffer) allocEmptyBuffer(); |
|
|
|
this.write(emptyBuffer); |
|
|
|
// Do an empty write to see if we need to write out as part of handshake
|
|
|
|
if (!emptyBuffer) allocEmptyBuffer(); |
|
|
|
this.write(emptyBuffer); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Stream.prototype.getPeerCertificate = function(credentials) { |
|
|
|
if (!this.secure) { |
|
|
|
throw new Error('Stream is not a secure stream.'); |
|
|
|
throw new Error('Stream is not a secure stream.'); |
|
|
|
} |
|
|
|
return this.secureStream.getPeerCertificate(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Stream.prototype.getCipher = function() { |
|
|
|
if (!this.secure) { |
|
|
|
throw new Error('Stream is not a secure stream.'); |
|
|
@ -530,12 +539,13 @@ Stream.prototype.write = function (data, encoding) { |
|
|
|
|
|
|
|
|
|
|
|
Stream.prototype._shutdownSecure = function () { |
|
|
|
this.secureStream.shutdown(); |
|
|
|
if (!securePool) allocNewSecurePool(); |
|
|
|
var secureLen = this.secureStream.writeExtract(securePool, 0, securePool.length); |
|
|
|
try { |
|
|
|
var secureBytesWritten = write(this.fd, securePool, 0, secureLen); |
|
|
|
} catch (e) {} |
|
|
|
this.secureStream.shutdown(); |
|
|
|
if (!securePool) allocNewSecurePool(); |
|
|
|
var secureLen = this.secureStream.writeExtract(securePool, 0, securePool.length); |
|
|
|
try { |
|
|
|
var secureBytesWritten = write(this.fd, securePool, 0, secureLen); |
|
|
|
} catch (e) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Directly writes the data to socket.
|
|
|
@ -552,10 +562,10 @@ Stream.prototype._writeOut = function (data, encoding) { |
|
|
|
else throw new Error('Stream is not writable'); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var buffer, off, len; |
|
|
|
var bytesWritten, charsWritten; |
|
|
|
var queuedData = false; |
|
|
|
|
|
|
|
if (typeof data != 'string') { |
|
|
|
// 'data' is a buffer, ignore 'encoding'
|
|
|
|
buffer = data; |
|
|
@ -608,23 +618,23 @@ Stream.prototype._writeOut = function (data, encoding) { |
|
|
|
|
|
|
|
try { |
|
|
|
if (this.secure) { |
|
|
|
if (!buffer) return false; |
|
|
|
bytesWritten = this.secureStream.writeInject(buffer, off, len); |
|
|
|
if (!securePool) allocNewSecurePool(); |
|
|
|
var secureLen = this.secureStream.writeExtract(securePool, 0, securePool.length); |
|
|
|
if (secureLen==-1) { |
|
|
|
// Check our read again for secure handshake
|
|
|
|
this._readWatcher.callback(); |
|
|
|
secureBytesWritten = 0; |
|
|
|
} else { |
|
|
|
var secureBytesWritten = write(this.fd, securePool, 0, secureLen); |
|
|
|
} |
|
|
|
if(!this.secureEstablished && this.secureStream.isInitFinished()) { |
|
|
|
this.secureEstablished = true; |
|
|
|
if (this._events && this._events['secure']) this.emit('secure'); |
|
|
|
} |
|
|
|
if (!buffer) return false; |
|
|
|
bytesWritten = this.secureStream.writeInject(buffer, off, len); |
|
|
|
if (!securePool) allocNewSecurePool(); |
|
|
|
var secureLen = this.secureStream.writeExtract(securePool, 0, securePool.length); |
|
|
|
if (secureLen==-1) { |
|
|
|
// Check our read again for secure handshake
|
|
|
|
this._readWatcher.callback(); |
|
|
|
secureBytesWritten = 0; |
|
|
|
} else { |
|
|
|
var secureBytesWritten = write(this.fd, securePool, 0, secureLen); |
|
|
|
} |
|
|
|
if(!this.secureEstablished && this.secureStream.isInitFinished()) { |
|
|
|
this.secureEstablished = true; |
|
|
|
if (this._events && this._events['secure']) this.emit('secure'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
bytesWritten = write(this.fd, buffer, off, len); |
|
|
|
bytesWritten = write(this.fd, buffer, off, len); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
this.forceClose(e); |
|
|
@ -819,7 +829,7 @@ Stream.prototype.forceClose = function (exception) { |
|
|
|
timeout.unenroll(this); |
|
|
|
|
|
|
|
if (this.secure) { |
|
|
|
this.secureStream.close(); |
|
|
|
this.secureStream.close(); |
|
|
|
} |
|
|
|
|
|
|
|
// FIXME Bug when this.fd == 0
|
|
|
|