From 87553ac400c424ba6da702f80158c13896dc2943 Mon Sep 17 00:00:00 2001 From: Alexander Volz Date: Mon, 17 Oct 2022 19:38:29 +0200 Subject: [PATCH 1/3] fix request memory leak and check for http status codes + added debug logging to apistats when no api key was provided --- scripting/get5/natives.sp | 8 +++++ scripting/get5_apistats.sp | 72 +++++++++++++++++++++++++++----------- scripting/include/get5.inc | 2 ++ 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/scripting/get5/natives.sp b/scripting/get5/natives.sp index 482e64773..9c79e31fe 100644 --- a/scripting/get5/natives.sp +++ b/scripting/get5/natives.sp @@ -21,6 +21,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("Get5_AddLiveCvar", Native_AddLiveCvar); CreateNative("Get5_IncreasePlayerStat", Native_IncreasePlayerStat); CreateNative("Get5_GetMatchStats", Native_GetMatchStats); + CreateNative("Get5_CreateGet5HTTPRequest", Native_CreateGet5HTTPRequest); RegPluginLibrary("get5"); return APLRes_Success; } @@ -251,3 +252,10 @@ public int Native_GetMatchStats(Handle plugin, int numParams) { return view_as(true); } } + +public int Native_CreateGet5HTTPRequest(Handle plugin, int numParams) { + EHTTPMethod method = view_as(GetNativeCell(1)); + char url[1024]; + GetNativeString(2, url, sizeof(url)); + return CreateGet5HTTPRequest(method, url); +} diff --git a/scripting/get5_apistats.sp b/scripting/get5_apistats.sp index a2f6d89bf..c4081cc4e 100644 --- a/scripting/get5_apistats.sp +++ b/scripting/get5_apistats.sp @@ -112,21 +112,20 @@ void ApiInfoChanged(ConVar convar, const char[] oldValue, const char[] newValue) } static Handle CreateRequest(EHTTPMethod httpMethod, const char[] apiMethod, any:...) { - char url[1024]; - FormatEx(url, sizeof(url), "%s%s", g_APIURL, apiMethod); - - char formattedUrl[1024]; - VFormat(formattedUrl, sizeof(formattedUrl), url, 3); - LogDebug("Trying to create request to url %s", formattedUrl); - - Handle req = SteamWorks_CreateHTTPRequest(httpMethod, formattedUrl); if (StrEqual(g_APIKey, "")) { // Not using a web interface. + LogError("Failed to create request because get5_web_api_key was not provided"); return INVALID_HANDLE; + } - } else if (req == INVALID_HANDLE) { - LogError("Failed to create request to %s", formattedUrl); + char url[1024]; + char formattedUrl[1024]; + FormatEx(url, sizeof(url), "%s%s", g_APIURL, apiMethod); + VFormat(formattedUrl, sizeof(formattedUrl), url, 3); + LogDebug("Trying to create request to url %s", formattedUrl); + Handle req = Get5_CreateGet5HTTPRequest(httpMethod, formattedUrl); + if (req == INVALID_HANDLE) { return INVALID_HANDLE; } else { @@ -136,15 +135,28 @@ static Handle CreateRequest(EHTTPMethod httpMethod, const char[] apiMethod, any: } } -int RequestCallback(Handle request, bool failure, bool requestSuccessful, +static int RequestCallback(Handle request, bool failure, bool requestSuccessful, EHTTPStatusCode statusCode) { + if (failure || !requestSuccessful) { - LogError("API request failed, HTTP status code = %d", statusCode); - char response[1024]; - SteamWorks_GetHTTPResponseBodyData(request, response, sizeof(response)); - LogError(response); + LogError("Network connection failed for the API request"); + delete request; return; } + + int status = view_as(statusCode); + if (status >= 300 || status < 200) { + LogError("API request failed with HTTP status code: %d.", statusCode); + int responseSize; + SteamWorks_GetHTTPResponseBodySize(request, responseSize); + char[] response = new char[responseSize]; + if (SteamWorks_GetHTTPResponseBodyData(request, response, responseSize)) { + LogError("Response body: %s", response); + } else { + LogError("Failed to read response body."); + } + } + delete request; } public void Get5_OnSeriesInit(const Get5SeriesStartedEvent event) { @@ -196,14 +208,28 @@ static void CheckForLogo(const char[] logo) { } } -static int LogoCallback(Handle request, bool failure, bool successful, EHTTPStatusCode status, - int data) { +static int LogoCallback(Handle request, bool failure, bool successful, EHTTPStatusCode statusCode, + DataPack data) { if (failure || !successful) { - LogError("Logo request failed, status code = %d", status); + LogError("Network connection failed for the logo request"); + delete request; return; } - DataPack pack = view_as(data); + int status = view_as(statusCode); + if (status >= 300 || status < 200) { + LogError("Logo request failed with HTTP status code: %d.", statusCode); + int responseSize; + SteamWorks_GetHTTPResponseBodySize(request, responseSize); + char[] response = new char[responseSize]; + if (SteamWorks_GetHTTPResponseBodyData(request, response, responseSize)) { + LogError("Response body: %s", response); + } else { + LogError("Failed to read response body."); + } + delete request; + } + pack.Reset(); char logo[32]; pack.ReadString(logo, sizeof(logo)); @@ -215,8 +241,12 @@ static int LogoCallback(Handle request, bool failure, bool successful, EHTTPStat FormatEx(logoPath, sizeof(logoPath), "%s/%s.png", g_LogoBasePath, logo); } - LogMessage("Saved logo for %s to %s", logo, logoPath); - SteamWorks_WriteHTTPResponseBodyToFile(request, logoPath); + if (SteamWorks_WriteHTTPResponseBodyToFile(request, logoPath)) { + LogMessage("Saved logo for %s to %s", logo, logoPath); + } else { + LogError("Failed to write logo %s to file %s.", logo, logoPath); + } + delete request; } public void Get5_OnGoingLive(const Get5GoingLiveEvent event) { diff --git a/scripting/include/get5.inc b/scripting/include/get5.inc index 059fe2c8f..c7ef5818c 100644 --- a/scripting/include/get5.inc +++ b/scripting/include/get5.inc @@ -141,6 +141,8 @@ native bool Get5_GetMatchStats(KeyValues kv); // Increases an (integer-typed) player statistic in the plugin's stats keyvalue structure. native int Get5_IncreasePlayerStat(int client, const char[] statName, int amount = 1); +// Creates a Steamworks http(s) request with the get5 headers +native int Get5_CreateGet5HTTPRequest(const EHTTPMethod method, const char[] url); methodmap Get5StatusTeam < JSON_Object { From 96944bea5a272c9b9d055e21a3aa4751c91490c5 Mon Sep 17 00:00:00 2001 From: Alexander Volz Date: Wed, 19 Oct 2022 19:48:51 +0200 Subject: [PATCH 2/3] fixup natives --- scripting/get5/natives.sp | 2 +- scripting/get5_apistats.sp | 4 ++-- scripting/include/get5.inc | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/scripting/get5/natives.sp b/scripting/get5/natives.sp index 9c79e31fe..996ad820b 100644 --- a/scripting/get5/natives.sp +++ b/scripting/get5/natives.sp @@ -257,5 +257,5 @@ public int Native_CreateGet5HTTPRequest(Handle plugin, int numParams) { EHTTPMethod method = view_as(GetNativeCell(1)); char url[1024]; GetNativeString(2, url, sizeof(url)); - return CreateGet5HTTPRequest(method, url); + return view_as(CreateGet5HTTPRequest(method, url)); } diff --git a/scripting/get5_apistats.sp b/scripting/get5_apistats.sp index c4081cc4e..f8b77ef79 100644 --- a/scripting/get5_apistats.sp +++ b/scripting/get5_apistats.sp @@ -230,9 +230,9 @@ static int LogoCallback(Handle request, bool failure, bool successful, EHTTPStat delete request; } - pack.Reset(); + data.Reset(); char logo[32]; - pack.ReadString(logo, sizeof(logo)); + data.ReadString(logo, sizeof(logo)); char logoPath[PLATFORM_MAX_PATH + 1]; if (g_UseSVGCvar.BoolValue) { diff --git a/scripting/include/get5.inc b/scripting/include/get5.inc index c7ef5818c..a390401bc 100644 --- a/scripting/include/get5.inc +++ b/scripting/include/get5.inc @@ -5,6 +5,7 @@ #include // github.com/clugg/sm-json #include +#include enum Get5Side { Get5Side_None = CS_TEAM_NONE, @@ -142,7 +143,7 @@ native bool Get5_GetMatchStats(KeyValues kv); native int Get5_IncreasePlayerStat(int client, const char[] statName, int amount = 1); // Creates a Steamworks http(s) request with the get5 headers -native int Get5_CreateGet5HTTPRequest(const EHTTPMethod method, const char[] url); +native Handle Get5_CreateGet5HTTPRequest(const EHTTPMethod method, const char[] url); methodmap Get5StatusTeam < JSON_Object { From a104ab5c42428acd164f12e2be14e0f5bf2949e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Oct 2022 18:03:47 +0000 Subject: [PATCH 3/3] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 6 +++--- .github/workflows/development.yml | 2 +- .github/workflows/generate_docs.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b631b34d0..73f661850 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: SM_JSON_INC_PATH: get5/dependencies/sm-json/addons/sourcemod/scripting/include STEAMWORKS_URL: https://raw.githubusercontent.com/PhlexPlexico/SteamWorks/master/Pawn/includes/SteamWorks.inc steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: path: 'get5' submodules: true @@ -74,7 +74,7 @@ jobs: if: github.ref == 'refs/heads/development' runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 with: name: ${{ needs.build.outputs.filename }} @@ -109,7 +109,7 @@ jobs: if: github.ref == 'refs/heads/master' runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Generate changelog id: changelog diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index 7048d1bd4..a1966505f 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -17,7 +17,7 @@ jobs: SM_JSON_INC_PATH: get5/dependencies/sm-json/addons/sourcemod/scripting/include STEAMWORKS_URL: https://raw.githubusercontent.com/PhlexPlexico/SteamWorks/master/Pawn/includes/SteamWorks.inc steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: path: 'get5' submodules: true diff --git a/.github/workflows/generate_docs.yml b/.github/workflows/generate_docs.yml index 09ac6837a..b23cb6939 100644 --- a/.github/workflows/generate_docs.yml +++ b/.github/workflows/generate_docs.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout main - uses: actions/checkout@v2 + uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.10'