📄 sessionmanager.java
字号:
* @param conn the connection to create the session from.
* @param id the streamID to use for the new session.
* @return a newly created session.
*/
public LocalClientSession createClientSession(Connection conn, StreamID id) {
if (serverName == null) {
throw new IllegalStateException("Server not initialized");
}
LocalClientSession session = new LocalClientSession(serverName, conn, id);
conn.init(session);
// Register to receive close notification on this session so we can
// remove and also send an unavailable presence if it wasn't
// sent before
conn.registerCloseListener(clientSessionListener, session);
// Add to pre-authenticated sessions.
localSessionManager.getPreAuthenticatedSessions().put(session.getAddress().getResource(), session);
// Increment the counter of user sessions
connectionsCounter.incrementAndGet();
return session;
}
public HttpSession createClientHttpSession(long rid, InetAddress address, StreamID id)
throws UnauthorizedException
{
if (serverName == null) {
throw new UnauthorizedException("Server not initialized");
}
PacketDeliverer backupDeliverer = server.getPacketDeliverer();
HttpSession session = new HttpSession(backupDeliverer, serverName, address, id, rid);
Connection conn = session.getConnection();
conn.init(session);
conn.registerCloseListener(clientSessionListener, session);
localSessionManager.getPreAuthenticatedSessions().put(session.getAddress().getResource(), session);
connectionsCounter.incrementAndGet();
return session;
}
public LocalComponentSession createComponentSession(JID address, Connection conn) {
if (serverName == null) {
throw new IllegalStateException("Server not initialized");
}
StreamID id = nextStreamID();
LocalComponentSession session = new LocalComponentSession(serverName, conn, id);
conn.init(session);
// Register to receive close notification on this session so we can
// remove the external component from the list of components
conn.registerCloseListener(componentSessionListener, session);
// Set the bind address as the address of the session
session.setAddress(address);
// Add to component session.
localSessionManager.getComponentsSessions().add(session);
// Keep track of the cluster node hosting the new external component
componentSessionsCache.put(address.toString(), server.getNodeID().toByteArray());
return session;
}
/**
* Creates a session for a remote server. The session should be created only after the
* remote server has been authenticated either using "server dialback" or SASL.
*
* @param conn the connection to the remote server.
* @param id the stream ID used in the stream element when authenticating the server.
* @return the newly created {@link IncomingServerSession}.
* @throws UnauthorizedException if the local server has not been initialized yet.
*/
public LocalIncomingServerSession createIncomingServerSession(Connection conn, StreamID id)
throws UnauthorizedException {
if (serverName == null) {
throw new UnauthorizedException("Server not initialized");
}
LocalIncomingServerSession session = new LocalIncomingServerSession(serverName, conn, id);
conn.init(session);
// Register to receive close notification on this session so we can
// remove its route from the sessions set
conn.registerCloseListener(incomingServerListener, session);
return session;
}
/**
* Notification message that a new OutgoingServerSession has been created. Register a listener
* that will react when the connection gets closed.
*
* @param session the newly created OutgoingServerSession.
*/
public void outgoingServerSessionCreated(LocalOutgoingServerSession session) {
// Register to receive close notification on this session so we can
// remove its route from the sessions set
session.getConnection().registerCloseListener(outgoingServerListener, session);
}
/**
* Registers that a server session originated by a remote server is hosting a given hostname.
* Notice that the remote server may be hosting several subdomains as well as virtual hosts so
* the same IncomingServerSession may be associated with many keys. If the remote server
* creates many sessions to this server (eg. one for each subdomain) then associate all
* the sessions with the originating server that created all the sessions.
*
* @param hostname the hostname that is being served by the remote server.
* @param session the incoming server session to the remote server.
*/
public void registerIncomingServerSession(String hostname, LocalIncomingServerSession session) {
// Keep local track of the incoming server session connected to this JVM
String streamID = session.getStreamID().getID();
localSessionManager.addIncomingServerSessions(streamID, session);
// Keep track of the nodeID hosting the incoming server session
incomingServerSessionsCache.put(streamID, server.getNodeID().toByteArray());
// Update list of sockets/sessions coming from the same remote hostname
Lock lock = CacheFactory.getLock(hostname, hostnameSessionsCache);
try {
lock.lock();
List<String> streamIDs = hostnameSessionsCache.get(hostname);
if (streamIDs == null) {
streamIDs = new ArrayList<String>();
}
streamIDs.add(streamID);
hostnameSessionsCache.put(hostname, streamIDs);
}
finally {
lock.unlock();
}
// Add to clustered cache
lock = CacheFactory.getLock(streamID, validatedDomainsCache);
try {
lock.lock();
Set<String> validatedDomains = validatedDomainsCache.get(streamID);
if (validatedDomains == null) {
validatedDomains = new HashSet<String>();
}
boolean added = validatedDomains.add(hostname);
if (added) {
validatedDomainsCache.put(streamID, validatedDomains);
}
} finally {
lock.unlock();
}
}
/**
* Unregisters the specified remote server session originiated by the specified remote server.
*
* @param hostname the hostname that is being served by the remote server.
* @param session the session to unregiser.
*/
public void unregisterIncomingServerSession(String hostname, IncomingServerSession session) {
// Remove local track of the incoming server session connected to this JVM
String streamID = session.getStreamID().getID();
localSessionManager.removeIncomingServerSessions(streamID);
// Remove track of the nodeID hosting the incoming server session
incomingServerSessionsCache.remove(streamID);
// Remove from list of sockets/sessions coming from the remote hostname
Lock lock = CacheFactory.getLock(hostname, hostnameSessionsCache);
try {
lock.lock();
List<String> streamIDs = hostnameSessionsCache.get(hostname);
if (streamIDs != null) {
streamIDs.remove(streamID);
if (streamIDs.isEmpty()) {
hostnameSessionsCache.remove(hostname);
}
else {
hostnameSessionsCache.put(hostname, streamIDs);
}
}
}
finally {
lock.unlock();
}
// Remove from clustered cache
lock = CacheFactory.getLock(streamID, validatedDomainsCache);
try {
lock.lock();
Set<String> validatedDomains = validatedDomainsCache.get(streamID);
if (validatedDomains == null) {
validatedDomains = new HashSet<String>();
}
validatedDomains.remove(hostname);
if (!validatedDomains.isEmpty()) {
validatedDomainsCache.put(streamID, validatedDomains);
}
else {
validatedDomainsCache.remove(streamID);
}
} finally {
lock.unlock();
}
}
/**
* Returns a collection with all the domains, subdomains and virtual hosts that where
* validated. The remote server is allowed to send packets from any of these domains,
* subdomains and virtual hosts.<p>
*
* Content is stored in a clustered cache so that even in the case of the node hosting
* the sessions is lost we can still have access to this info to be able to perform
* proper clean up logic.
*
* @param streamID id that uniquely identifies the session.
* @return domains, subdomains and virtual hosts that where validated.
*/
public Collection<String> getValidatedDomains(String streamID) {
Lock lock = CacheFactory.getLock(streamID, validatedDomainsCache);
try {
lock.lock();
Set<String> validatedDomains = validatedDomainsCache.get(streamID);
if (validatedDomains == null) {
return Collections.emptyList();
}
return Collections.unmodifiableCollection(validatedDomains);
} finally {
lock.unlock();
}
}
/**
* Add a new session to be managed. The session has been authenticated and resource
* binding has been done.
*
* @param session the session that was authenticated.
*/
public void addSession(LocalClientSession session) {
// Remove the pre-Authenticated session but remember to use the temporary ID as the key
localSessionManager.getPreAuthenticatedSessions().remove(session.getStreamID().toString());
// Add session to the routing table (routing table will know session is not available yet)
routingTable.addClientRoute(session.getAddress(), session);
SessionEventDispatcher.EventType event = session.getAuthToken().isAnonymous() ?
SessionEventDispatcher.EventType.anonymous_session_created :
SessionEventDispatcher.EventType.session_created;
// Fire session created event.
SessionEventDispatcher.dispatchEvent(session, event);
if (ClusterManager.isClusteringStarted()) {
// Track information about the session and share it with other cluster nodes
sessionInfoCache.put(session.getAddress().toString(), new ClientSessionInfo(session));
}
}
/**
* Notification message sent when a client sent an available presence for the session. Making
* the session available means that the session is now eligible for receiving messages from
* other clients. Sessions whose presence is not available may only receive packets (IQ packets)
* from the server. Therefore, an unavailable session remains invisible to other clients.
*
* @param session the session that receieved an available presence.
*/
public void sessionAvailable(LocalClientSession session) {
if (session.getAuthToken().isAnonymous()) {
// Anonymous session always have resources so we only need to add one route. That is
// the route to the anonymous session
routingTable.addClientRoute(session.getAddress(), session);
}
else {
// A non-anonymous session is now available
// Add route to the new session
routingTable.addClientRoute(session.getAddress(), session);
// Broadcast presence between the user's resources
broadcastPresenceOfOtherResource(session);
}
}
/**
* Sends the presences of other connected resources to the resource that just connected.
*
* @param session the newly created session.
*/
private void broadcastPresenceOfOtherResource(LocalClientSession session) {
Presence presence;
// Get list of sessions of the same user
JID searchJID = new JID(session.getAddress().getNode(), session.getAddress().getDomain(), null);
List<JID> addresses = routingTable.getRoutes(searchJID, null);
for (JID address : addresses) {
if (address.equals(session.getAddress())) {
continue;
}
// Send the presence of an existing session to the session that has just changed
// the presence
ClientSession userSession = routingTable.getClientRoute(address);
presence = userSession.getPresence().createCopy();
presence.setTo(session.getAddress());
session.process(presence);
}
}
/**
* Broadcasts presence updates from the originating user's resource to any of the user's
* existing available resources (if any).
*
* @param originatingResource the full JID of the session that sent the presence update.
* @param presence the presence.
*/
public void broadcastPresenceToOtherResources(JID originatingResource, Presence presence) {
// Get list of sessions of the same user
JID searchJID = new JID(originatingResource.getNode(), originatingResource.getDomain(), null);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -