[iOS] Synthesize IPv6 addresses closer to Apple's recommendation

This commit is contained in:
Lyubo Marinov 2017-12-19 13:34:56 -06:00
parent 05de599739
commit 65abd5efd4
2 changed files with 82 additions and 37 deletions

View File

@ -18,6 +18,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -29,54 +30,81 @@
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(getaddrinfo:(NSString *)hostname
servname:(NSString *)servname
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
int err;
const char *hostname_ = hostname ? hostname.UTF8String : NULL;
const char *servname_ = servname ? servname.UTF8String : NULL;
struct addrinfo hints;
struct addrinfo *res;
NSString *rejectCode;
if (0 == (err = getaddrinfo(hostname.UTF8String, NULL, NULL, &res))) {
int af = res->ai_family;
struct sockaddr *sa = res->ai_addr;
void *addr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_DEFAULT;
if (0 == (err = getaddrinfo(hostname_, servname_, &hints, &res))) {
char addr_[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
NSMutableArray *res_ = [[NSMutableArray alloc] init];
switch (af) {
case AF_INET:
addr = &(((struct sockaddr_in *) sa)->sin_addr);
break;
case AF_INET6:
addr = &(((struct sockaddr_in6 *) sa)->sin6_addr);
break;
default:
addr = NULL;
break;
}
if (addr) {
char v[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
for (struct addrinfo *ai = res; ai; ai = ai->ai_next) {
int af = ai->ai_family;
struct sockaddr *sa = ai->ai_addr;
void *addr;
if (inet_ntop(af, addr, v, sizeof(v))) {
resolve([NSString stringWithUTF8String:v]);
} else {
err = errno;
rejectCode = @"inet_ntop";
switch (af) {
case AF_INET:
addr = &(((struct sockaddr_in *) sa)->sin_addr);
break;
case AF_INET6:
addr = &(((struct sockaddr_in6 *) sa)->sin6_addr);
break;
default:
addr = NULL;
break;
}
if (addr) {
if (inet_ntop(af, addr, addr_, sizeof(addr_))) {
[res_ addObject:@{
@"ai_addr": [NSString stringWithUTF8String:addr_],
@"ai_family": [NSNumber numberWithInt:af],
@"ai_protocol":
[NSNumber numberWithInt:ai->ai_protocol],
@"ai_socktype": [NSNumber numberWithInt:ai->ai_socktype]
}];
} else {
err = errno;
rejectCode = @"inet_ntop";
}
} else {
err = EAFNOSUPPORT;
rejectCode = @"EAFNOSUPPORT";
}
} else {
err = EAFNOSUPPORT;
rejectCode = @"EAFNOSUPPORT";
}
freeaddrinfo(res);
// resolve
if (res_.count) {
resolve(res_);
return;
}
if (!err) {
err = ERANGE;
rejectCode = @"ERANGE";
}
} else {
rejectCode = @"getaddrinfo";
}
if (0 != err) {
NSError *error
= [NSError errorWithDomain:NSPOSIXErrorDomain
code:err
userInfo:nil];
reject(rejectCode, error.localizedDescription, error);
}
// reject
NSError *error
= [NSError errorWithDomain:NSPOSIXErrorDomain
code:err
userInfo:nil];
reject(rejectCode, error.localizedDescription, error);
}
@end

View File

@ -1,6 +1,23 @@
import { NativeModules } from 'react-native';
import { RTCPeerConnection, RTCSessionDescription } from 'react-native-webrtc';
/* eslint-disable no-unused-vars */
// Address families.
const AF_INET6 = 30; /* IPv6 */
// Protocols (RFC 1700)
const IPPROTO_TCP = 6; /* tcp */
const IPPROTO_UDP = 17; /* user datagram protocol */
// Protocol families, same as address families for now.
const PF_INET6 = AF_INET6;
const SOCK_DGRAM = 2; /* datagram socket */
const SOCK_STREAM = 1; /* stream socket */
/* eslint-enable no-unused-vars */
// XXX At the time of this writing extending RTCPeerConnection using ES6 'class'
// and 'extends' causes a runtime error related to the attempt to define the
// onaddstream property setter. The error mentions that babelHelpers.set is
@ -182,7 +199,7 @@ function _synthesizeIPv6Addresses(sdp) {
/* eslint-disable max-depth */
/**
* Implements the initial phase of the synthesis of IPv6 addresses.
* Begins the asynchronous synthesis of IPv6 addresses.
*
* @param {RTCSessionDescription} sessionDescription - The RTCSessionDescription
* for which IPv6 addresses will be synthesized.
@ -197,7 +214,7 @@ function _synthesizeIPv6Addresses0(sessionDescription) {
let start = 0;
const lines = [];
const ips = new Map();
const getaddrinfo = NativeModules.POSIX.getaddrinfo;
const { getaddrinfo } = NativeModules.POSIX;
do {
const end = sdp.indexOf('\r\n', start);
@ -236,8 +253,8 @@ function _synthesizeIPv6Addresses0(sessionDescription) {
if (v && typeof v === 'string') {
resolve(v);
} else {
getaddrinfo(ip).then(
value => {
getaddrinfo(ip, undefined).then(
([ { ai_addr: value } ]) => {
if (value.indexOf(':') === -1
|| value === ips.get(ip)) {
ips.delete(ip);
@ -275,7 +292,7 @@ function _synthesizeIPv6Addresses0(sessionDescription) {
/* eslint-enable max-depth */
/**
* Implements the initial phase of the synthesis of IPv6 addresses.
* Completes the asynchronous ynthesis of IPv6 addresses.
*
* @param {RTCSessionDescription} sessionDescription - The RTCSessionDescription
* for which IPv6 addresses are being synthesized.