Documentation for the Unreal C++ Library
Loading...
Searching...
No Matches
PVROFindServerTask.cpp
Go to the documentation of this file.
1// Copyright(c) 2023 PixoVR, LLC. All Rights Reserved.
2
4#include "PVROnlineSession.h"
5#include "PVROSubsystem.h"
6#include "GameFramework/GameStateBase.h"
7#include "GameFramework/PlayerState.h"
8#include "OnlineSubsystemUtils.h"
9#include "SocketSubsystem.h"
10#include "Runtime/JsonUtilities/Public/JsonObjectConverter.h"
11#include "Interfaces/IPv4/IPv4Address.h"
12#include "HttpModule.h"
13#if ENGINE_MAJOR_VERSION >= 5
14#include "IPAddressAsyncResolve.h"
15#include "Online/OnlineSessionNames.h"
16#endif
17
18
20{
21 return FString::Printf(TEXT("FPVROFindServerTask bWasSuccessful: %d Results: %d"), WasSuccessful(), SearchSettings->SearchResults.Num());
22}
23
25{
26 TSharedRef<IHttpRequest, ESPMode::ThreadSafe> HTTPRequest = FHttpModule::Get().CreateRequest();
27 HTTPRequest->OnProcessRequestComplete().BindRaw(this, &FPVROFindServerTask::OnRequestSessionResponseReceived);
28 HTTPRequest->SetURL(FPVROAsyncTaskManager::ServerURL / TEXT("RequestSession"));
29 HTTPRequest->SetVerb("GET");
30
31 FPVROMPSessionRequestInfo SessionRequestInfo {};
32
33 int ModuleId = 0;
34 // OK, we failed to find the module version reading from the terminal. Let's check the ini files.
35 GConfig->GetInt(TEXT("/Script/ApexSDK.ApexSDKSettings"), TEXT("ModuleId"), ModuleId, GEngineIni);
36
37 int OrgID = 0;
38 SearchSettings->QuerySettings.Get<int>(FName(TEXT("OrgID")), OrgID);
39
40 SessionRequestInfo.ModuleID = ModuleId;
41 SessionRequestInfo.ModuleVersion = FPVROAsyncTaskManager::ServerVersion;
42
43 UE_LOG(LogTemp, Warning, TEXT("Request to find Session: ModuleID: %d, OrgID: N/A, Version: %s, Client: %s"),
44 SessionRequestInfo.ModuleID, *SessionRequestInfo.ModuleVersion, *SessionRequestInfo.ClientID);
45
46 HTTPRequest->ProcessRequest();
47 SessionSearchStartInSeconds = FPlatformTime::Seconds();
48}
49
54
55void FPVROFindServerTask::OnRequestSessionResponseReceived(FHttpRequestPtr HTTPRequest, FHttpResponsePtr HTTPResponse, bool InWasSuccessful)
56{
57 if (InWasSuccessful)
58 {
59 PingInMs = static_cast<int32>((FPlatformTime::Seconds() - SessionSearchStartInSeconds) * 1000);
60
61 ServerInfos = {};
62 ServerInfos.FromJson(HTTPResponse->GetContentAsString());
63
65 {
67 {
68 UE_LOG_ONLINE(Warning, TEXT("PixoVR Master Service Started new Dedicated Server: %s"), *ServerInfos.Reply);
70 }
71 else
72 {
73 Counter++;
74 }
75
77 }
79 {
80 UE_LOG_ONLINE(Warning, TEXT("Failed due to invalid ModuleID."));
81
84 }
85 else if(ServerInfos.Reply == ReplyOK)
86 {
87 for(auto& Server : ServerInfos.CurrentSessions)
88 {
89 UE_LOG_ONLINE(Warning, TEXT("IPAddress: %s"), *Server.IPAddress);
90 UE_LOG_ONLINE(Warning, TEXT("Port: %s"), *Server.Port);
91 UE_LOG_ONLINE(Warning, TEXT("SessionID: %s"), *Server.SessionID);
92 UE_LOG_ONLINE(Warning, TEXT("MapName: %s"), *Server.MapName);
93 UE_LOG_ONLINE(Warning, TEXT("OwningUserName: %s"), *Server.OwningUserName);
94 }
95
98 }
99 else
100 {
102 bDedicatedServerStart = false;
103 }
104 }
105 else
106 {
108 }
109}
110
112{
113 // ATTN Yaakuro: Don't know why but bIsComplete and bWasSuccessful needs to be set inside this tick else it will not work.
115 {
116 bIsComplete = true;
117 bWasSuccessful = true;
118 bDedicatedServerStart = false;
119 }
121 {
122 bIsComplete = true;
123 bWasSuccessful = false;
124 bDedicatedServerStart = false;
125 }
127 {
128 // Check if PixoVR Master Service had to start a new Dedicated Server. If yes, wait a bit.
130 {
132 {
133 UE_LOG_ONLINE(Warning, TEXT("Failed to find any Sessions."));
134
135 bIsComplete = true;
136 bWasSuccessful = false;
137 bDedicatedServerStart = false;
138 }
139 else
140 {
141 double dT = (FPlatformTime::Seconds() - GStartTime) - DedicatedServerAquireStart;
143 {
144 UE_LOG_ONLINE(Warning, TEXT("Sending another Request: %d"), Counter);
145
147 DedicatedServerAquireStart = (FPlatformTime::Seconds() - GStartTime);
148 }
149 }
150 }
151 }
153 {
154 UE_LOG_ONLINE(Warning, TEXT("HTTP request invalid."), Counter);
155
156 bIsComplete = true;
157 bWasSuccessful = false;
158 bDedicatedServerStart = false;
159 }
160 else
161 {
162 // Should never happen.
163 check(0);
164 }
165}
166
168{
169 FPVROnlineSessionPtr SessionInt = StaticCastSharedPtr<FPVROnlineSession>(Subsystem->GetSessionInterface());
170 SearchSettings->SearchState = bWasSuccessful ? EOnlineAsyncTaskState::Done : EOnlineAsyncTaskState::Failed;
171 SessionInt->CurrentSessionSearch->SearchState = bWasSuccessful ? EOnlineAsyncTaskState::Done : EOnlineAsyncTaskState::Failed;
172
173 if (bWasSuccessful)
174 {
175 for(auto& Server : ServerInfos.CurrentSessions)
176 {
177 FOnlineSessionSearchResult* NewResult = new (SessionInt->CurrentSessionSearch->SearchResults) FOnlineSessionSearchResult();
178 NewResult->PingInMs = PingInMs;
179 FOnlineSession* NewSession = &NewResult->Session;
180
181 FPVROSessionInfo* PixoVRSessionInfo = new FPVROSessionInfo();
182 PixoVRSessionInfo->HostAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
183
184 int32 HostAddress = 0;
185 int32 HostPort = 0;
186
187 GetHostAndPort(HostAddress, HostPort, Server.IPAddress, Server.Port);
188 PixoVRSessionInfo->HostAddr->SetIp(HostAddress);
189 PixoVRSessionInfo->HostAddr->SetPort(HostPort);
190 NewSession->SessionSettings.Set(SETTING_MAPNAME, Server.MapName);
191 NewSession->OwningUserName = Server.OwningUserName;
192 NewSession->SessionInfo = MakeShareable(PixoVRSessionInfo);
193
194
195 // Allow game code to sort the servers
196 SearchSettings->SortSearchResults();
197 }
198 }
199
200 SessionInt->CurrentSessionSearch = NULL;
201}
202
204{
205 // TODO Yaakuro: For now we rely on timout to get to the JoinSession task.
206 if (FindServersCompleteDelegates.IsBound())
207 {
208 FindServersCompleteDelegates.Broadcast(bWasSuccessful);
209 }
210}
211
212void FPVROFindServerTask::GetHostAndPort(int32& Host, int32& Port, const FString& HostIP, const FString& HostPort)
213{
214 // Convert the HostAddress and Port into their appropriate forms.
215 FIPv4Address HostAddress;
216 bool Result = FIPv4Address::Parse(HostIP, HostAddress);
217 if(!Result)
218 {
219 ISocketSubsystem* SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
220 if(SocketSubsystem)
221 {
222 FResolveInfo* ResolveInfo = SocketSubsystem->GetHostByName(TCHAR_TO_ANSI(*HostIP));
223 while (!ResolveInfo->IsComplete());
224 if (ResolveInfo->GetErrorCode() == 0)
225 {
226 const FInternetAddr* Address = &ResolveInfo->GetResolvedAddress();
227 uint32 IP = 0;
228 Address->GetIp(IP);
229 Host = FIPv4Address(IP).Value;
230 }
231 }
232 else
233 {
234 // TODO SocketSubsystem issue?
235 UE_LOG(LogTemp, Warning, TEXT("FindSession: No SocketSubsystem found."));
236 }
237 }
238 else
239 {
240 Host = HostAddress.Value;
241 }
242
243 // +1 is a workaround because this implementation uses 2 ports for communication. The user shouldn't bother
244 // to add this inside the BP or config files.
245 Port = FCString::Atoi(*HostPort);
246}
const FString ReplyOK
const FString ReplyPending
const FString ReplyInvalidModuleID
TSharedPtr< FPVROnlineSession, ESPMode::ThreadSafe > FPVROnlineSessionPtr
TSharedPtr< class FOnlineSessionSearch > SearchSettings
virtual FString ToString() const override
virtual void Finalize() override
EPVRORequestSessionsReply bFoundSessions
FOnAsyncFindServersComplete FindServersCompleteDelegates
void OnRequestSessionResponseReceived(FHttpRequestPtr HTTPRequest, FHttpResponsePtr HTTPResponse, bool InWasSuccessful)
FPVROMPRequestServerInfo ServerInfos
virtual void Initialize() override
virtual void Tick() override
void GetHostAndPort(int32 &Host, int32 &Port, const FString &HostIP, const FString &HostPort)
virtual void TriggerDelegates() override
TSharedPtr< class FInternetAddr > HostAddr
TArray< FPVROMPSessionInfo > CurrentSessions