docs: function preprocessor (socket) {
    debug('setting up "data" preprocessor');
  
    function ondata (chunk) {
      // TODO: don't be lazy, buffer if needed...
      assert(chunk.length >= 3, 'buffer too small! ' + chunk.length);
      if (/icy/i.test(chunk.slice(0, 3))) {
        debug('got ICY response!');
        var b = new Buffer(chunk.length + HTTP10.length - 'icy'.length);
        var i = 0;
        i += HTTP10.copy(b);
        i += chunk.copy(b, i, 3);
        assert.equal(i, b.length);
        chunk = b;
        socket._wasIcy = true;
      } else {
        socket._wasIcy = false;
      }
  
      return chunk;
    }
  
    var listeners;
    function icyOnData (buf) {
      var chunk = ondata(buf);
  
      // clean up, and re-emit "data" event
      socket.removeListener('data', icyOnData);
      listeners.forEach(function (listener) {
        socket.on('data', listener);
      });
      listeners = null;
      socket.emit('data', chunk);
    }
  
    if ('function' == typeof socket.ondata) {
      // node < v0.11.3, the `ondata` function is set on the socket
      var origOnData = socket.ondata;
      socket.ondata = function (buf, start, length) {
        var chunk = ondata(buf.slice(start, length));
  
        // now clean up and inject the modified `chunk`
        socket.ondata = origOnData;
        origOnData = null;
        socket.ondata(chunk, 0, chunk.length);
      };
    } else if (socket.listeners('data').length > 0) {
      // node >= v0.11.3, the "data" event is listened for directly
  
      // add our own "data" listener, and remove all the old ones
      listeners = socket.listeners('data');
      socket.removeAllListeners('data');
      socket.on('data', icyOnData);
    } else {
      // never?
      throw new Error('should not happen...');
    }
  }