use of org.jivesoftware.openfire.forward.Forwarded in project Openfire by igniterealtime.
the class MessageCarbonsTest method testReceived.
@Test
public void testReceived() {
Message message = new Message();
message.setType(Message.Type.chat);
message.setBody("Tests");
Forwarded forwarded = new Forwarded(message);
Received received = new Received(forwarded);
String xml = received.getElement().asXML();
assertEquals("<received xmlns=\"urn:xmpp:carbons:2\"><forwarded xmlns=\"urn:xmpp:forward:0\"><message xmlns=\"jabber:client\" type=\"chat\"><body>Tests</body></message></forwarded></received>", xml);
}
use of org.jivesoftware.openfire.forward.Forwarded in project Openfire by igniterealtime.
the class MessageCarbonsTest method testSent.
@Test
public void testSent() {
Message message = new Message();
message.setType(Message.Type.chat);
message.setBody("Tests");
Forwarded forwarded = new Forwarded(message);
Sent sent = new Sent(forwarded);
String xml = sent.getElement().asXML();
assertEquals("<sent xmlns=\"urn:xmpp:carbons:2\"><forwarded xmlns=\"urn:xmpp:forward:0\"><message xmlns=\"jabber:client\" type=\"chat\"><body>Tests</body></message></forwarded></sent>", xml);
}
use of org.jivesoftware.openfire.forward.Forwarded in project Openfire by igniterealtime.
the class MessageRouter method route.
/**
* <p>Performs the actual packet routing.</p>
* <p>You routing is considered 'quick' and implementations may not take
* excessive amounts of time to complete the routing. If routing will take
* a long amount of time, the actual routing should be done in another thread
* so this method returns quickly.</p>
* <h2>Warning</h2>
* <p>Be careful to enforce concurrency DbC of concurrent by synchronizing
* any accesses to class resources.</p>
*
* @param packet The packet to route
* @throws NullPointerException If the packet is null
*/
public void route(Message packet) {
if (packet == null) {
throw new NullPointerException();
}
ClientSession session = sessionManager.getSession(packet.getFrom());
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) {
JID recipientJID = packet.getTo();
// If the server receives a message stanza with no 'to' attribute, it MUST treat the message as if the 'to' address were the bare JID <localpart@domainpart> of the sending entity.
if (recipientJID == null) {
recipientJID = packet.getFrom().asBareJID();
}
// Check if the message was sent to the server hostname
if (recipientJID.getNode() == null && recipientJID.getResource() == null && serverName.equals(recipientJID.getDomain())) {
if (packet.getElement().element("addresses") != null) {
// Message includes multicast processing instructions. Ask the multicastRouter
// to route this packet
multicastRouter.route(packet);
} else {
// Message was sent to the server hostname so forward it to a configurable
// set of JID's (probably admin users)
sendMessageToAdmins(packet);
}
return;
}
boolean isAcceptable = true;
if (session instanceof LocalClientSession) {
// Check if we could process messages from the recipient.
// If not, return a not-acceptable error as per XEP-0016:
// If the user attempts to send an outbound stanza to a contact and that stanza type is blocked, the user's server MUST NOT route the stanza to the contact but instead MUST return a <not-acceptable/> error
Message dummyMessage = packet.createCopy();
dummyMessage.setFrom(packet.getTo());
dummyMessage.setTo(packet.getFrom());
if (!((LocalClientSession) session).canProcess(dummyMessage)) {
packet.setTo(session.getAddress());
packet.setFrom((JID) null);
packet.setError(PacketError.Condition.not_acceptable);
session.process(packet);
isAcceptable = false;
}
}
if (isAcceptable) {
boolean isPrivate = packet.getElement().element(QName.get("private", "urn:xmpp:carbons:2")) != null;
try {
// Deliver stanza to requested route
routingTable.routePacket(recipientJID, packet, false);
} catch (Exception e) {
log.error("Failed to route packet: " + packet.toXML(), e);
routingFailed(recipientJID, packet);
}
// When a client sends a <message/> of type "chat"
if (packet.getType() == Message.Type.chat && !isPrivate && session != null) {
// && session.isMessageCarbonsEnabled() ??? // must the own session also be carbon enabled?
List<JID> routes = routingTable.getRoutes(packet.getFrom().asBareJID(), null);
for (JID route : routes) {
// The sending server SHOULD NOT send a forwarded copy to the sending full JID if it is a Carbons-enabled resource.
if (!route.equals(session.getAddress())) {
ClientSession clientSession = sessionManager.getSession(route);
if (clientSession != null && clientSession.isMessageCarbonsEnabled()) {
Message message = new Message();
// The wrapping message SHOULD maintain the same 'type' attribute value
message.setType(packet.getType());
// the 'from' attribute MUST be the Carbons-enabled user's bare JID
message.setFrom(packet.getFrom().asBareJID());
// and the 'to' attribute SHOULD be the full JID of the resource receiving the copy
message.setTo(route);
// The content of the wrapping message MUST contain a <sent/> element qualified by the namespace "urn:xmpp:carbons:2", which itself contains a <forwarded/> qualified by the namespace "urn:xmpp:forward:0" that contains the original <message/> stanza.
message.addExtension(new Sent(new Forwarded(packet)));
clientSession.process(message);
}
}
}
}
}
} else {
packet.setTo(session.getAddress());
packet.setFrom((JID) null);
packet.setError(PacketError.Condition.not_authorized);
session.process(packet);
}
// Invoke the interceptors after we have processed the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true, true);
} catch (PacketRejectedException e) {
// An interceptor rejected this packet
if (session != null && e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
// A message for the rejection will be sent to the sender of the rejected packet
Message reply = new Message();
reply.setID(packet.getID());
reply.setTo(session.getAddress());
reply.setFrom(packet.getTo());
reply.setType(packet.getType());
reply.setThread(packet.getThread());
reply.setBody(e.getRejectionMessage());
session.process(reply);
}
}
}
use of org.jivesoftware.openfire.forward.Forwarded in project Openfire by igniterealtime.
the class RoutingTableImpl method routeToLocalDomain.
/**
* Routes packets that are sent to the XMPP domain itself (excluding subdomains).
*
* @param jid
* the recipient of the packet to route.
* @param packet
* the packet to route.
* @param fromServer
* true if the packet was created by the server. This packets
* should always be delivered
* @throws PacketException
* thrown if the packet is malformed (results in the sender's
* session being shutdown).
* @return <tt>true</tt> if the packet was routed successfully,
* <tt>false</tt> otherwise.
*/
private boolean routeToLocalDomain(JID jid, Packet packet, boolean fromServer) {
boolean routed = false;
Element privateElement = packet.getElement().element(QName.get("private", "urn:xmpp:carbons:2"));
boolean isPrivate = privateElement != null;
// The receiving server and SHOULD remove the <private/> element before delivering to the recipient.
packet.getElement().remove(privateElement);
if (jid.getResource() == null) {
// Packet sent to a bare JID of a user
if (packet instanceof Message) {
// Find best route of local user
routed = routeToBareJID(jid, (Message) packet, isPrivate);
} else {
throw new PacketException("Cannot route packet of type IQ or Presence to bare JID: " + packet.toXML());
}
} else {
// Packet sent to local user (full JID)
ClientRoute clientRoute = usersCache.get(jid.toString());
if (clientRoute == null) {
clientRoute = anonymousUsersCache.get(jid.toString());
}
if (clientRoute != null) {
if (!clientRoute.isAvailable() && routeOnlyAvailable(packet, fromServer) && !presenceUpdateHandler.hasDirectPresence(packet.getTo(), packet.getFrom())) {
Log.debug("Unable to route packet. Packet should only be sent to available sessions and the route is not available. {} ", packet.toXML());
routed = false;
} else {
if (localRoutingTable.isLocalRoute(jid)) {
if (packet instanceof Message) {
Message message = (Message) packet;
if (message.getType() == Message.Type.chat && !isPrivate) {
List<JID> routes = getRoutes(jid.asBareJID(), null);
for (JID route : routes) {
// The receiving server MUST NOT send a forwarded copy to the full JID the original <message/> stanza was addressed to, as that recipient receives the original <message/> stanza.
if (!route.equals(jid)) {
ClientSession clientSession = getClientRoute(route);
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(route.asBareJID());
// and the 'to' attribute MUST be the full JID of the resource receiving the copy
carbon.setTo(route);
// The content of the wrapping message MUST contain a <received/> element qualified by the namespace "urn:xmpp:carbons:2", which itself contains a <forwarded/> element qualified by the namespace "urn:xmpp:forward:0" that contains the original <message/>.
carbon.addExtension(new Received(new Forwarded(message)));
try {
localRoutingTable.getRoute(route.toString()).process(carbon);
} catch (UnauthorizedException e) {
Log.error("Unable to route packet " + packet.toXML(), e);
}
}
}
}
}
}
// This is a route to a local user hosted in this node
try {
localRoutingTable.getRoute(jid.toString()).process(packet);
routed = true;
} catch (UnauthorizedException e) {
Log.error("Unable to route packet " + packet.toXML(), e);
}
} else {
// This is a route to a local user hosted in other node
if (remotePacketRouter != null) {
routed = remotePacketRouter.routePacket(clientRoute.getNodeID().toByteArray(), jid, packet);
if (!routed) {
// drop invalid client route
removeClientRoute(jid);
}
}
}
}
}
}
return routed;
}
use of org.jivesoftware.openfire.forward.Forwarded in project Openfire by igniterealtime.
the class IQQueryHandler method sendMessageResult.
/**
* Send archived message to requesting client
* @param session Client session that send message to
* @param queryRequest Query request made by client
* @param archivedMessage Message to send to client
* @return
*/
private void sendMessageResult(Session session, QueryRequest queryRequest, ArchivedMessage archivedMessage) {
String stanzaText = archivedMessage.getStanza();
if (stanzaText == null || stanzaText.equals("")) {
// Try creating a fake one from the body.
if (archivedMessage.getBody() != null && !archivedMessage.getBody().equals("")) {
stanzaText = String.format("<message from=\"{}\" to=\"{}\" type=\"chat\"><body>{}</body>", archivedMessage.getWithJid(), archivedMessage.getWithJid(), archivedMessage.getBody());
} else {
// Don't send legacy archived messages (that have no stanza)
return;
}
}
Message messagePacket = new Message();
messagePacket.setTo(session.getAddress());
Forwarded fwd;
Document stanza;
try {
stanza = DocumentHelper.parseText(stanzaText);
fwd = new Forwarded(stanza.getRootElement(), archivedMessage.getTime(), null);
} catch (DocumentException e) {
Log.error("Failed to parse message stanza.", e);
// If we can't parse stanza then we have no message to send to client, abort
return;
}
// Shouldn't be possible.
if (fwd == null)
return;
messagePacket.addExtension(new Result(fwd, NAMESPACE, queryRequest.getQueryid(), archivedMessage.getId().toString()));
session.process(messagePacket);
}
Aggregations