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 setKeepAlive() method #62

Merged
merged 12 commits into from
Jul 6, 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
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ To use this library you need to ensure you are using the correct version of Reac

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

## Usage
Expand Down Expand Up @@ -184,10 +184,13 @@ Here are listed all methods implemented in `react-native-tcp-socket`, their func
### TcpSocket
* **Methods:**
* **[`TcpSocket.createConnection(options[, callback])`](#createconnection)**
* [`write(data[, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback)
* [`address()`](https://nodejs.org/api/net.html#net_socket_address)
* [`destroy([error])`](https://nodejs.org/api/net.html#net_socket_destroy_error)
* [`end([data][, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_end_data_encoding_callback)
* [`setKeepAlive([enable][, initialDelay])`](https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) - _`initialDelay` is ignored_
* [`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)
* [`write(data[, encoding][, callback])`](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback)

#### `createConnection()`
`createConnection(options[, callback])` creates a TCP connection using the given [`options`](#createconnection-options).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,15 @@ public void setNoDelay(final boolean noDelay) throws IOException {
}
socket.setTcpNoDelay(noDelay);
}

/**
* @param enable `true` to enable keep-alive functionality
*/
public void setKeepAlive(final boolean enable, final int initialDelay) throws IOException {
if (socket == null) {
throw new IOException("Socket is not connected.");
}
// `initialDelay` is ignored
socket.setKeepAlive(enable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ protected void doInBackgroundGuarded(Void... params) {
}.executeOnExecutor(executorService);
}

@SuppressWarnings("unused")
@ReactMethod
public void setNoDelay(@NonNull final Integer cId, final boolean noDelay) {
final TcpSocketClient client = socketClients.get(cId);
Expand All @@ -178,6 +179,21 @@ public void setNoDelay(@NonNull final Integer cId, final boolean noDelay) {
}
}

@SuppressWarnings("unused")
@ReactMethod
public void setKeepAlive(@NonNull final Integer cId, final boolean enable, final int initialDelay) {
final TcpSocketClient client = socketClients.get(cId);
if (client == null) {
onError(cId, TAG + "socket not found.");
return;
}
try {
client.setKeepAlive(enable, initialDelay);
} catch (IOException e) {
onError(cId, e.getMessage());
}
}

private void requestNetwork(final int transportType) throws InterruptedException {
final NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
requestBuilder.addTransportType(transportType);
Expand Down
4 changes: 2 additions & 2 deletions examples/tcpsockets/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ PODS:
- React-cxxreact (= 0.62.1)
- React-jsi (= 0.62.1)
- React-jsinspector (0.62.1)
- react-native-tcp-socket (3.4.2):
- react-native-tcp-socket (4.1.0):
- CocoaAsyncSocket
- React
- React-RCTActionSheet (0.62.1):
Expand Down Expand Up @@ -430,7 +430,7 @@ SPEC CHECKSUMS:
React-jsi: 600d8e42510c3254fd2abd702f4b9d3f598d8f52
React-jsiexecutor: e9698dee4fd43ceb44832baf15d5745f455b0157
React-jsinspector: f74a62727e5604119abd4a1eda52c0a12144bcd5
react-native-tcp-socket: a100fffbe7c96f92f457fa7fad6a29ec24bb8187
react-native-tcp-socket: 7ae44fe823a4c8e73f66e4562fceef392f94ce13
React-RCTActionSheet: af8f28dd82fec89b8fe29637b8c779829e016a88
React-RCTAnimation: 0d21fff7c20fb8ee41de5f2ebb63221127febd96
React-RCTBlob: 9496bd93130b22069bfbc5d35e98653dae7c35c6
Expand Down
2 changes: 1 addition & 1 deletion examples/tcpsockets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dependencies": {
"react": "16.11.0",
"react-native": "0.62.1",
"react-native-tcp-socket": "^3.5.0"
"react-native-tcp-socket": "^4.1.0"
},
"devDependencies": {
"@babel/core": "^7.7.2",
Expand Down
2 changes: 2 additions & 0 deletions ios/TcpSocketClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,6 @@ typedef enum RCTTCPError RCTTCPError;

- (void)setNoDelay:(BOOL)noDelay;

- (void)setKeepAlive:(BOOL)enable initialDelay:(int)initialDelay;

@end
16 changes: 15 additions & 1 deletion ios/TcpSocketClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,21 @@ - (void)setNoDelay:(BOOL)noDelay
int on = noDelay ? 1 : 0;
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)) == -1) {
/* TODO: handle error */
RCTLogWarn(@"setNoDelay caused an unexpected error");
RCTLogWarn(@"react-native-tcp-socket: setNoDelay() caused an unexpected error");
}
}];
}

- (void)setKeepAlive:(BOOL)enable initialDelay:(int)initialDelay
{
[_tcpSocket performBlock:^{
int fd = [self->_tcpSocket socketFD];
int on = enable ? 1 : 0;
int enableKA = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
// `initialDelay` is ignored
if (enableKA == -1) {
/* TODO: handle error */
RCTLogWarn(@"react-native-tcp-socket: setKeepAlive() caused an unexpected error");
}
}];
}
Expand Down
7 changes: 7 additions & 0 deletions ios/TcpSockets.m
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ - (TcpSocketClient *)createSocket:(nonnull NSNumber*)cId
[client setNoDelay:noDelay];
}

RCT_EXPORT_METHOD(setKeepAlive:(nonnull NSNumber*)cId enable:(BOOL)enable initialDelay:(int)initialDelay) {
TcpSocketClient* client = [self findClient:cId];
if (!client) return;

[client setKeepAlive:enable initialDelay:initialDelay];
}

- (void)onConnect:(TcpSocketClient*) client
{
[self sendEventWithName:@"connect"
Expand Down
31 changes: 30 additions & 1 deletion src/TcpSocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,39 @@ export default class TcpSocket extends EventEmitter {
*
* 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.
*
* @param {boolean} noDelay
* @param {boolean} noDelay Default: `true`
*/
setNoDelay(noDelay = true) {
if (this._state != STATE.CONNECTED) {
this.once('connect', () => this.setNoDelay(noDelay));
return this;
}
Sockets.setNoDelay(this._id, noDelay);
return this;
}

/**
* Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket.
*
* `initialDelay` is ignored.
*
* @param {boolean} enable Default: `false`
* @param {number} initialDelay ***IGNORED**. Default: `0`
*/
setKeepAlive(enable = false, initialDelay = 0) {
if (this._state != STATE.CONNECTED) {
this.once('connect', () => this.setKeepAlive(enable, initialDelay));
return this;
}

if (initialDelay !== 0) {
console.warn(
'react-native-tcp-socket: initialDelay param in socket.setKeepAlive() is ignored'
);
}

Sockets.setKeepAlive(this._id, enable, Math.floor(initialDelay));
return this;
}

address() {
Expand Down