docs: function Messages () {
    var self = this;
  
    if (!(this instanceof Messages)) return new Messages();
  
    events.EventEmitter.call(this);
  
    debug('new messages');
  
    /**
     * When a socket is accepted
     *
     * @param {object} socket
     */
  
    this.onConnection = function (socket) {
  
      debug('on connection %s', socket.id);
  
      /**
       * This is used to add listeners to sockets when the Messages.prototype.action()
       * method is invoked
       *
       * @param {string} name
       */
  
      function onAction (name) {
        debug('on action %s', name);
        if (socket.listeners(name).indexOf(self.onMessage) < 0) {
          socket.on(name, function () {
            debug('socket on %s', name);
            var args = Array.prototype.slice.call(arguments);
            self.onMessage(socket, [name].concat(args));
          });
        }
      }
     
      self.on('action', onAction);
  
      /*
       * take the current actions and set up handlers for them
       */
  
      if (self.actions()) {
        self.actions().forEach(onAction);
      }
  
  
      /*
       * when we disconnect we want to remove the handlers and the onAction
       * method
       */
  
      socket.on('disconnect', function () {
        debug('on disconnect %s', socket.id);
        self.removeListener('action', onAction);
        self.actions().forEach(function (name) {
          debug('removing listeners for %s', name);
          socket.removeAllListeners(name);
          debug('listener count %s for %s', socket.listeners(name).length, name);
        });
      });
  
    };
  
    /*
     * Called when we receive data from the socket
     * It will build up the actor, target, and content
     * to produce a json object that will be published
     * onto an publisher / event emitter
     */
  
    this.onMessage = function (socket, args) {
      debug('on message %s', socket.id);
      args = args || [];
      if (!args.length) return;
      var message, isMessage = false;
      if (args.length === 2 && args[1] && args[1].isMessage) {
        isMessage = true;
        message = Message(args[1]);  
      }
      else {
        message = Message();
      }
      message.action(args.shift());
      self.actor(socket, function (err, actor) {
        debug('on actor %s, %s', socket.id, actor);
        if (err) {
          return self.emit('error', err, socket, args);
        }
        message.actor(actor);
        self.target(socket, args, function (err, target) {
          debug('on target %s, %s', socket.id, actor);
          if (err) {
            return self.emit('error', err, socket, args);
          }
          message.target(target);
          if (!isMessage) message.content(args);
          self.emit('message', message, socket);
        });
      });
    };
  
    /*
     * the middleware fucntion we attach to socket.io. It looks for events and if
     * we have auto propagation turned on it will trigger events that are *not*
     * in the current action set.
     */
  
    this.middleware = function (socket, next) {
      debug('middleware invoked on socket %s', socket.id);
      socket.onevent = self.onSocketEvent;
      next();
    };
  
    /*
     * The function we override the onevent with.
     */
  
    // TODO lets use socket.io-events
  
    this.onSocketEvent = function(packet) {
      debug('on socket event for socket %s', this.id);
      var args = packet.data || [];
  
      if (null != packet.id) {
        args.push(this.ack(packet.id));
      }
  
      if (this.listeners(args[0]).length) {
        events.EventEmitter.prototype.emit.apply(this, args);
      }
      else if (self.autoPropagate()) {
        self.onMessage(this, args);
      }
  
    };
  
    this.setMaxListeners(0);
  }