function Primus(url, options) {
  if (!(this instanceof Primus)) return new Primus(url, options);

  Primus.Stream.call(this);

  if ('function' !== typeof this.client) {
    return this.critical(new Error(
      'The client library has not been compiled correctly, see '+
      'https://github.com/primus/primus#client-library for more details'
    ));
  }

  if ('object' === typeof url) {
    options = url;
    url = options.url || options.uri || defaultUrl;
  } else {
    options = options || {};
  }

  if ('ping' in options || 'pong' in options) {
    return this.critical(new Error(
      'The `ping` and `pong` options have been removed'
    ));
  }

  var primus = this;

  // The maximum number of messages that can be placed in queue.
  options.queueSize = 'queueSize' in options ? options.queueSize : Infinity;

  // Connection timeout duration.
  options.timeout = 'timeout' in options ? options.timeout : 10e3;

  // Stores the back off configuration.
  options.reconnect = 'reconnect' in options ? options.reconnect : {};

  // Heartbeat ping interval.
  options.pingTimeout = 'pingTimeout' in options ? options.pingTimeout : 45e3;

  // Reconnect strategies.
  options.strategy = 'strategy' in options ? options.strategy : [];

  // Custom transport options.
  options.transport = 'transport' in options ? options.transport : {};

  primus.buffer = [];                           // Stores premature send data.
  primus.writable = true;                       // Silly stream compatibility.
  primus.readable = true;                       // Silly stream compatibility.
  primus.url = primus.parse(url || defaultUrl); // Parse the URL to a readable format.
  primus.readyState = Primus.CLOSED;            // The readyState of the connection.
  primus.options = options;                     // Reference to the supplied options.
  primus.timers = new TickTock(this);           // Contains all our timers.
  primus.socket = null;                         // Reference to the internal connection.
  primus.disconnect = false;                    // Did we receive a disconnect packet?
  primus.transport = options.transport;         // Transport options.
  primus.transformers = {                       // Message transformers.
    outgoing: [],
    incoming: []
  };

  //
  // Create our reconnection instance.
  //
  primus.recovery = new Recovery(options.reconnect);

  //
  // Parse the reconnection strategy. It can have the following strategies:
  //
  // - timeout: Reconnect when we have a network timeout.
  // - disconnect: Reconnect when we have an unexpected disconnect.
  // - online: Reconnect when we're back online.
  //
  if ('string' === typeof options.strategy) {
    options.strategy = options.strategy.split(/\s?,\s?/g);
  }

  if (false === options.strategy) {
    //
    // Strategies are disabled, but we still need an empty array to join it in
    // to nothing.
    //
    options.strategy = [];
  } else if (!options.strategy.length) {
    options.strategy.push('disconnect', 'online');

    //
    // Timeout based reconnection should only be enabled conditionally. When
    // authorization is enabled it could trigger.
    //
    if (!this.authorization) options.strategy.push('timeout');
  }

  options.strategy = options.strategy.join(',').toLowerCase();

  //
  // Force the use of WebSockets, even when we've detected some potential
  // broken WebSocket implementation.
  //
  if ('websockets' in options) {
    primus.AVOID_WEBSOCKETS = !options.websockets;
  }

  //
  // Force or disable the use of NETWORK events as leading client side
  // disconnection detection.
  //
  if ('network' in options) {
    primus.NETWORK_EVENTS = options.network;
  }

  //
  // Check if the user wants to manually initialise a connection. If they don't,
  // we want to do it after a really small timeout so we give the users enough
  // time to listen for `error` events etc.
  //
  if (!options.manual) primus.timers.setTimeout('open', function open() {
    primus.timers.clear('open');
    primus.open();
  }, 0);

  primus.initialise(options);
}
Primus is a real-time library agnostic framework for establishing real-time
connections with servers.

Options:
- reconnect, configuration for the reconnect process.
- manual, don't automatically call `.open` to start the connection.
- websockets, force the use of WebSockets, even when you should avoid them.
- timeout, connect timeout, server didn't respond in a timely manner.
- pingTimeout, The maximum amount of time to wait for the server to send a ping.
- network, Use network events as leading method for network connection drops.
- strategy, Reconnection strategies.
- transport, Transport options.
- url, uri, The URL to use connect with the server.

@constructor
@param {String} url The URL of your server.
@param {Object} options The configuration.
@api public