docs: function Protocol (stream, options) {
     this._options = {
        _peer_serializer: null, // Will hold the serializer declared by the peer
        _peer_max_len_exp: 0    // Will hold the maximum frame length declared by
                                // the peer
     };
  
     this._options = util.defaults(this._options, options, this.DEFAULT_OPTIONS);
  
     // Check valid options
     util.assert(this._options.serializer in this.SERIALIZERS,
        'Unsupported serializer: ' + this._options.serializer);
  
     util.assert(this._options.max_len_exp >= 9 &&
        this._options.max_len_exp <= 36,
        'Message length out of bounds [9, 36]: '+ this._options.max_len_exp);
  
     util.assert(!this._options.autoping ||
        (Number.isInteger(this._options.autoping) && this._options.autoping >= 0),
        'Autoping interval must be positive');
  
     util.assert(!this._options.ping_timeout ||
        (Number.isInteger(this._options.ping_timeout) &&
           this._options.ping_timeout >= 0),
        'Ping timeout duration must be positive');
  
     util.assert(!this._options.packet_timeout ||
        (Number.isInteger(this._options.packet_timeout) &&
           this._options.packet_timeout >= 0),
        'Packet timeout duration must be positive');
  
     util.assert((!this._options.autoping || !this._options.ping_timeout) ||
        this._options.autoping > this._options.ping_timeout,
        'Autoping interval (' + this._options.autoping + ') must be lower ' +
        'than ping timeout (' + this._options.ping_timeout + ')');
  
     // Will store a reference to the timeout function associated with the last
     // PING packet
     this._ping_timeout = null;
  
     // Will store the payload of the last PING packet
     this._ping_payload = null;
  
     // Will store the autoping setInterval reference
     this._ping_interval = null;
  
     // Protocol status (see Protocol.prototype.STATUS)
     this._status = this.STATUS.UNINITIATED;
  
     this._stream = stream;
     this._emitter = new EventEmitter();
  
     // Frame buffer
     this._buffer = new Buffer(4);
     this._bufferLen = 0;
     this._msgLen = 0;
  
     // Hook events
     var self = this;
     this._stream.on('data', function (data) {
        self._read(data);
     });
  
     this._stream.on('connect', function () {
        self._handshake();
     });
  
     // Proxy these events from the stream as we don't need to handle them
     var proxyEvents = [
        'close',
        'drain',
        'end',
        'error',
        'timeout'
     ];
     proxyEvents.forEach(function (evt) {
        self._stream.on(evt, function (data) {
           self._emitter.emit(evt, data);
        });
     });
  }