| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2019-08-28 09:19:52 +02:00
										 |  |  | /*  wsl_peer.cpp                                                         */ | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2022-01-13 09:45:09 +01:00
										 |  |  | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* 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.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef JAVASCRIPT_ENABLED
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "wsl_peer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "wsl_client.h"
 | 
					
						
							|  |  |  | #include "wsl_server.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-11 15:21:47 +02:00
										 |  |  | #include "core/crypto/crypto_core.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | #include "core/math/random_number_generator.h"
 | 
					
						
							|  |  |  | #include "core/os/os.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String WSLPeer::generate_key() { | 
					
						
							|  |  |  | 	// Random key
 | 
					
						
							|  |  |  | 	RandomNumberGenerator rng; | 
					
						
							|  |  |  | 	rng.set_seed(OS::get_singleton()->get_unix_time()); | 
					
						
							|  |  |  | 	PoolVector<uint8_t> bkey; | 
					
						
							|  |  |  | 	int len = 16; // 16 bytes, as per RFC
 | 
					
						
							|  |  |  | 	bkey.resize(len); | 
					
						
							|  |  |  | 	PoolVector<uint8_t>::Write w = bkey.write(); | 
					
						
							|  |  |  | 	for (int i = 0; i < len; i++) { | 
					
						
							|  |  |  | 		w[i] = (uint8_t)rng.randi_range(0, 255); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return CryptoCore::b64_encode_str(&w[0], len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String WSLPeer::compute_key_response(String p_key) { | 
					
						
							|  |  |  | 	String key = p_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // Magic UUID as per RFC
 | 
					
						
							|  |  |  | 	Vector<uint8_t> sha = key.sha1_buffer(); | 
					
						
							|  |  |  | 	return CryptoCore::b64_encode_str(sha.ptr(), sha.size()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WSLPeer::_wsl_destroy(struct PeerData **p_data) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (!p_data || !(*p_data)) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 	struct PeerData *data = *p_data; | 
					
						
							|  |  |  | 	if (data->polling) { | 
					
						
							|  |  |  | 		data->destroy = true; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wslay_event_context_free(data->ctx); | 
					
						
							|  |  |  | 	memdelete(data); | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	*p_data = nullptr; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool WSLPeer::_wsl_poll(struct PeerData *p_data) { | 
					
						
							|  |  |  | 	p_data->polling = true; | 
					
						
							|  |  |  | 	int err = 0; | 
					
						
							|  |  |  | 	if ((err = wslay_event_recv(p_data->ctx)) != 0 || (err = wslay_event_send(p_data->ctx)) != 0) { | 
					
						
							|  |  |  | 		print_verbose("Websocket (wslay) poll error: " + itos(err)); | 
					
						
							|  |  |  | 		p_data->destroy = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	p_data->polling = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_data->destroy || (wslay_event_get_close_sent(p_data->ctx) && wslay_event_get_close_received(p_data->ctx))) { | 
					
						
							|  |  |  | 		bool valid = p_data->valid; | 
					
						
							|  |  |  | 		_wsl_destroy(&p_data); | 
					
						
							|  |  |  | 		return valid; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ssize_t wsl_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, int flags, void *user_data) { | 
					
						
							|  |  |  | 	struct WSLPeer::PeerData *peer_data = (struct WSLPeer::PeerData *)user_data; | 
					
						
							|  |  |  | 	if (!peer_data->valid) { | 
					
						
							|  |  |  | 		wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Ref<StreamPeer> conn = peer_data->conn; | 
					
						
							|  |  |  | 	int read = 0; | 
					
						
							|  |  |  | 	Error err = conn->get_partial_data(data, len, read); | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		print_verbose("Websocket get data error: " + itos(err) + ", read (should be 0!): " + itos(read)); | 
					
						
							|  |  |  | 		wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (read == 0) { | 
					
						
							|  |  |  | 		wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return read; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ssize_t wsl_send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data) { | 
					
						
							|  |  |  | 	struct WSLPeer::PeerData *peer_data = (struct WSLPeer::PeerData *)user_data; | 
					
						
							|  |  |  | 	if (!peer_data->valid) { | 
					
						
							|  |  |  | 		wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Ref<StreamPeer> conn = peer_data->conn; | 
					
						
							|  |  |  | 	int sent = 0; | 
					
						
							|  |  |  | 	Error err = conn->put_partial_data(data, len, sent); | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (sent == 0) { | 
					
						
							|  |  |  | 		wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return sent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int wsl_genmask_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, void *user_data) { | 
					
						
							|  |  |  | 	RandomNumberGenerator rng; | 
					
						
							|  |  |  | 	// TODO maybe use crypto in the future?
 | 
					
						
							|  |  |  | 	rng.set_seed(OS::get_singleton()->get_unix_time()); | 
					
						
							|  |  |  | 	for (unsigned int i = 0; i < len; i++) { | 
					
						
							|  |  |  | 		buf[i] = (uint8_t)rng.randi_range(0, 255); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void wsl_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *user_data) { | 
					
						
							|  |  |  | 	struct WSLPeer::PeerData *peer_data = (struct WSLPeer::PeerData *)user_data; | 
					
						
							| 
									
										
										
										
											2019-12-21 16:04:36 +01:00
										 |  |  | 	if (!peer_data->valid || peer_data->closing) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	WSLPeer *peer = (WSLPeer *)peer_data->peer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (peer->parse_message(arg) != OK) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (peer_data->is_server) { | 
					
						
							|  |  |  | 		WSLServer *helper = (WSLServer *)peer_data->obj; | 
					
						
							|  |  |  | 		helper->_on_peer_packet(peer_data->id); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		WSLClient *helper = (WSLClient *)peer_data->obj; | 
					
						
							|  |  |  | 		helper->_on_peer_packet(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wslay_event_callbacks wsl_callbacks = { | 
					
						
							|  |  |  | 	wsl_recv_callback, | 
					
						
							|  |  |  | 	wsl_send_callback, | 
					
						
							|  |  |  | 	wsl_genmask_callback, | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	nullptr, /* on_frame_recv_start_callback */ | 
					
						
							|  |  |  | 	nullptr, /* on_frame_recv_callback */ | 
					
						
							|  |  |  | 	nullptr, /* on_frame_recv_end_callback */ | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 	wsl_msg_recv_callback | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error WSLPeer::parse_message(const wslay_event_on_msg_recv_arg *arg) { | 
					
						
							|  |  |  | 	uint8_t is_string = 0; | 
					
						
							|  |  |  | 	if (arg->opcode == WSLAY_TEXT_FRAME) { | 
					
						
							|  |  |  | 		is_string = 1; | 
					
						
							|  |  |  | 	} else if (arg->opcode == WSLAY_CONNECTION_CLOSE) { | 
					
						
							|  |  |  | 		close_code = arg->status_code; | 
					
						
							|  |  |  | 		size_t len = arg->msg_length; | 
					
						
							|  |  |  | 		close_reason = ""; | 
					
						
							|  |  |  | 		if (len > 2 /* first 2 bytes = close code */) { | 
					
						
							|  |  |  | 			close_reason.parse_utf8((char *)arg->msg + 2, len - 2); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!wslay_event_get_close_sent(_data->ctx)) { | 
					
						
							|  |  |  | 			if (_data->is_server) { | 
					
						
							|  |  |  | 				WSLServer *helper = (WSLServer *)_data->obj; | 
					
						
							|  |  |  | 				helper->_on_close_request(_data->id, close_code, close_reason); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				WSLClient *helper = (WSLClient *)_data->obj; | 
					
						
							|  |  |  | 				helper->_on_close_request(close_code, close_reason); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return ERR_FILE_EOF; | 
					
						
							|  |  |  | 	} else if (arg->opcode != WSLAY_BINARY_FRAME) { | 
					
						
							|  |  |  | 		// Ping or pong
 | 
					
						
							|  |  |  | 		return ERR_SKIP; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_in_buffer.write_packet(arg->msg, arg->msg_length, &is_string); | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WSLPeer::make_context(PeerData *p_data, unsigned int p_in_buf_size, unsigned int p_in_pkt_size, unsigned int p_out_buf_size, unsigned int p_out_pkt_size) { | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	ERR_FAIL_COND(_data != nullptr); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(p_data == nullptr); | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_in_buffer.resize(p_in_pkt_size, p_in_buf_size); | 
					
						
							| 
									
										
										
										
											2021-07-29 14:11:27 -06:00
										 |  |  | 	_packet_buffer.resize(1 << p_in_buf_size); | 
					
						
							|  |  |  | 	_out_buf_size = p_out_buf_size; | 
					
						
							|  |  |  | 	_out_pkt_size = p_out_pkt_size; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_data = p_data; | 
					
						
							|  |  |  | 	_data->peer = this; | 
					
						
							|  |  |  | 	_data->valid = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (_data->is_server) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		wslay_event_context_server_init(&(_data->ctx), &wsl_callbacks, _data); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		wslay_event_context_client_init(&(_data->ctx), &wsl_callbacks, _data); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-15 12:31:42 +01:00
										 |  |  | 	wslay_event_config_set_max_recv_msg_length(_data->ctx, (1ULL << p_in_buf_size)); | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WSLPeer::set_write_mode(WriteMode p_mode) { | 
					
						
							|  |  |  | 	write_mode = p_mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WSLPeer::WriteMode WSLPeer::get_write_mode() const { | 
					
						
							|  |  |  | 	return write_mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WSLPeer::poll() { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (!_data) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (_wsl_poll(_data)) { | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 		_data = nullptr; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error WSLPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!is_connected_to_host(), FAILED); | 
					
						
							| 
									
										
										
										
											2021-07-29 14:11:27 -06:00
										 |  |  | 	ERR_FAIL_COND_V(_out_pkt_size && (wslay_event_get_queued_msg_count(_data->ctx) >= (1ULL << _out_pkt_size)), ERR_OUT_OF_MEMORY); | 
					
						
							| 
									
										
										
										
											2021-10-29 15:43:17 +02:00
										 |  |  | 	ERR_FAIL_COND_V(_out_buf_size && (wslay_event_get_queued_msg_length(_data->ctx) + p_buffer_size >= (1ULL << _out_buf_size)), ERR_OUT_OF_MEMORY); | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 15:43:17 +02:00
										 |  |  | 	struct wslay_event_msg msg; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 	msg.opcode = write_mode == WRITE_MODE_TEXT ? WSLAY_TEXT_FRAME : WSLAY_BINARY_FRAME; | 
					
						
							|  |  |  | 	msg.msg = p_buffer; | 
					
						
							|  |  |  | 	msg.msg_length = p_buffer_size; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 15:43:17 +02:00
										 |  |  | 	if (wslay_event_queue_msg(_data->ctx, &msg) != 0 || wslay_event_send(_data->ctx) != 0) { | 
					
						
							| 
									
										
										
										
											2020-01-24 14:50:53 +01:00
										 |  |  | 		close_now(); | 
					
						
							|  |  |  | 		return FAILED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error WSLPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { | 
					
						
							|  |  |  | 	r_buffer_size = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!is_connected_to_host(), FAILED); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (_in_buffer.packets_left() == 0) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		return ERR_UNAVAILABLE; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int read = 0; | 
					
						
							|  |  |  | 	PoolVector<uint8_t>::Write rw = _packet_buffer.write(); | 
					
						
							|  |  |  | 	_in_buffer.read_packet(rw.ptr(), _packet_buffer.size(), &_is_string, read); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*r_buffer = rw.ptr(); | 
					
						
							|  |  |  | 	r_buffer_size = read; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int WSLPeer::get_available_packet_count() const { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (!is_connected_to_host()) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return _in_buffer.packets_left(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-29 14:11:27 -06:00
										 |  |  | int WSLPeer::get_current_outbound_buffered_amount() const { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!_data, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return wslay_event_get_queued_msg_length(_data->ctx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | bool WSLPeer::was_string_packet() const { | 
					
						
							|  |  |  | 	return _is_string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool WSLPeer::is_connected_to_host() const { | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	return _data != nullptr; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WSLPeer::close_now() { | 
					
						
							|  |  |  | 	close(1000, ""); | 
					
						
							|  |  |  | 	_wsl_destroy(&_data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WSLPeer::close(int p_code, String p_reason) { | 
					
						
							|  |  |  | 	if (_data && !wslay_event_get_close_sent(_data->ctx)) { | 
					
						
							|  |  |  | 		CharString cs = p_reason.utf8(); | 
					
						
							|  |  |  | 		wslay_event_queue_close(_data->ctx, p_code, (uint8_t *)cs.ptr(), cs.size()); | 
					
						
							|  |  |  | 		wslay_event_send(_data->ctx); | 
					
						
							| 
									
										
										
										
											2019-12-21 16:04:36 +01:00
										 |  |  | 		_data->closing = true; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_in_buffer.clear(); | 
					
						
							|  |  |  | 	_packet_buffer.resize(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IP_Address WSLPeer::get_connected_host() const { | 
					
						
							| 
									
										
										
										
											2019-10-04 12:58:06 +02:00
										 |  |  | 	ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), IP_Address()); | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 12:58:06 +02:00
										 |  |  | 	return _data->tcp->get_connected_host(); | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint16_t WSLPeer::get_connected_port() const { | 
					
						
							| 
									
										
										
										
											2019-10-04 12:58:06 +02:00
										 |  |  | 	ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), 0); | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 12:58:06 +02:00
										 |  |  | 	return _data->tcp->get_connected_port(); | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 14:06:28 +01:00
										 |  |  | void WSLPeer::set_no_delay(bool p_enabled) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!is_connected_to_host() || _data->tcp.is_null()); | 
					
						
							|  |  |  | 	_data->tcp->set_no_delay(p_enabled); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | void WSLPeer::invalidate() { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (_data) { | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 		_data->valid = false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WSLPeer::WSLPeer() { | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	_data = nullptr; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | 	_is_string = 0; | 
					
						
							|  |  |  | 	close_code = -1; | 
					
						
							|  |  |  | 	write_mode = WRITE_MODE_BINARY; | 
					
						
							| 
									
										
										
										
											2021-07-29 14:11:27 -06:00
										 |  |  | 	_out_buf_size = 0; | 
					
						
							|  |  |  | 	_out_pkt_size = 0; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WSLPeer::~WSLPeer() { | 
					
						
							|  |  |  | 	close(); | 
					
						
							|  |  |  | 	invalidate(); | 
					
						
							|  |  |  | 	_wsl_destroy(&_data); | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	_data = nullptr; | 
					
						
							| 
									
										
										
										
											2019-06-24 15:46:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif // JAVASCRIPT_ENABLED
 |