use of org.jivesoftware.smack.packet.IQ in project Smack by igniterealtime.
the class PacketParserUtils method parseIQ.
/**
* Parses an IQ packet.
*
* @param parser the XML parser, positioned at the start of an IQ packet.
* @return an IQ object.
* @throws Exception
*/
public static IQ parseIQ(XmlPullParser parser) throws Exception {
ParserUtils.assertAtStartTag(parser);
final int initialDepth = parser.getDepth();
IQ iqPacket = null;
XMPPError.Builder error = null;
final String id = parser.getAttributeValue("", "id");
final Jid to = ParserUtils.getJidAttribute(parser, "to");
final Jid from = ParserUtils.getJidAttribute(parser, "from");
final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));
outerloop: while (true) {
int eventType = parser.next();
switch(eventType) {
case XmlPullParser.START_TAG:
String elementName = parser.getName();
String namespace = parser.getNamespace();
switch(elementName) {
case "error":
error = PacketParserUtils.parseError(parser);
break;
// this element name and namespace.
default:
IQProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace);
if (provider != null) {
iqPacket = provider.parse(parser);
} else // Note that if we reach this code, it is guranteed that the result IQ contained a child element
// (RFC 6120 ยง 8.2.3 6) because otherwhise we would have reached the END_TAG first.
{
// No Provider found for the IQ stanza, parse it to an UnparsedIQ instance
// so that the content of the IQ can be examined later on
iqPacket = new UnparsedIQ(elementName, namespace, parseElement(parser));
}
break;
}
break;
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
}
}
// Decide what to do when an IQ packet was not understood
if (iqPacket == null) {
switch(type) {
case error:
// If an IQ packet wasn't created above, create an empty error IQ packet.
iqPacket = new ErrorIQ(error);
break;
case result:
iqPacket = new EmptyResultIQ();
break;
default:
break;
}
}
// Set basic values on the iq packet.
iqPacket.setStanzaId(id);
iqPacket.setTo(to);
iqPacket.setFrom(from);
iqPacket.setType(type);
iqPacket.setError(error);
return iqPacket;
}
use of org.jivesoftware.smack.packet.IQ in project Smack by igniterealtime.
the class AbstractXMPPConnection method invokeStanzaCollectorsAndNotifyRecvListeners.
/**
* Invoke {@link StanzaCollector#processStanza(Stanza)} for every
* StanzaCollector with the given packet. Also notify the receive listeners with a matching stanza(/packet) filter about the packet.
*
* @param packet the stanza(/packet) to notify the StanzaCollectors and receive listeners about.
*/
protected void invokeStanzaCollectorsAndNotifyRecvListeners(final Stanza packet) {
if (packet instanceof IQ) {
final IQ iq = (IQ) packet;
final IQ.Type type = iq.getType();
switch(type) {
case set:
case get:
final String key = XmppStringUtils.generateKey(iq.getChildElementName(), iq.getChildElementNamespace());
IQRequestHandler iqRequestHandler = null;
switch(type) {
case set:
synchronized (setIqRequestHandler) {
iqRequestHandler = setIqRequestHandler.get(key);
}
break;
case get:
synchronized (getIqRequestHandler) {
iqRequestHandler = getIqRequestHandler.get(key);
}
break;
default:
throw new IllegalStateException("Should only encounter IQ type 'get' or 'set'");
}
if (iqRequestHandler == null) {
if (!replyToUnkownIq) {
return;
}
// If the IQ stanza is of type "get" or "set" with no registered IQ request handler, then answer an
// IQ of type 'error' with condition 'service-unavailable'.
ErrorIQ errorIQ = IQ.createErrorResponse(iq, XMPPError.getBuilder((XMPPError.Condition.service_unavailable)));
try {
sendStanza(errorIQ);
} catch (InterruptedException | NotConnectedException e) {
LOGGER.log(Level.WARNING, "Exception while sending error IQ to unkown IQ request", e);
}
} else {
ExecutorService executorService = null;
switch(iqRequestHandler.getMode()) {
case sync:
executorService = singleThreadedExecutorService;
break;
case async:
executorService = cachedExecutorService;
break;
}
final IQRequestHandler finalIqRequestHandler = iqRequestHandler;
executorService.execute(new Runnable() {
@Override
public void run() {
IQ response = finalIqRequestHandler.handleIQRequest(iq);
if (response == null) {
// e.g. to avoid presence leaks.
return;
}
try {
sendStanza(response);
} catch (InterruptedException | NotConnectedException e) {
LOGGER.log(Level.WARNING, "Exception while sending response to IQ request", e);
}
}
});
// desired behavior.
return;
}
break;
default:
break;
}
}
// First handle the async recv listeners. Note that this code is very similar to what follows a few lines below,
// the only difference is that asyncRecvListeners is used here and that the packet listeners are started in
// their own thread.
final Collection<StanzaListener> listenersToNotify = new LinkedList<StanzaListener>();
synchronized (asyncRecvListeners) {
for (ListenerWrapper listenerWrapper : asyncRecvListeners.values()) {
if (listenerWrapper.filterMatches(packet)) {
listenersToNotify.add(listenerWrapper.getListener());
}
}
}
for (final StanzaListener listener : listenersToNotify) {
asyncGo(new Runnable() {
@Override
public void run() {
try {
listener.processStanza(packet);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Exception in async packet listener", e);
}
}
});
}
// Loop through all collectors and notify the appropriate ones.
for (StanzaCollector collector : collectors) {
collector.processStanza(packet);
}
// Notify the receive listeners interested in the packet
listenersToNotify.clear();
synchronized (syncRecvListeners) {
for (ListenerWrapper listenerWrapper : syncRecvListeners.values()) {
if (listenerWrapper.filterMatches(packet)) {
listenersToNotify.add(listenerWrapper.getListener());
}
}
}
// Decouple incoming stanza processing from listener invocation. Unlike async listeners, this uses a single
// threaded executor service and therefore keeps the order.
singleThreadedExecutorService.execute(new Runnable() {
@Override
public void run() {
for (StanzaListener listener : listenersToNotify) {
try {
listener.processStanza(packet);
} catch (NotConnectedException e) {
LOGGER.log(Level.WARNING, "Got not connected exception, aborting", e);
break;
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Exception in packet listener", e);
}
}
}
});
}
use of org.jivesoftware.smack.packet.IQ in project Smack by igniterealtime.
the class IQTest method testFullJIDToOfflineUser.
/**
* Check that sending an IQ to a full JID that is offline returns an IQ ERROR instead
* of being route to some other resource of the same user.
*/
public void testFullJIDToOfflineUser() {
// Request the version from the server.
Version versionRequest = new Version();
versionRequest.setType(IQ.Type.get);
versionRequest.setFrom(getFullJID(0));
versionRequest.setTo(getBareJID(0) + "/Something");
// Create a packet collector to listen for a response.
StanzaCollector collector = getConnection(0).createStanzaCollector(new PacketIDFilter(versionRequest.getStanzaId()));
getConnection(0).sendStanza(versionRequest);
// Wait up to 5 seconds for a result.
IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
collector.cancel();
assertNotNull("No response from server", result);
assertEquals("The server didn't reply with an error packet", IQ.Type.error, result.getType());
assertEquals("Server answered an incorrect error code", 503, result.getError().getCode());
}
use of org.jivesoftware.smack.packet.IQ in project Smack by igniterealtime.
the class IQTest method testInvalidNamespace.
/**
* Check that the server responds a 503 error code when the client sends an IQ stanza(/packet) with an
* invalid namespace.
*/
public void testInvalidNamespace() {
IQ iq = new IQ() {
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<query xmlns=\"jabber:iq:anything\">");
buf.append("</query>");
return buf.toString();
}
};
PacketFilter filter = new AndFilter(new PacketIDFilter(iq.getStanzaId()), new StanzaTypeFilter(IQ.class));
StanzaCollector collector = getConnection(0).createStanzaCollector(filter);
// Send the iq packet with an invalid namespace
getConnection(0).sendStanza(iq);
IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
collector.cancel();
if (result == null) {
fail("No response from server");
} else if (result.getType() != IQ.Type.error) {
fail("The server didn't reply with an error packet");
} else {
assertEquals("Server answered an incorrect error code", 503, result.getError().getCode());
}
}
use of org.jivesoftware.smack.packet.IQ in project jitsi by jitsi.
the class ColibriConferenceIQ method createGracefulShutdownErrorResponse.
/**
* Returns an error response for given <tt>IQ</tt> that is returned by
* the videobridge after it has entered graceful shutdown mode and new
* conferences can no longer be created.
*
* @param request the IQ for which error response will be created.
* @return an IQ of 'error' type and 'service-unavailable' condition plus
* the body of request IQ.
*/
public static IQ createGracefulShutdownErrorResponse(final IQ request) {
final XMPPError error = new XMPPError(XMPPError.Condition.service_unavailable);
error.addExtension(new GracefulShutdown());
final IQ result = IQ.createErrorResponse(request, error);
result.setType(Type.ERROR);
result.setPacketID(request.getPacketID());
result.setFrom(request.getTo());
result.setTo(request.getFrom());
result.setError(error);
return result;
}
Aggregations