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

KServerPorts now have an HLE handler "template", which is inherited by all ServerSessions created from it.

Subv 9 лет назад
Родитель
Сommit
dd8887c8cf

+ 9 - 1
src/core/hle/kernel/client_port.cpp

@@ -13,10 +13,18 @@ namespace Kernel {
 ClientPort::ClientPort() {}
 ClientPort::ClientPort() {}
 ClientPort::~ClientPort() {}
 ClientPort::~ClientPort() {}
 
 
-void ClientPort::AddWaitingSession(SharedPtr<ServerSession> server_session) {
+SharedPtr<ClientSession> ClientPort::Connect() {
+    // 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);
+    auto client_session = std::get<SharedPtr<ClientSession>>(sessions);
+    auto server_session = std::get<SharedPtr<ServerSession>>(sessions);
+
     server_port->pending_sessions.push_back(server_session);
     server_port->pending_sessions.push_back(server_session);
+
     // Wake the threads waiting on the ServerPort
     // Wake the threads waiting on the ServerPort
     server_port->WakeupAllWaitingThreads();
     server_port->WakeupAllWaitingThreads();
+
+    return std::move(client_session);
 }
 }
 
 
 } // namespace
 } // namespace

+ 6 - 4
src/core/hle/kernel/client_port.h

@@ -11,7 +11,7 @@
 namespace Kernel {
 namespace Kernel {
 
 
 class ServerPort;
 class ServerPort;
-class ServerSession;
+class ClientSession;
 
 
 class ClientPort final : public Object {
 class ClientPort final : public Object {
 public:
 public:
@@ -29,15 +29,17 @@ public:
     }
     }
 
 
     /**
     /**
-     * Adds the specified server session to the queue of pending sessions of the associated ServerPort
-     * @param server_session Server session to add to the queue
+     * Creates a new Session pair, adds the created ServerSession to the associated ServerPort's list of pending sessions,
+     * and signals the ServerPort, causing any threads waiting on it to awake.
+     * @returns ClientSession The client endpoint of the created Session pair.
      */
      */
-    void AddWaitingSession(SharedPtr<ServerSession> server_session);
+    SharedPtr<ClientSession> Connect();
 
 
     SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
     SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
     u32 max_sessions;    ///< Maximum number of simultaneous sessions the port can have
     u32 max_sessions;    ///< Maximum number of simultaneous sessions the port can have
     u32 active_sessions; ///< Number of currently open sessions to this port
     u32 active_sessions; ///< Number of currently open sessions to this port
     std::string name;    ///< Name of client port (optional)
     std::string name;    ///< Name of client port (optional)
+
 private:
 private:
     ClientPort();
     ClientPort();
     ~ClientPort() override;
     ~ClientPort() override;

+ 1 - 1
src/core/hle/kernel/client_session.cpp

@@ -20,7 +20,7 @@ ResultVal<SharedPtr<ClientSession>> ClientSession::Create(SharedPtr<ServerSessio
     return MakeResult<SharedPtr<ClientSession>>(std::move(client_session));
     return MakeResult<SharedPtr<ClientSession>>(std::move(client_session));
 }
 }
 
 
-ResultCode ClientSession::HandleSyncRequest() {
+ResultCode ClientSession::SendSyncRequest() {
     // Signal the server session that new data is available
     // Signal the server session that new data is available
     return server_session->HandleSyncRequest();
     return server_session->HandleSyncRequest();
 }
 }

+ 12 - 9
src/core/hle/kernel/client_session.h

@@ -17,17 +17,12 @@ class ServerSession;
 
 
 class ClientSession final : public Object {
 class ClientSession final : public Object {
 public:
 public:
-    /**
-     * Creates a client session.
-     * @param server_session The server session associated with this client session
-     * @param name Optional name of client session
-     * @return The created client session
-     */
-    static ResultVal<SharedPtr<ClientSession>> Create(SharedPtr<ServerSession> server_session, std::string name = "Unknown");
+    friend class ServerSession;
 
 
     std::string GetTypeName() const override {
     std::string GetTypeName() const override {
         return "ClientSession";
         return "ClientSession";
     }
     }
+
     std::string GetName() const override {
     std::string GetName() const override {
         return name;
         return name;
     }
     }
@@ -38,10 +33,10 @@ public:
     }
     }
 
 
     /**
     /**
-     * Handle a SyncRequest from the emulated application.
+     * Sends an SyncRequest from the current emulated thread.
      * @return ResultCode of the operation.
      * @return ResultCode of the operation.
      */
      */
-    ResultCode HandleSyncRequest();
+    ResultCode SendSyncRequest();
 
 
     std::string name;                           ///< Name of client port (optional)
     std::string name;                           ///< Name of client port (optional)
     SharedPtr<ServerSession> server_session;    ///< The server session associated with this client session.
     SharedPtr<ServerSession> server_session;    ///< The server session associated with this client session.
@@ -49,6 +44,14 @@ public:
 private:
 private:
     ClientSession();
     ClientSession();
     ~ClientSession() override;
     ~ClientSession() override;
+
+    /**
+     * Creates a client session.
+     * @param server_session The server session associated with this client session
+     * @param name Optional name of client session
+     * @return The created client session
+     */
+    static ResultVal<SharedPtr<ClientSession>> Create(SharedPtr<ServerSession> server_session, std::string name = "Unknown");
 };
 };
 
 
 } // namespace
 } // namespace

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

@@ -24,12 +24,13 @@ void ServerPort::Acquire() {
 }
 }
 
 
 std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
 std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
-    u32 max_sessions, std::string name) {
+    u32 max_sessions, std::string name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) {
 
 
     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 = 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;

+ 12 - 1
src/core/hle/kernel/server_port.h

@@ -9,6 +9,10 @@
 #include "common/common_types.h"
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/kernel.h"
 
 
+namespace Service {
+class SessionRequestHandler;
+}
+
 namespace Kernel {
 namespace Kernel {
 
 
 class ClientPort;
 class ClientPort;
@@ -19,10 +23,13 @@ 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");
+        u32 max_sessions, std::string name = "UnknownPort",
+        std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr);
 
 
     std::string GetTypeName() const override {
     std::string GetTypeName() const override {
         return "ServerPort";
         return "ServerPort";
@@ -41,6 +48,10 @@ public:
     std::vector<SharedPtr<WaitObject>>
     std::vector<SharedPtr<WaitObject>>
         pending_sessions; ///< ServerSessions waiting to be accepted by the port
         pending_sessions; ///< ServerSessions waiting to be accepted by the port
 
 
+    /// This session's HLE request handler template (optional)
+    /// ServerSessions created from this port inherit a reference to this handler.
+    std::shared_ptr<Service::SessionRequestHandler> hle_handler;
+
     bool ShouldWait() override;
     bool ShouldWait() override;
     void Acquire() override;
     void Acquire() override;
 
 

+ 3 - 3
src/core/hle/kernel/server_session.cpp

@@ -47,10 +47,10 @@ ResultCode ServerSession::HandleSyncRequest() {
 }
 }
 
 
 std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> ServerSession::CreateSessionPair(const std::string& name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) {
 std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> ServerSession::CreateSessionPair(const std::string& name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) {
-    auto server_session = ServerSession::Create(name + "Server", hle_handler).MoveFrom();
-    auto client_session = ClientSession::Create(server_session, name + "Client").MoveFrom();
+    auto server_session = ServerSession::Create(name + "_Server", hle_handler).MoveFrom();
+    auto client_session = ClientSession::Create(server_session, name + "_Client").MoveFrom();
 
 
-    return std::make_tuple(server_session, client_session);
+    return std::make_tuple(std::move(server_session), std::move(client_session));
 }
 }
 
 
 }
 }

+ 15 - 15
src/core/hle/kernel/server_session.h

@@ -29,20 +29,8 @@ class ClientSession;
  * the request, the response is marshalled back to the caller's TLS buffer and control is
  * the request, the response is marshalled back to the caller's TLS buffer and control is
  * transferred back to it.
  * transferred back to it.
  */
  */
-class ServerSession : public WaitObject {
+class ServerSession final : public WaitObject {
 public:
 public:
-    ServerSession();
-    ~ServerSession() override;
-
-    /**
-     * 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.
-     * @param name Optional name of the server session.
-     * @param hle_handler Optional HLE handler for this server session.
-     * @return The created server session
-     */
-    static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown", std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr);
-
     std::string GetTypeName() const override {
     std::string GetTypeName() const override {
         return "ServerSession";
         return "ServerSession";
     }
     }
@@ -61,10 +49,9 @@ public:
 
 
     /**
     /**
      * Handle a sync request from the emulated application.
      * Handle a sync request from the emulated application.
-     * Only HLE services should override this function.
      * @returns ResultCode from the operation.
      * @returns ResultCode from the operation.
      */
      */
-    virtual ResultCode HandleSyncRequest();
+    ResultCode HandleSyncRequest();
 
 
     bool ShouldWait() override;
     bool ShouldWait() override;
 
 
@@ -73,5 +60,18 @@ public:
     std::string name; ///< The name of this session (optional)
     std::string name; ///< The name of this session (optional)
     bool signaled;    ///< Whether there's new data available to this ServerSession
     bool signaled;    ///< Whether there's new data available to this ServerSession
     std::shared_ptr<Service::SessionRequestHandler> hle_handler; ///< This session's HLE request handler (optional)
     std::shared_ptr<Service::SessionRequestHandler> hle_handler; ///< This session's HLE request handler (optional)
+
+private:
+    ServerSession();
+    ~ServerSession() override;
+
+    /**
+     * 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.
+     * @param name Optional name of the server session.
+     * @param hle_handler Optional HLE handler for this server session.
+     * @return The created server session
+     */
+    static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown", std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr);
 };
 };
 }
 }

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

@@ -44,8 +44,8 @@
 
 
 namespace Service {
 namespace Service {
 
 
-std::unordered_map<std::string, std::tuple<Kernel::SharedPtr<Kernel::ClientPort>, std::shared_ptr<Interface>>> g_kernel_named_ports;
-std::unordered_map<std::string, std::tuple<Kernel::SharedPtr<Kernel::ClientPort>, std::shared_ptr<Interface>>> g_srv_services;
+std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_kernel_named_ports;
+std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_srv_services;
 
 
 /**
 /**
  * Creates a function string for logging, complete with the name (or header code, depending
  * Creates a function string for logging, complete with the name (or header code, depending
@@ -102,15 +102,17 @@ 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());
+    auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(),
+                                                    std::shared_ptr<Interface>(interface_));
     auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports);
     auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports);
-    g_kernel_named_ports.emplace(interface_->GetPortName(), std::make_tuple(client_port, std::shared_ptr<Interface>(interface_)));
+    g_kernel_named_ports.emplace(interface_->GetPortName(), client_port);
 }
 }
 
 
 void AddService(Interface* interface_) {
 void AddService(Interface* interface_) {
-    auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName());
+    auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(),
+                                                    std::shared_ptr<Interface>(interface_));
     auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports);
     auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports);
-    g_srv_services.emplace(interface_->GetPortName(), std::make_tuple(client_port, std::shared_ptr<Interface>(interface_)));
+    g_srv_services.emplace(interface_->GetPortName(), client_port);
 }
 }
 
 
 /// Initialize ServiceManager
 /// Initialize ServiceManager

+ 10 - 4
src/core/hle/service/service.h

@@ -176,7 +176,11 @@ namespace Service {
 static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
 static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
 static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port
 static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port
 
 
-/// TODO(Subv): Write documentation for this class
+/**
+ * Interface implemented by HLE Session handlers.
+ * 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.
+ */
 class SessionRequestHandler {
 class SessionRequestHandler {
 public:
 public:
     /**
     /**
@@ -190,7 +194,9 @@ public:
     virtual ResultCode HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) = 0;
     virtual ResultCode HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) = 0;
 };
 };
 
 
-/// Interface to a CTROS service
+/**
+ * Framework for implementing HLE service handlers which dispatch incoming SyncRequests based on a table mapping header ids to handler functions.
+ */
 class Interface : public SessionRequestHandler {
 class Interface : public SessionRequestHandler {
 public:
 public:
     std::string GetName() const {
     std::string GetName() const {
@@ -257,9 +263,9 @@ void Init();
 void Shutdown();
 void Shutdown();
 
 
 /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
 /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
-extern std::unordered_map<std::string, std::tuple<Kernel::SharedPtr<Kernel::ClientPort>, std::shared_ptr<Interface>>> g_kernel_named_ports;
+extern std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_kernel_named_ports;
 /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle.
 /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle.
-extern std::unordered_map<std::string, std::tuple<Kernel::SharedPtr<Kernel::ClientPort>, std::shared_ptr<Interface>>> g_srv_services;
+extern std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_srv_services;
 
 
 /// Adds a service to the services table
 /// Adds a service to the services table
 void AddService(Interface* interface_);
 void AddService(Interface* interface_);

+ 3 - 11
src/core/hle/service/srv.cpp

@@ -85,21 +85,13 @@ static void GetServiceHandle(Service::Interface* self) {
     auto it = Service::g_srv_services.find(port_name);
     auto it = Service::g_srv_services.find(port_name);
 
 
     if (it != Service::g_srv_services.end()) {
     if (it != Service::g_srv_services.end()) {
-        auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(it->second);
-        // The hle_handler will be nullptr if this port was registered by the emulated
-        // application by means of srv:RegisterService.
-        auto hle_handler = std::get<std::shared_ptr<Service::Interface>>(it->second);
-
-        // Create a new session pair
-        auto sessions = Kernel::ServerSession::CreateSessionPair(port_name, hle_handler);
-        auto client_session = std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions);
-        auto server_session = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions);
+        auto client_port = it->second;
 
 
         // Note: Threads do not wait for the server endpoint to call
         // Note: Threads do not wait for the server endpoint to call
         // AcceptSession before returning from this call.
         // AcceptSession before returning from this call.
 
 
-        // Add the server session to the port's queue
-        client_port->AddWaitingSession(server_session);
+        // Connect to the port and retrieve the client endpoint of the connection Session.
+        auto client_session = client_port->Connect();
 
 
         // Return the client session
         // Return the client session
         cmd_buff[3] = Kernel::g_handle_table.Create(client_session).MoveFrom();
         cmd_buff[3] = Kernel::g_handle_table.Create(client_session).MoveFrom();

+ 5 - 13
src/core/hle/svc.cpp

@@ -224,18 +224,10 @@ static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) {
         return ERR_NOT_FOUND;
         return ERR_NOT_FOUND;
     }
     }
 
 
-    auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(it->second);
-    // The hle_handler will be nullptr if this port was registered by the emulated
-    // application by means of svcCreatePort with a defined name.
-    auto hle_handler = std::get<std::shared_ptr<Service::Interface>>(it->second);
+    auto client_port = it->second;
 
 
-    // Create a new session pair
-    auto sessions = Kernel::ServerSession::CreateSessionPair(port_name, hle_handler);
-    auto client_session = std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions);
-    auto server_session = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions);
-
-    // Add the server session to the port's queue
-    client_port->AddWaitingSession(server_session);
+    // Connect to the port and retrieve the client endpoint of the connection Session.
+    auto client_session = client_port->Connect();
 
 
     // Note: Threads do not wait for the server endpoint to call
     // Note: Threads do not wait for the server endpoint to call
     // AcceptSession before returning from this call.
     // AcceptSession before returning from this call.
@@ -254,8 +246,8 @@ static ResultCode SendSyncRequest(Handle handle) {
 
 
     LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
     LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
 
 
-    // TODO(Subv): Wait the current thread and reschedule if this request is not going to be handled by HLE code.
-    return session->HandleSyncRequest();
+    // TODO(Subv): svcSendSyncRequest should put the caller thread to sleep while the server responds and cause a reschedule.
+    return session->SendSyncRequest();
 }
 }
 
 
 /// Close a handle
 /// Close a handle