mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	HLE/Services: Allow specifying a SessionData template parameter to ServiceFramework.
Some services can have multiple clients at the same time, and they identify the different clients using the server session as a key. This parameter (if present) should be a structure that contains the per-session data for each service. The data can be retrieved using ServiceFramework::GetSessionData(session)
This commit is contained in:
		
							parent
							
								
									aecd2b85fe
								
							
						
					
					
						commit
						daecd812b0
					
				
					 4 changed files with 57 additions and 11 deletions
				
			
		|  | @ -2,26 +2,32 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <algorithm> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <boost/range/algorithm_ext/erase.hpp> |  | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/hle/kernel/handle_table.h" | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/hle_ipc.h" | #include "core/hle/kernel/hle_ipc.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/kernel/server_session.h" |  | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
|  | SessionRequestHandler::SessionInfo::SessionInfo(SharedPtr<ServerSession> session, | ||||||
|  |                                                 std::unique_ptr<SessionDataBase> data) | ||||||
|  |     : session(std::move(session)), data(std::move(data)) {} | ||||||
|  | 
 | ||||||
| void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) { | void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) { | ||||||
|     server_session->SetHleHandler(shared_from_this()); |     server_session->SetHleHandler(shared_from_this()); | ||||||
|     connected_sessions.push_back(server_session); |     connected_sessions.emplace_back(std::move(server_session), MakeSessionData()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_session) { | void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_session) { | ||||||
|     server_session->SetHleHandler(nullptr); |     server_session->SetHleHandler(nullptr); | ||||||
|     boost::range::remove_erase(connected_sessions, server_session); |     connected_sessions.erase( | ||||||
|  |         std::remove_if(connected_sessions.begin(), connected_sessions.end(), | ||||||
|  |                        [&](const SessionInfo& info) { return info.session == server_session; }), | ||||||
|  |         connected_sessions.end()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| HLERequestContext::HLERequestContext(SharedPtr<ServerSession> session) | HLERequestContext::HLERequestContext(SharedPtr<ServerSession> session) | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <algorithm> | ||||||
| #include <array> | #include <array> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <vector> | #include <vector> | ||||||
|  | @ -54,13 +55,36 @@ public: | ||||||
|      * associated ServerSession. |      * associated ServerSession. | ||||||
|      * @param server_session ServerSession associated with the connection. |      * @param server_session ServerSession associated with the connection. | ||||||
|      */ |      */ | ||||||
|     virtual void ClientDisconnected(SharedPtr<ServerSession> server_session); |     void ClientDisconnected(SharedPtr<ServerSession> server_session); | ||||||
|  | 
 | ||||||
|  |     /// Empty placeholder structure for services with no per-session data. The session data classes
 | ||||||
|  |     /// in each service must inherit from this.
 | ||||||
|  |     struct SessionDataBase {}; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     /// List of sessions that are connected to this handler.
 |     /// Creates the storage for the session data of the service.
 | ||||||
|     /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list
 |     virtual std::unique_ptr<SessionDataBase> MakeSessionData() const = 0; | ||||||
|     // for the duration of the connection.
 | 
 | ||||||
|     std::vector<SharedPtr<ServerSession>> connected_sessions; |     /// Returns the session data associated with the server session.
 | ||||||
|  |     template <typename T> | ||||||
|  |     T* GetSessionData(SharedPtr<ServerSession> session) { | ||||||
|  |         static_assert(std::is_base_of<SessionDataBase, T>(), | ||||||
|  |                       "T is not a subclass of SessionDataBase"); | ||||||
|  |         auto itr = std::find_if(connected_sessions.begin(), connected_sessions.end(), | ||||||
|  |                                 [&](const SessionInfo& info) { return info.session == session; }); | ||||||
|  |         ASSERT(itr != connected_sessions.end()); | ||||||
|  |         return static_cast<T*>(itr->data.get()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     struct SessionInfo { | ||||||
|  |         SessionInfo(SharedPtr<ServerSession> session, std::unique_ptr<SessionDataBase> data); | ||||||
|  | 
 | ||||||
|  |         SharedPtr<ServerSession> session; | ||||||
|  |         std::unique_ptr<SessionDataBase> data; | ||||||
|  |     }; | ||||||
|  |     /// List of sessions that are connected to this handler. A ServerSession whose server endpoint
 | ||||||
|  |     /// is an HLE implementation is kept alive by this list for the duration of the connection.
 | ||||||
|  |     std::vector<SessionInfo> connected_sessions; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class MappedBuffer { | class MappedBuffer { | ||||||
|  |  | ||||||
|  | @ -108,6 +108,10 @@ public: | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override; |     void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override; | ||||||
|  | 
 | ||||||
|  |     std::unique_ptr<SessionDataBase> MakeSessionData() const override { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -87,6 +87,10 @@ public: | ||||||
| protected: | protected: | ||||||
|     void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override; |     void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override; | ||||||
| 
 | 
 | ||||||
|  |     std::unique_ptr<SessionDataBase> MakeSessionData() const override { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Registers the functions in the service |      * Registers the functions in the service | ||||||
|      */ |      */ | ||||||
|  | @ -144,7 +148,7 @@ protected: | ||||||
|     using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&); |     using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     template <typename T> |     template <typename T, typename SessionData> | ||||||
|     friend class ServiceFramework; |     friend class ServiceFramework; | ||||||
| 
 | 
 | ||||||
|     struct FunctionInfoBase { |     struct FunctionInfoBase { | ||||||
|  | @ -190,7 +194,7 @@ private: | ||||||
|  * of the passed in function pointers and then delegate the actual work to the implementation in the |  * of the passed in function pointers and then delegate the actual work to the implementation in the | ||||||
|  * base class. |  * base class. | ||||||
|  */ |  */ | ||||||
| template <typename Self> | template <typename Self, typename SessionData = Kernel::SessionRequestHandler::SessionDataBase> | ||||||
| class ServiceFramework : public ServiceFrameworkBase { | class ServiceFramework : public ServiceFrameworkBase { | ||||||
| protected: | protected: | ||||||
|     /// Contains information about a request type which is handled by the service.
 |     /// Contains information about a request type which is handled by the service.
 | ||||||
|  | @ -236,6 +240,14 @@ protected: | ||||||
|         RegisterHandlersBase(functions, n); |         RegisterHandlersBase(functions, n); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     std::unique_ptr<SessionDataBase> MakeSessionData() const override { | ||||||
|  |         return std::make_unique<SessionData>(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     SessionData* GetSessionData(Kernel::SharedPtr<Kernel::ServerSession> server_session) { | ||||||
|  |         return ServiceFrameworkBase::GetSessionData<SessionData>(server_session); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     /**
 |     /**
 | ||||||
|      * This function is used to allow invocation of pointers to handlers stored in the base class |      * This function is used to allow invocation of pointers to handlers stored in the base class | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue