@Override
  protected void processCommand(Packet packet) {
    BoshSession session = getBoshSession(packet.getTo());

    switch (packet.getCommand()) {
      case USER_LOGIN:
        String jid = Command.getFieldValue(packet, "user-jid");

        if (jid != null) {
          if (session != null) {
            try {
              BareJID fromJID = BareJID.bareJIDInstance(jid);
              BareJID hostJid = getSeeOtherHostForJID(fromJID, Phase.LOGIN);

              if (hostJid != null) {
                Element streamErrorElement =
                    see_other_host_strategy.getStreamError(
                        "urn:ietf:params:xml:ns:xmpp-streams", hostJid);
                Packet redirectPacket = Packet.packetInstance(streamErrorElement);

                redirectPacket.setPacketTo(packet.getTo());
                writePacketToSocket(redirectPacket);
                session.sendWaitingPackets();
                session.close();
                if (log.isLoggable(Level.FINE)) {
                  log.log(
                      Level.FINE,
                      "{0} : {1} ({2})",
                      new Object[] {
                        BOSH_OPERATION_TYPE.REMOVE, session.getSid(), "See other host"
                      });
                }
                sessions.remove(session.getSid());
              } else {
                session.setUserJid(jid);
              }
            } catch (TigaseStringprepException ex) {
              log.log(Level.SEVERE, "user JID violates RFC6122 (XMPP:Address Format): ", ex);
            }
          } else {
            if (log.isLoggable(Level.FINE)) {
              log.log(Level.FINE, "Missing XMPPIOService for USER_LOGIN command: {0}", packet);
            }
          }
        } else {
          log.log(Level.WARNING, "Missing user-jid for USER_LOGIN command: {0}", packet);
        }

        break;

      case CLOSE:
        if (session != null) {
          if (log.isLoggable(Level.FINER)) {
            log.log(Level.FINER, "Closing session for command CLOSE: {0}", session.getSid());
          }
          try {
            List<Element> err_el = packet.getElement().getChildrenStaticStr(Iq.IQ_COMMAND_PATH);

            if ((err_el != null) && (err_el.size() > 0)) {
              Element error = new Element("stream:error");

              error.addChild(err_el.get(0));

              Packet condition = Packet.packetInstance(error);

              condition.setPacketTo(packet.getTo());
              writePacketToSocket(condition);
              session.sendWaitingPackets();
              bosh_session_close_delay = 100;
            }
          } catch (TigaseStringprepException ex) {
            Logger.getLogger(BoshConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
          }
          if (bosh_session_close_delay > 0) {
            try {
              Thread.sleep(bosh_session_close_delay);
            } catch (InterruptedException ex) {

              // Intentionally left blank
            }
          }
          session.close();
          if (log.isLoggable(Level.FINE)) {
            log.log(
                Level.FINE,
                "{0} : {1} ({2})",
                new Object[] {
                  BOSH_OPERATION_TYPE.REMOVE, session.getSid(), "Closing session for command CLOSE"
                });
          }
          sessions.remove(session.getSid());
        } else {
          if (log.isLoggable(Level.FINE)) {
            log.log(Level.FINE, "Session does not exist for packet: {0}", packet);
          }
        }

        break;

      case CHECK_USER_CONNECTION:
        if (session != null) {

          // It's ok, the session has been found, respond with OK.
          addOutPacket(packet.okResult((String) null, 0));
        } else {

          // Session is no longer active, respond with an error.
          try {
            addOutPacket(
                Authorization.ITEM_NOT_FOUND.getResponseMessage(packet, "Connection gone.", false));
          } catch (PacketErrorTypeException e) {

            // Hm, error already, ignoring...
            log.log(Level.INFO, "Error packet is not really expected here: {0}", packet);
          }
        }

        break;

      default:
        super.processCommand(packet);

        break;
    } // end of switch (pc.getCommand())
  }
  protected Map<String, String> preBindSession(Map<String, String> attr) {
    String hostname = attr.get(TO_ATTR);

    Queue<Packet> out_results = new ArrayDeque<Packet>(2);

    BoshSession bs =
        new BoshSession(
            getDefVHostItem().getDomain(),
            JID.jidInstanceNS(routings.computeRouting(hostname)),
            this,
            sendNodeHostname ? getDefHostName().getDomain() : null,
            maxSessionWaitingPackets);

    String jid = attr.get(FROM_ATTR);
    String uuid = UUID.randomUUID().toString();
    JID userId = JID.jidInstanceNS(jid);
    if (null == userId.getResource()) {
      userId = userId.copyWithResourceNS(uuid);
      attr.put(FROM_ATTR, userId.toString());
      bs.setUserJid(jid);
    }
    long rid = (long) (Math.random() * 10000000);

    attr.put(RID_ATTR, Long.toString(rid));

    UUID sid = bs.getSid();
    sessions.put(sid, bs);
    if (log.isLoggable(Level.FINE)) {
      log.log(
          Level.FINE,
          "{0} : {1} ({2})",
          new Object[] {BOSH_OPERATION_TYPE.CREATE, bs.getSid(), "Pre-bind"});
    }

    attr.put(SID_ATTR, sid.toString());

    Packet p = null;
    try {
      Element el = new Element("body");
      el.setAttributes(attr);
      p = Packet.packetInstance(el);
    } catch (TigaseStringprepException ex) {
      Logger.getLogger(BoshConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
    }
    bs.init(
        p,
        null,
        max_wait,
        min_polling,
        max_inactivity,
        concurrent_requests,
        hold_requests,
        max_pause,
        max_batch_size,
        batch_queue_timeout,
        out_results,
        true);
    addOutPackets(out_results, bs);

    attr.put("hostname", getDefHostName().toString());

    return attr;
  }