Skip to content

Commit

Permalink
Implementing Stub Solver but not exposing (#598)
Browse files Browse the repository at this point in the history
* stub core implementing

* validating structures

* address mapper tested

* testing and refactoring

* refactoring

* testing ipv4 validator

* testing

* new test

* refactoring

* clean code

* docs

* clean code

* release notes

* [Gradle Release Plugin] - new version commit:  '3.32.0-snapshot'.

* clearing todos

* clean code

* adjusting version
  • Loading branch information
mageddo authored Nov 7, 2024
1 parent 9565b8d commit 9ac46dd
Show file tree
Hide file tree
Showing 16 changed files with 367 additions and 3 deletions.
3 changes: 3 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 3.32.0
* Implementing Stub Solver but not exposing. #545

## 3.31.1
* Adjusting Canary Rate Threshold Circuit Breaker to mark all circuits as open at the start. #533

Expand Down
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ buildscript {
mavenLocal()
mavenCentral()
gradlePluginPortal()
maven { url "https://oss.sonatype.org/service/local/repositories/releases/content" }
}
}

Expand Down Expand Up @@ -56,7 +57,7 @@ dependencies {

implementation('jakarta.enterprise:jakarta.enterprise.cdi-api:2.0.2')
implementation('jakarta.ws.rs:jakarta.ws.rs-api:2.1.6')
implementation('com.mageddo.commons:commons-lang:0.1.16')
implementation('com.mageddo.commons:commons-lang:0.1.21')
implementation('org.apache.commons:commons-exec:1.3')

implementation('ch.qos.logback:logback-classic:1.5.6')
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=3.31.1-snapshot
version=3.32.0-snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.mageddo.dnsproxyserver.solver.stub;

import com.mageddo.dnsproxyserver.solver.stub.addressexpression.AddressExpressions;
import com.mageddo.dnsproxyserver.solver.stub.addressexpression.ParseException;
import com.mageddo.net.IP;
import org.apache.commons.lang3.Validate;

public class HostnameIpExtractor {

public static IP extract(String hostname, String domain) {

hostname = removeDomainFrom(hostname, domain);
Validate.notBlank(hostname, "Hostname is empty");

RuntimeException lastException = null;
for (int i = 0; i < hostname.length(); i++) {
try {
return AddressExpressions.toIp(hostname.substring(i));
} catch (ParseException e) {
lastException = e;
}
}

throw lastException;
}

static String removeDomainFrom(String hostname, String domain) {
final var idx = hostname.indexOf(domain);
if (idx < 0) {
return hostname;
}
return hostname.substring(0, idx - 1);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.mageddo.dnsproxyserver.solver.stub;

import com.mageddo.dnsproxyserver.solver.Response;
import com.mageddo.dnsproxyserver.solver.Solver;
import org.xbill.DNS.Message;

/**
* Extract the address from the hostname then answer.
* Inspired at nip.io and sslip.io, see #545.
*/
public class SolverStub implements Solver {
@Override
public Response handle(Message query) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.mageddo.dnsproxyserver.solver.stub.addressexpression;

import com.mageddo.net.IP;

import java.util.List;

public class AddressExpressions {

public static IP toIp(String addressExpression) {
RuntimeException lastException = null;
for (final var parser : buildParsers()) {
try {
return parser.parse(addressExpression);
} catch (ParseException e) {
lastException = e;
}
}
throw lastException;
}

static List<Parser> buildParsers() {
return List.of(
new Ipv6Parser(),
new Ipv4Parser(),
new HexadecimalParser()
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.mageddo.dnsproxyserver.solver.stub.addressexpression;

import com.mageddo.net.IP;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;

public class HexadecimalParser implements Parser {
@Override
public IP parse(String addressExpression) {
try {
return IP.of(Hex.decodeHex(addressExpression));
} catch (DecoderException e) {
throw new ParseException("not a hexadecimal address: " + addressExpression, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.mageddo.dnsproxyserver.solver.stub.addressexpression;

import com.mageddo.dnsproxyserver.utils.Ips;
import com.mageddo.net.IP;

public class Ipv4Parser implements Parser {
@Override
public IP parse(String addressExpression) {
final var normalizedStr = addressExpression.replaceAll("-", ".");
if (Ips.isIpv4(normalizedStr)) {
return IP.of(normalizedStr);
}
throw new ParseException("invalid ipv4 address expression: " + addressExpression);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.mageddo.dnsproxyserver.solver.stub.addressexpression;

import com.mageddo.net.IP;
import org.apache.commons.lang3.StringUtils;

public class Ipv6Parser implements Parser {
@Override
public IP parse(String addressExpression) {
if (isIpv6(addressExpression)) {
try {
return IP.of(addressExpression.replaceAll("-", ":"));
} catch (RuntimeException e){
throw throwError(addressExpression);
}
}
throw throwError(addressExpression);
}

RuntimeException throwError(String addressExpression) {
throw new ParseException("Not ipv6 address: " + addressExpression);
}

static boolean isIpv6(String addressExpression) {
return (addressExpression.contains("--") || StringUtils.countMatches(addressExpression, "-") >= IP.IPV4_BYTES)
&& !addressExpression.contains(".");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.mageddo.dnsproxyserver.solver.stub.addressexpression;

public class ParseException extends RuntimeException {

public ParseException(String message) {
super(message);
}

public ParseException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.mageddo.dnsproxyserver.solver.stub.addressexpression;

import com.mageddo.net.IP;

public interface Parser {
IP parse(String addressExpression);
}
8 changes: 7 additions & 1 deletion src/main/java/com/mageddo/dnsproxyserver/utils/Ips.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mageddo.dnsproxyserver.utils;

import com.mageddo.commons.regex.Regexes;
import com.mageddo.net.IP;
import com.mageddo.utils.Bytes;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -10,9 +11,14 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.regex.Pattern;

public class Ips {

private static final Pattern IPV4_REGEX = Pattern.compile(
"^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$"
);

private Ips() {
}

Expand Down Expand Up @@ -73,7 +79,7 @@ public static boolean isIpv6(String v) {
}

public static boolean isIpv4(String v) {
return !isIpv6(v);
return Regexes.matches(v, IPV4_REGEX);
}

public static Short[] toShortArray(String ip) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.mageddo.dnsproxyserver.solver.stub;

import com.mageddo.dnsproxyserver.solver.stub.addressexpression.AddressExpressions;
import com.mageddo.net.IP;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class AddressExpressionsTest {

@Test
void mustConvertIpv4ExpressionSplitByDots() {
final var exp = "10.0.0.1";

final var addr = AddressExpressions.toIp(exp);

assertEquals(IP.of(exp), addr);
}

@Test
void mustConvertIpv4ExpressionSplitByDash() {
final var exp = "10-0-0-1";

final var addr = AddressExpressions.toIp(exp);

assertEquals(IP.of("10.0.0.1"), addr);
}

@Test
void mustConvertIpv6ExpressionSplitByDash() {
final var exp = "a--1";

final var addr = AddressExpressions.toIp(exp);

assertEquals(IP.of("a::1"), addr);
}

@Test
void mustConvertExpandedIpv6ExpressionSplitByDash() {
final var exp = "000a-0-0-0-0-0-0-0001";

final var addr = AddressExpressions.toIp(exp);

assertEquals(IP.of("a::1"), addr);
}

@Test
void mustConvertHexadecimal() {
final var exp = "0a000803";

final var addr = AddressExpressions.toIp(exp);

assertEquals(IP.of("10.0.8.3"), addr);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.mageddo.dnsproxyserver.solver.stub;

import com.mageddo.net.IP;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import testing.templates.HostnameTemplates;

import static org.junit.jupiter.api.Assertions.assertEquals;

class HostnameIpExtractorTest {

static final String SSLIP_IO = "sslip.io";
static final String NIP_IO = "nip.io";

@Test
@DisplayName("Must extract ipv4 from hostname starting with name, using dot-decimal notation")
void mustExtractIpv4IpFromHostnameStartingWithNameUsingDotDecimalNotation() {
final var hostname = HostnameTemplates.startingWithNameDotDecimalNotation();

final var addr = HostnameIpExtractor.extract(hostname, SSLIP_IO);

assertEquals(IP.of("192.168.0.1"), addr);
}

@Test
@DisplayName("Must extract ipv4 from hostname starting with name, separated by dash, using dot-decimal notation")
void mustExtractIpv4IpFromHostnameStartingWithNameSeparatedByDashUsingDotDecimalNotation() {
final var hostname = HostnameTemplates.startingWithNameDashSeparationDotDecimalNotation();

final var addr = HostnameIpExtractor.extract(hostname, SSLIP_IO);

assertEquals(IP.of("192.168.0.2"), addr);
}

@Test
void mustExtractIpWhenAllUsingDots() {
final var hostname = "customer1.app.10.0.0.1.nip.io";

final var addr = HostnameIpExtractor.extract(hostname, NIP_IO);

assertEquals(IP.of("10.0.0.1"), addr);
}

@Test
void mustExtractIpWhenAllUsingShortIpv6() {
final var hostname = "customer1.app.a--1.sslip.io";

final var addr = HostnameIpExtractor.extract(hostname, SSLIP_IO);

assertEquals(IP.of("a:0:0:0:0:0:0:1"), addr);
}

@Test
void mustExtractIpv4FromTheEnd() {
final var hostname = "116-116-203-255-68.nip.io";

final var addr = HostnameIpExtractor.extract(hostname, NIP_IO);

assertEquals(IP.of("116.203.255.68"), addr);
}

@Test
void mustExtractIpWhenAllUsingShortIpv6EvenWhenNameIsAValidHexadecimal() {
final var hostname = "bb.a--1.sslip.io";

final var addr = HostnameIpExtractor.extract(hostname, SSLIP_IO);

assertEquals(IP.of("a:0:0:0:0:0:0:1"), addr);
}

@Test
void mustExtractIpv4IpFromLabeledHexadecimal() {
final var hostname = "acme.c0a801fc.sslip.io";

final var addr = HostnameIpExtractor.extract(hostname, SSLIP_IO);

assertEquals(IP.of("192.168.1.252"), addr);
}

@Test
void mustExtractIpv4IpFromHexadecimal() {
final var hostname = "c0a801fc.sslip.io";

final var addr = HostnameIpExtractor.extract(hostname, SSLIP_IO);

assertEquals(IP.of("192.168.1.252"), addr);
}

@Test
void mustExtractIpv6IpFromLabeledHexadecimal() {
final var hostname = "acme.20010DB8000000000000000000000001.sslip.io";

final var addr = HostnameIpExtractor.extract(hostname, SSLIP_IO);

assertEquals(IP.of("2001:db8::1"), addr);
}

@Test
void mustRemoveDomainFromHostname() {
final var hostname = HostnameTemplates.startingWithNameDotDecimalNotation();

final var subdomain = HostnameIpExtractor.removeDomainFrom(hostname, SSLIP_IO);

assertEquals("www.192.168.0.1", subdomain);
}

@Test
void mustKeepTheHostnameWhenDomainIsNotPresent() {
final var hostname = "example.com";

final var subdomain = HostnameIpExtractor.removeDomainFrom(hostname, SSLIP_IO);

assertEquals(hostname, subdomain);
}
}
Loading

0 comments on commit 9ac46dd

Please sign in to comment.