Simplify http error handling in the launcher

This commit is contained in:
UnknownShadow200 2022-12-01 20:23:27 +11:00
parent 6761389db3
commit 2d8fe376f2
7 changed files with 87 additions and 83 deletions

View File

@ -706,12 +706,12 @@ CC_NOINLINE static void MainScreen_GetResume(struct ResumeInfo* info, cc_bool fu
info->ip.length && info->port.length; info->ip.length && info->port.length;
} }
CC_NOINLINE static void MainScreen_Error(struct LWebTask* task, const char* action) { CC_NOINLINE static void MainScreen_Error(struct HttpRequest* req, const char* action) {
cc_string str; char strBuffer[STRING_SIZE]; cc_string str; char strBuffer[STRING_SIZE];
struct MainScreen* s = &MainScreen; struct MainScreen* s = &MainScreen;
String_InitArray(str, strBuffer); String_InitArray(str, strBuffer);
LWebTask_DisplayError(task, action, &str); Launcher_DisplayHttpError(req, action, &str);
LLabel_SetText(&s->lblStatus, &str); LLabel_SetText(&s->lblStatus, &str);
s->signingIn = false; s->signingIn = false;
} }
@ -858,7 +858,7 @@ static void MainScreen_TickCheckUpdates(struct MainScreen* s) {
cc_uint32 latest, current; cc_uint32 latest, current;
if (!CheckUpdateTask.Base.working) return; if (!CheckUpdateTask.Base.working) return;
LWebTask_Tick(&CheckUpdateTask.Base); LWebTask_Tick(&CheckUpdateTask.Base, NULL);
if (!CheckUpdateTask.Base.completed) return; if (!CheckUpdateTask.Base.completed) return;
if (CheckUpdateTask.Base.success) { if (CheckUpdateTask.Base.success) {
@ -881,15 +881,16 @@ static void MainScreen_LoginPhase2(struct MainScreen* s, const cc_string* user)
LLabel_SetConst(&s->lblStatus, "&eRetrieving servers list.."); LLabel_SetConst(&s->lblStatus, "&eRetrieving servers list..");
} }
static void MainScreen_SignInError(struct HttpRequest* req) {
MainScreen_Error(req, "signing in");
}
static void MainScreen_TickGetToken(struct MainScreen* s) { static void MainScreen_TickGetToken(struct MainScreen* s) {
if (!GetTokenTask.Base.working) return; if (!GetTokenTask.Base.working) return;
LWebTask_Tick(&GetTokenTask.Base); LWebTask_Tick(&GetTokenTask.Base, MainScreen_SignInError);
if (!GetTokenTask.Base.completed) return;
if (!GetTokenTask.Base.success) { if (!GetTokenTask.Base.completed) return;
MainScreen_Error(&GetTokenTask.Base, "signing in"); if (!GetTokenTask.Base.success) return;
return;
}
if (!GetTokenTask.error && String_CaselessEquals(&GetTokenTask.username, &s->iptUsername.text)) { if (!GetTokenTask.error && String_CaselessEquals(&GetTokenTask.username, &s->iptUsername.text)) {
/* Already logged in, go straight to fetching servers */ /* Already logged in, go straight to fetching servers */
@ -902,7 +903,7 @@ static void MainScreen_TickGetToken(struct MainScreen* s) {
static void MainScreen_TickSignIn(struct MainScreen* s) { static void MainScreen_TickSignIn(struct MainScreen* s) {
if (!SignInTask.Base.working) return; if (!SignInTask.Base.working) return;
LWebTask_Tick(&SignInTask.Base); LWebTask_Tick(&SignInTask.Base, MainScreen_SignInError);
if (!SignInTask.Base.completed) return; if (!SignInTask.Base.completed) return;
if (SignInTask.needMFA) { MFAScreen_SetActive(); return; } if (SignInTask.needMFA) { MFAScreen_SetActive(); return; }
@ -911,20 +912,19 @@ static void MainScreen_TickSignIn(struct MainScreen* s) {
LLabel_SetConst(&s->lblStatus, SignInTask.error); LLabel_SetConst(&s->lblStatus, SignInTask.error);
} else if (SignInTask.Base.success) { } else if (SignInTask.Base.success) {
MainScreen_LoginPhase2(s, &SignInTask.username); MainScreen_LoginPhase2(s, &SignInTask.username);
} else {
MainScreen_Error(&SignInTask.Base, "signing in");
} }
} }
static void MainScreen_ServersError(struct HttpRequest* req) {
MainScreen_Error(req, "retrieving servers list");
}
static void MainScreen_TickFetchServers(struct MainScreen* s) { static void MainScreen_TickFetchServers(struct MainScreen* s) {
if (!FetchServersTask.Base.working) return; if (!FetchServersTask.Base.working) return;
LWebTask_Tick(&FetchServersTask.Base); LWebTask_Tick(&FetchServersTask.Base, MainScreen_ServersError);
if (!FetchServersTask.Base.completed) return;
if (!FetchServersTask.Base.success) { if (!FetchServersTask.Base.completed) return;
MainScreen_Error(&FetchServersTask.Base, "retrieving servers list"); if (!FetchServersTask.Base.success) return;
return;
}
s->signingIn = false; s->signingIn = false;
if (Launcher_AutoHash.length) { if (Launcher_AutoHash.length) {
@ -1078,7 +1078,19 @@ static void FetchResourcesScreen_Init(struct LScreen* s_) {
s->btnCancel.OnClick = CheckResourcesScreen_Next; s->btnCancel.OnClick = CheckResourcesScreen_Next;
} }
static void FetchResourcesScreen_Show(struct LScreen* s_) { Fetcher_Run(); }
static void FetchResourcesScreen_Error(struct HttpRequest* req) {
cc_string str; char buffer[STRING_SIZE];
String_InitArray(str, buffer);
Launcher_DisplayHttpError(req, "downloading resources", &str);
LLabel_SetText(&FetchResourcesScreen.lblStatus, &str);
}
static void FetchResourcesScreen_Show(struct LScreen* s_) {
Fetcher_ErrorCallback = FetchResourcesScreen_Error;
Fetcher_Run();
}
static void FetchResourcesScreen_UpdateStatus(struct FetchResourcesScreen* s, int reqID) { static void FetchResourcesScreen_UpdateStatus(struct FetchResourcesScreen* s, int reqID) {
cc_string str; char strBuffer[STRING_SIZE]; cc_string str; char strBuffer[STRING_SIZE];
@ -1107,14 +1119,6 @@ static void FetchResourcesScreen_UpdateProgress(struct FetchResourcesScreen* s)
LSlider_SetProgress(&s->sdrProgress, progress); LSlider_SetProgress(&s->sdrProgress, progress);
} }
static void FetchResourcesScreen_Error(struct FetchResourcesScreen* s) {
cc_string str; char buffer[STRING_SIZE];
String_InitArray(str, buffer);
Launcher_DisplayHttpError(Fetcher_Result, Fetcher_StatusCode, "downloading resources", &str);
LLabel_SetText(&s->lblStatus, &str);
}
static void FetchResourcesScreen_Tick(struct LScreen* s_) { static void FetchResourcesScreen_Tick(struct LScreen* s_) {
struct FetchResourcesScreen* s = (struct FetchResourcesScreen*)s_; struct FetchResourcesScreen* s = (struct FetchResourcesScreen*)s_;
if (!Fetcher_Working) return; if (!Fetcher_Working) return;
@ -1123,7 +1127,7 @@ static void FetchResourcesScreen_Tick(struct LScreen* s_) {
Fetcher_Update(); Fetcher_Update();
if (!Fetcher_Completed) return; if (!Fetcher_Completed) return;
if (Fetcher_Failed) { FetchResourcesScreen_Error(s); return; } if (Fetcher_Failed) return;
Launcher_TryLoadTexturePack(); Launcher_TryLoadTexturePack();
CheckResourcesScreen_Next(NULL); CheckResourcesScreen_Next(NULL);
@ -1274,11 +1278,11 @@ static void ServersScreen_Tick(struct LScreen* s_) {
LScreen_Tick(s_); LScreen_Tick(s_);
count = FetchFlagsTask.count; count = FetchFlagsTask.count;
LWebTask_Tick(&FetchFlagsTask.Base); LWebTask_Tick(&FetchFlagsTask.Base, NULL);
if (count != FetchFlagsTask.count) LBackend_TableFlagAdded(&s->table); if (count != FetchFlagsTask.count) LBackend_TableFlagAdded(&s->table);
if (!FetchServersTask.Base.working) return; if (!FetchServersTask.Base.working) return;
LWebTask_Tick(&FetchServersTask.Base); LWebTask_Tick(&FetchServersTask.Base, NULL);
if (!FetchServersTask.Base.completed) return; if (!FetchServersTask.Base.completed) return;
if (FetchServersTask.Base.success) { if (FetchServersTask.Base.success) {
@ -1644,7 +1648,7 @@ static void UpdatesScreen_Get(cc_bool release, int buildIndex) {
static void UpdatesScreen_CheckTick(struct UpdatesScreen* s) { static void UpdatesScreen_CheckTick(struct UpdatesScreen* s) {
if (!CheckUpdateTask.Base.working) return; if (!CheckUpdateTask.Base.working) return;
LWebTask_Tick(&CheckUpdateTask.Base); LWebTask_Tick(&CheckUpdateTask.Base, NULL);
if (!CheckUpdateTask.Base.completed) return; if (!CheckUpdateTask.Base.completed) return;
UpdatesScreen_FormatBoth(s); UpdatesScreen_FormatBoth(s);
@ -1665,23 +1669,25 @@ static void UpdatesScreen_UpdateProgress(struct UpdatesScreen* s, struct LWebTas
LLabel_SetText(&s->lblStatus, &str); LLabel_SetText(&s->lblStatus, &str);
} }
static void UpdatesScreen_FetchTick(struct UpdatesScreen* s) { static void FetchUpdatesError(struct HttpRequest* req) {
cc_string str; char strBuffer[STRING_SIZE]; cc_string str; char strBuffer[STRING_SIZE];
String_InitArray(str, strBuffer);
Launcher_DisplayHttpError(req, "fetching update", &str);
LLabel_SetText(&UpdatesScreen.lblStatus, &str);
}
static void UpdatesScreen_FetchTick(struct UpdatesScreen* s) {
if (!FetchUpdateTask.Base.working) return; if (!FetchUpdateTask.Base.working) return;
LWebTask_Tick(&FetchUpdateTask.Base); LWebTask_Tick(&FetchUpdateTask.Base, FetchUpdatesError);
UpdatesScreen_UpdateProgress(s, &FetchUpdateTask.Base); UpdatesScreen_UpdateProgress(s, &FetchUpdateTask.Base);
if (!FetchUpdateTask.Base.completed) return; if (!FetchUpdateTask.Base.completed) return;
if (!FetchUpdateTask.Base.success) { if (!FetchUpdateTask.Base.success) return;
String_InitArray(str, strBuffer); /* FetchUpdateTask handles saving the updated file for us */
LWebTask_DisplayError(&FetchUpdateTask.Base, "fetching update", &str); Launcher_ShouldExit = true;
LLabel_SetText(&s->lblStatus, &str); Launcher_ShouldUpdate = true;
} else {
/* FetchUpdateTask handles saving the updated file for us */
Launcher_ShouldExit = true;
Launcher_ShouldUpdate = true;
}
} }
static void UpdatesScreen_Rel_0(void* w) { UpdatesScreen_Get(true, 0); } static void UpdatesScreen_Rel_0(void* w) { UpdatesScreen_Get(true, 0); }

View File

@ -212,29 +212,23 @@ static void LWebTask_Reset(struct LWebTask* task) {
task->completed = false; task->completed = false;
task->working = true; task->working = true;
task->success = false; task->success = false;
task->res = 0;
task->status = 0;
} }
void LWebTask_Tick(struct LWebTask* task) { void LWebTask_Tick(struct LWebTask* task, LWebTask_ErrorCallback errorCallback) {
struct HttpRequest req; struct HttpRequest req;
if (task->completed) return; if (task->completed) return;
if (!Http_GetResult(task->reqID, &req)) return; if (!Http_GetResult(task->reqID, &req)) return;
task->res = req.result;
task->status = req.statusCode;
task->working = false; task->working = false;
task->completed = true; task->completed = true;
task->success = req.success; task->success = req.success;
if (!req.success) return; if (req.success) {
task->Handle((cc_uint8*)req.data, req.size); task->Handle((cc_uint8*)req.data, req.size);
Mem_Free(req.data); Mem_Free(req.data);
} } else if (errorCallback) {
errorCallback(&req);
void LWebTask_DisplayError(struct LWebTask* task, const char* action, cc_string* dst) { }
Launcher_DisplayHttpError(task->res, task->status, action, dst);
} }
void LWebTasks_Init(void) { void LWebTasks_Init(void) {

View File

@ -6,6 +6,7 @@
Copyright 2014-2022 ClassiCube | Licensed under BSD-3 Copyright 2014-2022 ClassiCube | Licensed under BSD-3
*/ */
struct HttpRequest;
struct JsonContext; struct JsonContext;
typedef void (*JsonOnValue)(struct JsonContext* ctx, const cc_string* v); typedef void (*JsonOnValue)(struct JsonContext* ctx, const cc_string* v);
typedef void (*JsonOnNew)(struct JsonContext* ctx); typedef void (*JsonOnNew)(struct JsonContext* ctx);
@ -53,15 +54,14 @@ struct LWebTask {
cc_bool completed; /* Whether the task has finished executing. */ cc_bool completed; /* Whether the task has finished executing. */
cc_bool working; /* Whether the task is currently in progress, or is scheduled to be. */ cc_bool working; /* Whether the task is currently in progress, or is scheduled to be. */
cc_bool success; /* Whether the task completed successfully. */ cc_bool success; /* Whether the task completed successfully. */
cc_result res; /* Error returned (e.g. for DNS failure) */
int status; /* HTTP return code for the request */
int reqID; /* Unique request identifier for this web task. */ int reqID; /* Unique request identifier for this web task. */
/* Called when task successfully downloaded/uploaded data. */ /* Called when task successfully downloaded/uploaded data. */
void (*Handle)(cc_uint8* data, cc_uint32 len); void (*Handle)(cc_uint8* data, cc_uint32 len);
}; };
void LWebTask_Tick(struct LWebTask* task); typedef void (*LWebTask_ErrorCallback)(struct HttpRequest* req);
void LWebTask_DisplayError(struct LWebTask* task, const char* action, cc_string* dst);
void LWebTask_Tick(struct LWebTask* task, LWebTask_ErrorCallback errorCallback);
void LWebTasks_Init(void); void LWebTasks_Init(void);

View File

@ -53,7 +53,10 @@ void Launcher_SetScreen(struct LScreen* screen) {
LBackend_Redraw(); LBackend_Redraw();
} }
void Launcher_DisplayHttpError(cc_result res, int status, const char* action, cc_string* dst) { void Launcher_DisplayHttpError(struct HttpRequest* req, const char* action, cc_string* dst) {
cc_result res = req->result;
int status = req->statusCode;
if (res) { if (res) {
/* Non HTTP error - this is not good */ /* Non HTTP error - this is not good */
Logger_Warn(res, action, Http_DescribeError); Logger_Warn(res, action, Http_DescribeError);
@ -120,9 +123,13 @@ CC_NOINLINE static void StartFromInfo(struct ServerInfo* info) {
Launcher_StartGame(&Launcher_Username, &info->mppass, &info->ip, &port, &info->name); Launcher_StartGame(&Launcher_Username, &info->mppass, &info->ip, &port, &info->name);
} }
static void ConnectToServerError(struct HttpRequest* req) {
cc_string logMsg = String_Init(NULL, 0, 0);
Launcher_DisplayHttpError(req, "fetching server info", &logMsg);
}
cc_bool Launcher_ConnectToServer(const cc_string* hash) { cc_bool Launcher_ConnectToServer(const cc_string* hash) {
struct ServerInfo* info; struct ServerInfo* info;
cc_string logMsg;
int i; int i;
if (!hash->length) return false; if (!hash->length) return false;
@ -139,7 +146,7 @@ cc_bool Launcher_ConnectToServer(const cc_string* hash) {
FetchServerTask_Run(hash); FetchServerTask_Run(hash);
while (!FetchServerTask.Base.completed) { while (!FetchServerTask.Base.completed) {
LWebTask_Tick(&FetchServerTask.Base); LWebTask_Tick(&FetchServerTask.Base, ConnectToServerError);
Thread_Sleep(10); Thread_Sleep(10);
} }
@ -148,9 +155,6 @@ cc_bool Launcher_ConnectToServer(const cc_string* hash) {
return true; return true;
} else if (FetchServerTask.Base.success) { } else if (FetchServerTask.Base.success) {
Window_ShowDialog("Failed to connect", "No server has that hash"); Window_ShowDialog("Failed to connect", "No server has that hash");
} else {
logMsg = String_Init(NULL, 0, 0);
LWebTask_DisplayError(&FetchServerTask.Base, "fetching server info", &logMsg);
} }
return false; return false;
} }

View File

@ -75,6 +75,6 @@ void Launcher_Run(void);
/* Starts the game from the given arguments. */ /* Starts the game from the given arguments. */
cc_bool Launcher_StartGame(const cc_string* user, const cc_string* mppass, const cc_string* ip, const cc_string* port, const cc_string* server); cc_bool Launcher_StartGame(const cc_string* user, const cc_string* mppass, const cc_string* ip, const cc_string* port, const cc_string* server);
/* Prints information about a http error to dst. (for status widget) */ /* Prints information about a http error to dst. (for status widget) */
/* If res is non-zero, also displays a dialog box on-screen. */ /* If req->result is non-zero, also displays a dialog box on-screen. */
void Launcher_DisplayHttpError(cc_result res, int status, const char* action, cc_string* dst); void Launcher_DisplayHttpError(struct HttpRequest* req, const char* action, cc_string* dst);
#endif #endif

View File

@ -778,8 +778,8 @@ void Resources_CheckExistence(void) {
*-----------------------------------------------------------Fetcher-------------------------------------------------------* *-----------------------------------------------------------Fetcher-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
cc_bool Fetcher_Working, Fetcher_Completed, Fetcher_Failed; cc_bool Fetcher_Working, Fetcher_Completed, Fetcher_Failed;
int Fetcher_StatusCode, Fetcher_Downloaded; int Fetcher_Downloaded;
cc_result Fetcher_Result; FetcherErrorCallback Fetcher_ErrorCallback;
const char* Fetcher_RequestName(int reqID) { const char* Fetcher_RequestName(int reqID) {
int i; int i;
@ -845,9 +845,10 @@ CC_NOINLINE static cc_bool Fetcher_Get(int reqID, struct HttpRequest* req) {
return true; return true;
} }
Fetcher_Failed = true; /* Only show error for first failed download */
Fetcher_Result = req->result; if (!Fetcher_Failed) Fetcher_ErrorCallback(req);
Fetcher_StatusCode = req->statusCode; Fetcher_Failed = true;
Fetcher_Finish(); Fetcher_Finish();
return false; return false;
} }

View File

@ -4,26 +4,25 @@
/* Implements checking, fetching, and patching the default game assets. /* Implements checking, fetching, and patching the default game assets.
Copyright 2014-2022 ClassiCube | Licensed under BSD-3 Copyright 2014-2022 ClassiCube | Licensed under BSD-3
*/ */
typedef void (*FetcherErrorCallback)(struct HttpRequest* req);
/* Number of resources that need to be downloaded. */ /* Number of resources that need to be downloaded */
extern int Resources_Count; extern int Resources_Count;
/* Total size of resources that need to be downloaded. */ /* Total size of resources that need to be downloaded */
extern int Resources_Size; extern int Resources_Size;
/* Checks existence of all assets. */ /* Checks existence of all assets */
void Resources_CheckExistence(void); void Resources_CheckExistence(void);
/* Whether fetcher is currently downloading resources. */ /* Whether fetcher is currently downloading resources */
extern cc_bool Fetcher_Working; extern cc_bool Fetcher_Working;
/* Whether fetcher has finished. (downloaded all resources, or an error) */ /* Whether fetcher has finished (downloaded all resources, or an error) */
extern cc_bool Fetcher_Completed; extern cc_bool Fetcher_Completed;
/* Number of resources that have been downloaded so far. */ /* Number of resources that have been downloaded so far */
extern int Fetcher_Downloaded; extern int Fetcher_Downloaded;
/* HTTP status code of last failed resource download */ /* Whether a resource failed to download */
extern int Fetcher_StatusCode;
/* Error code of last failed resource download. */
extern cc_result Fetcher_Result;
/* Whether a resource failed to download. */
extern cc_bool Fetcher_Failed; extern cc_bool Fetcher_Failed;
/* Callback function invoked if a resource fails to download */
extern FetcherErrorCallback Fetcher_ErrorCallback;
/* Finds name of resource associated with given http request. */ /* Finds name of resource associated with given http request. */
const char* Fetcher_RequestName(int reqID); const char* Fetcher_RequestName(int reqID);