org.jgroups.protocols.dns.DefaultDNSResolver Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.protocols.dns;
import org.jgroups.Address;
import org.jgroups.logging.Log;
import org.jgroups.logging.LogFactory;
import org.jgroups.stack.IpAddress;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.lang.invoke.MethodHandles;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DefaultDNSResolver implements DNSResolver {
private static final Pattern SRV_REGEXP = Pattern.compile("\\d+ \\d+ (\\d+) ([\\w+\\.-]+)");
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
private final DirContext dnsContext;
public DefaultDNSResolver(DirContext context) {
this.dnsContext = context;
}
public DefaultDNSResolver(String dnsContextFactory, String dnsAddress) throws NamingException {
log.trace("initializing DNS Context with factory: %s and url: %s", dnsContextFactory, dnsAddress);
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, dnsContextFactory);
if (dnsAddress != null) {
env.put(Context.PROVIDER_URL, "dns://" + dnsAddress);
}
this.dnsContext = new InitialDirContext(env);
}
@Override
public void close() {
try {
this.dnsContext.close();
} catch (NamingException e) {
log.warn(e.getLocalizedMessage(), e);
}
}
@Override
public List resolveIps(String dnsQuery, DNSRecordType recordType) {
log.trace("resolving DNS query: %s of a type: %s", dnsQuery, recordType.toString());
switch (recordType) {
case A:
return resolveAEntries(dnsQuery);
case SRV:
return resolveSRVEntries(dnsQuery);
default:
throw new IllegalStateException("Not implemented");
}
}
protected DirContext getDnsContext() {
return dnsContext;
}
protected List resolveSRVEntries(String dnsQuery) {
List addresses = new ArrayList<>();
try {
// We are parsing this kind of structure:
// {srv=SRV: 10 100 8888 9089f34a.jgroups-dns-ping.myproject.svc.cluster.local.}
// The frst attribute is the type of record. We are not interested in this. Next are addresses.
Attributes attributes = dnsContext.getAttributes(dnsQuery, new String[] { DNSRecordType.SRV.toString() });
if (attributes != null && attributes.getAll().hasMoreElements()) {
NamingEnumeration> namingEnumeration = attributes.get(DNSRecordType.SRV.toString()).getAll();
while (namingEnumeration.hasMoreElements()) {
try {
String srvEntry = namingEnumeration.nextElement().toString();
Matcher matcher = SRV_REGEXP.matcher(srvEntry);
if (matcher.find()) {
String srcPort = matcher.group(1);
String srcDNSRecord = matcher.group(2);
// The implementation here is not optimal but it's easy to read. SRV discovery will be performed
// extremely rarely, only when a fine grained discovery using ports is needed (ie: when using containers).
addresses.addAll(resolveAEntries(srcDNSRecord, srcPort));
}
} catch (Exception e) {
log.trace("non critical DNS resolution error", e);
}
}
}
} catch (NamingException ex) {
log.trace("no DNS records for query %s, ex: %s", dnsQuery, ex.getMessage());
}
return addresses;
}
protected List resolveAEntries(String dnsQuery) {
return resolveAEntries(dnsQuery, "0");
}
protected List resolveAEntries(String dnsQuery, String srcPort) {
List addresses = new ArrayList<>();
try {
InetAddress[] inetAddresses = InetAddress.getAllByName(dnsQuery);
for (InetAddress address : inetAddresses) {
addresses.add(new IpAddress(address, Integer.parseInt(srcPort)));
}
} catch (UnknownHostException ex) {
log.trace("failed to resolve query %s, ex: %s", dnsQuery, ex.getMessage());
}
return addresses;
}
}