mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-09 17:19:39 +02:00
Add support for XEP-0418: DNS Queries over XMPP (DoX)
Fixes SMACK-862.
This commit is contained in:
parent
75b1d8ce13
commit
62fd897cf7
20 changed files with 564 additions and 6 deletions
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.dox;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.StanzaError;
|
||||
import org.jivesoftware.smack.packet.StanzaError.Condition;
|
||||
import org.jivesoftware.smack.packet.StanzaError.Type;
|
||||
import org.jivesoftware.smack.util.RandomUtil;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.dox.element.DnsIq;
|
||||
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.minidns.dnsmessage.DnsMessage;
|
||||
import org.minidns.dnsmessage.Question;
|
||||
|
||||
public final class DnsOverXmppManager extends Manager {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(DnsOverXmppManager.class.getName());
|
||||
|
||||
private static final Map<XMPPConnection, DnsOverXmppManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
public static synchronized DnsOverXmppManager getInstanceFor(XMPPConnection connection) {
|
||||
DnsOverXmppManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new DnsOverXmppManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
private static final String NAMESPACE = DnsIq.NAMESPACE;
|
||||
|
||||
private static DnsOverXmppResolver defaultResolver;
|
||||
|
||||
public void setDefaultDnsOverXmppResolver(DnsOverXmppResolver resolver) {
|
||||
defaultResolver = resolver;
|
||||
}
|
||||
|
||||
private final ServiceDiscoveryManager serviceDiscoveryManager;
|
||||
|
||||
private DnsOverXmppResolver resolver = defaultResolver;
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
private final AbstractIqRequestHandler dnsIqRequestHandler = new AbstractIqRequestHandler(
|
||||
DnsIq.ELEMENT, DnsIq.NAMESPACE, IQ.Type.get, Mode.async) {
|
||||
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
DnsOverXmppResolver resolver = DnsOverXmppManager.this.resolver;
|
||||
if (resolver == null) {
|
||||
LOGGER.info("Resolver was null while attempting to handle " + iqRequest);
|
||||
return null;
|
||||
}
|
||||
|
||||
DnsIq dnsIqRequest = (DnsIq) iqRequest;
|
||||
DnsMessage query = dnsIqRequest.getDnsMessage();
|
||||
|
||||
DnsMessage response;
|
||||
try {
|
||||
response = resolver.resolve(query);
|
||||
} catch (IOException exception) {
|
||||
StanzaError.Builder errorBuilder = StanzaError.getBuilder()
|
||||
.setType(Type.CANCEL)
|
||||
.setCondition(Condition.internal_server_error)
|
||||
.setDescriptiveEnText("Exception while resolving your DNS query", exception)
|
||||
;
|
||||
|
||||
IQ errorResponse = IQ.createErrorResponse(iqRequest, errorBuilder);
|
||||
return errorResponse;
|
||||
}
|
||||
|
||||
DnsIq dnsIqResult = new DnsIq(response);
|
||||
dnsIqResult.setType(IQ.Type.result);
|
||||
return dnsIqResult;
|
||||
}
|
||||
};
|
||||
|
||||
private DnsOverXmppManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
this.serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
}
|
||||
|
||||
public synchronized void setDnsOverXmppResolver(DnsOverXmppResolver resolver) {
|
||||
this.resolver = resolver;
|
||||
if (resolver == null) {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void enable() {
|
||||
if (enabled) return;
|
||||
|
||||
if (resolver == null) {
|
||||
throw new IllegalStateException("No DnsOverXmppResolver configured");
|
||||
}
|
||||
|
||||
XMPPConnection connection = connection();
|
||||
if (connection == null) return;
|
||||
|
||||
connection.registerIQRequestHandler(dnsIqRequestHandler);
|
||||
serviceDiscoveryManager.addFeature(NAMESPACE);
|
||||
}
|
||||
|
||||
public synchronized void disable() {
|
||||
if (!enabled) return;
|
||||
|
||||
XMPPConnection connection = connection();
|
||||
if (connection == null) return;
|
||||
|
||||
serviceDiscoveryManager.removeFeature(NAMESPACE);
|
||||
connection.unregisterIQRequestHandler(dnsIqRequestHandler);
|
||||
}
|
||||
|
||||
public boolean isSupported(Jid jid)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return serviceDiscoveryManager.supportsFeature(jid, NAMESPACE);
|
||||
}
|
||||
|
||||
public DnsMessage query(Jid jid, Question question) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
DnsMessage queryMessage = DnsMessage.builder()
|
||||
.addQuestion(question)
|
||||
.setId(RandomUtil.nextSecureRandomInt())
|
||||
.setRecursionDesired(true)
|
||||
.build();
|
||||
return query(jid, queryMessage);
|
||||
}
|
||||
|
||||
public DnsMessage query(Jid jid, DnsMessage query)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
DnsIq queryIq = new DnsIq(query, jid);
|
||||
|
||||
DnsIq responseIq = connection().sendIqRequestAndWaitForResponse(queryIq);
|
||||
|
||||
return responseIq.getDnsMessage();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.dox;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.minidns.dnsmessage.DnsMessage;
|
||||
|
||||
public interface DnsOverXmppResolver {
|
||||
|
||||
DnsMessage resolve(DnsMessage query) throws IOException;
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.dox.element;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.minidns.dnsmessage.DnsMessage;
|
||||
|
||||
public class DnsIq extends IQ {
|
||||
|
||||
public static final String ELEMENT = "dns";
|
||||
public static final String NAMESPACE = "urn:xmpp:dox:0";
|
||||
|
||||
private final DnsMessage dnsMessage;
|
||||
|
||||
private String base64DnsMessage;
|
||||
|
||||
public DnsIq(String base64DnsMessage) throws IOException {
|
||||
this(Base64.decode(base64DnsMessage));
|
||||
this.base64DnsMessage = base64DnsMessage;
|
||||
}
|
||||
|
||||
public DnsIq(byte[] dnsMessage) throws IOException {
|
||||
this(new DnsMessage(dnsMessage));
|
||||
}
|
||||
|
||||
public DnsIq(DnsMessage dnsQuery, Jid to) {
|
||||
this(dnsQuery);
|
||||
setTo(to);
|
||||
setType(Type.get);
|
||||
}
|
||||
|
||||
public DnsIq(DnsMessage dnsMessage) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.dnsMessage = dnsMessage;
|
||||
}
|
||||
|
||||
public DnsMessage getDnsMessage() {
|
||||
return dnsMessage;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ByteBufferBackingArray")
|
||||
public String getDnsMessageBase64Encoded() {
|
||||
if (base64DnsMessage == null) {
|
||||
ByteBuffer byteBuffer = dnsMessage.getInByteBuffer();
|
||||
byte[] bytes = byteBuffer.array();
|
||||
base64DnsMessage = Base64.encodeToStringWithoutPadding(bytes);
|
||||
}
|
||||
return base64DnsMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.escape(getDnsMessageBase64Encoded());
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* XEP-0418: DNS Queries over XMPP (DoX) XML providers.
|
||||
*/
|
||||
package org.jivesoftware.smackx.dox.element;
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XEP-0418: DNS Queries over XMPP (Dox).
|
||||
*/
|
||||
package org.jivesoftware.smackx.dox;
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.dox.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smackx.dox.element.DnsIq;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
public class DnsIqProvider extends IQProvider<DnsIq> {
|
||||
|
||||
@Override
|
||||
public DnsIq parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment)
|
||||
throws XmlPullParserException, IOException, SmackParsingException {
|
||||
String base64DnsMessage = parser.nextText();
|
||||
return new DnsIq(base64DnsMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* XEP-0418: DNS Queries over XMPP (DoX) XML providers.
|
||||
*/
|
||||
package org.jivesoftware.smackx.dox.provider;
|
|
@ -317,4 +317,11 @@
|
|||
<className>org.jivesoftware.smackx.message_markup.provider.MarkupElementProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- XEP-0418: DNS Queries over XMPP (DoX) -->
|
||||
<iqProvider>
|
||||
<elementName>dns</elementName>
|
||||
<namespace>urn:xmpp:dox:0</namespace>
|
||||
<className>org.jivesoftware.smackx.dox.provider.DnsIqProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
</smackProviders>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue