diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/client_port.cpp | 13 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_session.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_session.h | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.cpp | 29 | ||||
| -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 | 
7 files changed, 85 insertions, 32 deletions
| 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..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<SharedPtr<ClientSession>> ClientSession::Create(ServerSession* server_session, -                                                          std::string name) { +ResultVal<SharedPtr<ClientSession>> ClientSession::Create(std::string name) {      SharedPtr<ClientSession> 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<SharedPtr<ClientSession>>(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<Session> 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<SharedPtr<ClientSession>> Create(ServerSession* server_session, -                                                      std::string name = "Unknown"); +    static ResultVal<SharedPtr<ClientSession>> 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<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,20 @@ 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(); +    auto client_session = ClientSession::Create(name + "_Client").MoveFrom(); + +    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, | 
