Skip to content

Commit 7d7c419

Browse files
ADKasterawesomekling
authored andcommitted
Ladybird: Add WebSocket server for use by Lagom networking
Hide its use behind the same flag as RequestServer in WebContent.
1 parent dd69421 commit 7d7c419

File tree

15 files changed

+162
-32
lines changed

15 files changed

+162
-32
lines changed

Ladybird/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ add_custom_target(debug${LADYBIRD_CUSTOM_TARGET_SUFFIX}
144144
add_subdirectory(SQLServer)
145145
add_subdirectory(WebContent)
146146
add_subdirectory(WebDriver)
147+
add_subdirectory(WebSocket)
147148
add_subdirectory(RequestServer)
148-
add_dependencies(ladybird SQLServer WebContent WebDriver RequestServer headless-browser)
149+
add_dependencies(ladybird SQLServer WebContent WebDriver WebSocketServer RequestServer headless-browser)
149150

150151
if (APPLE)
151152
# FIXME: Create a proper app bundle for each helper process
@@ -156,6 +157,7 @@ if (APPLE)
156157
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:SQLServer>" "${app_dir}"
157158
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:WebContent>" "${app_dir}"
158159
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:WebDriver>" "${app_dir}"
160+
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:WebSocketServer>" "${app_dir}"
159161
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:headless-browser>" "${app_dir}"
160162
)
161163
endif()

Ladybird/HelperProcess.cpp

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,36 +87,37 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(Web
8787
return new_client;
8888
}
8989

90-
ErrorOr<NonnullRefPtr<Protocol::RequestClient>> launch_request_server_process(ReadonlySpan<String> candidate_request_server_paths, StringView serenity_resource_root)
90+
template<typename Client>
91+
ErrorOr<NonnullRefPtr<Client>> launch_generic_server_process(ReadonlySpan<String> candidate_server_paths, StringView serenity_resource_root, StringView server_name)
9192
{
9293
int socket_fds[2] {};
9394
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
9495

9596
int ui_fd = socket_fds[0];
96-
int rc_fd = socket_fds[1];
97+
int server_fd = socket_fds[1];
9798

9899
int fd_passing_socket_fds[2] {};
99100
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds));
100101

101102
int ui_fd_passing_fd = fd_passing_socket_fds[0];
102-
int rc_fd_passing_fd = fd_passing_socket_fds[1];
103+
int server_fd_passing_fd = fd_passing_socket_fds[1];
103104

104105
if (auto child_pid = TRY(Core::System::fork()); child_pid == 0) {
105106
TRY(Core::System::close(ui_fd));
106107
TRY(Core::System::close(ui_fd_passing_fd));
107108

108-
auto takeover_string = TRY(String::formatted("RequestServer:{}", rc_fd));
109+
auto takeover_string = TRY(String::formatted("{}:{}", server_name, server_fd));
109110
TRY(Core::System::setenv("SOCKET_TAKEOVER"sv, takeover_string, true));
110111

111-
auto fd_passing_socket_string = TRY(String::number(rc_fd_passing_fd));
112+
auto fd_passing_socket_string = TRY(String::number(server_fd_passing_fd));
112113

113114
ErrorOr<void> result;
114-
for (auto const& path : candidate_request_server_paths) {
115+
for (auto const& path : candidate_server_paths) {
115116

116117
if (Core::System::access(path, X_OK).is_error())
117118
continue;
118119

119-
auto arguments = Vector {
120+
auto arguments = Vector<StringView, 5> {
120121
path.bytes_as_string_view(),
121122
"--fd-passing-socket"sv,
122123
fd_passing_socket_string,
@@ -130,18 +131,28 @@ ErrorOr<NonnullRefPtr<Protocol::RequestClient>> launch_request_server_process(Re
130131
}
131132

132133
if (result.is_error())
133-
warnln("Could not launch any of {}: {}", candidate_request_server_paths, result.error());
134+
warnln("Could not launch any of {}: {}", candidate_server_paths, result.error());
134135
VERIFY_NOT_REACHED();
135136
}
136137

137-
TRY(Core::System::close(rc_fd));
138-
TRY(Core::System::close(rc_fd_passing_fd));
138+
TRY(Core::System::close(server_fd));
139+
TRY(Core::System::close(server_fd_passing_fd));
139140

140141
auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd));
141142
TRY(socket->set_blocking(true));
142143

143-
auto new_client = TRY(try_make_ref_counted<Protocol::RequestClient>(move(socket)));
144+
auto new_client = TRY(try_make_ref_counted<Client>(move(socket)));
144145
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
145146

146147
return new_client;
147148
}
149+
150+
ErrorOr<NonnullRefPtr<Protocol::RequestClient>> launch_request_server_process(ReadonlySpan<String> candidate_request_server_paths, StringView serenity_resource_root)
151+
{
152+
return launch_generic_server_process<Protocol::RequestClient>(candidate_request_server_paths, serenity_resource_root, "RequestServer"sv);
153+
}
154+
155+
ErrorOr<NonnullRefPtr<Protocol::WebSocketClient>> launch_web_socket_process(ReadonlySpan<String> candidate_web_socket_paths, StringView serenity_resource_root)
156+
{
157+
return launch_generic_server_process<Protocol::WebSocketClient>(candidate_web_socket_paths, serenity_resource_root, "WebSocket"sv);
158+
}

Ladybird/HelperProcess.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <AK/Span.h>
1212
#include <AK/StringView.h>
1313
#include <LibProtocol/RequestClient.h>
14+
#include <LibProtocol/WebSocketClient.h>
1415
#include <LibWebView/ViewImplementation.h>
1516
#include <LibWebView/WebContentClient.h>
1617

@@ -22,3 +23,4 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(Web
2223
Ladybird::UseLagomNetworking);
2324

2425
ErrorOr<NonnullRefPtr<Protocol::RequestClient>> launch_request_server_process(ReadonlySpan<String> candidate_request_server_paths, StringView serenity_resource_root);
26+
ErrorOr<NonnullRefPtr<Protocol::WebSocketClient>> launch_web_socket_process(ReadonlySpan<String> candidate_web_socket_paths, StringView serenity_resource_root);

Ladybird/RequestServer/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <RequestServer/HttpProtocol.h>
2121
#include <RequestServer/HttpsProtocol.h>
2222

23+
// FIXME: Share b/w RequestServer and WebSocket
2324
ErrorOr<String> find_certificates(StringView serenity_resource_root)
2425
{
2526
auto cert_path = TRY(String::formatted("{}/res/ladybird/cacert.pem", serenity_resource_root));

Ladybird/WebContent/main.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <LibWeb/Platform/EventLoopPluginSerenity.h>
3131
#include <LibWeb/WebSockets/WebSocket.h>
3232
#include <LibWebView/RequestServerAdapter.h>
33+
#include <LibWebView/WebSocketClientAdapter.h>
3334
#include <QCoreApplication>
3435
#include <WebContent/ConnectionFromClient.h>
3536
#include <WebContent/PageHost.h>
@@ -56,8 +57,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
5657
return Ladybird::AudioCodecPluginQt::create(move(loader));
5758
});
5859

59-
Web::WebSockets::WebSocketClientManager::initialize(Ladybird::WebSocketClientManagerQt::create());
60-
6160
Web::FrameLoader::set_default_favicon_path(DeprecatedString::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root));
6261

6362
int webcontent_fd_passing_socket { -1 };
@@ -74,10 +73,15 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
7473

7574
if (use_lagom_networking) {
7675
auto candidate_request_server_paths = TRY(get_paths_for_helper_process("RequestServer"sv));
77-
auto protocol_client = TRY(launch_request_server_process(candidate_request_server_paths, s_serenity_resource_root));
78-
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(protocol_client))));
76+
auto request_server_client = TRY(launch_request_server_process(candidate_request_server_paths, s_serenity_resource_root));
77+
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(request_server_client))));
78+
79+
auto candidate_web_socket_paths = TRY(get_paths_for_helper_process("WebSocket"sv));
80+
auto web_socket_client = TRY(launch_web_socket_process(candidate_web_socket_paths, s_serenity_resource_root));
81+
Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create(move(web_socket_client))));
7982
} else {
8083
Web::ResourceLoader::initialize(Ladybird::RequestManagerQt::create());
84+
Web::WebSockets::WebSocketClientManager::initialize(Ladybird::WebSocketClientManagerQt::create());
8185
}
8286

8387
JS::Bytecode::Interpreter::set_enabled(use_javascript_bytecode);

Ladybird/WebSocket/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
set(SOURCES
2+
"${SERENITY_SOURCE_DIR}/Userland/Services/WebSocket/ConnectionFromClient.cpp"
3+
main.cpp
4+
)
5+
6+
add_executable(WebSocketServer ${SOURCES})
7+
set_target_properties(WebSocketServer PROPERTIES OUTPUT_NAME WebSocket)
8+
target_link_libraries(WebSocketServer PRIVATE LibCore LibFileSystem LibIPC LibMain LibTLS LibWebSocket LibWebView)

Ladybird/WebSocket/main.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
3+
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
4+
*
5+
* SPDX-License-Identifier: BSD-2-Clause
6+
*/
7+
8+
#include <AK/LexicalPath.h>
9+
#include <LibCore/ArgsParser.h>
10+
#include <LibCore/EventLoop.h>
11+
#include <LibCore/LocalServer.h>
12+
#include <LibCore/System.h>
13+
#include <LibFileSystem/FileSystem.h>
14+
#include <LibIPC/SingleServer.h>
15+
#include <LibMain/Main.h>
16+
#include <LibTLS/Certificate.h>
17+
#include <WebSocket/ConnectionFromClient.h>
18+
19+
// FIXME: Share b/w RequestServer and WebSocket
20+
ErrorOr<String> find_certificates(StringView serenity_resource_root)
21+
{
22+
auto cert_path = TRY(String::formatted("{}/res/ladybird/cacert.pem", serenity_resource_root));
23+
if (!FileSystem::exists(cert_path)) {
24+
auto app_dir = LexicalPath::dirname(TRY(Core::System::current_executable_path()).to_deprecated_string());
25+
26+
cert_path = TRY(String::formatted("{}/cacert.pem", LexicalPath(app_dir).parent()));
27+
if (!FileSystem::exists(cert_path))
28+
return Error::from_string_view("Don't know how to load certs!"sv);
29+
}
30+
return cert_path;
31+
}
32+
33+
ErrorOr<int> serenity_main(Main::Arguments arguments)
34+
{
35+
int fd_passing_socket { -1 };
36+
StringView serenity_resource_root;
37+
38+
Core::ArgsParser args_parser;
39+
args_parser.add_option(fd_passing_socket, "File descriptor of the fd passing socket", "fd-passing-socket", 'c', "fd-passing-socket");
40+
args_parser.add_option(serenity_resource_root, "Absolute path to directory for serenity resources", "serenity-resource-root", 'r', "serenity-resource-root");
41+
args_parser.parse(arguments);
42+
43+
// Ensure the certificates are read out here.
44+
DefaultRootCACertificates::set_default_certificate_path(TRY(find_certificates(serenity_resource_root)));
45+
[[maybe_unused]] auto& certs = DefaultRootCACertificates::the();
46+
47+
Core::EventLoop event_loop;
48+
49+
auto client = TRY(IPC::take_over_accepted_client_from_system_server<WebSocket::ConnectionFromClient>());
50+
client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket)));
51+
52+
return event_loop.exec();
53+
}

Ladybird/cmake/InstallRules.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ include(GNUInstallDirs)
44

55
set(package ladybird)
66

7-
set(ladybird_applications ladybird SQLServer WebContent WebDriver RequestServer headless-browser)
7+
set(ladybird_applications ladybird SQLServer WebContent WebDriver WebSocketServer RequestServer headless-browser)
88

99
set(app_install_targets ${ladybird_applications})
1010
if (ANDROID)

Meta/Lagom/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,20 +432,25 @@ if (BUILD_LAGOM)
432432
list(APPEND LIBWEBVIEW_SOURCES "../../Userland/Libraries/LibWebView/ViewImplementation.cpp")
433433
list(APPEND LIBWEBVIEW_SOURCES "../../Userland/Libraries/LibWebView/WebContentClient.cpp")
434434
list(APPEND LIBWEBVIEW_SOURCES "../../Userland/Libraries/LibWebView/RequestServerAdapter.cpp")
435+
list(APPEND LIBWEBVIEW_SOURCES "../../Userland/Libraries/LibWebView/WebSocketClientAdapter.cpp")
435436

436437
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebContent/WebContentServer.ipc WebContent/WebContentServerEndpoint.h)
437438
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebContent/WebContentClient.ipc WebContent/WebContentClientEndpoint.h)
438439
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebContent/WebDriverClient.ipc WebContent/WebDriverClientEndpoint.h)
439440
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebContent/WebDriverServer.ipc WebContent/WebDriverServerEndpoint.h)
440441
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/RequestServer/RequestClient.ipc RequestServer/RequestClientEndpoint.h)
441442
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/RequestServer/RequestServer.ipc RequestServer/RequestServerEndpoint.h)
443+
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebSocket/WebSocketClient.ipc WebSocket/WebSocketClientEndpoint.h)
444+
compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebSocket/WebSocketServer.ipc WebSocket/WebSocketServerEndpoint.h)
442445

443446
list(APPEND LIBWEBVIEW_GENERATED_SOURCES WebContent/WebContentClientEndpoint.h)
444447
list(APPEND LIBWEBVIEW_GENERATED_SOURCES WebContent/WebContentServerEndpoint.h)
445448
list(APPEND LIBWEBVIEW_GENERATED_SOURCES WebContent/WebDriverClientEndpoint.h)
446449
list(APPEND LIBWEBVIEW_GENERATED_SOURCES WebContent/WebDriverServerEndpoint.h)
447450
list(APPEND LIBWEBVIEW_GENERATED_SOURCES RequestServer/RequestClientEndpoint.h)
448451
list(APPEND LIBWEBVIEW_GENERATED_SOURCES RequestServer/RequestServerEndpoint.h)
452+
list(APPEND LIBWEBVIEW_GENERATED_SOURCES WebSocket/WebSocketClientEndpoint.h)
453+
list(APPEND LIBWEBVIEW_GENERATED_SOURCES WebSocket/WebSocketServerEndpoint.h)
449454

450455
set(GENERATED_SOURCES ${LIBWEBVIEW_GENERATED_SOURCES})
451456
lagom_lib(LibWebView webview

Meta/gn/secondary/Ladybird/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ executable("ladybird_executable") {
5656
"SQLServer",
5757
"WebContent",
5858
"WebDriver",
59+
"WebSocket",
5960
]
6061
deps = [
6162
":compile_resource_file",
@@ -149,12 +150,14 @@ if (current_os == "mac") {
149150
"SQLServer",
150151
"WebContent",
151152
"WebDriver",
153+
"WebSocket",
152154
]
153155
sources = [
154156
"$root_out_dir/bin/RequestServer",
155157
"$root_out_dir/bin/SQLServer",
156158
"$root_out_dir/bin/WebContent",
157159
"$root_out_dir/bin/WebDriver",
160+
"$root_out_dir/bin/WebSocket",
158161
"$root_out_dir/bin/headless-browser",
159162
"$root_out_dir/bin/ladybird",
160163
]

0 commit comments

Comments
 (0)