/** * Run the server. * * @return void */ public function run() { $this->_server->considerRemoteAddress(true); $this->_server->connectAndWait(); while (true) { $buffer = $this->_server->read(1024); if (empty($buffer)) { continue; } // Skip header. $handle = substr($buffer, 12); $domain = null; // QNAME. for ($i = 0, $m = strlen($handle); $i < $m; ++$i) { if (0 === ($length = ord($handle[$i]))) { break; } if (null !== $domain) { $domain .= '.'; } $domain .= substr($handle, $i + 1, $length); $i += $length; } // QTYPE. $i += 2; $qtype = (int) (string) ord($handle[$i]) + (int) (string) ord($handle[$i + 1]); $type = array_search($qtype, static::$_types) ?: $qtype; // QCLASS. $i += 2; $qclass = (int) (string) ord($handle[$i]); $class = array_search($qclass, static::$_classes) ?: $qclass; $ips = $this->_on->fire('query', new Core\Event\Bucket(['domain' => $domain, 'type' => $type, 'class' => $class])); $ip = null; if (false === $ips[0]) { $this->_server->writeAll($buffer[0] . $buffer[1] . pack('C', 1 << 7 | 1) . pack('C', 0 | 3) . pack('n', 0) . pack('n', 0) . pack('n', 0) . pack('n', 0)); continue; } foreach (explode('.', $ips[0]) as $foo) { $ip .= pack('C', $foo); } $this->_server->writeAll($buffer[0] . $buffer[1] . pack('C', 1 << 7 | 1) . pack('C', 0) . $buffer[4] . $buffer[5] . pack('n', 1) . pack('n', 0) . pack('n', 0) . $handle . pack('CC', 192, 12) . pack('n', $qtype) . pack('n', $qclass) . pack('N', 60) . pack('n', 4) . $ip); } $this->_server->disconnect(); return; }