session-ios/Signal/src/network/dns/DnsManager.m

77 lines
2.9 KiB
Objective-C

#import "DnsManager.h"
#import <netdb.h>
#import "HttpResponse.h"
#import "IpEndPoint.h"
#import "ThreadManager.h"
#import "UdpSocket.h"
#import "Util.h"
#define STRING_POINTER_FLAG 0xc0
#define gethostbyname_ErrorDescriptions @{ \
@HOST_NOT_FOUND: @"HOST_NOT_FOUND. The specified host is unknown.", \
@NO_ADDRESS: @"NO_ADDRESS. The requested name is valid but does not have an IP address.", \
@NO_DATA: @"NO_DATA. The requested name is valid but does not have an IP address.", \
@NO_RECOVERY: @"NO_RECOVERY. A nonrecoverable name server error occurred.", \
@TRY_AGAIN: @"TRY_AGAIN. A temporary error occurred on an authoritative name server." \
}
@implementation DnsManager
void handleDnsCompleted(CFHostRef, CFHostInfoType, const CFStreamError*, void*);
void handleDnsCompleted(CFHostRef hostRef, CFHostInfoType typeInfo, const CFStreamError* error, void* info) {
DnsManager* instance = (__bridge_transfer DnsManager*)info;
@try {
Boolean gotHostAddressesData = false;
NSArray* addressDatas = (__bridge NSArray*)CFHostGetAddressing(hostRef, &gotHostAddressesData);
checkOperation(gotHostAddressesData);
checkOperationDescribe(addressDatas != nil, @"No addresses for host");
NSArray* ips = [addressDatas map:^(id addressData) {
checkOperation([addressData isKindOfClass:NSData.class]);
return [[IpEndPoint ipEndPointFromSockaddrData:addressData] address];
}];
[instance->futureResultSource trySetResult:ips];
} @catch (OperationFailed* ex) {
[instance->futureResultSource trySetFailure:ex];
}
}
+(TOCFuture*) asyncQueryAddressesForDomainName:(NSString*)domainName
unlessCancelled:(TOCCancelToken*)unlessCancelledToken {
require(domainName != nil);
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFStringRef)domainName);
checkOperation(hostRef != nil);
DnsManager* d = [DnsManager new];
d->futureResultSource = [TOCFutureSource futureSourceUntil:unlessCancelledToken];
CFHostClientContext c;
c.version = 0;
c.info = (__bridge_retained void*)d;
c.release = CFRelease;
c.retain = CFRetain;
c.copyDescription = CFCopyDescription;
CFHostSetClient(hostRef, handleDnsCompleted, &c);
CFHostScheduleWithRunLoop(hostRef,
[[ThreadManager normalLatencyThreadRunLoop] getCFRunLoop],
kCFRunLoopDefaultMode);
Boolean startedSuccess = CFHostStartInfoResolution(hostRef, kCFHostAddresses, &d->error);
CFRelease(hostRef);
if (!startedSuccess) {
[d->futureResultSource trySetFailure:[OperationFailed new:[NSString stringWithFormat:@"DNS query failed to start. Error code: %d",
(int)d->error.error]]];
}
return d->futureResultSource.future;
}
@end