diff --git a/Userland/Libraries/LibWebSocket/CMakeLists.txt b/Userland/Libraries/LibWebSocket/CMakeLists.txt index 6e7e7fca7c..dae1899fd6 100644 --- a/Userland/Libraries/LibWebSocket/CMakeLists.txt +++ b/Userland/Libraries/LibWebSocket/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES ConnectionInfo.cpp Impl/WebSocketImpl.cpp + Impl/WebSocketImplSerenity.cpp WebSocket.cpp ) diff --git a/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.cpp b/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.cpp index 379bd0a4b4..5d03921117 100644 --- a/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.cpp +++ b/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.cpp @@ -10,61 +10,7 @@ namespace WebSocket { -WebSocketImpl::WebSocketImpl(Core::Object* parent) - : Object(parent) -{ -} - -void WebSocketImpl::connect(ConnectionInfo const& connection_info) -{ - VERIFY(!m_socket); - VERIFY(on_connected); - VERIFY(on_connection_error); - VERIFY(on_ready_to_read); - auto socket_result = [&]() -> ErrorOr> { - if (connection_info.is_secure()) { - TLS::Options options; - options.set_alert_handler([this](auto) { - on_connection_error(); - }); - return TRY(Core::Stream::BufferedSocket::create( - TRY(TLS::TLSv12::connect(connection_info.url().host(), connection_info.url().port_or_default(), move(options))))); - } - - return TRY(Core::Stream::BufferedTCPSocket::create( - TRY(Core::Stream::TCPSocket::connect(connection_info.url().host(), connection_info.url().port_or_default())))); - }(); - - if (socket_result.is_error()) { - deferred_invoke([this] { - on_connection_error(); - }); - return; - } - - m_socket = socket_result.release_value(); - - m_socket->on_ready_to_read = [this] { - on_ready_to_read(); - }; - - deferred_invoke([this] { - on_connected(); - }); -} - -ErrorOr WebSocketImpl::read(int max_size) -{ - auto buffer = TRY(ByteBuffer::create_uninitialized(max_size)); - auto read_bytes = TRY(m_socket->read(buffer)); - return buffer.slice(0, read_bytes.size()); -} - -ErrorOr WebSocketImpl::read_line(size_t size) -{ - auto buffer = TRY(ByteBuffer::create_uninitialized(size)); - auto line = TRY(m_socket->read_line(buffer)); - return line.to_string(); -} +WebSocketImpl::WebSocketImpl() = default; +WebSocketImpl::~WebSocketImpl() = default; } diff --git a/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.h b/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.h index f572eaa82c..597a9d6c76 100644 --- a/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.h +++ b/Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.h @@ -11,41 +11,29 @@ #include #include #include -#include #include namespace WebSocket { -class WebSocketImpl : public Core::Object { - C_OBJECT(WebSocketImpl); - +class WebSocketImpl : public RefCounted { public: - virtual ~WebSocketImpl() override = default; - explicit WebSocketImpl(Core::Object* parent = nullptr); + virtual ~WebSocketImpl(); - void connect(ConnectionInfo const&); - - bool can_read_line() { return MUST(m_socket->can_read_line()); } - ErrorOr read_line(size_t size); - - bool can_read() { return MUST(m_socket->can_read_without_blocking()); } - ErrorOr read(int max_size); - - bool send(ReadonlyBytes bytes) { return m_socket->write_or_error(bytes); } - - bool eof() { return m_socket->is_eof(); } - - void discard_connection() - { - m_socket.clear(); - } + virtual void connect(ConnectionInfo const&) = 0; + virtual bool can_read_line() = 0; + virtual ErrorOr read_line(size_t) = 0; + virtual bool can_read() = 0; + virtual ErrorOr read(int max_size) = 0; + virtual bool send(ReadonlyBytes) = 0; + virtual bool eof() = 0; + virtual void discard_connection() = 0; Function on_connected; Function on_connection_error; Function on_ready_to_read; -private: - OwnPtr m_socket; +protected: + WebSocketImpl(); }; } diff --git a/Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.cpp b/Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.cpp new file mode 100644 index 0000000000..cf291569ba --- /dev/null +++ b/Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, Dex♪ + * Copyright (c) 2022, Ali Mohammad Pur + * Copyright (c) 2022, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace WebSocket { + +WebSocketImplSerenity::~WebSocketImplSerenity() = default; +WebSocketImplSerenity::WebSocketImplSerenity() = default; + +bool WebSocketImplSerenity::can_read_line() +{ + return MUST(m_socket->can_read_line()); +} + +bool WebSocketImplSerenity::can_read() +{ + return MUST(m_socket->can_read_without_blocking()); +} + +bool WebSocketImplSerenity::send(ReadonlyBytes bytes) +{ + return m_socket->write_or_error(bytes); +} + +bool WebSocketImplSerenity::eof() +{ + return m_socket->is_eof(); +} + +void WebSocketImplSerenity::discard_connection() +{ + m_socket = nullptr; +} + +void WebSocketImplSerenity::connect(ConnectionInfo const& connection_info) +{ + VERIFY(!m_socket); + VERIFY(on_connected); + VERIFY(on_connection_error); + VERIFY(on_ready_to_read); + auto socket_result = [&]() -> ErrorOr> { + if (connection_info.is_secure()) { + TLS::Options options; + options.set_alert_handler([this](auto) { + on_connection_error(); + }); + return TRY(Core::Stream::BufferedSocket::create( + TRY(TLS::TLSv12::connect(connection_info.url().host(), connection_info.url().port_or_default(), move(options))))); + } + + return TRY(Core::Stream::BufferedTCPSocket::create( + TRY(Core::Stream::TCPSocket::connect(connection_info.url().host(), connection_info.url().port_or_default())))); + }(); + + if (socket_result.is_error()) { + Core::deferred_invoke([this] { + on_connection_error(); + }); + return; + } + + m_socket = socket_result.release_value(); + + m_socket->on_ready_to_read = [this] { + on_ready_to_read(); + }; + + Core::deferred_invoke([this] { + on_connected(); + }); +} + +ErrorOr WebSocketImplSerenity::read(int max_size) +{ + auto buffer = TRY(ByteBuffer::create_uninitialized(max_size)); + auto read_bytes = TRY(m_socket->read(buffer)); + return buffer.slice(0, read_bytes.size()); +} + +ErrorOr WebSocketImplSerenity::read_line(size_t size) +{ + auto buffer = TRY(ByteBuffer::create_uninitialized(size)); + auto line = TRY(m_socket->read_line(buffer)); + return line.to_string(); +} + +} diff --git a/Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.h b/Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.h new file mode 100644 index 0000000000..664caa2954 --- /dev/null +++ b/Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Dex♪ + * Copyright (c) 2022, Ali Mohammad Pur + * Copyright (c) 2022, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace WebSocket { + +class WebSocketImplSerenity final : public WebSocketImpl { +public: + explicit WebSocketImplSerenity(); + virtual ~WebSocketImplSerenity() override; + + virtual void connect(ConnectionInfo const&) override; + virtual bool can_read_line() override; + virtual ErrorOr read_line(size_t) override; + virtual bool can_read() override; + virtual ErrorOr read(int max_size) override; + virtual bool send(ReadonlyBytes) override; + virtual bool eof() override; + virtual void discard_connection() override; + +private: + OwnPtr m_socket; +}; + +} diff --git a/Userland/Libraries/LibWebSocket/WebSocket.cpp b/Userland/Libraries/LibWebSocket/WebSocket.cpp index 31f4557acb..ff7bddec15 100644 --- a/Userland/Libraries/LibWebSocket/WebSocket.cpp +++ b/Userland/Libraries/LibWebSocket/WebSocket.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,7 @@ void WebSocket::start() { VERIFY(m_state == WebSocket::InternalState::NotStarted); VERIFY(!m_impl); - m_impl = WebSocketImpl::construct(); + m_impl = adopt_ref(*new WebSocketImplSerenity); m_impl->on_connection_error = [this] { dbgln("WebSocket: Connection error (underlying socket)");