User = function (socket) {
    var self = this;
    // Set socket and the approprate handlers

    this.socket = socket;

    // groups that the user is in.
    /**
     * @private
     */
    this.groups = {};

    // the user's ScopeTable
    /**
     * @private
     */
    this.scopeTable = new ScopeTable();

    /**
     * @name User#user
     * @namespace Contains properties unique to each user. Can be used
     * to store information that should not be exposed to the
     * connected user.
     * @see User

     * @property {String} clientId The user's ID, as created by
     * Socket.IO.
     * @property {Object} cookie The user's cookie, as determined by
     * Socket.IO.
     * @property {Object} session The user's session, as created by express/connect. Value is undefined if no session object exists in the http server.
     */
    this.user = {
      clientId: socket.id,
      cookie: nowUtil.parseCookie(socket.handshake.headers.cookie)
    };

    // Populate session by parsing cookie
    var cookie = this.user.cookie[nowjs.options['cookieKey']];
    if (cookie) {
      this.user.session = nowjs.sessions[unescape(cookie)];
    }

    // set to true upon first replaceVar and emit connect event
    /**
     * @private
     */
    this.ready = false;

    /**
     * @name User#now
     * @namespace Synchronized with the connected user's local now
     * namespace; function calls with respect to this namespace will
     * only be executed for the current user.
     * @see User
     * @see User#user

     * @example everyone.now.prop = 42;
     * @example everyone.now.func = function () {
     *  console.log('hello!');
     * };
     */
    this.now = Proxy.wrap(this);

    // Remote function call handler
    socket.on('rfc', function rfcHandler(data) {
      var theFunction;
      if (data.fqn.split('_')[0] === 'closure') {
        theFunction = nowjs.closures[data.fqn];
      } else {
        theFunction = self.get(data.fqn);
      }
      var args = data.args;
      
      if (typeof args.length !== 'number' ||
        args.propertyIsEnumerable('length') ||
        typeof args.splice !== 'function') 
      {
         throw new Error('RFC with bad type');
         return;
      } 
      
      // Convert any remote function stubs into remote functions
      var user;
      for (var i = 0, ll = args.length; i < ll; i++) {
        if (nowUtil.hasProperty(args[i], 'fqn')) {
          user = nowUtil.clone(self, {fqn: args[i].fqn});
          args[i] = fn.remotecall.bind(user);
        }
      }
      theFunction.apply(self, args);
    });

    // Replace var handler
    if (nowjs.options.clientWrite) {
      socket.on('rv', function rvHandler(data) {
        var keys = Object.keys(data);
        var everyone = nowjs.getGroup('everyone');
        var fqn, user, value;
        for (var i = 0, ll = keys.length; i < ll ; i++) {
          fqn = keys[i];
          value = data[fqn];
          user = nowUtil.clone(self);
          user.fqn = fqn;
          if (nowUtil.hasProperty(value, 'fqn')) {
            value = fn.remotecall.bind(user);
          }
          // Set directly in scope table to avoid extra processing and
          // socket firing.
          self.scopeTable.set(fqn, (value && typeof value === 'object') ? [] : value);
          if (typeof value === 'function' &&
              everyone.scopeTable.get(fqn) === undefined) {
            everyone.scopeTable.set(fqn, nowUtil.noop);
          }
          if (Array.isArray(value)) {
            self.scopeTable.flagAsArray(fqn, 0);
          }
        }
      });

      // Variable deletion handler
      socket.on('del', function rfcHandler(data) {
        // Takes an array of fqns to delete.
        // Note: Does not handle deleting something that's a group
        // property (would need to override somehow).
        for (var i = 0; i < data.length; i++) {
          // delete straight from scopeTable to bypass emitting 'del'.
          self.scopeTable.deleteVar(data[i]);
        }
      });
    }

    // Called after initial scope sent. Ready handler
    socket.on('rd', function rdHandler() {
      var user = nowUtil.clone(self, {'_events': nowjs._events});
      nowjs.emit.call(user, 'connect');
    });

    socket.on('disconnect', function () {
      var user = nowUtil.clone(self, {'_events': nowjs._events});

      // trigger 'disconnect' in all groups.
      for (var g = Object.keys(self.groups), ll = g.length; ll--;) {
        self.groups[g[ll]].removeUser(self.user.clientId);
      }
      nowjs.emit.call(user, 'disconnect');

      delete nowjs.users[self.user.clientId];
    });
  }
@name User
@class Represents an individual user connected to the now
server. Exposed as the context in which group.now functions are
called, as well as the context in which the callback to
nowjs.getClient is executed. Each user has the {@link User#now}
and {@link User#user} namespaces.
@see Group#addUser
@see Group#removeUser
@see nowjs#getClient
@property {Socket} socket The user's Socket.IO socket.