// Copyright 2017 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include #include #include #include #include #include #include #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/server_port.h" #include "core/hle/result.h" #include "core/hle/service/service.h" namespace Core { class System; } namespace Kernel { class ClientSession; class SessionRequestHandler; } // namespace Kernel namespace Service::SM { class SRV; constexpr Result ResultServiceNotRegistered(1, ErrorModule::SRV, ErrorSummary::WouldBlock, ErrorLevel::Temporary); // 0xD0406401 constexpr Result ResultMaxConnectionsReached(2, ErrorModule::SRV, ErrorSummary::WouldBlock, ErrorLevel::Temporary); // 0xD0406402 constexpr Result ResultInvalidNameSize(5, ErrorModule::SRV, ErrorSummary::WrongArgument, ErrorLevel::Permanent); // 0xD9006405 constexpr Result ResultAccessDenied(6, ErrorModule::SRV, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); // 0xD8E06406 constexpr Result ResultNameContainsNul(7, ErrorModule::SRV, ErrorSummary::WrongArgument, ErrorLevel::Permanent); // 0xD9006407 constexpr Result ResultAlreadyRegistered(ErrorDescription::AlreadyExists, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); // 0xD9001BFC class ServiceManager { public: static void InstallInterfaces(Core::System& system); explicit ServiceManager(Core::System& system); Result RegisterService(std::shared_ptr* out_server_port, std::string name, u32 max_sessions); Result GetServicePort(std::shared_ptr* out_client_port, const std::string& name); Result ConnectToService(std::shared_ptr* out_client_session, const std::string& name); // For IPC Recorder std::string GetServiceNameByPortId(u32 port) const; template std::shared_ptr GetService(const std::string& service_name) const { static_assert(std::is_base_of_v, "Not a base of ServiceFrameworkBase"); auto service = registered_services.find(service_name); if (service == registered_services.end()) { LOG_DEBUG(Service, "Can't find service: {}", service_name); return nullptr; } auto port = service->second->GetServerPort(); if (port == nullptr) { return nullptr; } return std::static_pointer_cast(port->hle_handler); } private: Core::System& system; std::weak_ptr srv_interface; /// Map of registered services, retrieved using GetServicePort or ConnectToService. std::unordered_map> registered_services; // For IPC Recorder /// client port Object id -> service name std::unordered_map registered_services_inverse; template void save(Archive& ar, const unsigned int file_version) const { ar << registered_services; } template void load(Archive& ar, const unsigned int file_version) { ar >> registered_services; registered_services_inverse.clear(); for (const auto& pair : registered_services) { registered_services_inverse.emplace(pair.second->GetObjectId(), pair.first); } } BOOST_SERIALIZATION_SPLIT_MEMBER() friend class boost::serialization::access; }; } // namespace Service::SM