diff --git a/libgamestream/client.c b/libgamestream/client.c index 4d17332..a296f5e 100644 --- a/libgamestream/client.c +++ b/libgamestream/client.c @@ -203,6 +203,11 @@ static int load_server_status(PSERVER_DATA server) { goto cleanup; } + if (xml_status(data->memory, data->size) == GS_ERROR) { + ret = GS_ERROR; + goto cleanup; + } + if (xml_search(data->memory, data->size, "currentgame", ¤tGameText) != GS_OK) { goto cleanup; } @@ -408,7 +413,9 @@ int gs_pair(PSERVER_DATA server, char* pin) { else if ((ret = http_request(url, data)) != GS_OK) goto cleanup; - if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) + if ((ret = xml_status(data->memory, data->size) != GS_OK)) + goto cleanup; + else if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { @@ -464,7 +471,9 @@ int gs_pair(PSERVER_DATA server, char* pin) { free(result); result = NULL; - if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) + if ((ret = xml_status(data->memory, data->size) != GS_OK)) + goto cleanup; + else if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { @@ -521,7 +530,9 @@ int gs_pair(PSERVER_DATA server, char* pin) { free(result); result = NULL; - if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) + if ((ret = xml_status(data->memory, data->size) != GS_OK)) + goto cleanup; + else if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { @@ -570,7 +581,9 @@ int gs_pair(PSERVER_DATA server, char* pin) { free(result); result = NULL; - if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) + if ((ret = xml_status(data->memory, data->size) != GS_OK)) + goto cleanup; + else if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { @@ -587,7 +600,9 @@ int gs_pair(PSERVER_DATA server, char* pin) { free(result); result = NULL; - if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) + if ((ret = xml_status(data->memory, data->size) != GS_OK)) + goto cleanup; + else if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { @@ -624,6 +639,8 @@ int gs_applist(PSERVER_DATA server, PAPP_LIST *list) { sprintf(url, "https://%s:47984/applist?uniqueid=%s&uuid=%s", server->serverInfo.address, unique_id, uuid_str); if (http_request(url, data) != GS_OK) ret = GS_IO_ERROR; + else if (xml_status(data->memory, data->size) == GS_ERROR) + ret = GS_ERROR; else if (xml_applist(data->memory, data->size, list) != GS_OK) ret = GS_INVALID; @@ -679,7 +696,9 @@ int gs_start_app(PSERVER_DATA server, STREAM_CONFIGURATION *config, int appId, b else goto cleanup; - if ((ret = xml_search(data->memory, data->size, "gamesession", &result)) != GS_OK) + if ((ret = xml_status(data->memory, data->size) != GS_OK)) + goto cleanup; + else if ((ret = xml_search(data->memory, data->size, "gamesession", &result)) != GS_OK) goto cleanup; if (!strcmp(result, "0")) { @@ -711,7 +730,9 @@ int gs_quit_app(PSERVER_DATA server) { if ((ret = http_request(url, data)) != GS_OK) goto cleanup; - if ((ret = xml_search(data->memory, data->size, "cancel", &result)) != GS_OK) + if ((ret = xml_status(data->memory, data->size) != GS_OK)) + goto cleanup; + else if ((ret = xml_search(data->memory, data->size, "cancel", &result)) != GS_OK) goto cleanup; if (strcmp(result, "0") == 0) { diff --git a/libgamestream/errors.h b/libgamestream/errors.h index f657ae7..6de44a9 100644 --- a/libgamestream/errors.h +++ b/libgamestream/errors.h @@ -28,5 +28,6 @@ #define GS_NOT_SUPPORTED_4K -6 #define GS_UNSUPPORTED_VERSION -7 #define GS_NOT_SUPPORTED_MODE -8 +#define GS_ERROR -9 -const char* gs_error; +extern const char* gs_error; diff --git a/libgamestream/xml.c b/libgamestream/xml.c index 4e5e86e..d7076bc 100644 --- a/libgamestream/xml.c +++ b/libgamestream/xml.c @@ -23,6 +23,8 @@ #include #include +#define STATUS_OK 200 + static XML_Parser parser; struct xml_query { @@ -110,6 +112,23 @@ static void XMLCALL _xml_end_mode_element(void *userData, const char *name) { } } +static void XMLCALL _xml_start_status_element(void *userData, const char *name, const char **atts) { + if (strcmp("root", name) == 0) { + int* status = (int*) userData; + for (int i = 0; atts[i]; i += 2) { + if (strcmp("status_code", atts[i]) == 0) + *status = atoi(atts[i + 1]); + else if (*status != STATUS_OK && strcmp("status_message", atts[i]) == 0) { + gs_error = malloc(strlen(atts[i + 1])); + if (gs_error) + strcpy((char*) gs_error, atts[i + 1]); + } + } + } +} + +static void XMLCALL _xml_end_status_element(void *userData, const char *name) { } + static void XMLCALL _xml_write_data(void *userData, const XML_Char *s, int len) { struct xml_query *search = (struct xml_query*) userData; if (search->start > 0) { @@ -193,3 +212,19 @@ int xml_modelist(char* data, size_t len, PDISPLAY_MODE *mode_list) { return GS_OK; } + +int xml_status(char* data, size_t len) { + int status = 0; + XML_Parser parser = XML_ParserCreate("UTF-8"); + XML_SetUserData(parser, &status); + XML_SetElementHandler(parser, _xml_start_status_element, _xml_end_status_element); + if (!XML_Parse(parser, data, len, 1)) { + int code = XML_GetErrorCode(parser); + gs_error = XML_ErrorString(code); + XML_ParserFree(parser); + return GS_INVALID; + } + + XML_ParserFree(parser); + return status == STATUS_OK ? GS_OK : GS_ERROR; +} diff --git a/libgamestream/xml.h b/libgamestream/xml.h index aee4214..fb19477 100644 --- a/libgamestream/xml.h +++ b/libgamestream/xml.h @@ -36,3 +36,4 @@ typedef struct _DISPLAY_MODE { int xml_search(char* data, size_t len, char* node, char** result); int xml_applist(char* data, size_t len, PAPP_LIST *app_list); int xml_modelist(char* data, size_t len, PDISPLAY_MODE *mode_list); +int xml_status(char* data, size_t len); diff --git a/src/main.c b/src/main.c index 651cfd1..e111e88 100644 --- a/src/main.c +++ b/src/main.c @@ -96,6 +96,8 @@ static void stream(PSERVER_DATA server, PCONFIGURATION config, enum platform sys fprintf(stderr, "Server doesn't support 4K\n"); else if (ret == GS_NOT_SUPPORTED_MODE) fprintf(stderr, "Server doesn't support %dx%d (%d fps) or try --unsupported option\n", config->stream.width, config->stream.height, config->stream.fps); + else if (ret == GS_ERROR) + fprintf(stderr, "Gamestream error: %s\n", gs_error); else fprintf(stderr, "Errorcode starting app: %d\n", ret); exit(-1); @@ -219,8 +221,11 @@ int main(int argc, char* argv[]) { if ((ret = gs_init(&server, config.address, config.key_dir, config.debug_level, config.unsupported)) == GS_OUT_OF_MEMORY) { fprintf(stderr, "Not enough memory\n"); exit(-1); + } else if (ret == GS_ERROR) { + fprintf(stderr, "Gamestream error: %s\n", gs_error); + exit(-1); } else if (ret == GS_INVALID) { - fprintf(stderr, "Invalid data received from server: %s\n", config.address, gs_error); + fprintf(stderr, "Invalid data received from server: %s\n", gs_error); exit(-1); } else if (ret == GS_UNSUPPORTED_VERSION) { fprintf(stderr, "Unsupported version: %s\n", gs_error);