From cff6b178f0be940269f23558506baa7a3dfddcc9 Mon Sep 17 00:00:00 2001 From: KyleSanderson Date: Sat, 8 Feb 2014 12:19:32 -0700 Subject: [PATCH] Add HTTP Support. --- Extension/Makefile | 2 +- Extension/extension.cpp | 4 + Extension/extension.h | 3 + Extension/swhttp.cpp | 65 ++++ Extension/swhttp.h | 44 +++ Extension/swhttprequest.cpp | 574 ++++++++++++++++++++++++++++++++++++ Extension/swhttprequest.h | 58 ++++ 7 files changed, 749 insertions(+), 1 deletion(-) create mode 100644 Extension/swhttp.cpp create mode 100644 Extension/swhttp.h create mode 100644 Extension/swhttprequest.cpp create mode 100644 Extension/swhttprequest.h diff --git a/Extension/Makefile b/Extension/Makefile index 517b68c..338ba59 100644 --- a/Extension/Makefile +++ b/Extension/Makefile @@ -27,7 +27,7 @@ PROJECT = SteamWorks USESH = true USECD = true -OBJECTS = sdk/smsdk_ext.cpp extension.cpp swgameserver.cpp swgamedata.cpp swforwards.cpp gsnatives.cpp swgshooks.cpp swgsdetours.cpp ssnatives.cpp +OBJECTS = sdk/smsdk_ext.cpp extension.cpp swgameserver.cpp swgamedata.cpp swforwards.cpp gsnatives.cpp swgshooks.cpp swgsdetours.cpp ssnatives.cpp swhttp.cpp swhttprequest.cpp ifeq "$(USECD)" "true" OBJECTS += CDetour/detours.cpp asm/asm.c diff --git a/Extension/extension.cpp b/Extension/extension.cpp index f22a574..5e5efc9 100644 --- a/Extension/extension.cpp +++ b/Extension/extension.cpp @@ -45,7 +45,9 @@ bool SteamWorks::SDK_OnLoad(char *error, size_t maxlength, bool late) { this->pSWGameData = new SteamWorksGameData; this->pSWGameServer = new SteamWorksGameServer; + this->pSWHTTP = new SteamWorksHTTP; + this->pSWHTTPNatives = new SteamWorksHTTPNatives; this->pSWForward = new SteamWorksForwards; this->pGSNatives = new SteamWorksGSNatives; this->pGSHooks = new SteamWorksGSHooks; @@ -61,7 +63,9 @@ void SteamWorks::SDK_OnUnload() delete this->pGSHooks; delete this->pGSNatives; delete this->pSWForward; + delete this->pSWHTTPNatives; + delete this->pSWHTTP; delete this->pSWGameServer; delete this->pSWGameData; } diff --git a/Extension/extension.h b/Extension/extension.h index a2738b6..758ba84 100644 --- a/Extension/extension.h +++ b/Extension/extension.h @@ -49,6 +49,7 @@ #include "swgshooks.h" #include "ssnatives.h" #include "swgsdetours.h" +#include "swhttp.h" /** * @brief Sample implementation of the SDK Extension. @@ -139,6 +140,8 @@ public: SteamWorksGSHooks *pGSHooks; SteamWorksSSNatives *pSSNatives; SteamWorksGSDetours *pGSDetours; + SteamWorksHTTP *pSWHTTP; + SteamWorksHTTPNatives *pSWHTTPNatives; }; extern SteamWorks g_SteamWorks; diff --git a/Extension/swhttp.cpp b/Extension/swhttp.cpp new file mode 100644 index 0000000..6e63464 --- /dev/null +++ b/Extension/swhttp.cpp @@ -0,0 +1,65 @@ +/* + This file is part of SourcePawn SteamWorks. + + SourcePawn SteamWorks is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SourcePawn SteamWorks is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SourcePawn SteamWorks. If not, see . + + Author: Kyle Sanderson (KyleS). +*/ + +#include "swhttp.h" + +static ISteamHTTP *GetHTTPPointer() +{ + return g_SteamWorks.pSWGameServer->GetHTTP(); +} + +SteamWorksHTTP::SteamWorksHTTP() +{ + this->typeHTTP = handlesys->CreateType("HTTPHandle", this, 0, NULL, NULL, myself->GetIdentity(), NULL); +} + +SteamWorksHTTP::~SteamWorksHTTP() +{ + handlesys->RemoveType(this->typeHTTP, myself->GetIdentity()); +} + +HandleType_t SteamWorksHTTP::GetHTTPHandle(void) +{ + return this->typeHTTP; +} + +static void DelayedDeleteSteamWorksHTTPRequest(void *object) +{ + SteamWorksHTTPRequest *pRequest = reinterpret_cast(object); + delete pRequest; +} + +void SteamWorksHTTP::OnHandleDestroy(HandleType_t type, void *object) +{ + if (type == this->typeHTTP) /* Heaven forbid we ever offer another handle. */ + { + smutils->AddFrameAction(DelayedDeleteSteamWorksHTTPRequest, object); + } +} + +bool SteamWorksHTTP::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize) +{ + if (type == this->typeHTTP && pSize) /* Heaven forbid we ever offer another handle. */ + { + *pSize = sizeof(SteamWorksHTTPRequest); + return true; + } + + return false; +} diff --git a/Extension/swhttp.h b/Extension/swhttp.h new file mode 100644 index 0000000..227de9f --- /dev/null +++ b/Extension/swhttp.h @@ -0,0 +1,44 @@ +/* + This file is part of SourcePawn SteamWorks. + + SourcePawn SteamWorks is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SourcePawn SteamWorks is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SourcePawn SteamWorks. If not, see . + + Author: Kyle Sanderson (KyleS). +*/ + +#pragma once +#include "isteamgameserver.h" +#include "steam_gameserver.h" +#include "smsdk_ext.h" + +class SteamWorksHTTP : + public IHandleTypeDispatch +{ + public: + SteamWorksHTTP(); + ~SteamWorksHTTP(); + + public: + void OnHandleDestroy(HandleType_t type, void *object); + bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize); + + public: + HandleType_t GetHTTPHandle(void); + + private: + HandleType_t typeHTTP; +}; + +#include "swhttprequest.h" +#include "extension.h" \ No newline at end of file diff --git a/Extension/swhttprequest.cpp b/Extension/swhttprequest.cpp new file mode 100644 index 0000000..472773d --- /dev/null +++ b/Extension/swhttprequest.cpp @@ -0,0 +1,574 @@ +/* + This file is part of SourcePawn SteamWorks. + + SourcePawn SteamWorks is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SourcePawn SteamWorks is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SourcePawn SteamWorks. If not, see . + + Author: Kyle Sanderson (KyleS). +*/ + +#include "swhttprequest.h" + +static ISteamHTTP *GetHTTPPointer(void) +{ + return g_SteamWorks.pSWGameServer->GetHTTP(); +} + +static HandleType_t GetSteamHTTPHandle(void) +{ + return g_SteamWorks.pSWHTTP->GetHTTPHandle(); +} + +SteamWorksHTTPRequest::SteamWorksHTTPRequest() +{ + this->request = INVALID_HTTPREQUEST_HANDLE; + this->handle = BAD_HANDLE; + this->pCompletedForward = NULL; + this->pHeadersReceivedForward = NULL; + this->pDataReceivedForward = NULL; +}; + +SteamWorksHTTPRequest::~SteamWorksHTTPRequest() +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP != NULL) + { + pHTTP->ReleaseHTTPRequest(this->request); + this->request = INVALID_HTTPREQUEST_HANDLE; + } + + forwards->ReleaseForward(this->pCompletedForward); + this->pCompletedForward = NULL; + + forwards->ReleaseForward(this->pHeadersReceivedForward); + this->pHeadersReceivedForward = NULL; + + forwards->ReleaseForward(this->pDataReceivedForward); + this->pDataReceivedForward = NULL; +} + +/* We pay the Iron Price. */ +void SteamWorksHTTPRequest::OnHTTPRequestCompleted(HTTPRequestCompleted_t *pRequest, bool bFailed) +{ + if (this->pCompletedForward == NULL || this->pCompletedForward->GetFunctionCount() == 0) + { + return; + } + + this->pCompletedForward->PushCell(this->handle); + this->pCompletedForward->PushCell(bFailed); + this->pCompletedForward->PushCell(pRequest->m_bRequestSuccessful); + this->pCompletedForward->PushCell(pRequest->m_eStatusCode); + this->pCompletedForward->PushCell(pRequest->m_ulContextValue >> 32); + this->pCompletedForward->PushCell((pRequest->m_ulContextValue & 0x00000000FFFFFFFF)); + this->pCompletedForward->Execute(NULL); +} + +void SteamWorksHTTPRequest::OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pRequest, bool bFailed) +{ + if (this->pHeadersReceivedForward == NULL || this->pHeadersReceivedForward->GetFunctionCount() == 0) + { + return; + } + + this->pHeadersReceivedForward->PushCell(this->handle); + this->pHeadersReceivedForward->PushCell(bFailed); + this->pHeadersReceivedForward->PushCell(pRequest->m_ulContextValue >> 32); + this->pHeadersReceivedForward->PushCell((pRequest->m_ulContextValue & 0x00000000FFFFFFFF)); + this->pHeadersReceivedForward->Execute(NULL); +} + +void SteamWorksHTTPRequest::OnHTTPDataReceived(HTTPRequestDataReceived_t *pRequest, bool bFailed) +{ + if (this->pDataReceivedForward == NULL || this->pDataReceivedForward->GetFunctionCount() == 0) + { + return; + } + + this->pDataReceivedForward->PushCell(this->handle); + this->pDataReceivedForward->PushCell(bFailed); + this->pDataReceivedForward->PushCell(pRequest->m_cOffset); + this->pDataReceivedForward->PushCell(pRequest->m_cBytesReceived); + this->pDataReceivedForward->PushCell(pRequest->m_ulContextValue >> 32); + this->pDataReceivedForward->PushCell((pRequest->m_ulContextValue & 0x00000000FFFFFFFF)); + this->pDataReceivedForward->Execute(NULL); +} + +static cell_t sm_CreateHTTPRequest(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return BAD_HANDLE; + } + + char *pURL; + pContext->LocalToString(params[2], &pURL); + + HTTPRequestHandle request = pHTTP->CreateHTTPRequest(static_cast(params[1]), pURL); + if (request == INVALID_HTTPREQUEST_HANDLE) + { + return BAD_HANDLE; + } + + SteamWorksHTTPRequest *pRequest = new SteamWorksHTTPRequest; + Handle_t handle = handlesys->CreateHandle(GetSteamHTTPHandle(), pRequest, pContext->GetIdentity(), myself->GetIdentity(), NULL); + if (handle == BAD_HANDLE) + { + pHTTP->ReleaseHTTPRequest(request); + delete pRequest; + return BAD_HANDLE; + } + + pRequest->request = request; + pRequest->handle = handle; + + return handle; +} + +static cell_t sm_SetHTTPRequestContextValue(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + return pHTTP->SetHTTPRequestContextValue(pRequest->request, (static_cast(params[2]) << 32 | params[3])) ? 1 : 0; +} + +static cell_t sm_SetHTTPRequestNetworkActivityTimeout(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + return pHTTP->SetHTTPRequestNetworkActivityTimeout(pRequest->request, params[2]) ? 1 : 0; +} + +static cell_t sm_SetHTTPRequestHeaderValue(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + char *pName, *pValue; + pContext->LocalToString(params[2], &pName); + pContext->LocalToString(params[3], &pValue); + return pHTTP->SetHTTPRequestHeaderValue(pRequest->request, pName, pValue) ? 1 : 0; +} + +static cell_t sm_SetHTTPRequestGetOrPostParameter(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + char *pName, *pValue; + pContext->LocalToString(params[2], &pName); + pContext->LocalToString(params[3], &pValue); + return pHTTP->SetHTTPRequestGetOrPostParameter(pRequest->request, pName, pValue) ? 1 : 0; +} + +static cell_t sm_SetCallbacks(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + IPlugin *pPlugin; + if (params[5] == BAD_HANDLE) + { + pPlugin = plsys->FindPluginByContext(pContext->GetContext()); + } else { + pPlugin = plsys->PluginFromHandle(params[5], &err); + + if (!pPlugin) + { + return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", params[5], err); + } + } + + if (params[2] > 0) + { + if (pRequest->pCompletedForward == NULL) + { + pRequest->pCompletedForward = forwards->CreateForwardEx(NULL, ET_Ignore, 6, NULL, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + } + + IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[2]); + + if (!pFunction) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); + } + + pRequest->pCompletedForward->AddFunction(pFunction); + } + + if (params[3] > 0) + { + if (pRequest->pHeadersReceivedForward == NULL) + { + pRequest->pHeadersReceivedForward = forwards->CreateForwardEx(NULL, ET_Ignore, 4, NULL, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + } + + IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]); + + if (!pFunction) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[3]); + } + + pRequest->pHeadersReceivedForward->AddFunction(pFunction); + } + + if (params[4] > 0) + { + if (pRequest->pDataReceivedForward == NULL) + { + pRequest->pDataReceivedForward = forwards->CreateForwardEx(NULL, ET_Ignore, 6, NULL, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + } + + IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[4]); + + if (!pFunction) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[4]); + } + + pRequest->pDataReceivedForward->AddFunction(pFunction); + } + + return 1; +} + +static cell_t sm_SendHTTPRequest(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + SteamAPICall_t hCall; + cell_t result = pHTTP->SendHTTPRequest(pRequest->request, &hCall) ? 1 : 0; + + if (pRequest->pCompletedForward != NULL) + { + pRequest->CompletedCallResult.SetGameserverFlag(); + pRequest->CompletedCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPRequestCompleted); + } + + if (pRequest->pHeadersReceivedForward != NULL) + { + pRequest->HeadersCallResult.SetGameserverFlag(); + pRequest->HeadersCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPHeadersReceived); + } + + if (pRequest->pDataReceivedForward != NULL) + { + pRequest->DataCallResult.SetGameserverFlag(); + pRequest->DataCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPDataReceived); + } + + return result; +} + +static cell_t sm_DeferHTTPRequest(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + return pHTTP->DeferHTTPRequest(pRequest->request) ? 1 : 0; +} + +static cell_t sm_PrioritizeHTTPRequest(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + return pHTTP->PrioritizeHTTPRequest(pRequest->request) ? 1 : 0; +} + +static cell_t sm_GetHTTPResponseHeaderSize(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + char *pName; + pContext->LocalToString(params[2], &pName); + + cell_t *pSize; + pContext->LocalToPhysAddr(params[3], &pSize); + return pHTTP->GetHTTPResponseHeaderSize(pRequest->request, pName, reinterpret_cast(pSize)) ? 1 : 0; +} + +static cell_t sm_GetHTTPResponseHeaderValue(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + char *pName; + pContext->LocalToString(params[2], &pName); + + char *pBuffer; + pContext->LocalToString(params[3], &pBuffer); + return pHTTP->GetHTTPResponseHeaderValue(pRequest->request, pName, reinterpret_cast(pBuffer), params[4]) ? 1 : 0; /* uint8? wtf? */ +} + +static cell_t sm_GetHTTPResponseBodySize(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + cell_t *pSize; + pContext->LocalToPhysAddr(params[2], &pSize); + return pHTTP->GetHTTPResponseBodySize(pRequest->request, reinterpret_cast(pSize)) ? 1 : 0; +} + +static cell_t sm_GetHTTPResponseBodyData(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + char *pBuffer; + pContext->LocalToString(params[2], &pBuffer); + return pHTTP->GetHTTPResponseBodyData(pRequest->request, reinterpret_cast(pBuffer), params[3]) ? 1 : 0; +} + +static cell_t sm_GetHTTPDownloadProgressPct(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + float percent; + cell_t result = pHTTP->GetHTTPDownloadProgressPct(pRequest->request, &percent) ? 1 : 0; + + cell_t *pData; + pContext->LocalToPhysAddr(params[2], &pData); + *pData = sp_ftoc(percent); + return result; +} + +static cell_t sm_SetHTTPRequestRawPostBody(IPluginContext *pContext, const cell_t *params) +{ + ISteamHTTP *pHTTP = GetHTTPPointer(); + if (pHTTP == NULL) + { + return 0; + } + + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + SteamWorksHTTPRequest *pRequest; + if ((err = handlesys->ReadHandle(params[1], GetSteamHTTPHandle(), &sec, (void **)&pRequest)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + char *pName, *pBuffer; + pContext->LocalToString(params[2], &pName); + pContext->LocalToString(params[3], &pBuffer); + + return pHTTP->SetHTTPRequestRawPostBody(pRequest->request, pName, reinterpret_cast(pBuffer), params[4]) ? 1 : 0; +} + +static sp_nativeinfo_t httpnatives[] = { + {"SteamWorks_CreateHTTPRequest", sm_CreateHTTPRequest}, + {"SteamWorks_SetHTTPRequestContextValue", sm_SetHTTPRequestContextValue}, + {"SteamWorks_SetHTTPRequestNetworkActivityTimeout", sm_SetHTTPRequestNetworkActivityTimeout}, + {"SteamWorks_SetHTTPRequestHeaderValue", sm_SetHTTPRequestHeaderValue}, + {"SteamWorks_SetHTTPRequestGetOrPostParameter", sm_SetHTTPRequestGetOrPostParameter}, + {"SteamWorks_SetHTTPCallbacks", sm_SetCallbacks}, + {"SteamWorks_SendHTTPRequest", sm_SendHTTPRequest}, + {"SteamWorks_DeferHTTPRequest", sm_DeferHTTPRequest}, + {"SteamWorks_PrioritizeHTTPRequest", sm_PrioritizeHTTPRequest}, + {"SteamWorks_GetHTTPResponseHeaderSize", sm_GetHTTPResponseHeaderSize}, + {"SteamWorks_GetHTTPResponseHeaderValue", sm_GetHTTPResponseHeaderValue}, + {"SteamWorks_GetHTTPResponseBodySize", sm_GetHTTPResponseBodySize}, + {"SteamWorks_GetHTTPResponseBodyData", sm_GetHTTPResponseBodyData}, + {"SteamWorks_GetHTTPDownloadProgressPct", sm_GetHTTPDownloadProgressPct}, + {"SteamWorks_SetHTTPRequestRawPostBody", sm_SetHTTPRequestRawPostBody}, + {NULL, NULL} +}; + +SteamWorksHTTPNatives::SteamWorksHTTPNatives() +{ + sharesys->AddNatives(myself, httpnatives); +} + +SteamWorksHTTPNatives::~SteamWorksHTTPNatives() +{ +} diff --git a/Extension/swhttprequest.h b/Extension/swhttprequest.h new file mode 100644 index 0000000..07053d5 --- /dev/null +++ b/Extension/swhttprequest.h @@ -0,0 +1,58 @@ +/* + This file is part of SourcePawn SteamWorks. + + SourcePawn SteamWorks is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SourcePawn SteamWorks is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SourcePawn SteamWorks. If not, see . + + Author: Kyle Sanderson (KyleS). +*/ + +#pragma once +#include "isteamgameserver.h" +#include "steam_gameserver.h" +#include "smsdk_ext.h" + +class SteamWorksHTTPRequest +{ + public: + SteamWorksHTTPRequest(); + ~SteamWorksHTTPRequest(); + + public: + HTTPRequestHandle request; + Handle_t handle; + + public: + void OnHTTPRequestCompleted(HTTPRequestCompleted_t *pRequest, bool bFailed); + void OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pRequest, bool bFailed); + void OnHTTPDataReceived(HTTPRequestDataReceived_t *pRequest, bool bFailed); + + public: + CCallResult CompletedCallResult; + CCallResult HeadersCallResult; + CCallResult DataCallResult; + + public: + IChangeableForward *pCompletedForward; + IChangeableForward *pHeadersReceivedForward; + IChangeableForward *pDataReceivedForward; +}; + +class SteamWorksHTTPNatives +{ + public: + SteamWorksHTTPNatives(); + ~SteamWorksHTTPNatives(); +}; + +#include "extension.h" \ No newline at end of file