Skip to content

Commit 35cea93

Browse files
authored
feat: Add setKeepAlive() method (#62)
1 parent 2c9433c commit 35cea93

File tree

9 files changed

+89
-7
lines changed

9 files changed

+89
-7
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ To use this library you need to ensure you are using the correct version of Reac
106106

107107
| `react-native-tcp-socket` version | Required React Native Version |
108108
| ----------------------------------------- | --------------------------------------------------------------------------------- |
109-
| `3.x.x` | `>= 0.61` |
109+
| `4.X.X`, `3.X.X` | `>= 0.61` |
110110
| `1.2.2` | `>= 0.??` |
111111

112112
## Usage
@@ -184,10 +184,13 @@ Here are listed all methods implemented in `react-native-tcp-socket`, their func
184184
### TcpSocket
185185
* **Methods:**
186186
* **[`TcpSocket.createConnection(options[, callback])`](#createconnection)**
187-
* [`write(data[, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback)
187+
* [`address()`](https://nodejs.org/api/net.html#net_socket_address)
188188
* [`destroy([error])`](https://nodejs.org/api/net.html#net_socket_destroy_error)
189+
* [`end([data][, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_end_data_encoding_callback)
190+
* [`setKeepAlive([enable][, initialDelay])`](https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) - _`initialDelay` is ignored_
189191
* [`setNoDelay([noDelay])`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay)
190192
* [`setTimeout(timeout[, callback])`](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback)
193+
* [`write(data[, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback)
191194

192195
#### `createConnection()`
193196
`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#createconnection-options).

android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java

+11
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,15 @@ public void setNoDelay(final boolean noDelay) throws IOException {
141141
}
142142
socket.setTcpNoDelay(noDelay);
143143
}
144+
145+
/**
146+
* @param enable `true` to enable keep-alive functionality
147+
*/
148+
public void setKeepAlive(final boolean enable, final int initialDelay) throws IOException {
149+
if (socket == null) {
150+
throw new IOException("Socket is not connected.");
151+
}
152+
// `initialDelay` is ignored
153+
socket.setKeepAlive(enable);
154+
}
144155
}

android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java

+16
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ protected void doInBackgroundGuarded(Void... params) {
164164
}.executeOnExecutor(executorService);
165165
}
166166

167+
@SuppressWarnings("unused")
167168
@ReactMethod
168169
public void setNoDelay(@NonNull final Integer cId, final boolean noDelay) {
169170
final TcpSocketClient client = socketClients.get(cId);
@@ -178,6 +179,21 @@ public void setNoDelay(@NonNull final Integer cId, final boolean noDelay) {
178179
}
179180
}
180181

182+
@SuppressWarnings("unused")
183+
@ReactMethod
184+
public void setKeepAlive(@NonNull final Integer cId, final boolean enable, final int initialDelay) {
185+
final TcpSocketClient client = socketClients.get(cId);
186+
if (client == null) {
187+
onError(cId, TAG + "socket not found.");
188+
return;
189+
}
190+
try {
191+
client.setKeepAlive(enable, initialDelay);
192+
} catch (IOException e) {
193+
onError(cId, e.getMessage());
194+
}
195+
}
196+
181197
private void requestNetwork(final int transportType) throws InterruptedException {
182198
final NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
183199
requestBuilder.addTransportType(transportType);

examples/tcpsockets/ios/Podfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ PODS:
233233
- React-cxxreact (= 0.62.1)
234234
- React-jsi (= 0.62.1)
235235
- React-jsinspector (0.62.1)
236-
- react-native-tcp-socket (3.4.2):
236+
- react-native-tcp-socket (4.1.0):
237237
- CocoaAsyncSocket
238238
- React
239239
- React-RCTActionSheet (0.62.1):
@@ -430,7 +430,7 @@ SPEC CHECKSUMS:
430430
React-jsi: 600d8e42510c3254fd2abd702f4b9d3f598d8f52
431431
React-jsiexecutor: e9698dee4fd43ceb44832baf15d5745f455b0157
432432
React-jsinspector: f74a62727e5604119abd4a1eda52c0a12144bcd5
433-
react-native-tcp-socket: a100fffbe7c96f92f457fa7fad6a29ec24bb8187
433+
react-native-tcp-socket: 7ae44fe823a4c8e73f66e4562fceef392f94ce13
434434
React-RCTActionSheet: af8f28dd82fec89b8fe29637b8c779829e016a88
435435
React-RCTAnimation: 0d21fff7c20fb8ee41de5f2ebb63221127febd96
436436
React-RCTBlob: 9496bd93130b22069bfbc5d35e98653dae7c35c6

examples/tcpsockets/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"dependencies": {
1515
"react": "16.11.0",
1616
"react-native": "0.62.1",
17-
"react-native-tcp-socket": "^3.5.0"
17+
"react-native-tcp-socket": "^4.1.0"
1818
},
1919
"devDependencies": {
2020
"@babel/core": "^7.7.2",

ios/TcpSocketClient.h

+2
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,6 @@ typedef enum RCTTCPError RCTTCPError;
9494

9595
- (void)setNoDelay:(BOOL)noDelay;
9696

97+
- (void)setKeepAlive:(BOOL)enable initialDelay:(int)initialDelay;
98+
9799
@end

ios/TcpSocketClient.m

+15-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,21 @@ - (void)setNoDelay:(BOOL)noDelay
132132
int on = noDelay ? 1 : 0;
133133
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)) == -1) {
134134
/* TODO: handle error */
135-
RCTLogWarn(@"setNoDelay caused an unexpected error");
135+
RCTLogWarn(@"react-native-tcp-socket: setNoDelay() caused an unexpected error");
136+
}
137+
}];
138+
}
139+
140+
- (void)setKeepAlive:(BOOL)enable initialDelay:(int)initialDelay
141+
{
142+
[_tcpSocket performBlock:^{
143+
int fd = [self->_tcpSocket socketFD];
144+
int on = enable ? 1 : 0;
145+
int enableKA = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
146+
// `initialDelay` is ignored
147+
if (enableKA == -1) {
148+
/* TODO: handle error */
149+
RCTLogWarn(@"react-native-tcp-socket: setKeepAlive() caused an unexpected error");
136150
}
137151
}];
138152
}

ios/TcpSockets.m

+7
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ - (TcpSocketClient *)createSocket:(nonnull NSNumber*)cId
123123
[client setNoDelay:noDelay];
124124
}
125125

126+
RCT_EXPORT_METHOD(setKeepAlive:(nonnull NSNumber*)cId enable:(BOOL)enable initialDelay:(int)initialDelay) {
127+
TcpSocketClient* client = [self findClient:cId];
128+
if (!client) return;
129+
130+
[client setKeepAlive:enable initialDelay:initialDelay];
131+
}
132+
126133
- (void)onConnect:(TcpSocketClient*) client
127134
{
128135
[self sendEventWithName:@"connect"

src/TcpSocket.js

+30-1
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,39 @@ export default class TcpSocket extends EventEmitter {
162162
*
163163
* Passing `true` for `noDelay` or not passing an argument will disable Nagle's algorithm for the socket. Passing false for noDelay will enable Nagle's algorithm.
164164
*
165-
* @param {boolean} noDelay
165+
* @param {boolean} noDelay Default: `true`
166166
*/
167167
setNoDelay(noDelay = true) {
168+
if (this._state != STATE.CONNECTED) {
169+
this.once('connect', () => this.setNoDelay(noDelay));
170+
return this;
171+
}
168172
Sockets.setNoDelay(this._id, noDelay);
173+
return this;
174+
}
175+
176+
/**
177+
* Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket.
178+
*
179+
* `initialDelay` is ignored.
180+
*
181+
* @param {boolean} enable Default: `false`
182+
* @param {number} initialDelay ***IGNORED**. Default: `0`
183+
*/
184+
setKeepAlive(enable = false, initialDelay = 0) {
185+
if (this._state != STATE.CONNECTED) {
186+
this.once('connect', () => this.setKeepAlive(enable, initialDelay));
187+
return this;
188+
}
189+
190+
if (initialDelay !== 0) {
191+
console.warn(
192+
'react-native-tcp-socket: initialDelay param in socket.setKeepAlive() is ignored'
193+
);
194+
}
195+
196+
Sockets.setKeepAlive(this._id, enable, Math.floor(initialDelay));
197+
return this;
169198
}
170199

171200
address() {

0 commit comments

Comments
 (0)