mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-05 23:59:49 +00:00
LibWebSocket+RequestServer: Resolve WebSocket hosts using our resolver
Some checks failed
CI / Lagom (true, NO_FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-24.04, Linux, GNU) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Build Dev Container Image / build (push) Has been cancelled
Some checks failed
CI / Lagom (true, NO_FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-24.04, Linux, GNU) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Build Dev Container Image / build (push) Has been cancelled
This commit is contained in:
parent
eb4c565e57
commit
06faa7b160
Notes:
github-actions[bot]
2025-02-20 22:05:53 +00:00
Author: https://github.com/ADKaster
Commit: 06faa7b160
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3642
Reviewed-by: https://github.com/alimpfard ✅
5 changed files with 82 additions and 42 deletions
|
@ -14,6 +14,7 @@
|
|||
#include <LibCore/Proxy.h>
|
||||
#include <LibCore/Socket.h>
|
||||
#include <LibRequests/NetworkErrorEnum.h>
|
||||
#include <LibRequests/WebSocket.h>
|
||||
#include <LibTLS/TLSv12.h>
|
||||
#include <LibTextCodec/Decoder.h>
|
||||
#include <LibWebSocket/ConnectionInfo.h>
|
||||
|
@ -73,6 +74,24 @@ static NonnullRefPtr<Resolver> default_resolver()
|
|||
return resolver;
|
||||
}
|
||||
|
||||
ByteString build_curl_resolve_list(DNS::LookupResult const& dns_result, StringView host, u16 port)
|
||||
{
|
||||
StringBuilder resolve_opt_builder;
|
||||
resolve_opt_builder.appendff("{}:{}:", host, port);
|
||||
auto first = true;
|
||||
for (auto& addr : dns_result.cached_addresses()) {
|
||||
auto formatted_address = addr.visit(
|
||||
[&](IPv4Address const& ipv4) { return ipv4.to_byte_string(); },
|
||||
[&](IPv6Address const& ipv6) { return MUST(ipv6.to_string()).to_byte_string(); });
|
||||
if (!first)
|
||||
resolve_opt_builder.append(',');
|
||||
first = false;
|
||||
resolve_opt_builder.append(formatted_address);
|
||||
}
|
||||
|
||||
return resolve_opt_builder.to_byte_string();
|
||||
}
|
||||
|
||||
struct ConnectionFromClient::ActiveRequest {
|
||||
CURLM* multi { nullptr };
|
||||
CURL* easy { nullptr };
|
||||
|
@ -463,20 +482,7 @@ void ConnectionFromClient::start_request(i32 request_id, ByteString const& metho
|
|||
set_option(CURLOPT_HEADERFUNCTION, &on_header_received);
|
||||
set_option(CURLOPT_HEADERDATA, reinterpret_cast<void*>(request.ptr()));
|
||||
|
||||
StringBuilder resolve_opt_builder;
|
||||
resolve_opt_builder.appendff("{}:{}:", host, url.port_or_default());
|
||||
auto first = true;
|
||||
for (auto& addr : dns_result->cached_addresses()) {
|
||||
auto formatted_address = addr.visit(
|
||||
[&](IPv4Address const& ipv4) { return ipv4.to_byte_string(); },
|
||||
[&](IPv6Address const& ipv6) { return MUST(ipv6.to_string()).to_byte_string(); });
|
||||
if (!first)
|
||||
resolve_opt_builder.append(',');
|
||||
first = false;
|
||||
resolve_opt_builder.append(formatted_address);
|
||||
}
|
||||
|
||||
auto formatted_address = resolve_opt_builder.to_byte_string();
|
||||
auto formatted_address = build_curl_resolve_list(*dns_result, host, url.port_or_default());
|
||||
if (curl_slist* resolve_list = curl_slist_append(nullptr, formatted_address.characters())) {
|
||||
set_option(CURLOPT_RESOLVE, resolve_list);
|
||||
request->curl_string_lists.append(resolve_list);
|
||||
|
@ -653,37 +659,56 @@ void ConnectionFromClient::ensure_connection(URL::URL const& url, ::RequestServe
|
|||
|
||||
void ConnectionFromClient::websocket_connect(i64 websocket_id, URL::URL const& url, ByteString const& origin, Vector<ByteString> const& protocols, Vector<ByteString> const& extensions, HTTP::HeaderMap const& additional_request_headers)
|
||||
{
|
||||
// FIXME: Use our DNS resolver to resolve the hostname
|
||||
WebSocket::ConnectionInfo connection_info(url);
|
||||
connection_info.set_origin(origin);
|
||||
connection_info.set_protocols(protocols);
|
||||
connection_info.set_extensions(extensions);
|
||||
connection_info.set_headers(additional_request_headers);
|
||||
auto host = url.serialized_host().to_byte_string();
|
||||
|
||||
if (!g_default_certificate_path.is_empty())
|
||||
connection_info.set_root_certificates_path(g_default_certificate_path);
|
||||
// Check if host has the bracket notation for IPV6 addresses and remove them
|
||||
if (host.starts_with("["sv) && host.ends_with("]"sv))
|
||||
host = host.substring(1, host.length() - 2);
|
||||
|
||||
auto impl = WebSocketImplCurl::create(m_curl_multi);
|
||||
auto connection = WebSocket::WebSocket::create(move(connection_info), move(impl));
|
||||
m_resolver->dns.lookup(host, DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA })
|
||||
->when_rejected([this, websocket_id](auto const& error) {
|
||||
dbgln("WebSocketConnect: DNS lookup failed: {}", error);
|
||||
async_websocket_errored(websocket_id, static_cast<i32>(Requests::WebSocket::Error::CouldNotEstablishConnection));
|
||||
})
|
||||
.when_resolved([this, websocket_id, host, url, origin, protocols, extensions, additional_request_headers](auto dns_result) {
|
||||
if (dns_result->records().is_empty() || dns_result->cached_addresses().is_empty()) {
|
||||
dbgln("WebSocketConnect: DNS lookup failed for '{}'", host);
|
||||
async_websocket_errored(websocket_id, static_cast<i32>(Requests::WebSocket::Error::CouldNotEstablishConnection));
|
||||
return;
|
||||
}
|
||||
|
||||
connection->on_open = [this, websocket_id]() {
|
||||
async_websocket_connected(websocket_id);
|
||||
};
|
||||
connection->on_message = [this, websocket_id](auto message) {
|
||||
async_websocket_received(websocket_id, message.is_text(), message.data());
|
||||
};
|
||||
connection->on_error = [this, websocket_id](auto message) {
|
||||
async_websocket_errored(websocket_id, (i32)message);
|
||||
};
|
||||
connection->on_close = [this, websocket_id](u16 code, ByteString reason, bool was_clean) {
|
||||
async_websocket_closed(websocket_id, code, move(reason), was_clean);
|
||||
};
|
||||
connection->on_ready_state_change = [this, websocket_id](auto state) {
|
||||
async_websocket_ready_state_changed(websocket_id, (u32)state);
|
||||
};
|
||||
WebSocket::ConnectionInfo connection_info(url);
|
||||
connection_info.set_origin(origin);
|
||||
connection_info.set_protocols(protocols);
|
||||
connection_info.set_extensions(extensions);
|
||||
connection_info.set_headers(additional_request_headers);
|
||||
connection_info.set_dns_result(move(dns_result));
|
||||
|
||||
connection->start();
|
||||
m_websockets.set(websocket_id, move(connection));
|
||||
if (!g_default_certificate_path.is_empty())
|
||||
connection_info.set_root_certificates_path(g_default_certificate_path);
|
||||
|
||||
auto impl = WebSocketImplCurl::create(m_curl_multi);
|
||||
auto connection = WebSocket::WebSocket::create(move(connection_info), move(impl));
|
||||
|
||||
connection->on_open = [this, websocket_id]() {
|
||||
async_websocket_connected(websocket_id);
|
||||
};
|
||||
connection->on_message = [this, websocket_id](auto message) {
|
||||
async_websocket_received(websocket_id, message.is_text(), message.data());
|
||||
};
|
||||
connection->on_error = [this, websocket_id](auto message) {
|
||||
async_websocket_errored(websocket_id, (i32)message);
|
||||
};
|
||||
connection->on_close = [this, websocket_id](u16 code, ByteString reason, bool was_clean) {
|
||||
async_websocket_closed(websocket_id, code, move(reason), was_clean);
|
||||
};
|
||||
connection->on_ready_state_change = [this, websocket_id](auto state) {
|
||||
async_websocket_ready_state_changed(websocket_id, (u32)state);
|
||||
};
|
||||
|
||||
connection->start();
|
||||
m_websockets.set(websocket_id, move(connection));
|
||||
});
|
||||
}
|
||||
|
||||
void ConnectionFromClient::websocket_send(i64 websocket_id, bool is_text, ByteBuffer const& data)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue