Commit 723c9ffc authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gaston

Fixed several issues in roster and presence management.


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@1396 b35dd754-fafc-0310-a699-88a17e54d16e
parent 5d5b87aa
...@@ -101,5 +101,16 @@ public interface PresenceManager { ...@@ -101,5 +101,16 @@ public interface PresenceManager {
* *
* @param packet the received probe presence from a remote server. * @param packet the received probe presence from a remote server.
*/ */
void handleProbe(Presence packet) throws UnauthorizedException; public void handleProbe(Presence packet) throws UnauthorizedException;
/**
* Sends unavailable presence from all of the user's available resources to the remote user.
* When a remote user unsubscribes from the presence of a local user then the server should
* send to the remote user unavailable presence from all of the local user's available
* resources.
*
* @param recipientJID JID of the remote user that will receive the unavailable presences.
* @param userJID JID of the local user.
*/
public void sendUnavailableFromSessions(JID recipientJID, JID userJID);
} }
\ No newline at end of file
...@@ -89,28 +89,40 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand ...@@ -89,28 +89,40 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
JID senderJID = presence.getFrom(); JID senderJID = presence.getFrom();
JID recipientJID = presence.getTo(); JID recipientJID = presence.getTo();
Presence.Type type = presence.getType(); Presence.Type type = presence.getType();
Roster roster = getRoster(senderJID);
try { try {
if (roster != null) { Roster senderRoster = getRoster(senderJID);
manageSub(recipientJID, true, type, roster); boolean senderSubChanged = false;
if (senderRoster != null) {
senderSubChanged = manageSub(recipientJID, true, type, senderRoster);
} }
roster = getRoster(recipientJID); Roster recipientRoster = getRoster(recipientJID);
if (roster != null) { boolean recipientSubChanged = false;
manageSub(senderJID, false, type, roster); if (recipientRoster != null) {
recipientSubChanged = manageSub(senderJID, false, type, recipientRoster);
} }
// Try to obtain a handler for the packet based on the routes. If the handler is
// a module, the module will be able to handle the packet. If the handler is a
// Session the packet will be routed to the client. If a route cannot be found
// then the packet will be delivered based on its recipient and sender.
ChannelHandler handler = routingTable.getRoute(recipientJID);
handler.process(presence.createCopy());
if (getRoster(recipientJID) == null && type == Presence.Type.subscribed) { // Do not forward the packet to the recipient if the presence is of type subscribed
// Send the presence of the local user to the remote user. The remote user // and the recipient user has not changed its subscription state.
// subscribed to the presence of the local user and the local user accepted if (!(type == Presence.Type.subscribed && recipientRoster != null &&
presenceManager.probePresence(recipientJID, senderJID); !recipientSubChanged)) {
// Try to obtain a handler for the packet based on the routes. If the handler is
// a module, the module will be able to handle the packet. If the handler is a
// Session the packet will be routed to the client. If a route cannot be found
// then the packet will be delivered based on its recipient and sender.
ChannelHandler handler = routingTable.getRoute(recipientJID);
Presence presenteToSend = presence.createCopy();
// Stamp the presence with the user's bare JID as the 'from' address
presenteToSend.setFrom(senderJID.toBareJID());
handler.process(presenteToSend);
if (type == Presence.Type.subscribed) {
// Send the presence of the local user to the remote user. The remote user
// subscribed to the presence of the local user and the local user accepted
presenceManager.probePresence(recipientJID, senderJID);
}
} }
else if (getRoster(recipientJID) == null && type == Presence.Type.unsubscribed) {
if (type == Presence.Type.unsubscribed) {
// Send unavailable presence from all of the local user's available resources // Send unavailable presence from all of the local user's available resources
// to the remote user // to the remote user
presenceManager.sendUnavailableFromSessions(recipientJID, senderJID); presenceManager.sendUnavailableFromSessions(recipientJID, senderJID);
...@@ -169,10 +181,12 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand ...@@ -169,10 +181,12 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
* @param target The roster target's jid (the item's jid to be changed) * @param target The roster target's jid (the item's jid to be changed)
* @param isSending True if the request is being sent by the owner * @param isSending True if the request is being sent by the owner
* @param type The subscription change type (subscribe, unsubscribe, etc.) * @param type The subscription change type (subscribe, unsubscribe, etc.)
* @return true if the subscription state has changed.
*/ */
private void manageSub(JID target, boolean isSending, Presence.Type type, Roster roster) private boolean manageSub(JID target, boolean isSending, Presence.Type type, Roster roster)
throws UserAlreadyExistsException, SharedGroupException throws UserAlreadyExistsException, SharedGroupException
{ {
boolean modified = false;
try { try {
RosterItem item; RosterItem item;
if (roster.isRosterItem(target)) { if (roster.isRosterItem(target)) {
...@@ -181,13 +195,14 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand ...@@ -181,13 +195,14 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
else { else {
item = roster.createRosterItem(target); item = roster.createRosterItem(target);
} }
updateState(item, type, isSending); modified = updateState(item, type, isSending);
roster.updateRosterItem(item); roster.updateRosterItem(item);
} }
catch (UserNotFoundException e) { catch (UserNotFoundException e) {
// Should be there because we just checked that it's an item // Should be there because we just checked that it's an item
Log.error(LocaleUtils.getLocalizedString("admin.error"), e); Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} }
return modified;
} }
/** /**
...@@ -370,20 +385,24 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand ...@@ -370,20 +385,24 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
* @param item The item to be updated * @param item The item to be updated
* @param action The new state change request * @param action The new state change request
* @param isSending True if the roster owner of the item is sending the new state change request * @param isSending True if the roster owner of the item is sending the new state change request
* @return true if the subscription state has changed.
*/ */
private static void updateState(RosterItem item, Presence.Type action, boolean isSending) { private static boolean updateState(RosterItem item, Presence.Type action, boolean isSending) {
Map srTable = (Map)stateTable.get(item.getSubStatus()); Map srTable = (Map)stateTable.get(item.getSubStatus());
Map changeTable = (Map)srTable.get(isSending ? "send" : "recv"); Map changeTable = (Map)srTable.get(isSending ? "send" : "recv");
Change change = (Change)changeTable.get(action); Change change = (Change)changeTable.get(action);
if (change.newAsk != null) { boolean modified = false;
if (change.newAsk != null && change.newAsk != item.getAskStatus()) {
item.setAskStatus(change.newAsk); item.setAskStatus(change.newAsk);
} }
if (change.newSub != null) { if (change.newSub != null && change.newSub != item.getSubStatus()) {
item.setSubStatus(change.newSub); item.setSubStatus(change.newSub);
modified = true;
} }
if (change.newRecv != null) { if (change.newRecv != null && change.newRecv != item.getRecvStatus()) {
item.setRecvStatus(change.newRecv); item.setRecvStatus(change.newRecv);
} }
return modified;
} }
public void initialize(XMPPServer server) { public void initialize(XMPPServer server) {
......
...@@ -309,9 +309,9 @@ public class Roster implements Cacheable { ...@@ -309,9 +309,9 @@ public class Roster implements Cacheable {
//if (item.getAskStatus() != RosterItem.ASK_NONE) { //if (item.getAskStatus() != RosterItem.ASK_NONE) {
broadcast(item, true); broadcast(item, true);
//} //}
if (item.getSubStatus() == RosterItem.SUB_BOTH || item.getSubStatus() == RosterItem.SUB_TO) { /*if (item.getSubStatus() == RosterItem.SUB_BOTH || item.getSubStatus() == RosterItem.SUB_TO) {
probePresence(item.getJid()); probePresence(item.getJid());
} }*/
} }
/** /**
...@@ -361,14 +361,6 @@ public class Roster implements Cacheable { ...@@ -361,14 +361,6 @@ public class Roster implements Cacheable {
roster.setType(IQ.Type.set); roster.setType(IQ.Type.set);
roster.addItem(user, org.xmpp.packet.Roster.Subscription.remove); roster.addItem(user, org.xmpp.packet.Roster.Subscription.remove);
broadcast(roster); broadcast(roster);
// Send unavailable presence from all of the user's available resources to the contact
for (ClientSession session : sessionManager.getSessions(username)) {
Presence presence = new Presence();
presence.setFrom(session.getAddress());
presence.setTo(item.getJid());
presence.setType(Presence.Type.unavailable);
server.getPacketRouter().route(presence);
}
} }
return item; return item;
......
...@@ -228,6 +228,23 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -228,6 +228,23 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
} }
} }
public void sendUnavailableFromSessions(JID recipientJID, JID userJID) {
if (userJID.getNode() != null && !"".equals(userJID.getNode())) {
for (ClientSession session : sessionManager.getSessions(userJID.getNode())) {
Presence presencePacket = session.getPresence().createCopy();
presencePacket.setType(Presence.Type.unavailable);
presencePacket.setFrom(session.getAddress());
presencePacket.setTo(recipientJID);
try {
deliverer.deliver(presencePacket);
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
}
}
}
public void deleteLastUnavailablePresence(String username) { public void deleteLastUnavailablePresence(String username) {
if (username == null) { if (username == null) {
return; return;
......
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