diff options
Diffstat (limited to 'modules/websocket')
-rw-r--r-- | modules/websocket/SCsub | 155 | ||||
-rw-r--r-- | modules/websocket/config.py | 15 | ||||
-rw-r--r-- | modules/websocket/doc_classes/WebSocketClient.xml | 70 | ||||
-rw-r--r-- | modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml | 35 | ||||
-rw-r--r-- | modules/websocket/doc_classes/WebSocketPeer.xml | 75 | ||||
-rw-r--r-- | modules/websocket/doc_classes/WebSocketServer.xml | 109 | ||||
-rw-r--r-- | modules/websocket/emws_client.cpp | 1 | ||||
-rw-r--r-- | modules/websocket/lws_client.cpp | 12 | ||||
-rw-r--r-- | modules/websocket/lws_helper.h | 12 | ||||
-rw-r--r-- | modules/websocket/lws_peer.cpp | 80 | ||||
-rw-r--r-- | modules/websocket/lws_peer.h | 13 | ||||
-rw-r--r-- | modules/websocket/lws_server.cpp | 9 | ||||
-rw-r--r-- | modules/websocket/websocket_server.cpp | 6 |
13 files changed, 452 insertions, 140 deletions
diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub index b36f1beacd..c0985b3245 100644 --- a/modules/websocket/SCsub +++ b/modules/websocket/SCsub @@ -7,77 +7,88 @@ Import('env_modules') env_lws = env_modules.Clone() -thirdparty_dir = "#thirdparty/lws/" -helper_dir = "win32helpers/" -thirdparty_sources = [ - "client/client.c", - "client/client-handshake.c", - "client/client-parser.c", - "client/ssl-client.c", - - "ext/extension.c", - "ext/extension-permessage-deflate.c", - - "server/fops-zip.c", - "server/lejp-conf.c", - "server/parsers.c", - "server/ranges.c", - "server/server.c", - "server/server-handshake.c", - "server/ssl-server.c", - - "misc/base64-decode.c", - "misc/lejp.c", - "misc/sha-1.c", - - "alloc.c", - "context.c", - "handshake.c", - "header.c", - "libwebsockets.c", - "output.c", - "pollfd.c", - "service.c", - "ssl.c", - - "mbedtls_wrapper/library/ssl_cert.c", - "mbedtls_wrapper/library/ssl_pkey.c", - "mbedtls_wrapper/library/ssl_stack.c", - "mbedtls_wrapper/library/ssl_methods.c", - "mbedtls_wrapper/library/ssl_lib.c", - "mbedtls_wrapper/library/ssl_x509.c", - "mbedtls_wrapper/platform/ssl_port.c", - "mbedtls_wrapper/platform/ssl_pm.c", -] - -if env_lws["platform"] == "android": # Builtin getifaddrs - thirdparty_sources += ["misc/getifaddrs.c"] - -if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": # Winsock - thirdparty_sources += ["plat/lws-plat-win.c", helper_dir + "getopt.c", helper_dir + "getopt_long.c", helper_dir + "gettimeofday.c"] -else: # Unix socket - thirdparty_sources += ["plat/lws-plat-unix.c"] - - -thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - -if env_lws["platform"] == "javascript": # No need to add third party libraries at all - pass -else: - env_lws.add_source_files(env.modules_sources, thirdparty_sources) - env_lws.Append(CPPPATH=[thirdparty_dir]) - - wrapper_includes = ["#thirdparty/lws/mbedtls_wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]] - env_lws.Prepend(CPPPATH=wrapper_includes) - - if env['builtin_mbedtls']: - mbedtls_includes = "#thirdparty/mbedtls/include" - env_lws.Prepend(CPPPATH=[mbedtls_includes]) - - if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": - env_lws.Append(CPPPATH=[thirdparty_dir + helper_dir]) - - if env_lws["platform"] == "uwp": - env_lws.Append(CCFLAGS=["/DLWS_MINGW_SUPPORT"]) +if env['builtin_libwebsockets']: + thirdparty_dir = "#thirdparty/libwebsockets/" + helper_dir = "win32helpers/" + thirdparty_sources = [ + + "core/alloc.c", + "core/context.c", + "core/libwebsockets.c", + "core/output.c", + "core/pollfd.c", + "core/service.c", + + "event-libs/poll/poll.c", + + "misc/base64-decode.c", + "misc/lejp.c", + "misc/sha-1.c", + + "roles/h1/ops-h1.c", + "roles/http/header.c", + "roles/http/client/client.c", + "roles/http/client/client-handshake.c", + "roles/http/server/fops-zip.c", + "roles/http/server/lejp-conf.c", + "roles/http/server/parsers.c", + "roles/http/server/server.c", + "roles/listen/ops-listen.c", + "roles/pipe/ops-pipe.c", + "roles/raw/ops-raw.c", + + "roles/ws/client-ws.c", + "roles/ws/client-parser-ws.c", + "roles/ws/ops-ws.c", + "roles/ws/server-ws.c", + + "tls/tls.c", + "tls/tls-client.c", + "tls/tls-server.c", + + "tls/mbedtls/wrapper/library/ssl_cert.c", + "tls/mbedtls/wrapper/library/ssl_pkey.c", + "tls/mbedtls/wrapper/library/ssl_stack.c", + "tls/mbedtls/wrapper/library/ssl_methods.c", + "tls/mbedtls/wrapper/library/ssl_lib.c", + "tls/mbedtls/wrapper/library/ssl_x509.c", + "tls/mbedtls/wrapper/platform/ssl_port.c", + "tls/mbedtls/wrapper/platform/ssl_pm.c", + "tls/mbedtls/lws-genhash.c", + "tls/mbedtls/mbedtls-client.c", + "tls/mbedtls/lws-genrsa.c", + "tls/mbedtls/ssl.c", + "tls/mbedtls/mbedtls-server.c" + ] + + if env_lws["platform"] == "android": # Builtin getifaddrs + thirdparty_sources += ["misc/getifaddrs.c"] + + if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": # Winsock + thirdparty_sources += ["plat/lws-plat-win.c", helper_dir + "getopt.c", helper_dir + "getopt_long.c", helper_dir + "gettimeofday.c"] + else: # Unix socket + thirdparty_sources += ["plat/lws-plat-unix.c"] + + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + if env_lws["platform"] == "javascript": # No need to add third party libraries at all + pass + else: + env_lws.add_source_files(env.modules_sources, thirdparty_sources) + env_lws.Append(CPPPATH=[thirdparty_dir]) + + wrapper_includes = ["#thirdparty/libwebsockets/tls/mbedtls/wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]] + env_lws.Prepend(CPPPATH=wrapper_includes) + + if env['builtin_mbedtls']: + mbedtls_includes = "#thirdparty/mbedtls/include" + env_lws.Prepend(CPPPATH=[mbedtls_includes]) + + if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": + env_lws.Append(CPPPATH=[thirdparty_dir + helper_dir]) + + if env_lws["platform"] == "uwp": + env_lws.Append(CCFLAGS=["/DLWS_MINGW_SUPPORT"]) env_lws.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/websocket/config.py b/modules/websocket/config.py index fb920482f5..f59ef432b4 100644 --- a/modules/websocket/config.py +++ b/modules/websocket/config.py @@ -1,7 +1,16 @@ - -def can_build(platform): +def can_build(env, platform): return True - def configure(env): pass + +def get_doc_classes(): + return [ + "WebSocketClient", + "WebSocketMultiplayerPeer", + "WebSocketPeer", + "WebSocketServer" + ] + +def get_doc_path(): + return "doc_classes" diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml new file mode 100644 index 0000000000..2e11e1a44c --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketClient.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketClient" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + A WebSocket client implementation + </brief_description> + <description> + This class implements a WebSocket client compatible with any RFC 6455 complaint WebSocket server. + This client can be optionally used as a network peer for the [MultiplayerAPI]. + After starting the client ([method connect_to_url]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). + You will received appropriate signals when connecting, disconnecting, or when new data is available. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="connect_to_url"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="url" type="String"> + </argument> + <argument index="1" name="protocols" type="PoolStringArray" default="PoolStringArray( )"> + </argument> + <argument index="2" name="gd_mp_api" type="bool" default="false"> + </argument> + <description> + Connect to the given URL requesting one of the given [code]protocols[/code] as sub-protocol. + If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a network peer for the [MultiplayerAPI]. Note: connnections to non Godot servers will not work, and [signal data_received] will not be emitted when this option is true. + </description> + </method> + <method name="disconnect_from_host"> + <return type="void"> + </return> + <description> + Disconnect from the server if currently connected. + </description> + </method> + </methods> + <members> + <member name="verify_ssl" type="bool" setter="set_verify_ssl_enabled" getter="is_verify_ssl_enabled"> + Enable or disable SSL certificate verification. Note: You must specify the certificates to be used in the project settings for it to work when exported. + </member> + </members> + <signals> + <signal name="connection_closed"> + <description> + Emitted when the connection to the server is closed. + </description> + </signal> + <signal name="connection_error"> + <description> + Emitted when the connection to the server fails. + </description> + </signal> + <signal name="connection_established"> + <argument index="0" name="protocol" type="String"> + </argument> + <description> + Emitted when a connection with the server is established, [code]protocol[/code] will contain the sub-protocol agreed with the server. + </description> + </signal> + <signal name="data_received"> + <description> + Emitted when a WebSocket message is received. Note: This signal is NOT emitted when used as high level multiplayer peer. + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml new file mode 100644 index 0000000000..1a841f85ed --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + Base class for WebSocket server and client. + </brief_description> + <description> + Base class for WebSocket server and client, allowing them to be used as network peer for the [MultiplayerAPI]. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="get_peer" qualifiers="const"> + <return type="WebSocketPeer"> + </return> + <argument index="0" name="peer_id" type="int"> + </argument> + <description> + Returns the [WebSocketPeer] associated to the given [code]peer_id[/code]. + </description> + </method> + </methods> + <signals> + <signal name="peer_packet"> + <argument index="0" name="peer_source" type="int"> + </argument> + <description> + Emitted when a packet is received from a peer. Note: this signal is only emitted when the client or server is configured to use Godot multiplayer API. + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/modules/websocket/doc_classes/WebSocketPeer.xml b/modules/websocket/doc_classes/WebSocketPeer.xml new file mode 100644 index 0000000000..85a08e0c0b --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketPeer.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketPeer" inherits="PacketPeer" category="Core" version="3.1"> + <brief_description> + A class representing a specific WebSocket connection. + </brief_description> + <description> + This class represent a specific WebSocket connection, you can do lower level operations with it. + You can choose to write to the socket in binary or text mode, and you can recognize the mode used for writing by the other peer. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="close"> + <return type="void"> + </return> + <description> + Close this WebSocket connection, actively disconnecting the peer. + </description> + </method> + <method name="get_connected_host" qualifiers="const"> + <return type="String"> + </return> + <description> + Returns the IP Address of the connected peer. (Not available in HTML5 export) + </description> + </method> + <method name="get_connected_port" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns the remote port of the connected peer. (Not available in HTML5 export) + </description> + </method> + <method name="get_write_mode" qualifiers="const"> + <return type="int" enum="WebSocketPeer.WriteMode"> + </return> + <description> + Get the current selected write mode. See [enum WriteMode]. + </description> + </method> + <method name="is_connected_to_host" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns [code]true[/code] if this peer is currently connected. + </description> + </method> + <method name="set_write_mode"> + <return type="void"> + </return> + <argument index="0" name="mode" type="int" enum="WebSocketPeer.WriteMode"> + </argument> + <description> + Sets the socket to use the given [enum WriteMode]. + </description> + </method> + <method name="was_string_packet" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns [code]true[/code] if the last received packet was sent as a text payload. See [enum WriteMode] + </description> + </method> + </methods> + <constants> + <constant name="WRITE_MODE_TEXT" value="0" enum="WriteMode"> + Specify that WebSockets messages should be transferred as text payload (only valid UTF-8 is allowed). + </constant> + <constant name="WRITE_MODE_BINARY" value="1" enum="WriteMode"> + Specify that WebSockets messages should be transferred as binary payload (any byte combination is allowed). + </constant> + </constants> +</class> diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml new file mode 100644 index 0000000000..a1061e446b --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketServer.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketServer" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + A WebSocket server implementation + </brief_description> + <description> + This class implements a WebSocket server that can also support the high level multiplayer API. + After starting the server ([method listen]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). When clients connect, disconnect, or send data, you will receive the appropriate signal. + Note: This class will not work in HTML5 exports due to browser restrictions. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="disconnect_peer"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Disconnects the given peer. + </description> + </method> + <method name="get_peer_address" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns the IP address of the given peer. + </description> + </method> + <method name="get_peer_port" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns the remote port of the given peer. + </description> + </method> + <method name="has_peer" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns [code]true[/code] if a peer with the given ID is connected. + </description> + </method> + <method name="is_listening" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns [code]true[/code] if the server is actively listening on a port. + </description> + </method> + <method name="listen"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="port" type="int"> + </argument> + <argument index="1" name="protocols" type="PoolStringArray" default="PoolStringArray( )"> + </argument> + <argument index="2" name="gd_mp_api" type="bool" default="false"> + </argument> + <description> + Start listening on the given port. + You can specify the desired subprotocols via the "protocols" array. If the list empty (default), "binary" will be used. + You can use this server as a network peer for [MultiplayerAPI] by passing true as "gd_mp_api". Note: [signal data_received] will not be fired and clients other than Godot will not work in this case. + </description> + </method> + <method name="stop"> + <return type="void"> + </return> + <description> + Stop the server and clear its state. + </description> + </method> + </methods> + <signals> + <signal name="client_connected"> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="protocol" type="String"> + </argument> + <description> + Emitted when a new client connects. "protocol" will be the sub-protocol agreed with the client. + </description> + </signal> + <signal name="client_disconnected"> + <argument index="0" name="id" type="int"> + </argument> + <description> + Emitted when a client disconnects. + </description> + </signal> + <signal name="data_received"> + <argument index="0" name="id" type="int"> + </argument> + <description> + Emitted when a new message is received. Note: This signal is NOT emitted when used as high level multiplayer peer. + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index 1405fa98b0..00c36ebb47 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -64,7 +64,6 @@ Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, String str = "ws://"; String proto_string = ""; - int i = 0; if (p_ssl) str = "wss://"; diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index 2220c9adf2..ac31daa108 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -32,6 +32,7 @@ #include "lws_client.h" #include "core/io/ip.h" #include "core/io/stream_peer_ssl.h" +#include "tls/mbedtls/wrapper/include/openssl/ssl.h" Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) { @@ -126,11 +127,6 @@ int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi case LWS_CALLBACK_CLIENT_ESTABLISHED: peer->set_wsi(wsi); peer_data->peer_id = 0; - peer_data->in_size = 0; - peer_data->in_count = 0; - peer_data->out_count = 0; - peer_data->rbw.resize(16); - peer_data->rbr.resize(16); peer_data->force_close = false; _on_connect(lws_get_protocol(wsi)->name); break; @@ -140,11 +136,7 @@ int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi destroy_context(); return -1; // we should close the connection (would probably happen anyway) - case LWS_CALLBACK_CLOSED: - peer_data->in_count = 0; - peer_data->out_count = 0; - peer_data->rbw.resize(0); - peer_data->rbr.resize(0); + case LWS_CALLBACK_CLIENT_CLOSED: peer->close(); destroy_context(); _on_disconnect(); diff --git a/modules/websocket/lws_helper.h b/modules/websocket/lws_helper.h index a850a545d3..85a1e3769f 100644 --- a/modules/websocket/lws_helper.h +++ b/modules/websocket/lws_helper.h @@ -30,6 +30,9 @@ #ifndef LWS_HELPER_H #define LWS_HELPER_H +#define LWS_BUF_SIZE 65536 +#define LWS_PACKET_SIZE LWS_BUF_SIZE + #include "core/io/stream_peer.h" #include "core/os/os.h" #include "core/reference.h" @@ -124,6 +127,7 @@ static void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, /* LWS protocol structs */ ref->lws_structs = (struct lws_protocols *)memalloc(sizeof(struct lws_protocols) * (len + 2)); + memset(ref->lws_structs, 0, sizeof(struct lws_protocols) * (len + 2)); CharString strings = p_names.join(",").ascii(); int str_len = strings.length(); @@ -145,13 +149,15 @@ static void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, structs_ptr[0].name = "http-only"; structs_ptr[0].callback = p_callback; structs_ptr[0].per_session_data_size = data_size; - structs_ptr[0].rx_buffer_size = 0; + structs_ptr[0].rx_buffer_size = LWS_BUF_SIZE; + structs_ptr[0].tx_packet_size = LWS_PACKET_SIZE; /* add user defined protocols */ for (i = 0; i < len; i++) { structs_ptr[i + 1].name = (const char *)&names_ptr[pos]; structs_ptr[i + 1].callback = p_callback; structs_ptr[i + 1].per_session_data_size = data_size; - structs_ptr[i + 1].rx_buffer_size = 0; + structs_ptr[i + 1].rx_buffer_size = LWS_BUF_SIZE; + structs_ptr[i + 1].tx_packet_size = LWS_PACKET_SIZE; pos += pnr[i].ascii().length() + 1; names_ptr[pos - 1] = '\0'; } @@ -209,6 +215,6 @@ public: \ \ protected: - /* clang-format on */ +/* clang-format on */ #endif // LWS_HELPER_H diff --git a/modules/websocket/lws_peer.cpp b/modules/websocket/lws_peer.cpp index 8a064fb5a4..0989357258 100644 --- a/modules/websocket/lws_peer.cpp +++ b/modules/websocket/lws_peer.cpp @@ -35,11 +35,16 @@ // Needed for socket_helpers on Android at least. UNIXes has it, just include if not windows #if !defined(WINDOWS_ENABLED) #include <netinet/in.h> +#include <sys/socket.h> #endif #include "drivers/unix/socket_helpers.h" void LWSPeer::set_wsi(struct lws *p_wsi) { + ERR_FAIL_COND(wsi != NULL); + + rbw.resize(16); + rbr.resize(16); wsi = p_wsi; }; @@ -56,24 +61,24 @@ Error LWSPeer::read_wsi(void *in, size_t len) { ERR_FAIL_COND_V(!is_connected_to_host(), FAILED); PeerData *peer_data = (PeerData *)(lws_wsi_user(wsi)); - uint32_t size = peer_data->in_size; + uint32_t size = in_size; uint8_t is_string = lws_frame_is_binary(wsi) ? 0 : 1; - if (peer_data->rbr.space_left() < len + 5) { + if (rbr.space_left() < len + 5) { ERR_EXPLAIN("Buffer full! Dropping data"); ERR_FAIL_V(FAILED); } - copymem(&(peer_data->input_buffer[size]), in, len); + copymem(&(input_buffer[size]), in, len); size += len; - peer_data->in_size = size; + in_size = size; if (lws_is_final_fragment(wsi)) { - peer_data->rbr.write((uint8_t *)&size, 4); - peer_data->rbr.write((uint8_t *)&is_string, 1); - peer_data->rbr.write(peer_data->input_buffer, size); - peer_data->in_count++; - peer_data->in_size = 0; + rbr.write((uint8_t *)&size, 4); + rbr.write((uint8_t *)&is_string, 1); + rbr.write(input_buffer, size); + in_count++; + in_size = 0; } return OK; @@ -85,26 +90,26 @@ Error LWSPeer::write_wsi() { PeerData *peer_data = (PeerData *)(lws_wsi_user(wsi)); PoolVector<uint8_t> tmp; - int left = peer_data->rbw.data_left(); + int left = rbw.data_left(); uint32_t to_write = 0; - if (left == 0 || peer_data->out_count == 0) + if (left == 0 || out_count == 0) return OK; - peer_data->rbw.read((uint8_t *)&to_write, 4); - peer_data->out_count--; + rbw.read((uint8_t *)&to_write, 4); + out_count--; if (left < to_write) { - peer_data->rbw.advance_read(left); + rbw.advance_read(left); return FAILED; } tmp.resize(LWS_PRE + to_write); - peer_data->rbw.read(&(tmp.write()[LWS_PRE]), to_write); + rbw.read(&(tmp.write()[LWS_PRE]), to_write); lws_write(wsi, &(tmp.write()[LWS_PRE]), to_write, (enum lws_write_protocol)write_mode); tmp.resize(0); - if (peer_data->out_count > 0) + if (out_count > 0) lws_callback_on_writable(wsi); // we want to write more! return OK; @@ -115,9 +120,9 @@ Error LWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { ERR_FAIL_COND_V(!is_connected_to_host(), FAILED); PeerData *peer_data = (PeerData *)lws_wsi_user(wsi); - peer_data->rbw.write((uint8_t *)&p_buffer_size, 4); - peer_data->rbw.write(p_buffer, MIN(p_buffer_size, peer_data->rbw.space_left())); - peer_data->out_count++; + rbw.write((uint8_t *)&p_buffer_size, 4); + rbw.write(p_buffer, MIN(p_buffer_size, rbw.space_left())); + out_count++; lws_callback_on_writable(wsi); // notify that we want to write return OK; @@ -129,7 +134,7 @@ Error LWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { PeerData *peer_data = (PeerData *)lws_wsi_user(wsi); - if (peer_data->in_count == 0) + if (in_count == 0) return ERR_UNAVAILABLE; uint32_t to_read = 0; @@ -137,17 +142,17 @@ Error LWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { uint8_t is_string = 0; r_buffer_size = 0; - peer_data->rbr.read((uint8_t *)&to_read, 4); - peer_data->in_count--; - left = peer_data->rbr.data_left(); + rbr.read((uint8_t *)&to_read, 4); + in_count--; + left = rbr.data_left(); if (left < to_read + 1) { - peer_data->rbr.advance_read(left); + rbr.advance_read(left); return FAILED; } - peer_data->rbr.read(&is_string, 1); - peer_data->rbr.read(packet_buffer, to_read); + rbr.read(&is_string, 1); + rbr.read(packet_buffer, to_read); *r_buffer = packet_buffer; r_buffer_size = to_read; _was_string = is_string; @@ -160,7 +165,7 @@ int LWSPeer::get_available_packet_count() const { if (!is_connected_to_host()) return 0; - return ((PeerData *)lws_wsi_user(wsi))->in_count; + return in_count; }; bool LWSPeer::was_string_packet() const { @@ -175,12 +180,17 @@ bool LWSPeer::is_connected_to_host() const { void LWSPeer::close() { if (wsi != NULL) { - struct lws *tmp = wsi; PeerData *data = ((PeerData *)lws_wsi_user(wsi)); data->force_close = true; - wsi = NULL; - lws_callback_on_writable(tmp); // notify that we want to disconnect + lws_callback_on_writable(wsi); // notify that we want to disconnect } + wsi = NULL; + rbw.resize(0); + rbr.resize(0); + in_count = 0; + in_size = 0; + out_count = 0; + _was_string = false; }; IP_Address LWSPeer::get_connected_host() const { @@ -190,9 +200,11 @@ IP_Address LWSPeer::get_connected_host() const { IP_Address ip; int port = 0; - socklen_t len; struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + int fd = lws_get_socket_fd(wsi); + ERR_FAIL_COND_V(fd == -1, IP_Address()); int ret = getpeername(fd, (struct sockaddr *)&addr, &len); ERR_FAIL_COND_V(ret != 0, IP_Address()); @@ -209,9 +221,11 @@ uint16_t LWSPeer::get_connected_port() const { IP_Address ip; int port = 0; - socklen_t len; struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + int fd = lws_get_socket_fd(wsi); + ERR_FAIL_COND_V(fd == -1, 0); int ret = getpeername(fd, (struct sockaddr *)&addr, &len); ERR_FAIL_COND_V(ret != 0, 0); @@ -223,8 +237,8 @@ uint16_t LWSPeer::get_connected_port() const { LWSPeer::LWSPeer() { wsi = NULL; - _was_string = false; write_mode = WRITE_MODE_BINARY; + close(); }; LWSPeer::~LWSPeer() { diff --git a/modules/websocket/lws_peer.h b/modules/websocket/lws_peer.h index e96b38b168..d7d46e3076 100644 --- a/modules/websocket/lws_peer.h +++ b/modules/websocket/lws_peer.h @@ -57,14 +57,15 @@ public: struct PeerData { uint32_t peer_id; bool force_close; - RingBuffer<uint8_t> rbw; - RingBuffer<uint8_t> rbr; - mutable uint8_t input_buffer[PACKET_BUFFER_SIZE]; - uint32_t in_size; - int in_count; - int out_count; }; + RingBuffer<uint8_t> rbw; + RingBuffer<uint8_t> rbr; + uint8_t input_buffer[PACKET_BUFFER_SIZE]; + uint32_t in_size; + int in_count; + int out_count; + virtual int get_available_packet_count() const; virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size); virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size); diff --git a/modules/websocket/lws_server.cpp b/modules/websocket/lws_server.cpp index 8d13dc7a98..bb724bce9c 100644 --- a/modules/websocket/lws_server.cpp +++ b/modules/websocket/lws_server.cpp @@ -92,11 +92,6 @@ int LWSServer::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi _peer_map[id] = peer; peer_data->peer_id = id; - peer_data->in_size = 0; - peer_data->in_count = 0; - peer_data->out_count = 0; - peer_data->rbw.resize(16); - peer_data->rbr.resize(16); peer_data->force_close = false; _on_connect(id, lws_get_protocol(wsi)->name); @@ -111,10 +106,6 @@ int LWSServer::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi _peer_map[id]->close(); _peer_map.erase(id); } - peer_data->in_count = 0; - peer_data->out_count = 0; - peer_data->rbr.resize(0); - peer_data->rbw.resize(0); _on_disconnect(id); return 0; // we can end here } diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index 2693b26e47..53dd7b51b7 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -44,9 +44,9 @@ void WebSocketServer::_bind_methods() { ClassDB::bind_method(D_METHOD("listen", "port", "protocols", "gd_mp_api"), &WebSocketServer::listen, DEFVAL(PoolVector<String>()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("stop"), &WebSocketServer::stop); ClassDB::bind_method(D_METHOD("has_peer", "id"), &WebSocketServer::has_peer); - ClassDB::bind_method(D_METHOD("get_peer_address"), &WebSocketServer::get_peer_address); - ClassDB::bind_method(D_METHOD("get_peer_port"), &WebSocketServer::get_peer_port); - ClassDB::bind_method(D_METHOD("disconnect_peer"), &WebSocketServer::disconnect_peer); + ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &WebSocketServer::get_peer_address); + ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &WebSocketServer::get_peer_port); + ClassDB::bind_method(D_METHOD("disconnect_peer", "id"), &WebSocketServer::disconnect_peer); ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol"))); |