mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-23 10:52:13 +00:00
sf: implement mitm forwarding + domains.
This commit is contained in:
parent
0b22af1206
commit
4f455dacf4
14 changed files with 509 additions and 68 deletions
|
@ -26,6 +26,8 @@ static constexpr Result ResultServiceFrameworkInvalidCmifHeaderSize = MAKERESULT
|
||||||
static constexpr Result ResultServiceFrameworkInvalidCmifInHeader = MAKERESULT(Module_ServiceFramework, 211);
|
static constexpr Result ResultServiceFrameworkInvalidCmifInHeader = MAKERESULT(Module_ServiceFramework, 211);
|
||||||
static constexpr Result ResultServiceFrameworkUnknownCmifCommandId = MAKERESULT(Module_ServiceFramework, 221);
|
static constexpr Result ResultServiceFrameworkUnknownCmifCommandId = MAKERESULT(Module_ServiceFramework, 221);
|
||||||
static constexpr Result ResultServiceFrameworkInvalidCmifOutRawSize = MAKERESULT(Module_ServiceFramework, 232);
|
static constexpr Result ResultServiceFrameworkInvalidCmifOutRawSize = MAKERESULT(Module_ServiceFramework, 232);
|
||||||
|
static constexpr Result ResultServiceFrameworkInvalidCmifNumInObjects = MAKERESULT(Module_ServiceFramework, 235);
|
||||||
|
static constexpr Result ResultServiceFrameworkInvalidCmifNumOutObjects = MAKERESULT(Module_ServiceFramework, 236);
|
||||||
|
|
||||||
static constexpr Result ResultServiceFrameworkTargetNotFound = MAKERESULT(Module_ServiceFramework, 261);
|
static constexpr Result ResultServiceFrameworkTargetNotFound = MAKERESULT(Module_ServiceFramework, 261);
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace sts::sf::cmif {
|
||||||
class ServerDomainBase {
|
class ServerDomainBase {
|
||||||
public:
|
public:
|
||||||
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) = 0;
|
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) = 0;
|
||||||
virtual Result AlterReservedIds(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count) = 0;
|
virtual void ReserveSpecificIds(const DomainObjectId *ids, size_t count) = 0;
|
||||||
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) = 0;
|
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) = 0;
|
||||||
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) = 0;
|
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) = 0;
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace sts::sf::cmif {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) override final;
|
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) override final;
|
||||||
virtual Result AlterReservedIds(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count) override final;
|
virtual void ReserveSpecificIds(const DomainObjectId *ids, size_t count) override final;
|
||||||
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) override final;
|
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) override final;
|
||||||
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) override final;
|
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) override final;
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ namespace sts::sf::cmif {
|
||||||
Entry *AllocateEntry();
|
Entry *AllocateEntry();
|
||||||
void FreeEntry(Entry *);
|
void FreeEntry(Entry *);
|
||||||
|
|
||||||
void ReallocateEntries(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count);
|
void AllocateSpecificEntries(const DomainObjectId *ids, size_t count);
|
||||||
|
|
||||||
inline DomainObjectId GetId(Entry *e) {
|
inline DomainObjectId GetId(Entry *e) {
|
||||||
const size_t index = e - this->entries;
|
const size_t index = e - this->entries;
|
||||||
|
@ -116,6 +116,11 @@ namespace sts::sf::cmif {
|
||||||
}
|
}
|
||||||
return new (storage) Domain(this);
|
return new (storage) Domain(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void FreeDomainServiceObject(DomainServiceObject *object) {
|
||||||
|
static_cast<Domain *>(object)->~Domain();
|
||||||
|
this->FreeDomain(object);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,10 @@ namespace sts::sf::cmif {
|
||||||
class DomainServiceObjectDispatchTable : public impl::ServiceDispatchTableBase {
|
class DomainServiceObjectDispatchTable : public impl::ServiceDispatchTableBase {
|
||||||
private:
|
private:
|
||||||
Result ProcessMessageImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const;
|
Result ProcessMessageImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const;
|
||||||
|
Result ProcessMessageForMitmImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const;
|
||||||
public:
|
public:
|
||||||
Result ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
|
Result ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
|
||||||
|
Result ProcessMessageForMitm(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +35,30 @@ namespace sts::sf::cmif {
|
||||||
private:
|
private:
|
||||||
ServerMessageProcessor *impl_processor;
|
ServerMessageProcessor *impl_processor;
|
||||||
ServerDomainBase *domain;
|
ServerDomainBase *domain;
|
||||||
|
DomainObjectId *in_object_ids;
|
||||||
|
DomainObjectId *out_object_ids;
|
||||||
|
size_t num_in_objects;
|
||||||
|
ServerMessageRuntimeMetadata impl_metadata;
|
||||||
|
public:
|
||||||
|
DomainServiceObjectProcessor(ServerDomainBase *d, DomainObjectId *in_obj_ids, size_t num_in_objs) : domain(d), in_object_ids(in_obj_ids), num_in_objects(num_in_objs) {
|
||||||
|
STS_ASSERT(this->domain != nullptr);
|
||||||
|
STS_ASSERT(this->in_object_ids != nullptr);
|
||||||
|
this->impl_processor = nullptr;
|
||||||
|
this->out_object_ids = nullptr;
|
||||||
|
this->impl_metadata = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetInObjectCount() const {
|
||||||
|
return this->num_in_objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetOutObjectCount() const {
|
||||||
|
return this->impl_metadata.GetOutObjectCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetImplOutDataTotalSize() const {
|
||||||
|
return this->impl_metadata.GetOutDataSize() + this->impl_metadata.GetOutHeadersSize();
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
/* Used to enabled templated message processors. */
|
/* Used to enabled templated message processors. */
|
||||||
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) override final {
|
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) override final {
|
||||||
|
@ -41,16 +67,32 @@ namespace sts::sf::cmif {
|
||||||
} else {
|
} else {
|
||||||
this->impl_processor->SetImplementationProcessor(impl);
|
this->impl_processor->SetImplementationProcessor(impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->impl_metadata = this->impl_processor->GetRuntimeMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, size_t &headers_size) const override final;
|
virtual const ServerMessageRuntimeMetadata GetRuntimeMetadata() const override final {
|
||||||
|
const auto runtime_metadata = this->impl_processor->GetRuntimeMetadata();
|
||||||
|
|
||||||
|
return ServerMessageRuntimeMetadata {
|
||||||
|
.in_data_size = static_cast<u16>(runtime_metadata.GetInDataSize() + runtime_metadata.GetInObjectCount() * sizeof(DomainObjectId)),
|
||||||
|
.out_data_size = static_cast<u16>(runtime_metadata.GetOutDataSize() + runtime_metadata.GetOutObjectCount() * sizeof(DomainObjectId)),
|
||||||
|
.in_headers_size = static_cast<u8>(runtime_metadata.GetInHeadersSize() + sizeof(CmifDomainInHeader)),
|
||||||
|
.out_headers_size = static_cast<u8>(runtime_metadata.GetOutHeadersSize() + sizeof(CmifDomainOutHeader)),
|
||||||
|
.in_object_count = 0,
|
||||||
|
.out_object_count = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const override final;
|
||||||
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const override final;
|
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const override final;
|
||||||
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size, size_t &num_out_object_handles) override final;
|
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) override final;
|
||||||
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size) override final;
|
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) override final;
|
||||||
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) override final;
|
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) override final;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DomainServiceObject : public IServiceObject, public ServerDomainBase {
|
class DomainServiceObject : public IServiceObject, public ServerDomainBase {
|
||||||
|
friend class DomainServiceObjectDispatchTable;
|
||||||
public:
|
public:
|
||||||
static constexpr inline DomainServiceObjectDispatchTable s_CmifServiceDispatchTable{};
|
static constexpr inline DomainServiceObjectDispatchTable s_CmifServiceDispatchTable{};
|
||||||
private:
|
private:
|
||||||
|
@ -59,6 +101,8 @@ namespace sts::sf::cmif {
|
||||||
/* TODO: Implement to use domain object processor. */
|
/* TODO: Implement to use domain object processor. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MitmDomainServiceObject : public DomainServiceObject{};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ServiceDispatchTraits<DomainServiceObject> {
|
struct ServiceDispatchTraits<DomainServiceObject> {
|
||||||
static_assert(std::is_base_of<sf::IServiceObject, DomainServiceObject>::value, "DomainServiceObject must derive from sf::IServiceObject");
|
static_assert(std::is_base_of<sf::IServiceObject, DomainServiceObject>::value, "DomainServiceObject must derive from sf::IServiceObject");
|
||||||
|
@ -71,4 +115,16 @@ namespace sts::sf::cmif {
|
||||||
static constexpr inline ServiceDispatchMeta Meta{&DomainServiceObject::s_CmifServiceDispatchTable, ProcessHandlerImpl};
|
static constexpr inline ServiceDispatchMeta Meta{&DomainServiceObject::s_CmifServiceDispatchTable, ProcessHandlerImpl};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct ServiceDispatchTraits<MitmDomainServiceObject> {
|
||||||
|
static_assert(std::is_base_of<DomainServiceObject, MitmDomainServiceObject>::value, "MitmDomainServiceObject must derive from DomainServiceObject");
|
||||||
|
using ProcessHandlerType = decltype(ServiceDispatchMeta::ProcessHandler);
|
||||||
|
|
||||||
|
using DispatchTableType = DomainServiceObjectDispatchTable;
|
||||||
|
static constexpr ProcessHandlerType ProcessHandlerImpl = &impl::ServiceDispatchTableBase::ProcessMessageForMitm<DispatchTableType>;
|
||||||
|
|
||||||
|
static constexpr inline ServiceDispatchMeta Meta{&DomainServiceObject::s_CmifServiceDispatchTable, ProcessHandlerImpl};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,15 +25,57 @@ namespace sts::sf::cmif {
|
||||||
class ServiceObjectHolder;
|
class ServiceObjectHolder;
|
||||||
struct DomainObjectId;
|
struct DomainObjectId;
|
||||||
|
|
||||||
|
/* This is needed for non-templated domain message processing. */
|
||||||
|
struct ServerMessageRuntimeMetadata {
|
||||||
|
u16 in_data_size;
|
||||||
|
u16 out_data_size;
|
||||||
|
u8 in_headers_size;
|
||||||
|
u8 out_headers_size;
|
||||||
|
u8 in_object_count;
|
||||||
|
u8 out_object_count;
|
||||||
|
|
||||||
|
constexpr size_t GetInDataSize() const {
|
||||||
|
return size_t(this->in_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetOutDataSize() const {
|
||||||
|
return size_t(this->out_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetInHeadersSize() const {
|
||||||
|
return size_t(this->in_headers_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetOutHeadersSize() const {
|
||||||
|
return size_t(this->out_headers_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetInObjectCount() const {
|
||||||
|
return size_t(this->in_object_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetOutObjectCount() const {
|
||||||
|
return size_t(this->out_object_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetUnfixedOutPointerSizeOffset() const {
|
||||||
|
return this->GetInDataSize() + this->GetInHeadersSize() + 0x10 /* padding. */;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::is_pod<ServerMessageRuntimeMetadata>::value, "std::is_pod<ServerMessageRuntimeMetadata>::value");
|
||||||
|
static_assert(sizeof(ServerMessageRuntimeMetadata) == sizeof(u64), "sizeof(ServerMessageRuntimeMetadata)");
|
||||||
|
|
||||||
class ServerMessageProcessor {
|
class ServerMessageProcessor {
|
||||||
public:
|
public:
|
||||||
/* Used to enabled templated message processors. */
|
/* Used to enabled templated message processors. */
|
||||||
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) { /* ... */ }
|
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) { /* ... */ }
|
||||||
|
virtual const ServerMessageRuntimeMetadata GetRuntimeMetadata() const = 0;
|
||||||
|
|
||||||
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, size_t &headers_size) const = 0;
|
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const = 0;
|
||||||
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const = 0;
|
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const = 0;
|
||||||
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size, size_t &num_out_object_handles) = 0;
|
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) = 0;
|
||||||
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size) = 0;
|
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) = 0;
|
||||||
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) = 0;
|
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
namespace sts::sf::hipc {
|
namespace sts::sf::hipc {
|
||||||
|
|
||||||
class ServerSessionManager;
|
class ServerSessionManager;
|
||||||
|
class ServerSession;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ namespace sts::sf::cmif {
|
||||||
struct ServiceDispatchContext {
|
struct ServiceDispatchContext {
|
||||||
sf::IServiceObject *srv_obj;
|
sf::IServiceObject *srv_obj;
|
||||||
hipc::ServerSessionManager *manager;
|
hipc::ServerSessionManager *manager;
|
||||||
|
hipc::ServerSession *session;
|
||||||
ServerMessageProcessor *processor;
|
ServerMessageProcessor *processor;
|
||||||
HandlesToClose *handles_to_close;
|
HandlesToClose *handles_to_close;
|
||||||
const PointerAndSize pointer_buffer;
|
const PointerAndSize pointer_buffer;
|
||||||
|
|
|
@ -28,6 +28,14 @@ namespace sts::sf::hipc {
|
||||||
virtual Result DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message) override final;
|
virtual Result DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message) override final;
|
||||||
public:
|
public:
|
||||||
ServerDomainSessionManager(DomainEntryStorage *entry_storage, size_t entry_count) : ServerDomainManager(entry_storage, entry_count) { /* ... */ }
|
ServerDomainSessionManager(DomainEntryStorage *entry_storage, size_t entry_count) : ServerDomainManager(entry_storage, entry_count) { /* ... */ }
|
||||||
|
|
||||||
|
inline cmif::DomainServiceObject *AllocateDomainServiceObject() {
|
||||||
|
return cmif::ServerDomainManager::AllocateDomainServiceObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreeDomainServiceObject(cmif::DomainServiceObject *object) {
|
||||||
|
cmif::ServerDomainManager::FreeDomainServiceObject(object);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,12 @@
|
||||||
#include "../cmif/sf_cmif_service_object_holder.hpp"
|
#include "../cmif/sf_cmif_service_object_holder.hpp"
|
||||||
#include "sf_hipc_api.hpp"
|
#include "sf_hipc_api.hpp"
|
||||||
|
|
||||||
|
namespace sts::sf::cmif {
|
||||||
|
|
||||||
|
struct ServiceDispatchContext;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace sts::sf::hipc {
|
namespace sts::sf::hipc {
|
||||||
|
|
||||||
class ServerSessionManager;
|
class ServerSessionManager;
|
||||||
|
@ -65,6 +71,8 @@ namespace sts::sf::hipc {
|
||||||
bool IsMitmSession() const {
|
bool IsMitmSession() const {
|
||||||
return this->forward_service != nullptr;
|
return this->forward_service != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServerSessionManager {
|
class ServerSessionManager {
|
||||||
|
|
|
@ -442,8 +442,7 @@ namespace sts::sf::impl {
|
||||||
|
|
||||||
/* In/Out data marshalling. */
|
/* In/Out data marshalling. */
|
||||||
static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataOffsetCalculator<InDatas>::Offsets;
|
static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataOffsetCalculator<InDatas>::Offsets;
|
||||||
static constexpr size_t InDataRawUnfixedOutPointerSizeOffset = util::AlignUp(InDataOffsets[NumInDatas] + 0x10, alignof(u16));
|
static constexpr size_t InDataSize = util::AlignUp(InDataOffsets[NumInDatas], alignof(u16));
|
||||||
static constexpr size_t InDataSize = util::AlignUp(util::AlignUp(InDataOffsets[NumInDatas], alignof(u16)) + sizeof(u16) * NumUnfixedSizeOutHipcPointerBuffers, alignof(u32));
|
|
||||||
|
|
||||||
static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataOffsetCalculator<OutDatas>::Offsets;
|
static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataOffsetCalculator<OutDatas>::Offsets;
|
||||||
static constexpr size_t OutDataSize = util::AlignUp(OutDataOffsets[NumOutDatas], alignof(u32));
|
static constexpr size_t OutDataSize = util::AlignUp(OutDataOffsets[NumOutDatas], alignof(u32));
|
||||||
|
@ -464,6 +463,16 @@ namespace sts::sf::impl {
|
||||||
static_assert(NumInMoveHandles + NumInCopyHandles == NumInHandles, "NumInMoveHandles + NumInCopyHandles == NumInHandles");
|
static_assert(NumInMoveHandles + NumInCopyHandles == NumInHandles, "NumInMoveHandles + NumInCopyHandles == NumInHandles");
|
||||||
static_assert(NumOutMoveHandles + NumOutCopyHandles == NumOutHandles, "NumOutMoveHandles + NumOutCopyHandles == NumOutHandles");
|
static_assert(NumOutMoveHandles + NumOutCopyHandles == NumOutHandles, "NumOutMoveHandles + NumOutCopyHandles == NumOutHandles");
|
||||||
|
|
||||||
|
/* Used by server message processor at runtime. */
|
||||||
|
static constexpr inline const cmif::ServerMessageRuntimeMetadata RuntimeMetadata = cmif::ServerMessageRuntimeMetadata{
|
||||||
|
.in_data_size = InDataSize,
|
||||||
|
.out_data_size = OutDataSize,
|
||||||
|
.in_headers_size = sizeof(CmifInHeader),
|
||||||
|
.out_headers_size = sizeof(CmifOutHeader),
|
||||||
|
.in_object_count = NumInObjects,
|
||||||
|
.out_object_count = NumOutObjects,
|
||||||
|
};
|
||||||
|
|
||||||
/* Construction of argument serialization structs. */
|
/* Construction of argument serialization structs. */
|
||||||
private:
|
private:
|
||||||
template<typename>
|
template<typename>
|
||||||
|
@ -686,7 +695,11 @@ namespace sts::sf::impl {
|
||||||
template<typename CommandMeta>
|
template<typename CommandMeta>
|
||||||
struct HipcCommandProcessor : public sf::cmif::ServerMessageProcessor {
|
struct HipcCommandProcessor : public sf::cmif::ServerMessageProcessor {
|
||||||
public:
|
public:
|
||||||
virtual Result PrepareForProcess(const cmif::ServiceDispatchContext &ctx, size_t &headers_size) const override final {
|
virtual const cmif::ServerMessageRuntimeMetadata GetRuntimeMetadata() const override final {
|
||||||
|
return CommandMeta::RuntimeMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Result PrepareForProcess(const cmif::ServiceDispatchContext &ctx, const cmif::ServerMessageRuntimeMetadata runtime_metadata) const override final {
|
||||||
const auto &meta = ctx.request.meta;
|
const auto &meta = ctx.request.meta;
|
||||||
bool is_request_valid = true;
|
bool is_request_valid = true;
|
||||||
is_request_valid &= meta.send_pid == CommandMeta::HasInProcessIdHolder;
|
is_request_valid &= meta.send_pid == CommandMeta::HasInProcessIdHolder;
|
||||||
|
@ -699,30 +712,33 @@ namespace sts::sf::impl {
|
||||||
is_request_valid &= meta.num_move_handles == CommandMeta::NumInMoveHandles;
|
is_request_valid &= meta.num_move_handles == CommandMeta::NumInMoveHandles;
|
||||||
|
|
||||||
const size_t meta_raw_size = meta.num_data_words * sizeof(u32);
|
const size_t meta_raw_size = meta.num_data_words * sizeof(u32);
|
||||||
is_request_valid &= meta_raw_size >= CommandMeta::InDataSize + 0x10 /* padding */ + headers_size /* headers */;
|
const size_t command_raw_size = util::AlignUp(runtime_metadata.GetUnfixedOutPointerSizeOffset() + (CommandMeta::NumUnfixedSizeOutHipcPointerBuffers * sizeof(u16)), alignof(u32));
|
||||||
|
is_request_valid &= meta_raw_size >= command_raw_size;
|
||||||
|
|
||||||
R_UNLESS(is_request_valid, ResultHipcInvalidRequest);
|
R_UNLESS(is_request_valid, ResultHipcInvalidRequest);
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const size_t headers_size, size_t &num_out_object_handles) override final {
|
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const cmif::ServerMessageRuntimeMetadata runtime_metadata) override final {
|
||||||
|
const size_t raw_size = runtime_metadata.GetOutDataSize() + runtime_metadata.GetOutHeadersSize();
|
||||||
const auto response = hipcMakeRequestInline(ctx.out_message_buffer.GetPointer(),
|
const auto response = hipcMakeRequestInline(ctx.out_message_buffer.GetPointer(),
|
||||||
.type = CmifCommandType_Invalid, /* Really response */
|
.type = CmifCommandType_Invalid, /* Really response */
|
||||||
.num_send_statics = CommandMeta::NumOutHipcPointerBuffers,
|
.num_send_statics = CommandMeta::NumOutHipcPointerBuffers,
|
||||||
.num_data_words = static_cast<u32>((util::AlignUp(CommandMeta::OutDataSize + headers_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
|
.num_data_words = static_cast<u32>((util::AlignUp(raw_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
|
||||||
.num_copy_handles = CommandMeta::NumOutCopyHandles,
|
.num_copy_handles = CommandMeta::NumOutCopyHandles,
|
||||||
.num_move_handles = static_cast<u32>(CommandMeta::NumOutMoveHandles + num_out_object_handles),
|
.num_move_handles = static_cast<u32>(CommandMeta::NumOutMoveHandles + runtime_metadata.GetOutObjectCount()),
|
||||||
);
|
);
|
||||||
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), CommandMeta::OutDataSize + headers_size);
|
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), raw_size);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const size_t headers_size) override final {
|
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const cmif::ServerMessageRuntimeMetadata runtime_metadata) override final {
|
||||||
|
const size_t raw_size = runtime_metadata.GetOutHeadersSize();
|
||||||
const auto response = hipcMakeRequestInline(ctx.out_message_buffer.GetPointer(),
|
const auto response = hipcMakeRequestInline(ctx.out_message_buffer.GetPointer(),
|
||||||
.type = CmifCommandType_Invalid, /* Really response */
|
.type = CmifCommandType_Invalid, /* Really response */
|
||||||
.num_data_words = static_cast<u32>((util::AlignUp(headers_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
|
.num_data_words = static_cast<u32>((util::AlignUp(raw_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
|
||||||
);
|
);
|
||||||
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), headers_size);
|
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), raw_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Result GetInObjects(cmif::ServiceObjectHolder *in_objects) const override final {
|
virtual Result GetInObjects(cmif::ServiceObjectHolder *in_objects) const override final {
|
||||||
|
@ -789,7 +805,7 @@ namespace sts::sf::impl {
|
||||||
}();
|
}();
|
||||||
|
|
||||||
template<size_t BufferIndex, size_t Index = GetIndexFromBufferIndex<BufferIndex>>
|
template<size_t BufferIndex, size_t Index = GetIndexFromBufferIndex<BufferIndex>>
|
||||||
NX_CONSTEXPR void ProcessBufferImpl(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &buffer, bool &is_buffer_map_alias, bool &map_alias_buffers_valid, size_t &pointer_buffer_head, size_t &pointer_buffer_tail, size_t in_headers_size) {
|
NX_CONSTEXPR void ProcessBufferImpl(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &buffer, bool &is_buffer_map_alias, bool &map_alias_buffers_valid, size_t &pointer_buffer_head, size_t &pointer_buffer_tail, const cmif::ServerMessageRuntimeMetadata runtime_metadata) {
|
||||||
static_assert(Index != std::numeric_limits<size_t>::max(), "Invalid Index From Buffer Index");
|
static_assert(Index != std::numeric_limits<size_t>::max(), "Invalid Index From Buffer Index");
|
||||||
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
|
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
|
||||||
constexpr auto Attributes = CommandMeta::BufferAttributes[BufferIndex];
|
constexpr auto Attributes = CommandMeta::BufferAttributes[BufferIndex];
|
||||||
|
@ -824,7 +840,7 @@ namespace sts::sf::impl {
|
||||||
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
||||||
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
||||||
} else {
|
} else {
|
||||||
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + in_headers_size + CommandMeta::InDataRawUnfixedOutPointerSizeOffset);
|
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + runtime_metadata.GetUnfixedOutPointerSizeOffset());
|
||||||
const size_t size = size_t(recv_pointer_sizes[Info.unfixed_recv_pointer_index]);
|
const size_t size = size_t(recv_pointer_sizes[Info.unfixed_recv_pointer_index]);
|
||||||
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
||||||
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
||||||
|
@ -860,7 +876,7 @@ namespace sts::sf::impl {
|
||||||
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
||||||
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
||||||
} else {
|
} else {
|
||||||
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + CommandMeta::InDataRawUnfixedOutPointerSizeOffset);
|
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + runtime_metadata.GetUnfixedOutPointerSizeOffset());
|
||||||
const size_t size = size_t(recv_pointer_sizes[Info.unfixed_recv_pointer_index]);
|
const size_t size = size_t(recv_pointer_sizes[Info.unfixed_recv_pointer_index]);
|
||||||
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
|
||||||
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
|
||||||
|
@ -894,11 +910,11 @@ namespace sts::sf::impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
NX_CONSTEXPR Result ProcessBuffers(const cmif::ServiceDispatchContext &ctx, BufferArrayType &buffers, std::array<bool, CommandMeta::NumBuffers> &is_buffer_map_alias, size_t in_headers_size) {
|
NX_CONSTEXPR Result ProcessBuffers(const cmif::ServiceDispatchContext &ctx, BufferArrayType &buffers, std::array<bool, CommandMeta::NumBuffers> &is_buffer_map_alias, const cmif::ServerMessageRuntimeMetadata runtime_metadata) {
|
||||||
bool map_alias_buffers_valid = true;
|
bool map_alias_buffers_valid = true;
|
||||||
size_t pointer_buffer_tail = ctx.pointer_buffer.GetAddress();
|
size_t pointer_buffer_tail = ctx.pointer_buffer.GetAddress();
|
||||||
size_t pointer_buffer_head = pointer_buffer_tail + ctx.pointer_buffer.GetSize();
|
size_t pointer_buffer_head = pointer_buffer_tail + ctx.pointer_buffer.GetSize();
|
||||||
#define _SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(n) do { if constexpr (CommandMeta::NumBuffers > n) { ProcessBufferImpl<n>(ctx, buffers[n], is_buffer_map_alias[n], map_alias_buffers_valid, pointer_buffer_head, pointer_buffer_tail, in_headers_size); } } while (0)
|
#define _SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(n) do { if constexpr (CommandMeta::NumBuffers > n) { ProcessBufferImpl<n>(ctx, buffers[n], is_buffer_map_alias[n], map_alias_buffers_valid, pointer_buffer_head, pointer_buffer_tail, runtime_metadata); } } while (0)
|
||||||
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(0);
|
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(0);
|
||||||
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(1);
|
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(1);
|
||||||
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(2);
|
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(2);
|
||||||
|
@ -1032,8 +1048,8 @@ namespace sts::sf::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate the metadata has the expected counts. */
|
/* Validate the metadata has the expected counts. */
|
||||||
size_t in_headers_size = sizeof(CmifInHeader);
|
const auto runtime_metadata = ctx.processor->GetRuntimeMetadata();
|
||||||
R_TRY(ctx.processor->PrepareForProcess(ctx, in_headers_size));
|
R_TRY(ctx.processor->PrepareForProcess(ctx, runtime_metadata));
|
||||||
|
|
||||||
/* Storage for output. */
|
/* Storage for output. */
|
||||||
BufferArrayType buffers;
|
BufferArrayType buffers;
|
||||||
|
@ -1043,7 +1059,7 @@ namespace sts::sf::impl {
|
||||||
InOutObjectHolderType in_out_objects_holder;
|
InOutObjectHolderType in_out_objects_holder;
|
||||||
|
|
||||||
/* Process buffers. */
|
/* Process buffers. */
|
||||||
R_TRY(ImplProcessorType::ProcessBuffers(ctx, buffers, is_buffer_map_alias, in_headers_size));
|
R_TRY(ImplProcessorType::ProcessBuffers(ctx, buffers, is_buffer_map_alias, runtime_metadata));
|
||||||
|
|
||||||
/* Process input/output objects. */
|
/* Process input/output objects. */
|
||||||
R_TRY(in_out_objects_holder.GetInObjects(ctx.processor));
|
R_TRY(in_out_objects_holder.GetInObjects(ctx.processor));
|
||||||
|
@ -1062,7 +1078,7 @@ namespace sts::sf::impl {
|
||||||
if constexpr (CommandMeta::ReturnsResult) {
|
if constexpr (CommandMeta::ReturnsResult) {
|
||||||
R_TRY_CLEANUP(std::apply([=](auto&&... args) { return (this_ptr->*ServiceCommandImpl)(args...); }, args_tuple), {
|
R_TRY_CLEANUP(std::apply([=](auto&&... args) { return (this_ptr->*ServiceCommandImpl)(args...); }, args_tuple), {
|
||||||
cmif::PointerAndSize out_raw_data;
|
cmif::PointerAndSize out_raw_data;
|
||||||
ctx.processor->PrepareForErrorReply(ctx, out_raw_data, sizeof(CmifOutHeader));
|
ctx.processor->PrepareForErrorReply(ctx, out_raw_data, runtime_metadata);
|
||||||
R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data));
|
R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -1072,8 +1088,7 @@ namespace sts::sf::impl {
|
||||||
|
|
||||||
/* Encode. */
|
/* Encode. */
|
||||||
cmif::PointerAndSize out_raw_data;
|
cmif::PointerAndSize out_raw_data;
|
||||||
size_t num_out_object_handles = CommandMeta::NumOutObjects;
|
const auto response = ctx.processor->PrepareForReply(ctx, out_raw_data, runtime_metadata);
|
||||||
const auto response = ctx.processor->PrepareForReply(ctx, out_raw_data, sizeof(CmifOutHeader), num_out_object_handles);
|
|
||||||
R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data));
|
R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data));
|
||||||
|
|
||||||
/* Copy raw data output struct. */
|
/* Copy raw data output struct. */
|
||||||
|
@ -1084,7 +1099,7 @@ namespace sts::sf::impl {
|
||||||
ImplProcessorType::SetOutBuffers(response, buffers, is_buffer_map_alias);
|
ImplProcessorType::SetOutBuffers(response, buffers, is_buffer_map_alias);
|
||||||
|
|
||||||
/* Set out handles. */
|
/* Set out handles. */
|
||||||
out_handles_holder.CopyTo(response, num_out_object_handles);
|
out_handles_holder.CopyTo(response, runtime_metadata.GetOutObjectCount());
|
||||||
|
|
||||||
/* Set output objects. */
|
/* Set output objects. */
|
||||||
in_out_objects_holder.SetOutObjects(ctx, response);
|
in_out_objects_holder.SetOutObjects(ctx, response);
|
||||||
|
|
|
@ -41,9 +41,8 @@ namespace sts::sf::cmif {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerDomainManager::Domain::AlterReservedIds(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count) {
|
void ServerDomainManager::Domain::ReserveSpecificIds(const DomainObjectId *ids, size_t count) {
|
||||||
this->manager->entry_manager.ReallocateEntries(old_reserved_ids, new_reserved_ids, count);
|
this->manager->entry_manager.AllocateSpecificEntries(ids, count);
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerDomainManager::Domain::UnreserveIds(const DomainObjectId *ids, size_t count) {
|
void ServerDomainManager::Domain::UnreserveIds(const DomainObjectId *ids, size_t count) {
|
||||||
|
@ -132,27 +131,16 @@ namespace sts::sf::cmif {
|
||||||
this->free_list.push_front(*entry);
|
this->free_list.push_front(*entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerDomainManager::EntryManager::ReallocateEntries(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count) {
|
void ServerDomainManager::EntryManager::AllocateSpecificEntries(const DomainObjectId *ids, size_t count) {
|
||||||
std::scoped_lock lk(this->lock);
|
std::scoped_lock lk(this->lock);
|
||||||
|
|
||||||
/* Free old ids. */
|
/* Allocate new IDs. */
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
const auto id = old_reserved_ids[i];
|
const auto id = ids[i];
|
||||||
Entry *entry = this->GetEntry(id);
|
Entry *entry = this->GetEntry(id);
|
||||||
if (id != InvalidDomainObjectId) {
|
if (id != InvalidDomainObjectId) {
|
||||||
STS_ASSERT(entry != nullptr);
|
STS_ASSERT(entry != nullptr);
|
||||||
STS_ASSERT(entry->owner == nullptr);
|
STS_ASSERT(entry->owner == nullptr);
|
||||||
STS_ASSERT(!entry->object);
|
|
||||||
this->free_list.push_front(*entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate new IDs. */
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
const auto id = old_reserved_ids[i];
|
|
||||||
Entry *entry = this->GetEntry(id);
|
|
||||||
if (id != InvalidDomainObjectId) {
|
|
||||||
STS_ASSERT(entry != nullptr);
|
|
||||||
this->free_list.erase(this->free_list.iterator_to(*entry));
|
this->free_list.erase(this->free_list.iterator_to(*entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 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/>.
|
||||||
|
*/
|
||||||
|
#include <functional>
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
namespace sts::sf::cmif {
|
||||||
|
|
||||||
|
Result DomainServiceObjectDispatchTable::ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const {
|
||||||
|
return this->ProcessMessageImpl(ctx, static_cast<DomainServiceObject *>(ctx.srv_obj)->GetServerDomain(), in_raw_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DomainServiceObjectDispatchTable::ProcessMessageForMitm(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const {
|
||||||
|
return this->ProcessMessageForMitmImpl(ctx, static_cast<DomainServiceObject *>(ctx.srv_obj)->GetServerDomain(), in_raw_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DomainServiceObjectDispatchTable::ProcessMessageImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const {
|
||||||
|
const CmifDomainInHeader *in_header = reinterpret_cast<const CmifDomainInHeader *>(in_raw_data.GetPointer());
|
||||||
|
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
|
||||||
|
const cmif::PointerAndSize in_domain_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
|
||||||
|
|
||||||
|
const DomainObjectId target_object_id = DomainObjectId{in_header->object_id};
|
||||||
|
switch (in_header->type) {
|
||||||
|
case CmifDomainRequestType_SendMessage:
|
||||||
|
{
|
||||||
|
auto target_object = domain->GetObject(target_object_id);
|
||||||
|
R_UNLESS(static_cast<bool>(target_object), ResultServiceFrameworkTargetNotFound);
|
||||||
|
R_UNLESS(in_header->data_size + in_header->num_in_objects * sizeof(DomainObjectId) <= in_domain_raw_data.GetSize(), ResultServiceFrameworkInvalidCmifHeaderSize);
|
||||||
|
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_domain_raw_data.GetAddress(), in_header->data_size);
|
||||||
|
DomainObjectId in_object_ids[8];
|
||||||
|
R_UNLESS(in_header->num_in_objects <= util::size(in_object_ids), ResultServiceFrameworkInvalidCmifNumInObjects);
|
||||||
|
std::memcpy(in_object_ids, reinterpret_cast<DomainObjectId *>(in_message_raw_data.GetAddress() + in_message_raw_data.GetSize()), sizeof(DomainObjectId) * in_header->num_in_objects);
|
||||||
|
DomainServiceObjectProcessor domain_processor(domain, in_object_ids, in_header->num_in_objects);
|
||||||
|
if (ctx.processor == nullptr) {
|
||||||
|
ctx.processor = &domain_processor;
|
||||||
|
} else {
|
||||||
|
ctx.processor->SetImplementationProcessor(&domain_processor);
|
||||||
|
}
|
||||||
|
return target_object.ProcessMessage(ctx, in_message_raw_data);
|
||||||
|
}
|
||||||
|
case CmifDomainRequestType_Close:
|
||||||
|
/* TODO: N doesn't error check here. Should we? */
|
||||||
|
domain->UnregisterObject(target_object_id);
|
||||||
|
return ResultSuccess;
|
||||||
|
default:
|
||||||
|
return ResultServiceFrameworkInvalidCmifInHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DomainServiceObjectDispatchTable::ProcessMessageForMitmImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const {
|
||||||
|
const CmifDomainInHeader *in_header = reinterpret_cast<const CmifDomainInHeader *>(in_raw_data.GetPointer());
|
||||||
|
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
|
||||||
|
const cmif::PointerAndSize in_domain_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
|
||||||
|
|
||||||
|
const DomainObjectId target_object_id = DomainObjectId{in_header->object_id};
|
||||||
|
switch (in_header->type) {
|
||||||
|
case CmifDomainRequestType_SendMessage:
|
||||||
|
{
|
||||||
|
auto target_object = domain->GetObject(target_object_id);
|
||||||
|
|
||||||
|
/* Mitm. If we don't have a target object, we should forward to let the server handle. */
|
||||||
|
if (!target_object) {
|
||||||
|
return ctx.session->ForwardRequest(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
R_UNLESS(in_header->data_size + in_header->num_in_objects * sizeof(DomainObjectId) <= in_domain_raw_data.GetSize(), ResultServiceFrameworkInvalidCmifHeaderSize);
|
||||||
|
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_domain_raw_data.GetAddress(), in_header->data_size);
|
||||||
|
DomainObjectId in_object_ids[8];
|
||||||
|
R_UNLESS(in_header->num_in_objects <= util::size(in_object_ids), ResultServiceFrameworkInvalidCmifNumInObjects);
|
||||||
|
std::memcpy(in_object_ids, reinterpret_cast<DomainObjectId *>(in_message_raw_data.GetAddress() + in_message_raw_data.GetSize()), sizeof(DomainObjectId) * in_header->num_in_objects);
|
||||||
|
DomainServiceObjectProcessor domain_processor(domain, in_object_ids, in_header->num_in_objects);
|
||||||
|
if (ctx.processor == nullptr) {
|
||||||
|
ctx.processor = &domain_processor;
|
||||||
|
} else {
|
||||||
|
ctx.processor->SetImplementationProcessor(&domain_processor);
|
||||||
|
}
|
||||||
|
return target_object.ProcessMessage(ctx, in_message_raw_data);
|
||||||
|
}
|
||||||
|
case CmifDomainRequestType_Close:
|
||||||
|
{
|
||||||
|
auto target_object = domain->GetObject(target_object_id);
|
||||||
|
|
||||||
|
/* If the object is not in the domain, tell the server to close it. */
|
||||||
|
if (!target_object) {
|
||||||
|
return ctx.session->ForwardRequest(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the object is in the domain, close our copy of it. Mitm objects are required to close their associated domain id, so this shouldn't cause desynch. */
|
||||||
|
domain->UnregisterObject(target_object_id);
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return ResultServiceFrameworkInvalidCmifInHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DomainServiceObjectProcessor::PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const {
|
||||||
|
/* Validate in object count. */
|
||||||
|
R_UNLESS(this->impl_metadata.GetInObjectCount() == this->GetInObjectCount(), ResultServiceFrameworkInvalidCmifNumInObjects);
|
||||||
|
|
||||||
|
/* Nintendo reserves domain object IDs here. We do this later, to support mitm semantics. */
|
||||||
|
|
||||||
|
/* Pass onwards. */
|
||||||
|
return this->impl_processor->PrepareForProcess(ctx, runtime_metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result DomainServiceObjectProcessor::GetInObjects(ServiceObjectHolder *in_objects) const {
|
||||||
|
for (size_t i = 0; i < this->GetInObjectCount(); i++) {
|
||||||
|
in_objects[i] = this->domain->GetObject(this->in_object_ids[i]);
|
||||||
|
}
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
HipcRequest DomainServiceObjectProcessor::PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) {
|
||||||
|
/* Call into impl processor, get request. */
|
||||||
|
PointerAndSize raw_data;
|
||||||
|
HipcRequest request = this->impl_processor->PrepareForReply(ctx, raw_data, runtime_metadata);
|
||||||
|
|
||||||
|
/* Write out header. */
|
||||||
|
constexpr size_t out_header_size = sizeof(CmifDomainOutHeader);
|
||||||
|
const size_t impl_out_data_total_size = this->GetImplOutDataTotalSize();
|
||||||
|
STS_ASSERT(out_header_size + impl_out_data_total_size + sizeof(DomainObjectId) * this->GetOutObjectCount() <= raw_data.GetSize());
|
||||||
|
*reinterpret_cast<CmifDomainOutHeader *>(raw_data.GetPointer()) = CmifDomainOutHeader{ .num_out_objects = static_cast<u32>(this->GetOutObjectCount()), };
|
||||||
|
|
||||||
|
/* Set output raw data. */
|
||||||
|
out_raw_data = cmif::PointerAndSize(raw_data.GetAddress() + out_header_size, raw_data.GetSize() - out_header_size);
|
||||||
|
this->out_object_ids = reinterpret_cast<DomainObjectId *>(out_raw_data.GetAddress() + out_raw_data.GetSize());
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DomainServiceObjectProcessor::PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) {
|
||||||
|
/* Call into impl processor, get request. */
|
||||||
|
PointerAndSize raw_data;
|
||||||
|
this->impl_processor->PrepareForErrorReply(ctx, raw_data, runtime_metadata);
|
||||||
|
|
||||||
|
/* Write out header. */
|
||||||
|
constexpr size_t out_header_size = sizeof(CmifDomainOutHeader);
|
||||||
|
const size_t impl_out_data_total_size = this->GetImplOutDataTotalSize();
|
||||||
|
STS_ASSERT(out_header_size + impl_out_data_total_size <= raw_data.GetSize());
|
||||||
|
*reinterpret_cast<CmifDomainOutHeader *>(raw_data.GetPointer()) = CmifDomainOutHeader{ .num_out_objects = 0, };
|
||||||
|
|
||||||
|
/* Set output raw data. */
|
||||||
|
out_raw_data = cmif::PointerAndSize(raw_data.GetAddress() + out_header_size, raw_data.GetSize() - out_header_size);
|
||||||
|
|
||||||
|
/* Nintendo unreserves domain entries here, but we haven't reserved them yet. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void DomainServiceObjectProcessor::SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *selected_ids) {
|
||||||
|
const size_t num_out_objects = this->GetOutObjectCount();
|
||||||
|
|
||||||
|
/* Copy input object IDs from command impl (normally these are Invalid, in mitm they should be set). */
|
||||||
|
DomainObjectId object_ids[8];
|
||||||
|
bool is_reserved[8];
|
||||||
|
for (size_t i = 0; i < num_out_objects; i++) {
|
||||||
|
object_ids[i] = selected_ids[i];
|
||||||
|
is_reserved[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserve object IDs as necessary. */
|
||||||
|
{
|
||||||
|
DomainObjectId reservations[8];
|
||||||
|
{
|
||||||
|
size_t num_unreserved_ids = 0;
|
||||||
|
DomainObjectId specific_ids[8];
|
||||||
|
size_t num_specific_ids = 0;
|
||||||
|
for (size_t i = 0; i < num_out_objects; i++) {
|
||||||
|
/* In the mitm case, we must not reserve IDs in use by other objects, so mitm objects will set this. */
|
||||||
|
if (object_ids[i] == InvalidDomainObjectId) {
|
||||||
|
num_unreserved_ids++;
|
||||||
|
} else {
|
||||||
|
specific_ids[num_specific_ids++] = object_ids[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* TODO: Can we make this error non-fatal? It isn't for N, since they can reserve IDs earlier due to not having to worry about mitm. */
|
||||||
|
R_ASSERT(this->domain->ReserveIds(reservations, num_unreserved_ids));
|
||||||
|
this->domain->ReserveSpecificIds(specific_ids, num_specific_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t reservation_index = 0;
|
||||||
|
for (size_t i = 0; i < num_out_objects; i++) {
|
||||||
|
if (object_ids[i] == InvalidDomainObjectId) {
|
||||||
|
object_ids[i] = reservations[reservation_index++];
|
||||||
|
is_reserved[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actually set out objects. */
|
||||||
|
for (size_t i = 0; i < num_out_objects; i++) {
|
||||||
|
if (!out_objects[i]) {
|
||||||
|
if (is_reserved[i]) {
|
||||||
|
this->domain->UnreserveIds(object_ids + i, 1);
|
||||||
|
}
|
||||||
|
object_ids[i] = InvalidDomainObjectId;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this->domain->RegisterObject(object_ids[i], std::move(out_objects[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set out object IDs in message. */
|
||||||
|
for (size_t i = 0; i < num_out_objects; i++) {
|
||||||
|
this->out_object_ids[i] = object_ids[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ namespace sts::sf::cmif {
|
||||||
const CmifInHeader *in_header = reinterpret_cast<const CmifInHeader *>(in_raw_data.GetPointer());
|
const CmifInHeader *in_header = reinterpret_cast<const CmifInHeader *>(in_raw_data.GetPointer());
|
||||||
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
|
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
|
||||||
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, ResultServiceFrameworkInvalidCmifInHeader);
|
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, ResultServiceFrameworkInvalidCmifInHeader);
|
||||||
|
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
|
||||||
const u32 cmd_id = in_header->command_id;
|
const u32 cmd_id = in_header->command_id;
|
||||||
|
|
||||||
/* Find a handler. */
|
/* Find a handler. */
|
||||||
|
@ -40,7 +41,7 @@ namespace sts::sf::cmif {
|
||||||
|
|
||||||
/* Invoke handler. */
|
/* Invoke handler. */
|
||||||
CmifOutHeader *out_header = nullptr;
|
CmifOutHeader *out_header = nullptr;
|
||||||
Result command_result = cmd_handler(&out_header, ctx, cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header)));
|
Result command_result = cmd_handler(&out_header, ctx, in_message_raw_data);
|
||||||
|
|
||||||
/* Forward forwardable results, otherwise ensure we can send result to user. */
|
/* Forward forwardable results, otherwise ensure we can send result to user. */
|
||||||
R_TRY_CATCH(command_result) {
|
R_TRY_CATCH(command_result) {
|
||||||
|
@ -65,6 +66,7 @@ namespace sts::sf::cmif {
|
||||||
const CmifInHeader *in_header = reinterpret_cast<const CmifInHeader *>(in_raw_data.GetPointer());
|
const CmifInHeader *in_header = reinterpret_cast<const CmifInHeader *>(in_raw_data.GetPointer());
|
||||||
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
|
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
|
||||||
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, ResultServiceFrameworkInvalidCmifInHeader);
|
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, ResultServiceFrameworkInvalidCmifInHeader);
|
||||||
|
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
|
||||||
const u32 cmd_id = in_header->command_id;
|
const u32 cmd_id = in_header->command_id;
|
||||||
|
|
||||||
/* Find a handler. */
|
/* Find a handler. */
|
||||||
|
@ -78,21 +80,18 @@ namespace sts::sf::cmif {
|
||||||
|
|
||||||
/* If we didn't find a handler, forward the request. */
|
/* If we didn't find a handler, forward the request. */
|
||||||
if (cmd_handler == nullptr) {
|
if (cmd_handler == nullptr) {
|
||||||
/* TODO: FORWARD REQUEST */
|
return ctx.session->ForwardRequest(ctx);
|
||||||
STS_ASSERT(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invoke handler. */
|
/* Invoke handler. */
|
||||||
CmifOutHeader *out_header = nullptr;
|
CmifOutHeader *out_header = nullptr;
|
||||||
Result command_result = cmd_handler(&out_header, ctx, cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header)));
|
Result command_result = cmd_handler(&out_header, ctx, in_message_raw_data);
|
||||||
|
|
||||||
/* Forward forwardable results, otherwise ensure we can send result to user. */
|
/* Forward forwardable results, otherwise ensure we can send result to user. */
|
||||||
R_TRY_CATCH(command_result) {
|
R_TRY_CATCH(command_result) {
|
||||||
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) { return ResultServiceFrameworkRequestDeferredByUser; }
|
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) { return ResultServiceFrameworkRequestDeferredByUser; }
|
||||||
R_CATCH(ResultAtmosphereMitmShouldForwardToSession) {
|
R_CATCH(ResultAtmosphereMitmShouldForwardToSession) {
|
||||||
/* TODO: Restore TLS. */
|
return ctx.session->ForwardRequest(ctx);
|
||||||
/* TODO: FORWARD REQUEST */
|
|
||||||
STS_ASSERT(false);
|
|
||||||
}
|
}
|
||||||
R_CATCH_ALL() { STS_ASSERT(out_header != nullptr); }
|
R_CATCH_ALL() { STS_ASSERT(out_header != nullptr); }
|
||||||
} R_END_TRY_CATCH;
|
} R_END_TRY_CATCH;
|
||||||
|
|
|
@ -63,8 +63,50 @@ namespace sts::sf::hipc {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ConvertCurrentObjectToDomain(sf::Out<cmif::DomainObjectId> out) {
|
Result ConvertCurrentObjectToDomain(sf::Out<cmif::DomainObjectId> out) {
|
||||||
/* TODO */
|
/* Allocate a domain. */
|
||||||
return ResultHipcOutOfDomains;
|
auto domain = this->manager->AllocateDomainServiceObject();
|
||||||
|
R_UNLESS(domain, ResultHipcOutOfDomains);
|
||||||
|
|
||||||
|
cmif::DomainObjectId object_id = cmif::InvalidDomainObjectId;
|
||||||
|
|
||||||
|
cmif::ServiceObjectHolder new_holder;
|
||||||
|
|
||||||
|
if (this->is_mitm_session) {
|
||||||
|
/* If we're a mitm session, we need to convert the remote session to domain. */
|
||||||
|
STS_ASSERT(session->forward_service->own_handle);
|
||||||
|
R_TRY_CLEANUP(serviceConvertToDomain(session->forward_service.get()), {
|
||||||
|
this->manager->FreeDomainServiceObject(domain);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* The object ID reservation cannot fail here, as that would cause desynchronization from target domain. */
|
||||||
|
object_id = cmif::DomainObjectId{session->forward_service->object_id};
|
||||||
|
domain->ReserveSpecificIds(&object_id, 1);
|
||||||
|
|
||||||
|
/* Create new object. */
|
||||||
|
cmif::MitmDomainServiceObject *domain_ptr = static_cast<cmif::MitmDomainServiceObject *>(domain);
|
||||||
|
new_holder = cmif::ServiceObjectHolder(std::move(std::shared_ptr<cmif::MitmDomainServiceObject>(domain_ptr, [&](cmif::MitmDomainServiceObject *obj) {
|
||||||
|
this->manager->FreeDomainServiceObject(domain);
|
||||||
|
})));
|
||||||
|
} else {
|
||||||
|
/* We're not a mitm session. Reserve a new object in the domain. */
|
||||||
|
R_TRY(domain->ReserveIds(&object_id, 1));
|
||||||
|
|
||||||
|
/* Create new object. */
|
||||||
|
cmif::DomainServiceObject *domain_ptr = static_cast<cmif::DomainServiceObject *>(domain);
|
||||||
|
new_holder = cmif::ServiceObjectHolder(std::move(std::shared_ptr<cmif::DomainServiceObject>(domain_ptr, [&](cmif::DomainServiceObject *obj) {
|
||||||
|
this->manager->FreeDomainServiceObject(domain);
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
STS_ASSERT(object_id != cmif::InvalidDomainObjectId);
|
||||||
|
STS_ASSERT(static_cast<bool>(new_holder));
|
||||||
|
|
||||||
|
/* We succeeded! */
|
||||||
|
domain->RegisterObject(object_id, std::move(session->srv_obj_holder));
|
||||||
|
session->srv_obj_holder = std::move(new_holder);
|
||||||
|
out.SetValue(object_id);
|
||||||
|
|
||||||
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CopyFromCurrentDomain(sf::OutMoveHandle out, cmif::DomainObjectId object_id) {
|
Result CopyFromCurrentDomain(sf::OutMoveHandle out, cmif::DomainObjectId object_id) {
|
||||||
|
|
|
@ -17,6 +17,57 @@
|
||||||
|
|
||||||
namespace sts::sf::hipc {
|
namespace sts::sf::hipc {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline void PreProcessCommandBufferForMitm(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &pointer_buffer, uintptr_t cmd_buffer) {
|
||||||
|
/* TODO: Less gross method of editing command buffer? */
|
||||||
|
if (ctx.request.meta.send_pid) {
|
||||||
|
constexpr u64 MitmProcessIdTag = 0xFFFE000000000000ul;
|
||||||
|
constexpr u64 OldProcessIdMask = 0x0000FFFFFFFFFFFFul;
|
||||||
|
u64 *process_id = reinterpret_cast<u64 *>(cmd_buffer + sizeof(HipcHeader) + sizeof(HipcSpecialHeader));
|
||||||
|
*process_id = (MitmProcessIdTag) | (*process_id & OldProcessIdMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.request.meta.num_recv_statics) {
|
||||||
|
/* TODO: Can we do this without gross bit-hackery? */
|
||||||
|
reinterpret_cast<HipcHeader *>(cmd_buffer)->recv_static_mode = 2;
|
||||||
|
const uintptr_t old_recv_list_entry = reinterpret_cast<uintptr_t>(ctx.request.data.recv_list);
|
||||||
|
const size_t old_recv_list_offset = old_recv_list_entry - util::AlignDown(old_recv_list_entry, TlsMessageBufferSize);
|
||||||
|
*reinterpret_cast<HipcRecvListEntry *>(cmd_buffer + old_recv_list_offset) = hipcMakeRecvStatic(pointer_buffer.GetPointer(), pointer_buffer.GetSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ServerSession::ForwardRequest(const cmif::ServiceDispatchContext &ctx) const {
|
||||||
|
STS_ASSERT(this->IsMitmSession());
|
||||||
|
/* TODO: Support non-TLS messages? */
|
||||||
|
STS_ASSERT(this->saved_message.GetPointer() != nullptr);
|
||||||
|
STS_ASSERT(this->saved_message.GetSize() == TlsMessageBufferSize);
|
||||||
|
|
||||||
|
/* Copy saved TLS in. */
|
||||||
|
std::memcpy(armGetTls(), this->saved_message.GetPointer(), this->saved_message.GetSize());
|
||||||
|
|
||||||
|
/* Prepare buffer. */
|
||||||
|
PreProcessCommandBufferForMitm(ctx, this->pointer_buffer, reinterpret_cast<uintptr_t>(armGetTls()));
|
||||||
|
|
||||||
|
/* Dispatch forwards. */
|
||||||
|
R_TRY(svcSendSyncRequest(this->forward_service->session));
|
||||||
|
|
||||||
|
/* Parse, to ensure we catch any copy handles and close them. */
|
||||||
|
{
|
||||||
|
const auto response = hipcParseResponse(armGetTls());
|
||||||
|
if (response.num_copy_handles) {
|
||||||
|
ctx.handles_to_close->num_handles = response.num_copy_handles;
|
||||||
|
for (size_t i = 0; i < response.num_copy_handles; i++) {
|
||||||
|
ctx.handles_to_close->handles[i] = response.copy_handles[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
void ServerSessionManager::DestroySession(ServerSession *session) {
|
void ServerSessionManager::DestroySession(ServerSession *session) {
|
||||||
/* Destroy object. */
|
/* Destroy object. */
|
||||||
session->~ServerSession();
|
session->~ServerSession();
|
||||||
|
@ -63,6 +114,9 @@ namespace sts::sf::hipc {
|
||||||
/* Assign session resources. */
|
/* Assign session resources. */
|
||||||
session_memory->pointer_buffer = this->GetSessionPointerBuffer(session_memory);
|
session_memory->pointer_buffer = this->GetSessionPointerBuffer(session_memory);
|
||||||
session_memory->saved_message = this->GetSessionSavedMessageBuffer(session_memory);
|
session_memory->saved_message = this->GetSessionSavedMessageBuffer(session_memory);
|
||||||
|
/* Validate session pointer buffer. */
|
||||||
|
STS_ASSERT(session_memory->pointer_buffer.GetSize() >= session_memory->forward_service->pointer_buffer_size);
|
||||||
|
session_memory->pointer_buffer = cmif::PointerAndSize(session_memory->pointer_buffer.GetAddress(), session_memory->forward_service->pointer_buffer_size);
|
||||||
/* Register to wait list. */
|
/* Register to wait list. */
|
||||||
this->RegisterSessionToWaitList(session_memory);
|
this->RegisterSessionToWaitList(session_memory);
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
|
@ -205,6 +259,7 @@ namespace sts::sf::hipc {
|
||||||
cmif::ServiceDispatchContext dispatch_ctx = {
|
cmif::ServiceDispatchContext dispatch_ctx = {
|
||||||
.srv_obj = obj_holder.GetServiceObjectUnsafe(),
|
.srv_obj = obj_holder.GetServiceObjectUnsafe(),
|
||||||
.manager = this,
|
.manager = this,
|
||||||
|
.session = session,
|
||||||
.processor = nullptr, /* Filled in by template implementations. */
|
.processor = nullptr, /* Filled in by template implementations. */
|
||||||
.handles_to_close = &handles_to_close,
|
.handles_to_close = &handles_to_close,
|
||||||
.pointer_buffer = session->pointer_buffer,
|
.pointer_buffer = session->pointer_buffer,
|
||||||
|
|
Loading…
Reference in a new issue