/* vim: ts=4:sw=4:expandtab * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ ;(function(){ 'use strict'; /* * WebSocket-Resources * * Create a request-response interface over websockets using the * WebSocket-Resources sub-protocol[1]. * * var client = new WebSocketResource(socket, function(request) { * request.respond(200, 'OK'); * }); * * client.sendRequest({ * verb: 'PUT', * path: '/v1/messages', * body: '{ some: "json" }', * success: function(message, status, request) {...}, * error: function(message, status, request) {...} * }); * * 1. https://github.com/WhisperSystems/WebSocket-Resources * */ 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); } }; 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, handleRequest) { this.sendRequest = function(options) { return new OutgoingWebSocketRequest(options, socket); }; socket.onmessage = function(socketMessage) { var blob = socketMessage.data; var reader = new FileReader(); reader.onload = function() { var message = textsecure.protobuf.WebSocketMessage.decode(reader.result); 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; } } }; reader.readAsArrayBuffer(blob); }; }; }());