Index: frontend/node_modules/select-hose/lib/hose.js
===================================================================
--- frontend/node_modules/select-hose/lib/hose.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/select-hose/lib/hose.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,101 @@
+'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'));
+};
