package com.workshare.msnos.core.protocols.ip;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.workshare.msnos.core.protocols.ip.resolvers.CompositeIPResolver;
import com.workshare.msnos.core.protocols.ip.resolvers.IPResolver;
import com.workshare.msnos.core.protocols.ip.resolvers.IPResolverBySystemProperty;
import com.workshare.msnos.core.protocols.ip.resolvers.IPResolverByURL;
public class AddressResolver {
public static final String SYSP_PUBLIC_IP = "com.ws.msnos.address.public.ip";
public static final String SYSP_ROUTER_IP = "com.ws.msnos.address.router.ip";
// instance-data is usually 169.254.169.254
public static final String AMAZON_IPV4_DISCOVERY_ENDPOINT = "http://instance-data/latest/meta-data/public-ipv4";
public static final String ROUTER_DISCOVERY_ENDPOINT = "http://checkip.amazonaws.com";
public static IPResolver FOR_ROUTER_IP = new CompositeIPResolver(
new IPResolverBySystemProperty(SYSP_ROUTER_IP),
new IPResolverByURL(ROUTER_DISCOVERY_ENDPOINT)
);
public static IPResolver FOR_PUBLIC_IP = new CompositeIPResolver(
new IPResolverBySystemProperty(SYSP_PUBLIC_IP),
new IPResolverByURL(AMAZON_IPV4_DISCOVERY_ENDPOINT)
);
private static Logger log = LoggerFactory.getLogger(AddressResolver.class);
private final HttpClient httpClient;
private final IPResolver routerIpResolver;
private final IPResolver publicIpResolver;
public AddressResolver() {
this(HttpClientFactory.sharedHttpClient(), FOR_ROUTER_IP, getPublicResolver());
}
private static IPResolver getPublicResolver() {
if ("router".equalsIgnoreCase(System.getProperty(SYSP_PUBLIC_IP))) {
log.info("Using router resolver for public IP as requested");
return FOR_ROUTER_IP;
}
else
return FOR_PUBLIC_IP;
}
public AddressResolver(HttpClient httpClient, IPResolver routerIpResolver, IPResolver publicIpResolver) {
this.httpClient = httpClient;
this.routerIpResolver = routerIpResolver;
this.publicIpResolver = publicIpResolver;
}
public HttpClient httpClient() {
return httpClient;
}
public Network findRouterIP() {
return findIP(routerIpResolver, "external");
}
public Network findPublicIP() {
return findIP(publicIpResolver, "public");
}
private Network findIP(final IPResolver resolver, String type) {
Network result = newNetwork(resolver.resolve(this));
if (result == null)
log.debug("Unable to collect {} IP", type);
else
log.debug("Using {} address {}", type, result);
return result;
}
private Network newNetwork(byte[] ip) {
return (ip != null) ? new Network(ip, (short) 32) : null;
}
public byte[] getIPViaURL(final String url) {
byte[] address = null;
try {
HttpEntity entity = null;
try {
final HttpGet request = new HttpGet(url);
log.debug("Getting public address trough {}", request.getURI());
HttpResponse response = httpClient.execute(request);
if (response != null) {
entity = response.getEntity();
final String text = EntityUtils.toString(entity);
log.debug("Get result: {}", text);
address = (entity == null) ? null : Network.createAddressFromString(text);
log.debug("Got address: {}", address);
}
} finally {
EntityUtils.consume(entity);
}
} catch (Throwable ex) {
log.debug("Unable to resolve IP from url "+url, ex);
}
return address;
}
protected IPResolver getRouterIpResolver() {
return routerIpResolver;
}
protected IPResolver getPublicIpResolver() {
return publicIpResolver;
}
}