libstrat: convert to experimental new (super-accurate) sf allocation semantics
This commit is contained in:
@@ -46,75 +46,20 @@ namespace ams::sf::hipc {
|
||||
protected:
|
||||
using ServerDomainSessionManager::DomainEntryStorage;
|
||||
using ServerDomainSessionManager::DomainStorage;
|
||||
private:
|
||||
class ServerBase : public os::WaitableHolderType {
|
||||
protected:
|
||||
class Server : public os::WaitableHolderType {
|
||||
friend class ServerManagerBase;
|
||||
template<size_t, typename, size_t>
|
||||
friend class ServerManager;
|
||||
NON_COPYABLE(ServerBase);
|
||||
NON_MOVEABLE(ServerBase);
|
||||
NON_COPYABLE(Server);
|
||||
NON_MOVEABLE(Server);
|
||||
protected:
|
||||
cmif::ServiceObjectHolder static_object;
|
||||
::Handle port_handle;
|
||||
sm::ServiceName service_name;
|
||||
int index;
|
||||
bool service_managed;
|
||||
public:
|
||||
ServerBase(Handle ph, sm::ServiceName sn, bool m, cmif::ServiceObjectHolder &&sh) :
|
||||
static_object(std::move(sh)), port_handle(ph), service_name(sn), service_managed(m)
|
||||
{
|
||||
hipc::AttachWaitableHolderForAccept(this, ph);
|
||||
}
|
||||
|
||||
virtual ~ServerBase() = 0;
|
||||
virtual void CreateSessionObjectHolder(cmif::ServiceObjectHolder *out_obj, std::shared_ptr<::Service> *out_fsrv) const = 0;
|
||||
};
|
||||
|
||||
template<typename Interface, auto MakeShared>
|
||||
class Server : public ServerBase {
|
||||
NON_COPYABLE(Server);
|
||||
NON_MOVEABLE(Server);
|
||||
private:
|
||||
static constexpr bool IsMitmServer = sf::IsMitmServiceObject<Interface>;
|
||||
public:
|
||||
Server(Handle ph, sm::ServiceName sn, bool m, cmif::ServiceObjectHolder &&sh) : ServerBase(ph, sn, m, std::forward<cmif::ServiceObjectHolder>(sh)) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
virtual ~Server() override {
|
||||
if (this->service_managed) {
|
||||
if constexpr (IsMitmServer) {
|
||||
R_ABORT_UNLESS(sm::mitm::UninstallMitm(this->service_name));
|
||||
} else {
|
||||
R_ABORT_UNLESS(sm::UnregisterService(this->service_name));
|
||||
}
|
||||
R_ABORT_UNLESS(svc::CloseHandle(this->port_handle));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void CreateSessionObjectHolder(cmif::ServiceObjectHolder *out_obj, std::shared_ptr<::Service> *out_fsrv) const override final {
|
||||
/* If we're serving a static object, use it. */
|
||||
if (this->static_object) {
|
||||
*out_obj = std::move(this->static_object.Clone());
|
||||
*out_fsrv = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, we're either a mitm session or a non-mitm session. */
|
||||
if constexpr (IsMitmServer) {
|
||||
/* Custom deleter ensures that nothing goes awry. */
|
||||
std::shared_ptr<::Service> forward_service = std::move(ServerSession::CreateForwardService());
|
||||
|
||||
/* Get mitm forward session. */
|
||||
sm::MitmProcessInfo client_info;
|
||||
R_ABORT_UNLESS(sm::mitm::AcknowledgeSession(forward_service.get(), &client_info, this->service_name));
|
||||
|
||||
*out_obj = std::move(cmif::ServiceObjectHolder(std::move(MakeShared(std::shared_ptr<::Service>(forward_service), client_info))));
|
||||
*out_fsrv = std::move(forward_service);
|
||||
} else {
|
||||
*out_obj = std::move(cmif::ServiceObjectHolder(std::move(MakeShared())));
|
||||
*out_fsrv = nullptr;
|
||||
}
|
||||
}
|
||||
bool is_mitm_server;
|
||||
};
|
||||
private:
|
||||
/* Management of waitables. */
|
||||
@@ -139,33 +84,94 @@ namespace ams::sf::hipc {
|
||||
Result ProcessForMitmServer(os::WaitableHolderType *holder);
|
||||
Result ProcessForSession(os::WaitableHolderType *holder);
|
||||
|
||||
template<typename Interface, auto MakeShared>
|
||||
void RegisterServerImpl(Handle port_handle, sm::ServiceName service_name, bool managed, cmif::ServiceObjectHolder &&static_holder) {
|
||||
/* Allocate server memory. */
|
||||
auto *server = this->AllocateServer();
|
||||
AMS_ABORT_UNLESS(server != nullptr);
|
||||
new (server) Server<Interface, MakeShared>(port_handle, service_name, managed, std::forward<cmif::ServiceObjectHolder>(static_holder));
|
||||
void RegisterServerImpl(Server *server, Handle port_handle, bool is_mitm_server) {
|
||||
server->port_handle = port_handle;
|
||||
hipc::AttachWaitableHolderForAccept(server, port_handle);
|
||||
|
||||
if constexpr (!sf::IsMitmServiceObject<Interface>) {
|
||||
/* Non-mitm server. */
|
||||
os::SetWaitableHolderUserData(server, static_cast<uintptr_t>(UserDataTag::Server));
|
||||
} else {
|
||||
server->is_mitm_server = is_mitm_server;
|
||||
if (is_mitm_server) {
|
||||
/* Mitm server. */
|
||||
os::SetWaitableHolderUserData(server, static_cast<uintptr_t>(UserDataTag::MitmServer));
|
||||
} else {
|
||||
/* Non-mitm server. */
|
||||
os::SetWaitableHolderUserData(server, static_cast<uintptr_t>(UserDataTag::Server));
|
||||
}
|
||||
|
||||
os::LinkWaitableHolder(std::addressof(this->waitable_manager), server);
|
||||
}
|
||||
|
||||
template<typename Interface, typename ServiceImpl>
|
||||
static constexpr inline std::shared_ptr<Interface> MakeSharedMitm(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &client_info) {
|
||||
return sf::MakeShared<Interface, ServiceImpl>(std::forward<std::shared_ptr<::Service>>(s), client_info);
|
||||
void RegisterServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, Handle port_handle, bool is_mitm_server) {
|
||||
/* Allocate server memory. */
|
||||
auto *server = this->AllocateServer();
|
||||
AMS_ABORT_UNLESS(server != nullptr);
|
||||
server->service_managed = false;
|
||||
|
||||
if (static_holder) {
|
||||
server->static_object = std::move(static_holder);
|
||||
} else {
|
||||
server->index = index;
|
||||
}
|
||||
|
||||
this->RegisterServerImpl(server, port_handle, is_mitm_server);
|
||||
}
|
||||
|
||||
Result RegisterServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name, size_t max_sessions) {
|
||||
/* Register service. */
|
||||
Handle port_handle;
|
||||
R_TRY(sm::RegisterService(&port_handle, service_name, max_sessions, false));
|
||||
|
||||
/* Allocate server memory. */
|
||||
auto *server = this->AllocateServer();
|
||||
AMS_ABORT_UNLESS(server != nullptr);
|
||||
server->service_managed = true;
|
||||
server->service_name = service_name;
|
||||
|
||||
if (static_holder) {
|
||||
server->static_object = std::move(static_holder);
|
||||
} else {
|
||||
server->index = index;
|
||||
}
|
||||
|
||||
this->RegisterServerImpl(server, port_handle, false);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
Result RegisterMitmServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name) {
|
||||
/* Install mitm service. */
|
||||
Handle port_handle;
|
||||
R_TRY(this->InstallMitmServerImpl(&port_handle, service_name, &Interface::ShouldMitm));
|
||||
|
||||
/* Allocate server memory. */
|
||||
auto *server = this->AllocateServer();
|
||||
AMS_ABORT_UNLESS(server != nullptr);
|
||||
server->service_managed = true;
|
||||
server->service_name = service_name;
|
||||
|
||||
if (static_holder) {
|
||||
server->static_object = std::move(static_holder);
|
||||
} else {
|
||||
server->index = index;
|
||||
}
|
||||
|
||||
this->RegisterServerImpl(server, port_handle, true);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result InstallMitmServerImpl(Handle *out_port_handle, sm::ServiceName service_name, MitmQueryFunction query_func);
|
||||
protected:
|
||||
virtual ServerBase *AllocateServer() = 0;
|
||||
virtual void DestroyServer(ServerBase *server) = 0;
|
||||
virtual Server *AllocateServer() = 0;
|
||||
virtual void DestroyServer(Server *server) = 0;
|
||||
virtual Result OnNeedsToAccept(int port_index, Server *server) {
|
||||
AMS_ABORT("OnNeedsToAccept must be overridden when using indexed ports");
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
Result AcceptImpl(Server *server, SharedPointer<Interface> p) {
|
||||
return ServerSessionManager::AcceptSession(server->port_handle, std::move(p));
|
||||
}
|
||||
public:
|
||||
ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count) :
|
||||
ServerDomainSessionManager(entry_storage, entry_count),
|
||||
@@ -181,40 +187,27 @@ namespace ams::sf::hipc {
|
||||
os::InitializeWaitableManager(std::addressof(this->waitlist));
|
||||
}
|
||||
|
||||
template<typename Interface, typename ServiceImpl, auto MakeShared = sf::MakeShared<Interface, ServiceImpl>> requires (sf::IsServiceObject<Interface> && !sf::IsMitmServiceObject<Interface>)
|
||||
void RegisterServer(Handle port_handle, std::shared_ptr<Interface> static_object = nullptr) {
|
||||
/* Register server. */
|
||||
cmif::ServiceObjectHolder static_holder;
|
||||
if (static_object != nullptr) {
|
||||
static_holder = cmif::ServiceObjectHolder(std::move(static_object));
|
||||
}
|
||||
this->RegisterServerImpl<Interface, MakeShared>(port_handle, sm::InvalidServiceName, false, std::move(static_holder));
|
||||
template<typename Interface>
|
||||
void RegisterObjectForServer(SharedPointer<Interface> static_object, Handle port_handle) {
|
||||
this->RegisterServerImpl(0, cmif::ServiceObjectHolder(std::move(static_object)), port_handle, false);
|
||||
}
|
||||
|
||||
template<typename Interface, typename ServiceImpl, auto MakeShared = sf::MakeShared<Interface, ServiceImpl>> requires (sf::IsServiceObject<Interface> && !sf::IsMitmServiceObject<Interface>)
|
||||
Result RegisterServer(sm::ServiceName service_name, size_t max_sessions, std::shared_ptr<Interface> static_object = nullptr) {
|
||||
/* Register service. */
|
||||
Handle port_handle;
|
||||
R_TRY(sm::RegisterService(&port_handle, service_name, max_sessions, false));
|
||||
|
||||
/* Register server. */
|
||||
cmif::ServiceObjectHolder static_holder;
|
||||
if (static_object != nullptr) {
|
||||
static_holder = cmif::ServiceObjectHolder(std::move(static_object));
|
||||
}
|
||||
this->RegisterServerImpl<Interface, MakeShared>(port_handle, service_name, true, std::move(static_holder));
|
||||
return ResultSuccess();
|
||||
template<typename Interface>
|
||||
Result RegisterObjectForServer(SharedPointer<Interface> static_object, sm::ServiceName service_name, size_t max_sessions) {
|
||||
return this->RegisterServerImpl(0, cmif::ServiceObjectHolder(std::move(static_object)), service_name, max_sessions);
|
||||
}
|
||||
|
||||
template<typename Interface, typename ServiceImpl, auto MakeShared = MakeSharedMitm<Interface, ServiceImpl>>
|
||||
requires (sf::IsMitmServiceObject<Interface> && sf::IsMitmServiceImpl<ServiceImpl>)
|
||||
Result RegisterMitmServer(sm::ServiceName service_name) {
|
||||
/* Install mitm service. */
|
||||
Handle port_handle;
|
||||
R_TRY(this->InstallMitmServerImpl(&port_handle, service_name, &ServiceImpl::ShouldMitm));
|
||||
void RegisterServer(int port_index, Handle port_handle) {
|
||||
this->RegisterServerImpl(port_index, cmif::ServiceObjectHolder(), port_handle, false);
|
||||
}
|
||||
|
||||
this->RegisterServerImpl<Interface, MakeShared>(port_handle, service_name, true, cmif::ServiceObjectHolder());
|
||||
return ResultSuccess();
|
||||
Result RegisterServer(int port_index, sm::ServiceName service_name, size_t max_sessions) {
|
||||
return this->RegisterServerImpl(port_index, cmif::ServiceObjectHolder(), service_name, max_sessions);
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
Result RegisterMitmServer(int port_index, sm::ServiceName service_name) {
|
||||
return this->template RegisterMitmServerImpl<Interface>(port_index, cmif::ServiceObjectHolder(), service_name);
|
||||
}
|
||||
|
||||
/* Processing. */
|
||||
@@ -251,7 +244,7 @@ namespace ams::sf::hipc {
|
||||
private:
|
||||
/* Resource storage. */
|
||||
os::Mutex resource_mutex;
|
||||
TYPED_STORAGE(ServerBase) server_storages[MaxServers];
|
||||
TYPED_STORAGE(Server) server_storages[MaxServers];
|
||||
bool server_allocated[MaxServers];
|
||||
TYPED_STORAGE(ServerSession) session_storages[MaxSessions];
|
||||
bool session_allocated[MaxSessions];
|
||||
@@ -265,7 +258,7 @@ namespace ams::sf::hipc {
|
||||
bool domain_allocated[ManagerOptions::MaxDomains];
|
||||
DomainEntryStorage domain_entry_storages[ManagerOptions::MaxDomainObjects];
|
||||
private:
|
||||
constexpr inline size_t GetServerIndex(const ServerBase *server) const {
|
||||
constexpr inline size_t GetServerIndex(const Server *server) const {
|
||||
const size_t i = server - GetPointer(this->server_storages[0]);
|
||||
AMS_ABORT_UNLESS(i < MaxServers);
|
||||
return i;
|
||||
@@ -299,7 +292,7 @@ namespace ams::sf::hipc {
|
||||
this->session_allocated[index] = false;
|
||||
}
|
||||
|
||||
virtual ServerBase *AllocateServer() override final {
|
||||
virtual Server *AllocateServer() override final {
|
||||
std::scoped_lock lk(this->resource_mutex);
|
||||
for (size_t i = 0; i < MaxServers; i++) {
|
||||
if (!this->server_allocated[i]) {
|
||||
@@ -310,11 +303,22 @@ namespace ams::sf::hipc {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void DestroyServer(ServerBase *server) override final {
|
||||
virtual void DestroyServer(Server *server) override final {
|
||||
std::scoped_lock lk(this->resource_mutex);
|
||||
const size_t index = this->GetServerIndex(server);
|
||||
AMS_ABORT_UNLESS(this->server_allocated[index]);
|
||||
server->~ServerBase();
|
||||
{
|
||||
os::UnlinkWaitableHolder(server);
|
||||
os::FinalizeWaitableHolder(server);
|
||||
if (server->service_managed) {
|
||||
if (server->is_mitm_server) {
|
||||
R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->service_name));
|
||||
} else {
|
||||
R_ABORT_UNLESS(sm::UnregisterService(server->service_name));
|
||||
}
|
||||
R_ABORT_UNLESS(svc::CloseHandle(server->port_handle));
|
||||
}
|
||||
}
|
||||
this->server_allocated[index] = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,14 +34,14 @@ namespace ams::sf::hipc {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class HipcManager;
|
||||
class HipcManagerImpl;
|
||||
|
||||
}
|
||||
|
||||
class ServerSession : public os::WaitableHolderType {
|
||||
friend class ServerSessionManager;
|
||||
friend class ServerManagerBase;
|
||||
friend class impl::HipcManager;
|
||||
friend class impl::HipcManagerImpl;
|
||||
NON_COPYABLE(ServerSession);
|
||||
NON_MOVEABLE(ServerSession);
|
||||
private:
|
||||
@@ -92,16 +92,13 @@ namespace ams::sf::hipc {
|
||||
/* Allocate session. */
|
||||
ServerSession *session_memory = this->AllocateSession();
|
||||
R_UNLESS(session_memory != nullptr, sf::hipc::ResultOutOfSessionMemory());
|
||||
|
||||
/* Register session. */
|
||||
bool succeeded = false;
|
||||
ON_SCOPE_EXIT {
|
||||
if (!succeeded) {
|
||||
this->DestroySession(session_memory);
|
||||
}
|
||||
};
|
||||
auto register_guard = SCOPE_GUARD { this->DestroySession(session_memory); };
|
||||
R_TRY(ctor(session_memory));
|
||||
|
||||
/* Save new session to output. */
|
||||
succeeded = true;
|
||||
register_guard.Cancel();
|
||||
*out = session_memory;
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -162,13 +159,13 @@ namespace ams::sf::hipc {
|
||||
Result RegisterMitmSession(Handle session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||
Result AcceptMitmSession(Handle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||
|
||||
template<typename ServiceImpl>
|
||||
Result AcceptSession(Handle port_handle, std::shared_ptr<ServiceImpl> obj) {
|
||||
template<typename Interface>
|
||||
Result AcceptSession(Handle port_handle, SharedPointer<Interface> obj) {
|
||||
return this->AcceptSession(port_handle, cmif::ServiceObjectHolder(std::move(obj)));
|
||||
}
|
||||
|
||||
template<typename ServiceImpl>
|
||||
Result AcceptMitmSession(Handle mitm_port_handle, std::shared_ptr<ServiceImpl> obj, std::shared_ptr<::Service> &&fsrv) {
|
||||
template<typename Interface>
|
||||
Result AcceptMitmSession(Handle mitm_port_handle, SharedPointer<Interface> obj, std::shared_ptr<::Service> &&fsrv) {
|
||||
return this->AcceptMitmSession(mitm_port_handle, cmif::ServiceObjectHolder(std::move(obj)), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user