diff --git a/CHANGELOG.md b/CHANGELOG.md index 92c35b9..38cf374 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [6.2.0](https://github.com/Rapsssito/react-native-tcp-socket/compare/v6.1.0...v6.2.0) (2024-07-08) + + +### Features + +* **Android:** Add TLS key & cert for server ([#192](https://github.com/Rapsssito/react-native-tcp-socket/issues/192)) ([054c789](https://github.com/Rapsssito/react-native-tcp-socket/commit/054c7890dc0575acceb93c24794c0fade6c548a8)) + # [6.1.0](https://github.com/Rapsssito/react-native-tcp-socket/compare/v6.0.6...v6.1.0) (2024-06-20) diff --git a/README.md b/README.md index 865e35a..bacfdec 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ React Native TCP socket API for Android, iOS & macOS with **SSL/TLS support**. I - [Getting started](#getting-started) - [Overriding `net`](#overriding-net) - [Overriding `tls`](#overriding-tls) - - [Using React Native >= 0.60](#using-react-native--060) - - [Self-Signed SSL (only available for React Native > 0.60)](#self-signed-ssl-only-available-for-react-native--060) - - [Using React Native < 0.60](#using-react-native--060-1) + - [Using React Native \>= 0.60](#using-react-native--060) + - [Self-Signed SSL (only available for React Native \> 0.60)](#self-signed-ssl-only-available-for-react-native--060) + - [Using React Native \< 0.60](#using-react-native--060-1) - [React Native Compatibility](#react-native-compatibility) - [Usage](#usage) - [Client example](#client-example) @@ -409,6 +409,8 @@ Here are listed all methods implemented in `react-native-tcp-socket` that imitat #### TLSSocket * **Methods:** * All methods from [`Socket`](#socket) + * [`getCertificate()`](https://nodejs.org/api/tls.html#tlssocketgetcertificate) _Android only_ + * **[`getPeerCertificate()`](https://nodejs.org/api/tls.html#tlssocketgetpeercertificatedetailed)** _Android only_ * **Properties:** * All properties from [`Socket`](#socket) * **Events:** @@ -418,10 +420,15 @@ Here are listed all methods implemented in `react-native-tcp-socket` that imitat ##### `tls.connectTLS()` `tls.connectTLS(options[, callback])` creates a TLS socket connection using the given `options`. The `options` parameter must be an `object` with the following properties: -| Property | Type | iOS/macOS | Android | Description | -| -------- | ---------- | :-------: | :-----: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `ca` | `` | ✅ | ✅ | CA file (.pem format) to trust. If `null`, it will use the device's default SSL trusted list. Useful for self-signed certificates. _Check the [documentation](#self-signed-ssl-only-available-for-react-native--060) for generating such file_. **Default**: `null`. | -| `...` | `` | ✅ | ✅ | Any other [`socket.connect()`](#netcreateconnection----omit-in-toc) options not already listed. | +| Property | Type | iOS/macOS | Android | Description | +| ----------------- | ---------- | :-------: | :-----: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ca` | `` | ✅ | ✅ | CA file (.pem format) to trust. If `null`, it will use the device's default SSL trusted list. Useful for self-signed certificates. _Check the [documentation](#self-signed-ssl-only-available-for-react-native--060) for generating such file_. **Default**: `null`. | +| `key` | `` | ❌ | ✅ | Private key file (.pem format). _Check the [documentation](#self-signed-ssl-only-available-for-react-native--060) for generating such file_. | +| `cert` | `` | ❌ | ✅ | Public certificate file (.pem format). _Check the [documentation](#self-signed-ssl-only-available-for-react-native--060) for generating such file_. | +| `androidKeyStore` | `` | ❌ | ✅ | Android KeyStore alias. | +| `certAlias` | `` | ❌ | ✅ | Android KeyStore certificate alias. | +| `keyAlias` | `` | ❌ | ✅ | Android KeyStore private key alias. | +| `...` | `` | ✅ | ✅ | Any other [`socket.connect()`](#netcreateconnection----omit-in-toc) options not already listed. | #### TLSServer __Note__: The TLS server is named `Server` in Node's tls, but it is named `TLSServer` in `react-native-tcp-socket` in order to avoid confusion with the [`Server`](#server) class. diff --git a/android/build.gradle b/android/build.gradle index 5a70bd6..ddd2688 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -16,4 +16,7 @@ android { dependencies { //noinspection GradleDynamicVersion implementation 'com.facebook.react:react-native:+' // From node_modules + // Bouncy Castle dependencies + implementation 'org.bouncycastle:bcprov-jdk15on:1.70' + implementation 'org.bouncycastle:bcpkix-jdk15on:1.70' } \ No newline at end of file diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/KeystoreInfo.java b/android/src/main/java/com/asterinet/react/tcpsocket/KeystoreInfo.java new file mode 100644 index 0000000..fc23533 --- /dev/null +++ b/android/src/main/java/com/asterinet/react/tcpsocket/KeystoreInfo.java @@ -0,0 +1,58 @@ +package com.asterinet.react.tcpsocket; + +public class KeystoreInfo { + private String keystoreName; + private String caAlias; + private String certAlias; + private String keyAlias; + + public KeystoreInfo(String keystoreName, String caAlias, String certAlias, String keyAlias) { + this.keystoreName = keystoreName; + this.caAlias = (caAlias == null || caAlias.isEmpty()) ? "ca" : caAlias; + this.certAlias = (certAlias == null || certAlias.isEmpty()) ? "cert" : certAlias; + this.keyAlias = (keyAlias == null || keyAlias.isEmpty()) ? "key" : keyAlias; + } + + public String getKeystoreName() { + return this.keystoreName; + } + + public void setKeystoreName(String keystoreName) { + this.keystoreName = keystoreName; + } + + public String getCaAlias() { + return this.caAlias; + } + + public void setCaAlias(String caAlias) { + this.caAlias = caAlias; + } + + public String getCertAlias() { + return this.certAlias; + } + + public void setCertAlias(String certAlias) { + this.certAlias = certAlias; + } + + public String getKeyAlias() { + return this.keyAlias; + } + + public void setKeyAlias(String keyAlias) { + this.keyAlias = keyAlias; + } + + @Override + public String toString() { + return "KeystoreInfo{" + + "keystoreName='" + this.keystoreName + '\'' + + ", caAlias='" + this.caAlias + '\'' + + ", certAlias='" + this.certAlias + '\'' + + ", keyAlias='" + this.keyAlias + '\'' + + '}'; + } +} + diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/ResolvableOption.java b/android/src/main/java/com/asterinet/react/tcpsocket/ResolvableOption.java new file mode 100644 index 0000000..1df3ca1 --- /dev/null +++ b/android/src/main/java/com/asterinet/react/tcpsocket/ResolvableOption.java @@ -0,0 +1,20 @@ +package com.asterinet.react.tcpsocket; + +public class ResolvableOption { + private final String value; + private final boolean needsResolution; + + public ResolvableOption(String value, boolean needsResolution) { + this.value = value; + this.needsResolution = needsResolution; + } + + public String getValue() { + return value; + } + + public boolean needsResolution() { + return needsResolution; + } +} + diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/SSLCertificateHelper.java b/android/src/main/java/com/asterinet/react/tcpsocket/SSLCertificateHelper.java index 20bc9f8..9d830cb 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/SSLCertificateHelper.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/SSLCertificateHelper.java @@ -2,32 +2,56 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.os.Build; import androidx.annotation.NonNull; import androidx.annotation.RawRes; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ByteArrayInputStream; +import java.math.BigInteger; +import java.net.Socket; import java.net.URI; import java.security.GeneralSecurityException; +import java.security.KeyFactory; import java.security.KeyStore; +import java.security.PrivateKey; import java.security.SecureRandom; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPublicKey; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; +import java.util.Locale; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509TrustManager; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; + + +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.json.JSONObject; + final class SSLCertificateHelper { + /** * Creates an SSLSocketFactory instance for use with all CAs provided. * @@ -56,31 +80,113 @@ static SSLServerSocketFactory createServerSocketFactory(Context context, @NonNul return sslContext.getServerSocketFactory(); } + public static PrivateKey getPrivateKeyFromPEM(InputStream keyStream) { + try (PemReader pemReader = new PemReader(new InputStreamReader(keyStream))) { + PemObject pemObject = pemReader.readPemObject(); + byte[] pemContent = pemObject.getContent(); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemContent); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePrivate(keySpec); + } catch (Exception e) { + throw new RuntimeException("Failed to parse private key from PEM", e); + } + } + + /** + * Creates an InpuStream either from a getRawResourceStream or from raw string + * + * @param context Context used to retrieve resource + * @param optionRes ResolvableOption + * @return An InputStream + */ + public static InputStream getResolvableinputStream( + @NonNull final Context context, + ResolvableOption optionRes) throws IOException { + if (optionRes.needsResolution()) { + return getRawResourceStream(context, optionRes.getValue()); + } else { + return new ByteArrayInputStream(optionRes.getValue().getBytes()); + } + } + /** * Creates an SSLSocketFactory instance for use with the CA provided in the resource file. * - * @param context Context used to open up the CA file - * @param rawResourceUri Raw resource file to the CA (in .crt or .cer format, for instance) + * @param context Context used to open up the CA file + * @param optionResCa Raw resource file or string to the CA (in .crt or .cer format, for instance) + * @param optionResKey Optional raw resource file or string to the Key (in .crt or .cer format, for instance) + * @param optionResCert Optional raw resource file or string to the Cert (in .crt or .cer format, for instance) + * @param keystoreInfo Information about keystore name and key/cert alias * @return An SSLSocketFactory which trusts the provided CA when provided to network clients */ - static SSLSocketFactory createCustomTrustedSocketFactory(@NonNull final Context context, @NonNull final String rawResourceUri) throws IOException, GeneralSecurityException { - InputStream caInput = getRawResourceStream(context, rawResourceUri); - // Generate the CA Certificate from the raw resource file - Certificate ca = CertificateFactory.getInstance("X.509").generateCertificate(caInput); - caInput.close(); - // Load the key store using the CA - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null, null); - keyStore.setCertificateEntry("ca", ca); - - // Initialize the TrustManager with this CA - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(keyStore); - - // Create an SSL context that uses the created trust manager - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, tmf.getTrustManagers(), new SecureRandom()); - return sslContext.getSocketFactory(); + static SSLSocketFactory createCustomTrustedSocketFactory( + @NonNull final Context context, + final ResolvableOption optionResCa, + final ResolvableOption optionResKey, + final ResolvableOption optionResCert, + final KeystoreInfo keystoreInfo) throws IOException, GeneralSecurityException { + + SSLSocketFactory ssf = null; + if (optionResCert != null && optionResKey != null) { + final String keyStoreName = keystoreInfo.getKeystoreName().isEmpty() ? + KeyStore.getDefaultType() : + keystoreInfo.getKeystoreName(); + KeyStore keyStore = KeyStore.getInstance(keyStoreName); + keyStore.load(null, null); + + // Check if cert and key if already registered inside our keystore + // If one is missing we insert again + boolean hasCertInStore = keyStore.isCertificateEntry(keystoreInfo.getCertAlias()); + boolean hasKeyInStore = keyStore.isKeyEntry(keystoreInfo.getKeyAlias()); + if (!hasCertInStore || !hasKeyInStore) { + InputStream certInput = getResolvableinputStream(context, optionResCert); + Certificate cert = CertificateFactory.getInstance("X.509").generateCertificate(certInput); + keyStore.setCertificateEntry(keystoreInfo.getCertAlias(), cert); + + InputStream keyInput = getResolvableinputStream(context, optionResKey); + PrivateKey privateKey = getPrivateKeyFromPEM(keyInput); + keyStore.setKeyEntry(keystoreInfo.getKeyAlias(), privateKey, null, new Certificate[]{cert}); + } + + boolean hasCaInStore = keyStore.isCertificateEntry(keystoreInfo.getCaAlias()); + if (optionResCa != null && !hasCaInStore) { + InputStream caInput = getResolvableinputStream(context, optionResCa); + // Generate the CA Certificate from the raw resource file + Certificate ca = CertificateFactory.getInstance("X.509").generateCertificate(caInput); + caInput.close(); + // Load the key store using the CA + keyStore.setCertificateEntry(keystoreInfo.getCaAlias(), ca); + } + + // Initialize the KeyManagerFactory with this cert + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, new char[0]); + + // Create an SSL context that uses the created trust manager + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{new BlindTrustManager()}, null); + return sslContext.getSocketFactory(); + + } else { + // Keep old behavior + InputStream caInput = getResolvableinputStream(context, optionResCa); + // Generate the CA Certificate from the raw resource file + Certificate ca = CertificateFactory.getInstance("X.509").generateCertificate(caInput); + caInput.close(); + // Load the key store using the CA + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + keyStore.setCertificateEntry("ca", ca); + + // Initialize the TrustManager with this CA + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(keyStore); + + // Create an SSL context that uses the created trust manager + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, tmf.getTrustManagers(), new SecureRandom()); + return sslContext.getSocketFactory(); + } } private static InputStream getRawResourceStream(@NonNull final Context context, @NonNull final String resourceUri) throws IOException { @@ -113,4 +219,117 @@ public void checkClientTrusted(X509Certificate[] chain, String authType) { public void checkServerTrusted(X509Certificate[] chain, String authType) { } } + + public static ReadableMap getCertificateInfo(Socket socket, boolean wantPeerCert) { + WritableMap certInfo = Arguments.createMap(); + + if (socket instanceof SSLSocket) { + SSLSocket sslSocket = (SSLSocket) socket; + try { + SSLSession sslSession = sslSocket.getSession(); + Certificate[] certificates = wantPeerCert ? sslSession.getPeerCertificates() : sslSession.getLocalCertificates(); + if (certificates != null && certificates.length > 0 && certificates[0] instanceof X509Certificate) { + X509Certificate cert = (X509Certificate) certificates[0]; + WritableMap certDetails = Arguments.createMap(); + certDetails.putMap("subject", parseDN(cert.getSubjectDN().getName())); + certDetails.putMap("issuer", parseDN(cert.getIssuerDN().getName())); + certDetails.putBoolean("ca", cert.getBasicConstraints() != -1); + certDetails.putString("modulus", getModulus(cert)); + certDetails.putInt("bits", getModulusBitLength(cert)); + certDetails.putString("exponent", "0x" + getExponent(cert)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + certDetails.putString("pubkey", Base64.getEncoder().encodeToString(cert.getPublicKey().getEncoded())); + } + certDetails.putString("valid_from", formatDate(cert.getNotBefore())); + certDetails.putString("valid_to", formatDate(cert.getNotAfter())); + certDetails.putString("fingerprint", getFingerprint(cert, "SHA-1")); + certDetails.putString("fingerprint256", getFingerprint(cert, "SHA-256")); + certDetails.putString("fingerprint512", getFingerprint(cert, "SHA-512")); + certDetails.putString("serialNumber", getSerialNumber(cert)); + + certInfo = certDetails; + } + } catch (SSLPeerUnverifiedException e) { + throw new RuntimeException(e); + } catch (Exception e) { + throw new RuntimeException("Error processing certificate", e); + } + } + + return certInfo; + } + + // LdapName don't seem to be available on android .... + // So very very dummy implementation + // I can see inside android/platform/libcore an implementation but don't even know if we + // can import it... + //https://android.googlesource.com/platform/libcore/+/0ebbfbdbca73d6261a77183f68e1f3e56c339f9f/ojluni/src/main/java/javax/naming/ + + private static WritableMap parseDN(String dn) { + WritableMap details = Arguments.createMap(); + String[] components = dn.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); // Split by comma, but not inside quotes + for (String component : components) { + String[] keyValue = component.split("=", 2); + if (keyValue.length == 2) { + String key = keyValue[0].trim(); + String value = keyValue[1].trim(); + if ("2.5.4.46".equals(key)) { // OID for dnQualifier + if (value.startsWith("#")) { + String dnQualifier = decodeHexString(value.substring(1)); + details.putString("dnQualifier", dnQualifier); + } else { + details.putString("dnQualifier", value); + } + } else if ("CN".equals(key)) { + details.putString("CN", value); + } + } + } + return details; + } + + private static String decodeHexString(String hex) { + StringBuilder output = new StringBuilder(); + for (int i = 0; i < hex.length(); i += 2) { + String str = hex.substring(i, i + 2); + output.append((char) Integer.parseInt(str, 16)); + } + // Remove leading control characters if they exist + return output.toString().replaceAll("^\\p{Cntrl}", "").trim(); + } + + private static String getSerialNumber(X509Certificate cert) { + BigInteger serialNumber = cert.getSerialNumber(); + return serialNumber.toString(16).toUpperCase(); // Convert to hex string and uppercase + } + private static String getModulus(X509Certificate cert) throws Exception { + RSAPublicKey rsaPubKey = (RSAPublicKey) cert.getPublicKey(); + return rsaPubKey.getModulus().toString(16).toUpperCase(); + } + + private static int getModulusBitLength(X509Certificate cert) throws Exception { + RSAPublicKey rsaPubKey = (RSAPublicKey) cert.getPublicKey(); + return rsaPubKey.getModulus().bitLength(); + } + private static String getExponent(X509Certificate cert) throws Exception { + RSAPublicKey rsaPubKey = (RSAPublicKey) cert.getPublicKey(); + return rsaPubKey.getPublicExponent().toString(16).toUpperCase(); + } + + private static String getFingerprint(X509Certificate cert, String algorithm) throws Exception { + byte[] encoded = cert.getEncoded(); + java.security.MessageDigest md = java.security.MessageDigest.getInstance(algorithm); + byte[] digest = md.digest(encoded); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02X:", b)); + } + return sb.substring(0, sb.length() - 1); // Remove the trailing colon + } + + private static String formatDate(Date date) { + SimpleDateFormat sdf = new SimpleDateFormat("MMM dd HH:mm:ss yyyy 'GMT'", Locale.US); + sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT")); + return sdf.format(date); + } } diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java index d08fc1b..6e745a4 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java @@ -4,6 +4,7 @@ import android.net.Network; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.ReadableArray; import java.io.BufferedInputStream; import java.io.IOException; @@ -78,13 +79,58 @@ public void startTLS(Context context, ReadableMap tlsOptions) throws IOException socket = sslSocket; } + private boolean containsKey(ReadableArray array, String key) { + for (int i = 0; i < array.size(); i++) { + if (array.getString(i).equals(key)) { + return true; + } + } + return false; + } + private ResolvableOption getResolvableOption(ReadableMap tlsOptions, String key) { + if (tlsOptions.hasKey(key)) { + String value = tlsOptions.getString(key); + ReadableArray resolvedKeys = tlsOptions.hasKey("resolvedKeys") ? tlsOptions.getArray("resolvedKeys") : null; + boolean needsResolution = resolvedKeys != null && containsKey(resolvedKeys, key); + return new ResolvableOption(value, needsResolution); + } + return null; + } + private SSLSocketFactory getSSLSocketFactory(Context context, ReadableMap tlsOptions) throws GeneralSecurityException, IOException { - SSLSocketFactory ssf; + SSLSocketFactory ssf = null; + + final ResolvableOption customTlsCa = getResolvableOption(tlsOptions, "ca"); + final ResolvableOption customTlsKey = getResolvableOption(tlsOptions, "key"); + final ResolvableOption customTlsCert = getResolvableOption(tlsOptions, "cert"); + final String keystoreName = tlsOptions.hasKey("androidKeyStore") ? tlsOptions.getString("androidKeyStore") : ""; + final String caAlias = tlsOptions.hasKey("caAlias") ? tlsOptions.getString("caAlias") : ""; + final String keyAlias = tlsOptions.hasKey("keyAlias") ? tlsOptions.getString("keyAlias") : ""; + final String certAlias = tlsOptions.hasKey("certAlias") ? tlsOptions.getString("certAlias") : ""; + final KeystoreInfo keystoreInfo = new KeystoreInfo(keystoreName, caAlias, certAlias, keyAlias); + if (tlsOptions.hasKey("rejectUnauthorized") && !tlsOptions.getBoolean("rejectUnauthorized")) { - ssf = SSLCertificateHelper.createBlindSocketFactory(); + if (customTlsKey != null && customTlsCert != null ) { + ssf = SSLCertificateHelper.createCustomTrustedSocketFactory( + context, + customTlsCa, + customTlsKey, + customTlsCert, + keystoreInfo + ); + } else { + ssf = SSLCertificateHelper.createBlindSocketFactory(); + } } else { - final String customTlsCert = tlsOptions.hasKey("ca") ? tlsOptions.getString("ca") : null; - ssf = customTlsCert != null ? SSLCertificateHelper.createCustomTrustedSocketFactory(context, customTlsCert) : (SSLSocketFactory) SSLSocketFactory.getDefault(); + ssf = (customTlsCa != null) + ? SSLCertificateHelper.createCustomTrustedSocketFactory( + context, + customTlsCa, + customTlsKey, + customTlsCert, + keystoreInfo + ) + : (SSLSocketFactory) SSLSocketFactory.getDefault(); } return ssf; } @@ -118,6 +164,14 @@ public void run() { }); } + public ReadableMap getPeerCertificate() { + return SSLCertificateHelper.getCertificateInfo(socket, true); + } + + public ReadableMap getCertificate() { + return SSLCertificateHelper.getCertificateInfo(socket, false); + } + /** * Shuts down the receiver task, closing the socket. */ diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java index 3944542..326f7ef 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java @@ -10,6 +10,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.util.Base64; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -18,6 +19,8 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.Promise; import java.io.IOException; import java.net.Inet4Address; @@ -381,6 +384,28 @@ private TcpSocketServer getTcpServer(final int id) { return (TcpSocketServer) socket; } + @SuppressWarnings("unused") + @ReactMethod + public void getPeerCertificate(final int cId, Promise promise) { + try { + final TcpSocketClient client = getTcpClient(cId); + promise.resolve(client.getPeerCertificate()); + } catch (Exception e) { + promise.reject(e); + } + } + + @SuppressWarnings("unused") + @ReactMethod + public void getCertificate(final int cId, Promise promise) { + try { + final TcpSocketClient client = getTcpClient(cId); + promise.resolve(client.getCertificate()); + } catch (Exception e) { + promise.reject(e); + } + } + private static class CurrentNetwork { @Nullable Network network = null; diff --git a/coverage/coverage-final.json b/coverage/coverage-final.json index a7ea223..13e9246 100644 --- a/coverage/coverage-final.json +++ b/coverage/coverage-final.json @@ -2,6 +2,6 @@ ,"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/Server.js": {"path":"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/Server.js","statementMap":{"0":{"start":{"line":5,"column":16},"end":{"line":5,"column":40}},"1":{"start":{"line":26,"column":8},"end":{"line":26,"column":16}},"2":{"start":{"line":28,"column":8},"end":{"line":28,"column":31}},"3":{"start":{"line":30,"column":8},"end":{"line":30,"column":48}},"4":{"start":{"line":32,"column":8},"end":{"line":32,"column":38}},"5":{"start":{"line":34,"column":8},"end":{"line":34,"column":39}},"6":{"start":{"line":36,"column":8},"end":{"line":36,"column":36}},"7":{"start":{"line":38,"column":8},"end":{"line":38,"column":38}},"8":{"start":{"line":39,"column":8},"end":{"line":39,"column":31}},"9":{"start":{"line":40,"column":8},"end":{"line":40,"column":31}},"10":{"start":{"line":41,"column":8},"end":{"line":41,"column":74}},"11":{"start":{"line":41,"column":32},"end":{"line":41,"column":74}},"12":{"start":{"line":42,"column":8},"end":{"line":42,"column":54}},"13":{"start":{"line":60,"column":8},"end":{"line":60,"column":91}},"14":{"start":{"line":60,"column":46},"end":{"line":60,"column":91}},"15":{"start":{"line":61,"column":27},"end":{"line":61,"column":41}},"16":{"start":{"line":62,"column":8},"end":{"line":62,"column":55}},"17":{"start":{"line":63,"column":8},"end":{"line":66,"column":11}},"18":{"start":{"line":64,"column":12},"end":{"line":64,"column":34}},"19":{"start":{"line":65,"column":12},"end":{"line":65,"column":37}},"20":{"start":{"line":65,"column":26},"end":{"line":65,"column":37}},"21":{"start":{"line":67,"column":8},"end":{"line":67,"column":45}},"22":{"start":{"line":68,"column":8},"end":{"line":68,"column":20}},"23":{"start":{"line":80,"column":8},"end":{"line":80,"column":47}},"24":{"start":{"line":81,"column":8},"end":{"line":81,"column":20}},"25":{"start":{"line":94,"column":8},"end":{"line":97,"column":9}},"26":{"start":{"line":95,"column":12},"end":{"line":95,"column":60}},"27":{"start":{"line":96,"column":12},"end":{"line":96,"column":24}},"28":{"start":{"line":98,"column":8},"end":{"line":98,"column":51}},"29":{"start":{"line":98,"column":22},"end":{"line":98,"column":51}},"30":{"start":{"line":99,"column":8},"end":{"line":99,"column":31}},"31":{"start":{"line":100,"column":8},"end":{"line":100,"column":32}},"32":{"start":{"line":101,"column":8},"end":{"line":101,"column":61}},"33":{"start":{"line":101,"column":42},"end":{"line":101,"column":61}},"34":{"start":{"line":102,"column":8},"end":{"line":102,"column":20}},"35":{"start":{"line":113,"column":8},"end":{"line":113,"column":45}},"36":{"start":{"line":113,"column":33},"end":{"line":113,"column":45}},"37":{"start":{"line":114,"column":8},"end":{"line":114,"column":97}},"38":{"start":{"line":118,"column":8},"end":{"line":118,"column":90}},"39":{"start":{"line":119,"column":8},"end":{"line":119,"column":20}},"40":{"start":{"line":123,"column":8},"end":{"line":123,"column":92}},"41":{"start":{"line":124,"column":8},"end":{"line":124,"column":20}},"42":{"start":{"line":131,"column":8},"end":{"line":137,"column":11}},"43":{"start":{"line":132,"column":12},"end":{"line":132,"column":44}},"44":{"start":{"line":132,"column":37},"end":{"line":132,"column":44}},"45":{"start":{"line":133,"column":12},"end":{"line":133,"column":61}},"46":{"start":{"line":134,"column":12},"end":{"line":134,"column":55}},"47":{"start":{"line":135,"column":12},"end":{"line":135,"column":59}},"48":{"start":{"line":136,"column":12},"end":{"line":136,"column":35}},"49":{"start":{"line":138,"column":8},"end":{"line":142,"column":11}},"50":{"start":{"line":139,"column":12},"end":{"line":139,"column":44}},"51":{"start":{"line":139,"column":37},"end":{"line":139,"column":44}},"52":{"start":{"line":140,"column":12},"end":{"line":140,"column":25}},"53":{"start":{"line":141,"column":12},"end":{"line":141,"column":42}},"54":{"start":{"line":143,"column":8},"end":{"line":148,"column":11}},"55":{"start":{"line":144,"column":12},"end":{"line":144,"column":44}},"56":{"start":{"line":144,"column":37},"end":{"line":144,"column":44}},"57":{"start":{"line":145,"column":30},"end":{"line":145,"column":57}},"58":{"start":{"line":146,"column":12},"end":{"line":146,"column":43}},"59":{"start":{"line":147,"column":12},"end":{"line":147,"column":47}},"60":{"start":{"line":155,"column":8},"end":{"line":155,"column":39}},"61":{"start":{"line":156,"column":8},"end":{"line":156,"column":36}},"62":{"start":{"line":157,"column":8},"end":{"line":157,"column":38}},"63":{"start":{"line":166,"column":8},"end":{"line":169,"column":11}},"64":{"start":{"line":167,"column":12},"end":{"line":167,"column":45}},"65":{"start":{"line":168,"column":12},"end":{"line":168,"column":84}},"66":{"start":{"line":168,"column":65},"end":{"line":168,"column":84}},"67":{"start":{"line":170,"column":8},"end":{"line":170,"column":38}},"68":{"start":{"line":179,"column":26},"end":{"line":179,"column":38}},"69":{"start":{"line":180,"column":8},"end":{"line":180,"column":34}},"70":{"start":{"line":181,"column":8},"end":{"line":181,"column":49}},"71":{"start":{"line":182,"column":8},"end":{"line":182,"column":25}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":25,"column":4},"end":{"line":25,"column":5}},"loc":{"start":{"line":25,"column":36},"end":{"line":43,"column":5}},"line":25},"1":{"name":"(anonymous_1)","decl":{"start":{"line":59,"column":4},"end":{"line":59,"column":5}},"loc":{"start":{"line":59,"column":30},"end":{"line":69,"column":5}},"line":59},"2":{"name":"(anonymous_2)","decl":{"start":{"line":63,"column":31},"end":{"line":63,"column":32}},"loc":{"start":{"line":63,"column":37},"end":{"line":66,"column":9}},"line":63},"3":{"name":"(anonymous_3)","decl":{"start":{"line":79,"column":4},"end":{"line":79,"column":5}},"loc":{"start":{"line":79,"column":29},"end":{"line":82,"column":5}},"line":79},"4":{"name":"(anonymous_4)","decl":{"start":{"line":93,"column":4},"end":{"line":93,"column":5}},"loc":{"start":{"line":93,"column":20},"end":{"line":103,"column":5}},"line":93},"5":{"name":"(anonymous_5)","decl":{"start":{"line":112,"column":4},"end":{"line":112,"column":5}},"loc":{"start":{"line":112,"column":14},"end":{"line":115,"column":5}},"line":112},"6":{"name":"(anonymous_6)","decl":{"start":{"line":117,"column":4},"end":{"line":117,"column":5}},"loc":{"start":{"line":117,"column":10},"end":{"line":120,"column":5}},"line":117},"7":{"name":"(anonymous_7)","decl":{"start":{"line":122,"column":4},"end":{"line":122,"column":5}},"loc":{"start":{"line":122,"column":12},"end":{"line":125,"column":5}},"line":122},"8":{"name":"(anonymous_8)","decl":{"start":{"line":130,"column":4},"end":{"line":130,"column":5}},"loc":{"start":{"line":130,"column":22},"end":{"line":149,"column":5}},"line":130},"9":{"name":"(anonymous_9)","decl":{"start":{"line":131,"column":78},"end":{"line":131,"column":79}},"loc":{"start":{"line":131,"column":87},"end":{"line":137,"column":9}},"line":131},"10":{"name":"(anonymous_10)","decl":{"start":{"line":138,"column":70},"end":{"line":138,"column":71}},"loc":{"start":{"line":138,"column":79},"end":{"line":142,"column":9}},"line":138},"11":{"name":"(anonymous_11)","decl":{"start":{"line":143,"column":81},"end":{"line":143,"column":82}},"loc":{"start":{"line":143,"column":90},"end":{"line":148,"column":9}},"line":143},"12":{"name":"(anonymous_12)","decl":{"start":{"line":154,"column":4},"end":{"line":154,"column":5}},"loc":{"start":{"line":154,"column":23},"end":{"line":158,"column":5}},"line":154},"13":{"name":"(anonymous_13)","decl":{"start":{"line":164,"column":4},"end":{"line":164,"column":5}},"loc":{"start":{"line":164,"column":27},"end":{"line":171,"column":5}},"line":164},"14":{"name":"(anonymous_14)","decl":{"start":{"line":166,"column":27},"end":{"line":166,"column":28}},"loc":{"start":{"line":166,"column":33},"end":{"line":169,"column":9}},"line":166},"15":{"name":"(anonymous_15)","decl":{"start":{"line":178,"column":4},"end":{"line":178,"column":5}},"loc":{"start":{"line":178,"column":23},"end":{"line":183,"column":5}},"line":178}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":8},"end":{"line":41,"column":74}},"type":"if","locations":[{"start":{"line":41,"column":8},"end":{"line":41,"column":74}},{"start":{"line":41,"column":8},"end":{"line":41,"column":74}}],"line":41},"1":{"loc":{"start":{"line":60,"column":8},"end":{"line":60,"column":91}},"type":"if","locations":[{"start":{"line":60,"column":8},"end":{"line":60,"column":91}},{"start":{"line":60,"column":8},"end":{"line":60,"column":91}}],"line":60},"2":{"loc":{"start":{"line":62,"column":26},"end":{"line":62,"column":54}},"type":"binary-expr","locations":[{"start":{"line":62,"column":26},"end":{"line":62,"column":41}},{"start":{"line":62,"column":45},"end":{"line":62,"column":54}}],"line":62},"3":{"loc":{"start":{"line":65,"column":12},"end":{"line":65,"column":37}},"type":"if","locations":[{"start":{"line":65,"column":12},"end":{"line":65,"column":37}},{"start":{"line":65,"column":12},"end":{"line":65,"column":37}}],"line":65},"4":{"loc":{"start":{"line":94,"column":8},"end":{"line":97,"column":9}},"type":"if","locations":[{"start":{"line":94,"column":8},"end":{"line":97,"column":9}},{"start":{"line":94,"column":8},"end":{"line":97,"column":9}}],"line":94},"5":{"loc":{"start":{"line":98,"column":8},"end":{"line":98,"column":51}},"type":"if","locations":[{"start":{"line":98,"column":8},"end":{"line":98,"column":51}},{"start":{"line":98,"column":8},"end":{"line":98,"column":51}}],"line":98},"6":{"loc":{"start":{"line":101,"column":8},"end":{"line":101,"column":61}},"type":"if","locations":[{"start":{"line":101,"column":8},"end":{"line":101,"column":61}},{"start":{"line":101,"column":8},"end":{"line":101,"column":61}}],"line":101},"7":{"loc":{"start":{"line":113,"column":8},"end":{"line":113,"column":45}},"type":"if","locations":[{"start":{"line":113,"column":8},"end":{"line":113,"column":45}},{"start":{"line":113,"column":8},"end":{"line":113,"column":45}}],"line":113},"8":{"loc":{"start":{"line":132,"column":12},"end":{"line":132,"column":44}},"type":"if","locations":[{"start":{"line":132,"column":12},"end":{"line":132,"column":44}},{"start":{"line":132,"column":12},"end":{"line":132,"column":44}}],"line":132},"9":{"loc":{"start":{"line":139,"column":12},"end":{"line":139,"column":44}},"type":"if","locations":[{"start":{"line":139,"column":12},"end":{"line":139,"column":44}},{"start":{"line":139,"column":12},"end":{"line":139,"column":44}}],"line":139},"10":{"loc":{"start":{"line":144,"column":12},"end":{"line":144,"column":44}},"type":"if","locations":[{"start":{"line":144,"column":12},"end":{"line":144,"column":44}},{"start":{"line":144,"column":12},"end":{"line":144,"column":44}}],"line":144},"11":{"loc":{"start":{"line":168,"column":12},"end":{"line":168,"column":84}},"type":"if","locations":[{"start":{"line":168,"column":12},"end":{"line":168,"column":84}},{"start":{"line":168,"column":12},"end":{"line":168,"column":84}}],"line":168},"12":{"loc":{"start":{"line":168,"column":16},"end":{"line":168,"column":63}},"type":"binary-expr","locations":[{"start":{"line":168,"column":16},"end":{"line":168,"column":31}},{"start":{"line":168,"column":35},"end":{"line":168,"column":63}}],"line":168}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":1,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":1,"50":0,"51":0,"52":0,"53":0,"54":1,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0},"f":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":1,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"b":{"0":[1,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"931d8475e97a2935b74a179958ed4ecd9b024f4a"} ,"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/Socket.js": {"path":"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/Socket.js","statementMap":{"0":{"start":{"line":6,"column":16},"end":{"line":6,"column":40}},"1":{"start":{"line":50,"column":8},"end":{"line":50,"column":16}},"2":{"start":{"line":52,"column":8},"end":{"line":52,"column":31}},"3":{"start":{"line":54,"column":8},"end":{"line":54,"column":48}},"4":{"start":{"line":56,"column":8},"end":{"line":56,"column":49}},"5":{"start":{"line":58,"column":8},"end":{"line":58,"column":31}},"6":{"start":{"line":60,"column":8},"end":{"line":60,"column":34}},"7":{"start":{"line":62,"column":8},"end":{"line":62,"column":35}},"8":{"start":{"line":64,"column":8},"end":{"line":64,"column":24}},"9":{"start":{"line":66,"column":8},"end":{"line":66,"column":57}},"10":{"start":{"line":68,"column":8},"end":{"line":68,"column":32}},"11":{"start":{"line":70,"column":8},"end":{"line":70,"column":29}},"12":{"start":{"line":72,"column":8},"end":{"line":72,"column":31}},"13":{"start":{"line":74,"column":8},"end":{"line":74,"column":34}},"14":{"start":{"line":76,"column":8},"end":{"line":76,"column":28}},"15":{"start":{"line":78,"column":8},"end":{"line":78,"column":31}},"16":{"start":{"line":80,"column":8},"end":{"line":80,"column":33}},"17":{"start":{"line":82,"column":8},"end":{"line":82,"column":29}},"18":{"start":{"line":84,"column":8},"end":{"line":84,"column":32}},"19":{"start":{"line":87,"column":8},"end":{"line":87,"column":34}},"20":{"start":{"line":89,"column":8},"end":{"line":89,"column":36}},"21":{"start":{"line":90,"column":8},"end":{"line":90,"column":43}},"22":{"start":{"line":91,"column":8},"end":{"line":91,"column":43}},"23":{"start":{"line":92,"column":8},"end":{"line":92,"column":39}},"24":{"start":{"line":93,"column":8},"end":{"line":93,"column":38}},"25":{"start":{"line":94,"column":8},"end":{"line":94,"column":35}},"26":{"start":{"line":95,"column":8},"end":{"line":95,"column":39}},"27":{"start":{"line":96,"column":8},"end":{"line":96,"column":36}},"28":{"start":{"line":97,"column":8},"end":{"line":97,"column":38}},"29":{"start":{"line":98,"column":8},"end":{"line":98,"column":31}},"30":{"start":{"line":102,"column":8},"end":{"line":102,"column":32}},"31":{"start":{"line":106,"column":8},"end":{"line":106,"column":31}},"32":{"start":{"line":110,"column":8},"end":{"line":110,"column":29}},"33":{"start":{"line":114,"column":8},"end":{"line":114,"column":32}},"34":{"start":{"line":118,"column":8},"end":{"line":118,"column":34}},"35":{"start":{"line":122,"column":8},"end":{"line":122,"column":31}},"36":{"start":{"line":126,"column":8},"end":{"line":126,"column":29}},"37":{"start":{"line":134,"column":8},"end":{"line":134,"column":22}},"38":{"start":{"line":135,"column":8},"end":{"line":135,"column":31}},"39":{"start":{"line":143,"column":8},"end":{"line":143,"column":33}},"40":{"start":{"line":144,"column":8},"end":{"line":144,"column":34}},"41":{"start":{"line":145,"column":8},"end":{"line":145,"column":30}},"42":{"start":{"line":146,"column":8},"end":{"line":146,"column":56}},"43":{"start":{"line":147,"column":8},"end":{"line":147,"column":50}},"44":{"start":{"line":148,"column":8},"end":{"line":148,"column":58}},"45":{"start":{"line":149,"column":8},"end":{"line":149,"column":56}},"46":{"start":{"line":150,"column":8},"end":{"line":150,"column":52}},"47":{"start":{"line":158,"column":30},"end":{"line":158,"column":44}},"48":{"start":{"line":160,"column":8},"end":{"line":160,"column":63}},"49":{"start":{"line":161,"column":8},"end":{"line":161,"column":61}},"50":{"start":{"line":162,"column":8},"end":{"line":164,"column":11}},"51":{"start":{"line":163,"column":12},"end":{"line":163,"column":37}},"52":{"start":{"line":163,"column":26},"end":{"line":163,"column":37}},"53":{"start":{"line":165,"column":8},"end":{"line":165,"column":32}},"54":{"start":{"line":166,"column":8},"end":{"line":166,"column":37}},"55":{"start":{"line":167,"column":8},"end":{"line":167,"column":89}},"56":{"start":{"line":168,"column":8},"end":{"line":168,"column":20}},"57":{"start":{"line":185,"column":8},"end":{"line":189,"column":9}},"58":{"start":{"line":186,"column":12},"end":{"line":186,"column":33}},"59":{"start":{"line":188,"column":12},"end":{"line":188,"column":41}},"60":{"start":{"line":190,"column":8},"end":{"line":190,"column":53}},"61":{"start":{"line":190,"column":22},"end":{"line":190,"column":53}},"62":{"start":{"line":191,"column":8},"end":{"line":191,"column":20}},"63":{"start":{"line":199,"column":8},"end":{"line":199,"column":64}},"64":{"start":{"line":199,"column":35},"end":{"line":199,"column":64}},"65":{"start":{"line":200,"column":8},"end":{"line":200,"column":29}},"66":{"start":{"line":201,"column":8},"end":{"line":204,"column":31}},"67":{"start":{"line":202,"column":12},"end":{"line":202,"column":33}},"68":{"start":{"line":203,"column":12},"end":{"line":203,"column":33}},"69":{"start":{"line":211,"column":8},"end":{"line":214,"column":9}},"70":{"start":{"line":212,"column":12},"end":{"line":212,"column":40}},"71":{"start":{"line":213,"column":12},"end":{"line":213,"column":38}},"72":{"start":{"line":227,"column":8},"end":{"line":227,"column":34}},"73":{"start":{"line":228,"column":8},"end":{"line":228,"column":20}},"74":{"start":{"line":241,"column":8},"end":{"line":244,"column":9}},"75":{"start":{"line":242,"column":12},"end":{"line":242,"column":65}},"76":{"start":{"line":242,"column":39},"end":{"line":242,"column":63}},"77":{"start":{"line":243,"column":12},"end":{"line":243,"column":24}},"78":{"start":{"line":245,"column":8},"end":{"line":245,"column":46}},"79":{"start":{"line":246,"column":8},"end":{"line":246,"column":20}},"80":{"start":{"line":258,"column":8},"end":{"line":261,"column":9}},"81":{"start":{"line":259,"column":12},"end":{"line":259,"column":80}},"82":{"start":{"line":259,"column":39},"end":{"line":259,"column":78}},"83":{"start":{"line":260,"column":12},"end":{"line":260,"column":24}},"84":{"start":{"line":263,"column":8},"end":{"line":267,"column":9}},"85":{"start":{"line":264,"column":12},"end":{"line":266,"column":14}},"86":{"start":{"line":269,"column":8},"end":{"line":269,"column":73}},"87":{"start":{"line":270,"column":8},"end":{"line":270,"column":20}},"88":{"start":{"line":280,"column":8},"end":{"line":280,"column":42}},"89":{"start":{"line":280,"column":32},"end":{"line":280,"column":42}},"90":{"start":{"line":281,"column":8},"end":{"line":281,"column":95}},"91":{"start":{"line":291,"column":8},"end":{"line":296,"column":9}},"92":{"start":{"line":292,"column":12},"end":{"line":294,"column":15}},"93":{"start":{"line":293,"column":16},"end":{"line":293,"column":38}},"94":{"start":{"line":295,"column":12},"end":{"line":295,"column":24}},"95":{"start":{"line":297,"column":8},"end":{"line":297,"column":58}},"96":{"start":{"line":297,"column":46},"end":{"line":297,"column":58}},"97":{"start":{"line":299,"column":8},"end":{"line":299,"column":29}},"98":{"start":{"line":300,"column":8},"end":{"line":300,"column":30}},"99":{"start":{"line":301,"column":8},"end":{"line":301,"column":20}},"100":{"start":{"line":308,"column":8},"end":{"line":308,"column":41}},"101":{"start":{"line":308,"column":29},"end":{"line":308,"column":41}},"102":{"start":{"line":309,"column":8},"end":{"line":309,"column":31}},"103":{"start":{"line":310,"column":8},"end":{"line":310,"column":29}},"104":{"start":{"line":311,"column":8},"end":{"line":311,"column":34}},"105":{"start":{"line":312,"column":8},"end":{"line":312,"column":20}},"106":{"start":{"line":330,"column":21},"end":{"line":330,"column":25}},"107":{"start":{"line":331,"column":8},"end":{"line":331,"column":83}},"108":{"start":{"line":331,"column":46},"end":{"line":331,"column":83}},"109":{"start":{"line":333,"column":32},"end":{"line":333,"column":74}},"110":{"start":{"line":334,"column":8},"end":{"line":334,"column":60}},"111":{"start":{"line":335,"column":29},"end":{"line":335,"column":40}},"112":{"start":{"line":336,"column":8},"end":{"line":336,"column":66}},"113":{"start":{"line":337,"column":30},"end":{"line":353,"column":9}},"114":{"start":{"line":338,"column":35},"end":{"line":338,"column":38}},"115":{"start":{"line":339,"column":12},"end":{"line":352,"column":13}},"116":{"start":{"line":340,"column":16},"end":{"line":340,"column":77}},"117":{"start":{"line":341,"column":16},"end":{"line":341,"column":68}},"118":{"start":{"line":342,"column":16},"end":{"line":342,"column":43}},"119":{"start":{"line":343,"column":16},"end":{"line":343,"column":57}},"120":{"start":{"line":343,"column":35},"end":{"line":343,"column":57}},"121":{"start":{"line":344,"column":16},"end":{"line":347,"column":17}},"122":{"start":{"line":345,"column":20},"end":{"line":345,"column":51}},"123":{"start":{"line":346,"column":20},"end":{"line":346,"column":39}},"124":{"start":{"line":348,"column":16},"end":{"line":351,"column":17}},"125":{"start":{"line":349,"column":20},"end":{"line":350,"column":30}},"126":{"start":{"line":349,"column":29},"end":{"line":349,"column":48}},"127":{"start":{"line":350,"column":25},"end":{"line":350,"column":30}},"128":{"start":{"line":355,"column":8},"end":{"line":355,"column":63}},"129":{"start":{"line":356,"column":19},"end":{"line":356,"column":69}},"130":{"start":{"line":357,"column":8},"end":{"line":357,"column":47}},"131":{"start":{"line":357,"column":17},"end":{"line":357,"column":47}},"132":{"start":{"line":358,"column":8},"end":{"line":358,"column":43}},"133":{"start":{"line":359,"column":8},"end":{"line":359,"column":57}},"134":{"start":{"line":360,"column":8},"end":{"line":360,"column":82}},"135":{"start":{"line":361,"column":8},"end":{"line":361,"column":18}},"136":{"start":{"line":368,"column":8},"end":{"line":368,"column":33}},"137":{"start":{"line":368,"column":26},"end":{"line":368,"column":33}},"138":{"start":{"line":369,"column":8},"end":{"line":369,"column":28}},"139":{"start":{"line":370,"column":8},"end":{"line":370,"column":32}},"140":{"start":{"line":371,"column":8},"end":{"line":371,"column":27}},"141":{"start":{"line":378,"column":8},"end":{"line":378,"column":34}},"142":{"start":{"line":378,"column":27},"end":{"line":378,"column":34}},"143":{"start":{"line":379,"column":8},"end":{"line":379,"column":29}},"144":{"start":{"line":380,"column":8},"end":{"line":380,"column":28}},"145":{"start":{"line":381,"column":8},"end":{"line":381,"column":44}},"146":{"start":{"line":385,"column":8},"end":{"line":385,"column":90}},"147":{"start":{"line":389,"column":8},"end":{"line":389,"column":92}},"148":{"start":{"line":396,"column":8},"end":{"line":396,"column":35}},"149":{"start":{"line":396,"column":28},"end":{"line":396,"column":35}},"150":{"start":{"line":397,"column":8},"end":{"line":397,"column":30}},"151":{"start":{"line":398,"column":8},"end":{"line":427,"column":9}},"152":{"start":{"line":400,"column":30},"end":{"line":400,"column":32}},"153":{"start":{"line":401,"column":28},"end":{"line":401,"column":29}},"154":{"start":{"line":402,"column":20},"end":{"line":402,"column":21}},"155":{"start":{"line":403,"column":12},"end":{"line":414,"column":13}},"156":{"start":{"line":404,"column":32},"end":{"line":404,"column":85}},"157":{"start":{"line":405,"column":16},"end":{"line":405,"column":48}},"158":{"start":{"line":406,"column":16},"end":{"line":413,"column":17}},"159":{"start":{"line":407,"column":20},"end":{"line":407,"column":44}},"160":{"start":{"line":409,"column":39},"end":{"line":409,"column":77}},"161":{"start":{"line":410,"column":20},"end":{"line":410,"column":65}},"162":{"start":{"line":411,"column":20},"end":{"line":411,"column":98}},"163":{"start":{"line":412,"column":20},"end":{"line":412,"column":26}},"164":{"start":{"line":416,"column":24},"end":{"line":419,"column":13}},"165":{"start":{"line":421,"column":12},"end":{"line":421,"column":69}},"166":{"start":{"line":422,"column":12},"end":{"line":422,"column":39}},"167":{"start":{"line":423,"column":12},"end":{"line":426,"column":13}},"168":{"start":{"line":424,"column":16},"end":{"line":424,"column":39}},"169":{"start":{"line":425,"column":16},"end":{"line":425,"column":23}},"170":{"start":{"line":428,"column":8},"end":{"line":428,"column":31}},"171":{"start":{"line":429,"column":8},"end":{"line":429,"column":33}},"172":{"start":{"line":435,"column":23},"end":{"line":446,"column":5}},"173":{"start":{"line":436,"column":8},"end":{"line":436,"column":40}},"174":{"start":{"line":436,"column":33},"end":{"line":436,"column":40}},"175":{"start":{"line":437,"column":8},"end":{"line":445,"column":9}},"176":{"start":{"line":438,"column":31},"end":{"line":438,"column":62}},"177":{"start":{"line":439,"column":12},"end":{"line":439,"column":53}},"178":{"start":{"line":440,"column":30},"end":{"line":440,"column":95}},"179":{"start":{"line":441,"column":12},"end":{"line":441,"column":41}},"180":{"start":{"line":444,"column":12},"end":{"line":444,"column":45}},"181":{"start":{"line":452,"column":8},"end":{"line":452,"column":33}},"182":{"start":{"line":453,"column":8},"end":{"line":453,"column":91}},"183":{"start":{"line":454,"column":8},"end":{"line":458,"column":11}},"184":{"start":{"line":455,"column":12},"end":{"line":455,"column":44}},"185":{"start":{"line":455,"column":37},"end":{"line":455,"column":44}},"186":{"start":{"line":456,"column":12},"end":{"line":456,"column":27}},"187":{"start":{"line":457,"column":12},"end":{"line":457,"column":42}},"188":{"start":{"line":459,"column":8},"end":{"line":463,"column":11}},"189":{"start":{"line":460,"column":12},"end":{"line":460,"column":44}},"190":{"start":{"line":460,"column":37},"end":{"line":460,"column":44}},"191":{"start":{"line":461,"column":12},"end":{"line":461,"column":36}},"192":{"start":{"line":462,"column":12},"end":{"line":462,"column":42}},"193":{"start":{"line":464,"column":8},"end":{"line":468,"column":11}},"194":{"start":{"line":465,"column":12},"end":{"line":465,"column":44}},"195":{"start":{"line":465,"column":37},"end":{"line":465,"column":44}},"196":{"start":{"line":466,"column":12},"end":{"line":466,"column":47}},"197":{"start":{"line":467,"column":12},"end":{"line":467,"column":33}},"198":{"start":{"line":469,"column":8},"end":{"line":472,"column":11}},"199":{"start":{"line":470,"column":12},"end":{"line":470,"column":44}},"200":{"start":{"line":470,"column":37},"end":{"line":470,"column":44}},"201":{"start":{"line":471,"column":12},"end":{"line":471,"column":53}},"202":{"start":{"line":479,"column":8},"end":{"line":479,"column":37}},"203":{"start":{"line":480,"column":8},"end":{"line":480,"column":38}},"204":{"start":{"line":481,"column":8},"end":{"line":481,"column":38}},"205":{"start":{"line":482,"column":8},"end":{"line":482,"column":40}},"206":{"start":{"line":483,"column":8},"end":{"line":483,"column":40}},"207":{"start":{"line":492,"column":8},"end":{"line":502,"column":9}},"208":{"start":{"line":493,"column":12},"end":{"line":493,"column":49}},"209":{"start":{"line":494,"column":15},"end":{"line":502,"column":9}},"210":{"start":{"line":495,"column":12},"end":{"line":495,"column":26}},"211":{"start":{"line":496,"column":15},"end":{"line":502,"column":9}},"212":{"start":{"line":497,"column":12},"end":{"line":497,"column":39}},"213":{"start":{"line":499,"column":12},"end":{"line":501,"column":14}},"214":{"start":{"line":509,"column":8},"end":{"line":509,"column":33}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":49,"column":4},"end":{"line":49,"column":5}},"loc":{"start":{"line":49,"column":18},"end":{"line":99,"column":5}},"line":49},"1":{"name":"(anonymous_1)","decl":{"start":{"line":101,"column":4},"end":{"line":101,"column":5}},"loc":{"start":{"line":101,"column":21},"end":{"line":103,"column":5}},"line":101},"2":{"name":"(anonymous_2)","decl":{"start":{"line":105,"column":4},"end":{"line":105,"column":5}},"loc":{"start":{"line":105,"column":20},"end":{"line":107,"column":5}},"line":105},"3":{"name":"(anonymous_3)","decl":{"start":{"line":109,"column":4},"end":{"line":109,"column":5}},"loc":{"start":{"line":109,"column":18},"end":{"line":111,"column":5}},"line":109},"4":{"name":"(anonymous_4)","decl":{"start":{"line":113,"column":4},"end":{"line":113,"column":5}},"loc":{"start":{"line":113,"column":21},"end":{"line":115,"column":5}},"line":113},"5":{"name":"(anonymous_5)","decl":{"start":{"line":117,"column":4},"end":{"line":117,"column":5}},"loc":{"start":{"line":117,"column":23},"end":{"line":119,"column":5}},"line":117},"6":{"name":"(anonymous_6)","decl":{"start":{"line":121,"column":4},"end":{"line":121,"column":5}},"loc":{"start":{"line":121,"column":20},"end":{"line":123,"column":5}},"line":121},"7":{"name":"(anonymous_7)","decl":{"start":{"line":125,"column":4},"end":{"line":125,"column":5}},"loc":{"start":{"line":125,"column":18},"end":{"line":127,"column":5}},"line":125},"8":{"name":"(anonymous_8)","decl":{"start":{"line":133,"column":4},"end":{"line":133,"column":5}},"loc":{"start":{"line":133,"column":15},"end":{"line":136,"column":5}},"line":133},"9":{"name":"(anonymous_9)","decl":{"start":{"line":142,"column":4},"end":{"line":142,"column":5}},"loc":{"start":{"line":142,"column":34},"end":{"line":151,"column":5}},"line":142},"10":{"name":"(anonymous_10)","decl":{"start":{"line":157,"column":4},"end":{"line":157,"column":5}},"loc":{"start":{"line":157,"column":31},"end":{"line":169,"column":5}},"line":157},"11":{"name":"(anonymous_11)","decl":{"start":{"line":162,"column":29},"end":{"line":162,"column":30}},"loc":{"start":{"line":162,"column":35},"end":{"line":164,"column":9}},"line":162},"12":{"name":"(anonymous_12)","decl":{"start":{"line":184,"column":4},"end":{"line":184,"column":5}},"loc":{"start":{"line":184,"column":34},"end":{"line":192,"column":5}},"line":184},"13":{"name":"(anonymous_13)","decl":{"start":{"line":198,"column":4},"end":{"line":198,"column":5}},"loc":{"start":{"line":198,"column":28},"end":{"line":205,"column":5}},"line":198},"14":{"name":"(anonymous_14)","decl":{"start":{"line":201,"column":35},"end":{"line":201,"column":36}},"loc":{"start":{"line":201,"column":41},"end":{"line":204,"column":9}},"line":201},"15":{"name":"(anonymous_15)","decl":{"start":{"line":210,"column":4},"end":{"line":210,"column":5}},"loc":{"start":{"line":210,"column":20},"end":{"line":215,"column":5}},"line":210},"16":{"name":"(anonymous_16)","decl":{"start":{"line":226,"column":4},"end":{"line":226,"column":5}},"loc":{"start":{"line":226,"column":26},"end":{"line":229,"column":5}},"line":226},"17":{"name":"(anonymous_17)","decl":{"start":{"line":240,"column":4},"end":{"line":240,"column":5}},"loc":{"start":{"line":240,"column":31},"end":{"line":247,"column":5}},"line":240},"18":{"name":"(anonymous_18)","decl":{"start":{"line":242,"column":33},"end":{"line":242,"column":34}},"loc":{"start":{"line":242,"column":39},"end":{"line":242,"column":63}},"line":242},"19":{"name":"(anonymous_19)","decl":{"start":{"line":257,"column":4},"end":{"line":257,"column":5}},"loc":{"start":{"line":257,"column":51},"end":{"line":271,"column":5}},"line":257},"20":{"name":"(anonymous_20)","decl":{"start":{"line":259,"column":33},"end":{"line":259,"column":34}},"loc":{"start":{"line":259,"column":39},"end":{"line":259,"column":78}},"line":259},"21":{"name":"(anonymous_21)","decl":{"start":{"line":279,"column":4},"end":{"line":279,"column":5}},"loc":{"start":{"line":279,"column":14},"end":{"line":282,"column":5}},"line":279},"22":{"name":"(anonymous_22)","decl":{"start":{"line":290,"column":4},"end":{"line":290,"column":5}},"loc":{"start":{"line":290,"column":24},"end":{"line":302,"column":5}},"line":290},"23":{"name":"(anonymous_23)","decl":{"start":{"line":292,"column":39},"end":{"line":292,"column":40}},"loc":{"start":{"line":292,"column":45},"end":{"line":294,"column":13}},"line":292},"24":{"name":"(anonymous_24)","decl":{"start":{"line":307,"column":4},"end":{"line":307,"column":5}},"loc":{"start":{"line":307,"column":14},"end":{"line":313,"column":5}},"line":307},"25":{"name":"(anonymous_25)","decl":{"start":{"line":329,"column":4},"end":{"line":329,"column":5}},"loc":{"start":{"line":329,"column":32},"end":{"line":362,"column":5}},"line":329},"26":{"name":"(anonymous_26)","decl":{"start":{"line":337,"column":30},"end":{"line":337,"column":31}},"loc":{"start":{"line":337,"column":96},"end":{"line":353,"column":9}},"line":337},"27":{"name":"(anonymous_27)","decl":{"start":{"line":367,"column":4},"end":{"line":367,"column":5}},"loc":{"start":{"line":367,"column":12},"end":{"line":372,"column":5}},"line":367},"28":{"name":"(anonymous_28)","decl":{"start":{"line":377,"column":4},"end":{"line":377,"column":5}},"loc":{"start":{"line":377,"column":13},"end":{"line":382,"column":5}},"line":377},"29":{"name":"(anonymous_29)","decl":{"start":{"line":384,"column":4},"end":{"line":384,"column":5}},"loc":{"start":{"line":384,"column":10},"end":{"line":386,"column":5}},"line":384},"30":{"name":"(anonymous_30)","decl":{"start":{"line":388,"column":4},"end":{"line":388,"column":5}},"loc":{"start":{"line":388,"column":12},"end":{"line":390,"column":5}},"line":388},"31":{"name":"(anonymous_31)","decl":{"start":{"line":395,"column":4},"end":{"line":395,"column":5}},"loc":{"start":{"line":395,"column":41},"end":{"line":430,"column":5}},"line":395},"32":{"name":"(anonymous_32)","decl":{"start":{"line":435,"column":23},"end":{"line":435,"column":24}},"loc":{"start":{"line":435,"column":77},"end":{"line":446,"column":5}},"line":435},"33":{"name":"(anonymous_33)","decl":{"start":{"line":451,"column":4},"end":{"line":451,"column":5}},"loc":{"start":{"line":451,"column":22},"end":{"line":473,"column":5}},"line":451},"34":{"name":"(anonymous_34)","decl":{"start":{"line":454,"column":70},"end":{"line":454,"column":71}},"loc":{"start":{"line":454,"column":79},"end":{"line":458,"column":9}},"line":454},"35":{"name":"(anonymous_35)","decl":{"start":{"line":459,"column":70},"end":{"line":459,"column":71}},"loc":{"start":{"line":459,"column":79},"end":{"line":463,"column":9}},"line":459},"36":{"name":"(anonymous_36)","decl":{"start":{"line":464,"column":74},"end":{"line":464,"column":75}},"loc":{"start":{"line":464,"column":83},"end":{"line":468,"column":9}},"line":464},"37":{"name":"(anonymous_37)","decl":{"start":{"line":469,"column":74},"end":{"line":469,"column":75}},"loc":{"start":{"line":469,"column":83},"end":{"line":472,"column":9}},"line":469},"38":{"name":"(anonymous_38)","decl":{"start":{"line":478,"column":4},"end":{"line":478,"column":5}},"loc":{"start":{"line":478,"column":24},"end":{"line":484,"column":5}},"line":478},"39":{"name":"(anonymous_39)","decl":{"start":{"line":491,"column":4},"end":{"line":491,"column":5}},"loc":{"start":{"line":491,"column":42},"end":{"line":503,"column":5}},"line":491},"40":{"name":"(anonymous_40)","decl":{"start":{"line":508,"column":4},"end":{"line":508,"column":5}},"loc":{"start":{"line":508,"column":23},"end":{"line":510,"column":5}},"line":508}},"branchMap":{"0":{"loc":{"start":{"line":160,"column":29},"end":{"line":160,"column":62}},"type":"binary-expr","locations":[{"start":{"line":160,"column":29},"end":{"line":160,"column":47}},{"start":{"line":160,"column":51},"end":{"line":160,"column":62}}],"line":160},"1":{"loc":{"start":{"line":161,"column":29},"end":{"line":161,"column":60}},"type":"binary-expr","locations":[{"start":{"line":161,"column":29},"end":{"line":161,"column":55}},{"start":{"line":161,"column":59},"end":{"line":161,"column":60}}],"line":161},"2":{"loc":{"start":{"line":163,"column":12},"end":{"line":163,"column":37}},"type":"if","locations":[{"start":{"line":163,"column":12},"end":{"line":163,"column":37}},{"start":{"line":163,"column":12},"end":{"line":163,"column":37}}],"line":163},"3":{"loc":{"start":{"line":185,"column":8},"end":{"line":189,"column":9}},"type":"if","locations":[{"start":{"line":185,"column":8},"end":{"line":189,"column":9}},{"start":{"line":185,"column":8},"end":{"line":189,"column":9}}],"line":185},"4":{"loc":{"start":{"line":190,"column":8},"end":{"line":190,"column":53}},"type":"if","locations":[{"start":{"line":190,"column":8},"end":{"line":190,"column":53}},{"start":{"line":190,"column":8},"end":{"line":190,"column":53}}],"line":190},"5":{"loc":{"start":{"line":199,"column":8},"end":{"line":199,"column":64}},"type":"if","locations":[{"start":{"line":199,"column":8},"end":{"line":199,"column":64}},{"start":{"line":199,"column":8},"end":{"line":199,"column":64}}],"line":199},"6":{"loc":{"start":{"line":211,"column":8},"end":{"line":214,"column":9}},"type":"if","locations":[{"start":{"line":211,"column":8},"end":{"line":214,"column":9}},{"start":{"line":211,"column":8},"end":{"line":214,"column":9}}],"line":211},"7":{"loc":{"start":{"line":240,"column":15},"end":{"line":240,"column":29}},"type":"default-arg","locations":[{"start":{"line":240,"column":25},"end":{"line":240,"column":29}}],"line":240},"8":{"loc":{"start":{"line":241,"column":8},"end":{"line":244,"column":9}},"type":"if","locations":[{"start":{"line":241,"column":8},"end":{"line":244,"column":9}},{"start":{"line":241,"column":8},"end":{"line":244,"column":9}}],"line":241},"9":{"loc":{"start":{"line":257,"column":17},"end":{"line":257,"column":31}},"type":"default-arg","locations":[{"start":{"line":257,"column":26},"end":{"line":257,"column":31}}],"line":257},"10":{"loc":{"start":{"line":257,"column":33},"end":{"line":257,"column":49}},"type":"default-arg","locations":[{"start":{"line":257,"column":48},"end":{"line":257,"column":49}}],"line":257},"11":{"loc":{"start":{"line":258,"column":8},"end":{"line":261,"column":9}},"type":"if","locations":[{"start":{"line":258,"column":8},"end":{"line":261,"column":9}},{"start":{"line":258,"column":8},"end":{"line":261,"column":9}}],"line":258},"12":{"loc":{"start":{"line":263,"column":8},"end":{"line":267,"column":9}},"type":"if","locations":[{"start":{"line":263,"column":8},"end":{"line":267,"column":9}},{"start":{"line":263,"column":8},"end":{"line":267,"column":9}}],"line":263},"13":{"loc":{"start":{"line":280,"column":8},"end":{"line":280,"column":42}},"type":"if","locations":[{"start":{"line":280,"column":8},"end":{"line":280,"column":42}},{"start":{"line":280,"column":8},"end":{"line":280,"column":42}}],"line":280},"14":{"loc":{"start":{"line":291,"column":8},"end":{"line":296,"column":9}},"type":"if","locations":[{"start":{"line":291,"column":8},"end":{"line":296,"column":9}},{"start":{"line":291,"column":8},"end":{"line":296,"column":9}}],"line":291},"15":{"loc":{"start":{"line":297,"column":8},"end":{"line":297,"column":58}},"type":"if","locations":[{"start":{"line":297,"column":8},"end":{"line":297,"column":58}},{"start":{"line":297,"column":8},"end":{"line":297,"column":58}}],"line":297},"16":{"loc":{"start":{"line":297,"column":12},"end":{"line":297,"column":44}},"type":"binary-expr","locations":[{"start":{"line":297,"column":12},"end":{"line":297,"column":25}},{"start":{"line":297,"column":29},"end":{"line":297,"column":44}}],"line":297},"17":{"loc":{"start":{"line":308,"column":8},"end":{"line":308,"column":41}},"type":"if","locations":[{"start":{"line":308,"column":8},"end":{"line":308,"column":41}},{"start":{"line":308,"column":8},"end":{"line":308,"column":41}}],"line":308},"18":{"loc":{"start":{"line":331,"column":8},"end":{"line":331,"column":83}},"type":"if","locations":[{"start":{"line":331,"column":8},"end":{"line":331,"column":83}},{"start":{"line":331,"column":8},"end":{"line":331,"column":83}}],"line":331},"19":{"loc":{"start":{"line":331,"column":12},"end":{"line":331,"column":44}},"type":"binary-expr","locations":[{"start":{"line":331,"column":12},"end":{"line":331,"column":25}},{"start":{"line":331,"column":29},"end":{"line":331,"column":44}}],"line":331},"20":{"loc":{"start":{"line":339,"column":12},"end":{"line":352,"column":13}},"type":"if","locations":[{"start":{"line":339,"column":12},"end":{"line":352,"column":13}},{"start":{"line":339,"column":12},"end":{"line":352,"column":13}}],"line":339},"21":{"loc":{"start":{"line":343,"column":16},"end":{"line":343,"column":57}},"type":"if","locations":[{"start":{"line":343,"column":16},"end":{"line":343,"column":57}},{"start":{"line":343,"column":16},"end":{"line":343,"column":57}}],"line":343},"22":{"loc":{"start":{"line":344,"column":16},"end":{"line":347,"column":17}},"type":"if","locations":[{"start":{"line":344,"column":16},"end":{"line":347,"column":17}},{"start":{"line":344,"column":16},"end":{"line":347,"column":17}}],"line":344},"23":{"loc":{"start":{"line":344,"column":20},"end":{"line":344,"column":75}},"type":"binary-expr","locations":[{"start":{"line":344,"column":20},"end":{"line":344,"column":42}},{"start":{"line":344,"column":46},"end":{"line":344,"column":75}}],"line":344},"24":{"loc":{"start":{"line":348,"column":16},"end":{"line":351,"column":17}},"type":"if","locations":[{"start":{"line":348,"column":16},"end":{"line":351,"column":17}},{"start":{"line":348,"column":16},"end":{"line":351,"column":17}}],"line":348},"25":{"loc":{"start":{"line":349,"column":20},"end":{"line":350,"column":30}},"type":"if","locations":[{"start":{"line":349,"column":20},"end":{"line":350,"column":30}},{"start":{"line":349,"column":20},"end":{"line":350,"column":30}}],"line":349},"26":{"loc":{"start":{"line":357,"column":8},"end":{"line":357,"column":47}},"type":"if","locations":[{"start":{"line":357,"column":8},"end":{"line":357,"column":47}},{"start":{"line":357,"column":8},"end":{"line":357,"column":47}}],"line":357},"27":{"loc":{"start":{"line":368,"column":8},"end":{"line":368,"column":33}},"type":"if","locations":[{"start":{"line":368,"column":8},"end":{"line":368,"column":33}},{"start":{"line":368,"column":8},"end":{"line":368,"column":33}}],"line":368},"28":{"loc":{"start":{"line":378,"column":8},"end":{"line":378,"column":34}},"type":"if","locations":[{"start":{"line":378,"column":8},"end":{"line":378,"column":34}},{"start":{"line":378,"column":8},"end":{"line":378,"column":34}}],"line":378},"29":{"loc":{"start":{"line":396,"column":8},"end":{"line":396,"column":35}},"type":"if","locations":[{"start":{"line":396,"column":8},"end":{"line":396,"column":35}},{"start":{"line":396,"column":8},"end":{"line":396,"column":35}}],"line":396},"30":{"loc":{"start":{"line":406,"column":16},"end":{"line":413,"column":17}},"type":"if","locations":[{"start":{"line":406,"column":16},"end":{"line":413,"column":17}},{"start":{"line":406,"column":16},"end":{"line":413,"column":17}}],"line":406},"31":{"loc":{"start":{"line":423,"column":12},"end":{"line":426,"column":13}},"type":"if","locations":[{"start":{"line":423,"column":12},"end":{"line":426,"column":13}},{"start":{"line":423,"column":12},"end":{"line":426,"column":13}}],"line":423},"32":{"loc":{"start":{"line":436,"column":8},"end":{"line":436,"column":40}},"type":"if","locations":[{"start":{"line":436,"column":8},"end":{"line":436,"column":40}},{"start":{"line":436,"column":8},"end":{"line":436,"column":40}}],"line":436},"33":{"loc":{"start":{"line":437,"column":8},"end":{"line":445,"column":9}},"type":"if","locations":[{"start":{"line":437,"column":8},"end":{"line":445,"column":9}},{"start":{"line":437,"column":8},"end":{"line":445,"column":9}}],"line":437},"34":{"loc":{"start":{"line":440,"column":30},"end":{"line":440,"column":95}},"type":"cond-expr","locations":[{"start":{"line":440,"column":47},"end":{"line":440,"column":82}},{"start":{"line":440,"column":85},"end":{"line":440,"column":95}}],"line":440},"35":{"loc":{"start":{"line":455,"column":12},"end":{"line":455,"column":44}},"type":"if","locations":[{"start":{"line":455,"column":12},"end":{"line":455,"column":44}},{"start":{"line":455,"column":12},"end":{"line":455,"column":44}}],"line":455},"36":{"loc":{"start":{"line":460,"column":12},"end":{"line":460,"column":44}},"type":"if","locations":[{"start":{"line":460,"column":12},"end":{"line":460,"column":44}},{"start":{"line":460,"column":12},"end":{"line":460,"column":44}}],"line":460},"37":{"loc":{"start":{"line":465,"column":12},"end":{"line":465,"column":44}},"type":"if","locations":[{"start":{"line":465,"column":12},"end":{"line":465,"column":44}},{"start":{"line":465,"column":12},"end":{"line":465,"column":44}}],"line":465},"38":{"loc":{"start":{"line":470,"column":12},"end":{"line":470,"column":44}},"type":"if","locations":[{"start":{"line":470,"column":12},"end":{"line":470,"column":44}},{"start":{"line":470,"column":12},"end":{"line":470,"column":44}}],"line":470},"39":{"loc":{"start":{"line":492,"column":8},"end":{"line":502,"column":9}},"type":"if","locations":[{"start":{"line":492,"column":8},"end":{"line":502,"column":9}},{"start":{"line":492,"column":8},"end":{"line":502,"column":9}}],"line":492},"40":{"loc":{"start":{"line":494,"column":15},"end":{"line":502,"column":9}},"type":"if","locations":[{"start":{"line":494,"column":15},"end":{"line":502,"column":9}},{"start":{"line":494,"column":15},"end":{"line":502,"column":9}}],"line":494},"41":{"loc":{"start":{"line":496,"column":15},"end":{"line":502,"column":9}},"type":"if","locations":[{"start":{"line":496,"column":15},"end":{"line":502,"column":9}},{"start":{"line":496,"column":15},"end":{"line":502,"column":9}}],"line":496},"42":{"loc":{"start":{"line":496,"column":19},"end":{"line":496,"column":72}},"type":"binary-expr","locations":[{"start":{"line":496,"column":19},"end":{"line":496,"column":47}},{"start":{"line":496,"column":51},"end":{"line":496,"column":72}}],"line":496}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":1,"48":1,"49":1,"50":1,"51":0,"52":0,"53":1,"54":1,"55":1,"56":1,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":0,"129":0,"130":0,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0,"145":0,"146":0,"147":0,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":0,"157":0,"158":0,"159":0,"160":0,"161":0,"162":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":0,"169":0,"170":0,"171":0,"172":1,"173":0,"174":0,"175":0,"176":0,"177":0,"178":0,"179":0,"180":0,"181":1,"182":1,"183":1,"184":0,"185":0,"186":0,"187":0,"188":1,"189":0,"190":0,"191":0,"192":0,"193":1,"194":0,"195":0,"196":0,"197":0,"198":1,"199":0,"200":0,"201":0,"202":1,"203":1,"204":1,"205":1,"206":1,"207":0,"208":0,"209":0,"210":0,"211":0,"212":0,"213":0,"214":0},"f":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":1,"34":0,"35":0,"36":0,"37":0,"38":1,"39":0,"40":0},"b":{"0":[1,0],"1":[1,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0],"8":[0,0],"9":[0],"10":[0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"490e3e7a88bd1d9883262b2788e813cceffebc8f"} ,"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/TLSServer.js": {"path":"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/TLSServer.js","statementMap":{"0":{"start":{"line":18,"column":8},"end":{"line":18,"column":16}},"1":{"start":{"line":19,"column":8},"end":{"line":19,"column":92}},"2":{"start":{"line":19,"column":38},"end":{"line":19,"column":92}},"3":{"start":{"line":20,"column":8},"end":{"line":20,"column":34}},"4":{"start":{"line":28,"column":8},"end":{"line":28,"column":39}},"5":{"start":{"line":29,"column":8},"end":{"line":29,"column":86}},"6":{"start":{"line":47,"column":27},"end":{"line":47,"column":41}},"7":{"start":{"line":49,"column":8},"end":{"line":49,"column":42}},"8":{"start":{"line":50,"column":8},"end":{"line":50,"column":50}},"9":{"start":{"line":57,"column":8},"end":{"line":68,"column":10}},"10":{"start":{"line":60,"column":16},"end":{"line":60,"column":48}},"11":{"start":{"line":60,"column":41},"end":{"line":60,"column":48}},"12":{"start":{"line":61,"column":39},"end":{"line":61,"column":66}},"13":{"start":{"line":62,"column":16},"end":{"line":62,"column":51}},"14":{"start":{"line":63,"column":34},"end":{"line":63,"column":63}},"15":{"start":{"line":64,"column":16},"end":{"line":64,"column":47}},"16":{"start":{"line":65,"column":16},"end":{"line":65,"column":56}},"17":{"start":{"line":66,"column":16},"end":{"line":66,"column":57}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":17,"column":4},"end":{"line":17,"column":5}},"loc":{"start":{"line":17,"column":42},"end":{"line":21,"column":5}},"line":17},"1":{"name":"(anonymous_1)","decl":{"start":{"line":26,"column":4},"end":{"line":26,"column":5}},"loc":{"start":{"line":26,"column":30},"end":{"line":30,"column":5}},"line":26},"2":{"name":"(anonymous_2)","decl":{"start":{"line":46,"column":4},"end":{"line":46,"column":5}},"loc":{"start":{"line":46,"column":30},"end":{"line":51,"column":5}},"line":46},"3":{"name":"(anonymous_3)","decl":{"start":{"line":56,"column":4},"end":{"line":56,"column":5}},"loc":{"start":{"line":56,"column":25},"end":{"line":69,"column":5}},"line":56},"4":{"name":"(anonymous_4)","decl":{"start":{"line":59,"column":12},"end":{"line":59,"column":13}},"loc":{"start":{"line":59,"column":21},"end":{"line":67,"column":13}},"line":59}},"branchMap":{"0":{"loc":{"start":{"line":19,"column":8},"end":{"line":19,"column":92}},"type":"if","locations":[{"start":{"line":19,"column":8},"end":{"line":19,"column":92}},{"start":{"line":19,"column":8},"end":{"line":19,"column":92}}],"line":19},"1":{"loc":{"start":{"line":60,"column":16},"end":{"line":60,"column":48}},"type":"if","locations":[{"start":{"line":60,"column":16},"end":{"line":60,"column":48}},{"start":{"line":60,"column":16},"end":{"line":60,"column":48}}],"line":60}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"51eb42643262ddeb31bbd2ad312642ccff802430"} -,"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/TLSSocket.js": {"path":"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/TLSSocket.js","statementMap":{"0":{"start":{"line":4,"column":16},"end":{"line":4,"column":40}},"1":{"start":{"line":19,"column":8},"end":{"line":19,"column":16}},"2":{"start":{"line":21,"column":8},"end":{"line":21,"column":39}},"3":{"start":{"line":22,"column":8},"end":{"line":22,"column":96}},"4":{"start":{"line":22,"column":30},"end":{"line":22,"column":96}},"5":{"start":{"line":24,"column":8},"end":{"line":24,"column":30}},"6":{"start":{"line":26,"column":8},"end":{"line":26,"column":38}},"7":{"start":{"line":27,"column":8},"end":{"line":27,"column":25}},"8":{"start":{"line":28,"column":8},"end":{"line":29,"column":32}},"9":{"start":{"line":28,"column":49},"end":{"line":28,"column":98}},"10":{"start":{"line":28,"column":78},"end":{"line":28,"column":96}},"11":{"start":{"line":29,"column":13},"end":{"line":29,"column":32}},"12":{"start":{"line":37,"column":8},"end":{"line":37,"column":46}},"13":{"start":{"line":38,"column":8},"end":{"line":38,"column":71}},"14":{"start":{"line":38,"column":36},"end":{"line":38,"column":69}},"15":{"start":{"line":39,"column":8},"end":{"line":50,"column":11}},"16":{"start":{"line":57,"column":8},"end":{"line":57,"column":50}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":18,"column":4},"end":{"line":18,"column":5}},"loc":{"start":{"line":18,"column":38},"end":{"line":30,"column":5}},"line":18},"1":{"name":"(anonymous_1)","decl":{"start":{"line":28,"column":72},"end":{"line":28,"column":73}},"loc":{"start":{"line":28,"column":78},"end":{"line":28,"column":96}},"line":28},"2":{"name":"(anonymous_2)","decl":{"start":{"line":35,"column":4},"end":{"line":35,"column":5}},"loc":{"start":{"line":35,"column":18},"end":{"line":51,"column":5}},"line":35},"3":{"name":"(anonymous_3)","decl":{"start":{"line":38,"column":25},"end":{"line":38,"column":26}},"loc":{"start":{"line":38,"column":36},"end":{"line":38,"column":69}},"line":38},"4":{"name":"(anonymous_4)","decl":{"start":{"line":56,"column":4},"end":{"line":56,"column":5}},"loc":{"start":{"line":56,"column":16},"end":{"line":58,"column":5}},"line":56}},"branchMap":{"0":{"loc":{"start":{"line":18,"column":24},"end":{"line":18,"column":36}},"type":"default-arg","locations":[{"start":{"line":18,"column":34},"end":{"line":18,"column":36}}],"line":18},"1":{"loc":{"start":{"line":22,"column":8},"end":{"line":22,"column":96}},"type":"if","locations":[{"start":{"line":22,"column":8},"end":{"line":22,"column":96}},{"start":{"line":22,"column":8},"end":{"line":22,"column":96}}],"line":22},"2":{"loc":{"start":{"line":28,"column":8},"end":{"line":29,"column":32}},"type":"if","locations":[{"start":{"line":28,"column":8},"end":{"line":29,"column":32}},{"start":{"line":28,"column":8},"end":{"line":29,"column":32}}],"line":28},"3":{"loc":{"start":{"line":28,"column":12},"end":{"line":28,"column":47}},"type":"binary-expr","locations":[{"start":{"line":28,"column":12},"end":{"line":28,"column":26}},{"start":{"line":28,"column":30},"end":{"line":28,"column":47}}],"line":28}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0],"1":[0,0],"2":[0,0],"3":[0,0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"4cbdd655fe691b59f74561ef62d97f83dd37fdf3"} +,"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/TLSSocket.js": {"path":"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/TLSSocket.js","statementMap":{"0":{"start":{"line":4,"column":16},"end":{"line":4,"column":40}},"1":{"start":{"line":25,"column":8},"end":{"line":25,"column":16}},"2":{"start":{"line":27,"column":8},"end":{"line":27,"column":39}},"3":{"start":{"line":28,"column":8},"end":{"line":28,"column":60}},"4":{"start":{"line":29,"column":8},"end":{"line":29,"column":61}},"5":{"start":{"line":30,"column":8},"end":{"line":30,"column":62}},"6":{"start":{"line":33,"column":8},"end":{"line":33,"column":30}},"7":{"start":{"line":35,"column":8},"end":{"line":35,"column":38}},"8":{"start":{"line":36,"column":8},"end":{"line":36,"column":25}},"9":{"start":{"line":37,"column":8},"end":{"line":38,"column":32}},"10":{"start":{"line":37,"column":49},"end":{"line":37,"column":98}},"11":{"start":{"line":37,"column":78},"end":{"line":37,"column":96}},"12":{"start":{"line":38,"column":13},"end":{"line":38,"column":32}},"13":{"start":{"line":46,"column":8},"end":{"line":46,"column":46}},"14":{"start":{"line":47,"column":8},"end":{"line":47,"column":71}},"15":{"start":{"line":47,"column":36},"end":{"line":47,"column":69}},"16":{"start":{"line":48,"column":8},"end":{"line":59,"column":11}},"17":{"start":{"line":66,"column":8},"end":{"line":66,"column":50}},"18":{"start":{"line":70,"column":8},"end":{"line":70,"column":48}},"19":{"start":{"line":74,"column":8},"end":{"line":74,"column":52}},"20":{"start":{"line":84,"column":23},"end":{"line":84,"column":35}},"21":{"start":{"line":85,"column":8},"end":{"line":91,"column":9}},"22":{"start":{"line":86,"column":12},"end":{"line":88,"column":13}},"23":{"start":{"line":87,"column":16},"end":{"line":87,"column":42}},"24":{"start":{"line":89,"column":12},"end":{"line":89,"column":43}},"25":{"start":{"line":90,"column":12},"end":{"line":90,"column":64}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":24,"column":4},"end":{"line":24,"column":5}},"loc":{"start":{"line":24,"column":38},"end":{"line":39,"column":5}},"line":24},"1":{"name":"(anonymous_1)","decl":{"start":{"line":37,"column":72},"end":{"line":37,"column":73}},"loc":{"start":{"line":37,"column":78},"end":{"line":37,"column":96}},"line":37},"2":{"name":"(anonymous_2)","decl":{"start":{"line":44,"column":4},"end":{"line":44,"column":5}},"loc":{"start":{"line":44,"column":18},"end":{"line":60,"column":5}},"line":44},"3":{"name":"(anonymous_3)","decl":{"start":{"line":47,"column":25},"end":{"line":47,"column":26}},"loc":{"start":{"line":47,"column":36},"end":{"line":47,"column":69}},"line":47},"4":{"name":"(anonymous_4)","decl":{"start":{"line":65,"column":4},"end":{"line":65,"column":5}},"loc":{"start":{"line":65,"column":16},"end":{"line":67,"column":5}},"line":65},"5":{"name":"(anonymous_5)","decl":{"start":{"line":69,"column":4},"end":{"line":69,"column":5}},"loc":{"start":{"line":69,"column":21},"end":{"line":71,"column":5}},"line":69},"6":{"name":"(anonymous_6)","decl":{"start":{"line":73,"column":4},"end":{"line":73,"column":5}},"loc":{"start":{"line":73,"column":25},"end":{"line":75,"column":5}},"line":73},"7":{"name":"(anonymous_7)","decl":{"start":{"line":83,"column":4},"end":{"line":83,"column":5}},"loc":{"start":{"line":83,"column":46},"end":{"line":92,"column":5}},"line":83}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":24},"end":{"line":24,"column":36}},"type":"default-arg","locations":[{"start":{"line":24,"column":34},"end":{"line":24,"column":36}}],"line":24},"1":{"loc":{"start":{"line":37,"column":8},"end":{"line":38,"column":32}},"type":"if","locations":[{"start":{"line":37,"column":8},"end":{"line":38,"column":32}},{"start":{"line":37,"column":8},"end":{"line":38,"column":32}}],"line":37},"2":{"loc":{"start":{"line":37,"column":12},"end":{"line":37,"column":47}},"type":"binary-expr","locations":[{"start":{"line":37,"column":12},"end":{"line":37,"column":26}},{"start":{"line":37,"column":30},"end":{"line":37,"column":47}}],"line":37},"3":{"loc":{"start":{"line":85,"column":8},"end":{"line":91,"column":9}},"type":"if","locations":[{"start":{"line":85,"column":8},"end":{"line":91,"column":9}},{"start":{"line":85,"column":8},"end":{"line":91,"column":9}}],"line":85},"4":{"loc":{"start":{"line":85,"column":12},"end":{"line":85,"column":48}},"type":"binary-expr","locations":[{"start":{"line":85,"column":12},"end":{"line":85,"column":18}},{"start":{"line":85,"column":22},"end":{"line":85,"column":48}}],"line":85},"5":{"loc":{"start":{"line":86,"column":12},"end":{"line":88,"column":13}},"type":"if","locations":[{"start":{"line":86,"column":12},"end":{"line":88,"column":13}},{"start":{"line":86,"column":12},"end":{"line":88,"column":13}}],"line":86}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0},"b":{"0":[0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"03029c2b5d213b3d59c3d510a349220cd2305924"} ,"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/index.js": {"path":"/home/runner/work/react-native-tcp-socket/react-native-tcp-socket/src/index.js","statementMap":{"0":{"start":{"line":13,"column":4},"end":{"line":13,"column":42}},"1":{"start":{"line":22,"column":19},"end":{"line":22,"column":52}},"2":{"start":{"line":23,"column":4},"end":{"line":23,"column":37}},"3":{"start":{"line":24,"column":4},"end":{"line":24,"column":18}},"4":{"start":{"line":35,"column":19},"end":{"line":35,"column":31}},"5":{"start":{"line":36,"column":22},"end":{"line":36,"column":52}},"6":{"start":{"line":37,"column":4},"end":{"line":37,"column":66}},"7":{"start":{"line":37,"column":33},"end":{"line":37,"column":64}},"8":{"start":{"line":38,"column":4},"end":{"line":38,"column":60}},"9":{"start":{"line":38,"column":18},"end":{"line":38,"column":60}},"10":{"start":{"line":39,"column":4},"end":{"line":39,"column":28}},"11":{"start":{"line":40,"column":4},"end":{"line":40,"column":21}},"12":{"start":{"line":49,"column":22},"end":{"line":49,"column":34}},"13":{"start":{"line":50,"column":4},"end":{"line":50,"column":48}},"14":{"start":{"line":54,"column":14},"end":{"line":54,"column":68}},"15":{"start":{"line":55,"column":14},"end":{"line":55,"column":40}},"16":{"start":{"line":56,"column":16},"end":{"line":56,"column":40}},"17":{"start":{"line":59,"column":14},"end":{"line":59,"column":36}},"18":{"start":{"line":60,"column":16},"end":{"line":71,"column":1}},"19":{"start":{"line":79,"column":4},"end":{"line":79,"column":31}},"20":{"start":{"line":88,"column":4},"end":{"line":88,"column":31}},"21":{"start":{"line":97,"column":4},"end":{"line":98,"column":37}},"22":{"start":{"line":97,"column":23},"end":{"line":97,"column":32}},"23":{"start":{"line":98,"column":9},"end":{"line":98,"column":37}},"24":{"start":{"line":98,"column":28},"end":{"line":98,"column":37}},"25":{"start":{"line":99,"column":4},"end":{"line":99,"column":13}},"26":{"start":{"line":118,"column":0},"end":{"line":131,"column":2}}},"fnMap":{"0":{"name":"createServer","decl":{"start":{"line":12,"column":9},"end":{"line":12,"column":21}},"loc":{"start":{"line":12,"column":42},"end":{"line":14,"column":1}},"line":12},"1":{"name":"createTLSServer","decl":{"start":{"line":21,"column":9},"end":{"line":21,"column":24}},"loc":{"start":{"line":21,"column":54},"end":{"line":25,"column":1}},"line":21},"2":{"name":"connectTLS","decl":{"start":{"line":34,"column":9},"end":{"line":34,"column":19}},"loc":{"start":{"line":34,"column":39},"end":{"line":41,"column":1}},"line":34},"3":{"name":"(anonymous_3)","decl":{"start":{"line":37,"column":27},"end":{"line":37,"column":28}},"loc":{"start":{"line":37,"column":33},"end":{"line":37,"column":64}},"line":37},"4":{"name":"createConnection","decl":{"start":{"line":48,"column":9},"end":{"line":48,"column":25}},"loc":{"start":{"line":48,"column":45},"end":{"line":51,"column":1}},"line":48},"5":{"name":"isIPv4","decl":{"start":{"line":78,"column":9},"end":{"line":78,"column":15}},"loc":{"start":{"line":78,"column":23},"end":{"line":80,"column":1}},"line":78},"6":{"name":"isIPv6","decl":{"start":{"line":87,"column":9},"end":{"line":87,"column":15}},"loc":{"start":{"line":87,"column":23},"end":{"line":89,"column":1}},"line":87},"7":{"name":"isIP","decl":{"start":{"line":96,"column":9},"end":{"line":96,"column":13}},"loc":{"start":{"line":96,"column":21},"end":{"line":100,"column":1}},"line":96}},"branchMap":{"0":{"loc":{"start":{"line":38,"column":4},"end":{"line":38,"column":60}},"type":"if","locations":[{"start":{"line":38,"column":4},"end":{"line":38,"column":60}},{"start":{"line":38,"column":4},"end":{"line":38,"column":60}}],"line":38},"1":{"loc":{"start":{"line":97,"column":4},"end":{"line":98,"column":37}},"type":"if","locations":[{"start":{"line":97,"column":4},"end":{"line":98,"column":37}},{"start":{"line":97,"column":4},"end":{"line":98,"column":37}}],"line":97},"2":{"loc":{"start":{"line":98,"column":9},"end":{"line":98,"column":37}},"type":"if","locations":[{"start":{"line":98,"column":9},"end":{"line":98,"column":37}},{"start":{"line":98,"column":9},"end":{"line":98,"column":37}}],"line":98}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":5,"20":4,"21":3,"22":1,"23":2,"24":1,"25":1,"26":1},"f":{"0":1,"1":0,"2":0,"3":0,"4":1,"5":5,"6":4,"7":3},"b":{"0":[0,0],"1":[1,2],"2":[1,1]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"aebe15571445a458896b50ac9c36878008a352fc"} } diff --git a/lib/types/TLSSocket.d.ts b/lib/types/TLSSocket.d.ts index 219d02b..bc1f2b7 100644 --- a/lib/types/TLSSocket.d.ts +++ b/lib/types/TLSSocket.d.ts @@ -1,10 +1,23 @@ /** * @typedef {object} TLSSocketOptions * @property {any} [ca] + * @property {any} [key] + * @property {any} [cert] + * @property {string} [androidKeyStore] + * @property {string} [certAlias] + * @property {string} [keyAlias] + * @property {string[]} [resolvedKeys] * * @extends {Socket} */ export default class TLSSocket extends Socket { + /** + * @private + * Resolves the asset source if necessary and registers the resolved key. + * @param {TLSSocketOptions} options The options object containing the source to be resolved. + * @param {'ca' | 'key' | 'cert'} key The key name being resolved. + */ + private static resolveAssetIfNeeded; /** * @param {Socket} socket Any instance of `Socket`. * @param {TLSSocketOptions} [options] Options for the TLS socket. @@ -22,8 +35,16 @@ export default class TLSSocket extends Socket { * @private */ private _startTLS; + getCertificate(): any; + getPeerCertificate(): any; } export type TLSSocketOptions = { ca?: any; + key?: any; + cert?: any; + androidKeyStore?: string | undefined; + certAlias?: string | undefined; + keyAlias?: string | undefined; + resolvedKeys?: string[] | undefined; }; import Socket from "./Socket"; diff --git a/package.json b/package.json index fb9e91c..63d4df5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-native-tcp-socket", "title": "React Native Tcp Socket", - "version": "6.1.0", + "version": "6.2.0", "description": "React Native TCP socket API for Android & iOS with SSL/TLS support", "main": "src/index.js", "types": "lib/types/index.d.ts", diff --git a/src/TLSSocket.js b/src/TLSSocket.js index b038c77..d538638 100644 --- a/src/TLSSocket.js +++ b/src/TLSSocket.js @@ -7,6 +7,12 @@ import Socket from './Socket'; /** * @typedef {object} TLSSocketOptions * @property {any} [ca] + * @property {any} [key] + * @property {any} [cert] + * @property {string} [androidKeyStore] + * @property {string} [certAlias] + * @property {string} [keyAlias] + * @property {string[]} [resolvedKeys] * * @extends {Socket} */ @@ -19,7 +25,10 @@ export default class TLSSocket extends Socket { super(); /** @private */ this._options = { ...options }; - if (this._options.ca) this._options.ca = Image.resolveAssetSource(this._options.ca).uri; + TLSSocket.resolveAssetIfNeeded(this._options, 'ca'); + TLSSocket.resolveAssetIfNeeded(this._options, 'key'); + TLSSocket.resolveAssetIfNeeded(this._options, 'cert'); + /** @private */ this._socket = socket; // @ts-ignore @@ -56,4 +65,29 @@ export default class TLSSocket extends Socket { _startTLS() { Sockets.startTLS(this._id, this._options); } + + getCertificate() { + return Sockets.getCertificate(this._id); + } + + getPeerCertificate() { + return Sockets.getPeerCertificate(this._id); + } + + /** + * @private + * Resolves the asset source if necessary and registers the resolved key. + * @param {TLSSocketOptions} options The options object containing the source to be resolved. + * @param {'ca' | 'key' | 'cert'} key The key name being resolved. + */ + static resolveAssetIfNeeded(options, key) { + const source = options[key]; + if (source && typeof source !== 'string') { + if (!options.resolvedKeys) { + options.resolvedKeys = []; + } + options.resolvedKeys.push(key); + options[key] = Image.resolveAssetSource(source).uri; + } + } }