libstrat: fix domain issues. in/out objects now work.

This commit is contained in:
Michael Scire
2019-10-23 00:07:20 -07:00
committed by SciresM
parent 4f455dacf4
commit 15773e4755
23 changed files with 161 additions and 113 deletions

View File

@@ -28,6 +28,7 @@ static constexpr Result ResultServiceFrameworkUnknownCmifCommandId = MAKERE
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 ResultServiceFrameworkInvalidCmifInObject = MAKERESULT(Module_ServiceFramework, 239);
static constexpr Result ResultServiceFrameworkTargetNotFound = MAKERESULT(Module_ServiceFramework, 261);

View File

@@ -32,6 +32,10 @@ namespace sts::sf::cmif {
/* Default constructor, null all members. */
ServiceObjectHolder() : srv(nullptr), dispatch_meta(nullptr) { /* ... */ }
~ServiceObjectHolder() {
this->dispatch_meta = nullptr;
}
/* Ensure correct type id at runtime through template constructor. */
template<typename ServiceImpl>
constexpr explicit ServiceObjectHolder(std::shared_ptr<ServiceImpl> &&s) {
@@ -40,7 +44,10 @@ namespace sts::sf::cmif {
}
/* Move constructor, assignment operator. */
ServiceObjectHolder(ServiceObjectHolder &&o) : srv(std::move(o.srv)), dispatch_meta(std::move(o.dispatch_meta)) { /* ... */ }
ServiceObjectHolder(ServiceObjectHolder &&o) : srv(std::move(o.srv)), dispatch_meta(std::move(o.dispatch_meta)) {
o.dispatch_meta = nullptr;
}
ServiceObjectHolder &operator=(ServiceObjectHolder &&o) {
ServiceObjectHolder tmp(std::move(o));
tmp.Swap(*this);
@@ -80,14 +87,19 @@ namespace sts::sf::cmif {
}
template<typename ServiceImpl>
ServiceImpl *GetServiceObject() const {
constexpr inline bool IsServiceObjectValid() const {
return this->GetServiceId() == GetServiceDispatchMeta<ServiceImpl>()->GetServiceId();
}
template<typename ServiceImpl>
inline std::shared_ptr<ServiceImpl> GetServiceObject() const {
if (this->GetServiceId() == GetServiceDispatchMeta<ServiceImpl>()->GetServiceId()) {
return static_cast<ServiceImpl *>(this->srv.get());
return std::static_pointer_cast<ServiceImpl>(this->srv);
}
return nullptr;
}
sf::IServiceObject *GetServiceObjectUnsafe() const {
inline sf::IServiceObject *GetServiceObjectUnsafe() const {
return this->srv.get();
}

View File

@@ -100,10 +100,7 @@ namespace sts::sf::hipc {
if constexpr (IsMitmServer) {
/* Custom deleter ensures that nothing goes awry. */
/* TODO: Should this just be a custom wrapper object? */
std::shared_ptr<::Service> forward_service(new ::Service(), [](::Service *srv) {
serviceClose(srv);
delete srv;
});
std::shared_ptr<::Service> forward_service = std::move(ServerSession::CreateForwardService());
/* Get mitm forward session. */
os::ProcessId client_pid;
@@ -348,12 +345,8 @@ namespace sts::sf::hipc {
std::memset(this->pointer_buffer_storage, 0, sizeof(this->pointer_buffer_storage));
std::memset(this->saved_message_storage, 0, sizeof(this->saved_message_storage));
if constexpr (ManagerOptions::MaxDomains > 0) {
std::memset(this->domain_storages, 0, sizeof(this->domain_storages));
std::memset(this->domain_allocated, 0, sizeof(this->domain_allocated));
}
if constexpr (ManagerOptions::MaxDomainObjects > 0) {
std::memset(this->domain_entry_storages, 0, sizeof(this->domain_entry_storages));
}
/* Set resource starts. */
this->pointer_buffers_start = util::AlignUp(reinterpret_cast<uintptr_t>(this->pointer_buffer_storage), 0x10);

View File

@@ -73,6 +73,15 @@ namespace sts::sf::hipc {
}
Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const;
static inline void ForwardServiceDeleter(Service *srv) {
serviceClose(srv);
delete srv;
}
static inline std::shared_ptr<::Service> CreateForwardService() {
return std::shared_ptr<::Service>(new ::Service(), ForwardServiceDeleter);
}
};
class ServerSessionManager {

View File

@@ -70,6 +70,9 @@ namespace sts::sf {
}
template<typename T>
class IsOutForceEnabled<std::shared_ptr<T>> : public std::true_type{};
template<typename ServiceImpl>
class Out<std::shared_ptr<ServiceImpl>> : public impl::OutObjectTag {
static_assert(std::is_base_of<sf::IServiceObject, ServiceImpl>::value, "Out<std::shared_ptr<ServiceImpl>> requires ServiceObject base.");
@@ -86,7 +89,7 @@ namespace sts::sf {
Out(cmif::ServiceObjectHolder *s, cmif::DomainObjectId *o) : srv(s), object_id(o) { /* ... */ }
void SetValue(std::shared_ptr<ServiceImpl> &&s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) {
*this->srv = ServiceObjectHolder(std::move(s));
*this->srv = cmif::ServiceObjectHolder(std::move(s));
if (new_object_id != cmif::InvalidDomainObjectId) {
*this->object_id = new_object_id;
}
@@ -655,7 +658,18 @@ namespace sts::sf::impl {
std::array<cmif::ServiceObjectHolder, NumOutObjects> out_object_holders;
std::array<cmif::DomainObjectId, NumOutObjects> out_object_ids;
public:
constexpr InOutObjectHolder() : in_object_holders(), out_object_holders() { /* ... */ }
constexpr InOutObjectHolder() : in_object_holders(), out_object_holders() {
#define _SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(n) if constexpr (NumOutObjects > n) { this->out_object_ids[n] = cmif::InvalidDomainObjectId; }
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(0)
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(1)
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(2)
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(3)
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(4)
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(5)
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(6)
_SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID(7)
#undef _SF_IN_OUT_HOLDER_INITIALIZE_OBJECT_ID
}
Result GetInObjects(const sf::cmif::ServerMessageProcessor *processor) {
if constexpr (NumInObjects > 0) {
@@ -664,25 +678,36 @@ namespace sts::sf::impl {
return ResultSuccess;
}
Result ValidateInObjects() {
/* TODO: Actually validate. */
if constexpr (NumInObjects > 0) {
/* Need to call holder.template GetServiceObject<>() for each object */
}
template<typename ServiceImplTuple>
constexpr inline Result ValidateInObjects() const {
static_assert(std::tuple_size<ServiceImplTuple>::value == NumInObjects);
#define _SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(n) do { \
if constexpr (NumInObjects > n) { \
using SharedPtrToServiceImplType = typename std::tuple_element<n, ServiceImplTuple>::type; \
using ServiceImplType = typename SharedPtrToServiceImplType::element_type; \
R_UNLESS((this->in_object_holders[n].template IsServiceObjectValid<ServiceImplType>()), ResultServiceFrameworkInvalidCmifInObject); \
} \
} while (0)
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(0);
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(1);
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(2);
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(3);
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(4);
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(5);
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(6);
_SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(7);
return ResultSuccess;
}
template<size_t Index, typename ServiceImpl>
std::shared_ptr<ServiceImpl> &&GetInObject() const {
auto &&holder = this->in_object_holders[Index];
auto obj = holder.template GetServiceObject<ServiceImpl>();
STS_ASSERT(obj);
return std::move(obj);
std::shared_ptr<ServiceImpl> GetInObject() const {
/* We know from ValidateInObjects() that this will succeed always. */
return this->in_object_holders[Index].template GetServiceObject<ServiceImpl>();
}
template<size_t Index, typename ServiceImpl>
Out<ServiceImpl> GetOutObject() const {
return Out<ServiceImpl>(&this->out_object_holders[Index], &this->out_object_ids[Index]);
Out<std::shared_ptr<ServiceImpl>> GetOutObject() {
return Out<std::shared_ptr<ServiceImpl>>(&this->out_object_holders[Index], &this->out_object_ids[Index]);
}
constexpr void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response) {
@@ -947,7 +972,7 @@ namespace sts::sf::impl {
/* Argument deserialization. */
private:
template<size_t Index, typename T = typename std::tuple_element<Index, ArgsType>::type>
NX_CONSTEXPR T DeserializeArgumentImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, const InOutObjectHolderType &in_out_objects_holder) {
NX_CONSTEXPR T DeserializeArgumentImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder) {
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
if constexpr (Info.arg_type == ArgumentType::InData) {
/* New in rawdata. */
@@ -982,10 +1007,10 @@ namespace sts::sf::impl {
}
} else if constexpr (Info.arg_type == ArgumentType::InObject) {
/* New InObject. */
return std::move(in_out_objects_holder.template GetInObject<Info.in_object_index, typename std::remove_extent<T>::type>());
return in_out_objects_holder.template GetInObject<Info.in_object_index, typename T::element_type>();
} else if constexpr (Info.arg_type == ArgumentType::OutObject) {
/* New OutObject. */
return in_out_objects_holder.template GetOutObject<Info.in_object_index, typename T::ServiceImplType>();
return in_out_objects_holder.template GetOutObject<Info.out_object_index, typename T::ServiceImplType>();
} else if constexpr (Info.arg_type == ArgumentType::Buffer) {
/* Buffers were already processed earlier. */
if constexpr (sf::IsLargeData<T>) {
@@ -1009,11 +1034,11 @@ namespace sts::sf::impl {
}
template<size_t... Is>
NX_CONSTEXPR ArgsType DeserializeArgumentsImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, const InOutObjectHolderType &in_out_objects_holder, std::index_sequence<Is...>) {
NX_CONSTEXPR ArgsType DeserializeArgumentsImpl(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder, std::index_sequence<Is...>) {
return ArgsType { DeserializeArgumentImpl<Is>(ctx, in_raw_data, out_raw_holder, buffers, out_handles_holder, in_out_objects_holder)..., };
}
public:
NX_CONSTEXPR ArgsType DeserializeArguments(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, const InOutObjectHolderType &in_out_objects_holder) {
NX_CONSTEXPR ArgsType DeserializeArguments(const cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const OutRawHolderType &out_raw_holder, const BufferArrayType &buffers, OutHandleHolderType &out_handles_holder, InOutObjectHolderType &in_out_objects_holder) {
return DeserializeArgumentsImpl(ctx, in_raw_data, out_raw_holder, buffers, out_handles_holder, in_out_objects_holder, std::make_index_sequence<std::tuple_size<ArgsType>::value>{});
}
};
@@ -1063,7 +1088,7 @@ namespace sts::sf::impl {
/* Process input/output objects. */
R_TRY(in_out_objects_holder.GetInObjects(ctx.processor));
R_TRY(in_out_objects_holder.ValidateInObjects());
R_TRY((in_out_objects_holder.template ValidateInObjects<typename CommandMeta::InObjects>()));
/* Decoding/Invocation. */
{

View File

@@ -38,6 +38,18 @@ namespace sts::sf {
static_assert(std::is_base_of<sts::sf::IServiceObject, T>::value, "ServiceObjectTraits requires ServiceObject");
static constexpr bool IsMitmServiceObject = std::is_base_of<IMitmServiceObject, T>::value;
struct SharedPointerHelper {
static constexpr void EmptyDelete(T *) { /* Empty deleter, for fake shared pointer. */ }
static constexpr std::shared_ptr<T> GetEmptyDeleteSharedPointer(T *srv_obj) {
return std::shared_ptr<T>(srv_obj, EmptyDelete);
}
};
};
}