Commit a4bb6494 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Fixed and optimized resource conflict. JM-1355

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/branches@10345 b35dd754-fafc-0310-a699-88a17e54d16e
parent 1d93fe5e
......@@ -16,10 +16,10 @@ import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.openfire.*;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.session.Session;
......@@ -219,9 +219,16 @@ public class IQAuthHandler extends IQHandler implements IQAuthInfo {
ClientSession oldSession = routingTable.getClientRoute(new JID(username, serverName, resource, true));
if (oldSession != null) {
try {
oldSession.incrementConflictCount();
int conflictLimit = sessionManager.getConflictKickLimit();
if (conflictLimit != SessionManager.NEVER_KICK && oldSession.getConflictCount() > conflictLimit) {
if (conflictLimit == SessionManager.NEVER_KICK) {
IQ response = IQ.createResultIQ(packet);
response.setChildElement(packet.getChildElement().createCopy());
response.setError(PacketError.Condition.forbidden);
return response;
}
int conflictCount = oldSession.incrementConflictCount();
if (conflictCount > conflictLimit) {
// Send a stream:error before closing the old connection
StreamError error = new StreamError(StreamError.Condition.conflict);
oldSession.deliverRawText(error.toXML());
......
......@@ -17,9 +17,9 @@ import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.RoutingTable;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.stringprep.StringprepException;
......@@ -109,9 +109,17 @@ public class IQBindHandler extends IQHandler {
ClientSession oldSession = routingTable.getClientRoute(new JID(username, serverName, resource, true));
if (oldSession != null) {
try {
oldSession.incrementConflictCount();
int conflictLimit = sessionManager.getConflictKickLimit();
if (conflictLimit != SessionManager.NEVER_KICK && oldSession.getConflictCount() > conflictLimit) {
if (conflictLimit == SessionManager.NEVER_KICK) {
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(PacketError.Condition.conflict);
// Send the error directly since a route does not exist at this point.
session.process(reply);
return null;
}
int conflictCount = oldSession.incrementConflictCount();
if (conflictCount > conflictLimit) {
// Kick out the old connection that is conflicting with the new one
StreamError error = new StreamError(StreamError.Condition.conflict);
oldSession.deliverRawText(error.toXML());
......
......@@ -133,20 +133,9 @@ public interface ClientSession extends Session {
public void setPresence(Presence presence);
/**
* Returns the number of conflicts detected on this session.
* Conflicts typically occur when another session authenticates properly
* to the user account and requests to use a resource matching the one
* in use by this session. Administrators may configure the server to automatically
* kick off existing sessions when their conflict count exceeds some limit including
* 0 (old sessions are kicked off immediately to accommodate new sessions). Conflicts
* typically signify the existing (old) session is broken/hung.
* Increments the conflict by one and returns new number of conflicts detected on this session.
*
* @return The number of conflicts detected for this session
* @return the new number of conflicts detected on this session.
*/
public int getConflictCount();
/**
* Increments the conflict by one.
*/
public void incrementConflictCount();
public int incrementConflictCount();
}
......@@ -37,7 +37,6 @@ public class ClientSessionInfo implements Externalizable {
private Presence presence;
private String defaultList;
private String activeList;
private int conflictCount;
private boolean offlineFloodStopped;
public ClientSessionInfo() {
......@@ -47,7 +46,6 @@ public class ClientSessionInfo implements Externalizable {
presence = session.getPresence();
defaultList = session.getDefaultList() != null ? session.getDefaultList().getName() : null;
activeList = session.getActiveList() != null ? session.getActiveList().getName() : null;
conflictCount = session.getConflictCount();
offlineFloodStopped = session.isOfflineFloodStopped();
}
......@@ -63,10 +61,6 @@ public class ClientSessionInfo implements Externalizable {
return activeList;
}
public int getConflictCount() {
return conflictCount;
}
public boolean isOfflineFloodStopped() {
return offlineFloodStopped;
}
......@@ -81,7 +75,6 @@ public class ClientSessionInfo implements Externalizable {
if (activeList != null) {
ExternalizableUtil.getInstance().writeSafeUTF(out, activeList);
}
ExternalizableUtil.getInstance().writeInt(out, conflictCount);
ExternalizableUtil.getInstance().writeBoolean(out, offlineFloodStopped);
}
......@@ -94,7 +87,6 @@ public class ClientSessionInfo implements Externalizable {
if (ExternalizableUtil.getInstance().readBoolean(in)) {
activeList = ExternalizableUtil.getInstance().readSafeUTF(in);
}
conflictCount = ExternalizableUtil.getInstance().readInt(in);
offlineFloodStopped = ExternalizableUtil.getInstance().readBoolean(in);
}
}
......@@ -699,21 +699,6 @@ public class LocalClientSession extends LocalSession implements ClientSession {
}
}
/**
* Returns the number of conflicts detected on this session.
* Conflicts typically occur when another session authenticates properly
* to the user account and requests to use a resource matching the one
* in use by this session. Administrators may configure the server to automatically
* kick off existing sessions when their conflict count exceeds some limit including
* 0 (old sessions are kicked off immediately to accommodate new sessions). Conflicts
* typically signify the existing (old) session is broken/hung.
*
* @return The number of conflicts detected for this session
*/
public int getConflictCount() {
return conflictCount;
}
public String getAvailableStreamFeatures() {
// Offer authenticate and registration only if TLS was not required or if required
// then the connection is already secured
......@@ -750,13 +735,9 @@ public class LocalClientSession extends LocalSession implements ClientSession {
/**
* Increments the conflict by one.
*/
public void incrementConflictCount() {
public int incrementConflictCount() {
conflictCount++;
if (ClusterManager.isClusteringStarted()) {
// Track information about the session and share it with other cluster nodes
Cache<String,ClientSessionInfo> cache = SessionManager.getInstance().getSessionInfoCache();
cache.put(getAddress().toString(), new ClientSessionInfo(this));
}
return conflictCount;
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment