diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_accept_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_accept_task.cpp new file mode 100644 index 000000000..3dfd71bcd --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_accept_task.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result AcceptTask::SetArguments(s32 server_handle) { + /* Check that we're valid. */ + R_UNLESS(this->IsValid(), htcs::ResultInvalidTask()); + + /* Set our arguments. */ + m_server_handle = server_handle; + + return ResultSuccess(); + } + + void AcceptTask::Complete(htcs::SocketError err, s32 desc) { + /* Set our results. */ + m_err = err; + m_desc = desc; + + /* Complete. */ + HtcsSignalingTask::Complete(); + } + + Result AcceptTask::GetResult(htcs::SocketError *out_err, s32 *out_desc, s32 server_handle) const { + /* Check the server handle. */ + R_UNLESS(m_server_handle == server_handle, htcs::ResultInvalidServerHandle()); + + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + *out_desc = m_desc; + + return ResultSuccess(); + } + + Result AcceptTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), packet->params[1]); + + return ResultSuccess(); + } + + Result AcceptTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Accept, + .body_size = 0, + .task_id = task_id, + .params = { + m_server_handle, + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_bind_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_bind_task.cpp new file mode 100644 index 000000000..1149867bc --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_bind_task.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result BindTask::SetArguments(s32 handle, const HtcsPeerName &peer_name, const HtcsPortName &port_name) { + /* Set our arguments. */ + m_handle = handle; + m_peer_name = peer_name; + m_port_name = port_name; + + return ResultSuccess(); + } + + void BindTask::Complete(htcs::SocketError err) { + /* Set our results. */ + m_err = err; + + /* Complete. */ + HtcsTask::Complete(); + } + + Result BindTask::GetResult(htcs::SocketError *out_err) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + + return ResultSuccess(); + } + + Result BindTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0])); + + return ResultSuccess(); + } + + Result BindTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Bind, + .body_size = sizeof(m_peer_name) + sizeof(m_port_name), + .task_id = task_id, + .params = { + m_handle, + }, + }; + std::memcpy(packet->data + 0, std::addressof(m_peer_name), sizeof(m_peer_name)); + std::memcpy(packet->data + sizeof(m_peer_name), std::addressof(m_port_name), sizeof(m_port_name)); + + /* Set the output size. */ + *out = sizeof(*packet) + sizeof(m_peer_name) + sizeof(m_port_name); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_close_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_close_task.cpp new file mode 100644 index 000000000..f896b749e --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_close_task.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result CloseTask::SetArguments(s32 handle) { + /* Set our arguments. */ + m_handle = handle; + + return ResultSuccess(); + } + + void CloseTask::Complete(htcs::SocketError err) { + /* Set our results. */ + m_err = err; + + /* Complete. */ + HtcsTask::Complete(); + } + + Result CloseTask::GetResult(htcs::SocketError *out_err) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + + return ResultSuccess(); + } + + Result CloseTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0])); + + return ResultSuccess(); + } + + Result CloseTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Close, + .body_size = 0, + .task_id = task_id, + .params = { + m_handle, + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_connect_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_connect_task.cpp new file mode 100644 index 000000000..dbbb46d6e --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_connect_task.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result ConnectTask::SetArguments(s32 handle, const HtcsPeerName &peer_name, const HtcsPortName &port_name) { + /* Set our arguments. */ + m_handle = handle; + m_peer_name = peer_name; + m_port_name = port_name; + + return ResultSuccess(); + } + + void ConnectTask::Complete(htcs::SocketError err) { + /* Set our results. */ + m_err = err; + + /* Complete. */ + HtcsTask::Complete(); + } + + Result ConnectTask::GetResult(htcs::SocketError *out_err) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + + return ResultSuccess(); + } + + Result ConnectTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0])); + + return ResultSuccess(); + } + + Result ConnectTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Connect, + .body_size = sizeof(m_peer_name) + sizeof(m_port_name), + .task_id = task_id, + .params = { + m_handle, + }, + }; + std::memcpy(packet->data + 0, std::addressof(m_peer_name), sizeof(m_peer_name)); + std::memcpy(packet->data + sizeof(m_peer_name), std::addressof(m_port_name), sizeof(m_port_name)); + + /* Set the output size. */ + *out = sizeof(*packet) + sizeof(m_peer_name) + sizeof(m_port_name); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_fcntl_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_fcntl_task.cpp new file mode 100644 index 000000000..29d84ffae --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_fcntl_task.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result FcntlTask::SetArguments(s32 handle, s32 command, s32 value) { + /* Set our arguments. */ + m_handle = handle; + m_command = command; + m_value = value; + + return ResultSuccess(); + } + + void FcntlTask::Complete(htcs::SocketError err, s32 res) { + /* Set our results. */ + m_err = err; + m_res = res; + + /* Complete. */ + HtcsTask::Complete(); + } + + Result FcntlTask::GetResult(htcs::SocketError *out_err, s32 *out_res) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + *out_res = m_res; + + return ResultSuccess(); + } + + Result FcntlTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), packet->params[1]); + + return ResultSuccess(); + } + + Result FcntlTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Fcntl, + .body_size = 0, + .task_id = task_id, + .params = { + m_handle, + m_command, + m_value, + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_listen_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_listen_task.cpp new file mode 100644 index 000000000..101157e18 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_listen_task.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result ListenTask::SetArguments(s32 handle, s32 backlog) { + /* Set our arguments. */ + m_handle = handle; + m_backlog = backlog; + + return ResultSuccess(); + } + + void ListenTask::Complete(htcs::SocketError err) { + /* Set our results. */ + m_err = err; + + /* Complete. */ + HtcsTask::Complete(); + } + + Result ListenTask::GetResult(htcs::SocketError *out_err) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + + return ResultSuccess(); + } + + Result ListenTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0])); + + return ResultSuccess(); + } + + Result ListenTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Listen, + .body_size = 0, + .task_id = task_id, + .params = { + m_handle, + m_backlog, + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_receive_small_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_receive_small_task.cpp new file mode 100644 index 000000000..312d8a02b --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_receive_small_task.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result ReceiveSmallTask::SetArguments(s32 handle, s64 size, htcs::MessageFlag flags) { + /* Check that we're valid. */ + R_UNLESS(this->IsValid(), htcs::ResultInvalidTask()); + + /* Set our arguments. */ + m_handle = handle; + m_size = size; + m_flags = flags; + + return ResultSuccess(); + } + + void ReceiveSmallTask::Complete(htcs::SocketError err, s64 size) { + /* Set our results. */ + m_err = err; + m_result_size = size; + + /* Complete. */ + HtcsSignalingTask::Complete(); + } + + Result ReceiveSmallTask::GetResult(htcs::SocketError *out_err, s64 *out_size) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + *out_size = m_result_size; + + return ResultSuccess(); + } + + Result ReceiveSmallTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Copy the data to our buffer. */ + std::memcpy(m_buffer, packet->data, packet->body_size); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), packet->body_size); + + return ResultSuccess(); + } + + Result ReceiveSmallTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Receive, + .body_size = 0, + .task_id = task_id, + .params = { + m_handle, + m_size, + static_cast(m_flags), + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + + bool ReceiveSmallTask::IsReceiveBufferRequired() { + return true; + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_receive_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_receive_task.cpp new file mode 100644 index 000000000..d95420993 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_receive_task.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result ReceiveTask::SetArguments(s32 handle, s64 size, htcs::MessageFlag flags) { + /* Check that we're valid. */ + R_UNLESS(this->IsValid(), htcs::ResultInvalidTask()); + + /* Set our arguments. */ + m_handle = handle; + m_size = size; + m_flags = flags; + + return ResultSuccess(); + } + + void ReceiveTask::Complete(htcs::SocketError err, s64 size) { + /* Set our results. */ + m_err = err; + m_result_size = size; + + /* Complete. */ + HtcsSignalingTask::Complete(); + } + + Result ReceiveTask::GetResult(htcs::SocketError *out_err, s64 *out_size) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + *out_size = m_result_size; + + return ResultSuccess(); + } + + Result ReceiveTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), packet->params[1]); + + return ResultSuccess(); + } + + Result ReceiveTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::ReceiveLarge, + .body_size = 0, + .task_id = task_id, + .params = { + m_handle, + m_size, + static_cast(m_flags), + GetReceiveDataChannelId(task_id), + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + + Result ReceiveTask::CreateNotification(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Notification, + .type = HtcsPacketType::ReceiveLarge, + .body_size = 0, + .task_id = task_id, + .params = { + /* ... */ + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_select_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_select_task.cpp new file mode 100644 index 000000000..09e1507a9 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_select_task.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result SelectTask::SetArguments(Span read_handles, Span write_handles, Span exception_handles, s64 tv_sec, s64 tv_usec) { + /* Check that we're valid. */ + R_UNLESS(this->IsValid(), htcs::ResultInvalidTask()); + + /* Sanity check the spans. */ + AMS_ASSERT(0 <= read_handles.size() && read_handles.size() < static_cast(SocketCountMax)); + AMS_ASSERT(0 <= write_handles.size() && write_handles.size() < static_cast(SocketCountMax)); + AMS_ASSERT(0 <= exception_handles.size() && exception_handles.size() < static_cast(SocketCountMax)); + + /* Set our arguments. */ + m_read_handle_count = static_cast(read_handles.size()); + m_write_handle_count = static_cast(write_handles.size()); + m_exception_handle_count = static_cast(exception_handles.size()); + m_tv_sec = tv_sec; + m_tv_usec = tv_usec; + + /* Copy the handles. */ + std::memcpy(m_handles, read_handles.data(), read_handles.size_bytes()); + std::memcpy(m_handles + m_read_handle_count, write_handles.data(), write_handles.size_bytes()); + std::memcpy(m_handles + m_read_handle_count + m_write_handle_count, exception_handles.data(), exception_handles.size_bytes()); + + return ResultSuccess(); + } + + void SelectTask::Complete(htcs::SocketError err, s32 read_handle_count, s32 write_handle_count, s32 exception_handle_count, const void *body, s64 body_size) { + /* Sanity check the handle counts. */ + const auto handle_count = read_handle_count + write_handle_count + exception_handle_count; + AMS_ASSERT(0 <= read_handle_count && read_handle_count < SocketCountMax); + AMS_ASSERT(0 <= write_handle_count && write_handle_count < SocketCountMax); + AMS_ASSERT(0 <= exception_handle_count && exception_handle_count < SocketCountMax); + AMS_ASSERT(handle_count * static_cast(sizeof(s32)) == body_size); + + /* Set our results. */ + m_err = err; + m_out_read_handle_count = read_handle_count; + m_out_write_handle_count = write_handle_count; + m_out_exception_handle_count = exception_handle_count; + + /* Copy the handles. */ + std::memcpy(m_out_handles, static_cast(body), sizeof(s32) * read_handle_count); + std::memcpy(m_out_handles + read_handle_count, static_cast(body) + read_handle_count, sizeof(s32) * write_handle_count); + std::memcpy(m_out_handles + read_handle_count + write_handle_count, static_cast(body) + read_handle_count + write_handle_count, sizeof(s32) * exception_handle_count); + + /* Complete. */ + HtcsSignalingTask::Complete(); + } + + Result SelectTask::GetResult(htcs::SocketError *out_err, bool *out_empty, Span read_handles, Span write_handles, Span exception_handles) const { + /* Set the output error. */ + *out_err = m_err; + + /* Set the output empty value. */ + const bool empty = m_err == HTCS_ENONE && m_out_read_handle_count == 0 && m_out_write_handle_count == 0 && m_out_exception_handle_count == 0; + *out_empty = empty; + + /* Clear the output spans. */ + std::fill(read_handles.begin(), read_handles.end(), 0); + std::fill(write_handles.begin(), write_handles.end(), 0); + std::fill(exception_handles.begin(), exception_handles.end(), 0); + + /* Copy the handles. */ + if (m_err == HTCS_ENONE && !empty) { + const s32 * const out_read_start = m_out_handles; + const s32 * const out_read_end = out_read_start + m_out_read_handle_count; + const s32 * const out_write_start = out_read_end; + const s32 * const out_write_end = out_write_start + m_out_write_handle_count; + const s32 * const out_exception_start = out_write_end; + const s32 * const out_exception_end = out_exception_start + m_out_exception_handle_count; + std::copy(out_read_start, out_read_end, read_handles.begin()); + std::copy(out_write_start, out_write_end, write_handles.begin()); + std::copy(out_exception_start, out_exception_end, exception_handles.begin()); + } else { + const s32 * const read_start = m_handles; + const s32 * const read_end = read_start + m_read_handle_count; + const s32 * const write_start = read_end; + const s32 * const write_end = write_start + m_write_handle_count; + const s32 * const exception_start = write_end; + const s32 * const exception_end = exception_start + m_exception_handle_count; + std::copy(read_start, read_end, read_handles.begin()); + std::copy(write_start, write_end, write_handles.begin()); + std::copy(exception_start, exception_end, exception_handles.begin()); + } + + return ResultSuccess(); + } + + Result SelectTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), packet->params[1], packet->params[2], packet->params[3], packet->data, size - sizeof(*packet)); + + return ResultSuccess(); + } + + Result SelectTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Determine the body size. */ + const auto handle_count = m_read_handle_count + m_write_handle_count + m_exception_handle_count; + const s64 body_size = static_cast(handle_count * sizeof(s32)); + AMS_ASSERT(sizeof(HtcsRpcPacket) + body_size <= size); + + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Select, + .body_size = body_size, + .task_id = task_id, + .params = { + m_read_handle_count, + m_write_handle_count, + m_exception_handle_count, + m_tv_sec, + m_tv_usec, + }, + }; + + /* Set the packet body. */ + std::memcpy(packet->data, m_handles, body_size); + + /* Set the output size. */ + *out = sizeof(*packet) + body_size; + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_send_small_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_send_small_task.cpp new file mode 100644 index 000000000..1765089ca --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_send_small_task.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + void SendSmallTask::SetBuffer(const void *buffer, s64 buffer_size) { + /* Sanity check the buffer size. */ + AMS_ASSERT(0 <= buffer_size && buffer_size <= static_cast(sizeof(m_buffer))); + + /* Set our buffer. */ + if (buffer_size > 0) { + std::memcpy(m_buffer, buffer, buffer_size); + } + m_buffer_size = buffer_size; + } + + void SendSmallTask::NotifyDataChannelReady() { + /* Notify. */ + this->Notify(); + + /* Signal our ready event. */ + m_ready_event.Signal(); + } + + void SendSmallTask::WaitNotification() { + /* Wait on our ready event. */ + m_ready_event.Wait(); + } + + Result SendSmallTask::SetArguments(s32 handle, s64 size, htcs::MessageFlag flags) { + /* Check that we're valid. */ + R_UNLESS(this->IsValid(), htcs::ResultInvalidTask()); + + /* Set our arguments. */ + m_handle = handle; + m_size = size; + m_flags = flags; + + return ResultSuccess(); + } + + void SendSmallTask::Complete(htcs::SocketError err, s64 size) { + /* Set our results. */ + m_err = err; + m_result_size = size; + + /* Signal our ready event. */ + m_ready_event.Signal(); + + /* Complete. */ + HtcsSignalingTask::Complete(); + } + + Result SendSmallTask::GetResult(htcs::SocketError *out_err, s64 *out_size) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + *out_size = m_result_size; + + return ResultSuccess(); + } + + void SendSmallTask::Cancel(htc::server::rpc::RpcTaskCancelReason reason) { + /* Cancel the task. */ + HtcsSignalingTask::Cancel(reason); + + /* Signal our ready event. */ + m_ready_event.Signal(); + } + + Result SendSmallTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), this->GetSize()); + + return ResultSuccess(); + } + + Result SendSmallTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Sanity check our size. */ + AMS_ASSERT(sizeof(HtcsRpcPacket) + this->GetBufferSize() <= size); + + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Send, + .body_size = this->GetSize(), + .task_id = task_id, + .params = { + m_handle, + m_size, + static_cast(m_flags), + }, + }; + + /* Set the body. */ + if (this->GetSize() > 0) { + std::memcpy(packet->data, this->GetBuffer(), this->GetSize()); + } + + /* Set the output size. */ + *out = sizeof(*packet) + this->GetSize(); + + return ResultSuccess(); + } + + bool SendSmallTask::IsSendBufferRequired() { + return this->GetSize() > 0; + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_send_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_send_task.cpp new file mode 100644 index 000000000..126c4af52 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_send_task.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + void SendTask::SetBuffer(const void *buffer, s64 buffer_size) { + /* Set our buffer. */ + m_buffer = buffer; + m_buffer_size = buffer_size; + } + + void SendTask::NotifyDataChannelReady() { + /* Notify. */ + this->Notify(); + + /* Signal our ready event. */ + m_ready_event.Signal(); + } + + void SendTask::WaitNotification() { + /* Wait on our ready event. */ + m_ready_event.Wait(); + } + + Result SendTask::SetArguments(s32 handle, s64 size, htcs::MessageFlag flags) { + /* Check that we're valid. */ + R_UNLESS(this->IsValid(), htcs::ResultInvalidTask()); + + /* Set our arguments. */ + m_handle = handle; + m_size = size; + m_flags = flags; + + return ResultSuccess(); + } + + void SendTask::Complete(htcs::SocketError err, s64 size) { + /* Set our results. */ + m_err = err; + m_result_size = size; + + /* Signal our ready event. */ + m_ready_event.Signal(); + + /* Complete. */ + HtcsSignalingTask::Complete(); + } + + Result SendTask::GetResult(htcs::SocketError *out_err, s64 *out_size) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + *out_size = m_result_size; + + return ResultSuccess(); + } + + void SendTask::Cancel(htc::server::rpc::RpcTaskCancelReason reason) { + /* Cancel the task. */ + HtcsSignalingTask::Cancel(reason); + + /* Signal our ready event. */ + m_ready_event.Signal(); + } + + Result SendTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), packet->params[1]); + + return ResultSuccess(); + } + + Result SendTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::SendLarge, + .body_size = 0, + .task_id = task_id, + .params = { + m_handle, + m_size, + static_cast(m_flags), + GetSendDataChannelId(task_id), + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + + Result SendTask::ProcessNotification(const char *data, size_t size) { + this->NotifyDataChannelReady(); + return ResultSuccess(); + } + + Result SendTask::CreateNotification(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Notification, + .type = HtcsPacketType::SendLarge, + .body_size = 0, + .task_id = task_id, + .params = { + /* ... */ + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_shutdown_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_shutdown_task.cpp new file mode 100644 index 000000000..c7c5d9a40 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_shutdown_task.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + Result ShutdownTask::SetArguments(s32 handle, ShutdownType how) { + /* Set our arguments. */ + m_handle = handle; + m_how = how; + + return ResultSuccess(); + } + + void ShutdownTask::Complete(htcs::SocketError err) { + /* Set our results. */ + m_err = err; + + /* Complete. */ + HtcsTask::Complete(); + } + + Result ShutdownTask::GetResult(htcs::SocketError *out_err) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + + return ResultSuccess(); + } + + Result ShutdownTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0])); + + return ResultSuccess(); + } + + Result ShutdownTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = this->GetVersion(), + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Shutdown, + .body_size = 0, + .task_id = task_id, + .params = { + m_handle, + static_cast(m_how), + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_signaling_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_signaling_task.cpp new file mode 100644 index 000000000..d1fde1067 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_signaling_task.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + namespace { + + constexpr int MaxEventCount = 0x22; + + constinit os::SdkMutex g_event_count_mutex; + constinit int g_event_count = 0; + + } + + HtcsSignalingTask::HtcsSignalingTask(HtcsTaskType type) : HtcsTask(type), m_is_valid(false) { + /* Acquire the exclusive right to create an event. */ + std::scoped_lock lk(g_event_count_mutex); + + /* Create an event. */ + if (AMS_LIKELY(g_event_count < MaxEventCount)) { + /* Make the event. */ + R_ABORT_UNLESS(os::CreateSystemEvent(std::addressof(m_system_event), os::EventClearMode_ManualClear, true)); + + /* Increment the event count. */ + ++g_event_count; + + /* Mark ourselves as valid. */ + m_is_valid = true; + } + } + + HtcsSignalingTask::~HtcsSignalingTask() { + /* If we have an event, we need to destroy it. */ + if (AMS_LIKELY(m_is_valid)) { + /* Acquire exclusive access to the event count. */ + std::scoped_lock lk(g_event_count_mutex); + + /* Destroy our event. */ + os::DestroySystemEvent(std::addressof(m_system_event)); + + /* Decrement the event count. */ + if ((--g_event_count) < 0) { + g_event_count = 0; + } + } + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_socket_task.cpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_socket_task.cpp new file mode 100644 index 000000000..828fe0ee4 --- /dev/null +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_socket_task.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "htcs_rpc_tasks.hpp" + +namespace ams::htcs::impl::rpc { + + namespace { + + constinit s16 g_protocol_version = HtcsMaxVersion; + + } + + HtcsTask::HtcsTask(HtcsTaskType type) : m_task_type(type), m_version(g_protocol_version) { + /* ... */ + } + + Result SocketTask::SetArguments() { + return ResultSuccess(); + } + + void SocketTask::Complete(htcs::SocketError err, s32 desc) { + /* Set our results. */ + m_err = err; + m_desc = desc; + + /* Complete. */ + HtcsTask::Complete(); + } + + Result SocketTask::GetResult(htcs::SocketError *out_err, s32 *out_desc) const { + /* Sanity check our state. */ + AMS_ASSERT(this->GetTaskState() == htc::server::rpc::RpcTaskState::Completed); + + /* Set the output. */ + *out_err = m_err; + *out_desc = m_desc; + + return ResultSuccess(); + } + + Result SocketTask::ProcessResponse(const char *data, size_t size) { + /* Convert the input to a packet. */ + auto *packet = reinterpret_cast(data); + + /* Update the global protocol version. */ + g_protocol_version = std::min(g_protocol_version, packet->version); + + /* Complete the task. */ + this->Complete(static_cast(packet->params[0]), packet->params[1]); + + return ResultSuccess(); + } + + Result SocketTask::CreateRequest(size_t *out, char *data, size_t size, u32 task_id) { + /* Create the packet. */ + auto *packet = reinterpret_cast(data); + *packet = { + .protocol = HtcsProtocol, + .version = 3, + .category = HtcsPacketCategory::Request, + .type = HtcsPacketType::Socket, + .body_size = 0, + .task_id = task_id, + .params = { + /* ... */ + }, + }; + + /* Set the output size. */ + *out = sizeof(*packet); + + return ResultSuccess(); + } + +} diff --git a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_tasks.hpp b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_tasks.hpp index 582b62858..e4c388189 100644 --- a/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_tasks.hpp +++ b/libraries/libstratosphere/source/htcs/impl/rpc/htcs_rpc_tasks.hpp @@ -35,14 +35,71 @@ namespace ams::htcs::impl::rpc { Select = 12, }; - constexpr inline const s16 ProtocolVersion = 4; + constexpr inline s16 HtcsProtocol = 5; + constexpr inline const s16 HtcsMaxVersion = 4; + + enum class HtcsPacketCategory : s16 { + Request = 0, + Response = 1, + Notification = 2, + }; + + enum class HtcsPacketType : s16 { + Receive = 32, + Send = 33, + Shutdown = 34, + Close = 35, + Connect = 36, + Listen = 37, + Accept = 38, + Socket = 39, + Bind = 40, + Fcntl = 41, + ReceiveLarge = 42, + SendLarge = 43, + Select = 44, + }; + + struct HtcsRpcPacket { + s16 protocol; + s16 version; + HtcsPacketCategory category; + HtcsPacketType type; + s64 body_size; + u32 task_id; + s64 params[5]; + char data[]; + }; + static_assert(sizeof(HtcsRpcPacket) == 0x40); + + constexpr inline u16 ReceiveDataChannelIdBegin = htc::server::rpc::MaxRpcCount; + constexpr inline u16 ReceiveDataChannelIdEnd = ReceiveDataChannelIdBegin + htc::server::rpc::MaxRpcCount; + static_assert(ReceiveDataChannelIdEnd - ReceiveDataChannelIdBegin == htc::server::rpc::MaxRpcCount); + + constexpr inline u16 SendDataChannelIdBegin = ReceiveDataChannelIdEnd; + constexpr inline u16 SendDataChannelIdEnd = SendDataChannelIdBegin + htc::server::rpc::MaxRpcCount; + static_assert(SendDataChannelIdEnd - SendDataChannelIdBegin == htc::server::rpc::MaxRpcCount); + + constexpr inline u16 GetReceiveDataChannelId(u32 task_id) { + const u16 channel_id = task_id + ReceiveDataChannelIdBegin; + AMS_ASSERT(ReceiveDataChannelIdBegin <= channel_id && channel_id < ReceiveDataChannelIdEnd); + + return channel_id; + } + + constexpr inline u16 GetSendDataChannelId(u32 task_id) { + const u16 channel_id = task_id + SendDataChannelIdBegin; + AMS_ASSERT(SendDataChannelIdBegin <= channel_id && channel_id < SendDataChannelIdEnd); + + return channel_id; + } class HtcsTask : public htc::server::rpc::Task { private: HtcsTaskType m_task_type; s16 m_version; public: - HtcsTask(HtcsTaskType type) : m_task_type(type), m_version(ProtocolVersion) { /* ... */ } + HtcsTask(HtcsTaskType type); /* Defined in socket_task.cpp, for namespacing reasons. */ HtcsTaskType GetTaskType() const { return m_task_type; } s16 GetVersion() const { return m_version; } @@ -116,7 +173,7 @@ namespace ams::htcs::impl::rpc { s32 m_handle; s64 m_size; htcs::MessageFlag m_flags; - void *m_buffer; + const void *m_buffer; s64 m_buffer_size; htcs::SocketError m_err; s64 m_result_size; @@ -126,7 +183,7 @@ namespace ams::htcs::impl::rpc { s32 GetHandle() const { return m_handle; } s64 GetSize() const { return m_size; } htcs::MessageFlag GetFlags() const { return m_flags; } - void *GetBuffer() const { return m_buffer; } + const void *GetBuffer() const { return m_buffer; } s64 GetBufferSize() const { return m_buffer_size; } void SetBuffer(const void *buffer, s64 buffer_size); @@ -305,7 +362,7 @@ namespace ams::htcs::impl::rpc { s32 GetValue() const { return m_value; } public: Result SetArguments(s32 handle, s32 command, s32 value); - void Complete(htcs::SocketError err); + void Complete(htcs::SocketError err, s32 res); Result GetResult(htcs::SocketError *out_err, s32 *out_res) const; public: virtual Result ProcessResponse(const char *data, size_t size) override; diff --git a/libraries/libvapours/include/vapours/results/htcs_results.hpp b/libraries/libvapours/include/vapours/results/htcs_results.hpp index 3b3bc0a5d..216fe80ed 100644 --- a/libraries/libvapours/include/vapours/results/htcs_results.hpp +++ b/libraries/libvapours/include/vapours/results/htcs_results.hpp @@ -22,9 +22,11 @@ namespace ams::htcs { R_DEFINE_ERROR_RESULT(InvalidHandle, 9); - R_DEFINE_ERROR_RESULT(InvalidArgument, 2001); - R_DEFINE_ERROR_RESULT(InvalidSize, 2014); - R_DEFINE_ERROR_RESULT(Cancelled, 2021); - R_DEFINE_ERROR_RESULT(Completed, 2023); + R_DEFINE_ERROR_RESULT(InvalidArgument, 2001); + R_DEFINE_ERROR_RESULT(InvalidServerHandle, 2003); + R_DEFINE_ERROR_RESULT(InvalidSize, 2014); + R_DEFINE_ERROR_RESULT(Cancelled, 2021); + R_DEFINE_ERROR_RESULT(Completed, 2023); + R_DEFINE_ERROR_RESULT(InvalidTask, 2103); }