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; ...@@ -16,10 +16,10 @@ import org.dom4j.DocumentHelper;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.QName; import org.dom4j.QName;
import org.jivesoftware.openfire.*; import org.jivesoftware.openfire.*;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.auth.AuthFactory; import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.auth.AuthToken; import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.UnauthorizedException; import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.session.ClientSession; import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.LocalClientSession; import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.session.Session; import org.jivesoftware.openfire.session.Session;
...@@ -219,9 +219,16 @@ public class IQAuthHandler extends IQHandler implements IQAuthInfo { ...@@ -219,9 +219,16 @@ public class IQAuthHandler extends IQHandler implements IQAuthInfo {
ClientSession oldSession = routingTable.getClientRoute(new JID(username, serverName, resource, true)); ClientSession oldSession = routingTable.getClientRoute(new JID(username, serverName, resource, true));
if (oldSession != null) { if (oldSession != null) {
try { try {
oldSession.incrementConflictCount();
int conflictLimit = sessionManager.getConflictKickLimit(); 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 // Send a stream:error before closing the old connection
StreamError error = new StreamError(StreamError.Condition.conflict); StreamError error = new StreamError(StreamError.Condition.conflict);
oldSession.deliverRawText(error.toXML()); oldSession.deliverRawText(error.toXML());
......
...@@ -17,9 +17,9 @@ import org.jivesoftware.openfire.IQHandlerInfo; ...@@ -17,9 +17,9 @@ import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.RoutingTable; import org.jivesoftware.openfire.RoutingTable;
import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.auth.AuthToken; import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.UnauthorizedException; import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.session.ClientSession; import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.LocalClientSession; import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.stringprep.StringprepException; import org.jivesoftware.stringprep.StringprepException;
...@@ -109,9 +109,17 @@ public class IQBindHandler extends IQHandler { ...@@ -109,9 +109,17 @@ public class IQBindHandler extends IQHandler {
ClientSession oldSession = routingTable.getClientRoute(new JID(username, serverName, resource, true)); ClientSession oldSession = routingTable.getClientRoute(new JID(username, serverName, resource, true));
if (oldSession != null) { if (oldSession != null) {
try { try {
oldSession.incrementConflictCount();
int conflictLimit = sessionManager.getConflictKickLimit(); 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 // Kick out the old connection that is conflicting with the new one
StreamError error = new StreamError(StreamError.Condition.conflict); StreamError error = new StreamError(StreamError.Condition.conflict);
oldSession.deliverRawText(error.toXML()); oldSession.deliverRawText(error.toXML());
......
...@@ -133,20 +133,9 @@ public interface ClientSession extends Session { ...@@ -133,20 +133,9 @@ public interface ClientSession extends Session {
public void setPresence(Presence presence); public void setPresence(Presence presence);
/** /**
* Returns the number of conflicts detected on this session. * Increments the conflict by one and returns new 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 * @return the new number of conflicts detected on this session.
*/ */
public int getConflictCount(); public int incrementConflictCount();
/**
* Increments the conflict by one.
*/
public void incrementConflictCount();
} }
...@@ -37,7 +37,6 @@ public class ClientSessionInfo implements Externalizable { ...@@ -37,7 +37,6 @@ public class ClientSessionInfo implements Externalizable {
private Presence presence; private Presence presence;
private String defaultList; private String defaultList;
private String activeList; private String activeList;
private int conflictCount;
private boolean offlineFloodStopped; private boolean offlineFloodStopped;
public ClientSessionInfo() { public ClientSessionInfo() {
...@@ -47,7 +46,6 @@ public class ClientSessionInfo implements Externalizable { ...@@ -47,7 +46,6 @@ public class ClientSessionInfo implements Externalizable {
presence = session.getPresence(); presence = session.getPresence();
defaultList = session.getDefaultList() != null ? session.getDefaultList().getName() : null; defaultList = session.getDefaultList() != null ? session.getDefaultList().getName() : null;
activeList = session.getActiveList() != null ? session.getActiveList().getName() : null; activeList = session.getActiveList() != null ? session.getActiveList().getName() : null;
conflictCount = session.getConflictCount();
offlineFloodStopped = session.isOfflineFloodStopped(); offlineFloodStopped = session.isOfflineFloodStopped();
} }
...@@ -63,10 +61,6 @@ public class ClientSessionInfo implements Externalizable { ...@@ -63,10 +61,6 @@ public class ClientSessionInfo implements Externalizable {
return activeList; return activeList;
} }
public int getConflictCount() {
return conflictCount;
}
public boolean isOfflineFloodStopped() { public boolean isOfflineFloodStopped() {
return offlineFloodStopped; return offlineFloodStopped;
} }
...@@ -81,7 +75,6 @@ public class ClientSessionInfo implements Externalizable { ...@@ -81,7 +75,6 @@ public class ClientSessionInfo implements Externalizable {
if (activeList != null) { if (activeList != null) {
ExternalizableUtil.getInstance().writeSafeUTF(out, activeList); ExternalizableUtil.getInstance().writeSafeUTF(out, activeList);
} }
ExternalizableUtil.getInstance().writeInt(out, conflictCount);
ExternalizableUtil.getInstance().writeBoolean(out, offlineFloodStopped); ExternalizableUtil.getInstance().writeBoolean(out, offlineFloodStopped);
} }
...@@ -94,7 +87,6 @@ public class ClientSessionInfo implements Externalizable { ...@@ -94,7 +87,6 @@ public class ClientSessionInfo implements Externalizable {
if (ExternalizableUtil.getInstance().readBoolean(in)) { if (ExternalizableUtil.getInstance().readBoolean(in)) {
activeList = ExternalizableUtil.getInstance().readSafeUTF(in); activeList = ExternalizableUtil.getInstance().readSafeUTF(in);
} }
conflictCount = ExternalizableUtil.getInstance().readInt(in);
offlineFloodStopped = ExternalizableUtil.getInstance().readBoolean(in); offlineFloodStopped = ExternalizableUtil.getInstance().readBoolean(in);
} }
} }
...@@ -699,21 +699,6 @@ public class LocalClientSession extends LocalSession implements ClientSession { ...@@ -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() { public String getAvailableStreamFeatures() {
// Offer authenticate and registration only if TLS was not required or if required // Offer authenticate and registration only if TLS was not required or if required
// then the connection is already secured // then the connection is already secured
...@@ -750,13 +735,9 @@ public class LocalClientSession extends LocalSession implements ClientSession { ...@@ -750,13 +735,9 @@ public class LocalClientSession extends LocalSession implements ClientSession {
/** /**
* Increments the conflict by one. * Increments the conflict by one.
*/ */
public void incrementConflictCount() { public int incrementConflictCount() {
conflictCount++; conflictCount++;
if (ClusterManager.isClusteringStarted()) { return conflictCount;
// 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));
}
} }
/** /**
......
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