diff --git a/pom.xml b/pom.xml index 5896501..397a424 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,7 @@ 3.5.0 5.14.1 3.26.3 + 3.6.2 @@ -55,6 +56,11 @@ io.quarkus quarkus-arc + + dnsjava + dnsjava + ${dnsjava.version} + io.quarkus quarkus-junit5 diff --git a/src/main/java/de/rpr/ddnsclient/Updater.java b/src/main/java/de/rpr/ddnsclient/Updater.java index 1334f28..7d6a711 100644 --- a/src/main/java/de/rpr/ddnsclient/Updater.java +++ b/src/main/java/de/rpr/ddnsclient/Updater.java @@ -47,7 +47,7 @@ public class Updater { void run() { log.trace("Updater running."); - if(config.isEmpty()) { + if (config.isEmpty()) { throw new IllegalStateException("Missing configuration"); } diff --git a/src/main/java/de/rpr/ddnsclient/lookup/DnsJava.java b/src/main/java/de/rpr/ddnsclient/lookup/DnsJava.java new file mode 100644 index 0000000..d48c771 --- /dev/null +++ b/src/main/java/de/rpr/ddnsclient/lookup/DnsJava.java @@ -0,0 +1,48 @@ +package de.rpr.ddnsclient.lookup; + +import de.rpr.ddnsclient.model.IPs; +import jakarta.enterprise.context.ApplicationScoped; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.xbill.DNS.Record; +import org.xbill.DNS.*; + +import java.util.Optional; + +@ApplicationScoped +public class DnsJava implements DnsResolver { + + private final String resolverAddress; + + public DnsJava(@ConfigProperty(name = "", defaultValue = "9.9.9.9") String resolverAddress) { + this.resolverAddress = resolverAddress; + } + + @Override + public IPs resolve(String hostname) { + String v4 = getIp(hostname, Type.A).orElseThrow(() -> new RuntimeException("Missing A Record")); + String v6 = getIp(hostname, Type.AAAA).orElseThrow(() -> new RuntimeException("Missing AAAA Record")); + return new IPs(v4, v6); + } + + private Optional getIp(String hostname, int type) { + try { + SimpleResolver resolver = new SimpleResolver(resolverAddress); + + Lookup lookup = new Lookup(hostname, type); + lookup.setResolver(resolver); + + Record[] records = lookup.run(); + for (Record record : records) { + if (record instanceof ARecord) { + return Optional.of(((ARecord) record).getAddress().getHostAddress()); + } + if (record instanceof AAAARecord) { + return Optional.of(((AAAARecord) record).getAddress().getHostAddress()); + } + } + return Optional.empty(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java b/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java index 9a54e77..757b5db 100644 --- a/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java +++ b/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java @@ -1,48 +1,7 @@ package de.rpr.ddnsclient.lookup; - import de.rpr.ddnsclient.model.IPs; -import jakarta.enterprise.context.ApplicationScoped; -import org.jboss.logging.Logger; -import javax.naming.NamingException; -import javax.naming.directory.Attributes; -import javax.naming.directory.DirContext; - -@ApplicationScoped -public class DnsResolver { - - private static final Logger log = Logger.getLogger(DnsResolver.class); - - public static final int MAX_RETRIES = 5; - private final DirContext dirContext; - - DnsResolver(DirContext dirContext) { - this.dirContext = dirContext; - } - - public IPs resolve(String hostname) { - - log.tracef("Trying to resolve %s", hostname); - - int resolveCounter = 0; - try { - Attributes result; - do { - if (resolveCounter == MAX_RETRIES) { - throw new IllegalStateException("Couldn't resolve all attributes"); - } - resolveCounter++; - log.tracef("Try #%d", resolveCounter); - result = dirContext.getAttributes(hostname, new String[]{"A", "AAAA"}); - } while (result.size() != 2); - - return new IPs( - result.get("A").get().toString(), - result.get("AAAA").get().toString() - ); - } catch (NamingException e) { - throw new RuntimeException(e); - } - } +public interface DnsResolver { + IPs resolve(String hostname); } diff --git a/src/main/java/de/rpr/ddnsclient/lookup/PublicIpLookup.java b/src/main/java/de/rpr/ddnsclient/lookup/PublicIpLookup.java index 890ba97..a05f693 100644 --- a/src/main/java/de/rpr/ddnsclient/lookup/PublicIpLookup.java +++ b/src/main/java/de/rpr/ddnsclient/lookup/PublicIpLookup.java @@ -1,7 +1,6 @@ package de.rpr.ddnsclient.lookup; import de.rpr.ddnsclient.model.IPs; -import io.quarkus.runtime.Quarkus; import io.quarkus.runtime.StartupEvent; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; @@ -81,33 +80,24 @@ public class PublicIpLookup { try { String provider = this.provider.map(it -> it.url).orElseGet(() -> Providers.random().url); - IPs.Builder ipsBuilder = new IPs.Builder(); + String v4 = getIp(provider, CurlProcessFactory.IpClass.V4); + String v6 = getIp(provider, CurlProcessFactory.IpClass.V6); - try { - Process curlProcess = curlProcessFactory.create(provider, CurlProcessFactory.IpClass.V4).start(); - curlProcess.waitFor(); - InputStream inputStream = curlProcess.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - String v4 = reader.readLine(); - log.tracef("Retrieved ipv4: %s", v4); - ipsBuilder.v4(v4); - } catch (Exception e) { - throw new RuntimeException(e); - } + return new IPs(v4, v6); + } catch (Exception e) { + throw new RuntimeException(e); + } + } - try { - Process curlProcess = curlProcessFactory.create(provider, CurlProcessFactory.IpClass.V6).start(); - curlProcess.waitFor(); - InputStream inputStream = curlProcess.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - String v6 = reader.readLine(); - log.tracef("Retrieved ipv6: %s", v6); - ipsBuilder.v6(v6); - } catch (Exception e) { - throw new RuntimeException(e); - } - - return ipsBuilder.build(); + private String getIp(String provider, CurlProcessFactory.IpClass ipClass) { + try { + Process curlProcess = curlProcessFactory.create(provider, ipClass).start(); + curlProcess.waitFor(); + InputStream inputStream = curlProcess.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + String ip = reader.readLine(); + log.tracef("Retrieved ip: %s", ip); + return ip; } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/de/rpr/ddnsclient/model/Config.java b/src/main/java/de/rpr/ddnsclient/model/Config.java index dbe0cf6..3d3da8f 100644 --- a/src/main/java/de/rpr/ddnsclient/model/Config.java +++ b/src/main/java/de/rpr/ddnsclient/model/Config.java @@ -1,7 +1,11 @@ package de.rpr.ddnsclient.model; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.quarkus.runtime.annotations.RegisterForReflection; + import java.util.ArrayList; +@RegisterForReflection public class Config extends ArrayList { public record Value( @@ -12,4 +16,9 @@ public class Config extends ArrayList { String token) { } + @JsonCreator + public Config() { + // empty + } + } diff --git a/src/main/java/de/rpr/ddnsclient/model/IPs.java b/src/main/java/de/rpr/ddnsclient/model/IPs.java index bb742e6..6ec79af 100644 --- a/src/main/java/de/rpr/ddnsclient/model/IPs.java +++ b/src/main/java/de/rpr/ddnsclient/model/IPs.java @@ -2,23 +2,5 @@ package de.rpr.ddnsclient.model; public record IPs(String v4, String v6) { - public static final class Builder { - String v4; - String v6; - - public Builder v4(String v4) { - this.v4 = v4; - return this; - } - - public Builder v6(String v6) { - this.v6 = v6; - return this; - } - - public IPs build() { - return new IPs(v4, v6); - } - } } diff --git a/src/test/java/de/rpr/ddnsclient/lookup/DnsJavaTest.java b/src/test/java/de/rpr/ddnsclient/lookup/DnsJavaTest.java new file mode 100644 index 0000000..22e67a2 --- /dev/null +++ b/src/test/java/de/rpr/ddnsclient/lookup/DnsJavaTest.java @@ -0,0 +1,16 @@ +package de.rpr.ddnsclient.lookup; + +import de.rpr.ddnsclient.model.IPs; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DnsJavaTest { + + @Test + void test() { + IPs result = new DnsJava("9.9.9.9").resolve("example.com"); + assertThat(result.v4()).isNotBlank(); + assertThat(result.v6()).isNotBlank(); + } +} \ No newline at end of file diff --git a/src/test/java/de/rpr/ddnsclient/lookup/DnsResolverTest.java b/src/test/java/de/rpr/ddnsclient/lookup/DnsResolverTest.java deleted file mode 100644 index 5d5e5d3..0000000 --- a/src/test/java/de/rpr/ddnsclient/lookup/DnsResolverTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package de.rpr.ddnsclient.lookup; - -import de.rpr.ddnsclient.model.IPs; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import javax.naming.NamingException; -import javax.naming.directory.BasicAttributes; -import javax.naming.directory.DirContext; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class DnsResolverTest { - - @Mock - DirContext dirContext; - - @Test - void should_throw_exception_if_resolving_failes_repeatedly() throws NamingException { - - when(dirContext.getAttributes(anyString(), any())).thenReturn(new BasicAttributes()); - - DnsResolver dnsResolver = new DnsResolver(dirContext); - - assertThatExceptionOfType(IllegalStateException.class) - .isThrownBy(() -> dnsResolver.resolve("example.com")); - } - - @Test - void should_return_ips() throws NamingException { - - BasicAttributes attributes = new BasicAttributes() {{ - put("A", "ipv4"); - put("AAAA", "ipv6"); - }}; - when(dirContext.getAttributes(anyString(), any())).thenReturn(attributes); - - DnsResolver dnsResolver = new DnsResolver(dirContext); - - IPs result = dnsResolver.resolve("example.com"); - - assertThat(result.v4()).isEqualTo("ipv4"); - assertThat(result.v6()).isEqualTo("ipv6"); - - } -} \ No newline at end of file diff --git a/src/test/java/de/rpr/ddnsclient/lookup/PublicIpLookupTest.java b/src/test/java/de/rpr/ddnsclient/lookup/PublicIpLookupTest.java index dc2433c..df06f92 100644 --- a/src/test/java/de/rpr/ddnsclient/lookup/PublicIpLookupTest.java +++ b/src/test/java/de/rpr/ddnsclient/lookup/PublicIpLookupTest.java @@ -8,9 +8,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.stubbing.Answer; import java.util.Optional;