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.
		
		
		
		
			
				
					102 lines
				
				2.2 KiB
			
		
		
			
		
	
	
					102 lines
				
				2.2 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'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'));
							 | 
						||
| 
								 | 
							
								};
							 |