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

  this.fuse();

  if ('object' !== typeof server) {
    var message = 'The first argument of the constructor must be ' +
      'an HTTP or HTTPS server instance';
    throw new PrimusError(message, this);
  }

  options = options || {};
  options.maxLength = options.maxLength || 10485760;  // Maximum allowed packet size.
  options.transport = options.transport || {};        // Transformer specific options.
  options.pingInterval = 'pingInterval' in options    // Heartbeat interval.
    ? options.pingInterval
    : 30000;

  if ('timeout' in options) {
    throw new PrimusError('The `timeout` option has been removed', this);
  }

  var primus = this
    , key;

  this.auth = options.authorization || null;  // Do we have an authorization handler.
  this.connections = Object.create(null);     // Connection storage.
  this.ark = Object.create(null);             // Plugin storage.
  this.layers = [];                           // Middleware layers.
  this.heartbeatInterval = null;              // The heartbeat interval.
  this.transformer = null;                    // Reference to the real-time engine instance.
  this.encoder = null;                        // Shorthand to the parser's encoder.
  this.decoder = null;                        // Shorthand to the parser's decoder.
  this.connected = 0;                         // Connection counter.
  this.whitelist = [];                        // Forwarded-for white listing.
  this.options = options;                     // The configuration.
  this.transformers = {                       // Message transformers.
    outgoing: [],
    incoming: []
  };

  this.server = server;
  this.pathname = 'string' === typeof options.pathname
    ? options.pathname.charAt(0) !== '/'
      ? '/'+ options.pathname
      : options.pathname
    : '/primus';

  //
  // Create a specification file with the information that people might need to
  // connect to the server.
  //
  this.spec = {
    pingInterval: options.pingInterval,
    pathname: this.pathname,
    version: this.version
  };

  //
  // Create a pre-bound Spark constructor. Doing a Spark.bind(Spark, this) doesn't
  // work as we cannot extend the constructor of it anymore. The added benefit of
  // approach listed below is that the prototype extensions are only applied to
  // the Spark of this Primus instance.
  //
  this.Spark = function Sparky(headers, address, query, id, request, socket) {
    Spark.call(this, primus, headers, address, query, id, request, socket);
  };

  this.Spark.prototype = Object.create(Spark.prototype, {
    constructor: {
      configurable: true,
      value: this.Spark,
      writable: true
    },
    __initialise: {
      value: Spark.prototype.__initialise.slice(),
      configurable: true,
      writable: true
    }
  });

  //
  // Copy over the original Spark static properties and methods so readable and
  // writable can also be used.
  //
  for (key in Spark) {
    this.Spark[key] = Spark[key];
  }

  this.parsers(options.parser);
  this.initialise(options.transformer, options);

  //
  // If the plugins are supplied through the options, also initialise them.
  // This also allows us to use plugins when creating a client constructor
  // with the `Primus.createSocket({})` method.
  //
  if ('string' === typeof options.plugin) {
    options.plugin.split(/[, ]+/).forEach(function register(name) {
      primus.plugin(name, name);
    });
  } else if ('object' === typeof options.plugin) {
    for (key in options.plugin) {
      this.plugin(key, options.plugin[key]);
    }
  }

  //
  // - Cluster node 0.10 lets the Operating System decide to which worker a request
  //   goes. This can result in a not even distribution where some workers are
  //   used at 10% while others at 90%. In addition to that the load balancing
  //   isn't sticky.
  //
  // - Cluster node 0.12 implements a custom round robin algorithm. This solves the
  //   not even distribution of work but it does not address our sticky session
  //   requirement.
  //
  // Projects like `sticky-session` attempt to implement sticky sessions but they
  // are using `net` server instead of a HTTP server in combination with the
  // remoteAddress of the connection to load balance. This does not work when you
  // address your servers behind a load balancer as the IP is set to the load
  // balancer, not the connecting clients. All in all, it only causes more
  // scalability problems. So we've opted-in to warn users about the
  // risks of using Primus in a cluster.
  //
  if (!options.iknowclusterwillbreakconnections && require('cluster').isWorker) [
    '',
    'The `cluster` module does not implement sticky sessions. Learn more about',
    'this issue at:',
    '',
    'http://github.com/primus/primus#can-i-use-cluster',
    ''
  ].forEach(function warn(line) {
    console.error('Primus: '+ line);
  });
}
Primus is a universal wrapper for real-time frameworks that provides a common
interface for server and client interaction.

@constructor
@param {HTTP.Server} server HTTP or HTTPS server instance.
@param {Object} options Configuration
@api public