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();
}
}
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;
}
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?
}
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);
}
}
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();
}
Aggregations