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;
}
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];
struct MainScreen* s = &MainScreen;
String_InitArray(str, strBuffer);
LWebTask_DisplayError(task, action, &str);
Launcher_DisplayHttpError(req, action, &str);
LLabel_SetText(&s->lblStatus, &str);
s->signingIn = false;
}
@ -858,7 +858,7 @@ static void MainScreen_TickCheckUpdates(struct MainScreen* s) {
cc_uint32 latest, current;
if (!CheckUpdateTask.Base.working) return;
LWebTask_Tick(&CheckUpdateTask.Base);
LWebTask_Tick(&CheckUpdateTask.Base, NULL);
if (!CheckUpdateTask.Base.completed) return;
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..");
}
static void MainScreen_SignInError(struct HttpRequest* req) {
MainScreen_Error(req, "signing in");
}
static void MainScreen_TickGetToken(struct MainScreen* s) {
if (!GetTokenTask.Base.working) return;
LWebTask_Tick(&GetTokenTask.Base);
if (!GetTokenTask.Base.completed) return;
LWebTask_Tick(&GetTokenTask.Base, MainScreen_SignInError);
if (!GetTokenTask.Base.success) {
MainScreen_Error(&GetTokenTask.Base, "signing in");
return;
}
if (!GetTokenTask.Base.completed) return;
if (!GetTokenTask.Base.success) return;
if (!GetTokenTask.error && String_CaselessEquals(&GetTokenTask.username, &s->iptUsername.text)) {
/* 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) {
if (!SignInTask.Base.working) return;
LWebTask_Tick(&SignInTask.Base);
LWebTask_Tick(&SignInTask.Base, MainScreen_SignInError);
if (!SignInTask.Base.completed) return;
if (SignInTask.needMFA) { MFAScreen_SetActive(); return; }
@ -911,20 +912,19 @@ static void MainScreen_TickSignIn(struct MainScreen* s) {
LLabel_SetConst(&s->lblStatus, SignInTask.error);
} else if (SignInTask.Base.success) {
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) {
if (!FetchServersTask.Base.working) return;
LWebTask_Tick(&FetchServersTask.Base);
if (!FetchServersTask.Base.completed) return;
LWebTask_Tick(&FetchServersTask.Base, MainScreen_ServersError);
if (!FetchServersTask.Base.success) {
MainScreen_Error(&FetchServersTask.Base, "retrieving servers list");
return;
}
if (!FetchServersTask.Base.completed) return;
if (!FetchServersTask.Base.success) return;
s->signingIn = false;
if (Launcher_AutoHash.length) {
@ -1078,7 +1078,19 @@ static void FetchResourcesScreen_Init(struct LScreen* s_) {
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) {
cc_string str; char strBuffer[STRING_SIZE];
@ -1107,14 +1119,6 @@ static void FetchResourcesScreen_UpdateProgress(struct FetchResourcesScreen* s)
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_) {
struct FetchResourcesScreen* s = (struct FetchResourcesScreen*)s_;
if (!Fetcher_Working) return;
@ -1123,7 +1127,7 @@ static void FetchResourcesScreen_Tick(struct LScreen* s_) {
Fetcher_Update();
if (!Fetcher_Completed) return;
if (Fetcher_Failed) { FetchResourcesScreen_Error(s); return; }
if (Fetcher_Failed) return;
Launcher_TryLoadTexturePack();
CheckResourcesScreen_Next(NULL);
@ -1274,11 +1278,11 @@ static void ServersScreen_Tick(struct LScreen* s_) {
LScreen_Tick(s_);
count = FetchFlagsTask.count;
LWebTask_Tick(&FetchFlagsTask.Base);
LWebTask_Tick(&FetchFlagsTask.Base, NULL);
if (count != FetchFlagsTask.count) LBackend_TableFlagAdded(&s->table);
if (!FetchServersTask.Base.working) return;
LWebTask_Tick(&FetchServersTask.Base);
LWebTask_Tick(&FetchServersTask.Base, NULL);
if (!FetchServersTask.Base.completed) return;
if (FetchServersTask.Base.success) {
@ -1644,7 +1648,7 @@ static void UpdatesScreen_Get(cc_bool release, int buildIndex) {
static void UpdatesScreen_CheckTick(struct UpdatesScreen* s) {
if (!CheckUpdateTask.Base.working) return;
LWebTask_Tick(&CheckUpdateTask.Base);
LWebTask_Tick(&CheckUpdateTask.Base, NULL);
if (!CheckUpdateTask.Base.completed) return;
UpdatesScreen_FormatBoth(s);
@ -1665,23 +1669,25 @@ static void UpdatesScreen_UpdateProgress(struct UpdatesScreen* s, struct LWebTas
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];
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;
LWebTask_Tick(&FetchUpdateTask.Base);
LWebTask_Tick(&FetchUpdateTask.Base, FetchUpdatesError);
UpdatesScreen_UpdateProgress(s, &FetchUpdateTask.Base);
if (!FetchUpdateTask.Base.completed) return;
if (!FetchUpdateTask.Base.success) {
String_InitArray(str, strBuffer);
LWebTask_DisplayError(&FetchUpdateTask.Base, "fetching update", &str);
LLabel_SetText(&s->lblStatus, &str);
} else {
/* FetchUpdateTask handles saving the updated file for us */
Launcher_ShouldExit = true;
Launcher_ShouldUpdate = true;
}
if (!FetchUpdateTask.Base.success) return;
/* 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); }

View file

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

View file

@ -6,6 +6,7 @@
Copyright 2014-2022 ClassiCube | Licensed under BSD-3
*/
struct HttpRequest;
struct JsonContext;
typedef void (*JsonOnValue)(struct JsonContext* ctx, const cc_string* v);
typedef void (*JsonOnNew)(struct JsonContext* ctx);
@ -53,15 +54,14 @@ struct LWebTask {
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 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. */
/* Called when task successfully downloaded/uploaded data. */
void (*Handle)(cc_uint8* data, cc_uint32 len);
};
void LWebTask_Tick(struct LWebTask* task);
void LWebTask_DisplayError(struct LWebTask* task, const char* action, cc_string* dst);
typedef void (*LWebTask_ErrorCallback)(struct HttpRequest* req);
void LWebTask_Tick(struct LWebTask* task, LWebTask_ErrorCallback errorCallback);
void LWebTasks_Init(void);

View file

@ -53,7 +53,10 @@ void Launcher_SetScreen(struct LScreen* screen) {
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) {
/* Non HTTP error - this is not good */
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);
}
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) {
struct ServerInfo* info;
cc_string logMsg;
int i;
if (!hash->length) return false;
@ -139,7 +146,7 @@ cc_bool Launcher_ConnectToServer(const cc_string* hash) {
FetchServerTask_Run(hash);
while (!FetchServerTask.Base.completed) {
LWebTask_Tick(&FetchServerTask.Base);
LWebTask_Tick(&FetchServerTask.Base, ConnectToServerError);
Thread_Sleep(10);
}
@ -148,9 +155,6 @@ cc_bool Launcher_ConnectToServer(const cc_string* hash) {
return true;
} else if (FetchServerTask.Base.success) {
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;
}

View file

@ -75,6 +75,6 @@ void Launcher_Run(void);
/* 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);
/* Prints information about a http error to dst. (for status widget) */
/* If res is non-zero, also displays a dialog box on-screen. */
void Launcher_DisplayHttpError(cc_result res, int status, const char* action, cc_string* dst);
/* If req->result is non-zero, also displays a dialog box on-screen. */
void Launcher_DisplayHttpError(struct HttpRequest* req, const char* action, cc_string* dst);
#endif

View file

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

View file

@ -4,26 +4,25 @@
/* Implements checking, fetching, and patching the default game assets.
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;
/* Total size of resources that need to be downloaded. */
/* Total size of resources that need to be downloaded */
extern int Resources_Size;
/* Checks existence of all assets. */
/* Checks existence of all assets */
void Resources_CheckExistence(void);
/* Whether fetcher is currently downloading resources. */
/* Whether fetcher is currently downloading resources */
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;
/* Number of resources that have been downloaded so far. */
/* Number of resources that have been downloaded so far */
extern int Fetcher_Downloaded;
/* HTTP status code of last failed resource download */
extern int Fetcher_StatusCode;
/* Error code of last failed resource download. */
extern cc_result Fetcher_Result;
/* Whether a resource failed to download. */
/* Whether a resource failed to download */
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. */
const char* Fetcher_RequestName(int reqID);