ams: support building unit test programs on windows/linux/macos

This commit is contained in:
Michael Scire
2022-03-06 12:08:20 -08:00
committed by SciresM
parent 9a38be201a
commit 64a97576d0
756 changed files with 33359 additions and 9372 deletions

View File

@@ -15,13 +15,14 @@
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>
#include <stratosphere/tipc/tipc_service_object_base.hpp>
#include <stratosphere/tipc/impl/tipc_impl_command_serialization.hpp>
namespace ams::tipc::impl {
template<typename T>
concept HasDefaultServiceCommandProcessor = requires (T &t, const svc::ipc::MessageBuffer &message_buffer) {
concept HasDefaultServiceCommandProcessor = requires (T &t, const MessageBuffer &message_buffer) {
{ t.ProcessDefaultServiceCommand(message_buffer) } -> std::same_as<Result>;
};
@@ -129,7 +130,7 @@ namespace ams::tipc::impl {
constexpr explicit ImplTemplateBaseT(Args &&...args) : ImplHolder(std::forward<Args>(args)...) { /* ... */ } \
private: \
template<typename ImplType> \
ALWAYS_INLINE Result ProcessDefaultMethod(ImplType *impl, const svc::ipc::MessageBuffer &message_buffer) const { \
ALWAYS_INLINE Result ProcessDefaultMethod(ImplType *impl, const MessageBuffer &message_buffer) const { \
/* Handle a default command. */ \
if constexpr (HasDefaultServiceCommandProcessor<ImplType>) { \
return impl->ProcessDefaultServiceCommand(message_buffer); \
@@ -139,7 +140,7 @@ namespace ams::tipc::impl {
} \
\
template<u16 CommandId, typename ImplType> \
ALWAYS_INLINE Result ProcessMethodById(ImplType *impl, const svc::ipc::MessageBuffer &message_buffer, hos::Version fw_ver) const { \
ALWAYS_INLINE Result ProcessMethodById(ImplType *impl, const MessageBuffer &message_buffer, hos::Version fw_ver) const { \
CMD_MACRO(ImplType, AMS_TIPC_IMPL_PROCESS_METHOD_REQUEST_BY_ID) \
\
return this->ProcessDefaultMethod<ImplType>(impl, message_buffer); \
@@ -159,10 +160,10 @@ namespace ams::tipc::impl {
static_assert(::NAMESPACE::Is##INTERFACE<ImplType>); \
\
/* Get accessor to the message buffer. */ \
const svc::ipc::MessageBuffer message_buffer(svc::ipc::GetMessageBuffer()); \
const MessageBuffer message_buffer(tipc::GetMessageBuffer()); \
\
/* Get decision variables. */ \
const auto tag = svc::ipc::MessageBuffer::MessageHeader(message_buffer).GetTag(); \
const auto tag = MessageBuffer::MessageHeader(message_buffer).GetTag(); \
const auto fw_ver = IsFirmwareVersionAlwaysValid() ? hos::Version_Current : hos::GetVersion(); \
\
/* Process against the command ids. */ \

View File

@@ -29,6 +29,7 @@ namespace ams::tipc {
}
#if defined(ATMOSPHERE_OS_HORIZON)
namespace ams::tipc::impl {
/* Machinery for filtering type lists. */
@@ -302,21 +303,21 @@ namespace ams::tipc::impl {
/* tipc-specific accessors. */
static constexpr bool HasInSpecialHeader = HasProcessId || NumInHandles > 0;
static constexpr svc::ipc::MessageBuffer::MessageHeader InMessageHeader{CommandId, HasInSpecialHeader, 0, NumInBuffers, NumOutBuffers, 0, InDataSize / sizeof(u32), 0};
static constexpr svc::ipc::MessageBuffer::SpecialHeader InSpecialHeader{HasProcessId, NumInCopyHandles, NumInMoveHandles, HasInSpecialHeader};
static constexpr MessageBuffer::MessageHeader InMessageHeader{CommandId, HasInSpecialHeader, 0, NumInBuffers, NumOutBuffers, 0, InDataSize / sizeof(u32), 0};
static constexpr MessageBuffer::SpecialHeader InSpecialHeader{HasProcessId, NumInCopyHandles, NumInMoveHandles, HasInSpecialHeader};
static constexpr auto InMessageProcessIdIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader);
static constexpr auto InMessageHandleIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader) + (HasProcessId ? sizeof(u64) / sizeof(u32) : 0);
static constexpr auto InMessageBufferIndex = svc::ipc::MessageBuffer::GetMapAliasDescriptorIndex(InMessageHeader, InSpecialHeader);
static constexpr auto InMessageRawDataIndex = svc::ipc::MessageBuffer::GetRawDataIndex(InMessageHeader, InSpecialHeader);
static constexpr auto InMessageProcessIdIndex = MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader);
static constexpr auto InMessageHandleIndex = MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader) + (HasProcessId ? sizeof(u64) / sizeof(u32) : 0);
static constexpr auto InMessageBufferIndex = MessageBuffer::GetMapAliasDescriptorIndex(InMessageHeader, InSpecialHeader);
static constexpr auto InMessageRawDataIndex = MessageBuffer::GetRawDataIndex(InMessageHeader, InSpecialHeader);
static constexpr bool HasOutSpecialHeader = NumOutHandles > 0;
static constexpr svc::ipc::MessageBuffer::MessageHeader OutMessageHeader{CommandId, HasOutSpecialHeader, 0, 0, 0, 0, (OutDataSize / sizeof(u32)) + 1, 0};
static constexpr svc::ipc::MessageBuffer::SpecialHeader OutSpecialHeader{false, NumOutCopyHandles, NumOutMoveHandles, HasOutSpecialHeader};
static constexpr MessageBuffer::MessageHeader OutMessageHeader{CommandId, HasOutSpecialHeader, 0, 0, 0, 0, (OutDataSize / sizeof(u32)) + 1, 0};
static constexpr MessageBuffer::SpecialHeader OutSpecialHeader{false, NumOutCopyHandles, NumOutMoveHandles, HasOutSpecialHeader};
static constexpr auto OutMessageHandleIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(OutMessageHeader, OutSpecialHeader);
static constexpr auto OutMessageResultIndex = svc::ipc::MessageBuffer::GetRawDataIndex(OutMessageHeader, OutSpecialHeader);
static constexpr auto OutMessageHandleIndex = MessageBuffer::GetSpecialDataIndex(OutMessageHeader, OutSpecialHeader);
static constexpr auto OutMessageResultIndex = MessageBuffer::GetRawDataIndex(OutMessageHeader, OutSpecialHeader);
static constexpr auto OutMessageRawDataIndex = OutMessageResultIndex + 1;
static constexpr size_t InMessageTotalSize = (InMessageRawDataIndex * sizeof(u32)) + InDataSize;
@@ -410,7 +411,7 @@ namespace ams::tipc::impl {
return reinterpret_cast<uintptr_t>(data + Offset);
}
constexpr ALWAYS_INLINE void CopyTo(const svc::ipc::MessageBuffer &buffer) const {
constexpr ALWAYS_INLINE void CopyTo(const MessageBuffer &buffer) const {
if constexpr (Size > 0) {
buffer.SetRawArray(OutIndex, data, Size);
}
@@ -423,24 +424,24 @@ namespace ams::tipc::impl {
static constexpr size_t NumMove = _NumMove;
static constexpr size_t NumCopy = _NumCopy;
private:
os::NativeHandle move_handles[NumMove];
os::NativeHandle copy_handles[NumCopy];
tipc::NativeHandle move_handles[NumMove];
tipc::NativeHandle copy_handles[NumCopy];
public:
ALWAYS_INLINE OutHandleHolder() { /* ... */ }
template<size_t Index>
constexpr ALWAYS_INLINE os::NativeHandle *GetMoveHandlePointer() {
constexpr ALWAYS_INLINE tipc::NativeHandle *GetMoveHandlePointer() {
static_assert(Index < NumMove, "Index < NumMove");
return move_handles + Index;
}
template<size_t Index>
constexpr ALWAYS_INLINE os::NativeHandle *GetCopyHandlePointer() {
constexpr ALWAYS_INLINE tipc::NativeHandle *GetCopyHandlePointer() {
static_assert(Index < NumCopy, "Index < NumCopy");
return copy_handles + Index;
}
ALWAYS_INLINE void CopyTo(const svc::ipc::MessageBuffer &buffer) const {
ALWAYS_INLINE void CopyTo(const MessageBuffer &buffer) const {
#define _TIPC_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(n) do { if constexpr (NumCopy > n) { buffer.SetHandle(OutIndex + n, copy_handles[n]); } } while (0)
_TIPC_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(0);
_TIPC_OUT_HANDLE_HOLDER_WRITE_COPY_HANDLE(1);
@@ -475,7 +476,7 @@ namespace ams::tipc::impl {
using OutRawHolderType = OutRawHolder<CommandMeta::OutDataSize, CommandMeta::OutDataAlign, CommandMeta::OutMessageRawDataIndex>;
using OutHandleHolderType = OutHandleHolder<CommandMeta::NumOutMoveHandles, CommandMeta::NumOutCopyHandles, CommandMeta::OutMessageHandleIndex>;
private:
static constexpr u64 GetMessageHeaderForCheck(const svc::ipc::MessageBuffer::MessageHeader &header) {
static constexpr u64 GetMessageHeaderForCheck(const MessageBuffer::MessageHeader &header) {
using Value = util::BitPack32::Field<0, BITSIZEOF(util::BitPack32)>;
const util::BitPack32 *data = header.GetData();
@@ -485,7 +486,7 @@ namespace ams::tipc::impl {
return static_cast<u64>(lower) | (static_cast<u64>(upper) << BITSIZEOF(u32));
}
static constexpr u32 GetSpecialHeaderForCheck(const svc::ipc::MessageBuffer::SpecialHeader &header) {
static constexpr u32 GetSpecialHeaderForCheck(const MessageBuffer::SpecialHeader &header) {
using Value = util::BitPack32::Field<0, BITSIZEOF(util::BitPack32)>;
return header.GetHeader()->Get<Value>();
@@ -493,7 +494,7 @@ namespace ams::tipc::impl {
/* Argument deserialization. */
template<size_t Index, typename T = typename std::tuple_element<Index, ArgsType>::type>
static ALWAYS_INLINE typename std::tuple_element<Index, ArgsType>::type DeserializeArgumentImpl(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
static ALWAYS_INLINE typename std::tuple_element<Index, ArgsType>::type DeserializeArgumentImpl(const MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
if constexpr (Info.arg_type == ArgumentType::InData) {
/* New in rawdata. */
@@ -524,12 +525,12 @@ namespace ams::tipc::impl {
} else if constexpr (Info.arg_type == ArgumentType::OutHandle) {
/* New OutHandle. */
if constexpr (std::same_as<T, tipc::OutMoveHandle>) {
os::NativeHandle * const ptr = out_handles_holder.template GetMoveHandlePointer<Info.out_move_handle_index>();
*ptr = os::InvalidNativeHandle;
tipc::NativeHandle * const ptr = out_handles_holder.template GetMoveHandlePointer<Info.out_move_handle_index>();
*ptr = tipc::InvalidNativeHandle;
return T(ptr);
} else if constexpr (std::same_as<T, tipc::OutCopyHandle>) {
os::NativeHandle * const ptr = out_handles_holder.template GetCopyHandlePointer<Info.out_copy_handle_index>();
*ptr = os::InvalidNativeHandle;
tipc::NativeHandle * const ptr = out_handles_holder.template GetCopyHandlePointer<Info.out_copy_handle_index>();
*ptr = tipc::InvalidNativeHandle;
return T(ptr);
} else {
static_assert(!std::is_same<T, T>::value, "Invalid OutHandle kind");
@@ -537,19 +538,19 @@ namespace ams::tipc::impl {
} else if constexpr (Info.arg_type == ArgumentType::Buffer) {
/* NOTE: There are currently no tipc commands which use buffers-with-attributes */
/* If these are added (e.g., NonSecure buffers), implement checking here? */
constexpr size_t MapAliasDescriptorSize = svc::ipc::MessageBuffer::MapAliasDescriptor::GetDataSize();
constexpr size_t MapAliasDescriptorSize = MessageBuffer::MapAliasDescriptor::GetDataSize();
if constexpr (Info.is_send_buffer) {
/* Input send buffer. */
constexpr auto BufferIndex = CommandMeta::InMessageBufferIndex + (Info.send_map_alias_index * MapAliasDescriptorSize / sizeof(util::BitPack32));
const svc::ipc::MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
const MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
return T(descriptor.GetAddress(), descriptor.GetSize());
} else {
/* Input receive buffer. */
constexpr auto BufferIndex = CommandMeta::InMessageBufferIndex + ((CommandMeta::NumInBuffers + Info.recv_map_alias_index) * MapAliasDescriptorSize / sizeof(util::BitPack32));
const svc::ipc::MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
const MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
return T(descriptor.GetAddress(), descriptor.GetSize());
}
} else if constexpr (Info.arg_type == ArgumentType::ProcessId) {
@@ -559,7 +560,7 @@ namespace ams::tipc::impl {
}
}
public:
static ALWAYS_INLINE Result ValidateCommandFormat(const svc::ipc::MessageBuffer &message_buffer) {
static ALWAYS_INLINE Result ValidateCommandFormat(const MessageBuffer &message_buffer) {
/* Validate the message header. */
constexpr auto ExpectedMessageHeader = GetMessageHeaderForCheck(CommandMeta::InMessageHeader);
R_UNLESS(message_buffer.Get64(0) == ExpectedMessageHeader, tipc::ResultInvalidMessageFormat());
@@ -567,7 +568,7 @@ namespace ams::tipc::impl {
/* Validate the special header. */
if constexpr (CommandMeta::HasInSpecialHeader) {
constexpr auto ExpectedSpecialHeader = GetSpecialHeaderForCheck(CommandMeta::InSpecialHeader);
constexpr auto SpecialHeaderIndex = svc::ipc::MessageBuffer::MessageHeader::GetDataSize() / sizeof(util::BitPack32);
constexpr auto SpecialHeaderIndex = MessageBuffer::MessageHeader::GetDataSize() / sizeof(util::BitPack32);
R_UNLESS(message_buffer.Get32(SpecialHeaderIndex) == ExpectedSpecialHeader, tipc::ResultInvalidMessageFormat());
}
@@ -575,11 +576,11 @@ namespace ams::tipc::impl {
}
template<size_t Ix>
static ALWAYS_INLINE auto DeserializeArgument(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
static ALWAYS_INLINE auto DeserializeArgument(const MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
return DeserializeArgumentImpl<Ix>(message_buffer, out_raw_holder, out_handles_holder);
}
static ALWAYS_INLINE void SerializeResults(const svc::ipc::MessageBuffer &message_buffer, const Result &result, const OutRawHolderType &out_raw_holder, const OutHandleHolderType &out_handles_holder) {
static ALWAYS_INLINE void SerializeResults(const MessageBuffer &message_buffer, const Result &result, const OutRawHolderType &out_raw_holder, const OutHandleHolderType &out_handles_holder) {
/* Set output headers. */
message_buffer.Set(CommandMeta::OutMessageHeader);
if constexpr (CommandMeta::HasOutSpecialHeader) {
@@ -607,7 +608,7 @@ namespace ams::tipc::impl {
};
template<u16 _CommmandId, auto ServiceCommandImpl, typename ClassType>
constexpr ALWAYS_INLINE Result InvokeServiceCommandImpl(ClassType *object, const svc::ipc::MessageBuffer &message_buffer) {
constexpr ALWAYS_INLINE Result InvokeServiceCommandImpl(ClassType *object, const MessageBuffer &message_buffer) {
using Return = decltype(FunctionTraits::GetReturnImpl(ServiceCommandImpl));
using TrueArgumentsTuple = decltype(FunctionTraits::GetArgumentsImpl(ServiceCommandImpl));
@@ -641,3 +642,97 @@ namespace ams::tipc::impl {
}
}
#elif defined(ATMOSPHERE_OS_WINDOWS)
namespace ams::tipc::impl {
template<u16 _CommandId, typename ArgumentsTuple>
struct CommandMetaInfo;
template<u16 _CommandId, typename... Arguments>
struct CommandMetaInfo<_CommandId, std::tuple<Arguments...>> {
public:
static constexpr size_t InMessageTotalSize = 0x40; /* TODO */
static constexpr size_t OutMessageTotalSize = 0x40; /* TODO */
};
template<typename CommandMeta>
class CommandProcessor {
public:
static ALWAYS_INLINE Result ValidateCommandFormat(const MessageBuffer &) {
AMS_ABORT("TODO");
}
};
template<u16 _CommmandId, auto ServiceCommandImpl, typename ClassType>
ALWAYS_INLINE Result InvokeServiceCommandImpl(ClassType *object, const MessageBuffer &message_buffer) {
/* TODO: Is some kind of emulated serialization interesting/desirable? */
/* TIPC is generally a huge TODO. */
AMS_UNUSED(object, message_buffer);
AMS_ABORT("TIPC serialization not currently supported on Windows.");
}
}
#elif defined(ATMOSPHERE_OS_LINUX)
namespace ams::tipc::impl {
template<u16 _CommandId, typename ArgumentsTuple>
struct CommandMetaInfo;
template<u16 _CommandId, typename... Arguments>
struct CommandMetaInfo<_CommandId, std::tuple<Arguments...>> {
public:
static constexpr size_t InMessageTotalSize = 0x40; /* TODO */
static constexpr size_t OutMessageTotalSize = 0x40; /* TODO */
};
template<typename CommandMeta>
class CommandProcessor {
public:
static ALWAYS_INLINE Result ValidateCommandFormat(const MessageBuffer &) {
AMS_ABORT("TODO");
}
};
template<u16 _CommmandId, auto ServiceCommandImpl, typename ClassType>
ALWAYS_INLINE Result InvokeServiceCommandImpl(ClassType *object, const MessageBuffer &message_buffer) {
/* TODO: Is some kind of emulated serialization interesting/desirable? */
/* TIPC is generally a huge TODO. */
AMS_UNUSED(object, message_buffer);
AMS_ABORT("TIPC serialization not currently supported on Linux.");
}
}
#elif defined(ATMOSPHERE_OS_MACOS)
namespace ams::tipc::impl {
template<u16 _CommandId, typename ArgumentsTuple>
struct CommandMetaInfo;
template<u16 _CommandId, typename... Arguments>
struct CommandMetaInfo<_CommandId, std::tuple<Arguments...>> {
public:
static constexpr size_t InMessageTotalSize = 0x40; /* TODO */
static constexpr size_t OutMessageTotalSize = 0x40; /* TODO */
};
template<typename CommandMeta>
class CommandProcessor {
public:
static ALWAYS_INLINE Result ValidateCommandFormat(const MessageBuffer &) {
AMS_ABORT("TODO");
}
};
template<u16 _CommmandId, auto ServiceCommandImpl, typename ClassType>
ALWAYS_INLINE Result InvokeServiceCommandImpl(ClassType *object, const MessageBuffer &message_buffer) {
/* TODO: Is some kind of emulated serialization interesting/desirable? */
/* TIPC is generally a huge TODO. */
AMS_UNUSED(object, message_buffer);
AMS_ABORT("TIPC serialization not currently supported on macOS.");
}
}
#else
#error "Unknown OS for tipc Command serialization."
#endif

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#if defined(ATMOSPHERE_OS_HORIZON)
#include <stratosphere/tipc/impl/tipc_impl_message_api.os.horizon.hpp>
#elif defined(ATMOSPHERE_OS_WINDOWS)
#include <stratosphere/tipc/impl/tipc_impl_message_api.os.windows.hpp>
#elif defined(ATMOSPHERE_OS_LINUX)
#include <stratosphere/tipc/impl/tipc_impl_message_api.os.linux.hpp>
#elif defined(ATMOSPHERE_OS_MACOS)
#include <stratosphere/tipc/impl/tipc_impl_message_api.os.macos.hpp>
#else
#error "Unknown OS for tipc message impl"
#endif

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_common.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>
namespace ams::tipc::impl {
inline void Reply(tipc::NativeHandle reply_target) {
/* Perform the reply. */
s32 dummy;
R_TRY_CATCH(svc::ReplyAndReceive(std::addressof(dummy), nullptr, 0, reply_target, 0)) {
R_CATCH(svc::ResultTimedOut) {
/* Timing out is acceptable. */
}
R_CATCH(svc::ResultSessionClosed) {
/* It's okay if we couldn't reply to a closed session. */
}
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
}
ALWAYS_INLINE Result CloseHandle(tipc::NativeHandle handle) {
return svc::CloseHandle(handle);
}
ALWAYS_INLINE Result CreateSession(tipc::NativeHandle *out_server_session_handle, tipc::NativeHandle *out_client_session_handle, bool is_light, uintptr_t name) {
return svc::CreateSession(out_server_session_handle, out_client_session_handle, is_light, name);
}
ALWAYS_INLINE Result AcceptSession(tipc::NativeHandle *out_handle, tipc::NativeHandle port) {
return svc::AcceptSession(out_handle, port);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_common.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>
namespace ams::tipc::impl {
inline void Reply(tipc::NativeHandle reply_target) {
AMS_UNUSED(reply_target);
AMS_ABORT("TODO: tipc Linux Reply");
}
ALWAYS_INLINE Result CloseHandle(tipc::NativeHandle handle) {
AMS_UNUSED(handle);
AMS_ABORT("TODO: tipc Linux CloseHandle");
}
ALWAYS_INLINE Result CreateSession(tipc::NativeHandle *out_server_session_handle, tipc::NativeHandle *out_client_session_handle, bool is_light, uintptr_t name) {
AMS_UNUSED(out_server_session_handle, out_client_session_handle, is_light, name);
AMS_ABORT("TODO: tipc Linux CreateSession");
}
ALWAYS_INLINE Result AcceptSession(tipc::NativeHandle *out_handle, tipc::NativeHandle port) {
AMS_UNUSED(out_handle, port);
AMS_ABORT("TODO: tipc Linux AcceptSession");
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_common.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>
namespace ams::tipc::impl {
inline void Reply(tipc::NativeHandle reply_target) {
AMS_UNUSED(reply_target);
AMS_ABORT("TODO: tipc macOS Reply");
}
ALWAYS_INLINE Result CloseHandle(tipc::NativeHandle handle) {
AMS_UNUSED(handle);
AMS_ABORT("TODO: tipc macOS CloseHandle");
}
ALWAYS_INLINE Result CreateSession(tipc::NativeHandle *out_server_session_handle, tipc::NativeHandle *out_client_session_handle, bool is_light, uintptr_t name) {
AMS_UNUSED(out_server_session_handle, out_client_session_handle, is_light, name);
AMS_ABORT("TODO: tipc macOS CreateSession");
}
ALWAYS_INLINE Result AcceptSession(tipc::NativeHandle *out_handle, tipc::NativeHandle port) {
AMS_UNUSED(out_handle, port);
AMS_ABORT("TODO: tipc macOS AcceptSession");
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_common.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>
namespace ams::tipc::impl {
inline void Reply(tipc::NativeHandle reply_target) {
AMS_UNUSED(reply_target);
AMS_ABORT("TODO: tipc Windows Reply");
}
ALWAYS_INLINE Result CloseHandle(tipc::NativeHandle handle) {
AMS_UNUSED(handle);
AMS_ABORT("TODO: tipc Windows CloseHandle");
}
ALWAYS_INLINE Result CreateSession(tipc::NativeHandle *out_server_session_handle, tipc::NativeHandle *out_client_session_handle, bool is_light, uintptr_t name) {
AMS_UNUSED(out_server_session_handle, out_client_session_handle, is_light, name);
AMS_ABORT("TODO: tipc Windows CreateSession");
}
ALWAYS_INLINE Result AcceptSession(tipc::NativeHandle *out_handle, tipc::NativeHandle port) {
AMS_UNUSED(out_handle, port);
AMS_ABORT("TODO: tipc Windows AcceptSession");
}
}

View File

@@ -60,8 +60,8 @@ namespace ams::tipc {
constexpr ALWAYS_INLINE InBufferBase(const tipc::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
constexpr ALWAYS_INLINE InBufferBase(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE InBufferBase(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
constexpr ALWAYS_INLINE InBufferBase(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE InBufferBase(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE InBufferBase(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
};
class OutBufferBase : public BufferBase {
@@ -74,8 +74,8 @@ namespace ams::tipc {
constexpr ALWAYS_INLINE OutBufferBase(const tipc::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
constexpr ALWAYS_INLINE OutBufferBase(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE OutBufferBase(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
constexpr ALWAYS_INLINE OutBufferBase(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE OutBufferBase(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE OutBufferBase(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
};
template<u32 ExtraAttributes = 0>
@@ -89,10 +89,10 @@ namespace ams::tipc {
constexpr ALWAYS_INLINE InBufferImpl(const tipc::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
constexpr ALWAYS_INLINE InBufferImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE InBufferImpl(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
constexpr ALWAYS_INLINE InBufferImpl(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE InBufferImpl(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE InBufferImpl(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
constexpr ALWAYS_INLINE const u8 *GetPointer() const {
ALWAYS_INLINE const u8 *GetPointer() const {
return reinterpret_cast<const u8 *>(this->GetAddressImpl());
}
@@ -112,10 +112,10 @@ namespace ams::tipc {
constexpr ALWAYS_INLINE OutBufferImpl(const tipc::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
constexpr ALWAYS_INLINE OutBufferImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE OutBufferImpl(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
constexpr ALWAYS_INLINE OutBufferImpl(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE OutBufferImpl(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
ALWAYS_INLINE OutBufferImpl(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
constexpr ALWAYS_INLINE u8 *GetPointer() const {
ALWAYS_INLINE u8 *GetPointer() const {
return reinterpret_cast<u8 *>(this->GetAddressImpl());
}
@@ -134,9 +134,9 @@ namespace ams::tipc {
constexpr ALWAYS_INLINE InArrayImpl(const tipc::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
constexpr ALWAYS_INLINE InArrayImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE InArrayImpl(const T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
ALWAYS_INLINE InArrayImpl(const T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
constexpr ALWAYS_INLINE const T *GetPointer() const {
ALWAYS_INLINE const T *GetPointer() const {
return reinterpret_cast<const T *>(this->GetAddressImpl());
}
@@ -144,7 +144,7 @@ namespace ams::tipc {
return this->GetSizeImpl<T>();
}
constexpr ALWAYS_INLINE const T &operator[](size_t i) const {
ALWAYS_INLINE const T &operator[](size_t i) const {
return this->GetPointer()[i];
}
@@ -167,9 +167,9 @@ namespace ams::tipc {
constexpr ALWAYS_INLINE OutArrayImpl(const tipc::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
constexpr ALWAYS_INLINE OutArrayImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE OutArrayImpl(T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
ALWAYS_INLINE OutArrayImpl(T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
constexpr ALWAYS_INLINE T *GetPointer() const {
ALWAYS_INLINE T *GetPointer() const {
return reinterpret_cast<T *>(this->GetAddressImpl());
}
@@ -177,7 +177,7 @@ namespace ams::tipc {
return this->GetSizeImpl<T>();
}
constexpr ALWAYS_INLINE T &operator[](size_t i) const {
ALWAYS_INLINE T &operator[](size_t i) const {
return this->GetPointer()[i];
}

View File

@@ -17,4 +17,5 @@
#include <vapours.hpp>
#include <stratosphere/ams.hpp>
#include <stratosphere/os.hpp>
#include <stratosphere/sm/sm_types.hpp>
#include <stratosphere/sm/sm_types.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>

View File

@@ -15,6 +15,7 @@
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>
#include <stratosphere/tipc/tipc_object_holder.hpp>
#include <stratosphere/tipc/tipc_service_object_base.hpp>
@@ -56,7 +57,7 @@ namespace ams::tipc {
~DeferrableBaseImpl();
ALWAYS_INLINE void SetDeferralManager(DeferralManagerBase *manager, os::NativeHandle reply_target, ServiceObjectBase *object) {
ALWAYS_INLINE void SetDeferralManager(DeferralManagerBase *manager, tipc::NativeHandle reply_target, ServiceObjectBase *object) {
m_deferral_manager = manager;
m_object_holder.InitializeForDeferralManager(reply_target, object);
}
@@ -68,7 +69,7 @@ namespace ams::tipc {
template<IsResumeKey ResumeKey>
ALWAYS_INLINE void RegisterRetry(ResumeKey key) {
m_resume_key = ConvertToInternalResumeKey(key);
std::memcpy(m_message_buffer_base, svc::ipc::GetMessageBuffer(), m_message_buffer_size);
std::memcpy(m_message_buffer_base, tipc::GetMessageBuffer(), m_message_buffer_size);
}
template<IsResumeKey ResumeKey, typename F>
@@ -86,7 +87,7 @@ namespace ams::tipc {
m_resume_key = 0;
/* Restore message buffer. */
std::memcpy(svc::ipc::GetMessageBuffer(), m_message_buffer_base, m_message_buffer_size);
std::memcpy(tipc::GetMessageBuffer(), m_message_buffer_base, m_message_buffer_size);
/* Process the request. */
return port_manager->ProcessDeferredRequest(m_object_holder);
@@ -145,12 +146,11 @@ namespace ams::tipc {
public:
ALWAYS_INLINE DeferralManagerBase() : m_object_count(0) { /* ... */ }
void AddObject(DeferrableBaseImpl &object, os::NativeHandle reply_target, ServiceObjectBase *service_object) {
void AddObject(DeferrableBaseImpl &object, tipc::NativeHandle reply_target, ServiceObjectBase *service_object) {
/* Set ourselves as the manager for the object. */
object.SetDeferralManager(this, reply_target, service_object);
/* Add the object to our entries. */
AMS_ASSERT(m_object_count < N);
m_objects_base[m_object_count++] = std::addressof(object);
}

View File

@@ -34,28 +34,28 @@ namespace ams::tipc {
template<>
class Out<CopyHandle> {
private:
os::NativeHandle * const m_ptr;
tipc::NativeHandle * const m_ptr;
public:
ALWAYS_INLINE Out(os::NativeHandle *p) : m_ptr(p) { /* ... */ }
ALWAYS_INLINE Out(tipc::NativeHandle *p) : m_ptr(p) { /* ... */ }
ALWAYS_INLINE void SetValue(os::NativeHandle v) const {
ALWAYS_INLINE void SetValue(tipc::NativeHandle v) const {
*m_ptr = v;
}
ALWAYS_INLINE const os::NativeHandle &GetValue() const {
ALWAYS_INLINE const tipc::NativeHandle &GetValue() const {
return *m_ptr;
}
ALWAYS_INLINE os::NativeHandle *GetPointer() const {
ALWAYS_INLINE tipc::NativeHandle *GetPointer() const {
return m_ptr;
}
/* Convenience operators. */
ALWAYS_INLINE os::NativeHandle &operator*() const {
ALWAYS_INLINE tipc::NativeHandle &operator*() const {
return *m_ptr;
}
ALWAYS_INLINE os::NativeHandle *operator->() const {
ALWAYS_INLINE tipc::NativeHandle *operator->() const {
return m_ptr;
}
};
@@ -63,28 +63,28 @@ namespace ams::tipc {
template<>
class Out<MoveHandle> {
private:
os::NativeHandle * const m_ptr;
tipc::NativeHandle * const m_ptr;
public:
ALWAYS_INLINE Out(os::NativeHandle *p) : m_ptr(p) { /* ... */ }
ALWAYS_INLINE Out(tipc::NativeHandle *p) : m_ptr(p) { /* ... */ }
ALWAYS_INLINE void SetValue(os::NativeHandle v) const {
ALWAYS_INLINE void SetValue(tipc::NativeHandle v) const {
*m_ptr = v;
}
ALWAYS_INLINE const os::NativeHandle &GetValue() const {
ALWAYS_INLINE const tipc::NativeHandle &GetValue() const {
return *m_ptr;
}
ALWAYS_INLINE os::NativeHandle *GetPointer() const {
ALWAYS_INLINE tipc::NativeHandle *GetPointer() const {
return m_ptr;
}
/* Convenience operators. */
ALWAYS_INLINE os::NativeHandle &operator*() const {
ALWAYS_INLINE tipc::NativeHandle &operator*() const {
return *m_ptr;
}
ALWAYS_INLINE os::NativeHandle *operator->() const {
ALWAYS_INLINE tipc::NativeHandle *operator->() const {
return m_ptr;
}
};

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::tipc {
namespace impl {
template<typename HandleType>
class DummyMessageBuffer {
public:
class MessageHeader {
public:
MessageHeader() { AMS_ABORT("TODO"); }
MessageHeader(const DummyMessageBuffer &) { AMS_ABORT("TODO"); }
u16 GetTag() const { AMS_ABORT("TODO"); }
};
class SpecialHeader {
public:
SpecialHeader() { AMS_ABORT("TODO"); }
SpecialHeader(const DummyMessageBuffer &, const MessageHeader &) { AMS_ABORT("TODO"); }
bool GetHasProcessId() const { AMS_ABORT("TODO"); }
s32 GetCopyHandleCount() const { AMS_ABORT("TODO"); }
};
public:
DummyMessageBuffer(u32 *) { AMS_ABORT("TODO"); }
DummyMessageBuffer(u32 *, size_t) { AMS_ABORT("TODO"); }
void SetNull() const { AMS_ABORT("TODO"); }
HandleType GetHandle(s32) const { AMS_ABORT("TODO"); }
template<typename T>
const T &GetRaw(s32) const { AMS_ABORT("TODO"); }
static s32 GetSpecialDataIndex(const MessageHeader &, const SpecialHeader &) { AMS_ABORT("TODO"); }
static s32 GetRawDataIndex(const MessageHeader &, const SpecialHeader &) { AMS_ABORT("TODO"); }
};
}
#if defined(ATMOSPHERE_OS_HORIZON)
constexpr inline auto MaximumSessionsPerPort = svc::ArgumentHandleCountMax;
using NativeHandle = svc::Handle;
constexpr inline NativeHandle InvalidNativeHandle = svc::InvalidHandle;
using MessageBuffer = ::ams::svc::ipc::MessageBuffer;
ALWAYS_INLINE u32 *GetMessageBuffer() { return svc::ipc::GetMessageBuffer(); }
constexpr ALWAYS_INLINE u32 EncodeNativeHandleForMessageQueue(NativeHandle h) { return static_cast<u32>(h); }
constexpr ALWAYS_INLINE NativeHandle DecodeNativeHandleForMessageQueue(u32 v) { return static_cast<NativeHandle>(v); }
#elif defined(ATMOSPHERE_OS_WINDOWS)
/* TODO */
constexpr inline auto MaximumSessionsPerPort = 0x40;
using NativeHandle = void *;
constexpr inline NativeHandle InvalidNativeHandle = nullptr;
using MessageBuffer = ::ams::tipc::impl::DummyMessageBuffer<NativeHandle>;
ALWAYS_INLINE u32 *GetMessageBuffer() { AMS_ABORT("TODO"); }
ALWAYS_INLINE u32 EncodeNativeHandleForMessageQueue(NativeHandle) { AMS_ABORT("TODO"); }
ALWAYS_INLINE NativeHandle DecodeNativeHandleForMessageQueue(u32) { AMS_ABORT("TODO"); }
#elif defined(ATMOSPHERE_OS_LINUX)
/* TODO */
constexpr inline auto MaximumSessionsPerPort = 0x40;
using NativeHandle = s32;
constexpr inline NativeHandle InvalidNativeHandle = -1;
using MessageBuffer = ::ams::tipc::impl::DummyMessageBuffer<NativeHandle>;
ALWAYS_INLINE u32 *GetMessageBuffer() { AMS_ABORT("TODO"); }
ALWAYS_INLINE u32 EncodeNativeHandleForMessageQueue(NativeHandle) { AMS_ABORT("TODO"); }
ALWAYS_INLINE NativeHandle DecodeNativeHandleForMessageQueue(u32) { AMS_ABORT("TODO"); }
#elif defined(ATMOSPHERE_OS_MACOS)
/* TODO */
constexpr inline auto MaximumSessionsPerPort = 0x40;
using NativeHandle = s32;
constexpr inline NativeHandle InvalidNativeHandle = -1;
using MessageBuffer = ::ams::tipc::impl::DummyMessageBuffer<NativeHandle>;
ALWAYS_INLINE u32 *GetMessageBuffer() { AMS_ABORT("TODO"); }
ALWAYS_INLINE u32 EncodeNativeHandleForMessageQueue(NativeHandle) { AMS_ABORT("TODO"); }
ALWAYS_INLINE NativeHandle DecodeNativeHandleForMessageQueue(u32) { AMS_ABORT("TODO"); }
#else
#error "Unknown OS for tipc platform types."
#endif
namespace impl {
}
}

View File

@@ -30,12 +30,12 @@ namespace ams::tipc {
ObjectType_Deferral = ObjectType_Invalid,
};
private:
os::NativeHandle m_handle;
tipc::NativeHandle m_handle;
ObjectType m_type;
bool m_managed;
tipc::ServiceObjectBase *m_object;
private:
void InitializeImpl(ObjectType type, os::NativeHandle handle, bool managed, tipc::ServiceObjectBase *object) {
void InitializeImpl(ObjectType type, tipc::NativeHandle handle, bool managed, tipc::ServiceObjectBase *object) {
/* Validate that the object isn't already constructed. */
AMS_ASSERT(m_type == ObjectType_Invalid);
@@ -46,20 +46,20 @@ namespace ams::tipc {
m_object = object;
}
public:
constexpr inline ObjectHolder() : m_handle(os::InvalidNativeHandle), m_type(ObjectType_Invalid), m_managed(false), m_object(nullptr) { /* ... */ }
constexpr inline ObjectHolder() : m_handle(tipc::InvalidNativeHandle), m_type(ObjectType_Invalid), m_managed(false), m_object(nullptr) { /* ... */ }
void InitializeAsPort(os::NativeHandle handle) {
void InitializeAsPort(tipc::NativeHandle handle) {
/* NOTE: Nintendo sets ports as managed, but this will cause a nullptr-deref if one is ever closed. */
/* This is theoretically a non-issue, as ports can't be closed, but we will set ours as unmanaged, */
/* just in case. */
this->InitializeImpl(ObjectType_Port, handle, false, nullptr);
}
void InitializeAsSession(os::NativeHandle handle, bool managed, tipc::ServiceObjectBase *object) {
void InitializeAsSession(tipc::NativeHandle handle, bool managed, tipc::ServiceObjectBase *object) {
this->InitializeImpl(ObjectType_Session, handle, managed, object);
}
void InitializeForDeferralManager(os::NativeHandle handle, tipc::ServiceObjectBase *object) {
void InitializeForDeferralManager(tipc::NativeHandle handle, tipc::ServiceObjectBase *object) {
this->InitializeImpl(ObjectType_Deferral, handle, false, object);
}
@@ -75,13 +75,13 @@ namespace ams::tipc {
}
/* Reset all fields. */
m_handle = os::InvalidNativeHandle;
m_handle = tipc::InvalidNativeHandle;
m_type = ObjectType_Invalid;
m_managed = false;
m_object = nullptr;
}
constexpr os::NativeHandle GetHandle() const {
constexpr tipc::NativeHandle GetHandle() const {
return m_handle;
}

View File

@@ -16,6 +16,7 @@
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_common.hpp>
#include <stratosphere/tipc/impl/tipc_impl_message_api.hpp>
#include <stratosphere/tipc/tipc_service_object.hpp>
#include <stratosphere/tipc/tipc_object_holder.hpp>
@@ -37,7 +38,7 @@ namespace ams::tipc {
Entry *m_entries_end{};
os::MultiWaitType *m_multi_wait{};
private:
Entry *FindEntry(os::NativeHandle handle) {
Entry *FindEntry(tipc::NativeHandle handle) {
for (Entry *cur = m_entries_start; cur != m_entries_end; ++cur) {
if (GetReference(cur->object).GetHandle() == handle) {
return cur;
@@ -76,7 +77,7 @@ namespace ams::tipc {
std::scoped_lock lk(m_mutex);
/* Find an empty entry. */
auto *entry = this->FindEntry(os::InvalidNativeHandle);
auto *entry = this->FindEntry(tipc::InvalidNativeHandle);
AMS_ABORT_UNLESS(entry != nullptr);
/* Set the entry's object. */
@@ -87,7 +88,7 @@ namespace ams::tipc {
os::LinkMultiWaitHolder(m_multi_wait, std::addressof(entry->multi_wait_holder));
}
void CloseObject(os::NativeHandle handle) {
void CloseObject(tipc::NativeHandle handle) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
@@ -103,14 +104,14 @@ namespace ams::tipc {
GetReference(entry->object).Destroy();
}
Result ReplyAndReceive(os::MultiWaitHolderType **out_holder, ObjectHolder *out_object, os::NativeHandle reply_target, os::MultiWaitType *multi_wait) {
Result ReplyAndReceive(os::MultiWaitHolderType **out_holder, ObjectHolder *out_object, tipc::NativeHandle reply_target, os::MultiWaitType *multi_wait) {
/* Declare signaled holder for processing ahead of time. */
os::MultiWaitHolderType *signaled_holder;
/* Reply and receive until we get a newly signaled target. */
Result result = os::SdkReplyAndReceive(out_holder, reply_target, multi_wait);
for (signaled_holder = *out_holder; signaled_holder == nullptr; signaled_holder = *out_holder) {
result = os::SdkReplyAndReceive(out_holder, os::InvalidNativeHandle, multi_wait);
result = os::SdkReplyAndReceive(out_holder, tipc::InvalidNativeHandle, multi_wait);
}
/* Find the entry matching the signaled holder. */
@@ -125,32 +126,23 @@ namespace ams::tipc {
}
}
void Reply(os::NativeHandle reply_target) {
/* Perform the reply. */
s32 dummy;
R_TRY_CATCH(svc::ReplyAndReceive(std::addressof(dummy), nullptr, 0, reply_target, 0)) {
R_CATCH(svc::ResultTimedOut) {
/* Timing out is acceptable. */
}
R_CATCH(svc::ResultSessionClosed) {
/* It's okay if we couldn't reply to a closed session. */
}
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
void Reply(tipc::NativeHandle reply_target) {
return tipc::impl::Reply(reply_target);
}
Result ProcessRequest(ObjectHolder &object) {
/* Get the message buffer. */
const svc::ipc::MessageBuffer message_buffer(svc::ipc::GetMessageBuffer());
const MessageBuffer message_buffer(tipc::GetMessageBuffer());
/* Get the method id. */
const auto method_id = svc::ipc::MessageBuffer::MessageHeader(message_buffer).GetTag();
const auto method_id = MessageBuffer::MessageHeader(message_buffer).GetTag();
/* Process for the method id. */
{
/* Ensure that if we fail, we clean up any handles that get sent our way. */
ON_RESULT_FAILURE {
const svc::ipc::MessageBuffer::MessageHeader message_header(message_buffer);
const svc::ipc::MessageBuffer::SpecialHeader special_header(message_buffer, message_header);
const MessageBuffer::MessageHeader message_header(message_buffer);
const MessageBuffer::SpecialHeader special_header(message_buffer, message_header);
/* Determine the offset to the start of handles. */
auto offset = message_buffer.GetSpecialDataIndex(message_header, special_header);
@@ -160,8 +152,8 @@ namespace ams::tipc {
/* Close all copy handles. */
for (auto i = 0; i < special_header.GetCopyHandleCount(); ++i) {
svc::CloseHandle(message_buffer.GetHandle(offset));
offset += sizeof(ams::svc::Handle) / sizeof(u32);
tipc::impl::CloseHandle(message_buffer.GetHandle(offset));
offset += sizeof(typename std::remove_reference<decltype(message_buffer.GetHandle(offset))>::type) / sizeof(u32);
}
};
@@ -191,7 +183,7 @@ namespace ams::tipc {
/* Close the object's handle. */
/* NOTE: Nintendo does not check that this succeeds. */
R_ABORT_UNLESS(svc::CloseHandle(handle));
R_ABORT_UNLESS(tipc::impl::CloseHandle(handle));
/* Return an error to signify we closed the object. */
R_THROW(tipc::ResultSessionClosed());

View File

@@ -25,9 +25,9 @@ namespace ams::tipc {
public:
constexpr PointerAndSize() : m_pointer(0), m_size(0) { /* ... */ }
constexpr PointerAndSize(uintptr_t ptr, size_t sz) : m_pointer(ptr), m_size(sz) { /* ... */ }
constexpr PointerAndSize(void *ptr, size_t sz) : PointerAndSize(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
PointerAndSize(void *ptr, size_t sz) : PointerAndSize(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
constexpr ALWAYS_INLINE void *GetPointer() const {
ALWAYS_INLINE void *GetPointer() const {
return reinterpret_cast<void *>(m_pointer);
}

View File

@@ -50,16 +50,16 @@ namespace ams::tipc {
static_assert(NumPorts > 0);
/* Verify that it's possible to service this many sessions, with our port manager count. */
static_assert(MaxSessions <= NumPorts * svc::ArgumentHandleCountMax);
static_assert(MaxSessions <= NumPorts * MaximumSessionsPerPort);
static_assert(util::IsAligned(ThreadStackSize, os::ThreadStackAlignment));
alignas(os::ThreadStackAlignment) static constinit inline u8 s_port_stacks[ThreadStackSize * (NumPorts - 1)];
template<size_t Ix> requires (Ix < NumPorts)
template<size_t Ix> AMS_CONCEPTS_REQUIRES_IF_SUPPORTED(Ix < NumPorts)
static constexpr inline size_t SessionsPerPortManager = (Ix == NumPorts - 1) ? ((MaxSessions / NumPorts) + MaxSessions % NumPorts)
: ((MaxSessions / NumPorts));
template<size_t Ix> requires (Ix < NumPorts)
template<size_t Ix> AMS_CONCEPTS_REQUIRES_IF_SUPPORTED(Ix < NumPorts)
using PortInfo = typename std::tuple_element<Ix, std::tuple<PortInfos...>>::type;
static_assert(IsDeferralSupported == (PortInfos::CanDeferInvokeRequest || ...));
@@ -69,7 +69,7 @@ namespace ams::tipc {
using DeferralManagerBaseType = typename std::conditional<IsDeferralSupported, DeferralManagerBase, DummyDeferralManagerBase>::type;
template<size_t Ix> requires (Ix < NumPorts)
template<size_t Ix> AMS_CONCEPTS_REQUIRES_IF_SUPPORTED(Ix < NumPorts)
static constexpr inline bool IsPortDeferrable = PortInfo<Ix>::CanDeferInvokeRequest;
public:
class PortManagerBase {
@@ -125,7 +125,7 @@ namespace ams::tipc {
m_deferral_manager = dm;
}
void RegisterPort(s32 index, os::NativeHandle port_handle) {
void RegisterPort(s32 index, tipc::NativeHandle port_handle) {
/* Set our port number. */
m_port_number = index;
@@ -139,7 +139,7 @@ namespace ams::tipc {
m_object_manager->AddObject(object);
}
os::NativeHandle ProcessRequest(ObjectHolder &object) {
tipc::NativeHandle ProcessRequest(ObjectHolder &object) {
/* Acquire exclusive server manager access. */
std::scoped_lock lk(m_server_manager->GetMutex());
@@ -147,13 +147,13 @@ namespace ams::tipc {
const Result result = m_object_manager->ProcessRequest(object);
if (R_SUCCEEDED(result)) {
/* We should reply only if the request isn't deferred. */
return !IsRequestDeferred() ? object.GetHandle() : os::InvalidNativeHandle;
return !IsRequestDeferred() ? object.GetHandle() : tipc::InvalidNativeHandle;
} else {
/* Processing failed, so note the session as closed (or close it). */
this->CloseSessionIfNecessary(object, !tipc::ResultSessionClosed::Includes(result));
/* We shouldn't reply on failure. */
return os::InvalidNativeHandle;
return tipc::InvalidNativeHandle;
}
}
@@ -161,15 +161,15 @@ namespace ams::tipc {
void ProcessDeferredRequest(ObjectHolder &object) {
static_assert(Enable == IsDeferralSupported);
if (const auto reply_target = this->ProcessRequest(object); reply_target != os::InvalidNativeHandle) {
if (const auto reply_target = this->ProcessRequest(object); reply_target != tipc::InvalidNativeHandle) {
m_object_manager->Reply(reply_target);
}
}
bool ReplyAndReceive(os::MultiWaitHolderType **out_holder, ObjectHolder *out_object, os::NativeHandle reply_target) {
bool ReplyAndReceive(os::MultiWaitHolderType **out_holder, ObjectHolder *out_object, tipc::NativeHandle reply_target) {
/* If we don't have a reply target, clear our message buffer. */
if (reply_target == os::InvalidNativeHandle) {
svc::ipc::MessageBuffer(svc::ipc::GetMessageBuffer()).SetNull();
if (reply_target == tipc::InvalidNativeHandle) {
tipc::MessageBuffer(tipc::GetMessageBuffer()).SetNull();
}
/* Try to reply/receive. */
@@ -192,7 +192,7 @@ namespace ams::tipc {
return true;
}
void AddSession(os::NativeHandle session_handle, tipc::ServiceObjectBase *service_object) {
void AddSession(tipc::NativeHandle session_handle, tipc::ServiceObjectBase *service_object) {
/* Create an object holder for the session. */
tipc::ObjectHolder object;
@@ -215,7 +215,7 @@ namespace ams::tipc {
case MessageType_AddSession:
{
/* Get the handle from where it's packed into the message type. */
const os::NativeHandle session_handle = static_cast<os::NativeHandle>(message_type >> BITSIZEOF(u32));
const tipc::NativeHandle session_handle = tipc::DecodeNativeHandleForMessageQueue(message_type >> BITSIZEOF(u32));
/* Allocate a service object for the port. */
auto *service_object = m_server_manager->AllocateObject(static_cast<size_t>(message_data), session_handle, *m_deferral_manager);
@@ -243,7 +243,7 @@ namespace ams::tipc {
m_object_manager->CloseObject(handle);
/* Close the handle itself. */
R_ABORT_UNLESS(svc::CloseHandle(handle));
R_ABORT_UNLESS(tipc::impl::CloseHandle(handle));
/* Decrement our session count. */
--m_num_sessions;
@@ -258,7 +258,7 @@ namespace ams::tipc {
m_object_manager->CloseObject(handle);
/* Close the handle itself. */
R_ABORT_UNLESS(svc::CloseHandle(handle));
R_ABORT_UNLESS(tipc::impl::CloseHandle(handle));
}
/* Decrement our session count. */
@@ -286,12 +286,12 @@ namespace ams::tipc {
os::SendMessageQueue(std::addressof(m_message_queue), key);
}
void TriggerAddSession(os::NativeHandle session_handle, size_t port_index) {
void TriggerAddSession(tipc::NativeHandle session_handle, size_t port_index) {
/* Increment our session count. */
++m_num_sessions;
/* Send information about the session as a message. */
os::SendMessageQueue(std::addressof(m_message_queue), static_cast<uintptr_t>(MessageType_AddSession) | (static_cast<u64>(session_handle) << BITSIZEOF(u32)));
os::SendMessageQueue(std::addressof(m_message_queue), static_cast<uintptr_t>(MessageType_AddSession) | (static_cast<u64>(tipc::EncodeNativeHandleForMessageQueue(session_handle)) << BITSIZEOF(u32)));
os::SendMessageQueue(std::addressof(m_message_queue), static_cast<uintptr_t>(port_index));
}
private:
@@ -306,11 +306,11 @@ namespace ams::tipc {
static bool IsRequestDeferred() {
if constexpr (IsDeferralSupported) {
/* Get the message buffer. */
const svc::ipc::MessageBuffer message_buffer(svc::ipc::GetMessageBuffer());
const tipc::MessageBuffer message_buffer(tipc::GetMessageBuffer());
/* Parse the hipc headers. */
const svc::ipc::MessageBuffer::MessageHeader message_header(message_buffer);
const svc::ipc::MessageBuffer::SpecialHeader special_header(message_buffer, message_header);
const tipc::MessageBuffer::MessageHeader message_header(message_buffer);
const tipc::MessageBuffer::SpecialHeader special_header(message_buffer, message_header);
/* Determine raw data index. */
const auto raw_data_offset = message_buffer.GetRawDataIndex(message_header, special_header);
@@ -406,14 +406,14 @@ namespace ams::tipc {
}
template<size_t Ix>
void RegisterPort(os::NativeHandle port_handle) {
void RegisterPort(tipc::NativeHandle port_handle) {
this->GetPortManager<Ix>().RegisterPort(static_cast<s32>(Ix), port_handle);
}
template<size_t Ix>
void RegisterPort(sm::ServiceName service_name, size_t max_sessions) {
/* Register service. */
os::NativeHandle port_handle;
tipc::NativeHandle port_handle;
R_ABORT_UNLESS(sm::RegisterService(std::addressof(port_handle), service_name, max_sessions, false));
/* Register the port handle. */
@@ -454,7 +454,7 @@ namespace ams::tipc {
this->LoopAutoForPort<NumPorts - 1>();
}
tipc::ServiceObjectBase *AllocateObject(size_t port_index, os::NativeHandle handle, DeferralManagerBaseType &deferral_manager) {
tipc::ServiceObjectBase *AllocateObject(size_t port_index, tipc::NativeHandle handle, DeferralManagerBaseType &deferral_manager) {
/* Check that the port index is valid. */
AMS_ABORT_UNLESS(port_index < NumPorts);
@@ -483,13 +483,13 @@ namespace ams::tipc {
}(std::make_index_sequence<NumPorts>());
}
Result AddSession(os::NativeHandle *out, tipc::ServiceObjectBase *object) {
Result AddSession(tipc::NativeHandle *out, tipc::ServiceObjectBase *object) {
/* Acquire exclusive access to ourselves. */
std::scoped_lock lk(m_mutex);
/* Create a handle for the session. */
svc::Handle session_handle;
R_TRY(svc::CreateSession(std::addressof(session_handle), static_cast<svc::Handle *>(out), false, 0));
tipc::NativeHandle session_handle;
R_TRY(tipc::impl::CreateSession(std::addressof(session_handle), static_cast<tipc::NativeHandle *>(out), false, 0));
/* Select the best port manager. */
PortManagerBase *best_manager = nullptr;
@@ -505,7 +505,7 @@ namespace ams::tipc {
}
private:
template<size_t Ix> requires (Ix < NumPorts)
void TryAllocateObject(size_t port_index, os::NativeHandle handle, DeferralManagerBaseType &deferral_manager, tipc::ServiceObjectBase *&allocated) {
void TryAllocateObject(size_t port_index, tipc::NativeHandle handle, DeferralManagerBaseType &deferral_manager, tipc::ServiceObjectBase *&allocated) {
/* Check that the port index matches. */
if (port_index == Ix) {
/* Check that we haven't already allocated. */
@@ -535,13 +535,13 @@ namespace ams::tipc {
Result LoopProcess(PortManagerBase &port_manager) {
/* Process requests forever. */
os::NativeHandle reply_target = os::InvalidNativeHandle;
tipc::NativeHandle reply_target = tipc::InvalidNativeHandle;
while (true) {
/* Reply to our pending request, and wait to receive a new one. */
os::MultiWaitHolderType *signaled_holder = nullptr;
tipc::ObjectHolder signaled_object{};
while (!port_manager.ReplyAndReceive(std::addressof(signaled_holder), std::addressof(signaled_object), reply_target)) {
reply_target = os::InvalidNativeHandle;
reply_target = tipc::InvalidNativeHandle;
signaled_object = {};
}
@@ -551,13 +551,13 @@ namespace ams::tipc {
case ObjectHolder::ObjectType_Port:
{
/* Try to accept a new session */
svc::Handle session_handle;
if (R_SUCCEEDED(svc::AcceptSession(std::addressof(session_handle), signaled_object.GetHandle()))) {
tipc::NativeHandle session_handle;
if (R_SUCCEEDED(tipc::impl::AcceptSession(std::addressof(session_handle), signaled_object.GetHandle()))) {
this->TriggerAddSession(session_handle, static_cast<size_t>(port_manager.GetPortIndex()));
}
/* We have nothing to reply to. */
reply_target = os::InvalidNativeHandle;
reply_target = tipc::InvalidNativeHandle;
}
break;
case ObjectHolder::ObjectType_Session:
@@ -573,12 +573,12 @@ namespace ams::tipc {
port_manager.ProcessMessages();
/* We have nothing to reply to. */
reply_target = os::InvalidNativeHandle;
reply_target = tipc::InvalidNativeHandle;
}
}
}
void TriggerAddSession(os::NativeHandle session_handle, size_t port_index) {
void TriggerAddSession(tipc::NativeHandle session_handle, size_t port_index) {
/* Acquire exclusive access to ourselves. */
std::scoped_lock lk(m_mutex);
@@ -634,7 +634,7 @@ namespace ams::tipc {
static constexpr inline size_t MaxSessions = PortInfo::MaxSessions;
/* Verify that it's possible to service this many sessions, with our port manager count. */
static_assert(MaxSessions <= svc::ArgumentHandleCountMax);
static_assert(MaxSessions <= MaximumSessionsPerPort);
public:
class PortManagerBase {
protected:
@@ -651,7 +651,7 @@ namespace ams::tipc {
m_object_manager = om;
}
void RegisterPort(os::NativeHandle port_handle) {
void RegisterPort(tipc::NativeHandle port_handle) {
/* Create an object holder for the port. */
tipc::ObjectHolder object;
@@ -662,7 +662,7 @@ namespace ams::tipc {
m_object_manager->AddObject(object);
}
os::NativeHandle ProcessRequest(ObjectHolder &object) {
tipc::NativeHandle ProcessRequest(ObjectHolder &object) {
/* Process the request. */
const Result result = m_object_manager->ProcessRequest(object);
if (R_SUCCEEDED(result)) {
@@ -675,14 +675,14 @@ namespace ams::tipc {
}
/* We shouldn't reply on failure. */
return os::InvalidNativeHandle;
return tipc::InvalidNativeHandle;
}
}
bool ReplyAndReceive(ObjectHolder *out_object, os::NativeHandle reply_target) {
bool ReplyAndReceive(ObjectHolder *out_object, tipc::NativeHandle reply_target) {
/* If we don't have a reply target, clear our message buffer. */
if (reply_target == os::InvalidNativeHandle) {
svc::ipc::MessageBuffer(svc::ipc::GetMessageBuffer()).SetNull();
if (reply_target == tipc::InvalidNativeHandle) {
tipc::MessageBuffer(tipc::GetMessageBuffer()).SetNull();
}
/* Try to reply/receive. */
@@ -704,7 +704,7 @@ namespace ams::tipc {
return true;
}
void AddSession(os::NativeHandle session_handle, tipc::ServiceObjectBase *service_object) {
void AddSession(tipc::NativeHandle session_handle, tipc::ServiceObjectBase *service_object) {
/* Create an object holder for the session. */
tipc::ObjectHolder object;
@@ -723,7 +723,7 @@ namespace ams::tipc {
m_object_manager->CloseObject(handle);
/* Close the handle itself. */
R_ABORT_UNLESS(svc::CloseHandle(handle));
R_ABORT_UNLESS(tipc::impl::CloseHandle(handle));
}
};
@@ -756,13 +756,13 @@ namespace ams::tipc {
m_port_manager.Initialize();
}
void RegisterPort(os::NativeHandle port_handle) {
void RegisterPort(tipc::NativeHandle port_handle) {
m_port_manager.RegisterPort(port_handle);
}
void RegisterPort(sm::ServiceName service_name, size_t max_sessions) {
/* Register service. */
os::NativeHandle port_handle;
tipc::NativeHandle port_handle;
R_ABORT_UNLESS(sm::RegisterService(std::addressof(port_handle), service_name, max_sessions, false));
/* Register the port handle. */
@@ -787,10 +787,10 @@ namespace ams::tipc {
return new_object;
}
Result AddSession(os::NativeHandle *out, tipc::ServiceObjectBase *object) {
Result AddSession(tipc::NativeHandle *out, tipc::ServiceObjectBase *object) {
/* Create a handle for the session. */
svc::Handle session_handle;
R_TRY(svc::CreateSession(std::addressof(session_handle), static_cast<svc::Handle *>(out), false, 0));
tipc::NativeHandle session_handle;
R_TRY(tipc::impl::CreateSession(std::addressof(session_handle), static_cast<tipc::NativeHandle *>(out), false, 0));
/* Add the session to our manager. */
m_port_manager.AddSession(session_handle, object);
@@ -800,12 +800,12 @@ namespace ams::tipc {
private:
void LoopProcess(PortManagerBase &port_manager) {
/* Process requests forever. */
os::NativeHandle reply_target = os::InvalidNativeHandle;
tipc::NativeHandle reply_target = tipc::InvalidNativeHandle;
while (true) {
/* Reply to our pending request, and wait to receive a new one. */
tipc::ObjectHolder signaled_object{};
while (!port_manager.ReplyAndReceive(std::addressof(signaled_object), reply_target)) {
reply_target = os::InvalidNativeHandle;
reply_target = tipc::InvalidNativeHandle;
}
/* A session was signaled, accessible via signaled_object. */
@@ -813,13 +813,13 @@ namespace ams::tipc {
case ObjectHolder::ObjectType_Port:
{
/* Try to accept a new session */
svc::Handle session_handle;
if (R_SUCCEEDED(svc::AcceptSession(std::addressof(session_handle), signaled_object.GetHandle()))) {
tipc::NativeHandle session_handle;
if (R_SUCCEEDED(tipc::impl::AcceptSession(std::addressof(session_handle), signaled_object.GetHandle()))) {
port_manager.AddSession(session_handle, this->AllocateObject());
}
/* We have nothing to reply to. */
reply_target = os::InvalidNativeHandle;
reply_target = tipc::InvalidNativeHandle;
}
break;
case ObjectHolder::ObjectType_Session:

View File

@@ -30,7 +30,7 @@ namespace ams::tipc {
template<typename Impl>
class EmplacedImplHolder {
template<typename, typename, typename, typename>
template<typename, typename, typename, typename, typename>
friend class impl::ImplTemplateBaseT;
private:
using Impl2 = typename EmplacedImplHolderBaseGetter<Impl>::Type;

View File

@@ -15,6 +15,7 @@
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/tipc/tipc_message_types.hpp>
namespace ams::tipc {