[iOS] Synthesize IPv6 addresses closer to Apple's recommendation
This commit is contained in:
parent
05de599739
commit
65abd5efd4
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue