You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							101 lines
						
					
					
						
							2.2 KiB
						
					
					
				
			
		
		
	
	
							101 lines
						
					
					
						
							2.2 KiB
						
					
					
				'use strict'; | 
						|
 | 
						|
var util = require('util'); | 
						|
var EventEmitter = require('events').EventEmitter; | 
						|
 | 
						|
function Hose(socket, options, filter) { | 
						|
  EventEmitter.call(this); | 
						|
 | 
						|
  if (typeof options === 'function') { | 
						|
    filter = options; | 
						|
    options = {}; | 
						|
  } | 
						|
 | 
						|
  this.socket = socket; | 
						|
  this.options = options; | 
						|
  this.filter = filter; | 
						|
 | 
						|
  this.buffer = null; | 
						|
 | 
						|
  var self = this; | 
						|
  this.listeners = { | 
						|
    error: function(err) { | 
						|
      return self.onError(err); | 
						|
    }, | 
						|
    data: function(chunk) { | 
						|
      return self.onData(chunk); | 
						|
    }, | 
						|
    end: function() { | 
						|
      return self.onEnd(); | 
						|
    } | 
						|
  }; | 
						|
 | 
						|
  this.socket.on('error', this.listeners.error); | 
						|
  this.socket.on('data', this.listeners.data); | 
						|
  this.socket.on('end', this.listeners.end); | 
						|
} | 
						|
util.inherits(Hose, EventEmitter); | 
						|
module.exports = Hose; | 
						|
 | 
						|
Hose.create = function create(socket, options, filter) { | 
						|
  return new Hose(socket, options, filter); | 
						|
}; | 
						|
 | 
						|
Hose.prototype.detach = function detach() { | 
						|
  // Stop the flow | 
						|
  this.socket.pause(); | 
						|
 | 
						|
  this.socket.removeListener('error', this.listeners.error); | 
						|
  this.socket.removeListener('data', this.listeners.data); | 
						|
  this.socket.removeListener('end', this.listeners.end); | 
						|
}; | 
						|
 | 
						|
Hose.prototype.reemit = function reemit() { | 
						|
  var buffer = this.buffer; | 
						|
  this.buffer = null; | 
						|
 | 
						|
  // Modern age | 
						|
  if (this.socket.unshift) { | 
						|
    this.socket.unshift(buffer); | 
						|
    if (this.socket.listeners('data').length > 0) | 
						|
      this.socket.resume(); | 
						|
    return; | 
						|
  } | 
						|
 | 
						|
  // Rusty node v0.8 | 
						|
  if (this.socket.ondata) | 
						|
    this.socket.ondata(buffer, 0, buffer.length); | 
						|
  this.socket.emit('data', buffer); | 
						|
  this.socket.resume(); | 
						|
}; | 
						|
 | 
						|
Hose.prototype.onError = function onError(err) { | 
						|
  this.detach(); | 
						|
  this.emit('error', err); | 
						|
}; | 
						|
 | 
						|
Hose.prototype.onData = function onData(chunk) { | 
						|
  if (this.buffer) | 
						|
    this.buffer = Buffer.concat([ this.buffer, chunk ]); | 
						|
  else | 
						|
    this.buffer = chunk; | 
						|
 | 
						|
  var self = this; | 
						|
  this.filter(this.buffer, function(err, protocol) { | 
						|
    if (err) | 
						|
      return self.onError(err); | 
						|
 | 
						|
    // No protocol selected yet | 
						|
    if (!protocol) | 
						|
      return; | 
						|
 | 
						|
    self.detach(); | 
						|
    self.emit('select', protocol, self.socket); | 
						|
    self.reemit(); | 
						|
  }); | 
						|
}; | 
						|
 | 
						|
Hose.prototype.onEnd = function onEnd() { | 
						|
  this.detach(); | 
						|
  this.emit('error', new Error('Not enough data to recognize protocol')); | 
						|
};
 | 
						|
 |