Search in sources :

Example 11 with DomainPair

use of org.jivesoftware.openfire.session.DomainPair in project Openfire by igniterealtime.

the class RoutingTableImpl method addComponentRoute.

@Override
public void addComponentRoute(JID route, RoutableChannelHandler destination) {
    DomainPair pair = new DomainPair("", route.getDomain());
    String address = route.getDomain();
    localRoutingTable.addRoute(pair, destination);
    Lock lock = componentsCache.getLock(address);
    lock.lock();
    try {
        HashSet<NodeID> nodes = componentsCache.get(address);
        if (nodes == null) {
            nodes = new HashSet<>();
        }
        nodes.add(server.getNodeID());
        componentsCache.put(address, nodes);
    } finally {
        lock.unlock();
    }
}
Also used : DomainPair(org.jivesoftware.openfire.session.DomainPair) NodeID(org.jivesoftware.openfire.cluster.NodeID) Lock(java.util.concurrent.locks.Lock)

Example 12 with DomainPair

use of org.jivesoftware.openfire.session.DomainPair in project Openfire by igniterealtime.

the class RoutingTableImpl method addClientRoute.

@Override
public boolean addClientRoute(JID route, LocalClientSession destination) {
    boolean added;
    boolean available = destination.getPresence().isAvailable();
    Log.debug("Adding client route {}", route);
    localRoutingTable.addRoute(new DomainPair("", route.toString()), destination);
    final ClientRoute newClientRoute = new ClientRoute(server.getNodeID(), available);
    if (destination.getAuthToken().isAnonymous()) {
        Lock lockAn = anonymousUsersCache.getLock(route.toString());
        lockAn.lock();
        try {
            added = anonymousUsersCache.put(route.toString(), newClientRoute) == null;
        } finally {
            lockAn.unlock();
        }
        // Add the session to the list of user sessions
        if (route.getResource() != null && (!available || added)) {
            Lock lock = usersSessionsCache.getLock(route.toBareJID());
            lock.lock();
            try {
                usersSessionsCache.put(route.toBareJID(), new HashSet<>(Collections.singletonList(route.toString())));
            } finally {
                lock.unlock();
            }
        }
    } else {
        Lock lockU = usersCache.getLock(route.toString());
        lockU.lock();
        try {
            Log.debug("Adding client route {} to users cache under key {}", newClientRoute, route);
            added = usersCache.put(route.toString(), newClientRoute) == null;
        } finally {
            lockU.unlock();
        }
        // Add the session to the list of user sessions
        if (route.getResource() != null && (!available || added)) {
            Lock lock = usersSessionsCache.getLock(route.toBareJID());
            lock.lock();
            try {
                HashSet<String> jids = usersSessionsCache.get(route.toBareJID());
                if (jids == null) {
                    jids = new HashSet<>();
                }
                jids.add(route.toString());
                usersSessionsCache.put(route.toBareJID(), jids);
            } finally {
                lock.unlock();
            }
        }
    }
    return added;
}
Also used : DomainPair(org.jivesoftware.openfire.session.DomainPair) Lock(java.util.concurrent.locks.Lock)

Example 13 with DomainPair

use of org.jivesoftware.openfire.session.DomainPair in project Openfire by igniterealtime.

the class RoutingTableImpl method joinedCluster.

@Override
public void joinedCluster() {
    // The local node joined a cluster.
    // 
    // Upon joining a cluster, clustered caches are reset to their clustered equivalent (by the swap from the local
    // cache implementation to the clustered cache implementation that's done in the implementation of
    // org.jivesoftware.util.cache.CacheFactory.joinedCluster). This means that they now hold data that's
    // available on all other cluster nodes. Data that's available on the local node needs to be added again.
    restoreCacheContent();
    Log.debug("Add the entry listeners to the corresponding caches.");
    // Register a cache entry event listeners that will collect data for entries added by all other cluster nodes,
    // which is intended to be used (only) in the event of a cluster split.
    final ClusteredCacheEntryListener<String, ClientRoute> userCacheEntryListener = new ReverseLookupUpdatingCacheEntryListener<>(routeOwnersByClusterNode);
    final ClusteredCacheEntryListener<DomainPair, NodeID> serversCacheEntryListener = new ReverseLookupUpdatingCacheEntryListener<>(s2sDomainPairsByClusterNode);
    final ClusteredCacheEntryListener<String, HashSet<NodeID>> componentsCacheEntryListener = new ReverseLookupComputingCacheEntryListener<>(componentsByClusterNode, nodeIDS -> nodeIDS.stream().filter(n -> !n.equals(XMPPServer.getInstance().getNodeID())).collect(Collectors.toSet()));
    // Note that, when #joinedCluster() fired, the cache will _always_ have been replaced, meaning that it won't
    // have old event listeners. When #leaveCluster() fires, the cache will be destroyed. This takes away the need
    // to explicitly deregister the listener in that case.
    // Ensure that event listeners have been registered with the caches, before starting to simulate 'entryAdded' events,
    // to prevent the possibility of having entries that are missed by the simulation because of bad timing.
    usersCache.addClusteredCacheEntryListener(userCacheEntryListener, false, false);
    anonymousUsersCache.addClusteredCacheEntryListener(userCacheEntryListener, false, false);
    serversCache.addClusteredCacheEntryListener(serversCacheEntryListener, false, false);
    componentsCache.addClusteredCacheEntryListener(componentsCacheEntryListener, true, true);
    // This is not necessary for the usersSessions cache, because its content is being managed while the content
    // of users cache and anonymous users cache is being managed.
    Log.debug("Simulate 'entryAdded' for all data that already exists elsewhere in the cluster.");
    Stream.concat(usersCache.entrySet().stream(), anonymousUsersCache.entrySet().stream()).filter(entry -> !entry.getValue().getNodeID().equals(XMPPServer.getInstance().getNodeID())).forEach(entry -> userCacheEntryListener.entryAdded(entry.getKey(), entry.getValue(), entry.getValue().getNodeID()));
    serversCache.entrySet().stream().filter(entry -> !entry.getValue().equals(XMPPServer.getInstance().getNodeID())).forEach(entry -> serversCacheEntryListener.entryAdded(entry.getKey(), entry.getValue(), entry.getValue()));
    componentsCache.entrySet().forEach(entry -> {
        entry.getValue().forEach(nodeIdForComponent -> {
            // Iterate over all node ids on which the component is known
            if (!nodeIdForComponent.equals(XMPPServer.getInstance().getNodeID())) {
                // Here we pretend that the component has been added by the node id on which it is reported to
                // be available. This might not have been the case, but it is probably accurate. An alternative
                // approach is not easily available.
                componentsCacheEntryListener.entryAdded(entry.getKey(), entry.getValue(), nodeIdForComponent);
            }
        });
    });
    // Broadcast presence of local sessions to remote sessions when subscribed to presence.
    // Probe presences of remote sessions when subscribed to presence of local session.
    // Send pending subscription requests to local sessions from remote sessions.
    // Deliver offline messages sent to local sessions that were unavailable in other nodes.
    // Send available presences of local sessions to other resources of the same user.
    PresenceUpdateHandler presenceUpdateHandler = XMPPServer.getInstance().getPresenceUpdateHandler();
    for (LocalClientSession session : localRoutingTable.getClientRoutes()) {
        // Simulate that the local session has just become available
        session.setInitialized(false);
        // Simulate that current session presence has just been received
        presenceUpdateHandler.process(session.getPresence());
    }
// TODO OF-2067: the above also (re)generates events on the local node, where these events had already occurred. Ideally, that should not happen.
// TODO OF-2066: shouldn't a similar action be done on the other nodes, so that the node that just joined gets informed about all sessions living on other cluster nodes?
}
Also used : Presence(org.xmpp.packet.Presence) LocalClientSession(org.jivesoftware.openfire.session.LocalClientSession) Forwarded(org.jivesoftware.openfire.forward.Forwarded) ClientSession(org.jivesoftware.openfire.session.ClientSession) Received(org.jivesoftware.openfire.carbons.Received) BasicModule(org.jivesoftware.openfire.container.BasicModule) CacheFactory(org.jivesoftware.util.cache.CacheFactory) ClusteredCacheEntryListener(org.jivesoftware.openfire.cluster.ClusteredCacheEntryListener) LoggerFactory(org.slf4j.LoggerFactory) JiveGlobals(org.jivesoftware.util.JiveGlobals) MessageRouter(org.jivesoftware.openfire.MessageRouter) ReverseLookupUpdatingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupUpdatingCacheEntryListener) PresenceUpdateHandler(org.jivesoftware.openfire.handler.PresenceUpdateHandler) Message(org.xmpp.packet.Message) OutgoingServerSession(org.jivesoftware.openfire.session.OutgoingServerSession) CacheUtil(org.jivesoftware.util.cache.CacheUtil) RemoteServerManager(org.jivesoftware.openfire.server.RemoteServerManager) Cache(org.jivesoftware.util.cache.Cache) RoutingTable(org.jivesoftware.openfire.RoutingTable) PresenceRouter(org.jivesoftware.openfire.PresenceRouter) ClusterManager(org.jivesoftware.openfire.cluster.ClusterManager) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Collectors(java.util.stream.Collectors) Stream(java.util.stream.Stream) ConnectionSettings(org.jivesoftware.openfire.session.ConnectionSettings) RemoteSessionLocator(org.jivesoftware.openfire.session.RemoteSessionLocator) java.util(java.util) PacketException(org.jivesoftware.openfire.PacketException) Multimap(com.google.common.collect.Multimap) ReverseLookupComputingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupComputingCacheEntryListener) JID(org.xmpp.packet.JID) Function(java.util.function.Function) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) ConcurrentMap(java.util.concurrent.ConcurrentMap) NodeID(org.jivesoftware.openfire.cluster.NodeID) XMPPServer(org.jivesoftware.openfire.XMPPServer) RoutableChannelHandler(org.jivesoftware.openfire.RoutableChannelHandler) RemotePacketRouter(org.jivesoftware.openfire.RemotePacketRouter) ClusterEventListener(org.jivesoftware.openfire.cluster.ClusterEventListener) DomainPair(org.jivesoftware.openfire.session.DomainPair) LocalOutgoingServerSession(org.jivesoftware.openfire.session.LocalOutgoingServerSession) Logger(org.slf4j.Logger) ConsistencyChecks(org.jivesoftware.util.cache.ConsistencyChecks) ExternalComponentManager(org.jivesoftware.openfire.component.ExternalComponentManager) AtomicLong(java.util.concurrent.atomic.AtomicLong) Lock(java.util.concurrent.locks.Lock) Packet(org.xmpp.packet.Packet) OutgoingSessionPromise(org.jivesoftware.openfire.server.OutgoingSessionPromise) Element(org.dom4j.Element) QName(org.dom4j.QName) IQRouter(org.jivesoftware.openfire.IQRouter) IQ(org.xmpp.packet.IQ) ReverseLookupUpdatingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupUpdatingCacheEntryListener) PresenceUpdateHandler(org.jivesoftware.openfire.handler.PresenceUpdateHandler) LocalClientSession(org.jivesoftware.openfire.session.LocalClientSession) DomainPair(org.jivesoftware.openfire.session.DomainPair) NodeID(org.jivesoftware.openfire.cluster.NodeID) ReverseLookupComputingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupComputingCacheEntryListener)

Example 14 with DomainPair

use of org.jivesoftware.openfire.session.DomainPair in project Openfire by igniterealtime.

the class S2STestService method run.

/**
 * Run a test against the domain.
 * @return K-V pairs of debug information.
 * @throws Exception On error.
 */
public Map<String, String> run() throws Exception {
    waitUntil = new Semaphore(0);
    Map<String, String> results = new HashMap<>();
    final DomainPair pair = new DomainPair(XMPPServer.getInstance().getServerInfo().getXMPPDomain(), domain);
    // Tear down existing routes.
    final SessionManager sessionManager = SessionManager.getInstance();
    for (final Session incomingServerSession : sessionManager.getIncomingServerSessions(domain)) {
        incomingServerSession.close();
    }
    final Session outgoingServerSession = sessionManager.getOutgoingServerSession(pair);
    if (outgoingServerSession != null) {
        outgoingServerSession.close();
    }
    final IQ pingRequest = new IQ(Type.get);
    pingRequest.setChildElement("ping", IQPingHandler.NAMESPACE);
    pingRequest.setFrom(pair.getLocal());
    pingRequest.setTo(domain);
    // Intercept logging.
    final Writer logs = new StringWriter();
    final String appenderName = addAppender(logs);
    // Intercept packets.
    final PacketInterceptor interceptor = new S2SInterceptor(pingRequest);
    InterceptorManager.getInstance().addInterceptor(interceptor);
    // Send ping.
    try {
        Log.info("Sending server to server ping request to " + domain);
        XMPPServer.getInstance().getIQRouter().route(pingRequest);
        // Wait for success or exceed socket timeout.
        waitUntil.tryAcquire(RemoteServerManager.getSocketTimeout(), TimeUnit.MILLISECONDS);
        // Check on the connection status.
        logSessionStatus();
        // Prepare response.
        results.put("certs", getCertificates());
        results.put("stanzas", interceptor.toString());
        results.put("logs", logs.toString());
        return results;
    } finally {
        // Cleanup
        InterceptorManager.getInstance().removeInterceptor(interceptor);
        removeAppender(appenderName);
    }
}
Also used : StringWriter(java.io.StringWriter) DomainPair(org.jivesoftware.openfire.session.DomainPair) SessionManager(org.jivesoftware.openfire.SessionManager) IQ(org.xmpp.packet.IQ) Semaphore(java.util.concurrent.Semaphore) PacketInterceptor(org.jivesoftware.openfire.interceptor.PacketInterceptor) StringWriter(java.io.StringWriter) Writer(java.io.Writer) OutgoingServerSession(org.jivesoftware.openfire.session.OutgoingServerSession) Session(org.jivesoftware.openfire.session.Session)

Example 15 with DomainPair

use of org.jivesoftware.openfire.session.DomainPair in project Openfire by igniterealtime.

the class S2STestService method getCertificates.

/**
 * @return A String representation of the certificate chain for the connection to the domain under test.
 */
private String getCertificates() {
    final DomainPair pair = new DomainPair(XMPPServer.getInstance().getServerInfo().getXMPPDomain(), domain);
    Session session = XMPPServer.getInstance().getSessionManager().getOutgoingServerSession(pair);
    StringBuilder certs = new StringBuilder();
    if (session != null) {
        Log.info("Successfully negotiated TLS connection.");
        Certificate[] certificates = session.getPeerCertificates();
        for (Certificate certificate : certificates) {
            X509Certificate x509cert = (X509Certificate) certificate;
            certs.append("--\nSubject: ");
            certs.append(x509cert.getSubjectDN());
            List<String> subjectAltNames = new SANCertificateIdentityMapping().mapIdentity(x509cert);
            if (!subjectAltNames.isEmpty()) {
                certs.append("\nSubject Alternative Names: ");
                for (String subjectAltName : subjectAltNames) {
                    certs.append("\n  ");
                    certs.append(subjectAltName);
                }
            }
            certs.append("\nNot Before: ");
            certs.append(x509cert.getNotBefore());
            certs.append("\nNot After: ");
            certs.append(x509cert.getNotAfter());
            certs.append("\n\n-----BEGIN CERTIFICATE-----\n");
            certs.append(DatatypeConverter.printBase64Binary(certificate.getPublicKey().getEncoded()).replaceAll("(.{64})", "$1\n"));
            certs.append("\n-----END CERTIFICATE-----\n\n");
        }
    }
    return certs.toString();
}
Also used : DomainPair(org.jivesoftware.openfire.session.DomainPair) SANCertificateIdentityMapping(org.jivesoftware.util.cert.SANCertificateIdentityMapping) X509Certificate(java.security.cert.X509Certificate) OutgoingServerSession(org.jivesoftware.openfire.session.OutgoingServerSession) Session(org.jivesoftware.openfire.session.Session) X509Certificate(java.security.cert.X509Certificate) Certificate(java.security.cert.Certificate)

Aggregations

DomainPair (org.jivesoftware.openfire.session.DomainPair)15 NodeID (org.jivesoftware.openfire.cluster.NodeID)8 Lock (java.util.concurrent.locks.Lock)7 OutgoingServerSession (org.jivesoftware.openfire.session.OutgoingServerSession)6 AtomicLong (java.util.concurrent.atomic.AtomicLong)4 Element (org.dom4j.Element)4 PacketException (org.jivesoftware.openfire.PacketException)4 UnauthorizedException (org.jivesoftware.openfire.auth.UnauthorizedException)4 ClientSession (org.jivesoftware.openfire.session.ClientSession)4 LocalClientSession (org.jivesoftware.openfire.session.LocalClientSession)4 Session (org.jivesoftware.openfire.session.Session)4 Multimap (com.google.common.collect.Multimap)3 java.util (java.util)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 ConcurrentMap (java.util.concurrent.ConcurrentMap)3 Function (java.util.function.Function)3 Collectors (java.util.stream.Collectors)3 Stream (java.util.stream.Stream)3 QName (org.dom4j.QName)3 IQRouter (org.jivesoftware.openfire.IQRouter)3