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.
138 lines
3.8 KiB
JavaScript
138 lines
3.8 KiB
JavaScript
/* global window, dcodeIO, textsecure */
|
|
|
|
// eslint-disable-next-line func-names
|
|
(function() {
|
|
let server;
|
|
const EXHAUSTED_SNODES_RETRY_DELAY = 5000;
|
|
const NUM_CONCURRENT_CONNECTIONS = 3;
|
|
|
|
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);
|
|
};
|
|
};
|
|
|
|
window.HttpResource = function HttpResource(_server, opts = {}) {
|
|
server = _server;
|
|
let { handleRequest } = opts;
|
|
if (typeof handleRequest !== 'function') {
|
|
handleRequest = request => request.respond(404, 'Not found');
|
|
}
|
|
let connected = true;
|
|
this.calledStop = false;
|
|
let resolveStopPolling;
|
|
const stopPolling = new Promise(res => {
|
|
resolveStopPolling = res;
|
|
});
|
|
|
|
this.handleMessage = (message, options = {}) => {
|
|
try {
|
|
const dataPlaintext = stringToArrayBufferBase64(message);
|
|
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,
|
|
}),
|
|
options
|
|
);
|
|
}
|
|
} catch (error) {
|
|
const info = {
|
|
message,
|
|
error: error.message,
|
|
};
|
|
window.log.warn('HTTP-Resources Failed to handle message:', info);
|
|
}
|
|
};
|
|
|
|
this.pollServer = async () => {
|
|
// bg.connect calls mr connect after storage system is ready
|
|
window.log.info('http-resource pollServer start');
|
|
// This blocking call will return only when all attempts
|
|
// at reaching snodes are exhausted or a DNS error occured
|
|
try {
|
|
await server.startLongPolling(
|
|
NUM_CONCURRENT_CONNECTIONS,
|
|
stopPolling,
|
|
messages => {
|
|
connected = true;
|
|
messages.forEach(message => {
|
|
this.handleMessage(message.data);
|
|
});
|
|
}
|
|
);
|
|
} catch (e) {
|
|
// we'll try again anyway
|
|
window.log.error(
|
|
'http-resource pollServer error',
|
|
e.code,
|
|
e.message,
|
|
e.stack
|
|
);
|
|
}
|
|
connected = false;
|
|
|
|
if (this.calledStop) {
|
|
// don't restart
|
|
return;
|
|
}
|
|
|
|
// Exhausted all our snodes urls, trying again later from scratch
|
|
setTimeout(() => {
|
|
window.log.info(
|
|
`http-resource: Exhausted all our snodes urls, trying again in ${EXHAUSTED_SNODES_RETRY_DELAY /
|
|
1000}s from scratch`
|
|
);
|
|
this.pollServer();
|
|
}, EXHAUSTED_SNODES_RETRY_DELAY);
|
|
};
|
|
|
|
this.isConnected = function isConnected() {
|
|
return connected;
|
|
};
|
|
|
|
this.close = () => {
|
|
this.calledStop = true;
|
|
resolveStopPolling(true);
|
|
};
|
|
};
|
|
})();
|