All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jivesoftware.openfire.multiplex.ClientSessionConnection Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2005-2008 Jive Software. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jivesoftware.openfire.multiplex;

import org.dom4j.Element;
import org.jivesoftware.openfire.StreamID;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.net.VirtualConnection;
import org.jivesoftware.openfire.session.ConnectionMultiplexerSession;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Represents a connection of a Client Session that was established to a Connection Manager.
 * Connection Managers have their own physical connections to the server that are multiplexed
 * among connected clients. Each created {@link org.jivesoftware.openfire.session.ClientSession}
 * will use an instance of this class as its connection.
 *
 * @author Gaston Dombiak
 */
public class ClientSessionConnection extends VirtualConnection {

    private String connectionManagerName;
    private String serverName;
    private ConnectionMultiplexerManager multiplexerManager;
    private String hostName;
    private String hostAddress;

    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;
    }

    /**
     * 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.

* * 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) { StreamID streamID = session.getStreamID(); 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.

* * 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) { StreamID streamID = session.getStreamID(); 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(""); sb.append(text); sb.append(""); // Deliver the wrapped stanza multiplexerSession.deliverRawText(sb.toString()); } } @Override public ConnectionConfiguration getConfiguration() { // Here, a client-to-server configuration is mocked. It is likely not used, as actual connection handling takes // place at the connection manager. final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager()); return connectionManager.getListener( ConnectionType.SOCKET_C2S, true ).generateConnectionConfiguration(); } public byte[] getAddress() throws UnknownHostException { if (hostAddress != null) { return InetAddress.getByName(hostAddress).getAddress(); } return null; } @Override public String getHostAddress() throws UnknownHostException { if (hostAddress != null) { return hostAddress; } // Return IP address of the connection manager that the client used to log in ConnectionMultiplexerSession multiplexerSession = multiplexerManager.getMultiplexerSession(connectionManagerName); if (multiplexerSession != null) { return multiplexerSession.getHostAddress(); } return null; } @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; } @Override public void systemShutdown() { // Do nothing since a system-shutdown error will be sent to the Connection Manager // that in turn will send a system-shutdown to connected clients. This is an // optimization to reduce number of packets being sent from the server. } /** * 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 StreamID streamID = session.getStreamID(); 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.getID()); child.addElement("close"); multiplexerSession.process(closeRequest); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy