docs: function _handshake(handshakeProps, handshakeCallback) {
          if (_isFunction(handshakeProps)) {
              handshakeCallback = handshakeProps;
              handshakeProps = undefined;
          }
  
          _clientId = null;
  
          _clearSubscriptions();
  
          // Reset the transports if we're not retrying the handshake
          if (_isDisconnected()) {
              _transports.reset(true);
              _updateAdvice(_config.advice);
          } else {
              // We are retrying the handshake, either because another handshake failed
              // and we're backing off, or because the server timed us out and asks us to
              // re-handshake: in both cases, make sure that if the handshake succeeds
              // the next action is a connect.
              _updateAdvice(_cometd._mixin(false, _advice, {reconnect: 'retry'}));
          }
  
          _batch = 0;
  
          // Mark the start of an internal batch.
          // This is needed because handshake and connect are async.
          // It may happen that the application calls init() then subscribe()
          // and the subscribe message is sent before the connect message, if
          // the subscribe message is not held until the connect message is sent.
          // So here we start a batch to hold temporarily any message until
          // the connection is fully established.
          _internalBatch = true;
  
          // Save the properties provided by the user, so that
          // we can reuse them during automatic re-handshake
          _handshakeProps = handshakeProps;
          _handshakeCallback = handshakeCallback;
  
          var version = '1.0';
  
          // Figure out the transports to send to the server
          var url = _cometd.getURL();
          var transportTypes = _transports.findTransportTypes(version, _crossDomain, url);
  
          var bayeuxMessage = {
              id: _nextMessageId(),
              version: version,
              minimumVersion: version,
              channel: '/meta/handshake',
              supportedConnectionTypes: transportTypes,
              advice: {
                  timeout: _advice.timeout,
                  interval: _advice.interval
              }
          };
          // Do not allow the user to override important fields.
          var message = _cometd._mixin(false, {}, _handshakeProps, bayeuxMessage);
  
          // Save the callback.
          _cometd._putCallback(message.id, handshakeCallback);
  
          // Pick up the first available transport as initial transport
          // since we don't know if the server supports it
          if (!_transport) {
              _transport = _transports.negotiateTransport(transportTypes, version, _crossDomain, url);
              if (!_transport) {
                  var failure = 'Could not find initial transport among: ' + _transports.getTransportTypes();
                  _cometd._warn(failure);
                  throw failure;
              }
          }
  
          _cometd._debug('Initial transport is', _transport.getType());
  
          // We started a batch to hold the application messages,
          // so here we must bypass it and send immediately.
          _setStatus('handshaking');
          _cometd._debug('Handshake sent', message);
          _send(false, [message], false, 'handshake');
      }