public ClientSessionConnection(
     String connectionManagerName, String hostName, String hostAddress) {
   this.connectionManagerName = connectionManagerName;
   multiplexerManager = ConnectionMultiplexerManager.getInstance();
   serverName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
   this.hostName = hostName;
   this.hostAddress = hostAddress;
 }
 @Override
 public String getHostName() throws UnknownHostException {
   if (hostName != null) {
     return hostName;
   }
   // Return IP address of the connection manager that the client used to log in
   ConnectionMultiplexerSession multiplexerSession =
       multiplexerManager.getMultiplexerSession(connectionManagerName);
   if (multiplexerSession != null) {
     return multiplexerSession.getHostName();
   }
   return null;
 }
 /**
  * If the Connection Manager or the Client requested to close the connection then just do nothing.
  * But if the server originated the request to close the connection then we need to send to the
  * Connection Manager a packet letting him know that the Client Session needs to be terminated.
  */
 @Override
 public void closeVirtualConnection() {
   // Figure out who requested the connection to be closed
   String streamID = session.getStreamID().getID();
   if (multiplexerManager.getClientSession(connectionManagerName, streamID) == null) {
     // Client or Connection manager requested to close the session
     // Do nothing since it has already been removed and closed
   } else {
     ConnectionMultiplexerSession multiplexerSession =
         multiplexerManager.getMultiplexerSession(connectionManagerName, streamID);
     if (multiplexerSession != null) {
       // Server requested to close the client session so let the connection manager
       // know that he has to finish the client session
       IQ closeRequest = new IQ(IQ.Type.set);
       closeRequest.setFrom(serverName);
       closeRequest.setTo(connectionManagerName);
       Element child =
           closeRequest.setChildElement("session", "http://jabber.org/protocol/connectionmanager");
       child.addAttribute("id", streamID);
       child.addElement("close");
       multiplexerSession.process(closeRequest);
     }
   }
 }
 /**
  * Delivers the packet to the Connection Manager that in turn will forward it to the target user.
  * Connection Managers may have one or many connections to the server so just get any connection
  * to the Connection Manager (uses a random) and use it.
  *
  * <p>If the packet to send does not have a TO attribute then wrap the packet with a special IQ
  * packet. The wrapper IQ packet will be sent to the Connection Manager and the stream ID of this
  * Client Session will be used for identifying that the wrapped packet must be sent to the
  * connected user. Since some packets can be exchanged before the user has a binded JID we need to
  * use the stream ID as the unique identifier.
  *
  * @param packet the packet to send to the user.
  */
 @Override
 public void deliver(Packet packet) {
   String streamID = session.getStreamID().getID();
   ConnectionMultiplexerSession multiplexerSession =
       multiplexerManager.getMultiplexerSession(connectionManagerName, streamID);
   if (multiplexerSession != null) {
     // Wrap packet so that the connection manager can figure out the target session
     Route wrapper = new Route(streamID);
     wrapper.setFrom(serverName);
     wrapper.setTo(connectionManagerName);
     wrapper.setChildElement(packet.getElement().createCopy());
     // Deliver wrapper
     multiplexerSession.process(wrapper);
     session.incrementServerPacketCount();
   }
 }
 /**
  * Delivers the stanza to the Connection Manager that in turn will forward it to the target user.
  * Connection Managers may have one or many connections to the server so just get any connection
  * to the Connection Manager (uses a random) and use it.
  *
  * <p>The stanza to send wrapped with a special IQ packet. The wrapper IQ packet will be sent to
  * the Connection Manager and the stream ID of this Client Session will be used for identifying
  * that the wrapped stanza must be sent to the connected user.
  *
  * @param text the stanza to send to the user.
  */
 @Override
 public void deliverRawText(String text) {
   String streamID = session.getStreamID().getID();
   ConnectionMultiplexerSession multiplexerSession =
       multiplexerManager.getMultiplexerSession(connectionManagerName, streamID);
   if (multiplexerSession != null) {
     // Wrap packet so that the connection manager can figure out the target session
     StringBuilder sb = new StringBuilder(200 + text.length());
     sb.append("<route from=\"").append(serverName);
     sb.append("\" to=\"").append(connectionManagerName);
     sb.append("\" streamid=\"").append(streamID).append("\">");
     sb.append(text);
     sb.append("</route>");
     // Deliver the wrapped stanza
     multiplexerSession.deliverRawText(sb.toString());
   }
 }