First up, I’m assuming you have
getaddrinfo_compat
from
this post. Follow the link to find out why that’s important.
Second, pasted in below there’s some code I wrote for dealing with this sort of thing. It breaks down as follows:
WARNING
getaddrinfo
as used by
+addressesForIPv4DottedDecimal:port:
, can hit the network, making it a synchronous blocking networking call. Do not do this on the main thread. See QA1693
Synchronous Networking On The Main Thread for an explanation of why.
Note The reason why
getaddrinfo
can hit the network in this case is that it may need to look up
ipv4only.arpa.
.
RFC 7050 explains why.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
+ (nullable NSArray<NSData *> *)addressesForIPv4DottedDecimal:(NSString *)ipv4Addr port:(NSInteger)port {
NSMutableArray * result;
NSString * portStr;
struct addrinfo * addrList;
int err;
static const struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_flags = AI_DEFAULT
};
NSParameterAssert( ! [NSThread isMainThread] );
result = nil;
portStr = [NSString stringWithFormat:@"%zd", port];
err = getaddrinfo_compat(ipv4Addr.UTF8String, portStr.UTF8String, &hints, &addrList);
if (err == 0) {
struct addrinfo * addr;
result = [[NSMutableArray alloc] init];
for (addr = addrList; addr != NULL; addr = addr->ai_next) {
[result addObject:[NSData dataWithBytes:addr->ai_addr length:addr->ai_addrlen]];
}
freeaddrinfo(addrList);
}
return result;
}
+ (nullable NSString *)stringForAddress:(NSData *)address {
NSString * result;
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int err;
result = nil;
err = getnameinfo(address.bytes, (socklen_t) address.length, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
if (err == 0) {
result = [NSString stringWithFormat:@"%s:%s", host, service];
}
return result;
}
+ (nullable NSURL *)URLBySettingAddress:(NSData *)address inURL:(NSURL *)url {
NSURL * result;
NSURLComponents * components;
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int err;
result = nil;
components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
if (components != nil) {
err = getnameinfo(address.bytes, (socklen_t) address.length, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
if (err == 0) {
NSString * hostStr = @(host);
if ([hostStr containsString:@":"]) {
hostStr = [NSString stringWithFormat:@"[%@]", hostStr];
}
components.host = hostStr;
components.port = @(atoi(service));
result = components.URL;
}
}
return result;
}