mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Kernel: Add a dedicated SetHleHandler method to ServerPort/ServerSession
This allows attaching a HLE handle to a ServerPort at any point after it is created, allowing port/session creation to be generic between HLE and regular services.
This commit is contained in:
		
							parent
							
								
									7e5dd46cf4
								
							
						
					
					
						commit
						6354d08359
					
				
					 11 changed files with 73 additions and 62 deletions
				
			
		|  | @ -26,20 +26,17 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() { | |||
|     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, this); | ||||
|     auto client_session = std::get<SharedPtr<ClientSession>>(sessions); | ||||
|     auto server_session = std::get<SharedPtr<ServerSession>>(sessions); | ||||
|     auto sessions = ServerSession::CreateSessionPair(server_port->GetName(), this); | ||||
| 
 | ||||
|     if (server_port->hle_handler) | ||||
|         server_port->hle_handler->ClientConnected(server_session); | ||||
|         server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); | ||||
|     else | ||||
|         server_port->pending_sessions.push_back(std::move(server_session)); | ||||
|         server_port->pending_sessions.push_back(std::get<SharedPtr<ServerSession>>(sessions)); | ||||
| 
 | ||||
|     // Wake the threads waiting on the ServerPort
 | ||||
|     server_port->WakeupAllWaitingThreads(); | ||||
| 
 | ||||
|     return MakeResult<SharedPtr<ClientSession>>(std::move(client_session)); | ||||
|     return MakeResult(std::get<SharedPtr<ClientSession>>(sessions)); | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
|  | @ -12,10 +12,12 @@ | |||
| namespace Kernel { | ||||
| 
 | ||||
| void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) { | ||||
|     server_session->SetHleHandler(shared_from_this()); | ||||
|     connected_sessions.push_back(server_session); | ||||
| } | ||||
| 
 | ||||
| void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_session) { | ||||
|     server_session->SetHleHandler(nullptr); | ||||
|     boost::range::remove_erase(connected_sessions, server_session); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| 
 | ||||
|  | @ -16,7 +17,7 @@ class ServerSession; | |||
|  * This can be provided to a ServerSession in order to hook into several relevant events | ||||
|  * (such as a new connection or a SyncRequest) so they can be implemented in the emulator. | ||||
|  */ | ||||
| class SessionRequestHandler { | ||||
| class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> { | ||||
| public: | ||||
|     /**
 | ||||
|      * Handles a sync request from the emulated application. | ||||
|  |  | |||
|  | @ -24,13 +24,12 @@ void ServerPort::Acquire(Thread* thread) { | |||
| } | ||||
| 
 | ||||
| std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair( | ||||
|     u32 max_sessions, std::string name, std::shared_ptr<SessionRequestHandler> hle_handler) { | ||||
|     u32 max_sessions, std::string name) { | ||||
| 
 | ||||
|     SharedPtr<ServerPort> server_port(new ServerPort); | ||||
|     SharedPtr<ClientPort> client_port(new ClientPort); | ||||
| 
 | ||||
|     server_port->name = name + "_Server"; | ||||
|     server_port->hle_handler = std::move(hle_handler); | ||||
|     client_port->name = name + "_Client"; | ||||
|     client_port->server_port = server_port; | ||||
|     client_port->max_sessions = max_sessions; | ||||
|  |  | |||
|  | @ -20,15 +20,13 @@ class ServerPort final : public WaitObject { | |||
| public: | ||||
|     /**
 | ||||
|      * Creates a pair of ServerPort and an associated ClientPort. | ||||
|      * | ||||
|      * @param max_sessions Maximum number of sessions to the port | ||||
|      * @param name Optional name of the ports | ||||
|      * @param hle_handler Optional HLE handler template for the port, | ||||
|      * ServerSessions crated from this port will inherit a reference to this handler. | ||||
|      * @return The created port tuple | ||||
|      */ | ||||
|     static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair( | ||||
|         u32 max_sessions, std::string name = "UnknownPort", | ||||
|         std::shared_ptr<SessionRequestHandler> hle_handler = nullptr); | ||||
|         u32 max_sessions, std::string name = "UnknownPort"); | ||||
| 
 | ||||
|     std::string GetTypeName() const override { | ||||
|         return "ServerPort"; | ||||
|  | @ -42,6 +40,14 @@ public: | |||
|         return HANDLE_TYPE; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port | ||||
|      * will inherit a reference to this handler. | ||||
|      */ | ||||
|     void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) { | ||||
|         hle_handler = std::move(hle_handler_); | ||||
|     } | ||||
| 
 | ||||
|     std::string name; ///< Name of port (optional)
 | ||||
| 
 | ||||
|     std::vector<SharedPtr<WaitObject>> | ||||
|  |  | |||
|  | @ -28,16 +28,14 @@ ServerSession::~ServerSession() { | |||
|     parent->server = nullptr; | ||||
| } | ||||
| 
 | ||||
| ResultVal<SharedPtr<ServerSession>> ServerSession::Create( | ||||
|     std::string name, std::shared_ptr<SessionRequestHandler> hle_handler) { | ||||
| ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) { | ||||
|     SharedPtr<ServerSession> server_session(new ServerSession); | ||||
| 
 | ||||
|     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)); | ||||
|     return MakeResult(std::move(server_session)); | ||||
| } | ||||
| 
 | ||||
| bool ServerSession::ShouldWait(Thread* thread) const { | ||||
|  | @ -71,13 +69,9 @@ ResultCode ServerSession::HandleSyncRequest() { | |||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| ServerSession::SessionPair ServerSession::CreateSessionPair( | ||||
|     const std::string& name, std::shared_ptr<SessionRequestHandler> hle_handler, | ||||
|     SharedPtr<ClientPort> port) { | ||||
| 
 | ||||
|     auto server_session = | ||||
|         ServerSession::Create(name + "_Server", std::move(hle_handler)).MoveFrom(); | ||||
| 
 | ||||
| ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name, | ||||
|                                                             SharedPtr<ClientPort> port) { | ||||
|     auto server_session = ServerSession::Create(name + "_Server").MoveFrom(); | ||||
|     SharedPtr<ClientSession> client_session(new ClientSession); | ||||
|     client_session->name = name + "_Client"; | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,14 +50,20 @@ 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<SessionRequestHandler> hle_handler = nullptr, | ||||
|         SharedPtr<ClientPort> client_port = nullptr); | ||||
|     static SessionPair CreateSessionPair(const std::string& name = "Unknown", | ||||
|                                          SharedPtr<ClientPort> client_port = nullptr); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sets the HLE handler for the session. This handler will be called to service IPC requests | ||||
|      * instead of the regular IPC machinery. (The regular IPC machinery is currently not | ||||
|      * implemented.) | ||||
|      */ | ||||
|     void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) { | ||||
|         hle_handler = std::move(hle_handler_); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Handle a sync request from the emulated application. | ||||
|  | @ -83,11 +89,9 @@ private: | |||
|      * Creates a server session. The server session can have an optional HLE handler, | ||||
|      * which will be invoked to handle the IPC requests that this session receives. | ||||
|      * @param name Optional name of the server session. | ||||
|      * @param hle_handler Optional HLE handler for this server session. | ||||
|      * @return The created server session | ||||
|      */ | ||||
|     static ResultVal<SharedPtr<ServerSession>> Create( | ||||
|         std::string name = "Unknown", std::shared_ptr<SessionRequestHandler> hle_handler = nullptr); | ||||
|     static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown"); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -84,6 +84,10 @@ File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& | |||
| File::~File() {} | ||||
| 
 | ||||
| void File::HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) { | ||||
|     using Kernel::ClientSession; | ||||
|     using Kernel::ServerSession; | ||||
|     using Kernel::SharedPtr; | ||||
| 
 | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | ||||
|     switch (cmd) { | ||||
|  | @ -162,10 +166,9 @@ void File::HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_ses | |||
| 
 | ||||
|     case FileCommand::OpenLinkFile: { | ||||
|         LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); | ||||
|         auto sessions = Kernel::ServerSession::CreateSessionPair(GetName(), shared_from_this()); | ||||
|         ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions)); | ||||
|         cmd_buff[3] = Kernel::g_handle_table | ||||
|                           .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions)) | ||||
|         auto sessions = ServerSession::CreateSessionPair(GetName()); | ||||
|         ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); | ||||
|         cmd_buff[3] = Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)) | ||||
|                           .ValueOr(INVALID_HANDLE); | ||||
|         break; | ||||
|     } | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1, GameCard = 2 }; | |||
| 
 | ||||
| typedef u64 ArchiveHandle; | ||||
| 
 | ||||
| class File final : public Kernel::SessionRequestHandler, public std::enable_shared_from_this<File> { | ||||
| class File final : public Kernel::SessionRequestHandler { | ||||
| public: | ||||
|     File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); | ||||
|     ~File(); | ||||
|  |  | |||
|  | @ -20,8 +20,9 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Namespace FS_User
 | ||||
| 
 | ||||
| using Kernel::SharedPtr; | ||||
| using Kernel::ClientSession; | ||||
| using Kernel::ServerSession; | ||||
| using Kernel::SharedPtr; | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace FS { | ||||
|  | @ -79,11 +80,11 @@ static void OpenFile(Service::Interface* self) { | |||
|     rb.Push(file_res.Code()); | ||||
|     if (file_res.Succeeded()) { | ||||
|         std::shared_ptr<File> file = *file_res; | ||||
|         auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); | ||||
|         file->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions)); | ||||
|         rb.PushMoveHandles(Kernel::g_handle_table | ||||
|                                .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions)) | ||||
|                                .MoveFrom()); | ||||
|         auto sessions = ServerSession::CreateSessionPair(file->GetName()); | ||||
|         file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); | ||||
| 
 | ||||
|         rb.PushMoveHandles( | ||||
|             Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom()); | ||||
|     } else { | ||||
|         rb.PushMoveHandles(0); | ||||
|         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | ||||
|  | @ -145,11 +146,11 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
|     cmd_buff[1] = file_res.Code().raw; | ||||
|     if (file_res.Succeeded()) { | ||||
|         std::shared_ptr<File> file = *file_res; | ||||
|         auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); | ||||
|         file->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions)); | ||||
|         cmd_buff[3] = Kernel::g_handle_table | ||||
|                           .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions)) | ||||
|                           .MoveFrom(); | ||||
|         auto sessions = ServerSession::CreateSessionPair(file->GetName()); | ||||
|         file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); | ||||
| 
 | ||||
|         cmd_buff[3] = | ||||
|             Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom(); | ||||
|     } else { | ||||
|         cmd_buff[3] = 0; | ||||
|         LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u", | ||||
|  | @ -412,11 +413,11 @@ static void OpenDirectory(Service::Interface* self) { | |||
|     cmd_buff[1] = dir_res.Code().raw; | ||||
|     if (dir_res.Succeeded()) { | ||||
|         std::shared_ptr<Directory> directory = *dir_res; | ||||
|         auto sessions = ServerSession::CreateSessionPair(directory->GetName(), directory); | ||||
|         directory->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions)); | ||||
|         cmd_buff[3] = Kernel::g_handle_table | ||||
|                           .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions)) | ||||
|                           .MoveFrom(); | ||||
|         auto sessions = ServerSession::CreateSessionPair(directory->GetName()); | ||||
|         directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); | ||||
| 
 | ||||
|         cmd_buff[3] = | ||||
|             Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom(); | ||||
|     } else { | ||||
|         LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", | ||||
|                   dirname_type, dirname_size, dir_path.DebugStr().c_str()); | ||||
|  |  | |||
|  | @ -105,18 +105,22 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { | |||
| // Module interface
 | ||||
| 
 | ||||
| static void AddNamedPort(Interface* interface_) { | ||||
|     auto ports = | ||||
|         Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), | ||||
|                                            std::shared_ptr<Interface>(interface_)); | ||||
|     auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports); | ||||
|     Kernel::SharedPtr<Kernel::ServerPort> server_port; | ||||
|     Kernel::SharedPtr<Kernel::ClientPort> client_port; | ||||
|     std::tie(server_port, client_port) = | ||||
|         Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName()); | ||||
| 
 | ||||
|     server_port->SetHleHandler(std::shared_ptr<Interface>(interface_)); | ||||
|     g_kernel_named_ports.emplace(interface_->GetPortName(), std::move(client_port)); | ||||
| } | ||||
| 
 | ||||
| void AddService(Interface* interface_) { | ||||
|     auto ports = | ||||
|         Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), | ||||
|                                            std::shared_ptr<Interface>(interface_)); | ||||
|     auto client_port = std::get<Kernel::SharedPtr<Kernel::ClientPort>>(ports); | ||||
|     Kernel::SharedPtr<Kernel::ServerPort> server_port; | ||||
|     Kernel::SharedPtr<Kernel::ClientPort> client_port; | ||||
|     std::tie(server_port, client_port) = | ||||
|         Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName()); | ||||
| 
 | ||||
|     server_port->SetHleHandler(std::shared_ptr<Interface>(interface_)); | ||||
|     g_srv_services.emplace(interface_->GetPortName(), std::move(client_port)); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue