📄 sessionmanager.java
字号:
// the remote server
sessions.add(session);
}
}
}
/**
* Unregisters the server sessions originated by a remote server with the specified 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. The remote server may have
* many sessions established with this server (eg. to the server itself and to subdomains
* hosted by this server).
*
* @param hostname the hostname that is being served by the remote server.
*/
public void unregisterIncomingServerSessions(String hostname) {
synchronized (incomingServerSessions) {
incomingServerSessions.remove(hostname);
}
}
/**
* 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.
*/
private void unregisterIncomingServerSession(String hostname, IncomingServerSession session) {
synchronized (incomingServerSessions) {
List<IncomingServerSession> sessions = incomingServerSessions.get(hostname);
if (sessions != null) {
sessions.remove(session);
if (sessions.isEmpty()) {
// Remove key since there are no more sessions associated
incomingServerSessions.remove(hostname);
}
}
}
}
/**
* Registers that a server session originated by this server has been established to
* a remote server named hostname. This session will only be used for sending packets
* to the remote server and cannot receive packets. The {@link OutgoingServerSession}
* may have one or more domains, subdomains or virtual hosts authenticated with the
* remote server.
*
* @param hostname the hostname that is being served by the remote server.
* @param session the outgoing server session to the remote server.
*/
public void registerOutgoingServerSession(String hostname, OutgoingServerSession session) {
outgoingServerSessions.put(hostname, session);
}
/**
* Unregisters the server session that was originated by this server to a remote server
* named hostname. This session was only being used for sending packets
* to the remote server and not for receiving packets. The {@link OutgoingServerSession}
* may have one or more domains, subdomains or virtual hosts authenticated with the
* remote server.
*
* @param hostname the hostname that the session was connected with.
*/
public void unregisterOutgoingServerSession(String hostname) {
outgoingServerSessions.remove(hostname);
}
/**
* Add a new session to be managed.
*/
public void addSession(ClientSession session) {
String username = session.getAddress().getNode();
SessionMap resources;
synchronized (username.intern()) {
resources = sessions.get(username);
if (resources == null) {
resources = new SessionMap();
sessions.put(username, resources);
}
resources.addSession(session);
}
// Remove the pre-Authenticated session but remember to use the temporary ID as the key
preAuthenticatedSessions.remove(session.getStreamID().toString());
// Fire session created event.
SessionEventDispatcher
.dispatchEvent(session, SessionEventDispatcher.EventType.session_created);
}
/**
* 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(ClientSession session) {
if (anonymousSessions.containsValue(session)) {
// Anonymous session always have resources so we only need to add one route. That is
// the route to the anonymous session
routingTable.addRoute(session.getAddress(), session);
}
else {
// A non-anonymous session is now available
Session defaultSession;
try {
SessionMap sessionMap = sessions.get(session.getUsername());
if (sessionMap == null) {
Log.warn("No SessionMap found for session" + "\n" + session);
}
// Update the order of the sessions based on the new presence of this session
sessionMap.sessionAvailable(session);
defaultSession = sessionMap.getDefaultSession(true);
JID node = new JID(defaultSession.getAddress().getNode(),
defaultSession.getAddress().getDomain(), null);
// Add route to default session (used when no resource is specified)
routingTable.addRoute(node, defaultSession);
// Add route to the new session
routingTable.addRoute(session.getAddress(), session);
// Broadcast presence between the user's resources
broadcastPresenceOfOtherResource(session);
}
catch (UserNotFoundException e) {
// Do nothing since the session is anonymous (? - shouldn't happen)
}
}
}
/**
* Sends the presences of other connected resources to the resource that just connected.
*
* @param session the newly created session.
*/
private void broadcastPresenceOfOtherResource(ClientSession session)
throws UserNotFoundException {
Presence presence;
Collection<ClientSession> availableSession;
SessionMap sessionMap = sessions.get(session.getUsername());
if (sessionMap != null) {
availableSession = new ArrayList<ClientSession>(sessionMap.getAvailableSessions());
for (ClientSession userSession : availableSession) {
if (userSession != session) {
// Send the presence of an existing session to the session that has just changed
// the presence
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.
*/
public void broadcastPresenceToOtherResources(JID originatingResource, Presence presence) {
Collection<ClientSession> availableSession;
SessionMap sessionMap = sessions.get(originatingResource.getNode());
if (sessionMap != null) {
availableSession = new ArrayList<ClientSession>(sessionMap.getAvailableSessions());
for (ClientSession userSession : availableSession) {
if (userSession.getAddress() != originatingResource) {
// Send the presence of the session whose presence has changed to
// this other user's session
presence.setTo(userSession.getAddress());
userSession.process(presence);
}
}
}
}
/**
* Notification message sent when a client sent an unavailable presence for the session. Making
* the session unavailable means that the session is not eligible for receiving messages from
* other clients.
*
* @param session the session that receieved an unavailable presence.
*/
public void sessionUnavailable(ClientSession session) {
if (session.getAddress() != null && routingTable != null &&
session.getAddress().toBareJID().trim().length() != 0) {
// Remove route to the removed session (anonymous or not)
routingTable.removeRoute(session.getAddress());
try {
if (session.getUsername() == null) {
// Do nothing since this is an anonymous session
return;
}
SessionMap sessionMap = sessions.get(session.getUsername());
// If sessionMap is null, which is an irregular case, try to clean up the routes to
// the user from the routing table
if (sessionMap == null) {
JID userJID = new JID(session.getUsername(), serverName, "");
if (routingTable.getRoute(userJID) != null) {
// Remove the route for the session's BARE address
routingTable.removeRoute(new JID(session.getAddress().getNode(),
session.getAddress().getDomain(), ""));
}
}
// If all the user sessions are gone then remove the route to the default session
else if (sessionMap.getAvailableSessions().isEmpty()) {
// Remove the route for the session's BARE address
routingTable.removeRoute(new JID(session.getAddress().getNode(),
session.getAddress().getDomain(), ""));
}
else {
// Update the order of the sessions based on the new presence of this session
sessionMap.sessionUnavailable(session);
// Update the route for the session's BARE address
Session defaultSession = sessionMap.getDefaultSession(true);
routingTable.addRoute(new JID(defaultSession.getAddress().getNode(),
defaultSession.getAddress().getDomain(), ""),
defaultSession);
}
}
catch (UserNotFoundException e) {
// Do nothing since the session is anonymous
}
}
}
/**
* Change the priority of a session, that was already available, associated with the sender.
*
* @param sender The sender who's session just changed priority
* @param priority The new priority for the session
*/
public void changePriority(JID sender, int priority) {
if (sender.getNode() == null || !userManager.isRegisteredUser(sender.getNode())) {
// Do nothing if the session belongs to an anonymous user
return;
}
Session defaultSession;
String username = sender.getNode();
SessionMap resources = sessions.get(username);
if (resources == null) {
return;
}
synchronized (username.intern()) {
resources.changePriority(sender, priority);
// Get the session with highest priority
defaultSession = resources.getDefaultSession(true);
}
// Update the route to the bareJID with the session with highest priority
routingTable.addRoute(new JID(defaultSession.getAddress().getNode(),
defaultSession.getAddress().getDomain(), ""),
defaultSession);
}
/**
* Retrieve the best route to deliver packets to this session given the recipient jid. If the
* requested JID does not have a node (i.e. username) then the best route will be looked up
* in the anonymous sessions list. Otherwise, try to find a root for the exact JID
* (i.e. including the resource) and if none is found then answer the deafult session if any.
*
* @param recipient The recipient ID to deliver packets to
* @return The XMPPAddress best suited to use for delivery to the recipient
*/
public ClientSession getBestRoute(JID recipient) {
// Return null if the JID belongs to a foreign server
if (serverName == null || !serverName.equals(recipient.getDomain())) {
return null;
}
ClientSession session = null;
String resource = recipient.getResource();
String username = recipient.getNode();
if (resource != null && (username == null || !userManager.isRegisteredUser(username))) {
session = anonymousSessions.get(resource);
if (session == null){
session = getSession(recipient);
}
}
else {
SessionMap sessionMap = sessions.get(username);
if (sessionMap != null) {
if (resource == null) {
synchronized (username.intern()) {
session = sessionMap.getDefaultSession(false);
}
}
else {
session = sessionMap.getSession(resource);
if (session == null) {
synchronized (username.intern()) {
session = sessionMap.getDefaultSession(false);
}
}
}
}
}
// Sanity check - check if the underlying session connection is closed. Remove the session
// from the list of sessions if the session is closed and proceed to look for another route.
if (session != null && session.getConnection().isClosed()) {
removeSession(session);
return getBestRoute(recipient);
}
return session;
}
public boolean isAnonymousRoute(String username) {
// JID's node and resource are the same for anonymous sessions
return anonymousSessions.containsKey(username);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -