Commit b853644c authored by Dave Cridland's avatar Dave Cridland

Assume a client with MUC elements in presence needs to join

XEP-0045 discusses how a request to join a room is the only case where a MUC
element should exist in presence. Therefore, a conformant client will always
send this whenever it believes it is not joined. This can happen in cases of
stanza loss (due to network outage) or remote server crash.

This patch assumes that a client sending a MUC element is trying to join, and
will go through much of the motions of the join, including sending history as
required, existing occupants' presence, and so on. To other existing occupants,
however, it'll look like an ordinary presence update.
parent 4d6a8055
...@@ -563,6 +563,8 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener { ...@@ -563,6 +563,8 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
} }
LocalMUCRole joinRole = null; LocalMUCRole joinRole = null;
lock.writeLock().lock(); lock.writeLock().lock();
boolean clientOnlyJoin = false;
// A "client only join" here is one where the client is already joined, but has re-joined.
try { try {
// If the room has a limit of max user then check if the limit has been reached // If the room has a limit of max user then check if the limit has been reached
if (!canJoinRoom(user)) { if (!canJoinRoom(user)) {
...@@ -584,6 +586,9 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener { ...@@ -584,6 +586,9 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
// Nickname is already used, and not by the same JID // Nickname is already used, and not by the same JID
throw new UserAlreadyExistsException(); throw new UserAlreadyExistsException();
} }
if (occupant.getUserAddress().equals(user.getAddress())) {
clientOnlyJoin = true; // This user is already an occupant. The client thinks it isn't. (Or else this is a broken gmail).
}
} }
// If the room is password protected and the provided password is incorrect raise a // If the room is password protected and the provided password is incorrect raise a
// Unauthorized exception // Unauthorized exception
...@@ -650,8 +655,10 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener { ...@@ -650,8 +655,10 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
role = (isModerated() ? MUCRole.Role.visitor : MUCRole.Role.participant); role = (isModerated() ? MUCRole.Role.visitor : MUCRole.Role.participant);
affiliation = MUCRole.Affiliation.none; affiliation = MUCRole.Affiliation.none;
} }
if (!clientOnlyJoin) {
// Create a new role for this user in this room // Create a new role for this user in this room
joinRole = new LocalMUCRole(mucService, this, nickname, role, affiliation, user, presence, router); joinRole = new LocalMUCRole(mucService, this, nickname, role,
affiliation, user, presence, router);
// Add the new user as an occupant of this room // Add the new user as an occupant of this room
List<MUCRole> occupants = occupantsByNickname.get(nickname.toLowerCase()); List<MUCRole> occupants = occupantsByNickname.get(nickname.toLowerCase());
if (occupants == null) { if (occupants == null) {
...@@ -667,6 +674,10 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener { ...@@ -667,6 +674,10 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
} }
list.add(joinRole); list.add(joinRole);
occupantsByFullJID.put(user.getAddress(), joinRole); occupantsByFullJID.put(user.getAddress(), joinRole);
} else {
// Grab the existing one.
joinRole = (LocalMUCRole) occupantsByFullJID.get(user.getAddress());
}
} }
finally { finally {
lock.writeLock().unlock(); lock.writeLock().unlock();
...@@ -706,10 +717,13 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener { ...@@ -706,10 +717,13 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
else { else {
historyRequest.sendHistory(joinRole, roomHistory); historyRequest.sendHistory(joinRole, roomHistory);
} }
if (!clientOnlyJoin) {
// Update the date when the last occupant left the room // Update the date when the last occupant left the room
setEmptyDate(null); setEmptyDate(null);
// Fire event that occupant joined the room // Fire event that occupant joined the room
MUCEventDispatcher.occupantJoined(getRole().getRoleAddress(), user.getAddress(), joinRole.getNickname()); MUCEventDispatcher.occupantJoined(getRole().getRoleAddress(),
user.getAddress(), joinRole.getNickname());
}
return joinRole; return joinRole;
} }
......
...@@ -462,9 +462,12 @@ public class LocalMUCUser implements MUCUser { ...@@ -462,9 +462,12 @@ public class LocalMUCUser implements MUCUser {
String group = recipient.getNode(); String group = recipient.getNode();
if (group != null) { if (group != null) {
MUCRole role = roles.get(group); MUCRole role = roles.get(group);
if (role == null) { Element mucInfo = packet.getChildElement("x",
// If we're not already in a room, we either are joining it or it's not "http://jabber.org/protocol/muc");
if (role == null || mucInfo != null) {
// If we're not already in a room (role == null), we either are joining it or it's not
// properly addressed and we drop it silently // properly addressed and we drop it silently
// Alternative is that mucInfo is not null, in which case the client thinks it isn't in the room, so we should join anyway.
if (recipient.getResource() != null if (recipient.getResource() != null
&& recipient.getResource().trim().length() > 0) { && recipient.getResource().trim().length() > 0) {
if (packet.isAvailable()) { if (packet.isAvailable()) {
...@@ -472,8 +475,6 @@ public class LocalMUCUser implements MUCUser { ...@@ -472,8 +475,6 @@ public class LocalMUCUser implements MUCUser {
// Get or create the room // Get or create the room
MUCRoom room = server.getChatRoom(group, packet.getFrom()); MUCRoom room = server.getChatRoom(group, packet.getFrom());
// User must support MUC in order to create a room // User must support MUC in order to create a room
Element mucInfo = packet.getChildElement("x",
"http://jabber.org/protocol/muc");
HistoryRequest historyRequest = null; HistoryRequest historyRequest = null;
String password = null; String password = null;
// Check for password & requested history if client supports MUC // Check for password & requested history if client supports MUC
......
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