diff options
Diffstat (limited to 'modules/websocket/wsl_peer.h')
-rw-r--r-- | modules/websocket/wsl_peer.h | 130 |
1 files changed, 87 insertions, 43 deletions
diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index 92672eb2c4..379002739c 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -33,79 +33,123 @@ #ifndef WEB_ENABLED +#include "websocket_peer.h" + +#include "packet_buffer.h" + +#include "core/crypto/crypto_core.h" #include "core/error/error_list.h" #include "core/io/packet_peer.h" #include "core/io/stream_peer_tcp.h" #include "core/templates/ring_buffer.h" -#include "packet_buffer.h" -#include "websocket_peer.h" #include "wslay/wslay.h" #define WSL_MAX_HEADER_SIZE 4096 class WSLPeer : public WebSocketPeer { - GDCIIMPL(WSLPeer, WebSocketPeer); - -public: - struct PeerData { - bool polling = false; - bool destroy = false; - bool valid = false; - bool is_server = false; - bool closing = false; - void *obj = nullptr; - void *peer = nullptr; - Ref<StreamPeer> conn; - Ref<StreamPeerTCP> tcp; - int id = 1; - wslay_event_context_ptr ctx = nullptr; +private: + static CryptoCore::RandomGenerator *_static_rng; + static WebSocketPeer *_create() { return memnew(WSLPeer); } + + // Callbacks. + static ssize_t _wsl_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, int flags, void *user_data); + static ssize_t _wsl_send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data); + static int _wsl_genmask_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, void *user_data); + static void _wsl_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *user_data); + + static wslay_event_callbacks _wsl_callbacks; + + // Helpers + static String _compute_key_response(String p_key); + static String _generate_key(); + + // Client IP resolver. + class Resolver { + Array ip_candidates; + IP::ResolverID resolver_id = IP::RESOLVER_INVALID_ID; + int port = 0; + + public: + bool has_more_candidates() { + return ip_candidates.size() > 0 || resolver_id != IP::RESOLVER_INVALID_ID; + } + + void try_next_candidate(Ref<StreamPeerTCP> &p_tcp); + void start(const String &p_host, int p_port); + void stop(); + Resolver() {} }; - static String compute_key_response(String p_key); - static String generate_key(); + Resolver resolver; -private: - static bool _wsl_poll(struct PeerData *p_data); - static void _wsl_destroy(struct PeerData **p_data); + // WebSocket connection state. + WebSocketPeer::State ready_state = WebSocketPeer::STATE_CLOSED; + bool is_server = false; + Ref<StreamPeerTCP> tcp; + Ref<StreamPeer> connection; + wslay_event_context_ptr wsl_ctx = nullptr; + + String requested_url; + String requested_host; + bool pending_request = true; + Ref<StreamPeerBuffer> handshake_buffer; + String selected_protocol; + String session_key; - struct PeerData *_data = nullptr; - uint8_t _is_string = 0; + int close_code = -1; + String close_reason; + uint8_t was_string = 0; + + // WebSocket configuration. + bool use_tls = true; + bool verify_tls = true; + Ref<X509Certificate> tls_cert; + + // Packet buffers. + Vector<uint8_t> packet_buffer; // Our packet info is just a boolean (is_string), using uint8_t for it. - PacketBuffer<uint8_t> _in_buffer; + PacketBuffer<uint8_t> in_buffer; - Vector<uint8_t> _packet_buffer; + Error _send(const uint8_t *p_buffer, int p_buffer_size, wslay_opcode p_opcode); - WriteMode write_mode = WRITE_MODE_BINARY; + Error _do_server_handshake(); + bool _parse_client_request(); - int _out_buf_size = 0; - int _out_pkt_size = 0; + void _do_client_handshake(); + bool _verify_server_response(); + + void _clear(); public: - int close_code = -1; - String close_reason; - void poll(); // Used by client and server. + static void initialize(); + static void deinitialize(); + // PacketPeer virtual int get_available_packet_count() const override; virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override; - virtual int get_max_packet_size() const override { return _packet_buffer.size(); }; - virtual int get_current_outbound_buffered_amount() const override; + virtual int get_max_packet_size() const override { return packet_buffer.size(); }; - virtual void close_now(); + // WebSocketPeer + virtual Error send(const uint8_t *p_buffer, int p_buffer_size, WriteMode p_mode) override; + virtual Error connect_to_url(const String &p_url, bool p_verify_tls = true, Ref<X509Certificate> p_cert = Ref<X509Certificate>()) override; + virtual Error accept_stream(Ref<StreamPeer> p_stream) override; virtual void close(int p_code = 1000, String p_reason = "") override; - virtual bool is_connected_to_host() const override; + virtual void poll() override; + + virtual State get_ready_state() const override { return ready_state; } + virtual int get_close_code() const override { return close_code; } + virtual String get_close_reason() const override { return close_reason; } + virtual int get_current_outbound_buffered_amount() const override; + virtual IPAddress get_connected_host() const override; virtual uint16_t get_connected_port() const override; + virtual String get_selected_protocol() const override; + virtual String get_requested_url() const override; - virtual WriteMode get_write_mode() const override; - virtual void set_write_mode(WriteMode p_mode) override; - virtual bool was_string_packet() const override; + virtual bool was_string_packet() const override { return was_string; } virtual void set_no_delay(bool p_enabled) override; - void 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); - Error parse_message(const wslay_event_on_msg_recv_arg *arg); - void invalidate(); - WSLPeer(); ~WSLPeer(); }; |