//////////////////////////////////////////////////////////////////////////////// // (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour // //////////////////////////////////////////////////////////////////////////////// #include "ubiservices/facadeInternal.h" #include "ubiservices/core/configs/configpriv.h" #include "ubiservices/core/debug/assert.h" #include "ubiservices/core/errors/errorCodes.h" #include "ubiservices/core/helpers/helpers.h" #include "ubiservices/core/helpers/facadesManager.h" #include "ubiservices/core/helpers/instancesManager.h" #include "ubiservices/core/locks/scopedCS.h" #include "ubiservices/core/log/remoteLoggerSdk.h" #if defined(US_ENABLE_ALLOC_STATS) #include "ubiservices/core/memory/memoryManagement.h" #endif #include "ubiservices/core/tasks/asyncResultInternal.h" #include "ubiservices/facade.h" #if defined(US_SDK_SERVER) #include "ubiservices/services/authentication/authenticationClient.h" #include "ubiservices/services/event/eventClient.h" #include "ubiservices/services/event/eventClientImpl.h" #include "ubiservices/services/remoteLog/remoteLogClient.h" #include "ubiservices/services/remoteLog/remoteLoggerCustom.h" #endif #if !defined(US_SDK_SERVER) #include "ubiservices/services/secondaryStore/sessionManagerStore.h" #endif #if defined(US_MODULE_APPLICATION) #include "ubiservices/services/application/applicationClient.h" #endif #include "ubiservices/services/authentication/authenticationClient.h" #if defined(US_MODULE_BATTLEPASS) #include "ubiservices/services/battlepass/battlepassClient.h" #endif #if defined(US_MODULE_BLOCKLIST) #include "ubiservices/services/blocklist/blocklistClient.h" #endif #if !defined(US_SDK_SERVER) #include "ubiservices/services/cacheManager.h" #endif #if defined(US_MODULE_CHALLENGE) #include "ubiservices/services/challenge/challengeClient.h" #endif #if defined(US_MODULE_CLUB) #include "ubiservices/services/club/clubClient.h" #endif // #if defined(US_MODULE_CLUB) #if defined(US_MODULE_ENTITY) #include "ubiservices/services/entity/entityClient.h" #endif #if defined(US_MODULE_FRIEND) #include "ubiservices/services/friend/friendClient.h" #endif #if defined(US_MODULE_GAMESPLAYED) #include "ubiservices/services/gamesPlayed/gamesPlayedClient.h" #endif #if !defined(US_SDK_SERVER) #include "ubiservices/services/event/eventClient.h" #include "ubiservices/services/event/eventClientImpl.h" #endif //#if !defined(US_SDK_SERVER) #include "ubiservices/services/http/httpClient.h" #if defined(US_MODULE_LEADERBOARD) #include "ubiservices/services/leaderboard/leaderboardClient.h" #endif #if defined(US_MODULE_LOCALIZATION) #include "ubiservices/services/localization/localizationClient.h" #endif #if !defined(US_SDK_SERVER) #include "ubiservices/services/notification/connectionClient.h" #include "ubiservices/services/notification/notificationClient.h" #include "ubiservices/services/overlay/overlayClient.h" #endif // !defined(US_SDK_SERVER) #if defined(US_MODULE_MATCHMAKING) #include "ubiservices/services/matchmaking/matchmakingClient.h" #endif #if defined(US_MODULE_MODERATION) #include "ubiservices/services/moderation/moderationClient.h" #endif #if defined(US_MODULE_NEWS) #include "ubiservices/services/news/newsClient.h" #endif #include "ubiservices/services/parameters/parametersClient.h" #if defined(US_MODULE_PLAYERREPORTS) #include "ubiservices/services/playerReports/playerReportsClient.h" #endif #if defined(US_PRIMARY_STORE_ENABLED) || defined(US_PRIMARY_STORE_MOBILE_ENABLED) #include "ubiservices/services/primaryStore/primaryStoreClient.h" #endif #if defined(US_MODULE_RECOMMENDATIONS) #include "ubiservices/services/recommendations/recommendationsClient.h" #endif #if defined(US_ENABLE_UPLAY) #include "ubiservices/services/uplay/uplayClient.h" #endif #if defined(US_MODULE_USER) #include "ubiservices/services/user/userClient.h" #endif #if defined(US_MODULE_VOICECHAT) #include "ubiservices/services/voicechat/voicechatClient.h" #endif #if defined(US_MODULE_PERSONA) #include "ubiservices/services/persona/personaClient.h" #endif #if defined(US_MODULE_PLAYER_ONLINE_STATUS) #include "ubiservices/services/playerOnlineStatus/playerOnlineStatusClient.h" #endif #if defined(US_MODULE_PROFILE) #include "ubiservices/services/profile/profileClient.h" #endif #if !defined(US_SDK_SERVER) #include "ubiservices/services/populations/populationClient.h" #include "ubiservices/services/remoteLog/remoteLogClient.h" #include "ubiservices/services/remoteLog/remoteLoggerCustom.h" #include "ubiservices/services/secondaryStore/secondaryStoreClient.h" #endif #if defined(US_MODULE_SSI) #include "ubiservices/services/secondaryStoreInstantiation/secondaryStoreInstantiationClient.h" #endif #if defined(US_MODULE_STATS) #include "ubiservices/services/stats/statsClient.h" #endif #if defined(US_TARGET_WINDOWS) #include "ubiservices/services/tLog/tLogClient.h" #endif #include "ubiservices/services/userGeneratedContents/userGeneratedContentsClient.h" #include "ubiservices/services/websocket/websocketClient.h" #include "ubiservices/sessionManager.h" #if defined(US_SYSTEM_CHECK_ENABLED) #define INVALIDATE_CALLED_FACADE_INVALID "The facade instance cannot be used anymore. The invalidate() method has been called." #endif #if defined(US_ENABLE_ALLOC_STATS) struct AllocStatistics g_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #endif namespace US_NS {; FacadeInternal::FacadeInternal() : m_criticalSection(US_NEW(CriticalSection, "FacadeInternal::m_criticalSection", LockMasks::FourthLast)) , m_valid(true) , m_sessionManager(US_NEW(SessionManager, *this)) , m_remoteLoggerSdk(US_NEW(RemoteLoggerSdk, *this)) , m_remoteLoggerCustom(US_NEW(RemoteLoggerCustom)) , m_owner(nullptr) { } FacadeInternal::~FacadeInternal() { deleteMembers(); } void FacadeInternal::init(Facade* owner) { m_owner = owner; m_sessionManager->init(); } void FacadeInternal::deleteMembers() { // Deletes the clients to terminate all pending jobs (order matters, don't change it). #if defined(US_PRIMARY_STORE_ENABLED) || defined(US_PRIMARY_STORE_MOBILE_ENABLED) m_primaryStoreClient.reset(); #endif #if defined(US_MODULE_SSI) m_secondaryStoreInstantiationClient.reset(); #endif #if defined(US_MODULE_STORE) m_secondaryStoreClient.reset(); #endif #if defined(US_MODULE_ENTITY) m_entityClient.reset(); #endif #if defined(US_MODULE_FRIEND) m_friendClient.reset(); #endif #if defined(US_MODULE_CLUB) m_clubClient.reset(); #endif #if defined(US_MODULE_LEADERBOARD) m_leaderboardClient.reset(); #endif #if defined(US_ENABLE_UPLAY) m_uplayClient.reset(); #endif #if defined(US_MODULE_USER) m_userClient.reset(); #endif #if defined(US_TARGET_STADIA) m_overlayClient.reset(); #endif // defined(US_TARGET_STADIA) #if defined(US_MODULE_APPLICATION) m_applicationClient.reset(); #endif #if defined(US_MODULE_NEWS) m_newsClient.reset(); #endif #if !defined(US_SDK_SERVER) m_eventClient.reset(); #if !defined(US_SDK_SERVER) m_populationsClient.reset(); #endif #if defined(US_MODULE_PROFILE) // This service MUST be reset AFTER m_eventClient because it hosts // an async result call performed during JobEventPostLogin. // The ~EventClient cancels the call. m_profileClient.reset(); #endif m_authenticationClient.reset(); // ...should be deleted after all services #if !defined(US_SDK_SERVER) // Reset must be done after the authentication client. // (however this does not prevent all teardown error cases!) m_connectionClient.reset(); // Reset must be done after the connection client since jobInitiateConnection uses the notificationClient. m_notificationClient.reset(); #endif m_parametersClient.reset(); #endif m_httpClient.reset(); // Critical sections need to be reset after connection client since JobManageConnection and JobInitiate connection // are trying to get either the websocket client or the HTTP client m_criticalSection.reset(); #if !defined(US_SDK_SERVER) // Delete the event client again since it is called in the post login operations, // i.e. by the authentication client, and may have been recreated // TODO: Find a way to avoid this hack. Clients should not be accessible // (and obviously not recreated) once they have been released. m_eventClient.reset(); #if !defined(US_SDK_SERVER) m_sessionManager->resetSessionInfo(); #endif #endif } void FacadeInternal::invalidate() { US_LOG(LogLevel::Debug, LogCategory::Core, "Invalidating facade."); deleteMembers(); // Set the state to invalid after deleting the members prevents ASSERTS. // By deleting the members, pending calls are canceled. The cancel process // may call some facade methods e.g. getAuthenticationClient().invalidateSessionInfo() // which assert if the facade is invalid. m_valid = false; } void FacadeInternal::stopFacade() { if (m_eventClient.get() != nullptr && m_eventClient->m_eventClientImpl.get() != nullptr) { m_eventClient->m_eventClientImpl->stopClient(); } } #if defined(US_SDK_SERVER) AsyncResult FacadeInternal::createSession(const String& secret, const Vector& parametersGroupApplication, const Vector& parametersGroupSpace) { US_PERF_TASK_FUNC(); return getAuthenticationClient().createSession(secret, parametersGroupApplication, parametersGroupSpace); } #else AsyncResult FacadeInternal::createSession(const PlayerCredentialsBase& credentials, const Vector& parametersGroupApplication, const Vector& parametersGroupSpace, const EventsParams& eventsParams , const String& connectionMetaData #if !defined(US_SDK_SERVER) , const DynamicPopulationCustomParams& populationParams #endif #if defined(US_PRIMARY_STORE_WITHOUT_API) , const PrimaryStoreParams& primaryStoreParams #endif ) { US_PERF_TASK_FUNC(); AsyncResultInternal result("FacadeInternal::createSession"); VALIDATE_SUSPENDED_MODE(result); return getAuthenticationClient().createSession(credentials, parametersGroupApplication, parametersGroupSpace, eventsParams #if !defined(US_SDK_SERVER) , connectionMetaData, populationParams #endif #if defined(US_PRIMARY_STORE_WITHOUT_API) , primaryStoreParams #endif ); } #endif AsyncResult FacadeInternal::deleteSession() { US_PERF_TASK_FUNC(); US_ASSERT(m_valid, INVALIDATE_CALLED_FACADE_INVALID); AsyncResultInternal result("FacadeInternal::deleteSession"); VALIDATE_SUSPENDED_MODE(result); #if !defined(US_SDK_SERVER) // Clearing the caches here (instead of JobDeleteSession) prevents from instantiating unused clients. CacheManager::invalidateCaches(*this); #endif return getAuthenticationClient().deleteSession(); } template _TClientType& FacadeInternal::getClient(::std::unique_ptr<_TClientType>& member) { US_ASSERT(m_valid, INVALIDATE_CALLED_FACADE_INVALID); //US_ASSERT(m_criticalSection.get() != nullptr, "FacadeInternal deleted?"); if (member.get() == nullptr) { ScopedCS cs(*m_criticalSection); if (member.get() == nullptr) { member.reset(US_NEW(_TClientType, *this)); } } return *member; } const SessionManager& FacadeInternal::getManager() const { return *m_sessionManager; } SessionManager& FacadeInternal::getManager() { return *m_sessionManager; } const Environment FacadeInternal::getDetectedEnvironment() const { return m_sessionManager->getDetectedEnvironment(&m_sessionManager->getSessionInfoRO()); } const RemoteLoggerSdk& FacadeInternal::getRemoteLoggerSdk() const { return *m_remoteLoggerSdk; } RemoteLoggerSdk& FacadeInternal::getRemoteLoggerSdk() { return *m_remoteLoggerSdk; } const RemoteLoggerCustom& FacadeInternal::getRemoteLoggerCustom() const { return *m_remoteLoggerCustom; } RemoteLoggerCustom& FacadeInternal::getRemoteLoggerCustom() { return *m_remoteLoggerCustom; } /// Client accessors - All flavors (including modules) #if defined(US_MODULE_APPLICATION) const ApplicationClient& FacadeInternal::getApplicationClient() const { return const_cast(*this).getClient(const_cast< ::std::unique_ptr& >(m_applicationClient)); } ApplicationClient& FacadeInternal::getApplicationClient() { return getClient(m_applicationClient); } #endif const AuthenticationClient& FacadeInternal::getAuthenticationClient() const { return const_cast(*this).getClient(const_cast< ::std::unique_ptr&>(m_authenticationClient)); } AuthenticationClient& FacadeInternal::getAuthenticationClient() { return getClient(m_authenticationClient); } #if defined(US_MODULE_BATTLEPASS) const BattlepassClient& FacadeInternal::getBattlepassClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_battlepassClient)); } BattlepassClient& FacadeInternal::getBattlepassClient() { return getClient(m_battlepassClient); } #endif #if defined(US_MODULE_BLOCKLIST) const BlocklistClient& FacadeInternal::getBlocklistClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_blocklistClient)); } BlocklistClient& FacadeInternal::getBlocklistClient() { return getClient(m_blocklistClient); } #endif #if defined(US_MODULE_CHALLENGE) const ChallengeClient& FacadeInternal::getChallengeClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_challengeClient)); } ChallengeClient& FacadeInternal::getChallengeClient() { return getClient(m_challengeClient); } #endif HttpClient& FacadeInternal::getHttpClient() { return getClient(m_httpClient); } const EventClient& FacadeInternal::getEventClient() const { return const_cast(*this).getClient(const_cast< ::std::unique_ptr&>(m_eventClient)); } EventClient& FacadeInternal::getEventClient() { #if defined(US_TARGET_ANDROID) || defined(US_TARGET_IOS) getClient(m_eventClient); m_eventClient->init(); return *m_eventClient; #else return getClient(m_eventClient); #endif } #if defined(US_MODULE_CLUB) ClubClient& FacadeInternal::getClubClient() { return getClient(m_clubClient); } #endif #if defined(US_MODULE_ENTITY) EntityClient& FacadeInternal::getEntityClient() { return getClient(m_entityClient); } #endif #if defined(US_MODULE_FRIEND) FriendClient& FacadeInternal::getFriendClient() { return getClient(m_friendClient); } #endif #if defined(US_MODULE_GAMESPLAYED) GamesPlayedClient& FacadeInternal::getGamesPlayedClient() { return getClient(m_gamesPlayedClient); } #endif #if defined(US_MODULE_LEADERBOARD) LeaderboardClient& FacadeInternal::getLeaderboardClient() { return getClient(m_leaderboardClient); } #endif #if defined(US_MODULE_LOCALIZATION) LocalizationClient& FacadeInternal::getLocalizationClient() { return getClient(m_localizationClient); } #endif #if defined(US_MODULE_MATCHMAKING) const MatchmakingClient& FacadeInternal::getMatchmakingClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_matchmakingClient)); } MatchmakingClient& FacadeInternal::getMatchmakingClient() { return getClient(m_matchmakingClient); } #endif #if defined(US_MODULE_MODERATION) const ModerationClient& FacadeInternal::getModerationClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_moderationClient)); } ModerationClient& FacadeInternal::getModerationClient() { return getClient(m_moderationClient); } #endif #if defined(US_MODULE_NEWS) NewsClient& FacadeInternal::getNewsClient() { return getClient(m_newsClient); } #endif const ParametersClient& FacadeInternal::getParametersClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_parametersClient)); } ParametersClient& FacadeInternal::getParametersClient() { return getClient(m_parametersClient); } #if defined(US_MODULE_PERSONA) const PersonaClient& FacadeInternal::getPersonaClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_personaClient)); } PersonaClient& FacadeInternal::getPersonaClient() { return getClient(m_personaClient); } #endif #if defined(US_MODULE_PLAYER_ONLINE_STATUS) const PlayerOnlineStatusClient& FacadeInternal::getPlayerOnlineStatusClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_playerOnlineStatusClient)); } PlayerOnlineStatusClient& FacadeInternal::getPlayerOnlineStatusClient() { return getClient(m_playerOnlineStatusClient); } #endif #if defined(US_MODULE_PLAYERREPORTS) const PlayerReportsClient & FacadeInternal::getPlayerReportsClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_playerReportsClient)); } PlayerReportsClient & FacadeInternal::getPlayerReportsClient() { return getClient(m_playerReportsClient); } #endif #if defined(US_MODULE_PROFILE) const ProfileClient& FacadeInternal::getProfileClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_profileClient)); } ProfileClient& FacadeInternal::getProfileClient() { return getClient(m_profileClient); } #endif #if defined(US_MODULE_SSI) SecondaryStoreInstantiationClient& FacadeInternal::getSecondaryStoreInstantiationClient() { return getClient(m_secondaryStoreInstantiationClient); } #endif #if defined(US_PRIMARY_STORE_ENABLED) || defined(US_PRIMARY_STORE_MOBILE_ENABLED) PrimaryStoreClient& FacadeInternal::getPrimaryStoreClient() { return getClient(m_primaryStoreClient); } #endif #if defined(US_MODULE_RECOMMENDATIONS) const RecommendationsClient& FacadeInternal::getRecommendationsClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_recommendationsClient)); } RecommendationsClient& FacadeInternal::getRecommendationsClient() { return getClient(m_recommendationsClient); } #endif RemoteLogClient& FacadeInternal::getRemoteLogClient() { return getClient(m_remoteLogClient); } #if defined(US_MODULE_STATS) StatsClient& FacadeInternal::getStatsClient() { return getClient(m_statsClient); } #endif #if defined(US_MODULE_STORE) SecondaryStoreClient& FacadeInternal::getSecondaryStoreClient() { return getClient(m_secondaryStoreClient); } #endif #if defined(US_MODULE_TLOG) && defined(US_TARGET_WINDOWS) TLogClient& FacadeInternal::getTLogClient() { return getClient(m_tLogClient); } #endif #if defined(US_ENABLE_UPLAY) UplayClient& FacadeInternal::getUplayClient() { return getClient(m_uplayClient); } #endif #if defined(US_MODULE_UGC) const UserGeneratedContentsClient& FacadeInternal::getUserGeneratedContentsClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_userGeneratedContentsClient)); } UserGeneratedContentsClient& FacadeInternal::getUserGeneratedContentsClient() { return getClient(m_userGeneratedContentsClient); } #endif #if defined(US_MODULE_USER) UserClient& FacadeInternal::getUserClient() { return getClient(m_userClient); } #endif #if defined(US_MODULE_VOICECHAT) VoicechatClient& FacadeInternal::getVoicechatClient() { return getClient(m_voicechatClient); } #endif #if defined(US_TARGET_STADIA) OverlayClient& FacadeInternal::getOverlayClient() { return getClient(m_overlayClient); } #endif // defined(US_TARGET_STADIA /// Client accessors - Client that shouldn't be in Server SDK #if !defined(US_SDK_SERVER) ConnectionClient& FacadeInternal::getConnectionClient() { return getClient(m_connectionClient); } NotificationClient& FacadeInternal::getNotificationClient() { return getClient(m_notificationClient); } const PopulationClient& FacadeInternal::getPopulationsClient() const { return const_cast(*this).getClient(const_cast<::std::unique_ptr&>(m_populationsClient)); } PopulationClient& FacadeInternal::getPopulationsClient() { return getClient(m_populationsClient); } WebSocketClient& FacadeInternal::getWebsocketClient() { return getClient(m_websocketClient); } #endif // !defined(US_SDK_SERVER) RemoteLoggerCustom& TestRemoteLogClientHelper::getRemoteLoggerCustom(FacadeInternal& facade) { return facade.getRemoteLoggerCustom(); } void TestExtendSessionHelper::reduceSessionDuration(Facade& facade, uint64 expirationTimeMs) { facade.m_facadeInternal->getManager().reduceSessionDuration(expirationTimeMs); } #if !defined(US_SDK_SERVER) int32 TestSuspendedModeHelper::getRefCount(const Facade& facade) { return facade.m_facadeInternal->getRefCount(); } int32 TestSuspendedModeHelper::getRefCount(const FacadeInternal& facade) { return facade.getRefCount(); } void TestSuspendedModeHelper::copyRef(SmartPtr& target, const Facade& source) { target = source.m_facadeInternal; } const HttpHeader& TestSuspendedModeHelper::getRemoteLoggerSdkHeaders(FacadeInternal& facade) { return facade.getRemoteLoggerSdk().m_remoteLogSession.getHeaders(); } #endif };