From ddfabf31330c0c8e0558a714b6d7e1f1948b73ed Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 4 Jan 2017 23:23:17 -0500 Subject: Kernel: Use a Session object to keep track of the status of a Client/Server session pair. Reduce the associated port's connection count when a ServerSession is destroyed. --- src/core/CMakeLists.txt | 1 + src/core/hle/kernel/client_port.cpp | 13 +++++-------- src/core/hle/kernel/client_session.cpp | 24 +++++++++++++++--------- src/core/hle/kernel/client_session.h | 11 ++++++----- src/core/hle/kernel/server_session.cpp | 29 ++++++++++++++++++++++------- src/core/hle/kernel/server_session.h | 12 +++++++++--- src/core/hle/kernel/session.h | 27 +++++++++++++++++++++++++++ src/core/hle/result.h | 1 + 8 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 src/core/hle/kernel/session.h (limited to 'src') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 61a0b1cc3..b161c05ba 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -241,6 +241,7 @@ set(HEADERS hle/kernel/semaphore.h hle/kernel/server_port.h hle/kernel/server_session.h + hle/kernel/session.h hle/kernel/shared_memory.h hle/kernel/thread.h hle/kernel/timer.h diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index 22645f4ec..ddcf4c916 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -19,24 +19,21 @@ ResultVal> ClientPort::Connect() { // AcceptSession before returning from this call. if (active_sessions >= max_sessions) { - // TODO(Subv): Return an error code in this situation after session disconnection is - // implemented. - /*return ResultCode(ErrorDescription::MaxConnectionsReached, - ErrorModule::OS, ErrorSummary::WouldBlock, - ErrorLevel::Temporary);*/ + return ResultCode(ErrorDescription::MaxConnectionsReached, ErrorModule::OS, + ErrorSummary::WouldBlock, ErrorLevel::Temporary); } active_sessions++; // 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); + ServerSession::CreateSessionPair(server_port->GetName(), server_port->hle_handler, this); auto client_session = std::get>(sessions); auto server_session = std::get>(sessions); if (server_port->hle_handler) server_port->hle_handler->ClientConnected(server_session); - - server_port->pending_sessions.push_back(std::move(server_session)); + else + server_port->pending_sessions.push_back(std::move(server_session)); // Wake the threads waiting on the ServerPort server_port->WakeupAllWaitingThreads(); diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index 0331386ec..c2f48176e 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -14,27 +14,33 @@ ClientSession::~ClientSession() { // This destructor will be called automatically when the last ClientSession handle is closed by // the emulated application. - if (server_session->hle_handler) - server_session->hle_handler->ClientDisconnected(server_session); + if (parent->server) { + if (parent->server->hle_handler) + parent->server->hle_handler->ClientDisconnected(parent->server); - // TODO(Subv): If the session is still open, set the connection status to 2 (Closed by client), - // wake up all the ServerSession's waiting threads and set the WaitSynchronization result to - // 0xC920181A. + // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set + // their WaitSynchronization result to 0xC920181A. + } + + parent->client = nullptr; } -ResultVal> ClientSession::Create(ServerSession* server_session, - std::string name) { +ResultVal> ClientSession::Create(std::string name) { SharedPtr client_session(new ClientSession); client_session->name = std::move(name); - client_session->server_session = server_session; + client_session->parent = nullptr; client_session->session_status = SessionStatus::Open; return MakeResult>(std::move(client_session)); } ResultCode ClientSession::SendSyncRequest() { // Signal the server session that new data is available - return server_session->HandleSyncRequest(); + if (parent->server) + return parent->server->HandleSyncRequest(); + + return ResultCode(ErrorDescription::SessionClosedByRemote, ErrorModule::OS, + ErrorSummary::Canceled, ErrorLevel::Status); } } // namespace diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index ed468dec6..adb2d0b5f 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -14,6 +14,7 @@ namespace Kernel { class ServerSession; +class Session; enum class SessionStatus { Open = 1, @@ -44,8 +45,10 @@ public: */ ResultCode SendSyncRequest(); - std::string name; ///< Name of client port (optional) - ServerSession* server_session; ///< The server session associated with this client session. + std::string name; ///< Name of client port (optional) + + /// The parent session, which links to the server endpoint. + std::shared_ptr parent; SessionStatus session_status; ///< The session's current status. private: @@ -54,12 +57,10 @@ private: /** * 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> Create(ServerSession* server_session, - std::string name = "Unknown"); + static ResultVal> Create(std::string name = "Unknown"); }; } // namespace diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 9447ff236..a93e55c76 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -14,8 +14,15 @@ ServerSession::ServerSession() = default; ServerSession::~ServerSession() { // This destructor will be called automatically when the last ServerSession handle is closed by // the emulated application. - // TODO(Subv): Reduce the ClientPort's connection count, - // if the session is still open, set the connection status to 3 (Closed by server), + + // Decrease the port's connection count. + if (parent->port) + parent->port->active_sessions--; + + // TODO(Subv): Wake up all the ClientSession's waiting threads and set + // the SendSyncRequest result to 0xC920181A. + + parent->server = nullptr; } ResultVal> ServerSession::Create( @@ -25,6 +32,7 @@ ResultVal> ServerSession::Create( server_session->name = std::move(name); server_session->signaled = false; server_session->hle_handler = std::move(hle_handler); + server_session->parent = nullptr; return MakeResult>(std::move(server_session)); } @@ -61,13 +69,20 @@ ResultCode ServerSession::HandleSyncRequest() { } ServerSession::SessionPair ServerSession::CreateSessionPair( - const std::string& name, std::shared_ptr hle_handler) { + const std::string& name, std::shared_ptr hle_handler, + SharedPtr port) { + auto server_session = ServerSession::Create(name + "_Server", std::move(hle_handler)).MoveFrom(); - // We keep a non-owning pointer to the ServerSession in the ClientSession because we don't want - // to prevent the ServerSession's destructor from being called when the emulated - // application closes the last ServerSession handle. - auto client_session = ClientSession::Create(server_session.get(), name + "_Client").MoveFrom(); + auto client_session = ClientSession::Create(name + "_Client").MoveFrom(); + + std::shared_ptr parent(new Session); + parent->client = client_session.get(); + parent->server = server_session.get(); + parent->port = port; + + client_session->parent = parent; + server_session->parent = parent; return std::make_tuple(std::move(server_session), std::move(client_session)); } diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 761fc4781..c907d487c 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -9,6 +9,7 @@ #include "common/assert.h" #include "common/common_types.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/session.h" #include "core/hle/kernel/thread.h" #include "core/hle/result.h" #include "core/hle/service/service.h" @@ -17,6 +18,8 @@ namespace Kernel { class ClientSession; +class ClientPort; +class ServerSession; /** * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS @@ -47,11 +50,13 @@ public: * Creates a pair of ServerSession and an associated ClientSession. * @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. * @return The created session tuple */ static SessionPair CreateSessionPair( const std::string& name = "Unknown", - std::shared_ptr hle_handler = nullptr); + std::shared_ptr hle_handler = nullptr, + SharedPtr client_port = nullptr); /** * Handle a sync request from the emulated application. @@ -63,8 +68,9 @@ public: void Acquire(Thread* thread) override; - std::string name; ///< The name of this session (optional) - bool signaled; ///< Whether there's new data available to this ServerSession + std::string name; ///< The name of this session (optional) + bool signaled; ///< Whether there's new data available to this ServerSession + std::shared_ptr parent; ///< The parent session, which links to the client endpoint. std::shared_ptr hle_handler; ///< This session's HLE request handler (optional) diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h new file mode 100644 index 000000000..a45e78022 --- /dev/null +++ b/src/core/hle/kernel/session.h @@ -0,0 +1,27 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +class ClientSession; +class ClientPort; +class ServerSession; + +/** + * Parent structure to link the client and server endpoints of a session with their associated + * client port. The client port need not exist, as is the case for portless sessions like the + * FS File and Directory sessions. When one of the endpoints of a session is destroyed, its + * corresponding field in this structure will be set to nullptr. + */ +class Session final { +public: + ClientSession* client = nullptr; ///< The client endpoint of the session. + ServerSession* server = nullptr; ///< The server endpoint of the session. + SharedPtr port; ///< The port that this session is associated with (optional). +}; +} diff --git a/src/core/hle/result.h b/src/core/hle/result.h index cfefbbc64..13b948871 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -16,6 +16,7 @@ /// Detailed description of the error. This listing is likely incomplete. enum class ErrorDescription : u32 { Success = 0, + SessionClosedByRemote = 26, WrongPermission = 46, OS_InvalidBufferDescriptor = 48, MaxConnectionsReached = 52, -- cgit v1.2.3 From ce5bc477ca0cd59df4922c1c6cd245db365dc7bc Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 4 Jan 2017 23:24:06 -0500 Subject: Kernel: Remove a now unused enum and variable regarding a session's status. --- src/core/hle/kernel/client_session.cpp | 1 - src/core/hle/kernel/client_session.h | 7 ------- 2 files changed, 8 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index c2f48176e..6737b204b 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -30,7 +30,6 @@ ResultVal> ClientSession::Create(std::string name) { client_session->name = std::move(name); client_session->parent = nullptr; - client_session->session_status = SessionStatus::Open; return MakeResult>(std::move(client_session)); } diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index adb2d0b5f..5ec4ee901 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -16,12 +16,6 @@ namespace Kernel { class ServerSession; class Session; -enum class SessionStatus { - Open = 1, - ClosedByClient = 2, - ClosedBYServer = 3, -}; - class ClientSession final : public Object { public: friend class ServerSession; @@ -49,7 +43,6 @@ public: /// The parent session, which links to the server endpoint. std::shared_ptr parent; - SessionStatus session_status; ///< The session's current status. private: ClientSession(); -- cgit v1.2.3 From 37347bfa380464a1ee1236d2a35f1ec1b697e4b6 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 21 May 2017 18:52:42 -0500 Subject: Kernel/Sessions: Remove the ClientSession::Create function. It is not meant to be used by anything other than CreateSessionPair. --- src/core/hle/kernel/client_session.cpp | 8 -------- src/core/hle/kernel/client_session.h | 7 ------- src/core/hle/kernel/server_session.cpp | 4 +++- 3 files changed, 3 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index 6737b204b..e297b7464 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -25,14 +25,6 @@ ClientSession::~ClientSession() { parent->client = nullptr; } -ResultVal> ClientSession::Create(std::string name) { - SharedPtr client_session(new ClientSession); - - client_session->name = std::move(name); - client_session->parent = nullptr; - return MakeResult>(std::move(client_session)); -} - ResultCode ClientSession::SendSyncRequest() { // Signal the server session that new data is available if (parent->server) diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index 5ec4ee901..9f3adb72b 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -47,13 +47,6 @@ public: private: ClientSession(); ~ClientSession() override; - - /** - * Creates a client session. - * @param name Optional name of client session - * @return The created client session - */ - static ResultVal> Create(std::string name = "Unknown"); }; } // namespace diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index a93e55c76..500b909ab 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -74,7 +74,9 @@ ServerSession::SessionPair ServerSession::CreateSessionPair( auto server_session = ServerSession::Create(name + "_Server", std::move(hle_handler)).MoveFrom(); - auto client_session = ClientSession::Create(name + "_Client").MoveFrom(); + + SharedPtr client_session(new ClientSession); + client_session->name = name + "_Client"; std::shared_ptr parent(new Session); parent->client = client_session.get(); -- cgit v1.2.3