Re-factor Listeners and Resolvers to use ServiceLoader protocol discovery
This commit is contained in:
parent
0bca5ee0a2
commit
f118f6410b
@ -0,0 +1,19 @@
|
||||
package com.moparisthebest.dns.listen;
|
||||
|
||||
import com.moparisthebest.dns.net.ParsedUrl;
|
||||
import com.moparisthebest.dns.resolve.Resolver;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public class DefaultServices implements Services {
|
||||
@Override
|
||||
public Listener getListener(ParsedUrl parsedUrl, final Resolver resolver, final ExecutorService executor) {
|
||||
switch(parsedUrl.getProtocol()) {
|
||||
case "tcp":
|
||||
return new TcpAsync(parsedUrl.getAddr(), resolver, executor);
|
||||
case "udp":
|
||||
return new UdpSync(parsedUrl.getAddr(), resolver, executor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -6,30 +6,21 @@ import com.moparisthebest.dns.resolve.Resolver;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public interface Listener extends Runnable, AutoCloseable {
|
||||
public static Listener of(final String listener, final Resolver resolver, final ExecutorService executor) {
|
||||
/*
|
||||
listener = listener.trim().toLowerCase();
|
||||
final String[] hostPort = listener.substring(6).split(":");
|
||||
//System.out.println("hostPort: " + Arrays.toString(hostPort));
|
||||
final SocketAddress socketAddress = new InetSocketAddress(hostPort[0], Integer.parseInt(hostPort[1]));
|
||||
//System.out.println("socketAddress: " + socketAddress);
|
||||
if(listener.startsWith("tcp://")) {
|
||||
return new TcpAsync(socketAddress, resolver, executor);
|
||||
} else if(listener.startsWith("udp://")) {
|
||||
return new UdpSync(socketAddress, resolver, executor);
|
||||
}
|
||||
*/
|
||||
|
||||
ServiceLoader<Services> services = ServiceLoader.load(Services.class);
|
||||
|
||||
static Listener of(final String listener, final Resolver resolver, final ExecutorService executor) {
|
||||
final ParsedUrl parsedUrl = ParsedUrl.of(listener);
|
||||
switch(parsedUrl.getProtocol()) {
|
||||
case "tcp":
|
||||
return new TcpAsync(parsedUrl.getAddr(), resolver, executor);
|
||||
case "udp":
|
||||
return new UdpSync(parsedUrl.getAddr(), resolver, executor);
|
||||
for (final Services s : services) {
|
||||
final Listener ret = s.getListener(parsedUrl, resolver, executor);
|
||||
if (ret != null)
|
||||
return ret;
|
||||
}
|
||||
throw new IllegalArgumentException("invalid listener format");
|
||||
throw new IllegalArgumentException("unhandled listener format: " + listener);
|
||||
}
|
||||
|
||||
public static Listener ofAndStart(final String listener, final Resolver resolver, final ExecutorService executor) {
|
||||
|
@ -0,0 +1,10 @@
|
||||
package com.moparisthebest.dns.listen;
|
||||
|
||||
import com.moparisthebest.dns.net.ParsedUrl;
|
||||
import com.moparisthebest.dns.resolve.Resolver;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public interface Services {
|
||||
Listener getListener(ParsedUrl parsedUrl, Resolver resolver, ExecutorService executor);
|
||||
}
|
@ -11,13 +11,15 @@ import java.util.*;
|
||||
|
||||
public class ParsedUrl {
|
||||
|
||||
private final String urlStr;
|
||||
private final SocketAddress addr;
|
||||
private final URI uri; // minus #
|
||||
private final Map<String, String> props; // after #, split by ;
|
||||
private final Proxy proxy;
|
||||
private final SSLSocketFactory sslSocketFactory;
|
||||
|
||||
public ParsedUrl(final SocketAddress addr, final URI uri, final Map<String, String> props, final Proxy proxy, final SSLSocketFactory sslSocketFactory) {
|
||||
public ParsedUrl(final String urlStr, final SocketAddress addr, final URI uri, final Map<String, String> props, final Proxy proxy, final SSLSocketFactory sslSocketFactory) {
|
||||
this.urlStr = urlStr;
|
||||
this.addr = addr;
|
||||
this.uri = uri;
|
||||
this.props = props;
|
||||
@ -70,7 +72,7 @@ public class ParsedUrl {
|
||||
}
|
||||
if(sslSocketFactory == null && url.getScheme().equals("tls"))
|
||||
sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||
return new ParsedUrl(addr, url, props, proxy, sslSocketFactory);
|
||||
return new ParsedUrl(urlStr, addr, url, props, proxy, sslSocketFactory);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof RuntimeException)
|
||||
throw (RuntimeException) e;
|
||||
@ -104,6 +106,10 @@ public class ParsedUrl {
|
||||
return toUrlRemoveRef(uri);
|
||||
}
|
||||
|
||||
public String getUrlStr() {
|
||||
return urlStr;
|
||||
}
|
||||
|
||||
public SocketAddress getAddr() {
|
||||
return addr;
|
||||
}
|
||||
|
@ -29,17 +29,6 @@ public abstract class AbstractQueueProcessingResolver implements QueueProcessing
|
||||
executor.execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends RequestResponse> CompletableFuture<E> resolveAsync(final E requestResponse) {
|
||||
return null;
|
||||
/*
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
requestResponse.setResponse(resolve(requestResponse.getRequest()));
|
||||
return requestResponse;
|
||||
}, executor);
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
thisThread = Thread.currentThread();
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.moparisthebest.dns.resolve;
|
||||
|
||||
import com.moparisthebest.dns.net.ParsedUrl;
|
||||
|
||||
public class DefaultServices implements Services {
|
||||
@Override
|
||||
public Resolver getResolver(ParsedUrl parsedUrl) {
|
||||
final int connectTimeout = Integer.parseInt(parsedUrl.getProps().getOrDefault("connectTimeout", "500"));
|
||||
switch(parsedUrl.getProtocol()) {
|
||||
case "tcp":
|
||||
case "tls":
|
||||
return new SocketResolver(parsedUrl.getAddr(), connectTimeout, parsedUrl.getProxy(), parsedUrl.getSslSocketFactory());
|
||||
case "http":
|
||||
case "https":
|
||||
return new HttpResolver(parsedUrl.getUrlWithoutFragment(), connectTimeout, parsedUrl.getProxy(), parsedUrl.getSslSocketFactory());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.moparisthebest.dns.resolve;
|
||||
|
||||
import com.moparisthebest.dns.dto.Packet;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class DelegatingQueueProcessingResolver extends AbstractQueueProcessingResolver {
|
||||
|
||||
private final Resolver delegate;
|
||||
|
||||
public DelegatingQueueProcessingResolver(final int maxRetries, final String name, final Resolver delegate) {
|
||||
super(maxRetries, name);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends RequestResponse> CompletableFuture<E> resolveAsync(final E requestResponse) {
|
||||
return delegate.resolveAsync(requestResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet resolve(final Packet request) throws Exception {
|
||||
return delegate.resolve(request);
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import java.net.*;
|
||||
|
||||
import static com.moparisthebest.dns.Util.readPacket;
|
||||
|
||||
public class HttpResolver extends AbstractQueueProcessingResolver {
|
||||
public class HttpResolver implements Resolver {
|
||||
private final OpenConnection openConnection;
|
||||
private final int connectTimeout;
|
||||
private final int readTimeout = 4000;
|
||||
@ -18,8 +18,7 @@ public class HttpResolver extends AbstractQueueProcessingResolver {
|
||||
HttpURLConnection open() throws Exception;
|
||||
}
|
||||
|
||||
public HttpResolver(final int maxRetries, final String name, final URL url, final int connectTimeout, final Proxy proxy, final SSLSocketFactory sslSocketFactory) {
|
||||
super(maxRetries, name);
|
||||
public HttpResolver(final URL url, final int connectTimeout, final Proxy proxy, final SSLSocketFactory sslSocketFactory) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
if(proxy == null && sslSocketFactory == null) {
|
||||
openConnection = () -> (HttpURLConnection) url.openConnection();
|
||||
|
@ -1,14 +1,9 @@
|
||||
package com.moparisthebest.dns.resolve;
|
||||
|
||||
import com.moparisthebest.dns.dto.Packet;
|
||||
import com.moparisthebest.dns.net.ParsedUrl;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public interface QueueProcessingResolver extends Resolver, Runnable, AutoCloseable {
|
||||
@ -27,15 +22,6 @@ public interface QueueProcessingResolver extends Resolver, Runnable, AutoCloseab
|
||||
String name = parsedUrl.getProps().get("name");
|
||||
if(name == null)
|
||||
name = parsedUrl.getUri().toString();
|
||||
final int connectTimeout = Integer.parseInt(parsedUrl.getProps().getOrDefault("connectTimeout", "500"));
|
||||
switch(parsedUrl.getProtocol()) {
|
||||
case "tcp":
|
||||
case "tls":
|
||||
return new SocketResolver(maxRetries, name, parsedUrl.getAddr(), connectTimeout, parsedUrl.getProxy(), parsedUrl.getSslSocketFactory());
|
||||
case "http":
|
||||
case "https":
|
||||
return new HttpResolver(maxRetries, name, parsedUrl.getUrlWithoutFragment(), connectTimeout, parsedUrl.getProxy(), parsedUrl.getSslSocketFactory());
|
||||
}
|
||||
throw new IllegalArgumentException("invalid listener format");
|
||||
return new DelegatingQueueProcessingResolver(maxRetries, name, Resolver.of(parsedUrl));
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,32 @@
|
||||
package com.moparisthebest.dns.resolve;
|
||||
|
||||
import com.moparisthebest.dns.dto.Packet;
|
||||
import com.moparisthebest.dns.listen.Listener;
|
||||
import com.moparisthebest.dns.listen.TcpAsync;
|
||||
import com.moparisthebest.dns.listen.UdpSync;
|
||||
import com.moparisthebest.dns.net.ParsedUrl;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public interface Resolver {
|
||||
<E extends RequestResponse> CompletableFuture<E> resolveAsync(E requestResponse);
|
||||
default <E extends RequestResponse> CompletableFuture<E> resolveAsync(E requestResponse) {
|
||||
return null;
|
||||
/*
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
requestResponse.setResponse(resolve(requestResponse.getRequest()));
|
||||
return requestResponse;
|
||||
}, executor);
|
||||
*/
|
||||
}
|
||||
|
||||
Packet resolve(Packet request) throws Exception;
|
||||
|
||||
ServiceLoader<Services> services = ServiceLoader.load(Services.class);
|
||||
|
||||
static Resolver of(final ParsedUrl parsedUrl) {
|
||||
for (final Services s : services) {
|
||||
final Resolver ret = s.getResolver(parsedUrl);
|
||||
if (ret != null)
|
||||
return ret;
|
||||
}
|
||||
throw new IllegalArgumentException("unhandled resolver format: " + parsedUrl.getUrlStr());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package com.moparisthebest.dns.resolve;
|
||||
|
||||
import com.moparisthebest.dns.net.ParsedUrl;
|
||||
|
||||
public interface Services {
|
||||
Resolver getResolver(ParsedUrl parsedUrl);
|
||||
}
|
@ -14,7 +14,7 @@ import static com.moparisthebest.dns.Util.readTcpPacket;
|
||||
import static com.moparisthebest.dns.Util.tryClose;
|
||||
import static com.moparisthebest.dns.Util.writeTcpPacket;
|
||||
|
||||
public class SocketResolver extends AbstractQueueProcessingResolver {
|
||||
public class SocketResolver implements Resolver {
|
||||
private final OpenSocket openConnection;
|
||||
private final int readTimeout = 4000;
|
||||
|
||||
@ -22,8 +22,7 @@ public class SocketResolver extends AbstractQueueProcessingResolver {
|
||||
Socket open() throws Exception;
|
||||
}
|
||||
|
||||
public SocketResolver(final int maxRetries, final String name, final SocketAddress endpoint, final int connectTimeout, final Proxy proxy, final SSLSocketFactory sslSocketFactory) {
|
||||
super(maxRetries, name);
|
||||
public SocketResolver(final SocketAddress endpoint, final int connectTimeout, final Proxy proxy, final SSLSocketFactory sslSocketFactory) {
|
||||
if(proxy == null && sslSocketFactory == null) {
|
||||
openConnection = () -> {
|
||||
Socket s = null;
|
||||
|
@ -0,0 +1 @@
|
||||
com.moparisthebest.dns.listen.DefaultServices
|
@ -0,0 +1 @@
|
||||
com.moparisthebest.dns.resolve.DefaultServices
|
Loading…
Reference in New Issue
Block a user