366 lines
7.6 KiB
JavaScript
366 lines
7.6 KiB
JavaScript
|
/*
|
||
|
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
const platfNetworkingName = "platformNetworking";
|
||
|
|
||
|
(function() {
|
||
|
|
||
|
const WS_CLOSED = 0;
|
||
|
const WS_CONNECTING = 1;
|
||
|
const WS_CONNECTED = 2;
|
||
|
const WS_FAILED = 3;
|
||
|
|
||
|
function closeSocketImpl() {
|
||
|
this["_socket"].close();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {string} str
|
||
|
*/
|
||
|
function sendStringFrameImpl(str) {
|
||
|
this["_socket"].send(str);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {Uint8Array} bin
|
||
|
*/
|
||
|
function sendBinaryFrameImpl(bin) {
|
||
|
this["_socket"].send(bin);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {number}
|
||
|
*/
|
||
|
function availableFramesImpl() {
|
||
|
return this["_frameCountStr"] + this["_frameCountBin"];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {Object}
|
||
|
*/
|
||
|
function getNextFrameImpl() {
|
||
|
const f = this["_queue"];
|
||
|
if(f) {
|
||
|
if(f["_next"] === f && f["_prev"] === f) {
|
||
|
this["_queue"] = null;
|
||
|
}else {
|
||
|
this["_queue"] = f["_next"];
|
||
|
f["_prev"]["_next"] = f["_next"];
|
||
|
f["_next"]["_prev"] = f["_prev"];
|
||
|
}
|
||
|
f["_next"] = null;
|
||
|
f["_prev"] = null;
|
||
|
if(f["type"] === 0) {
|
||
|
--this["_frameCountStr"];
|
||
|
}else {
|
||
|
--this["_frameCountBin"];
|
||
|
}
|
||
|
return f;
|
||
|
}else {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {Array}
|
||
|
*/
|
||
|
function getAllFramesImpl() {
|
||
|
const len = this["_frameCountStr"] + this["_frameCountBin"];
|
||
|
if(len === 0) {
|
||
|
return null;
|
||
|
}
|
||
|
const ret = new Array(len);
|
||
|
var idx = 0;
|
||
|
var f = this["_queue"];
|
||
|
var g;
|
||
|
const ff = f;
|
||
|
do {
|
||
|
ret[idx++] = f;
|
||
|
g = f["_next"];
|
||
|
f["_next"] = null;
|
||
|
f["_prev"] = null;
|
||
|
f = g;
|
||
|
}while(f !== ff);
|
||
|
this["_queue"] = null;
|
||
|
this["_frameCountStr"] = 0;
|
||
|
this["_frameCountBin"] = 0;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
function clearFramesImpl() {
|
||
|
this["_queue"] = null;
|
||
|
this["_frameCountStr"] = 0;
|
||
|
this["_frameCountBin"] = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {Object} thisObj
|
||
|
* @param {number} type
|
||
|
* @return {Object}
|
||
|
*/
|
||
|
function getNextTypedFrameImpl(thisObj, type) {
|
||
|
var f = thisObj["_queue"];
|
||
|
if(!f) {
|
||
|
return null;
|
||
|
}
|
||
|
var g, h;
|
||
|
const ff = f;
|
||
|
do {
|
||
|
g = f["_next"];
|
||
|
if(f["type"] === type) {
|
||
|
h = f["_prev"];
|
||
|
if(g === f && h === f) {
|
||
|
thisObj["_queue"] = null;
|
||
|
}else {
|
||
|
if(f === ff) {
|
||
|
thisObj["_queue"] = g;
|
||
|
}
|
||
|
h["_next"] = g;
|
||
|
g["_prev"] = h;
|
||
|
}
|
||
|
f["_next"] = null;
|
||
|
f["_prev"] = null;
|
||
|
return f;
|
||
|
}
|
||
|
f = g;
|
||
|
}while(f !== ff);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {Object} thisObj
|
||
|
* @param {number} type
|
||
|
* @param {Array} ret
|
||
|
*/
|
||
|
function getAllTypedFrameImpl(thisObj, type, ret) {
|
||
|
var idx = 0;
|
||
|
var f = thisObj["_queue"];
|
||
|
var g, h;
|
||
|
const ff = f;
|
||
|
do {
|
||
|
g = f["_next"];
|
||
|
if(f["type"] === type) {
|
||
|
ret[idx++] = f;
|
||
|
}
|
||
|
f = g;
|
||
|
}while(f !== ff);
|
||
|
ret.length = idx;
|
||
|
for(var i = 0; i < idx; ++i) {
|
||
|
f = ret[i];
|
||
|
g = f["_next"];
|
||
|
h = f["_prev"];
|
||
|
if(g === f && h === f) {
|
||
|
thisObj["_queue"] = null;
|
||
|
}else {
|
||
|
if(f === thisObj["_queue"]) {
|
||
|
thisObj["_queue"] = g;
|
||
|
}
|
||
|
h["_next"] = g;
|
||
|
g["_prev"] = h;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {number}
|
||
|
*/
|
||
|
function availableStringFramesImpl() {
|
||
|
return this["_frameCountStr"];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {Object}
|
||
|
*/
|
||
|
function getNextStringFrameImpl() {
|
||
|
const len = this["_frameCountStr"];
|
||
|
if(len === 0) {
|
||
|
return null;
|
||
|
}
|
||
|
const ret = getNextTypedFrameImpl(this, 0);
|
||
|
if(!ret) {
|
||
|
this["_frameCountStr"] = 0;
|
||
|
}else {
|
||
|
--this["_frameCountStr"];
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {Array}
|
||
|
*/
|
||
|
function getAllStringFramesImpl() {
|
||
|
const len = this["_frameCountStr"];
|
||
|
if(len === 0) {
|
||
|
return null;
|
||
|
}
|
||
|
const ret = new Array(len);
|
||
|
getAllTypedFrameImpl(this, 0, ret);
|
||
|
this["_frameCountStr"] = 0;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
function clearStringFramesImpl() {
|
||
|
const len = this["_frameCountStr"];
|
||
|
if(len === 0) {
|
||
|
return null;
|
||
|
}
|
||
|
const ret = new Array(len);
|
||
|
getAllTypedFrameImpl(this, 0, ret);
|
||
|
this["_frameCountStr"] = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {number}
|
||
|
*/
|
||
|
function availableBinaryFramesImpl() {
|
||
|
return this["_frameCountBin"];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {Object}
|
||
|
*/
|
||
|
function getNextBinaryFrameImpl() {
|
||
|
const len = this["_frameCountBin"];
|
||
|
if(len === 0) {
|
||
|
return null;
|
||
|
}
|
||
|
const ret = getNextTypedFrameImpl(this, 1);
|
||
|
if(!ret) {
|
||
|
this["_frameCountBin"] = 0;
|
||
|
}else {
|
||
|
--this["_frameCountBin"];
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {Array}
|
||
|
*/
|
||
|
function getAllBinaryFramesImpl() {
|
||
|
const len = this["_frameCountBin"];
|
||
|
if(len === 0) {
|
||
|
return null;
|
||
|
}
|
||
|
const ret = new Array(len);
|
||
|
getAllTypedFrameImpl(this, 1, ret);
|
||
|
this["_frameCountBin"] = 0;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
function clearBinaryFramesImpl() {
|
||
|
const len = this["_frameCountBin"];
|
||
|
if(len === 0) {
|
||
|
return null;
|
||
|
}
|
||
|
const ret = new Array(len);
|
||
|
getAllTypedFrameImpl(this, 1, ret);
|
||
|
this["_frameCountBin"] = 0;
|
||
|
}
|
||
|
|
||
|
function addRecievedFrameImpl(dat) {
|
||
|
const isStr = (typeof dat === "string");
|
||
|
const itm = {
|
||
|
"type": (isStr ? 0 : 1),
|
||
|
"data": dat,
|
||
|
"timestamp": performance.now(),
|
||
|
"_next": null,
|
||
|
"_prev": null
|
||
|
};
|
||
|
const first = this["_queue"];
|
||
|
if(!first) {
|
||
|
this["_queue"] = itm;
|
||
|
itm["_next"] = itm;
|
||
|
itm["_prev"] = itm;
|
||
|
}else {
|
||
|
const last = first["_prev"];
|
||
|
last["_next"] = itm;
|
||
|
itm["_prev"] = last;
|
||
|
itm["_next"] = first;
|
||
|
first["_prev"] = itm;
|
||
|
}
|
||
|
if(isStr) {
|
||
|
++this["_frameCountStr"];
|
||
|
}else {
|
||
|
++this["_frameCountBin"];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {string} socketURI
|
||
|
* @return {Object}
|
||
|
*/
|
||
|
eagruntimeImpl.platformNetworking["createWebSocketHandle"] = function(socketURI) {
|
||
|
let sock;
|
||
|
|
||
|
try {
|
||
|
sock = new WebSocket(socketURI);
|
||
|
}catch(ex) {
|
||
|
eagError("Failed to create WebSocket: {}", socketURI);
|
||
|
eagStackTrace(ERROR, "Exception Caught", ex);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
sock.binaryType = "arraybuffer";
|
||
|
|
||
|
const ret = {
|
||
|
"state": WS_CONNECTING,
|
||
|
"_socket": sock,
|
||
|
"_queue": null,
|
||
|
"_frameCountStr": 0,
|
||
|
"_frameCountBin": 0,
|
||
|
"_addRecievedFrame": addRecievedFrameImpl,
|
||
|
"closeSocket": closeSocketImpl,
|
||
|
"sendStringFrame": sendStringFrameImpl,
|
||
|
"sendBinaryFrame": sendBinaryFrameImpl,
|
||
|
"availableFrames": availableFramesImpl,
|
||
|
"getNextFrame": getNextFrameImpl,
|
||
|
"getAllFrames": getAllFramesImpl,
|
||
|
"clearFrames": clearFramesImpl,
|
||
|
"availableStringFrames": availableStringFramesImpl,
|
||
|
"getNextStringFrame": getNextStringFrameImpl,
|
||
|
"getAllStringFrames": getAllStringFramesImpl,
|
||
|
"clearStringFrames": clearStringFramesImpl,
|
||
|
"availableBinaryFrames": availableBinaryFramesImpl,
|
||
|
"getNextBinaryFrame": getNextBinaryFrameImpl,
|
||
|
"getAllBinaryFrames": getAllBinaryFramesImpl,
|
||
|
"clearBinaryFrames": clearBinaryFramesImpl
|
||
|
};
|
||
|
|
||
|
sock.addEventListener("open", function(evt) {
|
||
|
ret["state"] = WS_CONNECTED;
|
||
|
});
|
||
|
|
||
|
sock.addEventListener("message", function(evt) {
|
||
|
ret["_addRecievedFrame"](evt.data);
|
||
|
});
|
||
|
|
||
|
sock.addEventListener("close", function(evt) {
|
||
|
if(ret["state"] !== WS_FAILED) {
|
||
|
ret["state"] = WS_CLOSED;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
sock.addEventListener("error", function(evt) {
|
||
|
if(ret["state"] === WS_CONNECTING) {
|
||
|
ret["state"] = WS_FAILED;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return ret;
|
||
|
};
|
||
|
|
||
|
})();
|