Now we've got everything prettified!

This commit is contained in:
Scott Nonnenberg 2018-05-02 09:51:22 -07:00
parent 754d65ae2e
commit a0ed993b42
30 changed files with 3562 additions and 2873 deletions

View file

@ -1,7 +1,7 @@
;(function(){
'use strict';
(function() {
'use strict';
/*
/*
* WebSocket-Resources
*
* Create a request-response interface over websockets using the
@ -23,212 +23,233 @@
*
*/
var Request = function(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;
var Request = function(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) {
var 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;
}
};
var IncomingWebSocketRequest = function(options) {
var request = new Request(options);
var socket = options.socket;
this.verb = request.verb;
this.path = request.path;
this.body = request.body;
this.respond = function(status, message) {
socket.send(
new textsecure.protobuf.WebSocketMessage({
type: textsecure.protobuf.WebSocketMessage.Type.RESPONSE,
response: { id: request.id, message: message, status: status }
}).encode().toArrayBuffer()
);
};
};
var outgoing = {};
var OutgoingWebSocketRequest = function(options, socket) {
var request = new Request(options);
outgoing[request.id] = request;
socket.send(
new textsecure.protobuf.WebSocketMessage({
type: textsecure.protobuf.WebSocketMessage.Type.REQUEST,
request: {
verb : request.verb,
path : request.path,
body : request.body,
id : request.id
}
}).encode().toArrayBuffer()
);
};
window.WebSocketResource = function(socket, opts) {
opts = opts || {};
var handleRequest = opts.handleRequest;
if (typeof handleRequest !== 'function') {
handleRequest = function(request) {
request.respond(404, 'Not found');
};
}
this.sendRequest = function(options) {
return new OutgoingWebSocketRequest(options, socket);
};
socket.onmessage = function(socketMessage) {
var blob = socketMessage.data;
var handleArrayBuffer = function(buffer) {
var message = textsecure.protobuf.WebSocketMessage.decode(buffer);
if (message.type === textsecure.protobuf.WebSocketMessage.Type.REQUEST ) {
handleRequest(
new IncomingWebSocketRequest({
verb : message.request.verb,
path : message.request.path,
body : message.request.body,
id : message.request.id,
socket : socket
})
);
}
else if (message.type === textsecure.protobuf.WebSocketMessage.Type.RESPONSE ) {
var response = message.response;
var request = outgoing[response.id];
if (request) {
request.response = response;
var callback = request.error;
if (response.status >= 200 && response.status < 300) {
callback = request.success;
}
if (typeof callback === 'function') {
callback(response.message, response.status, request);
}
} else {
throw 'Received response for unknown request ' + message.response.id;
}
}
};
if (blob instanceof ArrayBuffer) {
handleArrayBuffer(blob);
} else {
var reader = new FileReader();
reader.onload = function() {
handleArrayBuffer(reader.result);
};
reader.readAsArrayBuffer(blob);
}
};
if (opts.keepalive) {
this.keepalive = new KeepAlive(this, {
path : opts.keepalive.path,
disconnect : opts.keepalive.disconnect
});
var resetKeepAliveTimer = this.keepalive.reset.bind(this.keepalive);
socket.addEventListener('open', resetKeepAliveTimer);
socket.addEventListener('message', resetKeepAliveTimer);
socket.addEventListener('close', this.keepalive.stop.bind(this.keepalive));
}
socket.addEventListener('close', function() {
this.closed = true;
}.bind(this))
this.close = function(code, reason) {
if (this.closed) {
return;
}
console.log('WebSocketResource.close()');
if (!code) {
code = 3000;
}
if (this.keepalive) {
this.keepalive.stop();
}
socket.close(code, reason);
socket.onmessage = null;
// On linux the socket can wait a long time to emit its close event if we've
// lost the internet connection. On the order of minutes. This speeds that
// process up.
setTimeout(function() {
if (this.closed) {
return;
}
this.closed = true;
console.log('Dispatching our own socket close event');
var ev = new Event('close');
ev.code = code;
ev.reason = reason;
this.dispatchEvent(ev);
}.bind(this), 1000);
};
};
window.WebSocketResource.prototype = new textsecure.EventTarget();
function KeepAlive(websocketResource, opts) {
if (websocketResource instanceof WebSocketResource) {
opts = opts || {};
this.path = opts.path;
if (this.path === undefined) {
this.path = '/';
}
this.disconnect = opts.disconnect;
if (this.disconnect === undefined) {
this.disconnect = true;
}
this.wsr = websocketResource;
} else {
throw new TypeError('KeepAlive expected a WebSocketResource');
}
if (this.id === undefined) {
var bits = new Uint32Array(2);
window.crypto.getRandomValues(bits);
this.id = dcodeIO.Long.fromBits(bits[0], bits[1], true);
}
KeepAlive.prototype = {
constructor: KeepAlive,
stop: function() {
clearTimeout(this.keepAliveTimer);
clearTimeout(this.disconnectTimer);
},
reset: function() {
clearTimeout(this.keepAliveTimer);
clearTimeout(this.disconnectTimer);
this.keepAliveTimer = setTimeout(function() {
if (this.disconnect) {
// automatically disconnect if server doesn't ack
this.disconnectTimer = setTimeout(function() {
clearTimeout(this.keepAliveTimer);
this.wsr.close(3001, 'No response to keepalive request');
}.bind(this), 1000);
} else {
this.reset();
}
console.log('Sending a keepalive message');
this.wsr.sendRequest({
verb: 'GET',
path: this.path,
success: this.reset.bind(this)
});
}.bind(this), 55000);
if (this.body === undefined) {
this.body = null;
}
};
var IncomingWebSocketRequest = function(options) {
var request = new Request(options);
var socket = options.socket;
this.verb = request.verb;
this.path = request.path;
this.body = request.body;
this.respond = function(status, message) {
socket.send(
new textsecure.protobuf.WebSocketMessage({
type: textsecure.protobuf.WebSocketMessage.Type.RESPONSE,
response: { id: request.id, message: message, status: status },
})
.encode()
.toArrayBuffer()
);
};
};
var outgoing = {};
var OutgoingWebSocketRequest = function(options, socket) {
var request = new Request(options);
outgoing[request.id] = request;
socket.send(
new textsecure.protobuf.WebSocketMessage({
type: textsecure.protobuf.WebSocketMessage.Type.REQUEST,
request: {
verb: request.verb,
path: request.path,
body: request.body,
id: request.id,
},
})
.encode()
.toArrayBuffer()
);
};
window.WebSocketResource = function(socket, opts) {
opts = opts || {};
var handleRequest = opts.handleRequest;
if (typeof handleRequest !== 'function') {
handleRequest = function(request) {
request.respond(404, 'Not found');
};
}
this.sendRequest = function(options) {
return new OutgoingWebSocketRequest(options, socket);
};
}());
socket.onmessage = function(socketMessage) {
var blob = socketMessage.data;
var handleArrayBuffer = function(buffer) {
var message = textsecure.protobuf.WebSocketMessage.decode(buffer);
if (
message.type === textsecure.protobuf.WebSocketMessage.Type.REQUEST
) {
handleRequest(
new IncomingWebSocketRequest({
verb: message.request.verb,
path: message.request.path,
body: message.request.body,
id: message.request.id,
socket: socket,
})
);
} else if (
message.type === textsecure.protobuf.WebSocketMessage.Type.RESPONSE
) {
var response = message.response;
var request = outgoing[response.id];
if (request) {
request.response = response;
var callback = request.error;
if (response.status >= 200 && response.status < 300) {
callback = request.success;
}
if (typeof callback === 'function') {
callback(response.message, response.status, request);
}
} else {
throw 'Received response for unknown request ' +
message.response.id;
}
}
};
if (blob instanceof ArrayBuffer) {
handleArrayBuffer(blob);
} else {
var reader = new FileReader();
reader.onload = function() {
handleArrayBuffer(reader.result);
};
reader.readAsArrayBuffer(blob);
}
};
if (opts.keepalive) {
this.keepalive = new KeepAlive(this, {
path: opts.keepalive.path,
disconnect: opts.keepalive.disconnect,
});
var resetKeepAliveTimer = this.keepalive.reset.bind(this.keepalive);
socket.addEventListener('open', resetKeepAliveTimer);
socket.addEventListener('message', resetKeepAliveTimer);
socket.addEventListener(
'close',
this.keepalive.stop.bind(this.keepalive)
);
}
socket.addEventListener(
'close',
function() {
this.closed = true;
}.bind(this)
);
this.close = function(code, reason) {
if (this.closed) {
return;
}
console.log('WebSocketResource.close()');
if (!code) {
code = 3000;
}
if (this.keepalive) {
this.keepalive.stop();
}
socket.close(code, reason);
socket.onmessage = null;
// On linux the socket can wait a long time to emit its close event if we've
// lost the internet connection. On the order of minutes. This speeds that
// process up.
setTimeout(
function() {
if (this.closed) {
return;
}
this.closed = true;
console.log('Dispatching our own socket close event');
var ev = new Event('close');
ev.code = code;
ev.reason = reason;
this.dispatchEvent(ev);
}.bind(this),
1000
);
};
};
window.WebSocketResource.prototype = new textsecure.EventTarget();
function KeepAlive(websocketResource, opts) {
if (websocketResource instanceof WebSocketResource) {
opts = opts || {};
this.path = opts.path;
if (this.path === undefined) {
this.path = '/';
}
this.disconnect = opts.disconnect;
if (this.disconnect === undefined) {
this.disconnect = true;
}
this.wsr = websocketResource;
} else {
throw new TypeError('KeepAlive expected a WebSocketResource');
}
}
KeepAlive.prototype = {
constructor: KeepAlive,
stop: function() {
clearTimeout(this.keepAliveTimer);
clearTimeout(this.disconnectTimer);
},
reset: function() {
clearTimeout(this.keepAliveTimer);
clearTimeout(this.disconnectTimer);
this.keepAliveTimer = setTimeout(
function() {
if (this.disconnect) {
// automatically disconnect if server doesn't ack
this.disconnectTimer = setTimeout(
function() {
clearTimeout(this.keepAliveTimer);
this.wsr.close(3001, 'No response to keepalive request');
}.bind(this),
1000
);
} else {
this.reset();
}
console.log('Sending a keepalive message');
this.wsr.sendRequest({
verb: 'GET',
path: this.path,
success: this.reset.bind(this),
});
}.bind(this),
55000
);
},
};
})();