NetworkRTCResolverCocoa.cpp [plain text]
#include "config.h"
#include "NetworkRTCResolverCocoa.h"
#if USE(LIBWEBRTC)
#include <wtf/Expected.h>
namespace WebKit {
static void resolvedName(CFHostRef hostRef, CFHostInfoType typeInfo, const CFStreamError *error, void *info)
{
ASSERT_UNUSED(typeInfo, !typeInfo);
ASSERT(info);
auto* resolver = static_cast<NetworkRTCResolverCocoa*>(info);
if (error->domain) {
resolver->completed(makeUnexpected(WebCore::DNSError::Unknown));
return;
}
Boolean result;
CFArrayRef resolvedAddresses = (CFArrayRef)CFHostGetAddressing(hostRef, &result);
ASSERT_UNUSED(result, result);
size_t count = CFArrayGetCount(resolvedAddresses);
Vector<WebCore::IPAddress> addresses;
addresses.reserveInitialCapacity(count);
for (size_t index = 0; index < count; ++index) {
CFDataRef data = (CFDataRef)CFArrayGetValueAtIndex(resolvedAddresses, index);
auto* address = reinterpret_cast<const struct sockaddr_in*>(CFDataGetBytePtr(data));
if (address->sin_family == AF_INET)
addresses.uncheckedAppend(WebCore::IPAddress(*address));
}
if (addresses.isEmpty()) {
resolver->completed(makeUnexpected(WebCore::DNSError::CannotResolve));
return;
}
resolver->completed(WTFMove(addresses));
}
std::unique_ptr<NetworkRTCResolver> NetworkRTCResolver::create(uint64_t identifier, WebCore::DNSCompletionHandler&& completionHandler)
{
return std::unique_ptr<NetworkRTCResolver>(new NetworkRTCResolverCocoa(identifier, WTFMove(completionHandler)));
}
NetworkRTCResolverCocoa::NetworkRTCResolverCocoa(uint64_t identifier, WebCore::DNSCompletionHandler&& completionHandler)
: NetworkRTCResolver(identifier, WTFMove(completionHandler))
{
}
NetworkRTCResolverCocoa::~NetworkRTCResolverCocoa()
{
CFHostUnscheduleFromRunLoop(m_host.get(), CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFHostSetClient(m_host.get(), nullptr, nullptr);
}
void NetworkRTCResolverCocoa::start(const String& address)
{
m_host = adoptCF(CFHostCreateWithName(kCFAllocatorDefault, address.createCFString().get()));
CFHostClientContext context = { 0, this, nullptr, nullptr, nullptr };
CFHostSetClient(m_host.get(), resolvedName, &context);
CFHostScheduleWithRunLoop(m_host.get(), CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
Boolean result = CFHostStartInfoResolution(m_host.get(), kCFHostAddresses, nullptr);
ASSERT_UNUSED(result, result);
}
void NetworkRTCResolverCocoa::stop()
{
CFHostCancelInfoResolution(m_host.get(), CFHostInfoType::kCFHostAddresses);
if (auto completionHandler = WTFMove(m_completionHandler))
completionHandler(makeUnexpected(WebCore::DNSError::Cancelled));
}
void NetworkRTCResolverCocoa::completed(WebCore::DNSAddressesOrError&& addressesOrError)
{
if (auto completionHandler = WTFMove(m_completionHandler))
completionHandler(WTFMove(addressesOrError));
}
}
#endif // USE(LIBWEBRTC)