_xiaofang/xiaofang/Assets/UnityWebSocket/Plugins/WebGL/WebSocket.jslib
2024-11-23 14:08:04 +08:00

339 lines
8.9 KiB
JavaScript

var WebSocketLibrary =
{
$webSocketManager:
{
/*
* Map of instances
*
* Instance structure:
* {
* url: string,
* ws: WebSocket,
* subProtocols: string[],
* }
*/
instances: {},
/* Last instance ID */
lastId: 0,
/* Event listeners */
onOpen: null,
onMessage: null,
onMessageStr: null,
onError: null,
onClose: null
},
/**
* Set onOpen callback
*
* @param callback Reference to C# static function
*/
WebSocketSetOnOpen: function(callback)
{
webSocketManager.onOpen = callback;
},
/**
* Set onMessage callback
*
* @param callback Reference to C# static function
*/
WebSocketSetOnMessage: function(callback)
{
webSocketManager.onMessage = callback;
},
/**
* Set onMessageStr callback
*
* @param callback Reference to C# static function
*/
WebSocketSetOnMessageStr: function(callback)
{
webSocketManager.onMessageStr = callback;
},
/**
* Set onError callback
*
* @param callback Reference to C# static function
*/
WebSocketSetOnError: function(callback)
{
webSocketManager.onError = callback;
},
/**
* Set onClose callback
*
* @param callback Reference to C# static function
*/
WebSocketSetOnClose: function(callback)
{
webSocketManager.onClose = callback;
},
/**
* Allocate new WebSocket instance struct
*
* @param url Server URL
*/
WebSocketAllocate: function(urlPtr)
{
var url = UTF8ToString(urlPtr);
var id = ++webSocketManager.lastId;
webSocketManager.instances[id] = {
url: url,
ws: null,
};
return id;
},
/**
* Add Sub Protocol
*
* @param instanceId Instance ID
* @param protocol Sub Protocol
*/
WebSocketAddSubProtocol: function(instanceId, protocolPtr)
{
var instance = webSocketManager.instances[instanceId];
if (!instance) return -1;
var protocol = UTF8ToString(protocolPtr);
if (instance.subProtocols == null)
instance.subProtocols = [];
instance.subProtocols.push(protocol);
return 0;
},
/**
* Remove reference to WebSocket instance
*
* If socket is not closed function will close it but onClose event will not be emitted because
* this function should be invoked by C# WebSocket destructor.
*
* @param instanceId Instance ID
*/
WebSocketFree: function(instanceId)
{
var instance = webSocketManager.instances[instanceId];
if (!instance) return 0;
// Close if not closed
if (instance.ws !== null && instance.ws.readyState < 2)
instance.ws.close();
// Remove reference
delete webSocketManager.instances[instanceId];
return 0;
},
/**
* Connect WebSocket to the server
*
* @param instanceId Instance ID
*/
WebSocketConnect: function(instanceId)
{
var instance = webSocketManager.instances[instanceId];
if (!instance) return -1;
if (instance.ws !== null) return -2;
if (instance.subProtocols != null)
instance.ws = new WebSocket(instance.url, instance.subProtocols);
else
instance.ws = new WebSocket(instance.url);
instance.ws.onopen = function()
{
Module.dynCall_vi(webSocketManager.onOpen, instanceId);
};
instance.ws.onmessage = function(ev)
{
if (ev.data instanceof ArrayBuffer)
{
var array = new Uint8Array(ev.data);
var buffer = _malloc(array.length);
writeArrayToMemory(array, buffer);
try
{
Module.dynCall_viii(webSocketManager.onMessage, instanceId, buffer, array.length);
}
finally
{
_free(buffer);
}
}
else if (typeof ev.data == 'string')
{
var length = lengthBytesUTF8(ev.data) + 1;
var buffer = _malloc(length);
stringToUTF8(ev.data, buffer, length);
try
{
Module.dynCall_vii(webSocketManager.onMessageStr, instanceId, buffer);
}
finally
{
_free(buffer);
}
}
else if (typeof Blob !== 'undefined' && ev.data instanceof Blob)
{
var reader = new FileReader();
reader.onload = function()
{
var array = new Uint8Array(reader.result);
var buffer = _malloc(array.length);
writeArrayToMemory(array, buffer);
try
{
Module.dynCall_viii(webSocketManager.onMessage, instanceId, buffer, array.length);
}
finally
{
reader = null;
_free(buffer);
}
};
reader.readAsArrayBuffer(ev.data);
}
else
{
console.log("[JSLIB WebSocket] not support message type: ", (typeof ev.data));
}
};
instance.ws.onerror = function(ev)
{
var msg = "WebSocket error.";
var length = lengthBytesUTF8(msg) + 1;
var buffer = _malloc(length);
stringToUTF8(msg, buffer, length);
try
{
Module.dynCall_vii(webSocketManager.onError, instanceId, buffer);
}
finally
{
_free(buffer);
}
};
instance.ws.onclose = function(ev)
{
var msg = ev.reason;
var length = lengthBytesUTF8(msg) + 1;
var buffer = _malloc(length);
stringToUTF8(msg, buffer, length);
try
{
Module.dynCall_viii(webSocketManager.onClose, instanceId, ev.code, buffer);
}
finally
{
_free(buffer);
}
instance.ws = null;
};
return 0;
},
/**
* Close WebSocket connection
*
* @param instanceId Instance ID
* @param code Close status code
* @param reasonPtr Pointer to reason string
*/
WebSocketClose: function(instanceId, code, reasonPtr)
{
var instance = webSocketManager.instances[instanceId];
if (!instance) return -1;
if (instance.ws === null) return -3;
if (instance.ws.readyState === 2) return -4;
if (instance.ws.readyState === 3) return -5;
var reason = ( reasonPtr ? UTF8ToString(reasonPtr) : undefined );
try
{
instance.ws.close(code, reason);
}
catch (err)
{
return -7;
}
return 0;
},
/**
* Send message over WebSocket
*
* @param instanceId Instance ID
* @param bufferPtr Pointer to the message buffer
* @param length Length of the message in the buffer
*/
WebSocketSend: function(instanceId, bufferPtr, length)
{
var instance = webSocketManager.instances[instanceId];
if (!instance) return -1;
if (instance.ws === null) return -3;
if (instance.ws.readyState !== 1) return -6;
if (typeof HEAPU8 !== 'undefined')
instance.ws.send(HEAPU8.buffer.slice(bufferPtr, bufferPtr + length));
else if (typeof buffer !== 'undefined')
instance.ws.send(buffer.slice(bufferPtr, bufferPtr + length));
else
return -8; // not support buffer slice
return 0;
},
/**
* Send message string over WebSocket
*
* @param instanceId Instance ID
* @param stringPtr Pointer to the message string
*/
WebSocketSendStr: function(instanceId, stringPtr)
{
var instance = webSocketManager.instances[instanceId];
if (!instance) return -1;
if (instance.ws === null) return -3;
if (instance.ws.readyState !== 1) return -6;
instance.ws.send(UTF8ToString(stringPtr));
return 0;
},
/**
* Return WebSocket readyState
*
* @param instanceId Instance ID
*/
WebSocketGetState: function(instanceId)
{
var instance = webSocketManager.instances[instanceId];
if (!instance) return -1;
if (instance.ws === null) return 3; // socket null as closed
return instance.ws.readyState;
}
};
autoAddDeps(WebSocketLibrary, '$webSocketManager');
mergeInto(LibraryManager.library, WebSocketLibrary);