mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:38:11 +00:00
Userland: Add try_* IPC handlers
This enables calling auto-generated IPC methods in a way that doesn't crash the client if the peer disconnects.
This commit is contained in:
parent
34cf5cf07f
commit
8a6db55e79
4 changed files with 62 additions and 27 deletions
|
@ -247,6 +247,7 @@ int main(int argc, char** argv)
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <AK/MemoryStream.h>
|
#include <AK/MemoryStream.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
|
#include <AK/Result.h>
|
||||||
#include <AK/URL.h>
|
#include <AK/URL.h>
|
||||||
#include <AK/Utf8View.h>
|
#include <AK/Utf8View.h>
|
||||||
#include <LibCore/AnonymousBuffer.h>
|
#include <LibCore/AnonymousBuffer.h>
|
||||||
|
@ -496,7 +497,7 @@ public:
|
||||||
for (auto& message : endpoint.messages) {
|
for (auto& message : endpoint.messages) {
|
||||||
auto message_generator = endpoint_generator.fork();
|
auto message_generator = endpoint_generator.fork();
|
||||||
|
|
||||||
auto do_implement_proxy = [&](String const& name, Vector<Parameter> const& parameters, bool is_synchronous) {
|
auto do_implement_proxy = [&](String const& name, Vector<Parameter> const& parameters, bool is_synchronous, bool is_try) {
|
||||||
String return_type = "void";
|
String return_type = "void";
|
||||||
if (is_synchronous) {
|
if (is_synchronous) {
|
||||||
if (message.outputs.size() == 1)
|
if (message.outputs.size() == 1)
|
||||||
|
@ -504,14 +505,23 @@ public:
|
||||||
else if (!message.outputs.is_empty())
|
else if (!message.outputs.is_empty())
|
||||||
return_type = message_name(endpoint.name, message.name, true);
|
return_type = message_name(endpoint.name, message.name, true);
|
||||||
}
|
}
|
||||||
|
String inner_return_type = return_type;
|
||||||
|
if (is_try) {
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.append("Result<");
|
||||||
|
builder.append(return_type);
|
||||||
|
builder.append(", IPC::ErrorCode>");
|
||||||
|
return_type = builder.to_string();
|
||||||
|
}
|
||||||
message_generator.set("message.name", message.name);
|
message_generator.set("message.name", message.name);
|
||||||
message_generator.set("message.pascal_name", pascal_case(message.name));
|
message_generator.set("message.pascal_name", pascal_case(message.name));
|
||||||
message_generator.set("message.complex_return_type", return_type);
|
message_generator.set("message.complex_return_type", return_type);
|
||||||
message_generator.set("async_prefix_maybe", is_synchronous ? "" : "async_");
|
message_generator.set("async_prefix_maybe", is_synchronous ? "" : "async_");
|
||||||
|
message_generator.set("try_prefix_maybe", is_try ? "try_" : "");
|
||||||
|
|
||||||
message_generator.set("handler_name", name);
|
message_generator.set("handler_name", name);
|
||||||
message_generator.append(R"~~~(
|
message_generator.append(R"~~~(
|
||||||
@message.complex_return_type@ @async_prefix_maybe@@handler_name@()~~~");
|
@message.complex_return_type@ @try_prefix_maybe@@async_prefix_maybe@@handler_name@()~~~");
|
||||||
|
|
||||||
for (size_t i = 0; i < parameters.size(); ++i) {
|
for (size_t i = 0; i < parameters.size(); ++i) {
|
||||||
auto& parameter = parameters[i];
|
auto& parameter = parameters[i];
|
||||||
|
@ -525,18 +535,21 @@ public:
|
||||||
|
|
||||||
message_generator.append(") {");
|
message_generator.append(") {");
|
||||||
|
|
||||||
if (is_synchronous) {
|
if (is_synchronous && !is_try) {
|
||||||
if (return_type != "void") {
|
if (return_type != "void") {
|
||||||
message_generator.append(R"~~~(
|
message_generator.append(R"~~~(
|
||||||
return )~~~");
|
return )~~~");
|
||||||
if (message.outputs.size() != 1)
|
if (message.outputs.size() != 1)
|
||||||
message_generator.append(" move(*");
|
message_generator.append("move(*");
|
||||||
} else {
|
} else {
|
||||||
message_generator.append(R"~~~(
|
message_generator.append(R"~~~(
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
message_generator.append("m_connection.template send_sync<Messages::@endpoint.name@::@message.pascal_name@>(");
|
message_generator.append("m_connection.template send_sync<Messages::@endpoint.name@::@message.pascal_name@>(");
|
||||||
|
} else if (is_try) {
|
||||||
|
message_generator.append(R"~~~(
|
||||||
|
auto result = m_connection.template send_sync_but_allow_failure<Messages::@endpoint.name@::@message.pascal_name@>()~~~");
|
||||||
} else {
|
} else {
|
||||||
message_generator.append(R"~~~(
|
message_generator.append(R"~~~(
|
||||||
m_connection.post_message(Messages::@endpoint.name@::@message.pascal_name@ { )~~~");
|
m_connection.post_message(Messages::@endpoint.name@::@message.pascal_name@ { )~~~");
|
||||||
|
@ -554,7 +567,7 @@ public:
|
||||||
argument_generator.append(", ");
|
argument_generator.append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_synchronous) {
|
if (is_synchronous && !is_try) {
|
||||||
if (return_type != "void") {
|
if (return_type != "void") {
|
||||||
message_generator.append(")");
|
message_generator.append(")");
|
||||||
}
|
}
|
||||||
|
@ -566,20 +579,36 @@ public:
|
||||||
} else
|
} else
|
||||||
message_generator.append(")");
|
message_generator.append(")");
|
||||||
|
|
||||||
message_generator.append(R"~~~(;
|
message_generator.append(";");
|
||||||
}
|
} else if (is_try) {
|
||||||
|
message_generator.append(R"~~~();
|
||||||
|
if (!result)
|
||||||
|
return IPC::ErrorCode::PeerDisconnected;
|
||||||
)~~~");
|
)~~~");
|
||||||
|
if (inner_return_type != "void") {
|
||||||
|
message_generator.append(R"~~~(
|
||||||
|
return move(*result);
|
||||||
|
)~~~");
|
||||||
|
} else {
|
||||||
|
message_generator.append(R"~~~(
|
||||||
|
return { };
|
||||||
|
)~~~");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message_generator.append(R"~~~( });
|
message_generator.append(R"~~~( });
|
||||||
}
|
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message_generator.append(R"~~~(
|
||||||
|
}
|
||||||
|
)~~~");
|
||||||
};
|
};
|
||||||
|
|
||||||
do_implement_proxy(message.name, message.inputs, message.is_synchronous);
|
do_implement_proxy(message.name, message.inputs, message.is_synchronous, false);
|
||||||
if (message.is_synchronous)
|
if (message.is_synchronous) {
|
||||||
do_implement_proxy(message.name, message.inputs, false);
|
do_implement_proxy(message.name, message.inputs, false, false);
|
||||||
|
do_implement_proxy(message.name, message.inputs, true, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint_generator.append(R"~~~(
|
endpoint_generator.append(R"~~~(
|
||||||
|
|
|
@ -59,8 +59,8 @@ static LaunchServerConnection& connection()
|
||||||
|
|
||||||
bool Launcher::add_allowed_url(const URL& url)
|
bool Launcher::add_allowed_url(const URL& url)
|
||||||
{
|
{
|
||||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::AddAllowedUrl>(url);
|
auto response_or_error = connection().try_add_allowed_url(url);
|
||||||
if (!response) {
|
if (response_or_error.is_error()) {
|
||||||
dbgln("Launcher::add_allowed_url: Failed");
|
dbgln("Launcher::add_allowed_url: Failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,8 @@ bool Launcher::add_allowed_url(const URL& url)
|
||||||
|
|
||||||
bool Launcher::add_allowed_handler_with_any_url(const String& handler)
|
bool Launcher::add_allowed_handler_with_any_url(const String& handler)
|
||||||
{
|
{
|
||||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::AddAllowedHandlerWithAnyUrl>(handler);
|
auto response_or_error = connection().try_add_allowed_handler_with_any_url(handler);
|
||||||
if (!response) {
|
if (response_or_error.is_error()) {
|
||||||
dbgln("Launcher::add_allowed_handler_with_any_url: Failed");
|
dbgln("Launcher::add_allowed_handler_with_any_url: Failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,8 @@ bool Launcher::add_allowed_handler_with_any_url(const String& handler)
|
||||||
|
|
||||||
bool Launcher::add_allowed_handler_with_only_specific_urls(const String& handler, const Vector<URL>& urls)
|
bool Launcher::add_allowed_handler_with_only_specific_urls(const String& handler, const Vector<URL>& urls)
|
||||||
{
|
{
|
||||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::AddAllowedHandlerWithOnlySpecificUrls>(handler, urls);
|
auto response_or_error = connection().try_add_allowed_handler_with_only_specific_urls(handler, urls);
|
||||||
if (!response) {
|
if (response_or_error.is_error()) {
|
||||||
dbgln("Launcher::add_allowed_handler_with_only_specific_urls: Failed");
|
dbgln("Launcher::add_allowed_handler_with_only_specific_urls: Failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,8 @@ bool Launcher::add_allowed_handler_with_only_specific_urls(const String& handler
|
||||||
|
|
||||||
bool Launcher::seal_allowlist()
|
bool Launcher::seal_allowlist()
|
||||||
{
|
{
|
||||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::SealAllowlist>();
|
auto response_or_error = connection().try_seal_allowlist();
|
||||||
if (!response) {
|
if (response_or_error.is_error()) {
|
||||||
dbgln("Launcher::seal_allowlist: Failed");
|
dbgln("Launcher::seal_allowlist: Failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ struct MessageBuffer {
|
||||||
Vector<RefPtr<AutoCloseFileDescriptor>> fds;
|
Vector<RefPtr<AutoCloseFileDescriptor>> fds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ErrorCode : u32 {
|
||||||
|
PeerDisconnected
|
||||||
|
};
|
||||||
|
|
||||||
class Message {
|
class Message {
|
||||||
public:
|
public:
|
||||||
virtual ~Message();
|
virtual ~Message();
|
||||||
|
|
|
@ -42,21 +42,23 @@ Optional<DecodedImage> Client::decode_image(const ByteBuffer& encoded_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(encoded_buffer.data<void>(), encoded_data.data(), encoded_data.size());
|
memcpy(encoded_buffer.data<void>(), encoded_data.data(), encoded_data.size());
|
||||||
auto response = send_sync_but_allow_failure<Messages::ImageDecoderServer::DecodeImage>(move(encoded_buffer));
|
auto response_or_error = try_decode_image(move(encoded_buffer));
|
||||||
|
|
||||||
if (!response) {
|
if (response_or_error.is_error()) {
|
||||||
dbgln("ImageDecoder died heroically");
|
dbgln("ImageDecoder died heroically");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& response = response_or_error.value();
|
||||||
|
|
||||||
DecodedImage image;
|
DecodedImage image;
|
||||||
image.is_animated = response->is_animated();
|
image.is_animated = response.is_animated();
|
||||||
image.loop_count = response->loop_count();
|
image.loop_count = response.loop_count();
|
||||||
image.frames.resize(response->bitmaps().size());
|
image.frames.resize(response.bitmaps().size());
|
||||||
for (size_t i = 0; i < image.frames.size(); ++i) {
|
for (size_t i = 0; i < image.frames.size(); ++i) {
|
||||||
auto& frame = image.frames[i];
|
auto& frame = image.frames[i];
|
||||||
frame.bitmap = response->bitmaps()[i].bitmap();
|
frame.bitmap = response.bitmaps()[i].bitmap();
|
||||||
frame.duration = response->durations()[i];
|
frame.duration = response.durations()[i];
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue