/** * @abstract * @constructor **/ function AbstractRawTCPSocket() { /** @type {Array} */ this.onReadyReadHandlers = []; } /** * @abstract * @return {Promise} **/ AbstractRawTCPSocket.prototype.connect = function() {}; /** * @abstract * @param {string} msg **/ AbstractRawTCPSocket.prototype.write = function(msg) {}; /** * @param {function(string)} onReadyRead **/ AbstractRawTCPSocket.prototype.onReadyRead = function(onReadyRead) { this.onReadyReadHandlers.push(onReadyRead); }; /** @param {string} msg */ AbstractRawTCPSocket.prototype.triggerOnReadyRead = function(msg) { this.onReadyReadHandlers.forEach(function(handler) { handler(msg); }); }; AbstractRawTCPSocket.prototype.close = function() {}; // // This API is not available yet // https://www.w3.org/TR/raw-sockets/ // ///** // * @constructor // * @extends {AbstractRawTCPSocket} // * @param {string} address // * @param {number} port //**/ //function NavigatorRawTCPSocket(address, port) { // AbstractRawTCPSocket.apply(this); // // /** @type {string} */ // this.address = address; // // /** @type {number} */ // this.port = port; //} // //NavigatorRawTCPSocket.prototype = Object.create(AbstractRawTCPSocket); //NavigatorRawTCPSocket.prototype.constructor = NavigatorRawTCPSocket; // //NavigatorRawTCPSocket.prototype.checkPermission = function() { // return navigator.tcpPermission.requestPermission({ remoteAddress: this.address, remotePort: this.port }); //}; // //NavigatorRawTCPSocket.prototype.connect = function() { // this.sock = navigator.TCPSocket(this.address, this.port) //}; // //NavigatorRawTCPSocket.prototype.write = function(str) { //}; // //NavigatorRawTCPSocket.prototype.close = function() { //}; /** * @constructor * @extends {AbstractRawTCPSocket} * @param {string} address * @param {number} port **/ function NativeRawTCPSocket(address, port) { AbstractRawTCPSocket.apply(this); /** * @const * @type {number} **/ this.socketId = NativeRawTCPSocket.sockCount++; NativeRawTCPSocket.sockets[this.socketId] = this; /** @type {string} */ this.address = address; /** @type {number} */ this.port = port; /** @type {{ onSuccess: function(), onReject: function() }|null} */ this.connectPromise; } NativeRawTCPSocket.prototype = Object.create(AbstractRawTCPSocket); NativeRawTCPSocket.prototype.constructor = NativeRawTCPSocket; /** @return {Promise} */ NativeRawTCPSocket.prototype.connect = function() { return new Promise(function(onSuccess, onReject) { this.connectPromise = { onSuccess: onSuccess, onReject: onReject }; __native.TCPConnect(this.socketId, this.address, this.port); }); }; /** @param {boolean} success */ NativeRawTCPSocket.prototype.onConnected = function(success) { if (this.connectPromise) { if (success) this.connectPromise.onSuccess(); else this.connectPromise.onReject(); this.connectPromise = null; } }; /** @param {string} msg */ NativeRawTCPSocket.prototype.write = function(msg) { __native.TCPWrite(this.socketId, msg); }; NativeRawTCPSocket.prototype.close = function() { __native.TCPClose(this.socketId); }; /** @type {number} */ NativeRawTCPSocket.sockCount = 0; NativeRawTCPSocket.sockets = {}; NativeRawTCPSocket.onConnected = function(sockId, success) { NativeRawTCPSocket.sockets[sockId].onConnected(success); }; NativeRawTCPSocket.onReadyRead = function(sockId, msg) { NativeRawTCPSocket.sockets[sockId].triggerOnReadyRead(msg); }; /** * @param {string} address * @param {number} port * @return {AbstractRawTCPSocket|null} **/ function createSocket(address, port) { if (isNative()) return new NativeRawTCPSocket(address, port); // else if (navigator && "tcpPermission" in navigator) // return new NavigatorRawTCPSocket(address, port); return null; // unsupported }