| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  library_godot_websocket.js                                            */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the        */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including    */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
					
						
							|  |  |  | /* the following conditions:                                              */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be         */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.        */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | const GodotWebSocket = { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 	// Our socket implementation that forwards events to C++.
 | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 	$GodotWebSocket__deps: ['$IDHandler', '$GodotRuntime'], | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 	$GodotWebSocket: { | 
					
						
							|  |  |  | 		// Connection opened, report selected protocol
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		_onopen: function (p_id, callback, event) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							|  |  |  | 			if (!ref) { | 
					
						
							|  |  |  | 				return; // Godot object is gone.
 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 			const c_str = GodotRuntime.allocString(ref.protocol); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			callback(c_str); | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 			GodotRuntime.free(c_str); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Message received, report content and type (UTF8 vs binary)
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		_onmessage: function (p_id, callback, event) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							|  |  |  | 			if (!ref) { | 
					
						
							|  |  |  | 				return; // Godot object is gone.
 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 			let buffer; | 
					
						
							|  |  |  | 			let is_string = 0; | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			if (event.data instanceof ArrayBuffer) { | 
					
						
							|  |  |  | 				buffer = new Uint8Array(event.data); | 
					
						
							|  |  |  | 			} else if (event.data instanceof Blob) { | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 				GodotRuntime.error('Blob type not supported'); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 				return; | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 			} else if (typeof event.data === 'string') { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 				is_string = 1; | 
					
						
							| 
									
										
										
										
											2025-04-19 17:45:06 +02:00
										 |  |  | 				buffer = new TextEncoder('utf-8').encode(event.data); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 				GodotRuntime.error('Unknown message type'); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 			const len = buffer.length * buffer.BYTES_PER_ELEMENT; | 
					
						
							|  |  |  | 			const out = GodotRuntime.malloc(len); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			HEAPU8.set(buffer, out); | 
					
						
							|  |  |  | 			callback(out, len, is_string); | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 			GodotRuntime.free(out); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// An error happened, 'onclose' will be called after this.
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		_onerror: function (p_id, callback, event) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							|  |  |  | 			if (!ref) { | 
					
						
							|  |  |  | 				return; // Godot object is gone.
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			callback(); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Connection is closed, this is always fired. Report close code, reason, and clean status.
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		_onclose: function (p_id, callback, event) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							|  |  |  | 			if (!ref) { | 
					
						
							|  |  |  | 				return; // Godot object is gone.
 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 			const c_str = GodotRuntime.allocString(event.reason); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			callback(event.code, c_str, event.wasClean ? 1 : 0); | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 			GodotRuntime.free(c_str); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Send a message
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		send: function (p_id, p_data) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 			if (!ref || ref.readyState !== ref.OPEN) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 				return 1; // Godot object is gone or socket is not in a ready state.
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ref.send(p_data); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-29 14:11:27 -06:00
										 |  |  | 		// Get current bufferedAmount
 | 
					
						
							|  |  |  | 		bufferedAmount: function (p_id) { | 
					
						
							|  |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							|  |  |  | 			if (!ref) { | 
					
						
							|  |  |  | 				return 0; // Godot object is gone.
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return ref.bufferedAmount; | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		create: function (socket, p_on_open, p_on_message, p_on_error, p_on_close) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const id = IDHandler.add(socket); | 
					
						
							|  |  |  | 			socket.onopen = GodotWebSocket._onopen.bind(null, id, p_on_open); | 
					
						
							|  |  |  | 			socket.onmessage = GodotWebSocket._onmessage.bind(null, id, p_on_message); | 
					
						
							|  |  |  | 			socket.onerror = GodotWebSocket._onerror.bind(null, id, p_on_error); | 
					
						
							|  |  |  | 			socket.onclose = GodotWebSocket._onclose.bind(null, id, p_on_close); | 
					
						
							|  |  |  | 			return id; | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Closes the JavaScript WebSocket (if not already closing) associated to a given C++ object.
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		close: function (p_id, p_code, p_reason) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							|  |  |  | 			if (ref && ref.readyState < ref.CLOSING) { | 
					
						
							|  |  |  | 				const code = p_code; | 
					
						
							| 
									
										
										
										
											2023-07-13 13:04:32 +08:00
										 |  |  | 				const reason = p_reason; | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 				ref.close(code, reason); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Deletes the reference to a C++ object (closing any connected socket if necessary).
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		destroy: function (p_id) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			const ref = IDHandler.get(p_id); | 
					
						
							|  |  |  | 			if (!ref) { | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-03-17 18:36:35 -06:00
										 |  |  | 			GodotWebSocket.close(p_id, 3001, 'destroyed'); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			IDHandler.remove(p_id); | 
					
						
							|  |  |  | 			ref.onopen = null; | 
					
						
							|  |  |  | 			ref.onmessage = null; | 
					
						
							|  |  |  | 			ref.onerror = null; | 
					
						
							|  |  |  | 			ref.onclose = null; | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 09:42:03 -04:00
										 |  |  | 	godot_js_websocket_create__proxy: 'sync', | 
					
						
							| 
									
										
										
										
											2020-12-03 12:51:17 +01:00
										 |  |  | 	godot_js_websocket_create__sig: 'iiiiiiii', | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 	godot_js_websocket_create: function (p_ref, p_url, p_proto, p_on_open, p_on_message, p_on_error, p_on_close) { | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 		const on_open = GodotRuntime.get_func(p_on_open).bind(null, p_ref); | 
					
						
							|  |  |  | 		const on_message = GodotRuntime.get_func(p_on_message).bind(null, p_ref); | 
					
						
							|  |  |  | 		const on_error = GodotRuntime.get_func(p_on_error).bind(null, p_ref); | 
					
						
							|  |  |  | 		const on_close = GodotRuntime.get_func(p_on_close).bind(null, p_ref); | 
					
						
							|  |  |  | 		const url = GodotRuntime.parseString(p_url); | 
					
						
							|  |  |  | 		const protos = GodotRuntime.parseString(p_proto); | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		let socket = null; | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		try { | 
					
						
							|  |  |  | 			if (protos) { | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 				socket = new WebSocket(url, protos.split(',')); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				socket = new WebSocket(url); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} catch (e) { | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		socket.binaryType = 'arraybuffer'; | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		return GodotWebSocket.create(socket, on_open, on_message, on_error, on_close); | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 09:42:03 -04:00
										 |  |  | 	godot_js_websocket_send__proxy: 'sync', | 
					
						
							| 
									
										
										
										
											2020-12-03 12:51:17 +01:00
										 |  |  | 	godot_js_websocket_send__sig: 'iiiii', | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 	godot_js_websocket_send: function (p_id, p_buf, p_buf_len, p_raw) { | 
					
						
							|  |  |  | 		const bytes_array = new Uint8Array(p_buf_len); | 
					
						
							|  |  |  | 		let i = 0; | 
					
						
							|  |  |  | 		for (i = 0; i < p_buf_len; i++) { | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 			bytes_array[i] = GodotRuntime.getHeapValue(p_buf + i, 'i8'); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 		let out = bytes_array.buffer; | 
					
						
							| 
									
										
										
										
											2020-11-17 17:50:11 +00:00
										 |  |  | 		if (!p_raw) { | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 			out = new TextDecoder('utf-8').decode(bytes_array); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return GodotWebSocket.send(p_id, out); | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 09:42:03 -04:00
										 |  |  | 	godot_js_websocket_buffered_amount__proxy: 'sync', | 
					
						
							| 
									
										
										
										
											2021-07-29 14:11:27 -06:00
										 |  |  | 	godot_js_websocket_buffered_amount__sig: 'ii', | 
					
						
							|  |  |  | 	godot_js_websocket_buffered_amount: function (p_id) { | 
					
						
							|  |  |  | 		return GodotWebSocket.bufferedAmount(p_id); | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 09:42:03 -04:00
										 |  |  | 	godot_js_websocket_close__proxy: 'sync', | 
					
						
							| 
									
										
										
										
											2020-12-03 12:51:17 +01:00
										 |  |  | 	godot_js_websocket_close__sig: 'viii', | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 	godot_js_websocket_close: function (p_id, p_code, p_reason) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		const code = p_code; | 
					
						
							| 
									
										
										
										
											2020-11-19 16:54:07 +01:00
										 |  |  | 		const reason = GodotRuntime.parseString(p_reason); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		GodotWebSocket.close(p_id, code, reason); | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 09:42:03 -04:00
										 |  |  | 	godot_js_websocket_destroy__proxy: 'sync', | 
					
						
							| 
									
										
										
										
											2020-12-03 12:51:17 +01:00
										 |  |  | 	godot_js_websocket_destroy__sig: 'vi', | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | 	godot_js_websocket_destroy: function (p_id) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | 		GodotWebSocket.destroy(p_id); | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 12:13:52 +01:00
										 |  |  | autoAddDeps(GodotWebSocket, '$GodotWebSocket'); | 
					
						
							| 
									
										
										
										
											2020-10-23 18:33:20 +02:00
										 |  |  | mergeInto(LibraryManager.library, GodotWebSocket); |