Skip to content

Commit e642e1a

Browse files
authored
feat: Add setTimeout() method (#56)
1 parent 50e9b79 commit e642e1a

File tree

2 files changed

+54
-57
lines changed

2 files changed

+54
-57
lines changed

README.md

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
![](https://github.com/Rapsssito/react-native-tcp-socket/workflows/tests/badge.svg)
33

44

5-
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).
5+
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).
66

77
## Table of Contents
88

@@ -11,8 +11,8 @@ React Native TCP socket API for Android & iOS with **client SSL/TLS support**. I
1111
- [Compatibility](#react-native-compatibility)
1212
- [Usage](#usage)
1313
- [API](#api)
14-
- [Client](#client)
15-
- [Server](#server)
14+
- [TcpSocket](#tcpsocket)
15+
- [TcpServer](#tcpserver)
1616
- [Maintainers](#maintainers)
1717
- [Acknowledgments](#acknowledgments)
1818
- [License](#license)
@@ -113,7 +113,7 @@ To use this library you need to ensure you are using the correct version of Reac
113113
Import the library:
114114
```javascript
115115
import TcpSocket from 'react-native-tcp-socket';
116-
// var net = require('react-native-tcp-socket');
116+
// const net = require('react-native-tcp-socket');
117117
```
118118
### Client
119119
```javascript
@@ -179,12 +179,15 @@ const client = TcpSocket.createConnection({
179179
_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)._
180180

181181
## API
182-
### Client
182+
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**.
183+
184+
### TcpSocket
183185
* **Methods:**
184-
* [`createConnection(options[, callback])`](#createconnection)
185-
* [`write(data[, encoding][, callback])`](#write)
186-
* [`destroy()`](#destroy)
186+
* **[`TcpSocket.createConnection(options[, callback])`](#createconnection)**
187+
* [`write(data[, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback)
188+
* [`destroy([error])`](https://nodejs.org/api/net.html#net_socket_destroy_error)
187189
* [`setNoDelay([noDelay])`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay)
190+
* [`setTimeout(timeout[, callback])`](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback)
188191

189192
#### `createConnection()`
190193
`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#createconnection-options).
@@ -195,6 +198,7 @@ _Note: In order to use self-signed certificates make sure to [update your metro.
195198
| --------------------- | ------ | :--: | :-----: |-------------------------------------------------------------------------------------------------- |
196199
| **`port`** | `<number>` ||| **Required**. Port the socket should connect to. |
197200
| `host` | `<string>` ||| Host the socket should connect to. IP address in IPv4 format or `'localhost'`. **Default**: `'localhost'`. |
201+
| `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. |
198202
| `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. |
199203
| `localPort` | `<number>` ||| Local port the socket should connect from. If not specified, the OS will decide. |
200204
| `interface`| `<string>` ||| Interface the socket should connect from. If not specified, it will use the current active connection. The options are: `'wifi', 'ethernet', 'cellular'`. |
@@ -205,18 +209,11 @@ _Note: In order to use self-signed certificates make sure to [update your metro.
205209

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

208-
#### `write()`
209-
* `data`: `<string> | <Buffer> | <Uint8Array>`
210-
* `encoding`: `<string>`. Only used when `data` is `string`. Default: `utf8`.
211-
* `callback `: `<Function>`
212-
213-
`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.
214-
215-
### Server
212+
### TcpServer
216213
* **Methods:**
217-
* [`createServer(callback)`](#createserver)
218-
* [`listen(options[, callback])`](#listen)
219-
* [`close()`](#close)
214+
* [`TcpSocket.createServer(connectionListener)`](https://nodejs.org/api/net.html#net_net_createserver_options_connectionlistener)
215+
* **[`listen(options[, callback])`](#listen)**
216+
* [`close([callback])`](https://nodejs.org/api/net.html#net_server_close_callback)
220217

221218
#### `listen()`
222219
`listen(options[, callback])` creates a TCP server socket using the given [`options`](#listen-options).

src/TcpSocket.js

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const STATE = {
1515
* @typedef {{
1616
* port: number;
1717
* host?: string;
18-
* timeout?: number;
18+
* timeout?: number,
1919
* localAddress?: string,
2020
* localPort?: number,
2121
* interface?: 'wifi' | 'cellular' | 'ethernet',
@@ -38,6 +38,9 @@ export default class TcpSocket extends EventEmitter {
3838
this._id = id;
3939
this._eventEmitter = eventEmitter;
4040
/** @type {number} */
41+
this._timeoutMsecs = 0;
42+
this._timeout = undefined;
43+
/** @type {number} */
4144
this._state = STATE.DISCONNECTED;
4245
this._registerEvents();
4346
if (address != undefined) this._setConnected(address);
@@ -94,7 +97,7 @@ export default class TcpSocket extends EventEmitter {
9497
});
9598
// Timeout
9699
if (customOptions.timeout) this.setTimeout(customOptions.timeout);
97-
else if (this._timeout) this._activeTimer(this._timeout.msecs);
100+
else if (this._timeout) this._activateTimer();
98101
// TLS Cert
99102
if (customOptions.tlsCert) {
100103
customOptions.tlsCert = Image.resolveAssetSource(customOptions.tlsCert).uri;
@@ -107,53 +110,49 @@ export default class TcpSocket extends EventEmitter {
107110
}
108111

109112
/**
110-
* @private
111-
* @param {number} msecs
112-
* @param {() => void} [wrapper]
113+
* Sets the socket to timeout after `timeout` milliseconds of inactivity on the socket. By default `TcpSocket` do not have a timeout.
114+
*
115+
* When an idle timeout is triggered the socket will receive a `'timeout'` event but the connection will not be severed.
116+
* The user must manually call `socket.end()` or `socket.destroy()` to end the connection.
117+
*
118+
* If `timeout` is 0, then the existing idle timeout is disabled.
119+
*
120+
* The optional `callback` parameter will be added as a one-time listener for the `'timeout'` event.
121+
*
122+
* @param {number} timeout
123+
* @param {() => void} [callback]
113124
*/
114-
_activeTimer(msecs, wrapper) {
115-
if (this._timeout && this._timeout.handle) clearTimeout(this._timeout.handle);
116-
117-
if (!wrapper) {
118-
const self = this;
119-
wrapper = function() {
120-
self._timeout = null;
121-
self._eventEmitter.emit('timeout');
122-
};
125+
setTimeout(timeout, callback) {
126+
if (timeout === 0) {
127+
this._clearTimeout();
128+
} else {
129+
this._activateTimer(timeout);
123130
}
124-
125-
this._timeout = {
126-
handle: setTimeout(wrapper, msecs),
127-
wrapper: wrapper,
128-
msecs: msecs,
129-
};
131+
if (callback) this.once('timeout', callback);
132+
return this;
130133
}
131134

132135
/**
133136
* @private
137+
* @param {number} [timeout]
134138
*/
135-
_clearTimeout() {
136-
if (this._timeout) {
137-
clearTimeout(this._timeout.handle);
138-
this._timeout = null;
139-
}
139+
_activateTimer(timeout) {
140+
if (timeout !== undefined) this._timeoutMsecs = timeout;
141+
this._clearTimeout();
142+
this._timeout = setTimeout(() => {
143+
this._clearTimeout();
144+
this.emit('timeout');
145+
}, this._timeoutMsecs);
140146
}
141147

142148
/**
143-
* @deprecated
144-
* @param {number} msecs
145-
* @param {(...args: any[]) => void } [callback]
149+
* @private
146150
*/
147-
setTimeout(msecs, callback) {
148-
if (msecs === 0) {
149-
this._clearTimeout();
150-
if (callback) this._eventEmitter.removeListener('timeout', callback);
151-
} else {
152-
if (callback) this._eventEmitter.once('timeout', callback, this);
153-
154-
this._activeTimer(msecs);
151+
_clearTimeout() {
152+
if (this._timeout !== undefined) {
153+
clearTimeout(this._timeout);
154+
this._timeout = undefined;
155155
}
156-
return this;
157156
}
158157

159158
/**
@@ -186,6 +185,7 @@ export default class TcpSocket extends EventEmitter {
186185
});
187186
} else {
188187
this._destroyed = true;
188+
this._clearTimeout();
189189
Sockets.end(this._id);
190190
}
191191
}
@@ -242,7 +242,7 @@ export default class TcpSocket extends EventEmitter {
242242
* @param {string} err
243243
*/
244244
function(err) {
245-
if (self._timeout) self._activeTimer(self._timeout.msecs);
245+
if (self._timeout) self._activateTimer();
246246
if (callback) {
247247
if (err) return callback(err);
248248
callback(null);

0 commit comments

Comments
 (0)