michael@0: var spdy = require('../spdy'), michael@0: utils = exports; michael@0: michael@0: var zlib = require('zlib'), michael@0: Buffer = require('buffer').Buffer; michael@0: michael@0: // michael@0: // ### function createDeflate () michael@0: // Creates deflate stream with SPDY dictionary michael@0: // michael@0: utils.createDeflate = function createDeflate(version) { michael@0: var deflate = zlib.createDeflate({ michael@0: dictionary: spdy.protocol[version].dictionary, michael@0: windowBits: 11 michael@0: }); michael@0: michael@0: // Define lock information early michael@0: deflate.locked = false; michael@0: deflate.lockBuffer = []; michael@0: michael@0: return deflate; michael@0: }; michael@0: michael@0: // michael@0: // ### function createInflate () michael@0: // Creates inflate stream with SPDY dictionary michael@0: // michael@0: utils.createInflate = function createInflate(version) { michael@0: var inflate = zlib.createInflate({ michael@0: dictionary: spdy.protocol[version].dictionary, michael@0: windowBits: 15 michael@0: }); michael@0: michael@0: // Define lock information early michael@0: inflate.locked = false; michael@0: inflate.lockBuffer = []; michael@0: michael@0: return inflate; michael@0: }; michael@0: michael@0: // michael@0: // ### function resetZlibStream (stream) michael@0: // #### @stream {zlib.Stream} stream michael@0: // Resets zlib stream and associated locks michael@0: // michael@0: utils.resetZlibStream = function resetZlibStream(stream, callback) { michael@0: if (stream.locked) { michael@0: stream.lockBuffer.push(function() { michael@0: resetZlibStream(stream, callback); michael@0: }); michael@0: return; michael@0: } michael@0: michael@0: stream.reset(); michael@0: stream.lockBuffer = []; michael@0: michael@0: callback(null); michael@0: }; michael@0: michael@0: var delta = 0; michael@0: // michael@0: // ### function zstream (stream, buffer, callback) michael@0: // #### @stream {Deflate|Inflate} One of streams above michael@0: // #### @buffer {Buffer} Input data (to compress or to decompress) michael@0: // #### @callback {Function} Continuation to callback michael@0: // Compress/decompress data and pass it to callback michael@0: // michael@0: utils.zstream = function zstream(stream, buffer, callback) { michael@0: var flush = stream._flush, michael@0: chunks = [], michael@0: total = 0; michael@0: michael@0: if (stream.locked) { michael@0: stream.lockBuffer.push(function() { michael@0: zstream(stream, buffer, callback); michael@0: }); michael@0: return; michael@0: } michael@0: stream.locked = true; michael@0: michael@0: function collect(chunk) { michael@0: chunks.push(chunk); michael@0: total += chunk.length; michael@0: } michael@0: stream.on('data', collect); michael@0: stream.write(buffer); michael@0: michael@0: stream.once('error', function(err) { michael@0: stream.removeAllListeners('data'); michael@0: callback(err); michael@0: }); michael@0: michael@0: stream.flush(function() { michael@0: stream.removeAllListeners('data'); michael@0: stream.removeAllListeners('error'); michael@0: stream._flush = flush; michael@0: michael@0: callback(null, chunks, total); michael@0: michael@0: stream.locked = false; michael@0: var deferred = stream.lockBuffer.shift(); michael@0: if (deferred) deferred(); michael@0: }); michael@0: }; michael@0: michael@0: // michael@0: // ### function zwrap (stream) michael@0: // #### @stream {zlib.Stream} stream to wrap michael@0: // Wraps stream within function to allow simple deflate/inflate michael@0: // michael@0: utils.zwrap = function zwrap(stream) { michael@0: return function(data, callback) { michael@0: utils.zstream(stream, data, callback); michael@0: }; michael@0: };