Commit 7750f416 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

1) My little small refactoring.

2) Reroute failed packet to full JID to bare JID. JM-1075

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@8406 b35dd754-fafc-0310-a699-88a17e54d16e
parent 35bb6b57
......@@ -16,11 +16,14 @@ import org.jivesoftware.openfire.interceptor.InterceptorManager;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.xmpp.packet.*;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.PacketError;
import java.util.*;
import java.util.StringTokenizer;
/**
* <p>Route message packets throughout the server.</p>
......@@ -37,6 +40,7 @@ public class MessageRouter extends BasicModule {
private RoutingTable routingTable;
private SessionManager sessionManager;
private MulticastRouter multicastRouter;
private UserManager userManager;
private String serverName;
......@@ -68,14 +72,11 @@ public class MessageRouter extends BasicModule {
try {
// Invoke the interceptors before we process the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true, false);
if (session == null
|| session.getStatus() == Session.STATUS_AUTHENTICATED)
{
if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED) {
JID recipientJID = packet.getTo();
// Check if the message was sent to the server hostname
if (recipientJID != null && recipientJID.getNode() == null &&
recipientJID.getResource() == null &&
if (recipientJID != null && recipientJID.getNode() == null && recipientJID.getResource() == null &&
serverName.equals(recipientJID.getDomain())) {
if (packet.getElement().element("addresses") != null) {
// Message includes multicast processing instructions. Ask the multicastRouter
......@@ -91,25 +92,12 @@ public class MessageRouter extends BasicModule {
}
try {
// Check if message was sent to a bare JID of a local user
if (recipientJID != null && recipientJID.getResource() == null &&
serverName.equals(recipientJID.getDomain())) {
routeToBareJID(recipientJID, packet);
}
else {
// Deliver stanza to requested route
routingTable.routePacket(recipientJID, packet);
}
// Deliver stanza to requested route
routingTable.routePacket(recipientJID, packet);
}
catch (Exception e) {
try {
messageStrategy.storeOffline(packet);
}
catch (Exception e1) {
Log.error(e1);
}
routingFailed(recipientJID, packet);
}
}
else {
packet.setTo(session.getAddress());
......@@ -135,100 +123,6 @@ public class MessageRouter extends BasicModule {
}
}
/**
* Deliver the message sent to the bare JID of a local user to the best connected resource. If the
* target user is not online then messages will be stored offline according to the offline strategy.
* However, if the user is connected from only one resource then the message will be delivered to
* that resource. In the case that the user is connected from many resources the logic will be the
* following:
* <ol>
* <li>Select resources with highest priority</li>
* <li>Select resources with highest show value (chat, available, away, xa, dnd)</li>
* <li>Select resource with most recent activity</li>
* </ol>
*
* Admins can override the above logic and just send the message to all connected resources
* with highest priority by setting the system property <tt>route.all-resources</tt> to
* <tt>true</tt>.
*
* @param recipientJID the bare JID of the target local user.
* @param packet the message to send.
*/
private void routeToBareJID(JID recipientJID, Message packet) {
List<ClientSession> sessions = sessionManager.getHighestPrioritySessions(recipientJID.getNode());
if (sessions.isEmpty()) {
// No session is available so store offline
messageStrategy.storeOffline(packet);
}
else if (sessions.size() == 1) {
// Found only one session so deliver message
sessions.get(0).process(packet);
}
else {
// Many sessions have the highest priority (be smart now) :)
if (!JiveGlobals.getBooleanProperty("route.all-resources", false)) {
// Sort sessions by show value (e.g. away, xa)
Collections.sort(sessions, new Comparator<ClientSession>() {
public int compare(ClientSession o1, ClientSession o2) {
int thisVal = getShowValue(o1);
int anotherVal = getShowValue(o2);
return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}
/**
* Priorities are: chat, available, away, xa, dnd.
*/
private int getShowValue(ClientSession session) {
Presence.Show show = session.getPresence().getShow();
if (show == Presence.Show.chat) {
return 1;
}
else if (show == null) {
return 2;
}
else if (show == Presence.Show.away) {
return 3;
}
else if (show == Presence.Show.xa) {
return 4;
}
else {
return 5;
}
}
});
// Get same sessions with same max show value
List<ClientSession> targets = new ArrayList<ClientSession>();
Presence.Show showFilter = sessions.get(0).getPresence().getShow();
for (ClientSession session : sessions) {
if (session.getPresence().getShow() == showFilter) {
targets.add(session);
}
else {
break;
}
}
// Get session with most recent activity (and highest show value)
Collections.sort(targets, new Comparator<ClientSession>() {
public int compare(ClientSession o1, ClientSession o2) {
return o1.getLastActiveDate().compareTo(o2.getLastActiveDate());
}
});
// Deliver stanza to session with highest priority, highest show value and most recent activity
targets.get(0).process(packet);
}
else {
// Deliver stanza to all connected resources with highest priority
for (ClientSession session : sessions) {
session.process(packet);
}
}
}
}
/**
* Forwards the received message to the list of users defined in the property
* <b>xmpp.forward.admins</b>. The property may include bare JIDs or just usernames separated
......@@ -274,15 +168,24 @@ public class MessageRouter extends BasicModule {
routingTable = server.getRoutingTable();
sessionManager = server.getSessionManager();
multicastRouter = server.getMulticastRouter();
userManager = server.getUserManager();
serverName = server.getServerInfo().getName();
}
/**
* Notification message indicating that a packet has failed to be routed to the receipient.
*
* @param receipient address of the entity that failed to receive the packet.
* @param packet Message packet that failed to be sent to the receipient.
*/
public void routingFailed(Packet packet) {
messageStrategy.storeOffline((Message) packet);
public void routingFailed(JID receipient, Packet packet) {
// If message was sent to an unavailable full JID of a user then retry using the bare JID
if (serverName.equals(receipient.getDomain()) && receipient.getResource() != null &&
userManager.isRegisteredUser(receipient.getNode())) {
routingTable.routePacket(new JID(receipient.toBareJID()), packet);
} else {
// Just store the message offline
messageStrategy.storeOffline((Message) packet);
}
}
}
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