diff --git a/libraries/libstratosphere/include/stratosphere/scs/scs_server_manager.hpp b/libraries/libstratosphere/include/stratosphere/scs/scs_server_manager.hpp index 7c0336d50..a57e88e6b 100644 --- a/libraries/libstratosphere/include/stratosphere/scs/scs_server_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/scs/scs_server_manager.hpp @@ -40,6 +40,8 @@ namespace ams::scs { static constexpr size_t PointerBufferSize = 0; static constexpr size_t MaxDomains = 6; static constexpr size_t MaxDomainObjects = 16; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; class ServerManager final : public sf::hipc::ServerManager { diff --git a/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_manager.hpp b/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_manager.hpp index 9d29fed2c..6a36e9201 100644 --- a/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_manager.hpp @@ -24,6 +24,8 @@ namespace ams::sf::hipc { static constexpr size_t PointerBufferSize = 0; static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomainObjects = 0; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; static constexpr size_t ServerSessionCountMax = 0x40; @@ -72,6 +74,9 @@ namespace ams::sf::hipc { R_ABORT_UNLESS(sm::mitm::AcknowledgeSession(out_fsrv->get(), out_client_info, m_service_name)); } }; + protected: + static constinit inline bool g_is_any_deferred_supported = false; + static constinit inline bool g_is_any_mitm_supported = false; private: /* Multiple wait management. */ os::MultiWaitType m_multi_wait; @@ -84,6 +89,10 @@ namespace ams::sf::hipc { os::SdkMutex m_deferred_list_mutex; os::MultiWaitType m_deferred_list; + + /* Boolean values. */ + const bool m_is_defer_supported; + const bool m_is_mitm_supported; private: virtual void RegisterServerSessionToWait(ServerSession *session) override final; void LinkToDeferredList(os::MultiWaitHolderType *holder); @@ -102,6 +111,7 @@ namespace ams::sf::hipc { server->m_is_mitm_server = is_mitm_server; if (is_mitm_server) { /* Mitm server. */ + AMS_ABORT_UNLESS(this->CanManageMitmServers()); os::SetMultiWaitHolderUserData(server, static_cast(UserDataTag::MitmServer)); } else { /* Non-mitm server. */ @@ -148,6 +158,26 @@ namespace ams::sf::hipc { return ResultSuccess(); } + Result InstallMitmServerImpl(os::NativeHandle *out_port_handle, sm::ServiceName service_name, MitmQueryFunction query_func); + protected: + virtual Server *AllocateServer() = 0; + virtual void DestroyServer(Server *server) = 0; + virtual Result OnNeedsToAccept(int port_index, Server *server) { + AMS_UNUSED(port_index, server); + AMS_ABORT("OnNeedsToAccept must be overridden when using indexed ports"); + } + + template + Result AcceptImpl(Server *server, SharedPointer p) { + return ServerSessionManager::AcceptSession(server->m_port_handle, std::move(p)); + } + + template + Result AcceptMitmImpl(Server *server, SharedPointer p, std::shared_ptr<::Service> forward_service) { + AMS_ABORT_UNLESS(this->CanManageMitmServers()); + return ServerSessionManager::AcceptMitmSession(server->m_port_handle, std::move(p), std::move(forward_service)); + } + template Result RegisterMitmServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name) { /* Install mitm service. */ @@ -170,30 +200,11 @@ namespace ams::sf::hipc { return ResultSuccess(); } - - Result InstallMitmServerImpl(os::NativeHandle *out_port_handle, sm::ServiceName service_name, MitmQueryFunction query_func); - protected: - virtual Server *AllocateServer() = 0; - virtual void DestroyServer(Server *server) = 0; - virtual Result OnNeedsToAccept(int port_index, Server *server) { - AMS_UNUSED(port_index, server); - AMS_ABORT("OnNeedsToAccept must be overridden when using indexed ports"); - } - - template - Result AcceptImpl(Server *server, SharedPointer p) { - return ServerSessionManager::AcceptSession(server->m_port_handle, std::move(p)); - } - - template - Result AcceptMitmImpl(Server *server, SharedPointer p, std::shared_ptr<::Service> forward_service) { - return ServerSessionManager::AcceptMitmSession(server->m_port_handle, std::move(p), std::move(forward_service)); - } public: - ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count) : + ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count, bool defer_supported, bool mitm_supported) : ServerDomainSessionManager(entry_storage, entry_count), m_request_stop_event(os::EventClearMode_ManualClear), m_notify_event(os::EventClearMode_ManualClear), - m_selection_mutex(), m_deferred_list_mutex() + m_selection_mutex(), m_deferred_list_mutex(), m_is_defer_supported(defer_supported), m_is_mitm_supported(mitm_supported) { /* Link multi-wait holders. */ os::InitializeMultiWait(std::addressof(m_multi_wait)); @@ -205,6 +216,22 @@ namespace ams::sf::hipc { os::InitializeMultiWait(std::addressof(m_deferred_list)); } + static ALWAYS_INLINE bool CanAnyDeferInvokeRequest() { + return g_is_any_deferred_supported; + } + + static ALWAYS_INLINE bool CanAnyManageMitmServers() { + return g_is_any_mitm_supported; + } + + ALWAYS_INLINE bool CanDeferInvokeRequest() const { + return CanAnyDeferInvokeRequest() && m_is_defer_supported; + } + + ALWAYS_INLINE bool CanManageMitmServers() const { + return CanAnyManageMitmServers() && m_is_mitm_supported; + } + template void RegisterObjectForServer(SharedPointer static_object, os::NativeHandle port_handle) { this->RegisterServerImpl(0, cmif::ServiceObjectHolder(std::move(static_object)), port_handle, false); @@ -223,11 +250,6 @@ namespace ams::sf::hipc { return this->RegisterServerImpl(port_index, cmif::ServiceObjectHolder(), service_name, max_sessions); } - template - Result RegisterMitmServer(int port_index, sm::ServiceName service_name) { - return this->template RegisterMitmServerImpl(port_index, cmif::ServiceObjectHolder(), service_name); - } - /* Processing. */ os::MultiWaitHolderType *WaitSignaled(); @@ -267,7 +289,7 @@ namespace ams::sf::hipc { util::TypedStorage m_session_storages[MaxSessions]; bool m_session_allocated[MaxSessions]; u8 m_pointer_buffer_storage[0x10 + (MaxSessions * ManagerOptions::PointerBufferSize)]; - u8 m_saved_message_storage[0x10 + (MaxSessions * hipc::TlsMessageBufferSize)]; + u8 m_saved_message_storage[0x10 + (MaxSessions * (ManagerOptions::CanDeferInvokeRequest ? hipc::TlsMessageBufferSize : 0))]; uintptr_t m_pointer_buffers_start; uintptr_t m_saved_messages_start; @@ -337,12 +359,16 @@ namespace ams::sf::hipc { os::UnlinkMultiWaitHolder(server); os::FinalizeMultiWaitHolder(server); if (server->m_service_managed) { - if (server->m_is_mitm_server) { - R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->m_service_name)); + if constexpr (ManagerOptions::CanManageMitmServers) { + if (server->m_is_mitm_server) { + R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->m_service_name)); + } else { + R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name)); + } } else { R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name)); } - R_ABORT_UNLESS(svc::CloseHandle(server->m_port_handle)); + os::CloseNativeHandle(server->m_port_handle); } } m_server_allocated[index] = false; @@ -377,10 +403,14 @@ namespace ams::sf::hipc { } virtual cmif::PointerAndSize GetSessionSavedMessageBuffer(const ServerSession *session) const override final { - return this->GetObjectBySessionIndex(session, m_saved_messages_start, hipc::TlsMessageBufferSize); + if constexpr (ManagerOptions::CanDeferInvokeRequest) { + return this->GetObjectBySessionIndex(session, m_saved_messages_start, hipc::TlsMessageBufferSize); + } else { + return cmif::PointerAndSize(); + } } public: - ServerManager() : ServerManagerBase(m_domain_entry_storages, ManagerOptions::MaxDomainObjects), m_resource_mutex() { + ServerManager() : ServerManagerBase(m_domain_entry_storages, ManagerOptions::MaxDomainObjects, ManagerOptions::CanDeferInvokeRequest, ManagerOptions::CanManageMitmServers), m_resource_mutex() { /* Clear storages. */ #define SF_SM_MEMCLEAR(obj) if constexpr (sizeof(obj) > 0) { std::memset(obj, 0, sizeof(obj)); } SF_SM_MEMCLEAR(m_server_storages); @@ -395,6 +425,14 @@ namespace ams::sf::hipc { /* Set resource starts. */ m_pointer_buffers_start = util::AlignUp(reinterpret_cast(m_pointer_buffer_storage), 0x10); m_saved_messages_start = util::AlignUp(reinterpret_cast(m_saved_message_storage), 0x10); + + /* Update globals. */ + if constexpr (ManagerOptions::CanDeferInvokeRequest) { + ServerManagerBase::g_is_any_deferred_supported = true; + } + if constexpr (ManagerOptions::CanManageMitmServers) { + ServerManagerBase::g_is_any_mitm_supported = true; + } } ~ServerManager() { @@ -416,6 +454,12 @@ namespace ams::sf::hipc { } } } + public: + template::type> + Result RegisterMitmServer(int port_index, sm::ServiceName service_name) { + AMS_ABORT_UNLESS(this->CanManageMitmServers()); + return this->template RegisterMitmServerImpl(port_index, cmif::ServiceObjectHolder(), service_name); + } }; } diff --git a/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_session_manager.hpp b/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_session_manager.hpp index cecaeb822..bbcf0468b 100644 --- a/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_session_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/sf/hipc/sf_hipc_server_session_manager.hpp @@ -48,29 +48,29 @@ namespace ams::sf::hipc { cmif::ServiceObjectHolder m_srv_obj_holder; cmif::PointerAndSize m_pointer_buffer; cmif::PointerAndSize m_saved_message; - std::shared_ptr<::Service> m_forward_service; + util::TypedStorage> m_forward_service; os::NativeHandle m_session_handle; bool m_is_closed; bool m_has_received; + const bool m_has_forward_service; public: - ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj) : m_srv_obj_holder(std::move(obj)), m_session_handle(h) { + ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj) : m_srv_obj_holder(std::move(obj)), m_session_handle(h), m_has_forward_service(false) { hipc::AttachMultiWaitHolderForReply(this, h); m_is_closed = false; m_has_received = false; - m_forward_service = nullptr; AMS_ABORT_UNLESS(!this->IsMitmSession()); } - ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : m_srv_obj_holder(std::move(obj)), m_session_handle(h) { + ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : m_srv_obj_holder(std::move(obj)), m_session_handle(h), m_has_forward_service(true) { hipc::AttachMultiWaitHolderForReply(this, h); m_is_closed = false; m_has_received = false; - m_forward_service = std::move(fsrv); - AMS_ABORT_UNLESS(this->IsMitmSession()); + util::ConstructAt(m_forward_service, std::move(fsrv)); + AMS_ABORT_UNLESS(util::GetReference(m_forward_service) != nullptr); } - bool IsMitmSession() const { - return m_forward_service != nullptr; + ALWAYS_INLINE bool IsMitmSession() const { + return m_has_forward_service; } Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const; diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_service.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_service.cpp index 03da203c8..083c661c2 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_service.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_service.cpp @@ -27,9 +27,11 @@ namespace ams::erpt::srv { namespace { struct ErrorReportServerOptions { - static constexpr size_t PointerBufferSize = 0; - static constexpr size_t MaxDomains = 64; - static constexpr size_t MaxDomainObjects = 2 * ReportCountMax + 5 + 2; + static constexpr size_t PointerBufferSize = 0; + static constexpr size_t MaxDomains = 64; + static constexpr size_t MaxDomainObjects = 2 * ReportCountMax + 5 + 2; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; constexpr inline size_t ErrorReportNumServers = 2; diff --git a/libraries/libstratosphere/source/htcfs/htcfs_hipc_server.cpp b/libraries/libstratosphere/source/htcfs/htcfs_hipc_server.cpp index 39dc815da..a5a4c17ec 100644 --- a/libraries/libstratosphere/source/htcfs/htcfs_hipc_server.cpp +++ b/libraries/libstratosphere/source/htcfs/htcfs_hipc_server.cpp @@ -26,9 +26,11 @@ namespace ams::htcfs { static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("file_io"); struct ServerOptions { - static constexpr size_t PointerBufferSize = 0x1000; - static constexpr size_t MaxDomains = 0x10; - static constexpr size_t MaxDomainObjects = 0x100; + static constexpr size_t PointerBufferSize = 0x1000; + static constexpr size_t MaxDomains = 0x10; + static constexpr size_t MaxDomainObjects = 0x100; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; using ServerManager = sf::hipc::ServerManager; diff --git a/libraries/libstratosphere/source/htcs/server/htcs_hipc_server.cpp b/libraries/libstratosphere/source/htcs/server/htcs_hipc_server.cpp index 86670dc41..c7b6511ec 100644 --- a/libraries/libstratosphere/source/htcs/server/htcs_hipc_server.cpp +++ b/libraries/libstratosphere/source/htcs/server/htcs_hipc_server.cpp @@ -25,9 +25,11 @@ namespace ams::htcs::server { static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("htcs"); struct ServerOptions { - static constexpr size_t PointerBufferSize = 0x80; - static constexpr size_t MaxDomains = 0x10; - static constexpr size_t MaxDomainObjects = 100; + static constexpr size_t PointerBufferSize = 0x80; + static constexpr size_t MaxDomains = 0x10; + static constexpr size_t MaxDomainObjects = 100; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; using ServerManager = sf::hipc::ServerManager; diff --git a/libraries/libstratosphere/source/lm/srv/lm_ipc_server.cpp b/libraries/libstratosphere/source/lm/srv/lm_ipc_server.cpp index 2e04a2163..8ae083a4b 100644 --- a/libraries/libstratosphere/source/lm/srv/lm_ipc_server.cpp +++ b/libraries/libstratosphere/source/lm/srv/lm_ipc_server.cpp @@ -30,9 +30,11 @@ namespace ams::lm::srv { constexpr inline size_t PortCountMax = 2; struct ServerManagerOptions { - static constexpr size_t PointerBufferSize = 0x400; - static constexpr size_t MaxDomains = 31; - static constexpr size_t MaxDomainObjects = 61; + static constexpr size_t PointerBufferSize = 0x400; + static constexpr size_t MaxDomains = 31; + static constexpr size_t MaxDomainObjects = 61; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; using ServerManager = sf::hipc::ServerManager; diff --git a/libraries/libstratosphere/source/sf/hipc/sf_hipc_mitm_query_api.cpp b/libraries/libstratosphere/source/sf/hipc/sf_hipc_mitm_query_api.cpp index 832b9ffce..8fb68eaaf 100644 --- a/libraries/libstratosphere/source/sf/hipc/sf_hipc_mitm_query_api.cpp +++ b/libraries/libstratosphere/source/sf/hipc/sf_hipc_mitm_query_api.cpp @@ -27,7 +27,7 @@ namespace ams::sf::hipc::impl { class MitmQueryService { private: - ServerManagerBase::MitmQueryFunction m_query_function; + const ServerManagerBase::MitmQueryFunction m_query_function; public: MitmQueryService(ServerManagerBase::MitmQueryFunction qf) : m_query_function(qf) { /* ... */ } diff --git a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_domain_session_manager.cpp b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_domain_session_manager.cpp index 795e67d74..07d82763e 100644 --- a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_domain_session_manager.cpp +++ b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_domain_session_manager.cpp @@ -32,7 +32,7 @@ namespace ams::sf::hipc { private: ServerDomainSessionManager *m_manager; ServerSession *m_session; - bool m_is_mitm_session; + const bool m_is_mitm_session; private: Result CloneCurrentObjectImpl(sf::OutMoveHandle &out_client_handle, ServerSessionManager *tagged_manager) { /* Clone the object. */ @@ -47,9 +47,12 @@ namespace ams::sf::hipc { if (!m_is_mitm_session) { R_ABORT_UNLESS(tagged_manager->RegisterSession(server_handle, std::move(clone))); } else { + /* Check that we can create a mitm session. */ + AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers()); + /* Clone the forward service. */ std::shared_ptr<::Service> new_forward_service = std::move(ServerSession::CreateForwardService()); - R_ABORT_UNLESS(serviceClone(m_session->m_forward_service.get(), new_forward_service.get())); + R_ABORT_UNLESS(serviceClone(util::GetReference(m_session->m_forward_service).get(), new_forward_service.get())); R_ABORT_UNLESS(tagged_manager->RegisterMitmSession(server_handle, std::move(clone), std::move(new_forward_service))); } @@ -58,7 +61,7 @@ namespace ams::sf::hipc { return ResultSuccess(); } public: - explicit HipcManagerImpl(ServerDomainSessionManager *m, ServerSession *s) : m_manager(m), m_session(s), m_is_mitm_session(s->m_forward_service != nullptr) { + explicit HipcManagerImpl(ServerDomainSessionManager *m, ServerSession *s) : m_manager(m), m_session(s), m_is_mitm_session(s->IsMitmSession()) { /* ... */ } @@ -70,15 +73,18 @@ namespace ams::sf::hipc { /* Set up the new domain object. */ cmif::DomainObjectId object_id = cmif::InvalidDomainObjectId; if (m_is_mitm_session) { + /* Check that we can create a mitm session. */ + AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers()); + /* Make a new shared pointer to manage the allocated domain. */ SharedPointer cmif_domain(static_cast(domain), false); /* Convert the remote session to domain. */ - AMS_ABORT_UNLESS(m_session->m_forward_service->own_handle); - R_TRY(serviceConvertToDomain(m_session->m_forward_service.get())); + AMS_ABORT_UNLESS(util::GetReference(m_session->m_forward_service)->own_handle); + R_TRY(serviceConvertToDomain(util::GetReference(m_session->m_forward_service).get())); /* The object ID reservation cannot fail here, as that would cause desynchronization from target domain. */ - object_id = cmif::DomainObjectId{m_session->m_forward_service->object_id}; + object_id = cmif::DomainObjectId{util::GetReference(m_session->m_forward_service)->object_id}; domain->ReserveSpecificIds(std::addressof(object_id), 1); /* Register the object. */ @@ -116,14 +122,17 @@ namespace ams::sf::hipc { if (!object) { R_UNLESS(m_is_mitm_session, sf::hipc::ResultDomainObjectNotFound()); + /* Check that we can create a mitm session. */ + AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers()); + os::NativeHandle handle; - R_TRY(cmifCopyFromCurrentDomain(m_session->m_forward_service->session, object_id.value, std::addressof(handle))); + R_TRY(cmifCopyFromCurrentDomain(util::GetReference(m_session->m_forward_service)->session, object_id.value, std::addressof(handle))); out.SetValue(handle, false); return ResultSuccess(); } - if (!m_is_mitm_session || object_id.value != serviceGetObjectId(m_session->m_forward_service.get())) { + if (!m_is_mitm_session || (ServerManagerBase::CanAnyManageMitmServers() && object_id.value != serviceGetObjectId(util::GetReference(m_session->m_forward_service).get()))) { /* Create new session handles. */ os::NativeHandle server_handle, client_handle; R_ABORT_UNLESS(hipc::CreateSession(std::addressof(server_handle), std::addressof(client_handle))); @@ -134,9 +143,12 @@ namespace ams::sf::hipc { /* Set output client handle. */ out.SetValue(client_handle, false); } else { + /* Check that we can create a mitm session. */ + AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers()); + /* Copy from the target domain. */ os::NativeHandle new_forward_target; - R_TRY(cmifCopyFromCurrentDomain(m_session->m_forward_service->session, object_id.value, std::addressof(new_forward_target))); + R_TRY(cmifCopyFromCurrentDomain(util::GetReference(m_session->m_forward_service)->session, object_id.value, std::addressof(new_forward_target))); /* Create new session handles. */ os::NativeHandle server_handle, client_handle; diff --git a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_manager.cpp b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_manager.cpp index ee3521efa..6717f4f6e 100644 --- a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_manager.cpp +++ b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_manager.cpp @@ -114,21 +114,34 @@ namespace ams::sf::hipc { ServerSession *session = static_cast(holder); cmif::PointerAndSize tls_message(svc::GetThreadLocalRegion()->message_buffer, hipc::TlsMessageBufferSize); - const cmif::PointerAndSize &saved_message = session->m_saved_message; - AMS_ABORT_UNLESS(tls_message.GetSize() == saved_message.GetSize()); - if (!session->m_has_received) { - R_TRY(this->ReceiveRequest(session, tls_message)); - session->m_has_received = true; - std::memcpy(saved_message.GetPointer(), tls_message.GetPointer(), tls_message.GetSize()); - } else { - /* We were deferred and are re-receiving, so just memcpy. */ - std::memcpy(tls_message.GetPointer(), saved_message.GetPointer(), tls_message.GetSize()); - } + if (this->CanDeferInvokeRequest()) { + const cmif::PointerAndSize &saved_message = session->m_saved_message; + AMS_ABORT_UNLESS(tls_message.GetSize() == saved_message.GetSize()); - /* Treat a meta "Context Invalidated" message as a success. */ - R_TRY_CATCH(this->ProcessRequest(session, tls_message)) { - R_CONVERT(sf::impl::ResultRequestInvalidated, ResultSuccess()); - } R_END_TRY_CATCH; + if (!session->m_has_received) { + R_TRY(this->ReceiveRequest(session, tls_message)); + session->m_has_received = true; + std::memcpy(saved_message.GetPointer(), tls_message.GetPointer(), tls_message.GetSize()); + } else { + /* We were deferred and are re-receiving, so just memcpy. */ + std::memcpy(tls_message.GetPointer(), saved_message.GetPointer(), tls_message.GetSize()); + } + + /* Treat a meta "Context Invalidated" message as a success. */ + R_TRY_CATCH(this->ProcessRequest(session, tls_message)) { + R_CONVERT(sf::impl::ResultRequestInvalidated, ResultSuccess()); + } R_END_TRY_CATCH; + } else { + if (!session->m_has_received) { + R_TRY(this->ReceiveRequest(session, tls_message)); + session->m_has_received = true; + } + + R_TRY_CATCH(this->ProcessRequest(session, tls_message)) { + R_CATCH(sf::ResultRequestDeferred) { AMS_ABORT("Request Deferred on server which does not support deferral"); } + R_CATCH(sf::impl::ResultRequestInvalidated) { AMS_ABORT("Request Invalidated on server which does not support deferral"); } + } R_END_TRY_CATCH; + } return ResultSuccess(); } @@ -138,6 +151,7 @@ namespace ams::sf::hipc { case UserDataTag::Server: return this->ProcessForServer(holder); case UserDataTag::MitmServer: + AMS_ABORT_UNLESS(this->CanManageMitmServers()); return this->ProcessForMitmServer(holder); case UserDataTag::Session: return this->ProcessForSession(holder); diff --git a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp index a57a34a41..bf4545b82 100644 --- a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp +++ b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp @@ -40,7 +40,9 @@ namespace ams::sf::hipc { } Result ServerSession::ForwardRequest(const cmif::ServiceDispatchContext &ctx) const { + AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers()); AMS_ABORT_UNLESS(this->IsMitmSession()); + /* TODO: Support non-TLS messages? */ AMS_ABORT_UNLESS(m_saved_message.GetPointer() != nullptr); AMS_ABORT_UNLESS(m_saved_message.GetSize() == TlsMessageBufferSize); @@ -55,7 +57,7 @@ namespace ams::sf::hipc { PreProcessCommandBufferForMitm(ctx, m_pointer_buffer, reinterpret_cast(message_buffer)); /* Dispatch forwards. */ - R_TRY(svc::SendSyncRequest(m_forward_service->session)); + R_TRY(svc::SendSyncRequest(util::GetReference(m_forward_service)->session)); /* Parse, to ensure we catch any copy handles and close them. */ { @@ -114,6 +116,8 @@ namespace ams::sf::hipc { } Result ServerSessionManager::RegisterMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) { + AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers()); + /* Create session object. */ std::construct_at(session_memory, mitm_session_handle, std::forward(obj), std::forward>(fsrv)); @@ -122,8 +126,8 @@ namespace ams::sf::hipc { session_memory->m_saved_message = this->GetSessionSavedMessageBuffer(session_memory); /* Validate session pointer buffer. */ - AMS_ABORT_UNLESS(session_memory->m_pointer_buffer.GetSize() >= session_memory->m_forward_service->pointer_buffer_size); - session_memory->m_pointer_buffer = cmif::PointerAndSize(session_memory->m_pointer_buffer.GetAddress(), session_memory->m_forward_service->pointer_buffer_size); + AMS_ABORT_UNLESS(session_memory->m_pointer_buffer.GetSize() >= util::GetReference(session_memory->m_forward_service)->pointer_buffer_size); + session_memory->m_pointer_buffer = cmif::PointerAndSize(session_memory->m_pointer_buffer.GetAddress(), util::GetReference(session_memory->m_forward_service)->pointer_buffer_size); /* Register to wait list. */ this->RegisterServerSessionToWait(session_memory); @@ -131,6 +135,8 @@ namespace ams::sf::hipc { } Result ServerSessionManager::AcceptMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) { + AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers()); + /* Create session handle. */ os::NativeHandle mitm_session_handle; R_TRY(svc::AcceptSession(std::addressof(mitm_session_handle), mitm_port_handle)); @@ -201,7 +207,7 @@ namespace ams::sf::hipc { namespace { - NX_CONSTEXPR u32 GetCmifCommandType(const cmif::PointerAndSize &message) { + constexpr ALWAYS_INLINE u32 GetCmifCommandType(const cmif::PointerAndSize &message) { HipcHeader hdr = {}; __builtin_memcpy(std::addressof(hdr), message.GetPointer(), sizeof(hdr)); return hdr.type; diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_api.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_api.cpp index 14729521a..216ae2b53 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_api.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_api.cpp @@ -41,9 +41,11 @@ namespace ams::sprofile::srv { constexpr inline size_t PortCountMax = 2; struct ServerManagerOptions { - static constexpr size_t PointerBufferSize = 0x0; - static constexpr size_t MaxDomains = SessionCountMax; /* NOTE: Official is 3 */ - static constexpr size_t MaxDomainObjects = 16; /* NOTE: Official is 8 */ + static constexpr size_t PointerBufferSize = 0x0; + static constexpr size_t MaxDomains = SessionCountMax; /* NOTE: Official is 3 */ + static constexpr size_t MaxDomainObjects = 16; /* NOTE: Official is 8 */ + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; using ServerManager = sf::hipc::ServerManager; diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp index ffbd3d5d1..d06a48578 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp @@ -32,7 +32,14 @@ namespace ams::mitm::bpc { constexpr size_t MitmServiceMaxSessions = 13; constexpr size_t MaxSessions = MitmServiceMaxSessions; - using ServerOptions = sf::hipc::DefaultServerManagerOptions; + + struct ServerOptions { + static constexpr size_t PointerBufferSize = sf::hipc::DefaultServerManagerOptions::PointerBufferSize; + static constexpr size_t MaxDomains = sf::hipc::DefaultServerManagerOptions::MaxDomains; + static constexpr size_t MaxDomainObjects = sf::hipc::DefaultServerManagerOptions::MaxDomainObjects; + static constexpr bool CanDeferInvokeRequest = sf::hipc::DefaultServerManagerOptions::CanDeferInvokeRequest; + static constexpr bool CanManageMitmServers = true; + }; class ServerManager final : public sf::hipc::ServerManager { private: diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp index eadb2e6a8..3e959a47f 100644 --- a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp +++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp @@ -32,7 +32,14 @@ namespace ams::mitm::socket::resolver { constexpr sm::ServiceName DnsMitmServiceName = sm::ServiceName::Encode("sfdnsres"); constexpr size_t MaxSessions = 30; - using ServerOptions = sf::hipc::DefaultServerManagerOptions; + + struct ServerOptions { + static constexpr size_t PointerBufferSize = sf::hipc::DefaultServerManagerOptions::PointerBufferSize; + static constexpr size_t MaxDomains = sf::hipc::DefaultServerManagerOptions::MaxDomains; + static constexpr size_t MaxDomainObjects = sf::hipc::DefaultServerManagerOptions::MaxDomainObjects; + static constexpr bool CanDeferInvokeRequest = sf::hipc::DefaultServerManagerOptions::CanDeferInvokeRequest; + static constexpr bool CanManageMitmServers = true; + }; class ServerManager final : public sf::hipc::ServerManager { private: diff --git a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_module.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_module.cpp index 37256650d..ce6433fea 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_module.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_module.cpp @@ -29,9 +29,11 @@ namespace ams::mitm::fs { constexpr sm::ServiceName MitmServiceName = sm::ServiceName::Encode("fsp-srv"); struct ServerOptions { - static constexpr size_t PointerBufferSize = 0x800; - static constexpr size_t MaxDomains = 0x40; - static constexpr size_t MaxDomainObjects = 0x4000; + static constexpr size_t PointerBufferSize = 0x800; + static constexpr size_t MaxDomains = 0x40; + static constexpr size_t MaxDomainObjects = 0x4000; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = true; }; constexpr size_t MaxSessions = 61; diff --git a/stratosphere/ams_mitm/source/ns_mitm/nsmitm_module.cpp b/stratosphere/ams_mitm/source/ns_mitm/nsmitm_module.cpp index a9fb0c785..bb48fac93 100644 --- a/stratosphere/ams_mitm/source/ns_mitm/nsmitm_module.cpp +++ b/stratosphere/ams_mitm/source/ns_mitm/nsmitm_module.cpp @@ -32,7 +32,14 @@ namespace ams::mitm::ns { constexpr sm::ServiceName NsWebMitmServiceName = sm::ServiceName::Encode("ns:web"); constexpr size_t MaxSessions = 5; - using ServerOptions = sf::hipc::DefaultServerManagerOptions; + + struct ServerOptions { + static constexpr size_t PointerBufferSize = sf::hipc::DefaultServerManagerOptions::PointerBufferSize; + static constexpr size_t MaxDomains = sf::hipc::DefaultServerManagerOptions::MaxDomains; + static constexpr size_t MaxDomainObjects = sf::hipc::DefaultServerManagerOptions::MaxDomainObjects; + static constexpr bool CanDeferInvokeRequest = sf::hipc::DefaultServerManagerOptions::CanDeferInvokeRequest; + static constexpr bool CanManageMitmServers = true; + }; class ServerManager final : public sf::hipc::ServerManager { private: diff --git a/stratosphere/ams_mitm/source/set_mitm/setmitm_module.cpp b/stratosphere/ams_mitm/source/set_mitm/setmitm_module.cpp index 72f6b419d..982b64e89 100644 --- a/stratosphere/ams_mitm/source/set_mitm/setmitm_module.cpp +++ b/stratosphere/ams_mitm/source/set_mitm/setmitm_module.cpp @@ -33,9 +33,11 @@ namespace ams::mitm::settings { constexpr sm::ServiceName SetSysMitmServiceName = sm::ServiceName::Encode("set:sys"); struct ServerOptions { - static constexpr size_t PointerBufferSize = 0x200; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; + static constexpr size_t PointerBufferSize = 0x200; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = true; }; constexpr size_t MaxSessions = 60; diff --git a/stratosphere/ams_mitm/source/sysupdater/sysupdater_module.cpp b/stratosphere/ams_mitm/source/sysupdater/sysupdater_module.cpp index 2f2eedadb..74db5d5f2 100644 --- a/stratosphere/ams_mitm/source/sysupdater/sysupdater_module.cpp +++ b/stratosphere/ams_mitm/source/sysupdater/sysupdater_module.cpp @@ -34,9 +34,11 @@ namespace ams::mitm::sysupdater { constexpr size_t MaxSessions = SystemUpdateMaxSessions + 3; struct ServerOptions { - static constexpr size_t PointerBufferSize = 1_KB; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; + static constexpr size_t PointerBufferSize = 1_KB; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; sf::hipc::ServerManager g_server_manager; diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 03ba52601..5b6001f93 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -46,9 +46,11 @@ namespace ams { namespace { struct ServerOptions { - static constexpr size_t PointerBufferSize = 0x400; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; + static constexpr size_t PointerBufferSize = 0x400; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; /* ldr:pm, ldr:shel, ldr:dmnt. */ diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index ed1e4f416..29f80a849 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -45,9 +45,11 @@ namespace ams { namespace { struct ContentManagerServerOptions { - static constexpr size_t PointerBufferSize = 0x400; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; + static constexpr size_t PointerBufferSize = 0x400; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; constexpr inline size_t ContentManagerNumServers = 1; @@ -90,9 +92,11 @@ namespace ams { }; struct LocationResolverServerOptions { - static constexpr size_t PointerBufferSize = 0x400; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; + static constexpr size_t PointerBufferSize = 0x400; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; constexpr inline size_t LocationResolverNumServers = 1; diff --git a/stratosphere/spl/source/spl_main.cpp b/stratosphere/spl/source/spl_main.cpp index 5a5a155e3..2ff3f1d56 100644 --- a/stratosphere/spl/source/spl_main.cpp +++ b/stratosphere/spl/source/spl_main.cpp @@ -32,9 +32,11 @@ namespace ams { namespace { struct SplServerOptions { - static constexpr size_t PointerBufferSize = 0x800; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; + static constexpr size_t PointerBufferSize = 0x800; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + static constexpr bool CanDeferInvokeRequest = false; + static constexpr bool CanManageMitmServers = false; }; enum PortIndex {