void FOnlineSessionInfoNull::Init(const FOnlineSubsystemNull& Subsystem) { // Read the IP from the system bool bCanBindAll; HostAddr = ISocketSubsystem::Get()->GetLocalHostAddr(*GLog, bCanBindAll); // The below is a workaround for systems that set hostname to a distinct address from 127.0.0.1 on a loopback interface. // See e.g. https://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_the_hostname_resolution // and http://serverfault.com/questions/363095/why-does-my-hostname-appear-with-the-address-127-0-1-1-rather-than-127-0-0-1-in // Since we bind to 0.0.0.0, we won't answer on 127.0.1.1, so we need to advertise ourselves as 127.0.0.1 for any other loopback address we may have. uint32 HostIp = 0; HostAddr->GetIp(HostIp); // will return in host order // if this address is on loopback interface, advertise it as 127.0.0.1 if ((HostIp & 0xff000000) == 0x7f000000) { HostAddr->SetIp(0x7f000001); // 127.0.0.1 } // Now set the port that was configured HostAddr->SetPort(GetPortFromNetDriver(Subsystem.GetInstanceName())); FGuid OwnerGuid; FPlatformMisc::CreateGuid(OwnerGuid); SessionId = FUniqueNetIdString(OwnerGuid.ToString()); }
bool FOnlineIdentityAmazon::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials) { bool bWasSuccessful = false; if (!bHasLoginOutstanding && AmazonEndpoint.Len() && RedirectUrl.Len() && ClientId.Len()) { State = FString::FromInt(FMath::Rand() % 100000); const FString& Command = FString::Printf(TEXT("%s?scope=profile&response_type=code&redirect_uri=%s&client_id=%s&state=%s"), *AmazonEndpoint, *RedirectUrl, *ClientId, *State); // This should open the browser with the command as the URL bHasLoginOutstanding = bWasSuccessful = FPlatformMisc::OsExecute(TEXT("open"), *Command); if (!bWasSuccessful) { UE_LOG(LogOnline, Error, TEXT("RegisterUser() : Failed to execute command %s "), *Command); } else { // keep track of local user requesting registration LocalUserNumPendingLogin = LocalUserNum; } } else { UE_LOG(LogOnline, Error, TEXT("RegisterUser() : OnlineSubsystemAmazon is improperly configured in DefaultEngine.ini")); } if (!bWasSuccessful) { TriggerOnLoginCompleteDelegates(LocalUserNum, false, FUniqueNetIdString(TEXT("")), FString(TEXT("RegisterUser() failed"))); } return bWasSuccessful; }
bool FOnlineIdentityGooglePlay::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials) { bool bStartedLogin = false; if (bLoggedIn) { // already logged in so just report all is ok! // Now logged in bStartedLogin = true; static const int32 MAX_TEXT_LINE_LEN = 32; TCHAR Line[MAX_TEXT_LINE_LEN + 1] = { 0 }; int32 Len = FCString::Snprintf(Line, MAX_TEXT_LINE_LEN, TEXT("%d"), LocalUserNum); const FString PlayerId(Line); UniqueNetId = MakeShareable(new FUniqueNetIdString(PlayerId)); TriggerOnLoginCompleteDelegates(LocalUserNum, true, *UniqueNetId, TEXT("")); } else if (!PendingConnectRequest.IsConnectionPending) { // Kick the login sequence... bStartedLogin = true; PendingConnectRequest.IsConnectionPending = true; } else { TriggerOnLoginCompleteDelegates(LocalUserNum, false, FUniqueNetIdString(TEXT("")), FString("Already trying to login")); } return bStartedLogin; }
void FOnlineIdentityAmazon::TickLogin(float DeltaTime) { if (bHasLoginOutstanding) { LastCheckElapsedTime += DeltaTime; TotalCheckElapsedTime += DeltaTime; // See if enough time has elapsed in order to check for completion if (LastCheckElapsedTime > 1.f || // Do one last check if we're getting ready to time out TotalCheckElapsedTime > MaxCheckElapsedTime) { LastCheckElapsedTime = 0.f; FString Title; if (FPlatformMisc::GetWindowTitleMatchingText(TEXT("accessToken"), Title)) { bHasLoginOutstanding = false; FUserOnlineAccountAmazon User; if (ParseLoginResults(Title, User)) { TSharedRef<FUserOnlineAccountAmazon> UserRef(new FUserOnlineAccountAmazon(User.UserId, User.SecretKey, User.AuthTicket)); UserAccounts.Add(User.UserId, UserRef); TriggerOnLoginCompleteDelegates(LocalUserNumPendingLogin, true, *UserRef->GetUserId(), FString()); } else { TriggerOnLoginCompleteDelegates(LocalUserNumPendingLogin, false, FUniqueNetIdString(TEXT("")), FString(TEXT("RegisterUser() failed to parse the user registration results"))); } } // Trigger the delegate if we hit the timeout limit else if (TotalCheckElapsedTime > MaxCheckElapsedTime) { bHasLoginOutstanding = false; TriggerOnLoginCompleteDelegates(LocalUserNumPendingLogin, false, FUniqueNetIdString(TEXT("")), FString(TEXT("RegisterUser() timed out without getting the data"))); } } // Reset our time trackers if we are done ticking for now if (!bHasLoginOutstanding) { LastCheckElapsedTime = 0.f; TotalCheckElapsedTime = 0.f; } } }
bool FOnlineIdentityNull::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials) { FString ErrorStr; TSharedPtr<FUserOnlineAccountNull> UserAccountPtr; // valid local player index if (LocalUserNum < 0 || LocalUserNum >= MAX_LOCAL_PLAYERS) { ErrorStr = FString::Printf(TEXT("Invalid LocalUserNum=%d"), LocalUserNum); } else if (AccountCredentials.Id.IsEmpty()) { ErrorStr = FString::Printf(TEXT("Invalid account id=%s"), *AccountCredentials.Id); } else { TSharedPtr<FUniqueNetId>* UserId = UserIds.Find(LocalUserNum); if (UserId == NULL) { FString RandomUserId = GenerateRandomUserId(LocalUserNum); FUniqueNetIdString NewUserId(RandomUserId); UserAccountPtr = MakeShareable(new FUserOnlineAccountNull(RandomUserId)); UserAccountPtr->UserAttributes.Add(TEXT("id"), RandomUserId); // update/add cached entry for user UserAccounts.Add(NewUserId, UserAccountPtr.ToSharedRef()); // keep track of user ids for local users UserIds.Add(LocalUserNum, UserAccountPtr->GetUserId()); } else { const FUniqueNetIdString* UniqueIdStr = (FUniqueNetIdString*)(UserId->Get()); TSharedRef<FUserOnlineAccountNull>* TempPtr = UserAccounts.Find(*UniqueIdStr); check(TempPtr); UserAccountPtr = *TempPtr; } } if (!ErrorStr.IsEmpty()) { UE_LOG_ONLINE(Warning, TEXT("Login request failed. %s"), *ErrorStr); TriggerOnLoginCompleteDelegates(LocalUserNum, false, FUniqueNetIdString(), ErrorStr); return false; } TriggerOnLoginCompleteDelegates(LocalUserNum, true, *UserAccountPtr->GetUserId(), ErrorStr); return true; }
bool FOnlineIdentityLeet::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials) { UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::Login")); FString ErrorStr; if (bHasLoginOutstanding) { ErrorStr = FString::Printf(TEXT("Registration already pending for user %d"), LocalUserNumPendingLogin); } else if (!(LoginUrl.Len() && LoginRedirectUrl.Len() && ClientId.Len())) { ErrorStr = FString::Printf(TEXT("OnlineSubsystemLeet is improperly configured in DefaultEngine.ini LeetEndpoint=%s RedirectUrl=%s ClientId=%s"), *LoginUrl, *LoginRedirectUrl, *ClientId); } else { // random number to represent client generated state for verification on login State = FString::FromInt(FMath::Rand() % 100000); // auth url to spawn in browser const FString& Command = FString::Printf(TEXT("%s?redirect_uri=%s&client_id=%s&state=%s&response_type=token"), *LoginUrl, *LoginRedirectUrl, *ClientId, *State); UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::Login - %s"), *LoginUrl); // This should open the browser with the command as the URL if (FPlatformMisc::OsExecute(TEXT("open"), *Command)) { // keep track of local user requesting registration LocalUserNumPendingLogin = LocalUserNum; bHasLoginOutstanding = true; } else { ErrorStr = FString::Printf(TEXT("Failed to execute command %s"), *Command); } } if (!ErrorStr.IsEmpty()) { UE_LOG(LogOnline, Error, TEXT("RegisterUser() failed: %s"), *ErrorStr); TriggerOnLoginCompleteDelegates(LocalUserNum, false, FUniqueNetIdString(TEXT("")), ErrorStr); return false; } return true; }
bool FOnlineIdentityNull::Logout(int32 LocalUserNum) { TSharedPtr<FUniqueNetId> UserId = GetUniquePlayerId(LocalUserNum); if (UserId.IsValid()) { // remove cached user account UserAccounts.Remove(FUniqueNetIdString(*UserId)); // remove cached user id UserIds.Remove(LocalUserNum); // not async but should call completion delegate anyway TriggerOnLogoutCompleteDelegates(LocalUserNum, true); return true; } else { UE_LOG_ONLINE(Warning, TEXT("No logged in user found for LocalUserNum=%d."), LocalUserNum); TriggerOnLogoutCompleteDelegates(LocalUserNum, false); } return false; }
/** * Ticks the registration process handling timeouts, etc. * * @param DeltaTime the amount of time that has elapsed since last tick */ void FOnlineIdentityLeet::TickLogin(float DeltaTime) { if (bHasLoginOutstanding) { //UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::TickLogin bHasLoginOutstanding")); LastCheckElapsedTime += DeltaTime; TotalCheckElapsedTime += DeltaTime; // See if enough time has elapsed in order to check for completion if (LastCheckElapsedTime > 1.f || // Do one last check if we're getting ready to time out TotalCheckElapsedTime > MaxCheckElapsedTime) { LastCheckElapsedTime = 0.f; FString Title; // Find the browser window we spawned which should now be titled with the redirect url if (FPlatformMisc::GetWindowTitleMatchingText(*LoginRedirectUrl, Title)) { UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::TickLogin GetWindowTitleMatchingText")); bHasLoginOutstanding = false; // Parse access token from the login redirect url FString AccessToken; if (FParse::Value(*Title, TEXT("access_token="), AccessToken) && !AccessToken.IsEmpty()) { UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::TickLogin Found access_token")); // strip off any url parameters and just keep the token itself FString AccessTokenOnly; if (AccessToken.Split(TEXT("&"), &AccessTokenOnly, NULL)) { AccessToken = AccessTokenOnly; } // kick off http request to get user info with the new token TSharedRef<class IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest(); LoginUserRequests.Add(&HttpRequest.Get(), FPendingLoginUser(LocalUserNumPendingLogin, AccessToken)); FString MeUrl = TEXT("https://leetsandbox.appspot.com/me?access_token=`token"); HttpRequest->OnProcessRequestComplete().BindRaw(this, &FOnlineIdentityLeet::MeUser_HttpRequestComplete); HttpRequest->SetURL(MeUrl.Replace(TEXT("`token"), *AccessToken, ESearchCase::IgnoreCase)); HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); HttpRequest->SetVerb(TEXT("GET")); HttpRequest->ProcessRequest(); } else { TriggerOnLoginCompleteDelegates(LocalUserNumPendingLogin, false, FUniqueNetIdString(TEXT("")), FString(TEXT("RegisterUser() failed to parse the user registration results"))); } } // Trigger the delegate if we hit the timeout limit else if (TotalCheckElapsedTime > MaxCheckElapsedTime) { bHasLoginOutstanding = false; TriggerOnLoginCompleteDelegates(LocalUserNumPendingLogin, false, FUniqueNetIdString(TEXT("")), FString(TEXT("RegisterUser() timed out without getting the data"))); } } // Reset our time trackers if we are done ticking for now if (!bHasLoginOutstanding) { LastCheckElapsedTime = 0.f; TotalCheckElapsedTime = 0.f; } } }
void FOnlineIdentityLeet::MeUser_HttpRequestComplete(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded) { UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::MeUser_HttpRequestComplete")); bool bResult = false; FString ResponseStr, ErrorStr; FUserOnlineAccountLeet User; FPendingLoginUser PendingRegisterUser = LoginUserRequests.FindRef(HttpRequest.Get()); // Remove the request from list of pending entries LoginUserRequests.Remove(HttpRequest.Get()); if (bSucceeded && HttpResponse.IsValid()) { ResponseStr = HttpResponse->GetContentAsString(); if (EHttpResponseCodes::IsOk(HttpResponse->GetResponseCode())) { UE_LOG(LogOnline, Verbose, TEXT("RegisterUser request complete. url=%s code=%d response=%s"), *HttpRequest->GetURL(), HttpResponse->GetResponseCode(), *ResponseStr); if (User.FromJson(ResponseStr)) { if (!User.UserId.IsEmpty()) { // copy and construct the unique id TSharedRef<FUserOnlineAccountLeet> UserRef(new FUserOnlineAccountLeet(User)); UserRef->UserIdPtr = MakeShareable(new FUniqueNetIdString(User.UserId)); // update/add cached entry for user UserAccounts.Add(User.UserId, UserRef); // update the access token UserRef->AuthTicket = PendingRegisterUser.AccessToken; // keep track of user ids for local users UserIds.Add(PendingRegisterUser.LocalUserNum, UserRef->GetUserId()); bResult = true; } else { ErrorStr = FString::Printf(TEXT("Missing user id. payload=%s"), *ResponseStr); } } else { ErrorStr = FString::Printf(TEXT("Invalid response payload=%s"), *ResponseStr); } } else { ErrorStr = FString::Printf(TEXT("Invalid response. code=%d error=%s"), HttpResponse->GetResponseCode(), *ResponseStr); } } else { ErrorStr = TEXT("No response"); } if (!ErrorStr.IsEmpty()) { UE_LOG(LogOnline, Warning, TEXT("RegisterUser request failed. %s"), *ErrorStr); } TriggerOnLoginCompleteDelegates(PendingRegisterUser.LocalUserNum, bResult, FUniqueNetIdString(User.UserId), ErrorStr); }
void FOnlineAchievementsGameCircle::QueryAchievements(const FUniqueNetId& PlayerId, const FOnQueryAchievementsCompleteDelegate& Delegate) { if(AndroidSubsystem->GetCallbackManager() == nullptr || AndroidSubsystem->GetIdentityGameCircle()->GetLoginStatus(0) != ELoginStatus::LoggedIn) { Delegate.ExecuteIfBound(PlayerId, false); return; } AmazonGames::AchievementsClientInterface::getAchievements(new FOnlineGetAchievementsCallback(AndroidSubsystem, FUniqueNetIdString(PlayerId), Delegate)); }