Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 92 additions & 19 deletions DNS/dnsProtocol.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,19 @@ class dnsProtocol
protected $port;
/**
*
* @var float $timeout = 60
* @var float $connectiontimeout = 60
*/
protected $timeout;
protected $connectiontimeout;
/**
*
* @var float $readtimeoutsec = 60
*/
protected $readtimeoutsec;
/**
*
* @var float $readtimeoutusec = 0
*/
protected $readtimeoutusec;
/**
*
* @var boolean $udp = false;
Expand All @@ -42,7 +52,8 @@ class dnsProtocol
*/
protected $types;

const DEFAULT_TIMEOUT = 60;
const DEFAULT_CONNECTION_TIMEOUT = 60.0;
const DEFAULT_READ_TIMEOUT = 60.0;

function __construct($logging = false)
{
Expand All @@ -51,10 +62,10 @@ function __construct($logging = false)
$this->enableLogging();
}
$this->port=53;
$this->timeout=self::DEFAULT_TIMEOUT;
$this->setConnectionTimeout();
$this->setReadTimeout();
$this->udp=false;
$this->types=new dnsTypes();
set_error_handler(array($this,'error_handler'));
$this->writelog("dnsProtocol Class Initialised");
}

Expand Down Expand Up @@ -85,6 +96,9 @@ function error_handler($errno = 0, $errstr = null, $errfile = null, $errline = n
*/
function Query($question,$type='A')
{
set_error_handler(array($this,'error_handler'));
try {

$typeid=$this->types->GetByName($type);
if ($typeid===false)
{
Expand All @@ -99,7 +113,7 @@ function Query($question,$type='A')
{
$host=$this->server;
}
if (!$socket=@fsockopen($host,$this->port,$errno,$errstr,$this->timeout))
if (!$socket=@fsockopen($host,$this->port,$errno,$errstr,$this->connectiontimeout))
{
throw new dnsException("Failed to open socket to ".$host);
}
Expand Down Expand Up @@ -164,10 +178,21 @@ function Query($question,$type='A')
fclose($socket);
throw new dnsException("Failed to write question to socket");
}
if (!$this->rawbuffer=fread($socket,4096)) // read until the end with UDP

stream_set_blocking($socket, true); // set blocking mode to make fread wait for data to become available
stream_set_timeout($socket, $this->readtimeoutsec, $this->readtimeoutusec); // set read timeout

$this->rawbuffer=fread($socket,4096);
$info = stream_get_meta_data($socket);
if ($info['timed_out'])
{
fclose($socket);
throw new dnsException("Failed to write read data buffer");
throw new dnsException("Connection timed out while read data buffer");
}
if (!$this->rawbuffer) // read until the end with UDP
{
fclose($socket);
throw new dnsException("Failed to read data buffer");
}
}
else // TCP method
Expand All @@ -182,14 +207,32 @@ function Query($question,$type='A')
fclose($socket);
throw new dnsException("Failed to write question to TCP socket");
}
if (!$returnsize=fread($socket,2))

stream_set_blocking($socket, true); // set blocking mode to make fread wait for data to become available
stream_set_timeout($socket, $this->readtimeoutsec, $this->readtimeoutusec); // set read timeout

$returnsize=fread($socket,2);
$info = stream_get_meta_data($socket);
if ($info['timed_out'])
{
fclose($socket);
throw new dnsException("Connection timed out");
}
if (!$returnsize)
{
fclose($socket);
}
$tmplen=unpack("nlength",$returnsize);
$datasize=$tmplen['length'];
$this->writeLog("TCP Stream Length Limit ".$datasize);
if (!$this->rawbuffer=fread($socket,$datasize))
$this->rawbuffer=fread($socket,$datasize);
$info = stream_get_meta_data($socket);
if ($info['timed_out'])
{
fclose($socket);
throw new dnsException("Connection timed out while read data buffer");
}
if (!$this->rawbuffer)
{
fclose($socket);
throw new dnsException("Failed to read data buffer");
Expand Down Expand Up @@ -260,6 +303,10 @@ function Query($question,$type='A')
$response->ReadRecord($this->rawbuffer,dnsResponse::RESULTTYPE_ADDITIONAL);
}
return $response;

} finally {
restore_error_handler();
}
}

public function setServer($server)
Expand All @@ -272,18 +319,39 @@ public function getServer()
return $this->server;
}

public function setTimeout($timeout = self::DEFAULT_TIMEOUT)
/**
* @param float $timeout - integer part means seconds, fractional part means microseconds
* @throws dnsException
*/
public function setConnectionTimeout($timeout = self::DEFAULT_CONNECTION_TIMEOUT)
{
if (!$new_timeout = floatval($timeout) || $timeout < 0)
{
throw new dnsException("Incorrect timeout value: <" . $timeout . ">. Timeout must be positive number.");
if (!is_float($timeout) || $timeout <= 0) {
throw new dnsException("Invalid connection timeout value: < $timeout >. Timeout must be a positive float.");
}
$this->connectiontimeout = $timeout;
}

public function getConnectionTimeout()
{
return $this->connectiontimeout;
}

/**
* @param float $timeout - integer part means seconds, fractional part means microseconds
* @throws dnsException
*/
public function setReadTimeout($timeout = self::DEFAULT_READ_TIMEOUT)
{
if (!is_float($timeout) || $timeout <= 0) {
throw new dnsException("Invalid connection timeout value: < $timeout >. Timeout must be a positive float.");
}
$this->timeout = $new_timeout;
$this->readtimeoutsec = (int)floor($timeout); // get seconds
$this->readtimeoutusec = (int)round(($timeout - $this->readtimeoutsec) * 1000000); // get microseconds
}

public function getTimeout()
public function getReadTimeout()
{
return $this->timeout;
return $this->readtimeoutsec + $this->readtimeoutusec / 1000000;
}

public function setPort($port)
Expand Down Expand Up @@ -358,8 +426,13 @@ function algorithm($code)

function registrynameservers($tld)
{
$ns = new dnsNameserver();
return $ns->getNs($tld);
set_error_handler(array($this,'error_handler'));
try {
$ns = new dnsNameserver();
return $ns->getNs($tld);
} finally {
restore_error_handler();
}
}

function base32encode($input, $padding = true) {
Expand Down