From 983f2b70741f17f30fe2321451f10cabecc013d2 Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 16 Oct 2022 01:53:56 -0400 Subject: kernel: invert session request handling flow --- src/core/hle/service/service.cpp | 13 ++++++++----- src/core/hle/service/service.h | 4 ++++ src/core/hle/service/sm/sm.cpp | 13 ++++++++----- src/core/hle/service/sm/sm.h | 1 + src/core/hle/service/sm/sm_controller.cpp | 21 +++++++++++---------- 5 files changed, 32 insertions(+), 20 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5db6588e4..0913a8065 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -99,6 +99,10 @@ ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* se ServiceFrameworkBase::~ServiceFrameworkBase() { // Wait for other threads to release access before destroying const auto guard = LockService(); + + if (named_port != nullptr) { + named_port->Close(); + } } void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) { @@ -115,13 +119,12 @@ Kernel::KClientPort& ServiceFrameworkBase::CreatePort() { ASSERT(!service_registered); - auto* port = Kernel::KPort::Create(kernel); - port->Initialize(max_sessions, false, service_name); - port->GetServerPort().SetSessionHandler(shared_from_this()); + named_port = Kernel::KPort::Create(kernel); + named_port->Initialize(max_sessions, false, service_name); service_registered = true; - return port->GetClientPort(); + return named_port->GetClientPort(); } void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { @@ -199,7 +202,6 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, switch (ctx.GetCommandType()) { case IPC::CommandType::Close: case IPC::CommandType::TIPC_Close: { - session.Close(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); result = IPC::ERR_REMOTE_PROCESS_DEAD; @@ -244,6 +246,7 @@ Services::Services(std::shared_ptr& sm, Core::System& system system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory); + system.Kernel().RegisterInterfaceForNamedService("sm:", SM::ServiceManager::SessionHandler); Account::InstallInterfaces(system); AM::InstallInterfaces(*sm, *nv_flinger, system); diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index ec9deeee4..22e2119d7 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -20,6 +20,7 @@ class System; namespace Kernel { class HLERequestContext; class KClientPort; +class KPort; class KServerSession; class ServiceThread; } // namespace Kernel @@ -98,6 +99,9 @@ protected: /// Identifier string used to connect to the service. std::string service_name; + /// Port used by ManageNamedPort. + Kernel::KPort* named_port{}; + private: template friend class ServiceFramework; diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index cb6c0e96f..c1f535d71 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -43,6 +43,10 @@ Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core return self.sm_interface->CreatePort(); } +void ServiceManager::SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port) { + self.sm_interface->AcceptSession(server_port); +} + Result ServiceManager::RegisterService(std::string name, u32 max_sessions, Kernel::SessionRequestHandlerPtr handler) { @@ -83,7 +87,6 @@ ResultVal ServiceManager::GetServicePort(const std::string& name port->Initialize(ServerSessionCountMax, false, name); auto handler = it->second; - port->GetServerPort().SetSessionHandler(std::move(handler)); return port; } @@ -144,7 +147,8 @@ ResultVal SM::GetServiceImpl(Kernel::HLERequestContext& // Find the named port. auto port_result = service_manager.GetServicePort(name); - if (port_result.Failed()) { + auto service = service_manager.GetService(name); + if (port_result.Failed() || !service) { LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw); return port_result.Code(); } @@ -156,12 +160,11 @@ ResultVal SM::GetServiceImpl(Kernel::HLERequestContext& // Create a new session. Kernel::KClientSession* session{}; - if (const auto result = port->GetClientPort().CreateSession( - std::addressof(session), std::make_shared(kernel)); - result.IsError()) { + if (const auto result = port->GetClientPort().CreateSession(&session); result.IsError()) { LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); return result; } + service->AcceptSession(&port->GetServerPort()); LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 878decc6f..cfe370652 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -51,6 +51,7 @@ private: class ServiceManager { public: static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system); + static void SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port); explicit ServiceManager(Kernel::KernelCore& kernel_); ~ServiceManager(); diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 46a8439d8..940c33478 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp @@ -15,10 +15,9 @@ namespace Service::SM { void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { - ASSERT_MSG(!ctx.Session()->GetSessionRequestManager()->IsDomain(), - "Session is already a domain"); + ASSERT_MSG(!ctx.GetManager()->IsDomain(), "Session is already a domain"); LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); - ctx.Session()->GetSessionRequestManager()->ConvertToDomainOnRequestEnd(); + ctx.GetManager()->ConvertToDomainOnRequestEnd(); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -29,30 +28,32 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service, "called"); auto& process = *ctx.GetThread().GetOwnerProcess(); - auto& parent_session = *ctx.Session()->GetParent(); - auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager(); - auto& session_handler = session_manager->SessionHandler(); + auto session_manager = ctx.GetManager(); // FIXME: this is duplicated from the SVC, it should just call it instead // once this is a proper process + // Declare the session we're going to allocate. + Kernel::KSession* session; + // Reserve a new session from the process resource limit. Kernel::KScopedResourceReservation session_reservation(&process, Kernel::LimitableResource::Sessions); ASSERT(session_reservation.Succeeded()); // Create the session. - Kernel::KSession* session = Kernel::KSession::Create(system.Kernel()); + session = Kernel::KSession::Create(system.Kernel()); ASSERT(session != nullptr); // Initialize the session. - session->Initialize(nullptr, parent_session.GetName(), session_manager); + session->Initialize(nullptr, ""); // Commit the session reservation. session_reservation.Commit(); - // Register the session. - session_handler.ClientConnected(&session->GetServerSession()); + // Register with manager. + session_manager->SessionHandler().RegisterSession(&session->GetServerSession(), + session_manager); // We succeeded. IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; -- cgit v1.2.3