Add support for sending binary data in websockets

Summary:This is a reprise of #6327, but with iOS 7.0 compatibility and less `package.json` changes.

**Test Plan:** Load WebSocketExample in UIExplorer app and start websocket test server script (both provided in #6889) and test sending binary data on both iOS and Android
Closes https://github.com/facebook/react-native/pull/6961

Differential Revision: D3202022

Pulled By: mkonicek

fb-gh-sync-id: 38843d0a9c0172971c5c70a5139ded04042b280a
fbshipit-source-id: 38843d0a9c0172971c5c70a5139ded04042b280a
This commit is contained in:
Philipp von Weitershausen 2016-04-20 08:52:22 -07:00 committed by Facebook Github Bot 8
parent ad15b74aae
commit ed930b4710
4 changed files with 54 additions and 6 deletions

View File

@ -31,7 +31,7 @@ const respondWithBinary = process.argv.indexOf('--binary') !== -1;
const server = new WebSocket.Server({port: 5555});
server.on('connection', (ws) => {
ws.on('message', (message) => {
console.log('Received message: %s', message);
console.log('Received message:', message);
if (respondWithBinary) {
message = new Buffer(message);
}

View File

@ -67,6 +67,12 @@ RCT_EXPORT_METHOD(send:(NSString *)message socketID:(nonnull NSNumber *)socketID
[_sockets[socketID] send:message];
}
RCT_EXPORT_METHOD(sendBinary:(NSString *)base64String socketID:(nonnull NSNumber *)socketID)
{
NSData *message = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
[_sockets[socketID] send:message];
}
RCT_EXPORT_METHOD(close:(nonnull NSNumber *)socketID)
{
[_sockets[socketID] close];

View File

@ -21,6 +21,18 @@ const base64 = require('base64-js');
import type EventSubscription from 'EventSubscription';
type ArrayBufferView =
Int8Array |
Uint8Array |
Uint8ClampedArray |
Int16Array |
Uint16Array |
Int32Array |
Uint32Array |
Float32Array |
Float64Array |
DataView;
const CONNECTING = 0;
const OPEN = 1;
const CLOSING = 2;
@ -94,18 +106,31 @@ class WebSocket extends EventTarget(WEBSOCKET_EVENTS) {
this._close(code, reason);
}
send(data: any): void {
send(data: string | ArrayBuffer | ArrayBufferView): void {
if (this.readyState === this.CONNECTING) {
throw new Error('INVALID_STATE_ERR');
}
if (typeof data === 'string') {
RCTWebSocketModule.send(data, this._socketId);
} else if (data instanceof ArrayBuffer) {
console.warn('Sending ArrayBuffers is not yet supported');
} else {
throw new Error('Not supported data type');
return;
}
// Maintain iOS 7 compatibility which doesn't have JS typed arrays.
if (typeof ArrayBuffer !== 'undefined' &&
typeof Uint8Array !== 'undefined') {
if (ArrayBuffer.isView(data)) {
// $FlowFixMe: no way to assert that 'data' is indeed an ArrayBufferView now
data = data.buffer;
}
if (data instanceof ArrayBuffer) {
data = base64.fromByteArray(new Uint8Array(data));
RCTWebSocketModule.sendBinary(data, this._socketId);
return;
}
}
throw new Error('Unsupported data type');
}
_close(code?: number, reason?: string): void {

View File

@ -44,6 +44,7 @@ import java.util.concurrent.TimeUnit;
import okio.Buffer;
import okio.BufferedSource;
import okio.ByteString;
public class WebSocketModule extends ReactContextBaseJavaModule {
@ -216,6 +217,22 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
}
}
@ReactMethod
public void sendBinary(String base64String, int id) {
WebSocket client = mWebSocketConnections.get(id);
if (client == null) {
// This is a programmer error
throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id);
}
try {
client.sendMessage(
WebSocket.PayloadType.BINARY,
new Buffer().write(ByteString.decodeBase64(base64String)));
} catch (IOException | IllegalStateException e) {
notifyWebSocketFailed(id, e.getMessage());
}
}
private void notifyWebSocketFailed(int id, String message) {
WritableMap params = Arguments.createMap();
params.putInt("id", id);