mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #2406 from Subv/session_disconnect
Kernel: Properly update port counters on session disconnection.
This commit is contained in:
		@@ -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();
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
}
 | 
			
		||||
        // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set
 | 
			
		||||
        // their WaitSynchronization result to 0xC920181A.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
ResultVal<SharedPtr<ClientSession>> ClientSession::Create(ServerSession* server_session,
 | 
			
		||||
                                                          std::string name) {
 | 
			
		||||
    SharedPtr<ClientSession> client_session(new ClientSession);
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								src/core/hle/kernel/session.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/core/hle/kernel/session.h
									
									
									
									
									
										Normal file
									
								
							@@ -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).
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user