Skip to content

Commit

Permalink
feat: Add setTimeout() method (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rapsssito authored Jun 18, 2020
1 parent 50e9b79 commit e642e1a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 57 deletions.
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

0 comments on commit e642e1a

Please sign in to comment.