diff options
| author | Yuri Kunde Schlesner <yuriks@yuriks.net> | 2017-05-21 17:18:16 -0700 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-21 17:18:16 -0700 | 
| commit | cc566dadd8cd310658785b87b1692880ce51eeda (patch) | |
| tree | 07136b798781adb9d864115f338eb62d09147949 /src/core | |
| parent | 188d63fdb62fbbcfa287e470cefa6c27efa2977d (diff) | |
| parent | 37347bfa380464a1ee1236d2a35f1ec1b697e4b6 (diff) | |
Merge pull request #2406 from Subv/session_disconnect
Kernel: Properly update port counters on session disconnection.
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, | 
