You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.4 KiB
JavaScript
108 lines
3.4 KiB
JavaScript
/* global window, dcodeIO, textsecure, StringView */
|
|
|
|
// eslint-disable-next-line func-names
|
|
(function () {
|
|
let server;
|
|
const development = (window.getEnvironment() !== 'production');
|
|
const pollTime = development ? 100 : 5000;
|
|
|
|
function stringToArrayBufferBase64(string) {
|
|
return dcodeIO.ByteBuffer.wrap(string, 'base64').toArrayBuffer();
|
|
}
|
|
|
|
const Response = function Response(options) {
|
|
this.verb = options.verb || options.type;
|
|
this.path = options.path || options.url;
|
|
this.body = options.body || options.data;
|
|
this.success = options.success;
|
|
this.error = options.error;
|
|
this.id = options.id;
|
|
|
|
if (this.id === undefined) {
|
|
const bits = new Uint32Array(2);
|
|
window.crypto.getRandomValues(bits);
|
|
this.id = dcodeIO.Long.fromBits(bits[0], bits[1], true);
|
|
}
|
|
|
|
if (this.body === undefined) {
|
|
this.body = null;
|
|
}
|
|
};
|
|
|
|
const IncomingHttpResponse = function IncomingHttpResponse(options) {
|
|
const request = new Response(options);
|
|
|
|
this.verb = request.verb;
|
|
this.path = request.path;
|
|
this.body = request.body;
|
|
|
|
this.respond = (status, message) => {
|
|
// Mock websocket response
|
|
window.log.info(status, message);
|
|
};
|
|
};
|
|
|
|
const filterIncomingMessages = async function filterIncomingMessages(messages) {
|
|
const incomingHashes = messages.map(m => m.hash);
|
|
const dupHashes = await window.Signal.Data.getSeenMessagesByHashList(incomingHashes);
|
|
const newMessages = messages.filter(m => !dupHashes.includes(m.hash));
|
|
const newHashes = newMessages.map(m => ({
|
|
expiresAt: m.expiration,
|
|
hash: m.hash,
|
|
}));
|
|
await window.Signal.Data.saveSeenMessageHashes(newHashes);
|
|
return newMessages;
|
|
};
|
|
|
|
window.HttpResource = function HttpResource(_server, opts = {}) {
|
|
server = _server;
|
|
let { handleRequest } = opts;
|
|
if (typeof handleRequest !== 'function') {
|
|
handleRequest = request => request.respond(404, 'Not found');
|
|
};
|
|
let connected = false;
|
|
|
|
this.startPolling = async function pollServer(callBack) {
|
|
const myKeys = await textsecure.storage.protocol.getIdentityKeyPair();
|
|
const pubKey = StringView.arrayBufferToHex(myKeys.pubKey)
|
|
let result;
|
|
try {
|
|
result = await server.retrieveMessages(pubKey);
|
|
connected = true;
|
|
} catch (err) {
|
|
connected = false;
|
|
setTimeout(() => { pollServer(callBack); }, pollTime);
|
|
return;
|
|
}
|
|
if (typeof callBack === 'function') {
|
|
callBack(connected);
|
|
}
|
|
if (!result.messages) {
|
|
setTimeout(() => { pollServer(callBack); }, pollTime);
|
|
return;
|
|
}
|
|
const newMessages = await filterIncomingMessages(result.messages);
|
|
newMessages.forEach(async message => {
|
|
const { data } = message;
|
|
const dataPlaintext = stringToArrayBufferBase64(data);
|
|
const messageBuf = textsecure.protobuf.WebSocketMessage.decode(dataPlaintext);
|
|
if (messageBuf.type === textsecure.protobuf.WebSocketMessage.Type.REQUEST) {
|
|
handleRequest(
|
|
new IncomingHttpResponse({
|
|
verb: messageBuf.request.verb,
|
|
path: messageBuf.request.path,
|
|
body: messageBuf.request.body,
|
|
id: messageBuf.request.id,
|
|
})
|
|
);
|
|
}
|
|
});
|
|
setTimeout(() => { pollServer(callBack); }, pollTime);
|
|
};
|
|
|
|
this.isConnected = function isConnected() {
|
|
return connected;
|
|
}
|
|
};
|
|
})();
|