/**
* Called when new UDP packet received.
* @param string $pct
* @return void
*/
public function onUdpPacket($pct)
{
$orig = $pct;
$this->response = [];
/*$id = */
Binary::getWord($pct);
$bitmap = Binary::getBitmap(Binary::getByte($pct)) . Binary::getBitmap(Binary::getByte($pct));
//$qr = (int) $bitmap[0];
$opcode = bindec(substr($bitmap, 1, 4));
//$aa = (int) $bitmap[5];
//$tc = (int) $bitmap[6];
//$rd = (int) $bitmap[7];
//$ra = (int) $bitmap[8];
//$z = bindec(substr($bitmap, 9, 3));
//$rcode = bindec(substr($bitmap, 12));
$qdcount = Binary::getWord($pct);
$ancount = Binary::getWord($pct);
$nscount = Binary::getWord($pct);
$arcount = Binary::getWord($pct);
for ($i = 0; $i < $qdcount; ++$i) {
$name = Binary::parseLabels($pct, $orig);
$typeInt = Binary::getWord($pct);
$type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')';
$classInt = Binary::getWord($pct);
$class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')';
if (!isset($this->response[$type])) {
$this->response[$type] = [];
}
$record = ['name' => $name, 'type' => $type, 'class' => $class];
$this->response['query'][] = $record;
}
$getResRecord = function (&$pct) use($orig) {
$name = Binary::parseLabels($pct, $orig);
$typeInt = Binary::getWord($pct);
$type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')';
$classInt = Binary::getWord($pct);
$class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')';
$ttl = Binary::getDWord($pct);
$length = Binary::getWord($pct);
$data = binarySubstr($pct, 0, $length);
$pct = binarySubstr($pct, $length);
$record = ['name' => $name, 'type' => $type, 'class' => $class, 'ttl' => $ttl];
if ($type === 'A') {
if ($data === "") {
$record['ip'] = false;
$record['ttl'] = 5;
} else {
$record['ip'] = inet_ntop($data);
}
} elseif ($type === 'NS') {
$record['ns'] = Binary::parseLabels($data);
} elseif ($type === 'CNAME') {
$record['cname'] = Binary::parseLabels($data, $orig);
}
return $record;
};
for ($i = 0; $i < $ancount; ++$i) {
$record = $getResRecord($pct);
if (!isset($this->response[$record['type']])) {
$this->response[$record['type']] = [];
}
$this->response[$record['type']][] = $record;
}
for ($i = 0; $i < $nscount; ++$i) {
$record = $getResRecord($pct);
if (!isset($this->response[$record['type']])) {
$this->response[$record['type']] = [];
}
$this->response[$record['type']][] = $record;
}
for ($i = 0; $i < $arcount; ++$i) {
$record = $getResRecord($pct);
if (!isset($this->response[$record['type']])) {
$this->response[$record['type']] = [];
}
$this->response[$record['type']][] = $record;
}
$this->onResponse->executeOne($this->response);
if (!$this->keepalive) {
$this->finish();
return;
} else {
$this->checkFree();
}
}