소스 검색

feat(android): support NAT64

Adds Nat64InfoModule which resolves IPv6 addresses for IPv4 addresses
in IPv6 only network where jitsi-meet deployment does not provide any
IPv6 addresses as ICE candidates.
master
paweldomas 7 년 전
부모
커밋
968b279b37

+ 2
- 0
android/sdk/build.gradle 파일 보기

@@ -33,6 +33,8 @@ dependencies {
33 33
     compile project(':react-native-vector-icons')
34 34
     compile project(':react-native-webrtc')
35 35
     compile project(':react-native-calendar-events')
36
+
37
+    testCompile 'junit:junit:4.12'
36 38
 }
37 39
 
38 40
 // Build process helpers

+ 2
- 2
android/sdk/src/main/java/org/jitsi/meet/sdk/JitsiMeetView.java 파일 보기

@@ -21,7 +21,6 @@ import android.app.Application;
21 21
 import android.content.Context;
22 22
 import android.content.Intent;
23 23
 import android.net.Uri;
24
-import android.os.Build;
25 24
 import android.os.Bundle;
26 25
 import android.support.annotation.NonNull;
27 26
 import android.support.annotation.Nullable;
@@ -78,7 +77,8 @@ public class JitsiMeetView extends FrameLayout {
78 77
             new ExternalAPIModule(reactContext),
79 78
             new PictureInPictureModule(reactContext),
80 79
             new ProximityModule(reactContext),
81
-            new WiFiStatsModule(reactContext)
80
+            new WiFiStatsModule(reactContext),
81
+            new org.jitsi.meet.sdk.net.NAT64AddrInfoModule(reactContext)
82 82
         );
83 83
     }
84 84
 

+ 238
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/net/NAT64AddrInfo.java 파일 보기

@@ -0,0 +1,238 @@
1
+/*
2
+ * Copyright @ 2018-present Atlassian Pty Ltd
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package org.jitsi.meet.sdk.net;
17
+
18
+import java.net.InetAddress;
19
+import java.net.UnknownHostException;
20
+
21
+/**
22
+ * Constructs IPv6 addresses for IPv4 addresses in the NAT64 environment.
23
+ *
24
+ * NAT64 translates IPv4 to IPv6 addresses by adding "well known" prefix and
25
+ * suffix configured by the administrator. Those are figured out by discovering
26
+ * both IPv6 and IPv4 addresses of a host and then trying to find a place where
27
+ * the IPv4 address fits into the format described here:
28
+ * https://tools.ietf.org/html/rfc6052#section-2.2
29
+ */
30
+public class NAT64AddrInfo {
31
+    /**
32
+     * Coverts bytes array to upper case HEX string.
33
+     *
34
+     * @param bytes an array of bytes to be converted
35
+     * @return ex. "010AFF" for an array of {1, 10, 255}.
36
+     */
37
+    static String bytesToHexString(byte[] bytes) {
38
+        StringBuilder hexStr = new StringBuilder();
39
+
40
+        for (byte b : bytes) {
41
+            hexStr.append(String.format("%02X", b));
42
+        }
43
+
44
+        return hexStr.toString();
45
+    }
46
+
47
+    /**
48
+     * Tries to discover the NAT64 prefix/suffix based on the IPv4 and IPv6
49
+     * addresses resolved for given {@code host}.
50
+     *
51
+     * @param host the host for which the code will try to discover IPv4 and
52
+     * IPv6 addresses which then will be used to figure out the NAT64 prefix.
53
+     * @return {@link NAT64AddrInfo} instance if the NAT64 prefix/suffix was
54
+     * successfully discovered or {@code null} if it failed for any reason.
55
+     * @throws UnknownHostException thrown by {@link InetAddress#getAllByName}.
56
+     */
57
+    public static NAT64AddrInfo discover(String host)
58
+            throws UnknownHostException {
59
+        InetAddress ipv4 = null;
60
+        InetAddress ipv6 = null;
61
+
62
+        for(InetAddress addr : InetAddress.getAllByName(host)) {
63
+            byte[] bytes = addr.getAddress();
64
+
65
+            if (bytes.length == 4) {
66
+                ipv4 = addr;
67
+            } else if (bytes.length == 16) {
68
+                ipv6 = addr;
69
+            }
70
+        }
71
+
72
+        if (ipv4 != null && ipv6 != null) {
73
+            return figureOutNAT64AddrInfo(ipv4.getAddress(), ipv6.getAddress());
74
+        }
75
+
76
+        return null;
77
+    }
78
+
79
+    /**
80
+     * Based on IPv4 and IPv6 addresses of the same host, the method will make
81
+     * an attempt to figure out what are the NAT64 prefix and suffix.
82
+     *
83
+     * @param ipv4AddrBytes the IPv4 address of the same host in NAT64 network,
84
+     * as returned by {@link InetAddress#getAddress()}.
85
+     * @param ipv6AddrBytes the IPv6 address of the same host in NAT64 network,
86
+     * as returned by {@link InetAddress#getAddress()}.
87
+     * @return {@link NAT64AddrInfo} instance which contains the prefix/suffix
88
+     * of the current NAT64 network or {@code null} if the prefix could not be
89
+     * found.
90
+     */
91
+    static NAT64AddrInfo figureOutNAT64AddrInfo(
92
+            byte[] ipv4AddrBytes,
93
+            byte[] ipv6AddrBytes) {
94
+        String ipv6Str = bytesToHexString(ipv6AddrBytes);
95
+        String ipv4Str = bytesToHexString(ipv4AddrBytes);
96
+
97
+        // NAT64 address format:
98
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
99
+        // |PL| 0-------------32--40--48--56--64--72--80--88--96--104---------|
100
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
101
+        // |32|     prefix    |v4(32)         | u | suffix                    |
102
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
103
+        // |40|     prefix        |v4(24)     | u |(8)| suffix                |
104
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
105
+        // |48|     prefix            |v4(16) | u | (16)  | suffix            |
106
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
107
+        // |56|     prefix                |(8)| u |  v4(24)   | suffix        |
108
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
109
+        // |64|     prefix                    | u |   v4(32)      | suffix    |
110
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
111
+        // |96|     prefix                                    |    v4(32)     |
112
+        // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
113
+        int prefixLength = 96;
114
+        int suffixLength = 0;
115
+        String prefix = null;
116
+        String suffix = null;
117
+
118
+        if (ipv4Str.equalsIgnoreCase(ipv6Str.substring(prefixLength / 4))) {
119
+            prefix = ipv6Str.substring(0, prefixLength / 4);
120
+        } else {
121
+            // Cut out the 'u' octet
122
+            ipv6Str = ipv6Str.substring(0, 16) + ipv6Str.substring(18);
123
+
124
+            for (prefixLength = 64, suffixLength = 6; prefixLength >= 32; ) {
125
+                if (ipv4Str.equalsIgnoreCase(
126
+                        ipv6Str.substring(
127
+                                prefixLength / 4, prefixLength / 4 + 8))) {
128
+                    prefix = ipv6Str.substring(0, prefixLength / 4);
129
+                    suffix = ipv6Str.substring(ipv6Str.length() - suffixLength);
130
+                    break;
131
+                }
132
+
133
+                prefixLength -= 8;
134
+                suffixLength += 2;
135
+            }
136
+        }
137
+
138
+        return prefix != null ? new NAT64AddrInfo(prefix, suffix) : null;
139
+    }
140
+
141
+    /**
142
+     * An overload for {@link #hexStringToIPv6String(StringBuilder)}.
143
+     *
144
+     * @param hexStr a hex representation of IPv6 address bytes.
145
+     * @return an IPv6 address string.
146
+     */
147
+    static String hexStringToIPv6String(String hexStr) {
148
+        return hexStringToIPv6String(new StringBuilder(hexStr));
149
+    }
150
+
151
+    /**
152
+     * Converts from HEX representation of IPv6 address bytes into IPv6 address
153
+     * string which includes the ':' signs.
154
+     *
155
+     * @param str a hex representation of IPv6 address bytes.
156
+     * @return eg. FE80:CD00:0000:0CDA:1357:0000:212F:749C
157
+     */
158
+    static String hexStringToIPv6String(StringBuilder str) {
159
+        for (int i = 32 - 4; i > 0; i -= 4) {
160
+            str.insert(i, ":");
161
+        }
162
+
163
+        return str.toString().toUpperCase();
164
+    }
165
+
166
+    /**
167
+     * Parses an IPv4 address string and returns it's byte array representation.
168
+     *
169
+     * @param ipv4Address eg. '192.168.3.23'
170
+     * @return byte representation of given IPv4 address string.
171
+     * @throws IllegalArgumentException if the address is not in valid format.
172
+     */
173
+    static byte[] ipv4AddressStringToBytes(String ipv4Address) {
174
+        InetAddress address;
175
+
176
+        try {
177
+            address = InetAddress.getByName(ipv4Address);
178
+        } catch (UnknownHostException e) {
179
+            throw new IllegalArgumentException(
180
+                    "Invalid IP address: " + ipv4Address, e);
181
+        }
182
+
183
+        byte[] bytes = address.getAddress();
184
+
185
+        if (bytes.length != 4) {
186
+            throw new IllegalArgumentException(
187
+                    "Not an IPv4 address: " + ipv4Address);
188
+        }
189
+
190
+        return bytes;
191
+    }
192
+
193
+    /**
194
+     * The NAT64 prefix added to construct IPv6 from an IPv4 address.
195
+     */
196
+    private final String prefix;
197
+
198
+    /**
199
+     * The NAT64 suffix (if any) used to construct IPv6 from an IPv4 address.
200
+     */
201
+    private final String suffix;
202
+
203
+    /**
204
+     * Creates new instance of {@link NAT64AddrInfo}.
205
+     *
206
+     * @param prefix the NAT64 prefix.
207
+     * @param suffix the NAT64 suffix.
208
+     */
209
+    private NAT64AddrInfo(String prefix, String suffix) {
210
+        this.prefix = prefix;
211
+        this.suffix = suffix;
212
+    }
213
+
214
+    /**
215
+     * Based on the NAT64 prefix and suffix will create an IPv6 representation
216
+     * of the given IPv4 address.
217
+     *
218
+     * @param ipv4Address eg. '192.34.2.3'
219
+     * @return IPv6 address string eg. FE80:CD00:0000:0CDA:1357:0000:212F:749C
220
+     * @throws IllegalArgumentException if given string is not a valid IPv4
221
+     * address.
222
+     */
223
+    public String getIPv6Address(String ipv4Address) {
224
+        byte[] ipv4AddressBytes = ipv4AddressStringToBytes(ipv4Address);
225
+        StringBuilder newIPv6Str = new StringBuilder();
226
+
227
+        newIPv6Str.append(prefix);
228
+        newIPv6Str.append(bytesToHexString(ipv4AddressBytes));
229
+
230
+        if (suffix != null) {
231
+            // Insert the 'u' octet.
232
+            newIPv6Str.insert(16, "00");
233
+            newIPv6Str.append(suffix);
234
+        }
235
+
236
+        return hexStringToIPv6String(newIPv6Str);
237
+    }
238
+}

+ 122
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/net/NAT64AddrInfoModule.java 파일 보기

@@ -0,0 +1,122 @@
1
+/*
2
+ * Copyright @ 2018-present Atlassian Pty Ltd
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package org.jitsi.meet.sdk.net;
17
+
18
+import android.util.Log;
19
+
20
+import com.facebook.react.bridge.Promise;
21
+import com.facebook.react.bridge.ReactApplicationContext;
22
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
23
+import com.facebook.react.bridge.ReactMethod;
24
+
25
+import java.net.UnknownHostException;
26
+
27
+/**
28
+ * This module exposes the functionality of creating an IPv6 representation
29
+ * of IPv4 addresses in NAT64 environment.
30
+ *
31
+ * See[1] and [2] for more info on what NAT64 is.
32
+ * [1]: https://tools.ietf.org/html/rfc6146
33
+ * [2]: https://tools.ietf.org/html/rfc6052
34
+ */
35
+public class NAT64AddrInfoModule extends ReactContextBaseJavaModule {
36
+    /**
37
+     * The host for which the module wil try to resolve both IPv4 and IPv6
38
+     * addresses in order to figure out the NAT64 prefix.
39
+     */
40
+    private final static String HOST = "nat64.jitsi.net";
41
+
42
+    /**
43
+     * How long is the {@link NAT64AddrInfo} instance valid.
44
+     */
45
+    private final static long INFO_LIFETIME = 60 * 1000;
46
+
47
+    /**
48
+     * The name of this module.
49
+     */
50
+    private final static String MODULE_NAME = "NAT64AddrInfo";
51
+
52
+    /**
53
+     * The {@code Log} tag {@code NAT64AddrInfoModule} is to log messages with.
54
+     */
55
+    private final static String TAG = MODULE_NAME;
56
+
57
+    /**
58
+     * The {@link NAT64AddrInfo} instance which holds NAT64 prefix/suffix.
59
+     */
60
+    private NAT64AddrInfo info;
61
+
62
+    /**
63
+     * When {@link #info} was created.
64
+     */
65
+    private long infoTimestamp;
66
+
67
+    /**
68
+     * Creates new {@link NAT64AddrInfoModule}.
69
+     *
70
+     * @param reactContext the react context to be used by the new module
71
+     * instance.
72
+     */
73
+    public NAT64AddrInfoModule(ReactApplicationContext reactContext) {
74
+        super(reactContext);
75
+    }
76
+
77
+    /**
78
+     * Tries to obtain IPv6 address for given IPv4 address in NAT64 environment.
79
+     *
80
+     * @param ipv4Address IPv4 address string.
81
+     * @param promise a {@link Promise} which will be resolved either with IPv6
82
+     * address for given IPv4 address or with {@code null} if no
83
+     * {@link NAT64AddrInfo} was resolved for the current network. Will be
84
+     * rejected if given {@code ipv4Address} is not a valid IPv4 address.
85
+     */
86
+    @ReactMethod
87
+    public void getIPv6Address(String ipv4Address, final Promise promise) {
88
+        // Reset if cached for too long.
89
+        if (System.currentTimeMillis() - infoTimestamp > INFO_LIFETIME) {
90
+            info = null;
91
+        }
92
+
93
+        if (info == null) {
94
+            String host = HOST;
95
+
96
+            try {
97
+                info = NAT64AddrInfo.discover(host);
98
+            } catch (UnknownHostException e) {
99
+                Log.e(TAG, "NAT64AddrInfo.discover: " + host, e);
100
+            }
101
+            infoTimestamp = System.currentTimeMillis();
102
+        }
103
+
104
+        String result;
105
+
106
+        try {
107
+            result = info == null ? null : info.getIPv6Address(ipv4Address);
108
+        } catch (IllegalArgumentException exc) {
109
+            Log.e(TAG, "Failed to get IPv6 address for: " + ipv4Address, exc);
110
+
111
+            // We don't want to reject. It's not a big deal if there's no IPv6
112
+            // address resolved.
113
+            result = null;
114
+        }
115
+        promise.resolve(result);
116
+    }
117
+
118
+    @Override
119
+    public String getName() {
120
+        return MODULE_NAME;
121
+    }
122
+}

+ 150
- 0
android/sdk/src/test/java/org/jitsi/meet/sdk/net/NAT64AddrInfoTest.java 파일 보기

@@ -0,0 +1,150 @@
1
+/*
2
+ * Copyright @ 2017-present Atlassian Pty Ltd
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package org.jitsi.meet.sdk.net;
17
+
18
+import org.junit.Test;
19
+
20
+import java.math.BigInteger;
21
+import java.net.UnknownHostException;
22
+
23
+import static org.junit.Assert.*;
24
+
25
+/**
26
+ * Tests for {@link NAT64AddrInfo} class.
27
+ */
28
+public class NAT64AddrInfoTest {
29
+    /**
30
+     * Test case for the 96 prefix length.
31
+     */
32
+    @Test
33
+    public void test96Prefix() {
34
+        testPrefixSuffix(
35
+                "260777000000000400000000", "", "203.0.113.1", "23.17.23.3");
36
+    }
37
+
38
+    /**
39
+     * Test case for the 64 prefix length.
40
+     */
41
+    @Test
42
+    public void test64Prefix() {
43
+        String prefix = "1FF2A227B3AAF3D2";
44
+        String suffix = "BB87C8";
45
+
46
+        testPrefixSuffix(prefix, suffix, "48.46.87.34", "23.87.145.4");
47
+    }
48
+
49
+    /**
50
+     * Test case for the 56 prefix length.
51
+     */
52
+    @Test
53
+    public void test56Prefix() {
54
+        String prefix = "1FF2A227B3AAF3";
55
+        String suffix = "A2BB87C8";
56
+
57
+        testPrefixSuffix(prefix, suffix, "34.72.234.255", "1.235.3.65");
58
+    }
59
+
60
+    /**
61
+     * Test case for the 48 prefix length.
62
+     */
63
+    @Test
64
+    public void test48Prefix() {
65
+        String prefix = "1FF2A227B3AA";
66
+        String suffix = "72A2BB87C8";
67
+
68
+        testPrefixSuffix(prefix, suffix, "97.54.3.23", "77.49.0.33");
69
+    }
70
+
71
+    /**
72
+     * Test case for the 40 prefix length.
73
+     */
74
+    @Test
75
+    public void test40Prefix() {
76
+        String prefix = "1FF2A227B3";
77
+        String suffix = "D972A2BB87C8";
78
+
79
+        testPrefixSuffix(prefix, suffix, "10.23.56.121", "97.65.32.21");
80
+    }
81
+
82
+    /**
83
+     * Test case for the 32 prefix length.
84
+     */
85
+    @Test
86
+    public void test32Prefix()
87
+        throws UnknownHostException {
88
+        String prefix = "1FF2A227";
89
+        String suffix = "20D972A2BB87C8";
90
+
91
+        testPrefixSuffix(prefix, suffix, "162.63.65.189", "135.222.84.206");
92
+    }
93
+
94
+    private static String buildIPv6Addr(
95
+            String prefix, String suffix, String ipv4Hex) {
96
+        String ipv6Str = prefix + ipv4Hex + suffix;
97
+
98
+        if (suffix.length() > 0) {
99
+            ipv6Str = new StringBuilder(ipv6Str).insert(16, "00").toString();
100
+        }
101
+
102
+        return ipv6Str;
103
+    }
104
+
105
+    private void testPrefixSuffix(
106
+            String prefix, String suffix, String ipv4, String otherIPv4) {
107
+        byte[] ipv4Bytes = NAT64AddrInfo.ipv4AddressStringToBytes(ipv4);
108
+        String ipv4String = NAT64AddrInfo.bytesToHexString(ipv4Bytes);
109
+        String ipv6Str = buildIPv6Addr(prefix, suffix, ipv4String);
110
+
111
+        BigInteger ipv6Address = new BigInteger(ipv6Str, 16);
112
+
113
+        NAT64AddrInfo nat64AddrInfo
114
+            = NAT64AddrInfo.figureOutNAT64AddrInfo(
115
+                    ipv4Bytes, ipv6Address.toByteArray());
116
+
117
+        assertNotNull("Failed to figure out NAT64 info", nat64AddrInfo);
118
+
119
+        String newIPv6 = nat64AddrInfo.getIPv6Address(ipv4);
120
+
121
+        assertEquals(
122
+                NAT64AddrInfo.hexStringToIPv6String(ipv6Address.toString(16)),
123
+                newIPv6);
124
+
125
+        byte[] ipv4Addr2 = NAT64AddrInfo.ipv4AddressStringToBytes(otherIPv4);
126
+        String ipv4Addr2Hex = NAT64AddrInfo.bytesToHexString(ipv4Addr2);
127
+
128
+        newIPv6 = nat64AddrInfo.getIPv6Address(otherIPv4);
129
+
130
+        assertEquals(
131
+                NAT64AddrInfo.hexStringToIPv6String(
132
+                        buildIPv6Addr(prefix, suffix, ipv4Addr2Hex)),
133
+                newIPv6);
134
+    }
135
+
136
+    @Test
137
+    public void testInvalidIPv4Format() {
138
+        testInvalidIPv4Format("256.1.2.3");
139
+        testInvalidIPv4Format("FE80:CD00:0000:0CDA:1357:0000:212F:749C");
140
+    }
141
+
142
+    private void testInvalidIPv4Format(String ipv4Str) {
143
+        try {
144
+            NAT64AddrInfo.ipv4AddressStringToBytes(ipv4Str);
145
+            fail("Did not throw IllegalArgumentException");
146
+        } catch (IllegalArgumentException exc) {
147
+            /* OK */
148
+        }
149
+    }
150
+}

+ 51
- 11
react/features/base/lib-jitsi-meet/native/RTCPeerConnection.js 파일 보기

@@ -231,8 +231,54 @@ function _setRemoteDescription(sessionDescription) {
231 231
     });
232 232
 }
233 233
 
234
+// XXX The function _synthesizeIPv6FromIPv4Address is not placed relative to the
235
+// other functions in the file according to alphabetical sorting rule of the
236
+// coding style. But eslint wants constants to be defined before they are used.
237
+
234 238
 /**
235
- * Synthesize IPv6 addresses on iOS in order to support IPv6 NAT64 networks.
239
+ * Synthesizes an IPv6 address from a specific IPv4 address.
240
+ *
241
+ * @param {string} ipv4 - The IPv4 address from which an IPv6 address is to be
242
+ * synthesized.
243
+ * @returns {Promise<?string>} A {@code Promise} which gets resolved with the
244
+ * IPv6 address synthesized from the specified {@code ipv4} or a falsy value to
245
+ * be treated as inability to synthesize an IPv6 address from the specified
246
+ * {@code ipv4}.
247
+ */
248
+const _synthesizeIPv6FromIPv4Address: string => Promise<?string> = (function() {
249
+    // POSIX.getaddrinfo
250
+    const { POSIX } = NativeModules;
251
+
252
+    if (POSIX) {
253
+        const { getaddrinfo } = POSIX;
254
+
255
+        if (typeof getaddrinfo === 'function') {
256
+            return ipv4 =>
257
+                getaddrinfo(/* hostname */ ipv4, /* servname */ undefined)
258
+                    .then(([ { ai_addr: ipv6 } ]) => ipv6);
259
+        }
260
+    }
261
+
262
+    // NAT64AddrInfo.getIPv6Address
263
+    const { NAT64AddrInfo } = NativeModules;
264
+
265
+    if (NAT64AddrInfo) {
266
+        const { getIPv6Address } = NAT64AddrInfo;
267
+
268
+        if (typeof getIPv6Address === 'function') {
269
+            return getIPv6Address;
270
+        }
271
+    }
272
+
273
+    // There's no POSIX.getaddrinfo or NAT64AddrInfo.getIPv6Address.
274
+    return () =>
275
+        Promise.reject(
276
+            'The impossible just happened! No POSIX.getaddrinfo or'
277
+                + ' NAT64AddrInfo.getIPv6Address!');
278
+})();
279
+
280
+/**
281
+ * Synthesizes IPv6 addresses on iOS in order to support IPv6 NAT64 networks.
236 282
  *
237 283
  * @param {RTCSessionDescription} sdp - The RTCSessionDescription which
238 284
  * specifies the configuration of the remote end of the connection.
@@ -240,12 +286,6 @@ function _setRemoteDescription(sessionDescription) {
240 286
  * @returns {Promise}
241 287
  */
242 288
 function _synthesizeIPv6Addresses(sdp) {
243
-    // The synthesis of IPv6 addresses is implemented on iOS only at the time of
244
-    // this writing.
245
-    if (!NativeModules.POSIX) {
246
-        return Promise.resolve(sdp);
247
-    }
248
-
249 289
     return (
250 290
         new Promise(resolve => resolve(_synthesizeIPv6Addresses0(sdp)))
251 291
             .then(({ ips, lines }) =>
@@ -272,7 +312,6 @@ function _synthesizeIPv6Addresses0(sessionDescription) {
272 312
     let start = 0;
273 313
     const lines = [];
274 314
     const ips = new Map();
275
-    const { getaddrinfo } = NativeModules.POSIX;
276 315
 
277 316
     do {
278 317
         const end = sdp.indexOf('\r\n', start);
@@ -311,9 +350,10 @@ function _synthesizeIPv6Addresses0(sessionDescription) {
311 350
                                 if (v && typeof v === 'string') {
312 351
                                     resolve(v);
313 352
                                 } else {
314
-                                    getaddrinfo(ip, undefined).then(
315
-                                        ([ { ai_addr: value } ]) => {
316
-                                            if (value.indexOf(':') === -1
353
+                                    _synthesizeIPv6FromIPv4Address(ip).then(
354
+                                        value => {
355
+                                            if (!value
356
+                                                    || value.indexOf(':') === -1
317 357
                                                     || value === ips.get(ip)) {
318 358
                                                 ips.delete(ip);
319 359
                                             } else {

Loading…
취소
저장