diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/client_port.cpp | 13 | ||||
-rw-r--r-- | src/core/hle/kernel/client_session.cpp | 27 | ||||
-rw-r--r-- | src/core/hle/kernel/client_session.h | 23 | ||||
-rw-r--r-- | src/core/hle/kernel/server_session.cpp | 31 | ||||
-rw-r--r-- | src/core/hle/kernel/server_session.h | 12 | ||||
-rw-r--r-- | src/core/hle/kernel/session.h | 27 | ||||
-rw-r--r-- | src/core/hle/result.h | 1 |
8 files changed, 84 insertions, 51 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b894564b6..c733e5d21 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -239,6 +239,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<SharedPtr<ClientSession>> 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<SharedPtr<ClientSession>>(sessions); auto server_session = std::get<SharedPtr<ServerSession>>(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..e297b7464 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -14,27 +14,24 @@ 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. -} - -ResultVal<SharedPtr<ClientSession>> ClientSession::Create(ServerSession* server_session, - std::string name) { - SharedPtr<ClientSession> client_session(new ClientSession); + // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set + // their WaitSynchronization result to 0xC920181A. + } - client_session->name = std::move(name); - client_session->server_session = server_session; - client_session->session_status = SessionStatus::Open; - return MakeResult<SharedPtr<ClientSession>>(std::move(client_session)); + parent->client = nullptr; } 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..9f3adb72b 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -14,12 +14,7 @@ namespace Kernel { class ServerSession; - -enum class SessionStatus { - Open = 1, - ClosedByClient = 2, - ClosedBYServer = 3, -}; +class Session; class ClientSession final : public Object { public: @@ -44,22 +39,14 @@ public: */ ResultCode SendSyncRequest(); - std::string name; ///< Name of client port (optional) - ServerSession* server_session; ///< The server session associated with this client session. - SessionStatus session_status; ///< The session's current status. + std::string name; ///< Name of client port (optional) + + /// The parent session, which links to the server endpoint. + std::shared_ptr<Session> parent; private: ClientSession(); ~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(ServerSession* server_session, - 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..500b909ab 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<SharedPtr<ServerSession>> ServerSession::Create( @@ -25,6 +32,7 @@ ResultVal<SharedPtr<ServerSession>> 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<SharedPtr<ServerSession>>(std::move(server_session)); } @@ -61,13 +69,22 @@ ResultCode ServerSession::HandleSyncRequest() { } ServerSession::SessionPair ServerSession::CreateSessionPair( - const std::string& name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) { + const std::string& name, std::shared_ptr<Service::SessionRequestHandler> hle_handler, + SharedPtr<ClientPort> 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(); + + SharedPtr<ClientSession> client_session(new ClientSession); + client_session->name = name + "_Client"; + + std::shared_ptr<Session> 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<Service::SessionRequestHandler> hle_handler = nullptr); + std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr, + SharedPtr<ClientPort> 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<Session> parent; ///< The parent session, which links to the client endpoint. std::shared_ptr<Service::SessionRequestHandler> 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<ClientPort> 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, |