mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									6a72bd62b5
								
							
						
					
					
						commit
						ddfabf3133
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -19,23 +19,20 @@ 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);
 | 
			
		||||
 | 
			
		||||
    else
 | 
			
		||||
        server_port->pending_sessions.push_back(std::move(server_session));
 | 
			
		||||
 | 
			
		||||
    // Wake the threads waiting on the ServerPort
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
ResultVal<SharedPtr<ClientSession>> ClientSession::Create(ServerSession* server_session,
 | 
			
		||||
                                                          std::string name) {
 | 
			
		||||
    parent->client = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
class ServerSession;
 | 
			
		||||
class Session;
 | 
			
		||||
 | 
			
		||||
enum class SessionStatus {
 | 
			
		||||
    Open = 1,
 | 
			
		||||
@ -45,7 +46,9 @@ public:
 | 
			
		||||
    ResultCode SendSyncRequest();
 | 
			
		||||
 | 
			
		||||
    std::string name; ///< Name of client port (optional)
 | 
			
		||||
    ServerSession* server_session; ///< The server session associated with this client session.
 | 
			
		||||
 | 
			
		||||
    /// 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
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
@ -65,6 +70,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    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).
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user