define(["sugar-web/env"], function (env) {
|
|
|
|
'use strict';
|
|
|
|
var lastId = 0;
|
|
var callbacks = {};
|
|
var notificationCallbacks = {};
|
|
var client = null;
|
|
var inputStreams = [];
|
|
|
|
function WebSocketClient(environment) {
|
|
this.queue = [];
|
|
this.socket = null;
|
|
|
|
var that = this;
|
|
|
|
env.getEnvironment(function (error, environment) {
|
|
var port = environment.apiSocketPort;
|
|
var socket = new WebSocket("ws://localhost:" + port);
|
|
|
|
socket.binaryType = "arraybuffer";
|
|
|
|
socket.onopen = function () {
|
|
var params = [environment.activityId,
|
|
environment.apiSocketKey];
|
|
|
|
socket.send(JSON.stringify({
|
|
"method": "authenticate",
|
|
"id": "authenticate",
|
|
"params": params
|
|
}));
|
|
|
|
while (that.queue.length > 0) {
|
|
socket.send(that.queue.shift());
|
|
}
|
|
};
|
|
|
|
socket.onmessage = function (message) {
|
|
that.onMessage(message);
|
|
};
|
|
|
|
that.socket = socket;
|
|
});
|
|
}
|
|
|
|
WebSocketClient.prototype.send = function (data) {
|
|
if (this.socket && this.socket.readyState == WebSocket.OPEN) {
|
|
this.socket.send(data);
|
|
} else {
|
|
this.queue.push(data);
|
|
}
|
|
};
|
|
|
|
WebSocketClient.prototype.close = function () {
|
|
this.socket.close();
|
|
};
|
|
|
|
var bus = {};
|
|
|
|
function InputStream() {
|
|
this.streamId = null;
|
|
this.readCallback = null;
|
|
}
|
|
|
|
InputStream.prototype.open = function (callback) {
|
|
var that = this;
|
|
bus.sendMessage("open_stream", [], function (error, result) {
|
|
that.streamId = result[0];
|
|
inputStreams[that.streamId] = that;
|
|
callback(error);
|
|
});
|
|
};
|
|
|
|
InputStream.prototype.read = function (count, callback) {
|
|
if (this.readCallback) {
|
|
throw new Error("Read already in progress");
|
|
}
|
|
|
|
this.readCallback = callback;
|
|
|
|
var buffer = new ArrayBuffer(8);
|
|
|
|
var headerView = new Uint8Array(buffer, 0, 1);
|
|
headerView[0] = this.streamId;
|
|
|
|
var bodyView = new Uint32Array(buffer, 4, 1);
|
|
bodyView[0] = count;
|
|
|
|
bus.sendBinary(buffer);
|
|
};
|
|
|
|
InputStream.prototype.gotData = function (buffer) {
|
|
var callback = this.readCallback;
|
|
|
|
this.readCallback = null;
|
|
|
|
callback(null, buffer);
|
|
};
|
|
|
|
InputStream.prototype.close = function (callback) {
|
|
var that = this;
|
|
|
|
function onStreamClosed(error, result) {
|
|
if (callback) {
|
|
callback(error);
|
|
}
|
|
delete inputStreams[that.streamId];
|
|
}
|
|
|
|
bus.sendMessage("close_stream", [this.streamId], onStreamClosed);
|
|
};
|
|
|
|
function OutputStream() {
|
|
this.streamId = null;
|
|
}
|
|
|
|
OutputStream.prototype.open = function (callback) {
|
|
var that = this;
|
|
bus.sendMessage("open_stream", [], function (error, result) {
|
|
that.streamId = result[0];
|
|
callback(error);
|
|
});
|
|
};
|
|
|
|
OutputStream.prototype.write = function (data) {
|
|
var buffer = new ArrayBuffer(data.byteLength + 1);
|
|
|
|
var bufferView = new Uint8Array(buffer);
|
|
bufferView[0] = this.streamId;
|
|
bufferView.set(new Uint8Array(data), 1);
|
|
|
|
bus.sendBinary(buffer);
|
|
};
|
|
|
|
OutputStream.prototype.close = function (callback) {
|
|
bus.sendMessage("close_stream", [this.streamId], callback);
|
|
};
|
|
|
|
bus.createInputStream = function (callback) {
|
|
return new InputStream();
|
|
};
|
|
|
|
bus.createOutputStream = function (callback) {
|
|
return new OutputStream();
|
|
};
|
|
|
|
bus.sendMessage = function (method, params, callback) {
|
|
var message = {
|
|
"method": method,
|
|
"id": lastId,
|
|
"params": params,
|
|
"jsonrpc": "2.0"
|
|
};
|
|
|
|
if (callback) {
|
|
callbacks[lastId] = callback;
|
|
}
|
|
|
|
client.send(JSON.stringify(message));
|
|
|
|
lastId++;
|
|
};
|
|
|
|
bus.onNotification = function (method, callback) {
|
|
notificationCallbacks[method] = callback;
|
|
};
|
|
|
|
bus.sendBinary = function (buffer, callback) {
|
|
client.send(buffer);
|
|
};
|
|
|
|
bus.listen = function (customClient) {
|
|
if (customClient) {
|
|
client = customClient;
|
|
} else {
|
|
client = new WebSocketClient();
|
|
}
|
|
|
|
client.onMessage = function (message) {
|
|
if (typeof message.data != "string") {
|
|
var dataView = new Uint8Array(message.data);
|
|
var streamId = dataView[0];
|
|
|
|
if (streamId in inputStreams) {
|
|
var inputStream = inputStreams[streamId];
|
|
inputStream.gotData(message.data.slice(1));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
var parsed = JSON.parse(message.data);
|
|
var responseId = parsed.id;
|
|
|
|
if (parsed.method) {
|
|
var notificationCallback = notificationCallbacks[parsed.method];
|
|
if (notificationCallback !== undefined) {
|
|
notificationCallback(parsed.params);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (responseId in callbacks) {
|
|
var callback = callbacks[responseId];
|
|
|
|
if (parsed.error === null) {
|
|
callback(null, parsed.result);
|
|
} else {
|
|
callback(new Error(parsed.error), null);
|
|
}
|
|
|
|
delete callbacks[responseId];
|
|
}
|
|
};
|
|
};
|
|
|
|
bus.close = function () {
|
|
client.close();
|
|
client = null;
|
|
};
|
|
|
|
return bus;
|
|
});
|