mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-24 23:32:05 +01:00
[core] Properly reply to IQ requests
Properly reply to IQ requests with feature-not-implemented or service-unavailable. In case there is no IQ request handler but the IQ namespace is known, we reply with feature-not-implemented, otherwise with service-unavailable.
This commit is contained in:
parent
252cea1149
commit
533695c1b4
2 changed files with 53 additions and 13 deletions
|
@ -377,6 +377,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
private final Map<QName, IQRequestHandler> setIqRequestHandler = new HashMap<>();
|
private final Map<QName, IQRequestHandler> setIqRequestHandler = new HashMap<>();
|
||||||
private final Map<QName, IQRequestHandler> getIqRequestHandler = new HashMap<>();
|
private final Map<QName, IQRequestHandler> getIqRequestHandler = new HashMap<>();
|
||||||
|
private final Set<String> iqRequestHandlerNamespaces = new CopyOnWriteArraySet<>();
|
||||||
|
private final Map<String, Integer> iqRequestHandlerNamespacesReferenceCounters = new HashMap<>();
|
||||||
|
|
||||||
private final StanzaFactory stanzaFactory;
|
private final StanzaFactory stanzaFactory;
|
||||||
|
|
||||||
|
@ -1524,15 +1526,18 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
throw new IllegalStateException("Should only encounter IQ type 'get' or 'set'");
|
throw new IllegalStateException("Should only encounter IQ type 'get' or 'set'");
|
||||||
}
|
}
|
||||||
if (iqRequestHandler == null) {
|
if (iqRequestHandler == null) {
|
||||||
|
final String iqNamespace = key.getNamespaceURI();
|
||||||
StanzaError.Condition replyCondition;
|
StanzaError.Condition replyCondition;
|
||||||
switch (unknownIqRequestReplyMode) {
|
switch (unknownIqRequestReplyMode) {
|
||||||
case doNotReply:
|
case doNotReply:
|
||||||
return;
|
return;
|
||||||
case replyFeatureNotImplemented:
|
case reply:
|
||||||
replyCondition = StanzaError.Condition.feature_not_implemented;
|
boolean isKnownNamespace = iqRequestHandlerNamespaces.contains(iqNamespace);
|
||||||
break;
|
if (isKnownNamespace) {
|
||||||
case replyServiceUnavailable:
|
replyCondition = StanzaError.Condition.feature_not_implemented;
|
||||||
replyCondition = StanzaError.Condition.service_unavailable;
|
} else {
|
||||||
|
replyCondition = StanzaError.Condition.service_unavailable;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
|
@ -2043,18 +2048,35 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
@Override
|
@Override
|
||||||
public IQRequestHandler registerIQRequestHandler(final IQRequestHandler iqRequestHandler) {
|
public IQRequestHandler registerIQRequestHandler(final IQRequestHandler iqRequestHandler) {
|
||||||
final QName key = iqRequestHandler.getQName();
|
final QName key = iqRequestHandler.getQName();
|
||||||
|
IQRequestHandler previous;
|
||||||
switch (iqRequestHandler.getType()) {
|
switch (iqRequestHandler.getType()) {
|
||||||
case set:
|
case set:
|
||||||
synchronized (setIqRequestHandler) {
|
synchronized (setIqRequestHandler) {
|
||||||
return setIqRequestHandler.put(key, iqRequestHandler);
|
previous = setIqRequestHandler.put(key, iqRequestHandler);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case get:
|
case get:
|
||||||
synchronized (getIqRequestHandler) {
|
synchronized (getIqRequestHandler) {
|
||||||
return getIqRequestHandler.put(key, iqRequestHandler);
|
previous = getIqRequestHandler.put(key, iqRequestHandler);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Only IQ type of 'get' and 'set' allowed");
|
throw new IllegalArgumentException("Only IQ type of 'get' and 'set' allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final String iqNamespace = key.getNamespaceURI();
|
||||||
|
synchronized (iqRequestHandlerNamespacesReferenceCounters) {
|
||||||
|
Integer newValue;
|
||||||
|
Integer counter = iqRequestHandlerNamespacesReferenceCounters.get(iqNamespace);
|
||||||
|
if (counter == null) {
|
||||||
|
iqRequestHandlerNamespaces.add(iqNamespace);
|
||||||
|
newValue = 0;
|
||||||
|
} else {
|
||||||
|
newValue = counter.intValue() + 1;
|
||||||
|
}
|
||||||
|
iqRequestHandlerNamespacesReferenceCounters.put(iqNamespace, newValue);
|
||||||
|
}
|
||||||
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2065,19 +2087,38 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type) {
|
public IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type) {
|
||||||
|
IQRequestHandler unregisteredHandler;
|
||||||
final QName key = new QName(namespace, element);
|
final QName key = new QName(namespace, element);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case set:
|
case set:
|
||||||
synchronized (setIqRequestHandler) {
|
synchronized (setIqRequestHandler) {
|
||||||
return setIqRequestHandler.remove(key);
|
unregisteredHandler = setIqRequestHandler.remove(key);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case get:
|
case get:
|
||||||
synchronized (getIqRequestHandler) {
|
synchronized (getIqRequestHandler) {
|
||||||
return getIqRequestHandler.remove(key);
|
unregisteredHandler = getIqRequestHandler.remove(key);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Only IQ type of 'get' and 'set' allowed");
|
throw new IllegalArgumentException("Only IQ type of 'get' and 'set' allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unregisteredHandler == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (iqRequestHandlerNamespacesReferenceCounters) {
|
||||||
|
int newValue = iqRequestHandlerNamespacesReferenceCounters.get(namespace).intValue() - 1;
|
||||||
|
if (newValue == 0) {
|
||||||
|
iqRequestHandlerNamespacesReferenceCounters.remove(namespace);
|
||||||
|
iqRequestHandlerNamespaces.remove(namespace);
|
||||||
|
} else {
|
||||||
|
iqRequestHandlerNamespacesReferenceCounters.put(namespace, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unregisteredHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long lastStanzaReceived;
|
private long lastStanzaReceived;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2003-2007 Jive Software, 2018-2020 Florian Schmaus.
|
* Copyright 2003-2007 Jive Software, 2018-2021 Florian Schmaus.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -343,11 +343,10 @@ public final class SmackConfiguration {
|
||||||
|
|
||||||
public enum UnknownIqRequestReplyMode {
|
public enum UnknownIqRequestReplyMode {
|
||||||
doNotReply,
|
doNotReply,
|
||||||
replyFeatureNotImplemented,
|
reply,
|
||||||
replyServiceUnavailable,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UnknownIqRequestReplyMode unknownIqRequestReplyMode = UnknownIqRequestReplyMode.replyFeatureNotImplemented;
|
private static UnknownIqRequestReplyMode unknownIqRequestReplyMode = UnknownIqRequestReplyMode.reply;
|
||||||
|
|
||||||
public static UnknownIqRequestReplyMode getUnknownIqRequestReplyMode() {
|
public static UnknownIqRequestReplyMode getUnknownIqRequestReplyMode() {
|
||||||
return unknownIqRequestReplyMode;
|
return unknownIqRequestReplyMode;
|
||||||
|
|
Loading…
Reference in a new issue