From 827c279b92dd0c7c360ab8175e78b139be38ef94 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Fri, 10 Jan 2020 20:59:37 +0100 Subject: [PATCH 01/12] Updated README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 164615c..4e8b779 100644 --- a/README.md +++ b/README.md @@ -161,11 +161,12 @@ server.on('close', () => { | Property | Type | Description | | --------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------- | -| **`host`** | `` | **Required**. A valid server IP address in IPv4 format or `"localhost"`. | -| **`port`** | `` | **Required**. A valid server port. | -| `[localAddress]` | `` | A valid local IP address to bind the socket. If not specified, the OS will decide. It is **highly recommended** to specify a `localAddress` to prevent overload errors and improve performance. | -| `[localPort]` | `` | A valid local port to bind the socket. If not specified, the OS will decide. | -| `[interface]`| `` | The interface to bind the socket. If not specified, it will use the current active connection. The options are: `"wifi"`. | +| **`port`** | `` | **Required**. Port the socket should connect to. | +| `host` | `` | Host the socket should connect to. IP address in IPv4 format or `"localhost"`. **Default**: `"localhost"`. | +| `reuseAddress`| `` | Enable/disable the reuseAddress socket option. **Default**: `false`. | +| `localAddress` | `` | Local address the socket should connect from. If not specified, the OS will decide. It is **highly recommended** to specify a `localAddress` to prevent overload errors and improve performance. | +| `localPort` | `` | Local port the socket should connect from. If not specified, the OS will decide. | +| `interface`| `` | Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `"wifi"`. | #### `write()` * `data`: ` | | ` From 6b643257352eed1d36bed98c95491545ce2ef496 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Fri, 10 Jan 2020 21:14:07 +0100 Subject: [PATCH 02/12] Android: client socket setReuseAddress --- android/build.gradle | 1 + .../react/tcpsocket/TcpSocketClient.java | 18 ++++++++++++------ .../react/tcpsocket/TcpSocketModule.java | 11 +++++++---- .../react/tcpsocket/TcpSocketPackage.java | 1 + 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 6af83d6..724da6a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -66,6 +66,7 @@ dependencies { } def configureReactNativePom(def pom) { + //noinspection UnnecessaryQualifiedReference def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text) pom.project { 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 b2a4ac7..ddf85ba 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,8 @@ import android.os.AsyncTask; import android.util.Pair; +import com.facebook.react.bridge.ReadableMap; + import java.io.OutputStream; import java.io.IOException; import java.net.InetAddress; @@ -24,23 +26,27 @@ public TcpSocketClient() { /** * TcpSocketClient constructor * - * @param address server address - * @param port server port - * @param localAddress local address to bound to - * @param localPort local port to bound to + * @param address server address + * @param port server port + * @param options extra options */ public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, - final String address, final Integer port, final String localAddress, final int localPort, final Network network) + final String address, final Integer port, final ReadableMap options, final Network network) throws IOException { this.id = id; // Get the addresses + String localAddress = options.getString("localAddress"); InetAddress localInetAddress = InetAddress.getByName(localAddress); InetAddress remoteInetAddress = InetAddress.getByName(address); // Create the socket socket = new Socket(); if (network != null) network.bindSocket(socket); - socket.setReuseAddress(true); + // setReuseAddress + boolean reuseAddress = options.getBoolean("reuseAddress"); + socket.setReuseAddress(reuseAddress); + // bind + int localPort = options.getInt("localPort"); socket.bind(new InetSocketAddress(localInetAddress, localPort)); socket.connect(new InetSocketAddress(remoteInetAddress, port)); receiverTask = new TcpReceiverTask(); 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 de6f261..288e132 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java @@ -108,6 +108,7 @@ public void onUnavailable() { * @param port socket port to be bound * @param options extra options */ + @SuppressWarnings("unused") @ReactMethod public void connect(final Integer cId, final String host, final Integer port, final ReadableMap options) { new GuardedAsyncTask(mReactContext.getExceptionHandler()) { @@ -123,13 +124,12 @@ protected void doInBackgroundGuarded(Void... params) { onError(cId, TAG + "createSocket called twice with the same id."); return; } - String localAddress = options.getString("localAddress"); - String iface = options.getString("interface"); - int localPort = options.getInt("localPort"); try { // Get the network interface + String localAddress = options.getString("localAddress"); + String iface = options.getString("interface"); selectNetwork(iface, localAddress); - client = new TcpSocketClient(TcpSocketModule.this, cId, host, port, localAddress, localPort, mSelectedNetwork); + client = new TcpSocketClient(TcpSocketModule.this, cId, host, port, options, mSelectedNetwork); socketClients.put(cId, client); onConnect(cId, host, port); } catch (Exception e) { @@ -139,6 +139,7 @@ protected void doInBackgroundGuarded(Void... params) { }.execute(); } + @SuppressWarnings("unused") @ReactMethod public void write(final Integer cId, final String base64String, final Callback callback) { new GuardedAsyncTask(mReactContext.getExceptionHandler()) { @@ -178,11 +179,13 @@ protected void doInBackgroundGuarded(Void... params) { }.execute(); } + @SuppressWarnings("unused") @ReactMethod public void destroy(final Integer cId) { end(cId); } + @SuppressWarnings("unused") @ReactMethod public void listen(final Integer cId, final String host, final Integer port) { new GuardedAsyncTask(mReactContext.getExceptionHandler()) { diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java index 83ae6cb..941ac73 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java @@ -11,6 +11,7 @@ import androidx.annotation.NonNull; +@SuppressWarnings("unused") public class TcpSocketPackage implements ReactPackage { @Override public @NonNull List createNativeModules(@NonNull ReactApplicationContext reactContext) { From 9b1bb98b8999fdb0d8911fabe76b13392f66b614 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Fri, 10 Jan 2020 21:21:58 +0100 Subject: [PATCH 03/12] Android: Better inheritance --- .../com/asterinet/react/tcpsocket/TcpSocketClient.java | 10 +++++----- .../com/asterinet/react/tcpsocket/TcpSocketServer.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) 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 ddf85ba..ee0487e 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java @@ -17,10 +17,10 @@ public class TcpSocketClient { private Socket socket; private TcpReceiverTask.OnDataReceivedListener mReceiverListener; - protected Integer id; - - public TcpSocketClient() { + private Integer id; + public TcpSocketClient(final int id) { + this.id = id; } /** @@ -33,7 +33,7 @@ public TcpSocketClient() { public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, final String address, final Integer port, final ReadableMap options, final Network network) throws IOException { - this.id = id; + this(id); // Get the addresses String localAddress = options.getString("localAddress"); InetAddress localInetAddress = InetAddress.getByName(localAddress); @@ -55,7 +55,7 @@ public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverList } public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, final Socket socket) { - this.id = id; + this(id); this.socket = socket; receiverTask = new TcpReceiverTask(); mReceiverListener = receiverListener; diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java index e9e31a3..d95905c 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java @@ -40,9 +40,9 @@ protected Void doInBackground(Object[] objects) { public TcpSocketServer(final SparseArray socketClients, final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, final String address, final Integer port) throws IOException { - this.id = id; + super(id); this.socketClients = socketClients; - clientSocketIds = (1 + this.id) * 1000; + clientSocketIds = (1 + getId()) * 1000; // Get the addresses InetAddress localInetAddress = InetAddress.getByName(address); // Create the socket From 6aa27177006adffbb3349d0e41c252fd1a961b93 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Fri, 10 Jan 2020 22:53:16 +0100 Subject: [PATCH 04/12] Android: server socket setReuseAddress --- README.md | 26 +++++++++++++------ .../react/tcpsocket/TcpSocketModule.java | 6 +++-- .../react/tcpsocket/TcpSocketServer.java | 10 ++++++- src/TcpServer.js | 13 +++++++--- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4e8b779..9a298d1 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ client.on('close', function(){ }); // Write on the socket -client.write("Hello server!"); +client.write('Hello server!'); // Close socket client.destroy(); @@ -155,18 +155,18 @@ server.on('close', () => { * [`destroy()`](#destroy) #### `createConnection()` -`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#options). -##### `options` -**Required**. Available options for creating a socket. It is an `object` with the following properties: +`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#createConnection:%20options). +##### `createConnection: options` +**Required**. Available options for creating a socket. It must be an `object` with the following properties: | Property | Type | Description | | --------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------- | | **`port`** | `` | **Required**. Port the socket should connect to. | -| `host` | `` | Host the socket should connect to. IP address in IPv4 format or `"localhost"`. **Default**: `"localhost"`. | +| `host` | `` | Host the socket should connect to. IP address in IPv4 format or `'localhost'`. **Default**: `'localhost'`. | | `reuseAddress`| `` | Enable/disable the reuseAddress socket option. **Default**: `false`. | | `localAddress` | `` | Local address the socket should connect from. If not specified, the OS will decide. It is **highly recommended** to specify a `localAddress` to prevent overload errors and improve performance. | | `localPort` | `` | Local port the socket should connect from. If not specified, the OS will decide. | -| `interface`| `` | Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `"wifi"`. | +| `interface`| `` | Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `'wifi'`. | #### `write()` * `data`: ` | | ` @@ -178,11 +178,21 @@ server.on('close', () => { ### Server * **Methods:** * [`createServer(callback)`](#createserver) - * [`listen(port[, host])`](#listen) + * [`listen(options[, callback])`](#listen) * [`close()`](#close) #### `listen()` -`listen(port[, host])` creates a TCP server socket listening on the given port. If the host is not explicity selected, the socket will be bound to `'0.0.0.0'`. +`listen(options[, callback])` creates a TCP server socket using the given [`options`](#listen:%20options). + +##### `listen: options` +**Required**. Available options for creating a server socket. It must be an `object` with the following properties: + +| Property | Type | Description | +| --------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------- | +| **`port`** | `` | **Required**. Port the socket should listen to. | +| `host` | `` | Host the socket should listen to. IP address in IPv4 format or `'localhost'`. **Default**: `'0.0.0.0'`. | +| `reuseAddress`| `` | Enable/disable the reuseAddress socket option. **Default**: `false`. | + ## Maintainers Looking for maintainers! 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 288e132..9cdb81c 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java @@ -187,13 +187,15 @@ public void destroy(final Integer cId) { @SuppressWarnings("unused") @ReactMethod - public void listen(final Integer cId, final String host, final Integer port) { + public void listen(final Integer cId, final ReadableMap options) { new GuardedAsyncTask(mReactContext.getExceptionHandler()) { @Override protected void doInBackgroundGuarded(Void... params) { try { - TcpSocketServer server = new TcpSocketServer(socketClients, TcpSocketModule.this, cId, host, port); + TcpSocketServer server = new TcpSocketServer(socketClients, TcpSocketModule.this, cId, options); socketClients.put(cId, server); + Integer port = options.getInt("port"); + String host = options.getString("host"); onConnect(cId, host, port); } catch (Exception uhe) { onError(cId, uhe.getMessage()); diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java index d95905c..e24728e 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java @@ -3,6 +3,8 @@ import android.os.AsyncTask; import android.util.SparseArray; +import com.facebook.react.bridge.ReadableMap; + import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -39,14 +41,20 @@ protected Void doInBackground(Object[] objects) { public TcpSocketServer(final SparseArray socketClients, final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, - final String address, final Integer port) throws IOException { + final ReadableMap options) throws IOException { super(id); + // Get data from options + Integer port = options.getInt("port"); + String address = options.getString("host"); this.socketClients = socketClients; clientSocketIds = (1 + getId()) * 1000; // Get the addresses InetAddress localInetAddress = InetAddress.getByName(address); // Create the socket serverSocket = new ServerSocket(port, 50, localInetAddress); + // setReuseAddress + boolean reuseAddress = options.getBoolean("reuseAddress"); + serverSocket.setReuseAddress(reuseAddress); mReceiverListener = receiverListener; listen(); } diff --git a/src/TcpServer.js b/src/TcpServer.js index 4e13352..a608a22 100644 --- a/src/TcpServer.js +++ b/src/TcpServer.js @@ -20,8 +20,15 @@ export default class TcpServer extends TcpSocket { callback(this._connections.length); } - listen(port, host, callback) { - host = host || '0.0.0.0'; + listen(options, callback) { + // Normalize args + if (arguments[0] instanceof Number) { + // Old version: listen(port[, host][, callback]) + options.port = arguments[0]; + options.host = arguments[1] || '0.0.0.0'; + callback = arguments[2]; + } + options.host = options.host || '0.0.0.0'; const connectListener = this._eventEmitter.addListener('connect', (ev) => { if (this._id !== ev.id) return; connectListener.remove(); @@ -32,7 +39,7 @@ export default class TcpServer extends TcpSocket { if (this._id !== ev.id) return; this._onConnection(ev.info); }); - Sockets.listen(this._id, host, port); + Sockets.listen(this._id, options); return this; } From d1a18eb81e774dfcaed422333bfa92062e619e0a Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Fri, 10 Jan 2020 22:57:48 +0100 Subject: [PATCH 05/12] Corrected README links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a298d1..4093601 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ server.on('close', () => { * [`destroy()`](#destroy) #### `createConnection()` -`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#createConnection:%20options). +`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#createconnection-options). ##### `createConnection: options` **Required**. Available options for creating a socket. It must be an `object` with the following properties: @@ -182,7 +182,7 @@ server.on('close', () => { * [`close()`](#close) #### `listen()` -`listen(options[, callback])` creates a TCP server socket using the given [`options`](#listen:%20options). +`listen(options[, callback])` creates a TCP server socket using the given [`options`](#listen-options). ##### `listen: options` **Required**. Available options for creating a server socket. It must be an `object` with the following properties: From 943a5f60a986120fddc81e07166e66796767a087 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Fri, 10 Jan 2020 23:56:17 +0100 Subject: [PATCH 06/12] Add deprecated warning --- src/TcpServer.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/TcpServer.js b/src/TcpServer.js index a608a22..d7809f9 100644 --- a/src/TcpServer.js +++ b/src/TcpServer.js @@ -23,7 +23,10 @@ export default class TcpServer extends TcpSocket { listen(options, callback) { // Normalize args if (arguments[0] instanceof Number) { - // Old version: listen(port[, host][, callback]) + // Deprecated old version: listen(port[, host][, callback]) + console.warn( + 'TcpServer.listen(port[, host][, callback]) is deprecated. It has been moved to TcpServer.listen(options[, callback]) and will be removed in react-native-tcp-socket@4.0.0' + ); options.port = arguments[0]; options.host = arguments[1] || '0.0.0.0'; callback = arguments[2]; From ca72896ad85aed2784c277d8d9e4b9857caf62f5 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Sat, 11 Jan 2020 13:30:47 +0100 Subject: [PATCH 07/12] Android: fix empty options causing error --- .../react/tcpsocket/TcpSocketClient.java | 7 +++++-- .../react/tcpsocket/TcpSocketServer.java | 7 +++++-- src/TcpServer.js | 15 +++++++++------ 3 files changed, 19 insertions(+), 10 deletions(-) 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 ee0487e..5343089 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java @@ -5,6 +5,7 @@ import android.util.Pair; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.ReadableType; import java.io.OutputStream; import java.io.IOException; @@ -43,8 +44,10 @@ public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverList if (network != null) network.bindSocket(socket); // setReuseAddress - boolean reuseAddress = options.getBoolean("reuseAddress"); - socket.setReuseAddress(reuseAddress); + if (options.getType("reuseAddress") == ReadableType.Boolean){ + boolean reuseAddress = options.getBoolean("reuseAddress"); + socket.setReuseAddress(reuseAddress); + } // bind int localPort = options.getInt("localPort"); socket.bind(new InetSocketAddress(localInetAddress, localPort)); diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java index e24728e..fb0df0a 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java @@ -4,6 +4,7 @@ import android.util.SparseArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.ReadableType; import java.io.IOException; import java.net.InetAddress; @@ -53,8 +54,10 @@ public TcpSocketServer(final SparseArray socketClients, final T // Create the socket serverSocket = new ServerSocket(port, 50, localInetAddress); // setReuseAddress - boolean reuseAddress = options.getBoolean("reuseAddress"); - serverSocket.setReuseAddress(reuseAddress); + if (options.getType("reuseAddress") == ReadableType.Boolean){ + boolean reuseAddress = options.getBoolean("reuseAddress"); + serverSocket.setReuseAddress(reuseAddress); + } mReceiverListener = receiverListener; listen(); } diff --git a/src/TcpServer.js b/src/TcpServer.js index d7809f9..c568b2e 100644 --- a/src/TcpServer.js +++ b/src/TcpServer.js @@ -21,17 +21,20 @@ export default class TcpServer extends TcpSocket { } listen(options, callback) { + let gotOptions = {}; // Normalize args - if (arguments[0] instanceof Number) { + if (typeof arguments[0] === 'number') { // Deprecated old version: listen(port[, host][, callback]) console.warn( - 'TcpServer.listen(port[, host][, callback]) is deprecated. It has been moved to TcpServer.listen(options[, callback]) and will be removed in react-native-tcp-socket@4.0.0' + 'TcpServer.listen(port[, host][, callback]) is deprecated and has been moved to TcpServer.listen(options[, callback]). It will be removed in react-native-tcp-socket@4.0.0' ); - options.port = arguments[0]; - options.host = arguments[1] || '0.0.0.0'; + gotOptions.port = arguments[0]; + gotOptions.host = arguments[1]; callback = arguments[2]; + } else { + gotOptions = options; } - options.host = options.host || '0.0.0.0'; + gotOptions.host = gotOptions.host || '0.0.0.0'; const connectListener = this._eventEmitter.addListener('connect', (ev) => { if (this._id !== ev.id) return; connectListener.remove(); @@ -42,7 +45,7 @@ export default class TcpServer extends TcpSocket { if (this._id !== ev.id) return; this._onConnection(ev.info); }); - Sockets.listen(this._id, options); + Sockets.listen(this._id, gotOptions); return this; } From c114c8c017a55225e4a572172dc8ba7d788c7f80 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Sat, 11 Jan 2020 13:43:06 +0100 Subject: [PATCH 08/12] Android: Java refactor --- android/build.gradle | 2 +- android/gradle/wrapper/gradle-wrapper.properties | 4 ++-- .../react/tcpsocket/TcpReceiverTask.java | 4 +++- .../react/tcpsocket/TcpSocketClient.java | 15 +++++++++------ .../react/tcpsocket/TcpSocketModule.java | 10 ++++++++-- .../react/tcpsocket/TcpSocketPackage.java | 1 + .../react/tcpsocket/TcpSocketServer.java | 12 ++++++++---- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 724da6a..456e1f1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -14,7 +14,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.1' + classpath 'com.android.tools.build:gradle:3.5.3' } } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 5785b34..870f3a6 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Oct 05 12:20:33 CEST 2019 +#Sat Jan 11 13:40:56 CET 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpReceiverTask.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpReceiverTask.java index 9239dfa..6b9b782 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpReceiverTask.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpReceiverTask.java @@ -18,8 +18,9 @@ public class TcpReceiverTask extends AsyncTask... params) { + protected final Void doInBackground(Pair... params) { if (params.length > 1) { throw new IllegalArgumentException("This task is only for a single socket/listener pair."); } @@ -52,6 +53,7 @@ protected Void doInBackground(Pair(this, receiverListener)); } - public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, final Socket socket) { + TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, final Socket socket) { this(id); this.socket = socket; receiverTask = new TcpReceiverTask(); mReceiverListener = receiverListener; + //noinspection unchecked receiverTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Pair<>(this, receiverListener)); } 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 9cdb81c..1e31014 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java @@ -1,6 +1,7 @@ package com.asterinet.react.tcpsocket; +import android.annotation.SuppressLint; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; @@ -35,7 +36,7 @@ public class TcpSocketModule extends ReactContextBaseJavaModule implements TcpRe private final SparseArray mNetworkMap = new SparseArray<>(); private Network mSelectedNetwork; - public static final String TAG = "TcpSockets"; + private static final String TAG = "TcpSockets"; public TcpSocketModule(ReactApplicationContext reactContext) { super(reactContext); @@ -108,6 +109,7 @@ public void onUnavailable() { * @param port socket port to be bound * @param options extra options */ + @SuppressLint("StaticFieldLeak") @SuppressWarnings("unused") @ReactMethod public void connect(final Integer cId, final String host, final Integer port, final ReadableMap options) { @@ -139,6 +141,7 @@ protected void doInBackgroundGuarded(Void... params) { }.execute(); } + @SuppressLint("StaticFieldLeak") @SuppressWarnings("unused") @ReactMethod public void write(final Integer cId, final String base64String, final Callback callback) { @@ -164,6 +167,8 @@ protected void doInBackgroundGuarded(Void... params) { }.execute(); } + @SuppressLint("StaticFieldLeak") + @SuppressWarnings("unused") @ReactMethod public void end(final Integer cId) { new GuardedAsyncTask(mReactContext.getExceptionHandler()) { @@ -185,6 +190,7 @@ public void destroy(final Integer cId) { end(cId); } + @SuppressLint("StaticFieldLeak") @SuppressWarnings("unused") @ReactMethod public void listen(final Integer cId, final ReadableMap options) { @@ -194,7 +200,7 @@ protected void doInBackgroundGuarded(Void... params) { try { TcpSocketServer server = new TcpSocketServer(socketClients, TcpSocketModule.this, cId, options); socketClients.put(cId, server); - Integer port = options.getInt("port"); + int port = options.getInt("port"); String host = options.getString("host"); onConnect(cId, host, port); } catch (Exception uhe) { diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java index 941ac73..f66e679 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java @@ -15,6 +15,7 @@ public class TcpSocketPackage implements ReactPackage { @Override public @NonNull List createNativeModules(@NonNull ReactApplicationContext reactContext) { + //noinspection ArraysAsListWithZeroOrOneArgument return Arrays.asList(new TcpSocketModule(reactContext)); } diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java index fb0df0a..51d75db 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java @@ -1,10 +1,10 @@ package com.asterinet.react.tcpsocket; +import android.annotation.SuppressLint; import android.os.AsyncTask; import android.util.SparseArray; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableType; import java.io.IOException; import java.net.InetAddress; @@ -16,9 +16,10 @@ public class TcpSocketServer extends TcpSocketClient { private ServerSocket serverSocket; private TcpReceiverTask.OnDataReceivedListener mReceiverListener; private int clientSocketIds; - private SparseArray socketClients; + private final SparseArray socketClients; private final SparseArray serverSocketClients = new SparseArray<>(); + @SuppressLint("StaticFieldLeak") private final AsyncTask listening = new AsyncTask() { @Override protected Void doInBackground(Object[] objects) { @@ -45,7 +46,7 @@ public TcpSocketServer(final SparseArray socketClients, final T final ReadableMap options) throws IOException { super(id); // Get data from options - Integer port = options.getInt("port"); + int port = options.getInt("port"); String address = options.getString("host"); this.socketClients = socketClients; clientSocketIds = (1 + getId()) * 1000; @@ -54,9 +55,11 @@ public TcpSocketServer(final SparseArray socketClients, final T // Create the socket serverSocket = new ServerSocket(port, 50, localInetAddress); // setReuseAddress - if (options.getType("reuseAddress") == ReadableType.Boolean){ + try { boolean reuseAddress = options.getBoolean("reuseAddress"); serverSocket.setReuseAddress(reuseAddress); + } catch (Exception e) { + // Ignore errors } mReceiverListener = receiverListener; listen(); @@ -72,6 +75,7 @@ private int getClientId() { } private void listen() { + //noinspection unchecked listening.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } From 5e2ec3d4e1fc3a8001f2f891e7dff8c06752502d Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Sat, 11 Jan 2020 13:46:58 +0100 Subject: [PATCH 09/12] Updated example --- examples/tcpsockets/App.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/tcpsockets/App.js b/examples/tcpsockets/App.js index 11ef5f7..b269c1c 100644 --- a/examples/tcpsockets/App.js +++ b/examples/tcpsockets/App.js @@ -48,7 +48,7 @@ class App extends React.Component { socket.on('close', (error) => { this.updateChatter('server client closed ' + (error ? error : '')); }); - }).listen(serverPort, serverHost, (address) => { + }).listen({port: serverPort, host: serverHost, reuseAddress: true}, (address) => { this.updateChatter('opened server on ' + JSON.stringify(address)); }); @@ -64,6 +64,7 @@ class App extends React.Component { port: serverPort, host: serverHost, localAddress: "127.0.0.1", + reuseAddress: true, // localPort: 20000, // interface: "wifi" }, (address) => { From 6ea8372d52728664ea7011ae855fddc56c3aeb65 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Sat, 11 Jan 2020 15:04:29 +0100 Subject: [PATCH 10/12] iOS compatibility --- ios/TcpSocketClient.h | 5 ++--- ios/TcpSocketClient.m | 6 +++++- ios/TcpSockets.m | 7 +++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ios/TcpSocketClient.h b/ios/TcpSocketClient.h index 4f74b78..4434d7f 100644 --- a/ios/TcpSocketClient.h +++ b/ios/TcpSocketClient.h @@ -69,11 +69,10 @@ typedef enum RCTTCPError RCTTCPError; /** * Starts listening on a local host and port * - * @param local ip address - * @param local port + * @param options NSDictionary which must have a @"port" and @"host" to specify where to listen * @return true if connected, false if there was an error */ -- (BOOL)listen:(NSString *)host port:(int)port error:(NSError **)error; +- (BOOL)listen:(NSDictionary *)options error:(NSError **)error; /** * Returns the address information diff --git a/ios/TcpSocketClient.m b/ios/TcpSocketClient.m index d08dcab..9f6d1c6 100644 --- a/ios/TcpSocketClient.m +++ b/ios/TcpSocketClient.m @@ -108,7 +108,7 @@ - (BOOL)connect:(NSString *)host port:(int)port withOptions:(NSDictionary *)opti @"family": @"unkown" }; } -- (BOOL)listen:(NSString *)host port:(int)port error:(NSError **)error +- (BOOL)listen:(NSDictionary *)options error:(NSError **)error { if (_tcpSocket) { if (error) { @@ -121,6 +121,10 @@ - (BOOL)listen:(NSString *)host port:(int)port error:(NSError **)error _tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:[self methodQueue]]; [_tcpSocket setUserData: _id]; + // Get the host and port + NSString *host = options[@"host"]; + int port = [options[@"port"] intValue]; + // GCDAsyncSocket doesn't recognize 0.0.0.0 if ([@"0.0.0.0" isEqualToString: host]) { host = nil; diff --git a/ios/TcpSockets.m b/ios/TcpSockets.m index 9d96cc0..1135f51 100644 --- a/ios/TcpSockets.m +++ b/ios/TcpSockets.m @@ -106,8 +106,7 @@ - (TcpSocketClient *)createSocket:(nonnull NSNumber*)cId } RCT_EXPORT_METHOD(listen:(nonnull NSNumber*)cId - host:(NSString *)host - port:(int)port) + withOptions:(nonnull NSDictionary *)options) { TcpSocketClient* client = _clients[cId]; if (!client) { @@ -115,7 +114,7 @@ - (TcpSocketClient *)createSocket:(nonnull NSNumber*)cId } NSError *error = nil; - if (![client listen:host port:port error:&error]) + if (![client listen:options error:&error]) { [self onError:client withError:error]; return; @@ -200,4 +199,4 @@ -(NSNumber*)getNextId { return @(_counter++ + COUNTER_OFFSET); } -@end \ No newline at end of file +@end From dce9767afa128388414fed46b5284438de22d605 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Sat, 11 Jan 2020 15:12:39 +0100 Subject: [PATCH 11/12] Changed to default=true --- README.md | 26 +++++++++---------- .../react/tcpsocket/TcpSocketClient.java | 3 ++- .../react/tcpsocket/TcpSocketServer.java | 3 ++- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4093601..b312e20 100644 --- a/README.md +++ b/README.md @@ -159,14 +159,14 @@ server.on('close', () => { ##### `createConnection: options` **Required**. Available options for creating a socket. It must be an `object` with the following properties: -| Property | Type | Description | -| --------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------- | -| **`port`** | `` | **Required**. Port the socket should connect to. | -| `host` | `` | Host the socket should connect to. IP address in IPv4 format or `'localhost'`. **Default**: `'localhost'`. | -| `reuseAddress`| `` | Enable/disable the reuseAddress socket option. **Default**: `false`. | -| `localAddress` | `` | Local address the socket should connect from. If not specified, the OS will decide. It is **highly recommended** to specify a `localAddress` to prevent overload errors and improve performance. | -| `localPort` | `` | Local port the socket should connect from. If not specified, the OS will decide. | -| `interface`| `` | Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `'wifi'`. | +| Property | Type | iOS | Android |Description | +| --------------------- | ------ | :--: | :-----: |-------------------------------------------------------------------------------------------------- | +| **`port`** | `` | ✅ | ✅ | **Required**. Port the socket should connect to. | +| `host` | `` | ✅ | ✅ | Host the socket should connect to. IP address in IPv4 format or `'localhost'`. **Default**: `'localhost'`. | +| `localAddress` | `` | ✅ | ✅ | Local address the socket should connect from. If not specified, the OS will decide. It is **highly recommended** to specify a `localAddress` to prevent overload errors and improve performance. | +| `localPort` | `` | ✅ | ✅ | Local port the socket should connect from. If not specified, the OS will decide. | +| `interface`| `` | ❌ | ✅ | Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `'wifi'`. | +| `reuseAddress`| `` | ❌ | ✅ | Enable/disable the reuseAddress socket option. **Default**: `true`. | #### `write()` * `data`: ` | | ` @@ -187,11 +187,11 @@ server.on('close', () => { ##### `listen: options` **Required**. Available options for creating a server socket. It must be an `object` with the following properties: -| Property | Type | Description | -| --------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------- | -| **`port`** | `` | **Required**. Port the socket should listen to. | -| `host` | `` | Host the socket should listen to. IP address in IPv4 format or `'localhost'`. **Default**: `'0.0.0.0'`. | -| `reuseAddress`| `` | Enable/disable the reuseAddress socket option. **Default**: `false`. | +| Property | Type | iOS | Android |Description | +| --------------------- | ------ | :--: | :-----: |-------------------------------------------------------------------------------------------------- | +| **`port`** | `` | ✅ | ✅ | **Required**. Port the socket should listen to. | +| `host` | `` | ✅ | ✅ | Host the socket should listen to. IP address in IPv4 format or `'localhost'`. **Default**: `'0.0.0.0'`. | +| `reuseAddress`| `` | ❌ | ✅ | Enable/disable the reuseAddress socket option. **Default**: `true`. | ## Maintainers 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 598f892..010423e 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java @@ -47,7 +47,8 @@ public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverList boolean reuseAddress = options.getBoolean("reuseAddress"); socket.setReuseAddress(reuseAddress); } catch (Exception e) { - // Ignore errors + // Default to true + socket.setReuseAddress(true); } // bind int localPort = options.getInt("localPort"); diff --git a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java index 51d75db..f56d82d 100644 --- a/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java +++ b/android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketServer.java @@ -59,7 +59,8 @@ public TcpSocketServer(final SparseArray socketClients, final T boolean reuseAddress = options.getBoolean("reuseAddress"); serverSocket.setReuseAddress(reuseAddress); } catch (Exception e) { - // Ignore errors + // Default to true + serverSocket.setReuseAddress(true); } mReceiverListener = receiverListener; listen(); From e5e4e21a48ff6dfbe7e2fec366291312a2241244 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Sat, 11 Jan 2020 15:16:27 +0100 Subject: [PATCH 12/12] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b312e20..fb7aa53 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,8 @@ server.on('close', () => { | `interface`| `` | ❌ | ✅ | Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `'wifi'`. | | `reuseAddress`| `` | ❌ | ✅ | Enable/disable the reuseAddress socket option. **Default**: `true`. | +**Note**: The platforms marked as ❌ use the default value. + #### `write()` * `data`: ` | | ` * `encoding`: ``. Only used when `data` is `string`. Default: `utf8`. @@ -193,6 +195,7 @@ server.on('close', () => { | `host` | `` | ✅ | ✅ | Host the socket should listen to. IP address in IPv4 format or `'localhost'`. **Default**: `'0.0.0.0'`. | | `reuseAddress`| `` | ❌ | ✅ | Enable/disable the reuseAddress socket option. **Default**: `true`. | +**Note**: The platforms marked as ❌ use the default value. ## Maintainers Looking for maintainers!