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
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <vector> | ||||
| #include <boost/range/algorithm_ext/erase.hpp> | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/hle_ipc.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/server_session.h" | ||||
| 
 | ||||
| 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) { | ||||
|     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) { | ||||
|     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) | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
| #include <memory> | ||||
| #include <vector> | ||||
|  | @ -54,13 +55,36 @@ public: | |||
|      * associated ServerSession. | ||||
|      * @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: | ||||
|     /// 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<SharedPtr<ServerSession>> connected_sessions; | ||||
|     /// Creates the storage for the session data of the service.
 | ||||
|     virtual std::unique_ptr<SessionDataBase> MakeSessionData() const = 0; | ||||
| 
 | ||||
|     /// 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 { | ||||
|  |  | |||
|  | @ -108,6 +108,10 @@ public: | |||
| 
 | ||||
| protected: | ||||
|     void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override; | ||||
| 
 | ||||
|     std::unique_ptr<SessionDataBase> MakeSessionData() const override { | ||||
|         return nullptr; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -87,6 +87,10 @@ public: | |||
| protected: | ||||
|     void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override; | ||||
| 
 | ||||
|     std::unique_ptr<SessionDataBase> MakeSessionData() const override { | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Registers the functions in the service | ||||
|      */ | ||||
|  | @ -144,7 +148,7 @@ protected: | |||
|     using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&); | ||||
| 
 | ||||
| private: | ||||
|     template <typename T> | ||||
|     template <typename T, typename SessionData> | ||||
|     friend class ServiceFramework; | ||||
| 
 | ||||
|     struct FunctionInfoBase { | ||||
|  | @ -190,7 +194,7 @@ private: | |||
|  * of the passed in function pointers and then delegate the actual work to the implementation in the | ||||
|  * base class. | ||||
|  */ | ||||
| template <typename Self> | ||||
| template <typename Self, typename SessionData = Kernel::SessionRequestHandler::SessionDataBase> | ||||
| class ServiceFramework : public ServiceFrameworkBase { | ||||
| protected: | ||||
|     /// Contains information about a request type which is handled by the service.
 | ||||
|  | @ -236,6 +240,14 @@ protected: | |||
|         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: | ||||
|     /**
 | ||||
|      * 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