mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-15 10:20:05 +00:00
Merge pull request #2753 from yuriks/set-hle-handler
Add SetHleHandler to ServerPort/ServerSession
This commit is contained in:
commit
fc1bd06192
@ -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,
|
||||
ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name,
|
||||
SharedPtr<ClientPort> port) {
|
||||
|
||||
auto server_session =
|
||||
ServerSession::Create(name + "_Server", std::move(hle_handler)).MoveFrom();
|
||||
|
||||
auto server_session = ServerSession::Create(name + "_Server").MoveFrom();
|
||||
SharedPtr<ClientSession> client_session(new ClientSession);
|
||||
client_session->name = name + "_Client";
|
||||
|
||||
|
@ -50,15 +50,21 @@ 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,
|
||||
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.
|
||||
* @returns ResultCode from the operation.
|
||||
@ -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");
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -415,6 +415,16 @@ ResultVal<T> MakeResult(Args&&... args) {
|
||||
return ResultVal<T>::WithCode(RESULT_SUCCESS, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deducible overload of MakeResult, allowing the template parameter to be ommited if you're just
|
||||
* copy or move constructing.
|
||||
*/
|
||||
template <typename Arg>
|
||||
ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
|
||||
return ResultVal<std::remove_reference_t<Arg>>::WithCode(RESULT_SUCCESS,
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps
|
||||
* the contained value and assigns it to `target`, which can be either an l-value expression or a
|
||||
@ -426,3 +436,12 @@ ResultVal<T> MakeResult(Args&&... args) {
|
||||
if (CONCAT2(check_result_L, __LINE__).Failed()) \
|
||||
return CONCAT2(check_result_L, __LINE__).Code(); \
|
||||
target = std::move(*CONCAT2(check_result_L, __LINE__))
|
||||
|
||||
/**
|
||||
* Analogous to CASCADE_RESULT, but for a bare ResultCode. The code will be propagated if
|
||||
* non-success, or discarded otherwise.
|
||||
*/
|
||||
#define CASCADE_CODE(source) \
|
||||
auto CONCAT2(check_result_L, __LINE__) = source; \
|
||||
if (CONCAT2(check_result_L, __LINE__).IsError()) \
|
||||
return CONCAT2(check_result_L, __LINE__);
|
||||
|
@ -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…
Reference in New Issue
Block a user