react-native/local-cli/server/util/messageSocket.js
Lukas Piatkowski d8f48d1b51 Refactor the packager server for further protocol changes
Reviewed By: cwdick

Differential Revision: D4543321

fbshipit-source-id: f7d5823b0d340f8ca17b3dd6caf4e158fa918bcf
2017-02-14 09:45:57 -08:00

103 lines
2.7 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
const WebSocketServer = require('ws').Server;
const PROTOCOL_VERSION = 1;
function parseMessage(data, binary) {
if (binary) {
console.error('Expected text message, got binary!');
return undefined;
}
try {
const message = JSON.parse(data);
if (message.version === PROTOCOL_VERSION) {
return message;
}
console.error('Received message had wrong protocol version: '
+ message.version);
} catch (e) {
console.error('Failed to parse the message as JSON:\n' + data);
}
return undefined;
}
function attachToServer(server, path) {
const wss = new WebSocketServer({
server: server,
path: path
});
const clients = new Map();
let nextClientId = 0;
function handleSendBroadcast(broadcasterId, message) {
const forwarded = {
version: PROTOCOL_VERSION,
target: message.target,
action: message.action,
};
for (const [otherId, otherWs] of clients) {
if (otherId !== broadcasterId) {
try {
otherWs.send(JSON.stringify(forwarded));
} catch (e) {
console.error(`Failed to send broadcast to client: '${otherId}' ` +
`due to:\n ${e.toString()}`);
}
}
}
}
wss.on('connection', function(clientWs) {
const clientId = `client#${nextClientId++}`;
function handleCatchedError(message, error) {
const errorMessage = {
target: message.target,
action: message.action === undefined ? 'undefined' : 'defined',
};
console.error(
`Handling message from ${clientId} failed with:\n${error}\n` +
`message:\n${JSON.stringify(errorMessage)}`);
}
clients.set(clientId, clientWs);
clientWs.onclose =
clientWs.onerror = () => {
clientWs.onmessage = null;
clients.delete(clientId);
};
clientWs.onmessage = (event) => {
const message = parseMessage(event.data, event.binary);
if (message === undefined) {
console.error('Received message not matching protocol');
return;
}
try {
handleSendBroadcast(clientId, message);
} catch (e) {
handleCatchedError(message, e.toString());
}
};
});
return {
broadcast: (target, action) => {
handleSendBroadcast(null, {target: target, action: action});
}
};
}
module.exports = {
attachToServer: attachToServer,
parseMessage: parseMessage,
};