Commit 3c580276 authored by Derek McLean's avatar Derek McLean Committed by Christian Schudt

Cannot join room in a cluster after an availability update.

When a room occupant sends an availability update to a host in an
Openfire cluster, other users cannot join the room from other hosts in
the cluster. The availability update causes the other hosts to lose an
occupant's role and affiliation. New occupants encounter an NPE when
joining and are prevented from joining the room. Specifically, the NPE
occurs when Openfire attempts to send initial presences for current
occupants.

Remote hosts in the cluster lose the occupant's association because the
local room simply broadcasts the presence packet for the occupant's
availability update. Because it is from the client, this packet does not
have the occupant's role or affiliation. The remote hosts treat the
presence packet as the occupant's presence without modification.

This fix changes the order in which Openfire handles an availability
update. First, it updates its local view of an occupant's presence. This
populates the correct association. Then, it broadcasts the updated
presence to remote hosts in the cluster.
parent 5e84ea54
......@@ -1868,20 +1868,35 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
public boolean isManuallyLocked() {
return lockedTime > 0 && creationDate.getTime() != lockedTime;
}
@Override
public void presenceUpdated(MUCRole occupantRole, Presence newPresence) {
// Ask other cluster nodes to update the presence of the occupant
UpdatePresence request = new UpdatePresence(this, newPresence.createCopy(), occupantRole.getNickname());
CacheFactory.doClusterTask(request);
// Update the presence of the occupant
request = new UpdatePresence(this, newPresence.createCopy(), occupantRole.getNickname());
request.setOriginator(true);
request.run();
// Broadcast new presence of occupant
broadcastPresence(occupantRole.getPresence().createCopy(), false);
/**
* Handles occupants updating their presence in the chatroom. Assumes the user updates their presence whenever their
* availability in the room changes. This method should not be called to handle other presence related updates, such
* as nickname changes.
* {@inheritDoc}
*/
@Override
public void presenceUpdated(final MUCRole occupantRole, final Presence newPresence) {
final String occupantNickName = occupantRole.getNickname();
// Update the presence of the occupant on the local node with the occupant's new availability. Updates the
// local node first so the remote nodes receive presence that correctly reflects the occupant's new
// availability and previously existing role and affiliation with the room.
final UpdatePresence localUpdateRequest = new UpdatePresence(this, newPresence.createCopy(), occupantNickName);
localUpdateRequest.setOriginator(true);
localUpdateRequest.run();
// Get the new, updated presence for the occupant in the room. The presence reflects the occupant's updated
// availability and their existing association.
final Presence updatedPresence = occupantRole.getPresence().createCopy();
// Ask other cluster nodes to update the presence of the occupant. Uses the updated presence from the local
// MUC role.
final UpdatePresence clusterUpdateRequest = new UpdatePresence(this, updatedPresence, occupantNickName);
CacheFactory.doClusterTask(clusterUpdateRequest);
// Broadcast updated presence of occupant.
broadcastPresence(updatedPresence, false);
}
/**
......
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