/******************************************************************************* * * * Copyright (C) 2017 by Max Lv * * Copyright (C) 2017 by Mygod Studio * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * *******************************************************************************/ package com.github.shadowsocks.bg import android.util.Log import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.BuildConfig import org.xbill.DNS.* import java.io.IOException import java.net.* object Dns { private const val TAG = "Dns" private val hasIPv6Support get() = try { val result = NetworkInterface.getNetworkInterfaces().asSequence().flatMap { it.inetAddresses.asSequence() } .any { it is Inet6Address && !it.isLoopbackAddress && !it.isLinkLocalAddress } if (result && BuildConfig.DEBUG) Log.d(TAG, "IPv6 address detected") result } catch (ex: SocketException) { Log.e(TAG, "Failed to get interfaces' addresses.", ex) app.track(ex) false } private fun resolve(host: String, addrType: Int): String? { try { val lookup = Lookup(host, addrType) val resolver = SimpleResolver("208.67.220.220") resolver.setTCP(true) resolver.setPort(443) resolver.setTimeout(5) lookup.setResolver(resolver) val records = (lookup.run() ?: return null).toMutableList() records.shuffle() for (r in records) { when (addrType) { Type.A -> return (r as ARecord).address.hostAddress Type.AAAA -> return (r as AAAARecord).address.hostAddress } } } catch (_: IOException) { } return null } private fun resolve(host: String): String? = try { InetAddress.getByName(host).hostAddress } catch (_: UnknownHostException) { null } fun resolve(host: String, enableIPv6: Boolean): String? = (if (enableIPv6 && hasIPv6Support) resolve(host, Type.AAAA) else null) ?: resolve(host, Type.A) ?: resolve(host) }