From e7544492625e1e400baea408c5eb0432c96bf661 Mon Sep 17 00:00:00 2001 From: Greg Thomas Date: Tue, 10 Dec 2019 16:41:04 +0000 Subject: [PATCH] Break out the CC to a method on it's own, and ensure we don't CC a message that is already CC'd --- .../openfire/carbons/Received.java | 6 +- .../openfire/spi/RoutingTableImpl.java | 94 ++++++++++--------- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/carbons/Received.java b/xmppserver/src/main/java/org/jivesoftware/openfire/carbons/Received.java index 5ac6f942e1..0f2279ebe5 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/carbons/Received.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/carbons/Received.java @@ -10,8 +10,12 @@ * @author Christian Schudt */ public final class Received extends PacketExtension { + + public static final String NAME = "received"; + public static final String NAMESPACE = "urn:xmpp:carbons:2"; + public Received(Forwarded forwarded) { - super("received", "urn:xmpp:carbons:2"); + super(NAME, NAMESPACE); element.add(forwarded.getElement()); } } diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/spi/RoutingTableImpl.java b/xmppserver/src/main/java/org/jivesoftware/openfire/spi/RoutingTableImpl.java index 53f131b429..53b8fbd949 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/spi/RoutingTableImpl.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/spi/RoutingTableImpl.java @@ -313,7 +313,7 @@ else if (packet instanceof Presence) { private boolean routeToLocalDomain(JID jid, Packet packet, boolean fromServer) { boolean routed = false; - Element privateElement = packet.getElement().element(QName.get("private", "urn:xmpp:carbons:2")); + Element privateElement = packet.getElement().element(QName.get("private", Received.NAMESPACE)); boolean isPrivate = privateElement != null; // The receiving server and SHOULD remove the element before delivering to the recipient. packet.getElement().remove(privateElement); @@ -339,49 +339,8 @@ private boolean routeToLocalDomain(JID jid, Packet packet, routed = false; } else { if (localRoutingTable.isLocalRoute(jid)) { - if (packet instanceof Message) { - Message message = (Message) packet; - if (message.getType() == Message.Type.chat && !isPrivate) { - List routes = getRoutes(jid.asBareJID(), null); - for (JID ccJid : routes) { - // The receiving server MUST NOT send a forwarded copy to the full JID the original stanza was addressed to, as that recipient receives the original stanza. - if (!ccJid.equals(jid)) { - ClientSession clientSession = getClientRoute(ccJid); - if (clientSession.isMessageCarbonsEnabled()) { - Message carbon = new Message(); - // The wrapping message SHOULD maintain the same 'type' attribute value; - carbon.setType(message.getType()); - // the 'from' attribute MUST be the Carbons-enabled user's bare JID - carbon.setFrom(ccJid.asBareJID()); - // and the 'to' attribute MUST be the full JID of the resource receiving the copy - carbon.setTo(ccJid); - // The content of the wrapping message MUST contain a element qualified by the namespace "urn:xmpp:carbons:2", which itself contains a element qualified by the namespace "urn:xmpp:forward:0" that contains the original . - carbon.addExtension(new Received(new Forwarded(message))); - - try { - final RoutableChannelHandler localRoute = localRoutingTable.getRoute(ccJid); - if (localRoute != null) { - // This session is on a local cluster node - localRoute.process(carbon); - } else { - // The session is not on a local cluster node, so try a remote - final ClientRoute remoteRoute = getClientRouteForLocalUser(ccJid); - if (remotePacketRouter != null // If we're in a cluster - && remoteRoute != null // and we've found a route to the other node - && !remoteRoute.getNodeID().equals(XMPPServer.getInstance().getNodeID())) { // and it really is a remote node - // Try and route the packet to the remote session - remotePacketRouter.routePacket(remoteRoute.getNodeID().toByteArray(), ccJid, carbon); - } else { - Log.warn("Unable to find route to CC remote user {}", ccJid); - } - } - } catch (UnauthorizedException e) { - Log.error("Unable to route packet " + packet.toXML(), e); - } - } - } - } - } + if (!isPrivate && packet instanceof Message) { + ccMessage(jid, (Message) packet); } // This is a route to a local user hosted in this node @@ -408,6 +367,53 @@ private boolean routeToLocalDomain(JID jid, Packet packet, return routed; } + private void ccMessage(JID originalRecipient, Message message) { + // We don't want to CC a message that is already a CC + final Element receivedElement = message.getChildElement(Received.NAME, Received.NAMESPACE); + final boolean isCC = receivedElement != null; + if (message.getType() == Message.Type.chat && !isCC) { + List routes = getRoutes(originalRecipient.asBareJID(), null); + for (JID ccJid : routes) { + // The receiving server MUST NOT send a forwarded copy to the full JID the original stanza was addressed to, as that recipient receives the original stanza. + if (!ccJid.equals(originalRecipient)) { + ClientSession clientSession = getClientRoute(ccJid); + if (clientSession.isMessageCarbonsEnabled()) { + Message carbon = new Message(); + // The wrapping message SHOULD maintain the same 'type' attribute value; + carbon.setType(message.getType()); + // the 'from' attribute MUST be the Carbons-enabled user's bare JID + carbon.setFrom(ccJid.asBareJID()); + // and the 'to' attribute MUST be the full JID of the resource receiving the copy + carbon.setTo(ccJid); + // The content of the wrapping message MUST contain a element qualified by the namespace "urn:xmpp:carbons:2", which itself contains a element qualified by the namespace "urn:xmpp:forward:0" that contains the original . + carbon.addExtension(new Received(new Forwarded(message))); + + try { + final RoutableChannelHandler localRoute = localRoutingTable.getRoute(ccJid); + if (localRoute != null) { + // This session is on a local cluster node + localRoute.process(carbon); + } else { + // The session is not on a local cluster node, so try a remote + final ClientRoute remoteRoute = getClientRouteForLocalUser(ccJid); + if (remotePacketRouter != null // If we're in a cluster + && remoteRoute != null // and we've found a route to the other node + && !remoteRoute.getNodeID().equals(XMPPServer.getInstance().getNodeID())) { // and it really is a remote node + // Try and route the packet to the remote session + remotePacketRouter.routePacket(remoteRoute.getNodeID().toByteArray(), ccJid, carbon); + } else { + Log.warn("Unable to find route to CC remote user {}", ccJid); + } + } + } catch (UnauthorizedException e) { + Log.error("Unable to route packet {}", message, e); + } + } + } + } + } + } + private ClientRoute getClientRouteForLocalUser(JID jid) { ClientRoute clientRoute = usersCache.get(jid.toString()); if (clientRoute == null) {