toResolvedServer(); } } $txtRecords = self::dnsGetTxtRecords($domain); if ($txtRecords === false) { throw new ResolutionException(sprintf("Failed to resolve DNS TXT records for %s", $domain)); } $fullRecord = self::concatenateTxtRecords($txtRecords); if (preg_match(self::PATTERN, $fullRecord, $matches)) { $endpoint = trim($matches[1]); $publicKey = trim(str_replace(' ', '', $matches[2])); if (empty($endpoint)) { throw new ResolutionException(sprintf("Failed to resolve RPC endpoint for %s", $domain)); } if (empty($publicKey)) { throw new ResolutionException(sprintf("Failed to resolve public key for %s", $domain)); } return new ResolvedServer($endpoint, $publicKey); } else { throw new ResolutionException(sprintf("Failed to find valid SocialBox record for %s", $domain)); } } /** * Retrieves the TXT records for a given domain using the dns_get_record function. * * @param string $domain The domain name to fetch TXT records for. * @return array|false An array of DNS TXT records on success, or false on failure. */ private static function dnsGetTxtRecords(string $domain) { return dns_get_record($domain, DNS_TXT); } /** * Concatenates an array of TXT records into a single string, filtering for SocialBox records. * * @param array $txtRecords An array of TXT records, where each record is expected to have a 'txt' key. * @return string A concatenated string of all relevant TXT records. */ private static function concatenateTxtRecords(array $txtRecords): string { $fullRecordBuilder = ''; foreach ($txtRecords as $txt) { if (isset($txt['txt'])) { $record = trim($txt['txt'], '" '); // Only include records that start with v=socialbox if (stripos($record, 'v=socialbox') === 0) { $fullRecordBuilder .= $record; } } } return $fullRecordBuilder; } }