|
|
@ -16,7 +16,52 @@ if (debugLevel & 0x2) { |
|
|
|
|
|
|
|
|
|
|
|
/* Lazy Loaded crypto object */ |
|
|
|
var SecureStream = null; |
|
|
|
var SecureStream = null; // note SecureStream is not a "real" stream.
|
|
|
|
|
|
|
|
// Base class of both CleartextStream and EncryptedStream
|
|
|
|
function CryptoStream (pair) { |
|
|
|
stream.Stream.call(this); |
|
|
|
|
|
|
|
this.pair = pair; |
|
|
|
|
|
|
|
this.readable = this.writable = true; |
|
|
|
|
|
|
|
this._writeState = true; |
|
|
|
this._pending = []; |
|
|
|
} |
|
|
|
util.inherits(CryptoStream, stream.Stream); |
|
|
|
|
|
|
|
|
|
|
|
CryptoStream.prototype.write = function(data) { |
|
|
|
if (typeof data == 'string') data = Buffer(data); |
|
|
|
debug('clearIn data'); |
|
|
|
this._pending.push(data); |
|
|
|
this.pair._cycle(); |
|
|
|
return this._writeState; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
CryptoStream.prototype.pause = function() { |
|
|
|
debug('paused cleartext'); |
|
|
|
this._writeState = false; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
CryptoStream.prototype.resume = function() { |
|
|
|
debug('resumed cleartext'); |
|
|
|
this._writeState = true; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
CryptoStream.prototype.end = function(err) { |
|
|
|
debug('cleartext end'); |
|
|
|
if (!this.pair._done) { |
|
|
|
this.pair._ssl.shutdown(); |
|
|
|
this.pair._cycle(); |
|
|
|
} |
|
|
|
this.pair._destroy(err); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Provides a pair of streams to do encrypted communication. |
|
|
@ -75,68 +120,10 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized) { |
|
|
|
|
|
|
|
|
|
|
|
/* Acts as a r/w stream to the cleartext side of the stream. */ |
|
|
|
this.cleartext = new stream.Stream(); |
|
|
|
this.cleartext.readable = true; |
|
|
|
this.cleartext.writable = true; |
|
|
|
this.cleartext = new CryptoStream(this); |
|
|
|
|
|
|
|
/* Acts as a r/w stream to the encrypted side of the stream. */ |
|
|
|
this.encrypted = new stream.Stream(); |
|
|
|
this.encrypted.readable = true; |
|
|
|
this.encrypted.writable = true; |
|
|
|
|
|
|
|
this.cleartext.write = function(data) { |
|
|
|
if (typeof data == 'string') data = Buffer(data); |
|
|
|
debug('clearIn data'); |
|
|
|
self._clearInPending.push(data); |
|
|
|
self._cycle(); |
|
|
|
return self._cleartextWriteState; |
|
|
|
}; |
|
|
|
|
|
|
|
this.cleartext.pause = function() { |
|
|
|
debug('paused cleartext'); |
|
|
|
self._cleartextWriteState = false; |
|
|
|
}; |
|
|
|
|
|
|
|
this.cleartext.resume = function() { |
|
|
|
debug('resumed cleartext'); |
|
|
|
self._cleartextWriteState = true; |
|
|
|
}; |
|
|
|
|
|
|
|
this.cleartext.end = function(err) { |
|
|
|
debug('cleartext end'); |
|
|
|
if (!self._done) { |
|
|
|
self._ssl.shutdown(); |
|
|
|
self._cycle(); |
|
|
|
} |
|
|
|
self._destroy(err); |
|
|
|
}; |
|
|
|
|
|
|
|
this.encrypted.write = function(data) { |
|
|
|
debug('encIn data'); |
|
|
|
self._encInPending.push(data); |
|
|
|
self._cycle(); |
|
|
|
return self._encryptedWriteState; |
|
|
|
}; |
|
|
|
|
|
|
|
this.encrypted.pause = function() { |
|
|
|
if (typeof data == 'string') data = Buffer(data); |
|
|
|
debug('pause encrypted'); |
|
|
|
self._encryptedWriteState = false; |
|
|
|
}; |
|
|
|
|
|
|
|
this.encrypted.resume = function() { |
|
|
|
debug('resume encrypted'); |
|
|
|
self._encryptedWriteState = true; |
|
|
|
}; |
|
|
|
|
|
|
|
this.encrypted.end = function(err) { |
|
|
|
debug('encrypted end'); |
|
|
|
if (!self._done) { |
|
|
|
self._ssl.shutdown(); |
|
|
|
self._cycle(); |
|
|
|
} |
|
|
|
self._destroy(err); |
|
|
|
}; |
|
|
|
this.encrypted = new CryptoStream(this); |
|
|
|
|
|
|
|
process.nextTick(function() { |
|
|
|
self._ssl.start(); |
|
|
@ -240,9 +227,9 @@ SecurePair.prototype._cycle = function() { |
|
|
|
// pair.encrypted.write(d)
|
|
|
|
// });
|
|
|
|
//
|
|
|
|
var encPending = this._encInPending.length > 0; |
|
|
|
while (this._encInPending.length > 0) { |
|
|
|
tmp = this._encInPending.shift(); |
|
|
|
var encPending = this.encrypted._pending.length > 0; |
|
|
|
while (this.encrypted._pending.length > 0) { |
|
|
|
tmp = this.encrypted._pending.shift(); |
|
|
|
|
|
|
|
try { |
|
|
|
debug('writing from encIn'); |
|
|
@ -252,7 +239,7 @@ SecurePair.prototype._cycle = function() { |
|
|
|
} |
|
|
|
|
|
|
|
if (rv === 0) { |
|
|
|
this._encInPending.unshift(tmp); |
|
|
|
this.encrypted._pending.unshift(tmp); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
@ -260,7 +247,7 @@ SecurePair.prototype._cycle = function() { |
|
|
|
} |
|
|
|
|
|
|
|
// If we've cleared all of incoming encrypted data, emit drain.
|
|
|
|
if (encPending && this._encInPending.length === 0) { |
|
|
|
if (this.encrypted._pending && this.encrypted._pending.length === 0) { |
|
|
|
debug('encrypted drain'); |
|
|
|
this.encrypted.emit('drain'); |
|
|
|
} |
|
|
@ -271,9 +258,9 @@ SecurePair.prototype._cycle = function() { |
|
|
|
//
|
|
|
|
// pair.cleartext.write("hello world");
|
|
|
|
//
|
|
|
|
var clearPending = this._clearInPending.length > 0; |
|
|
|
while (this._clearInPending.length > 0) { |
|
|
|
tmp = this._clearInPending.shift(); |
|
|
|
var clearPending = this.cleartext._pending.length > 0; |
|
|
|
while (this.cleartext._pending.length > 0) { |
|
|
|
tmp = this.cleartext._pending.shift(); |
|
|
|
try { |
|
|
|
debug('writng from clearIn'); |
|
|
|
rv = this._ssl.clearIn(tmp, 0, tmp.length); |
|
|
@ -282,7 +269,7 @@ SecurePair.prototype._cycle = function() { |
|
|
|
} |
|
|
|
|
|
|
|
if (rv === 0) { |
|
|
|
this._clearInPending.unshift(tmp); |
|
|
|
this.cleartext._pending.unshift(tmp); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
@ -290,7 +277,7 @@ SecurePair.prototype._cycle = function() { |
|
|
|
} |
|
|
|
|
|
|
|
// If we've cleared all of incoming cleartext data, emit drain.
|
|
|
|
if (clearPending && this._clearInPending.length === 0) { |
|
|
|
if (clearPending && this.cleartext._pending.length === 0) { |
|
|
|
debug('cleartext drain'); |
|
|
|
this.cleartext.emit('drain'); |
|
|
|
} |
|
|
@ -308,7 +295,7 @@ SecurePair.prototype._cycle = function() { |
|
|
|
self.cleartext.emit('data', chunk); |
|
|
|
}, |
|
|
|
function() { |
|
|
|
return self._cleartextWriteState === true; |
|
|
|
return self.cleartext._writeState === true; |
|
|
|
}); |
|
|
|
|
|
|
|
// Move encrypted data to the stream. From the user's perspective this
|
|
|
@ -330,7 +317,7 @@ SecurePair.prototype._cycle = function() { |
|
|
|
}, |
|
|
|
function() { |
|
|
|
if (!self._ssl) return false; |
|
|
|
return self._encryptedWriteState === true; |
|
|
|
return self.encrypted._writeState === true; |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -559,3 +546,5 @@ Server.prototype.setOptions = function(options) { |
|
|
|
if (options.ca) this.ca = options.ca; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|