/* 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.
/* 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();
// 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');
}
if (rv === 0) {
- this._encInPending.unshift(tmp);
+ this.encrypted._pending.unshift(tmp);
break;
}
}
// 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');
}
//
// 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);
}
if (rv === 0) {
- this._clearInPending.unshift(tmp);
+ this.cleartext._pending.unshift(tmp);
break;
}
}
// 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');
}
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
},
function() {
if (!self._ssl) return false;
- return self._encryptedWriteState === true;
+ return self.encrypted._writeState === true;
});
if (options.ca) this.ca = options.ca;
};
+
+