diff --git a/documentation/extensions/index.md b/documentation/extensions/index.md index 05eb8e311..44739287b 100644 --- a/documentation/extensions/index.md +++ b/documentation/extensions/index.md @@ -103,6 +103,7 @@ Experimental Smack Extensions and currently supported XEPs of smack-experimental | [OMEMO Multi End Message and Object Encryption](omemo.md) | [XEP-0384](https://xmpp.org/extensions/xep-0384.html) | n/a | Encrypt messages using OMEMO encryption (currently only with smack-omemo-signal -> GPLv3). | | [Consistent Color Generation](consistent_colors.md) | [XEP-0392](https://xmpp.org/extensions/xep-0392.html) | 0.4.0 | Generate consistent colors for identifiers like usernames to provide a consistent user experience. | | [Message Markup](messagemarkup.md) | [XEP-0394](https://xmpp.org/extensions/xep-0394.html) | 0.1.0 | Style message bodies while keeping body and markup information separated. | +| DNS Queries over XMPP (DoX) | [XEP-0418](https://xmpp.org/extensions/xep-0418.html) | 0.1.0 | Send DNS queries and responses over XMPP. | Unofficial XMPP Extensions -------------------------- diff --git a/settings.gradle b/settings.gradle index 53b0bd554..6188d60b6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,6 +12,7 @@ include 'smack-core', 'smack-debug-slf4j', 'smack-resolver-dnsjava', 'smack-resolver-minidns', + 'smack-resolver-minidns-dox', 'smack-resolver-javax', 'smack-sasl-javax', 'smack-sasl-provided', diff --git a/smack-android/src/main/java/org/jivesoftware/smack/util/stringencoder/android/AndroidBase64Encoder.java b/smack-android/src/main/java/org/jivesoftware/smack/util/stringencoder/android/AndroidBase64Encoder.java index 42346274b..8e4d47d6c 100644 --- a/smack-android/src/main/java/org/jivesoftware/smack/util/stringencoder/android/AndroidBase64Encoder.java +++ b/smack-android/src/main/java/org/jivesoftware/smack/util/stringencoder/android/AndroidBase64Encoder.java @@ -46,6 +46,11 @@ public final class AndroidBase64Encoder implements org.jivesoftware.smack.util.s return Base64.encodeToString(input, BASE64_ENCODER_FLAGS); } + @Override + public String encodeToStringWithoutPadding(byte[] input) { + return Base64.encodeToString(input, BASE64_ENCODER_FLAGS | Base64.NO_PADDING); + } + @Override public byte[] encode(byte[] input) { return Base64.encode(input, BASE64_ENCODER_FLAGS); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/RandomUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/RandomUtil.java index 6a0c617ba..857557869 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/RandomUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/RandomUtil.java @@ -43,4 +43,8 @@ public class RandomUtil { public static int nextSecureRandomInt(int bound) { return SECURE_RANDOM.get().nextInt(bound); } + + public static int nextSecureRandomInt() { + return SECURE_RANDOM.get().nextInt(); + } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/stringencoder/Base64.java b/smack-core/src/main/java/org/jivesoftware/smack/util/stringencoder/Base64.java index bf19067d9..e98e84197 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/stringencoder/Base64.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/stringencoder/Base64.java @@ -39,18 +39,17 @@ public class Base64 { } public static final String encodeToString(byte[] input) { - byte[] bytes = encode(input); - try { - return new String(bytes, StringUtils.USASCII); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } + return base64encoder.encodeToString(input); } public static final String encodeToString(byte[] input, int offset, int len) { return encodeToString(slice(input, offset, len)); } + public static final String encodeToStringWithoutPadding(byte[] input) { + return base64encoder.encodeToStringWithoutPadding(input); + } + public static final byte[] encode(byte[] input) { return base64encoder.encode(input); } @@ -103,6 +102,8 @@ public class Base64 { String encodeToString(byte[] input); + String encodeToStringWithoutPadding(byte[] input); + byte[] encode(byte[] input); } } diff --git a/smack-core/src/test/java/org/jivesoftware/smack/test/util/SmackTestSuite.java b/smack-core/src/test/java/org/jivesoftware/smack/test/util/SmackTestSuite.java index 889a32483..ae60c4543 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/test/util/SmackTestSuite.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/test/util/SmackTestSuite.java @@ -39,6 +39,11 @@ public class SmackTestSuite { return Base64.getEncoder().encodeToString(input); } + @Override + public String encodeToStringWithoutPadding(byte[] input) { + return Base64.getEncoder().withoutPadding().encodeToString(input); + } + @Override public byte[] encode(byte[] input) { return Base64.getEncoder().encode(input); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppManager.java new file mode 100644 index 000000000..092c1ce91 --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppManager.java @@ -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 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(); + } +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppResolver.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppResolver.java new file mode 100644 index 000000000..26f6cfa5e --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppResolver.java @@ -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; + +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/DnsIq.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/DnsIq.java new file mode 100644 index 000000000..77c626eae --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/DnsIq.java @@ -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; + } + +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/package-info.java new file mode 100644 index 000000000..163c14fb8 --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/package-info.java @@ -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; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/package-info.java new file mode 100644 index 000000000..0aa8e5137 --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/package-info.java @@ -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; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/provider/DnsIqProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/provider/DnsIqProvider.java new file mode 100644 index 000000000..3800060eb --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/provider/DnsIqProvider.java @@ -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 { + + @Override + public DnsIq parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) + throws XmlPullParserException, IOException, SmackParsingException { + String base64DnsMessage = parser.nextText(); + return new DnsIq(base64DnsMessage); + } + +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/provider/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/provider/package-info.java new file mode 100644 index 000000000..c0c8ce8fe --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/provider/package-info.java @@ -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; diff --git a/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers b/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers index a47159e88..974c149f2 100644 --- a/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers +++ b/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers @@ -317,4 +317,11 @@ org.jivesoftware.smackx.message_markup.provider.MarkupElementProvider + + + dns + urn:xmpp:dox:0 + org.jivesoftware.smackx.dox.provider.DnsIqProvider + + diff --git a/smack-java7/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java b/smack-java7/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java index 3ea688c92..6b8d07252 100644 --- a/smack-java7/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java +++ b/smack-java7/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java @@ -27,10 +27,13 @@ public final class Java7Base64Encoder implements org.jivesoftware.smack.util.str private static final Java7Base64Encoder instance = new Java7Base64Encoder(); private final Base64.Encoder encoder; + private final Base64.Encoder encoderWithoutPadding; + private final Base64.Decoder decoder; private Java7Base64Encoder() { encoder = Base64.getEncoder(); + encoderWithoutPadding = encoder.withoutPadding(); decoder = Base64.getDecoder(); } @@ -48,6 +51,11 @@ public final class Java7Base64Encoder implements org.jivesoftware.smack.util.str return encoder.encodeToString(input); } + @Override + public String encodeToStringWithoutPadding(byte[] input) { + return encoderWithoutPadding.encodeToString(input); + } + @Override public byte[] encode(byte[] input) { return encoder.encode(input); diff --git a/smack-repl/build.gradle b/smack-repl/build.gradle index aac8253e9..2b36f85ef 100644 --- a/smack-repl/build.gradle +++ b/smack-repl/build.gradle @@ -14,6 +14,7 @@ dependencies { compile project(':smack-bosh') compile project(':smack-java7') compile project(':smack-resolver-minidns') + compile project(':smack-resolver-minidns-dox') compile project(':smack-extensions') compile project(':smack-experimental') compile project(':smack-legacy') diff --git a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java new file mode 100644 index 000000000..ddab89d4d --- /dev/null +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java @@ -0,0 +1,78 @@ +/** + * + * 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.igniterealtime.smack.smackrepl; + +import java.io.IOException; + +import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.debugger.ConsoleDebugger; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.jivesoftware.smackx.dox.DnsOverXmppManager; +import org.jivesoftware.smackx.dox.resolver.minidns.DnsOverXmppMiniDnsResolver; + +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.minidns.dnsmessage.DnsMessage; +import org.minidns.dnsmessage.Question; +import org.minidns.record.Record; + +public class DoX { + + public static void main(String[] args) throws XMPPException, SmackException, IOException, InterruptedException { + SmackConfiguration.DEBUG = true; + + XMPPTCPConnection connection = new XMPPTCPConnection(args[0], args[1]); + connection.setReplyTimeout(60000); + + connection.connect().login(); + + DnsOverXmppManager dox = DnsOverXmppManager.getInstanceFor(connection); + + Jid target = JidCreate.from("dns@moparisthebest.com/listener"); + Question question = new Question("geekplace.eu", Record.TYPE.A); + + DnsMessage response = dox.query(target, question); + + // CHECKSTYLE:OFF + System.out.println(response); + // CHECKSTYLE:ON + + connection.disconnect(); + } + + public static XMPPTCPConnection runDoxResolver(String jid, String password) + throws XMPPException, SmackException, IOException, InterruptedException { + XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() + .setXmppAddressAndPassword(jid, password) + .setResource("dns") + .setDebuggerFactory(ConsoleDebugger.Factory.INSTANCE) + .build(); + XMPPTCPConnection connection = new XMPPTCPConnection(config); + + connection.connect().login(); + + DnsOverXmppManager dox = DnsOverXmppManager.getInstanceFor(connection); + dox.setDnsOverXmppResolver(DnsOverXmppMiniDnsResolver.INSTANCE); + + dox.enable(); + + return connection; + } +} diff --git a/smack-resolver-minidns-dox/build.gradle b/smack-resolver-minidns-dox/build.gradle new file mode 100644 index 000000000..62c973774 --- /dev/null +++ b/smack-resolver-minidns-dox/build.gradle @@ -0,0 +1,7 @@ +description = """\ +DNS over XMPP (DoX) support using MiniDNS.""" + +dependencies { + compile project(path: ':smack-resolver-minidns') + compile project(path: ':smack-experimental') +} diff --git a/smack-resolver-minidns-dox/src/main/java/org/jivesoftware/smackx/dox/resolver/minidns/DnsOverXmppMiniDnsResolver.java b/smack-resolver-minidns-dox/src/main/java/org/jivesoftware/smackx/dox/resolver/minidns/DnsOverXmppMiniDnsResolver.java new file mode 100644 index 000000000..e3a1f9d64 --- /dev/null +++ b/smack-resolver-minidns-dox/src/main/java/org/jivesoftware/smackx/dox/resolver/minidns/DnsOverXmppMiniDnsResolver.java @@ -0,0 +1,47 @@ +/** + * + * 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.resolver.minidns; + +import java.io.IOException; + +import org.jivesoftware.smackx.dox.DnsOverXmppResolver; + +import org.minidns.DnsClient; +import org.minidns.dnsmessage.DnsMessage; +import org.minidns.dnsmessage.Question; +import org.minidns.dnsqueryresult.DnsQueryResult; + +public class DnsOverXmppMiniDnsResolver implements DnsOverXmppResolver { + + public static final DnsOverXmppMiniDnsResolver INSTANCE = new DnsOverXmppMiniDnsResolver(new DnsClient()); + + private final DnsClient dnsClient; + + public DnsOverXmppMiniDnsResolver(DnsClient dnsClient) { + this.dnsClient = dnsClient; + } + + @Override + public DnsMessage resolve(DnsMessage query) throws IOException { + Question question = query.getQuestion(); + + DnsQueryResult dnsQueryResult = dnsClient.query(question); + + return dnsQueryResult.response; + } + +} diff --git a/smack-resolver-minidns-dox/src/main/java/org/jivesoftware/smackx/dox/resolver/minidns/package-info.java b/smack-resolver-minidns-dox/src/main/java/org/jivesoftware/smackx/dox/resolver/minidns/package-info.java new file mode 100644 index 000000000..e101e6f20 --- /dev/null +++ b/smack-resolver-minidns-dox/src/main/java/org/jivesoftware/smackx/dox/resolver/minidns/package-info.java @@ -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) using MiniDNS. + */ +package org.jivesoftware.smackx.dox.resolver.minidns;