public function get($hostname, $cb, $noncache = false, $nameServers = [], $proto = 'udp')
{
$pool = $this;
if (!$nameServers) {
$nameServers = $this->nameServers;
}
if (!$this->preloading->hasCompleted()) {
$this->preloading->addListener(function ($job) use($hostname, $cb, $noncache, $pool, $nameServers, $proto) {
$pool->get($hostname, $cb, $noncache, $nameServers, $proto);
});
return;
}
$nameServer = reset($nameServers);
$isIpv6 = filter_var($nameServer, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
if ($isIpv6) {
$nameServer = '[' . $nameServer . ']';
}
$onGetConnection = function ($conn) use($cb, $hostname, $nameServers, $noncache, $pool, $proto) {
if (!$conn || !$conn->isConnected()) {
if ($proto === 'udp') {
//Fail to connect via udp, trying by tcp
$pool->get($hostname, $cb, $noncache, $nameServers, 'tcp');
return;
}
array_shift($nameServers);
if (!$nameServers) {
//Totally fail to resolve name
$cb(false);
} else {
//Fail connect to curr Ns, but we can try another ns
$pool->get($hostname, $cb, $noncache, $nameServers, 'udp');
}
} else {
$conn->get($hostname, function ($response) use($hostname, $cb, $proto, $noncache, $nameServers, $pool) {
if ($response === false && $proto === 'udp') {
//Fail to connect via udp, trying by tcp
$pool->get($hostname, $cb, $noncache, $nameServers, 'tcp');
} else {
call_user_func($cb, $response);
}
});
}
};
list($host, $type, $class) = explode(':', $hostname . '::', 3);
if ($type === 'AXFR') {
$proto = 'tcp';
}
$this->getConnection($proto . '://' . $nameServer, $onGetConnection);
return;
}