All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.leancloud.network.DNSDetoxicant Maven / Gradle / Ivy

package cn.leancloud.network;

import cn.leancloud.cache.PersistenceUtil;
import cn.leancloud.core.AppConfiguration;
import cn.leancloud.utils.StringUtil;
import okhttp3.*;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class DNSDetoxicant implements Dns {
  static final long TWENTY_MIN_IN_MILLS = 20 * 60 * 1000L;
  static final String AVOS_SERVER_HOST_ZONE = "avoscloud_server_host_zone";
  public static final String EXPIRE_TIME = ".expireTime";
  static final String DNSPOD_HOST = System.getProperty("dnspodHost","119.29.29.29");

  // DNS 请求的超时时间设置为两秒
  private static final int DNS_REQUEST_TIME_OUT = 2 * 1000;

  public List lookup(String hostname) throws UnknownHostException {
    if (StringUtil.isEmpty(hostname)) {
      throw new UnknownHostException("hostname is empty");
    }
    try {
      InetAddress[] addresses = InetAddress.getAllByName(hostname);
      return Arrays.asList(addresses);
    } catch (UnknownHostException e) {
      try {
        String response = getCacheDNSResult(hostname);
        boolean isCacheValid = !StringUtil.isEmpty(response);
        if (!isCacheValid) {
          response = getIPByHostSync(hostname);
        }
        InetAddress[] addresses = getIPAddress(hostname, response);
        if (!isCacheValid) {
          cacheDNS(hostname, response);
        }
        return Arrays.asList(addresses);
      } catch (Exception e1) {
        throw new UnknownHostException();
      }
    }
  }
  public static String getIPByHostSync(String host) throws Exception {
    HttpUrl httpUrl = new HttpUrl.Builder().scheme("http").host(DNSPOD_HOST)
            .addPathSegment("d").addQueryParameter("dn", host).build();

    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    builder.connectTimeout(DNS_REQUEST_TIME_OUT, TimeUnit.MILLISECONDS);
    builder.dns(Dns.SYSTEM);
    OkHttpClient okHttpClient = builder.build();
    Request request = new Request.Builder().url(httpUrl).get().build();

    try {
      Response response = okHttpClient.newCall(request).execute();
      if (null != response && response.isSuccessful()) {
        return response.body().string();
      } else {
        return "";
      }
    } catch (IOException e) {
      return "";
    }
  }

  private void cacheDNS(String host, String response) {
    AppConfiguration.getDefaultSetting().saveString(AVOS_SERVER_HOST_ZONE, host, response);
    AppConfiguration.getDefaultSetting().saveString(AVOS_SERVER_HOST_ZONE,
            host + EXPIRE_TIME, String.valueOf(System.currentTimeMillis() + TWENTY_MIN_IN_MILLS));
  }

  private String getCacheDNSResult(String url) {
    String response = AppConfiguration.getDefaultSetting().getString(AVOS_SERVER_HOST_ZONE, url, null);
    String expiredAt = AppConfiguration.getDefaultSetting().getString(AVOS_SERVER_HOST_ZONE,
            url + EXPIRE_TIME, "0");

    if (!StringUtil.isEmpty(response) && System.currentTimeMillis() < Long.parseLong(expiredAt)) {
      return response;
    } else {
      return null;
    }
  }

  private static InetAddress[] getIPAddress(String url, String response) throws Exception {
    String[] ips = response.split(";");
    InetAddress[] addresses = new InetAddress[ips.length];
    Constructor constructor =
            InetAddress.class.getDeclaredConstructor(int.class, byte[].class, String.class);
    constructor.setAccessible(true);
    for (int i = 0; i < ips.length; i++) {
      String ip = ips[i];
      String[] ipSegment = ip.split("\\.");
      if (ipSegment.length == 4) {
        byte[] ipInBytes =
                {(byte) Integer.parseInt(ipSegment[0]), (byte) Integer.parseInt(ipSegment[1]),
                        (byte) Integer.parseInt(ipSegment[2]), (byte) Integer.parseInt(ipSegment[3])};
        addresses[i] = (InetAddress) constructor.newInstance(2, ipInBytes, url);
      }
    }
    return addresses;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy