Просмотр исходного кода

Kernel: Add a dedicated SetHleHandler method to ServerPort/ServerSession

This allows attaching a HLE handle to a ServerPort at any point after it
is created, allowing port/session creation to be generic between HLE and
regular services.
Yuri Kunde Schlesner 9 лет назад
Родитель
Сommit
6354d08359

+ 4 - 7
src/core/hle/kernel/client_port.cpp

@@ -26,20 +26,17 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
     active_sessions++;
     active_sessions++;
 
 
     // Create a new session pair, let the created sessions inherit the parent port's HLE handler.
     // Create a new session pair, let the created sessions inherit the parent port's HLE handler.
-    auto sessions =
-        ServerSession::CreateSessionPair(server_port->GetName(), server_port->hle_handler, this);
-    auto client_session = std::get<SharedPtr<ClientSession>>(sessions);
-    auto server_session = std::get<SharedPtr<ServerSession>>(sessions);
+    auto sessions = ServerSession::CreateSessionPair(server_port->GetName(), this);
 
 
     if (server_port->hle_handler)
     if (server_port->hle_handler)
-        server_port->hle_handler->ClientConnected(server_session);
+        server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
     else
     else
-        server_port->pending_sessions.push_back(std::move(server_session));
+        server_port->pending_sessions.push_back(std::get<SharedPtr<ServerSession>>(sessions));
 
 
     // Wake the threads waiting on the ServerPort
     // Wake the threads waiting on the ServerPort
     server_port->WakeupAllWaitingThreads();
     server_port->WakeupAllWaitingThreads();
 
 
-    return MakeResult<SharedPtr<ClientSession>>(std::move(client_session));
+    return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
 }
 }
 
 
 } // namespace
 } // namespace

+ 2 - 0
src/core/hle/kernel/hle_ipc.cpp

@@ -12,10 +12,12 @@
 namespace Kernel {
 namespace Kernel {
 
 
 void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) {
 void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) {
+    server_session->SetHleHandler(shared_from_this());
     connected_sessions.push_back(server_session);
     connected_sessions.push_back(server_session);
 }
 }
 
 
 void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_session) {
 void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_session) {
+    server_session->SetHleHandler(nullptr);
     boost::range::remove_erase(connected_sessions, server_session);
     boost::range::remove_erase(connected_sessions, server_session);
 }
 }
 
 

+ 2 - 1
src/core/hle/kernel/hle_ipc.h

@@ -4,6 +4,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <memory>
 #include <vector>
 #include <vector>
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/kernel.h"
 
 
@@ -16,7 +17,7 @@ class ServerSession;
  * This can be provided to a ServerSession in order to hook into several relevant events
  * This can be provided to a ServerSession in order to hook into several relevant events
  * (such as a new connection or a SyncRequest) so they can be implemented in the emulator.
  * (such as a new connection or a SyncRequest) so they can be implemented in the emulator.
  */
  */
-class SessionRequestHandler {
+class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
 public:
 public:
     /**
     /**
      * Handles a sync request from the emulated application.
      * Handles a sync request from the emulated application.

+ 1 - 2
src/core/hle/kernel/server_port.cpp

@@ -24,13 +24,12 @@ void ServerPort::Acquire(Thread* thread) {
 }
 }
 
 
 std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
 std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
-    u32 max_sessions, std::string name, std::shared_ptr<SessionRequestHandler> hle_handler) {
+    u32 max_sessions, std::string name) {
 
 
     SharedPtr<ServerPort> server_port(new ServerPort);
     SharedPtr<ServerPort> server_port(new ServerPort);
     SharedPtr<ClientPort> client_port(new ClientPort);
     SharedPtr<ClientPort> client_port(new ClientPort);
 
 
     server_port->name = name + "_Server";
     server_port->name = name + "_Server";
-    server_port->hle_handler = std::move(hle_handler);
     client_port->name = name + "_Client";
     client_port->name = name + "_Client";
     client_port->server_port = server_port;
     client_port->server_port = server_port;
     client_port->max_sessions = max_sessions;
     client_port->max_sessions = max_sessions;

+ 10 - 4
src/core/hle/kernel/server_port.h

@@ -20,15 +20,13 @@ class ServerPort final : public WaitObject {
 public:
 public:
     /**
     /**
      * Creates a pair of ServerPort and an associated ClientPort.
      * Creates a pair of ServerPort and an associated ClientPort.
+     *
      * @param max_sessions Maximum number of sessions to the port
      * @param max_sessions Maximum number of sessions to the port
      * @param name Optional name of the ports
      * @param name Optional name of the ports
-     * @param hle_handler Optional HLE handler template for the port,
-     * ServerSessions crated from this port will inherit a reference to this handler.
      * @return The created port tuple
      * @return The created port tuple
      */
      */
     static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
     static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
-        u32 max_sessions, std::string name = "UnknownPort",
-        std::shared_ptr<SessionRequestHandler> hle_handler = nullptr);
+        u32 max_sessions, std::string name = "UnknownPort");
 
 
     std::string GetTypeName() const override {
     std::string GetTypeName() const override {
         return "ServerPort";
         return "ServerPort";
@@ -42,6 +40,14 @@ public:
         return HANDLE_TYPE;
         return HANDLE_TYPE;
     }
     }
 
 
+    /**
+     * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
+     * will inherit a reference to this handler.
+     */
+    void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) {
+        hle_handler = std::move(hle_handler_);
+    }
+
     std::string name; ///< Name of port (optional)
     std::string name; ///< Name of port (optional)
 
 
     std::vector<SharedPtr<WaitObject>>
     std::vector<SharedPtr<WaitObject>>

+ 5 - 11
src/core/hle/kernel/server_session.cpp

@@ -28,16 +28,14 @@ ServerSession::~ServerSession() {
     parent->server = nullptr;
     parent->server = nullptr;
 }
 }
 
 
-ResultVal<SharedPtr<ServerSession>> ServerSession::Create(
-    std::string name, std::shared_ptr<SessionRequestHandler> hle_handler) {
+ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) {
     SharedPtr<ServerSession> server_session(new ServerSession);
     SharedPtr<ServerSession> server_session(new ServerSession);
 
 
     server_session->name = std::move(name);
     server_session->name = std::move(name);
     server_session->signaled = false;
     server_session->signaled = false;
-    server_session->hle_handler = std::move(hle_handler);
     server_session->parent = nullptr;
     server_session->parent = nullptr;
 
 
-    return MakeResult<SharedPtr<ServerSession>>(std::move(server_session));
+    return MakeResult(std::move(server_session));
 }
 }
 
 
 bool ServerSession::ShouldWait(Thread* thread) const {
 bool ServerSession::ShouldWait(Thread* thread) const {
@@ -71,13 +69,9 @@ ResultCode ServerSession::HandleSyncRequest() {
     return RESULT_SUCCESS;
     return RESULT_SUCCESS;
 }
 }
 
 
-ServerSession::SessionPair ServerSession::CreateSessionPair(
-    const std::string& name, std::shared_ptr<SessionRequestHandler> hle_handler,
-    SharedPtr<ClientPort> port) {
-
-    auto server_session =
-        ServerSession::Create(name + "_Server", std::move(hle_handler)).MoveFrom();
-
+ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name,
+                                                            SharedPtr<ClientPort> port) {
+    auto server_session = ServerSession::Create(name + "_Server").MoveFrom();
     SharedPtr<ClientSession> client_session(new ClientSession);
     SharedPtr<ClientSession> client_session(new ClientSession);
     client_session->name = name + "_Client";
     client_session->name = name + "_Client";
 
 

+ 12 - 8
src/core/hle/kernel/server_session.h

@@ -50,14 +50,20 @@ public:
     /**
     /**
      * Creates a pair of ServerSession and an associated ClientSession.
      * Creates a pair of ServerSession and an associated ClientSession.
      * @param name        Optional name of the ports.
      * @param name        Optional name of the ports.
-     * @param hle_handler Optional HLE handler for this server session.
      * @param client_port Optional The ClientPort that spawned this session.
      * @param client_port Optional The ClientPort that spawned this session.
      * @return The created session tuple
      * @return The created session tuple
      */
      */
-    static SessionPair CreateSessionPair(
-        const std::string& name = "Unknown",
-        std::shared_ptr<SessionRequestHandler> hle_handler = nullptr,
-        SharedPtr<ClientPort> client_port = nullptr);
+    static SessionPair CreateSessionPair(const std::string& name = "Unknown",
+                                         SharedPtr<ClientPort> client_port = nullptr);
+
+    /**
+     * Sets the HLE handler for the session. This handler will be called to service IPC requests
+     * instead of the regular IPC machinery. (The regular IPC machinery is currently not
+     * implemented.)
+     */
+    void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) {
+        hle_handler = std::move(hle_handler_);
+    }
 
 
     /**
     /**
      * Handle a sync request from the emulated application.
      * Handle a sync request from the emulated application.
@@ -83,11 +89,9 @@ private:
      * Creates a server session. The server session can have an optional HLE handler,
      * Creates a server session. The server session can have an optional HLE handler,
      * which will be invoked to handle the IPC requests that this session receives.
      * which will be invoked to handle the IPC requests that this session receives.
      * @param name Optional name of the server session.
      * @param name Optional name of the server session.
-     * @param hle_handler Optional HLE handler for this server session.
      * @return The created server session
      * @return The created server session
      */
      */
-    static ResultVal<SharedPtr<ServerSession>> Create(
-        std::string name = "Unknown", std::shared_ptr<SessionRequestHandler> hle_handler = nullptr);
+    static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown");
 };
 };
 
 
 /**
 /**

+ 7 - 4
src/core/hle/service/fs/archive.cpp

@@ -84,6 +84,10 @@ File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path&
 File::~File() {}
 File::~File() {}
 
 
 void File::HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) {
 void File::HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) {
+    using Kernel::ClientSession;
+    using Kernel::ServerSession;
+    using Kernel::SharedPtr;
+
     u32* cmd_buff = Kernel::GetCommandBuffer();
     u32* cmd_buff = Kernel::GetCommandBuffer();
     FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
     FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
     switch (cmd) {
     switch (cmd) {
@@ -162,10 +166,9 @@ void File::HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_ses
 
 
     case FileCommand::OpenLinkFile: {
     case FileCommand::OpenLinkFile: {
         LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
         LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
-        auto sessions = Kernel::ServerSession::CreateSessionPair(GetName(), shared_from_this());
-        ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions));
-        cmd_buff[3] = Kernel::g_handle_table
-                          .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions))
+        auto sessions = ServerSession::CreateSessionPair(GetName());
+        ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
+        cmd_buff[3] = Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions))
                           .ValueOr(INVALID_HANDLE);
                           .ValueOr(INVALID_HANDLE);
         break;
         break;
     }
     }

+ 1 - 1
src/core/hle/service/fs/archive.h

@@ -43,7 +43,7 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1, GameCard = 2 };
 
 
 typedef u64 ArchiveHandle;
 typedef u64 ArchiveHandle;
 
 
-class File final : public Kernel::SessionRequestHandler, public std::enable_shared_from_this<File> {
+class File final : public Kernel::SessionRequestHandler {
 public:
 public:
     File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path);
     File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path);
     ~File();
     ~File();

+ 17 - 16
src/core/hle/service/fs/fs_user.cpp

@@ -20,8 +20,9 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Namespace FS_User
 // Namespace FS_User
 
 
-using Kernel::SharedPtr;
+using Kernel::ClientSession;
 using Kernel::ServerSession;
 using Kernel::ServerSession;
+using Kernel::SharedPtr;
 
 
 namespace Service {
 namespace Service {
 namespace FS {
 namespace FS {
@@ -79,11 +80,11 @@ static void OpenFile(Service::Interface* self) {
     rb.Push(file_res.Code());
     rb.Push(file_res.Code());
     if (file_res.Succeeded()) {
     if (file_res.Succeeded()) {
         std::shared_ptr<File> file = *file_res;
         std::shared_ptr<File> file = *file_res;
-        auto sessions = ServerSession::CreateSessionPair(file->GetName(), file);
-        file->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions));
-        rb.PushMoveHandles(Kernel::g_handle_table
-                               .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions))
-                               .MoveFrom());
+        auto sessions = ServerSession::CreateSessionPair(file->GetName());
+        file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
+
+        rb.PushMoveHandles(
+            Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom());
     } else {
     } else {
         rb.PushMoveHandles(0);
         rb.PushMoveHandles(0);
         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -145,11 +146,11 @@ static void OpenFileDirectly(Service::Interface* self) {
     cmd_buff[1] = file_res.Code().raw;
     cmd_buff[1] = file_res.Code().raw;
     if (file_res.Succeeded()) {
     if (file_res.Succeeded()) {
         std::shared_ptr<File> file = *file_res;
         std::shared_ptr<File> file = *file_res;
-        auto sessions = ServerSession::CreateSessionPair(file->GetName(), file);
-        file->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions));
-        cmd_buff[3] = Kernel::g_handle_table
-                          .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions))
-                          .MoveFrom();
+        auto sessions = ServerSession::CreateSessionPair(file->GetName());
+        file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
+
+        cmd_buff[3] =
+            Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom();
     } else {
     } else {
         cmd_buff[3] = 0;
         cmd_buff[3] = 0;
         LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u",
         LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u",
@@ -412,11 +413,11 @@ static void OpenDirectory(Service::Interface* self) {
     cmd_buff[1] = dir_res.Code().raw;
     cmd_buff[1] = dir_res.Code().raw;
     if (dir_res.Succeeded()) {
     if (dir_res.Succeeded()) {
         std::shared_ptr<Directory> directory = *dir_res;
         std::shared_ptr<Directory> directory = *dir_res;
-        auto sessions = ServerSession::CreateSessionPair(directory->GetName(), directory);
-        directory->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions));
-        cmd_buff[3] = Kernel::g_handle_table
-                          .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions))
-                          .MoveFrom();
+        auto sessions = ServerSession::CreateSessionPair(directory->GetName());
+        directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
+
+        cmd_buff[3] =
+            Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom();
     } else {
     } else {
         LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s",
         LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s",
                   dirname_type, dirname_size, dir_path.DebugStr().c_str());
                   dirname_type, dirname_size, dir_path.DebugStr().c_str());

+ 12 - 8
src/core/hle/service/service.cpp

@@ -105,18 +105,22 @@ void Interface::Register(const FunctionInfo* functions, size_t n) {
 // Module interface
 // Module interface
 
 
 static void AddNamedPort(Interface* interface_) {
 static void AddNamedPort(Interface* interface_) {
-    auto ports =
-        Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(),
-                                           std::shared_ptr<Interface>(interface_));
-    auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports);
+    Kernel::SharedPtr<Kernel::ServerPort> server_port;
+    Kernel::SharedPtr<Kernel::ClientPort> client_port;
+    std::tie(server_port, client_port) =
+        Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName());
+
+    server_port->SetHleHandler(std::shared_ptr<Interface>(interface_));
     g_kernel_named_ports.emplace(interface_->GetPortName(), std::move(client_port));
     g_kernel_named_ports.emplace(interface_->GetPortName(), std::move(client_port));
 }
 }
 
 
 void AddService(Interface* interface_) {
 void AddService(Interface* interface_) {
-    auto ports =
-        Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(),
-                                           std::shared_ptr<Interface>(interface_));
-    auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports);
+    Kernel::SharedPtr<Kernel::ServerPort> server_port;
+    Kernel::SharedPtr<Kernel::ClientPort> client_port;
+    std::tie(server_port, client_port) =
+        Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName());
+
+    server_port->SetHleHandler(std::shared_ptr<Interface>(interface_));
     g_srv_services.emplace(interface_->GetPortName(), std::move(client_port));
     g_srv_services.emplace(interface_->GetPortName(), std::move(client_port));
 }
 }