Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add setTimeout() method #56

Merged
merged 4 commits into from
Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
![](https://github.com/Rapsssito/react-native-tcp-socket/workflows/tests/badge.svg)


React Native TCP socket API for Android & iOS with **client SSL/TLS support**. It allows you to create TCP clients and servers sockets, imitating some of node's [net](https://nodejs.org/api/net.html) API functionalities (check the available [API](#api) for more information).
React Native TCP socket API for Android & iOS with **client SSL/TLS support**. It allows you to create TCP clients and servers sockets, imitating some of Node's [net](https://nodejs.org/api/net.html) API functionalities (check the available [API](#api) for more information).

## Table of Contents

Expand All @@ -11,8 +11,8 @@ React Native TCP socket API for Android & iOS with **client SSL/TLS support**. I
- [Compatibility](#react-native-compatibility)
- [Usage](#usage)
- [API](#api)
- [Client](#client)
- [Server](#server)
- [TcpSocket](#tcpsocket)
- [TcpServer](#tcpserver)
- [Maintainers](#maintainers)
- [Acknowledgments](#acknowledgments)
- [License](#license)
Expand Down Expand Up @@ -113,7 +113,7 @@ To use this library you need to ensure you are using the correct version of Reac
Import the library:
```javascript
import TcpSocket from 'react-native-tcp-socket';
// var net = require('react-native-tcp-socket');
// const net = require('react-native-tcp-socket');
```
### Client
```javascript
Expand Down Expand Up @@ -179,12 +179,15 @@ const client = TcpSocket.createConnection({
_Note: In order to use self-signed certificates make sure to [update your metro.config.js configuration](#self-signed-ssl-only-available-for-react-native--060)._

## API
### Client
Here are listed all methods implemented in `react-native-tcp-socket`, their functionalities are equivalent to those provided by Node's [net](https://nodejs.org/api/net.html) (more info on [#41](https://github.com/Rapsssito/react-native-tcp-socket/issues/41)). However, the **methods whose interface differs from Node are shown in bold**.

### TcpSocket
* **Methods:**
* [`createConnection(options[, callback])`](#createconnection)
* [`write(data[, encoding][, callback])`](#write)
* [`destroy()`](#destroy)
* **[`TcpSocket.createConnection(options[, callback])`](#createconnection)**
* [`write(data[, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback)
* [`destroy([error])`](https://nodejs.org/api/net.html#net_socket_destroy_error)
* [`setNoDelay([noDelay])`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay)
* [`setTimeout(timeout[, callback])`](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback)

#### `createConnection()`
`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#createconnection-options).
Expand All @@ -195,6 +198,7 @@ _Note: In order to use self-signed certificates make sure to [update your metro.
| --------------------- | ------ | :--: | :-----: |-------------------------------------------------------------------------------------------------- |
| **`port`** | `<number>` | ✅ | ✅ | **Required**. Port the socket should connect to. |
| `host` | `<string>` | ✅ | ✅ | Host the socket should connect to. IP address in IPv4 format or `'localhost'`. **Default**: `'localhost'`. |
| `timeout` | `<number>` | ✅ | ✅ | If set, will be used to call [`setTimeout(timeout)`](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the socket is created, but before it starts the connection. |
| `localAddress` | `<string>` | ✅ | ✅ | 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` | `<number>` | ✅ | ✅ | Local port the socket should connect from. If not specified, the OS will decide. |
| `interface`| `<string>` | ❌ | ✅ | Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `'wifi', 'ethernet', 'cellular'`. |
Expand All @@ -205,18 +209,11 @@ _Note: In order to use self-signed certificates make sure to [update your metro.

**Note**: The platforms marked as ❌ use the default value.

#### `write()`
* `data`: `<string> | <Buffer> | <Uint8Array>`
* `encoding`: `<string>`. Only used when `data` is `string`. Default: `utf8`.
* `callback `: `<Function>`

`write(data[, encoding][, callback])` sends data on the socket. The second parameter specifies the encoding in the case of a string — it defaults to UTF8 encoding.

### Server
### TcpServer
* **Methods:**
* [`createServer(callback)`](#createserver)
* [`listen(options[, callback])`](#listen)
* [`close()`](#close)
* [`TcpSocket.createServer(connectionListener)`](https://nodejs.org/api/net.html#net_net_createserver_options_connectionlistener)
* **[`listen(options[, callback])`](#listen)**
* [`close([callback])`](https://nodejs.org/api/net.html#net_server_close_callback)

#### `listen()`
`listen(options[, callback])` creates a TCP server socket using the given [`options`](#listen-options).
Expand Down
76 changes: 38 additions & 38 deletions src/TcpSocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const STATE = {
* @typedef {{
* port: number;
* host?: string;
* timeout?: number;
* timeout?: number,
* localAddress?: string,
* localPort?: number,
* interface?: 'wifi' | 'cellular' | 'ethernet',
Expand All @@ -38,6 +38,9 @@ export default class TcpSocket extends EventEmitter {
this._id = id;
this._eventEmitter = eventEmitter;
/** @type {number} */
this._timeoutMsecs = 0;
this._timeout = undefined;
/** @type {number} */
this._state = STATE.DISCONNECTED;
this._registerEvents();
if (address != undefined) this._setConnected(address);
Expand Down Expand Up @@ -94,7 +97,7 @@ export default class TcpSocket extends EventEmitter {
});
// Timeout
if (customOptions.timeout) this.setTimeout(customOptions.timeout);
else if (this._timeout) this._activeTimer(this._timeout.msecs);
else if (this._timeout) this._activateTimer();
// TLS Cert
if (customOptions.tlsCert) {
customOptions.tlsCert = Image.resolveAssetSource(customOptions.tlsCert).uri;
Expand All @@ -107,53 +110,49 @@ export default class TcpSocket extends EventEmitter {
}

/**
* @private
* @param {number} msecs
* @param {() => void} [wrapper]
* Sets the socket to timeout after `timeout` milliseconds of inactivity on the socket. By default `TcpSocket` do not have a timeout.
*
* When an idle timeout is triggered the socket will receive a `'timeout'` event but the connection will not be severed.
* The user must manually call `socket.end()` or `socket.destroy()` to end the connection.
*
* If `timeout` is 0, then the existing idle timeout is disabled.
*
* The optional `callback` parameter will be added as a one-time listener for the `'timeout'` event.
*
* @param {number} timeout
* @param {() => void} [callback]
*/
_activeTimer(msecs, wrapper) {
if (this._timeout && this._timeout.handle) clearTimeout(this._timeout.handle);

if (!wrapper) {
const self = this;
wrapper = function() {
self._timeout = null;
self._eventEmitter.emit('timeout');
};
setTimeout(timeout, callback) {
if (timeout === 0) {
this._clearTimeout();
} else {
this._activateTimer(timeout);
}

this._timeout = {
handle: setTimeout(wrapper, msecs),
wrapper: wrapper,
msecs: msecs,
};
if (callback) this.once('timeout', callback);
return this;
}

/**
* @private
* @param {number} [timeout]
*/
_clearTimeout() {
if (this._timeout) {
clearTimeout(this._timeout.handle);
this._timeout = null;
}
_activateTimer(timeout) {
if (timeout !== undefined) this._timeoutMsecs = timeout;
this._clearTimeout();
this._timeout = setTimeout(() => {
this._clearTimeout();
this.emit('timeout');
}, this._timeoutMsecs);
}

/**
* @deprecated
* @param {number} msecs
* @param {(...args: any[]) => void } [callback]
* @private
*/
setTimeout(msecs, callback) {
if (msecs === 0) {
this._clearTimeout();
if (callback) this._eventEmitter.removeListener('timeout', callback);
} else {
if (callback) this._eventEmitter.once('timeout', callback, this);

this._activeTimer(msecs);
_clearTimeout() {
if (this._timeout !== undefined) {
clearTimeout(this._timeout);
this._timeout = undefined;
}
return this;
}

/**
Expand Down Expand Up @@ -186,6 +185,7 @@ export default class TcpSocket extends EventEmitter {
});
} else {
this._destroyed = true;
this._clearTimeout();
Sockets.end(this._id);
}
}
Expand Down Expand Up @@ -242,7 +242,7 @@ export default class TcpSocket extends EventEmitter {
* @param {string} err
*/
function(err) {
if (self._timeout) self._activeTimer(self._timeout.msecs);
if (self._timeout) self._activateTimer();
if (callback) {
if (err) return callback(err);
callback(null);
Expand Down