Bladeren bron

LibWebSocket: Make WebSocketImpl an abstract class

The LibCore sockets implementation becomes WebSocketImplSerenity.
This will allow us to create a custom WebSocketImpl subclass for Qt
to use in Ladybird.
Andreas Kling 2 jaren geleden
bovenliggende
commit
be5f6aa46e

+ 1 - 0
Userland/Libraries/LibWebSocket/CMakeLists.txt

@@ -1,6 +1,7 @@
 set(SOURCES
     ConnectionInfo.cpp
     Impl/WebSocketImpl.cpp
+    Impl/WebSocketImplSerenity.cpp
     WebSocket.cpp
 )
 

+ 2 - 56
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<NonnullOwnPtr<Core::Stream::BufferedSocketBase>> {
-        if (connection_info.is_secure()) {
-            TLS::Options options;
-            options.set_alert_handler([this](auto) {
-                on_connection_error();
-            });
-            return TRY(Core::Stream::BufferedSocket<TLS::TLSv12>::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<ByteBuffer> 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<String> 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;
 
 }

+ 12 - 24
Userland/Libraries/LibWebSocket/Impl/WebSocketImpl.h

@@ -11,41 +11,29 @@
 #include <AK/ByteBuffer.h>
 #include <AK/Span.h>
 #include <AK/String.h>
-#include <LibCore/Object.h>
 #include <LibWebSocket/ConnectionInfo.h>
 
 namespace WebSocket {
 
-class WebSocketImpl : public Core::Object {
-    C_OBJECT(WebSocketImpl);
-
+class WebSocketImpl : public RefCounted<WebSocketImpl> {
 public:
-    virtual ~WebSocketImpl() override = default;
-    explicit WebSocketImpl(Core::Object* parent = nullptr);
-
-    void connect(ConnectionInfo const&);
-
-    bool can_read_line() { return MUST(m_socket->can_read_line()); }
-    ErrorOr<String> read_line(size_t size);
-
-    bool can_read() { return MUST(m_socket->can_read_without_blocking()); }
-    ErrorOr<ByteBuffer> read(int max_size);
-
-    bool send(ReadonlyBytes bytes) { return m_socket->write_or_error(bytes); }
-
-    bool eof() { return m_socket->is_eof(); }
+    virtual ~WebSocketImpl();
 
-    void discard_connection()
-    {
-        m_socket.clear();
-    }
+    virtual void connect(ConnectionInfo const&) = 0;
+    virtual bool can_read_line() = 0;
+    virtual ErrorOr<String> read_line(size_t) = 0;
+    virtual bool can_read() = 0;
+    virtual ErrorOr<ByteBuffer> read(int max_size) = 0;
+    virtual bool send(ReadonlyBytes) = 0;
+    virtual bool eof() = 0;
+    virtual void discard_connection() = 0;
 
     Function<void()> on_connected;
     Function<void()> on_connection_error;
     Function<void()> on_ready_to_read;
 
-private:
-    OwnPtr<Core::Stream::BufferedSocketBase> m_socket;
+protected:
+    WebSocketImpl();
 };
 
 }

+ 94 - 0
Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.cpp

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
+ * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
+ * Copyright (c) 2022, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibCore/EventLoop.h>
+#include <LibWebSocket/Impl/WebSocketImplSerenity.h>
+
+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<NonnullOwnPtr<Core::Stream::BufferedSocketBase>> {
+        if (connection_info.is_secure()) {
+            TLS::Options options;
+            options.set_alert_handler([this](auto) {
+                on_connection_error();
+            });
+            return TRY(Core::Stream::BufferedSocket<TLS::TLSv12>::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<ByteBuffer> 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<String> 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();
+}
+
+}

+ 33 - 0
Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
+ * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
+ * Copyright (c) 2022, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWebSocket/Impl/WebSocketImpl.h>
+
+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<String> read_line(size_t) override;
+    virtual bool can_read() override;
+    virtual ErrorOr<ByteBuffer> read(int max_size) override;
+    virtual bool send(ReadonlyBytes) override;
+    virtual bool eof() override;
+    virtual void discard_connection() override;
+
+private:
+    OwnPtr<Core::Stream::BufferedSocketBase> m_socket;
+};
+
+}

+ 2 - 1
Userland/Libraries/LibWebSocket/WebSocket.cpp

@@ -8,6 +8,7 @@
 #include <AK/Base64.h>
 #include <AK/Random.h>
 #include <LibCrypto/Hash/HashManager.h>
+#include <LibWebSocket/Impl/WebSocketImplSerenity.h>
 #include <LibWebSocket/WebSocket.h>
 #include <unistd.h>
 
@@ -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)");