use of org.xmpp.packet.IQ in project Openfire by igniterealtime.
the class MultiUserChatServiceImpl method process.
/**
* Returns true if the IQ packet was processed. This method should only process disco packets
* as well as jabber:iq:register packets sent to the MUC service.
*
* @param iq the IQ packet to process.
* @return true if the IQ packet was processed.
*/
private boolean process(final IQ iq) {
final Element childElement = iq.getChildElement();
String namespace = null;
// Ignore IQs of type ERROR
if (IQ.Type.error == iq.getType()) {
return false;
}
if (iq.getTo().getResource() != null) {
// Ignore IQ packets sent to room occupants
return false;
}
if (childElement != null) {
namespace = childElement.getNamespaceURI();
}
if ("jabber:iq:register".equals(namespace)) {
final IQ reply = registerHandler.handleIQ(iq);
XMPPServer.getInstance().getPacketRouter().route(reply);
} else if ("jabber:iq:search".equals(namespace)) {
final IQ reply = searchHandler.handleIQ(iq);
XMPPServer.getInstance().getPacketRouter().route(reply);
} else if (IQMuclumbusSearchHandler.NAMESPACE.equals(namespace)) {
final IQ reply = muclumbusSearchHandler.handleIQ(iq);
XMPPServer.getInstance().getPacketRouter().route(reply);
} else if (IQMUCvCardHandler.NAMESPACE.equals(namespace)) {
final IQ reply = mucVCardHandler.handleIQ(iq);
XMPPServer.getInstance().getPacketRouter().route(reply);
} else if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
// TODO MUC should have an IQDiscoInfoHandler of its own when MUC becomes
// a component
final IQ reply = XMPPServer.getInstance().getIQDiscoInfoHandler().handleIQ(iq);
XMPPServer.getInstance().getPacketRouter().route(reply);
} else if ("http://jabber.org/protocol/disco#items".equals(namespace)) {
// TODO MUC should have an IQDiscoItemsHandler of its own when MUC becomes
// a component
final IQ reply = XMPPServer.getInstance().getIQDiscoItemsHandler().handleIQ(iq);
XMPPServer.getInstance().getPacketRouter().route(reply);
} else if ("urn:xmpp:ping".equals(namespace)) {
XMPPServer.getInstance().getPacketRouter().route(IQ.createResultIQ(iq));
} else if (this.iqHandlers != null) {
final IQHandler h = this.iqHandlers.get(namespace);
if (h != null) {
try {
final IQ reply = h.handleIQ(iq);
if (reply != null) {
XMPPServer.getInstance().getPacketRouter().route(reply);
}
} catch (final UnauthorizedException e) {
final IQ reply = IQ.createResultIQ(iq);
reply.setType(IQ.Type.error);
reply.setError(PacketError.Condition.service_unavailable);
XMPPServer.getInstance().getPacketRouter().route(reply);
}
return true;
}
return false;
} else {
return false;
}
return true;
}
use of org.xmpp.packet.IQ in project Openfire by igniterealtime.
the class MultiUserChatServiceImpl method isPendingPingResponse.
/**
* Determines if a stanza is a client-generated response to an IQ Ping request sent by this server.
*
* A 'true' result of this method indicates that the client sending the IQ response is currently reachable.
*
* @param stanza The stanza to check
* @return true if the stanza is a response to an IQ Ping request sent by the server, otherwise false.
*/
public boolean isPendingPingResponse(@Nonnull final Packet stanza) {
if (!(stanza instanceof IQ)) {
return false;
}
final IQ iq = (IQ) stanza;
if (iq.isRequest()) {
return false;
}
// Check if this is an error to a ghost-detection ping that we've sent out. Note that clients that are
// connected but do not support XEP-0199 should send back a 'service-unavailable' error per the XEP, but
// some clients are known to send 'feature-not-available'. Treat these as indications that the client is
// still connected.
final Collection<PacketError.Condition> pingErrorsIndicatingClientConnectivity = Arrays.asList(PacketError.Condition.service_unavailable, PacketError.Condition.feature_not_implemented);
final JID jid = PINGS_SENT.get(iq.getID());
final boolean result = jid != null && iq.getFrom().equals(jid) && (iq.getError() == null || pingErrorsIndicatingClientConnectivity.contains(iq.getError().getCondition()));
if (result) {
// If this is _not_ a valid response, 'isDeliveryRelatedErrorResponse' might want to process this. Otherwise, remove.
PINGS_SENT.remove(iq.getID());
}
return result;
}
use of org.xmpp.packet.IQ in project Openfire by igniterealtime.
the class MultiUserChatServiceImpl method pingOccupant.
/**
* Sends an IQ Ping request to an occupant, and schedules a check that determines if a response to that request
* was received (removing the occupant if it is not).
*
* @param occupant The occupant to ping.
*/
private void pingOccupant(@Nonnull final OccupantManager.Occupant occupant) {
Log.debug("Pinging {} as the occupant is exceeding the idle time limit.", occupant);
final IQ pingRequest = new IQ(IQ.Type.get);
pingRequest.setChildElement(IQPingHandler.ELEMENT_NAME, IQPingHandler.NAMESPACE);
pingRequest.setFrom(occupant.getRoomName() + "@" + getServiceDomain());
pingRequest.setTo(occupant.getRealJID());
// Generate unique ID, to prevent duplicate cache entries.
pingRequest.setID(UUID.randomUUID().toString());
XMPPServer.getInstance().getPacketRouter().route(pingRequest);
PINGS_SENT.put(pingRequest.getID(), pingRequest.getTo());
// Schedule a check to see if the ping was answered, kicking the occupant if it wasn't.
// The check should be done _before_ the next ping would be sent (to prevent a backlog of ping requests forming)
long timeoutMs = userIdlePing.dividedBy(4).toMillis();
final CheckPingResponseTask task = new CheckPingResponseTask(occupant, pingRequest.getID());
occupant.setPendingPingTask(task);
TaskEngine.getInstance().schedule(task, timeoutMs);
}
use of org.xmpp.packet.IQ in project Openfire by igniterealtime.
the class SoftwareVersionManager method resourceBound.
@Override
public void resourceBound(final Session session) {
if (!VERSION_QUERY_ENABLED.getValue()) {
return;
}
// Prevent retaining a reference to the session object, while waiting for the right time to execute the query.
// There's (unproven) concern that this is a factor in issue OF-2367. Better safe than sorry.
final JID address = session.getAddress();
// The server should not send requests to the client before the client session
// has been established (see IQSessionEstablishmentHandler). Sadly, Openfire
// does not provide a hook for this. For now, the resource bound event is
// used instead (which should be immediately followed by session establishment).
TaskEngine.getInstance().schedule(new TimerTask() {
@Override
public void run() {
try {
final Session session = SessionManager.getInstance().getSession(address);
if (session == null || session.isClosed() || !VERSION_QUERY_ENABLED.getValue()) {
return;
}
IQ versionRequest = new IQ(IQ.Type.get);
versionRequest.setTo(session.getAddress());
versionRequest.setFrom(session.getServerName());
versionRequest.setChildElement("query", "jabber:iq:version");
session.process(versionRequest);
} catch (Exception e) {
Log.error("Exception while trying to query a client ({}) for its software version.", session.getAddress(), e);
}
}
}, // Let time pass for the session establishment to have occurred.
VERSION_QUERY_DELAY.getValue().toMillis());
}
use of org.xmpp.packet.IQ in project Openfire by igniterealtime.
the class SearchPlugin method handleIQRequest.
/**
* Handles IQ requests. This method throws an IllegalArgumentException if an IQ stanza is supplied that is not a request (if the stanza
* is not of type 'get' or 'set'). This method will either throw an Exception, or return a non-null IQ stanza of type 'error' or
* 'result', as XMPP Core specifies that <strong>all</strong> IQ request stanza's (type 'get' or 'set') MUST be replied to.
*
* @param iq
* The IQ stanza that forms the request.
* @return The response to the request.
*/
private IQ handleIQRequest(IQ iq) {
// 'final' to ensure that it is set.
final IQ replyPacket;
if (iq == null) {
throw new IllegalArgumentException("Argument 'iq' cannot be null.");
}
final IQ.Type type = iq.getType();
if (type != IQ.Type.get && type != IQ.Type.set) {
throw new IllegalArgumentException("Argument 'iq' must be of type 'get' or 'set'");
}
final Element childElement = iq.getChildElement();
if (childElement == null) {
replyPacket = IQ.createResultIQ(iq);
replyPacket.setError(new PacketError(Condition.bad_request, org.xmpp.packet.PacketError.Type.modify, "IQ stanzas of type 'get' and 'set' MUST contain one and only one child element (RFC 3920 section 9.2.3)."));
return replyPacket;
}
final String namespace = childElement.getNamespaceURI();
if (namespace == null) {
replyPacket = IQ.createResultIQ(iq);
replyPacket.setError(Condition.feature_not_implemented);
return replyPacket;
}
if (namespace.equals(NAMESPACE_JABBER_IQ_SEARCH)) {
replyPacket = handleSearchRequest(iq);
} else if (namespace.equals(IQDiscoInfoHandler.NAMESPACE_DISCO_INFO)) {
replyPacket = handleDiscoInfo(iq);
} else if (namespace.equals(IQDiscoItemsHandler.NAMESPACE_DISCO_ITEMS)) {
replyPacket = IQ.createResultIQ(iq);
replyPacket.setChildElement("query", IQDiscoItemsHandler.NAMESPACE_DISCO_ITEMS);
} else {
// don't known what to do with this.
replyPacket = IQ.createResultIQ(iq);
replyPacket.setError(Condition.feature_not_implemented);
}
return replyPacket;
}
Aggregations