⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 localoutgoingserversession.java

📁 openfire 服务器源码下载
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/**
 * $RCSfile: $
 * $Revision: $
 * $Date: $
 *
 * Copyright (C) 2008 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Public License (GPL),
 * a copy of which is included in this distribution, or a commercial license
 * agreement with Jive.
 */

package org.jivesoftware.openfire.session;

import com.jcraft.jzlib.JZlib;
import com.jcraft.jzlib.ZInputStream;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.*;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.net.DNSUtil;
import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.server.OutgoingServerSocketReader;
import org.jivesoftware.openfire.server.RemoteServerConfiguration;
import org.jivesoftware.openfire.server.RemoteServerManager;
import org.jivesoftware.openfire.server.ServerDialback;
import org.jivesoftware.openfire.spi.BasicStreamIDFactory;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.StringUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmpp.packet.*;

import javax.net.ssl.SSLHandshakeException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.regex.Pattern;

/**
 * Server-to-server communication is done using two TCP connections between the servers. One
 * connection is used for sending packets while the other connection is used for receiving packets.
 * The <tt>OutgoingServerSession</tt> represents the connection to a remote server that will only
 * be used for sending packets.<p>
 *
 * Currently only the Server Dialback method is being used for authenticating with the remote
 * server. Use {@link #authenticateDomain(String, String)} to create a new connection to a remote
 * server that will be used for sending packets to the remote server from the specified domain.
 * Only the authenticated domains with the remote server will be able to effectively send packets
 * to the remote server. The remote server will reject and close the connection if a
 * non-authenticated domain tries to send a packet through this connection.<p>
 *
 * Once the connection has been established with the remote server and at least a domain has been
 * authenticated then a new route will be added to the routing table for this connection. For
 * optimization reasons the same outgoing connection will be used even if the remote server has
 * several hostnames. However, different routes will be created in the routing table for each
 * hostname of the remote server.
 *
 * @author Gaston Dombiak
 */
public class LocalOutgoingServerSession extends LocalSession implements OutgoingServerSession {

    /**
     * Regular expression to ensure that the hostname contains letters.
     */
    private static Pattern pattern = Pattern.compile("[a-zA-Z]");

    private Collection<String> authenticatedDomains = new HashSet<String>();
    private final Collection<String> hostnames = new HashSet<String>();
    private OutgoingServerSocketReader socketReader;
    /**
     * Flag that indicates if the session was created usign server-dialback.
     */
    private boolean usingServerDialback = true;

    /**
     * Creates a new outgoing connection to the specified hostname if no one exists. The port of
     * the remote server could be configured by setting the <b>xmpp.server.socket.remotePort</b>
     * property or otherwise the standard port 5269 will be used. Either a new connection was
     * created or already existed the specified hostname will be authenticated with the remote
     * server. Once authenticated the remote server will start accepting packets from the specified
     * domain.<p>
     *
     * The Server Dialback method is currently the only implemented method for server-to-server
     * authentication. This implies that the remote server will ask the Authoritative Server
     * to verify the domain to authenticate. Most probably this server will act as the
     * Authoritative Server. See {@link IncomingServerSession} for more information.
     *
     * @param domain the local domain to authenticate with the remote server.
     * @param hostname the hostname of the remote server.
     * @return True if the domain was authenticated by the remote server.
     */
    public static boolean authenticateDomain(String domain, String hostname) {
        if (hostname == null || hostname.length() == 0 || hostname.trim().indexOf(' ') > -1) {
            // Do nothing if the target hostname is empty, null or contains whitespaces
            return false;
        }
        try {
            // Check if the remote hostname is in the blacklist
            if (!RemoteServerManager.canAccess(hostname)) {
                return false;
            }

            OutgoingServerSession session;
            // Check if a session, that is using server dialback, already exists to the desired
            // hostname (i.e. remote server). If no one exists then create a new session. The same
            // session will be used for the same hostname for all the domains to authenticate
            SessionManager sessionManager = SessionManager.getInstance();
            if (sessionManager == null) {
                // Server is shutting down while we are trying to create a new s2s connection
                return false;
            }
            session = sessionManager.getOutgoingServerSession(hostname);
            if (session == null) {
                // Try locating if the remote server has previously authenticated with this server
                for (IncomingServerSession incomingSession : sessionManager.getIncomingServerSessions(hostname)) {
                    for (String otherHostname : incomingSession.getValidatedDomains()) {
                        session = sessionManager.getOutgoingServerSession(otherHostname);
                        if (session != null) {
                            if (session.isUsingServerDialback()) {
                                // A session to the same remote server but with different hostname
                                // was found. Use this session.
                                break;
                            } else {
                                session = null;
                            }
                        }
                    }
                }
            }
            if (session == null) {
                int port = RemoteServerManager.getPortForServer(hostname);
                // No session was found to the remote server so make sure that only one is created
                session = sessionManager.getOutgoingServerSession(hostname);
                if (session == null) {
                    session = createOutgoingSession(domain, hostname, port);
                    if (session != null) {
                        // Add the validated domain as an authenticated domain
                        session.addAuthenticatedDomain(domain);
                        // Add the new hostname to the list of names that the server may have
                        session.addHostname(hostname);
                        // Notify the SessionManager that a new session has been created
                        sessionManager.outgoingServerSessionCreated((LocalOutgoingServerSession) session);
                        return true;
                    } else {
                        // Ensure that the hostname is not an IP address (i.e. contains chars)
                        if (!pattern.matcher(hostname).find()) {
                            return false;
                        }
                        // Check if hostname is a subdomain of an existing outgoing session
                        for (String otherHost : sessionManager.getOutgoingServers()) {
                            if (hostname.contains(otherHost)) {
                                session = sessionManager.getOutgoingServerSession(otherHost);
                                // Add the new hostname to the found session
                                session.addHostname(hostname);
                                return true;
                            }
                        }
                        // Try to establish a connection to candidate hostnames. Iterate on the
                        // substring after the . and try to establish a connection. If a
                        // connection is established then the same session will be used for
                        // sending packets to the "candidate hostname" as well as for the
                        // requested hostname (i.e. the subdomain of the candidate hostname)
                        // This trick is useful when remote servers haven't registered in their
                        // DNSs an entry for their subdomains
                        int index = hostname.indexOf('.');
                        while (index > -1 && index < hostname.length()) {
                            String newHostname = hostname.substring(index + 1);
                            String serverName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
                            if ("com".equals(newHostname) || "net".equals(newHostname) ||
                                    "org".equals(newHostname) ||
                                    "gov".equals(newHostname) ||
                                    "edu".equals(newHostname) ||
                                    serverName.equals(newHostname)) {
                                return false;
                            }
                            session = createOutgoingSession(domain, newHostname, port);
                            if (session != null) {
                                // Add the validated domain as an authenticated domain
                                session.addAuthenticatedDomain(domain);
                                // Add the new hostname to the list of names that the server may have
                                session.addHostname(hostname);
                                // Add the new hostname to the found session
                                session.addHostname(newHostname);
                                // Notify the SessionManager that a new session has been created
                                sessionManager.outgoingServerSessionCreated((LocalOutgoingServerSession) session);
                                return true;
                            } else {
                                index = hostname.indexOf('.', index + 1);
                            }
                        }
                        return false;
                    }
                }
            }
            // A session already exists. The session was established using server dialback so
            // it is possible to do piggybacking to authenticate more domains
            if (session.getAuthenticatedDomains().contains(domain) && session.getHostnames().contains(hostname)) {
                // Do nothing since the domain has already been authenticated
                return true;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -