/* 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, as per version 3 of the License. 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" #include /* SourceMod 1.13 (extension API 9) changed IPluginManager::FindPluginByContext() to take an IPluginContext* directly; older SM (API 8) takes the low-level sp_context_t* from IPluginContext::GetContext(). */ #if SMINTERFACE_EXTENSIONAPI_VERSION >= 9 #define SW_PLUGIN_CTX(ctx) (ctx) #else #define SW_PLUGIN_CTX(ctx) ((ctx)->GetContext()) #endif static ISteamHTTP *GetHTTPPointer(void) { return g_SteamWorks.pSWGameServer->GetHTTP(); } static HandleType_t GetSteamHTTPHandle(void) { return g_SteamWorks.pSWHTTP->GetHTTPHandle(); } static SteamWorksHTTPRequest *GetRequestPointer(ISteamHTTP *&pHTTP, IPluginContext *pContext, cell_t Handle) { pHTTP = GetHTTPPointer(); if (pHTTP == NULL) { return NULL; } HandleError err; HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); SteamWorksHTTPRequest *pRequest; if ((err = handlesys->ReadHandle(Handle, GetSteamHTTPHandle(), &sec, (void **)&pRequest)) != HandleError_None) { pContext->ThrowNativeError("Invalid Handle %x (error: %d)", Handle, err); return NULL; } return pRequest; } SteamWorksHTTPRequest::SteamWorksHTTPRequest() : request(INVALID_HTTPREQUEST_HANDLE), handle(BAD_HANDLE), pCompletedForward(NULL), pHeadersReceivedForward(NULL), pDataReceivedForward(NULL) { }; SteamWorksHTTPRequest::~SteamWorksHTTPRequest() { /* Requests are freed via a frame action, so on extension unload this can run after the dispatcher itself has been torn down; pSWHTTP is nulled in that case (see SDK_OnUnload), so guard against it. */ if (g_SteamWorks.pSWHTTP != NULL) { g_SteamWorks.pSWHTTP->UnregisterRequest(this); } 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); } /* Streaming header/data notifications are success-only callbacks (unlike the completion call result, they carry no IO-failure flag), so bFailure is always false here. Failures still surface through the completion callback. */ void SteamWorksHTTPRequest::OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pRequest) { if (this->pHeadersReceivedForward == NULL || this->pHeadersReceivedForward->GetFunctionCount() == 0) { return; } this->pHeadersReceivedForward->PushCell(this->handle); this->pHeadersReceivedForward->PushCell(false); this->pHeadersReceivedForward->PushCell(pRequest->m_ulContextValue >> 32); this->pHeadersReceivedForward->PushCell((pRequest->m_ulContextValue & 0x00000000FFFFFFFF)); this->pHeadersReceivedForward->Execute(NULL); } void SteamWorksHTTPRequest::OnHTTPDataReceived(HTTPRequestDataReceived_t *pRequest) { if (this->pDataReceivedForward == NULL || this->pDataReceivedForward->GetFunctionCount() == 0) { return; } this->pDataReceivedForward->PushCell(this->handle); this->pDataReceivedForward->PushCell(false); 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; g_SteamWorks.pSWHTTP->RegisterRequest(pRequest); return handle; } static cell_t sm_SetHTTPRequestContextValue(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } return pHTTP->SetHTTPRequestContextValue(pRequest->request, (static_cast(params[2]) << 32 | static_cast(params[3]))) ? 1 : 0; } static cell_t sm_SetHTTPRequestNetworkActivityTimeout(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } return pHTTP->SetHTTPRequestNetworkActivityTimeout(pRequest->request, params[2]) ? 1 : 0; } static cell_t sm_SetHTTPRequestHeaderValue(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } IPlugin *pPlugin; if (params[5] == BAD_HANDLE) { pPlugin = plsys->FindPluginByContext(SW_PLUGIN_CTX(pContext)); } else { HandleError err; 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 void SetCallbacks(SteamAPICall_t &hCall, SteamWorksHTTPRequest *pRequest) { /* Only completion is a call result of this send. Header/data streaming notifications are delivered as broadcast callbacks and routed to the request by SteamWorksHTTP's dispatcher, so there is nothing to bind to hCall here. */ if (pRequest->pCompletedForward != NULL) { pRequest->CompletedCallResult.SetGameserverFlag(); pRequest->CompletedCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPRequestCompleted); } } static cell_t sm_SendHTTPRequestAndStreamResponse(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } SteamAPICall_t hCall; cell_t result = pHTTP->SendHTTPRequestAndStreamResponse(pRequest->request, &hCall) ? 1 : 0; SetCallbacks(hCall, pRequest); return result; } static cell_t sm_SendHTTPRequest(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } SteamAPICall_t hCall; cell_t result = pHTTP->SendHTTPRequest(pRequest->request, &hCall) ? 1 : 0; SetCallbacks(hCall, pRequest); return result; } static cell_t sm_DeferHTTPRequest(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } return pHTTP->DeferHTTPRequest(pRequest->request) ? 1 : 0; } static cell_t sm_PrioritizeHTTPRequest(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } return pHTTP->PrioritizeHTTPRequest(pRequest->request) ? 1 : 0; } static cell_t sm_GetHTTPResponseHeaderSize(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } 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 cell_t sm_SetHTTPRequestRawPostBodyFromFile(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } char *pContentType, *pFilePath; pContext->LocalToString(params[2], &pContentType); pContext->LocalToString(params[3], &pFilePath); char szFinalPath[PLATFORM_MAX_PATH]; smutils->BuildPath(Path_Game, szFinalPath, sizeof(szFinalPath), "%s", pFilePath); FILE *pInputFile = fopen(szFinalPath, "rb"); if (!pInputFile) { return pContext->ThrowNativeError("Unable to open %s for reading. errno: %d", szFinalPath, errno); } fseek(pInputFile, 0, SEEK_END); uint32_t size = ftell(pInputFile); fseek(pInputFile, 0, SEEK_SET); if (size <= 0) { fclose(pInputFile); return 0; } char *pBuffer = new char[size + 1]; size_t itemsRead = fread(pBuffer, sizeof(char), size, pInputFile); fclose(pInputFile); if (itemsRead != size) { delete [] pBuffer; return 0; } cell_t result = pHTTP->SetHTTPRequestRawPostBody(pRequest->request, pContentType, reinterpret_cast(pBuffer), size) ? 1 : 0; delete [] pBuffer; return result; } static cell_t sm_GetHTTPResponseBodyCallback(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } IPlugin *pPlugin; if (params[4] == BAD_HANDLE) { pPlugin = plsys->FindPluginByContext(SW_PLUGIN_CTX(pContext)); } else { HandleError err; pPlugin = plsys->PluginFromHandle(params[4], &err); if (!pPlugin) { return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", params[4], err); } } IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[2]); if (!pFunction) { return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); } uint32_t size; if (pHTTP->GetHTTPResponseBodySize(pRequest->request, &size) == false) { return 0; } char *pBuffer = new char[size+1]; if (pHTTP->GetHTTPResponseBodyData(pRequest->request, reinterpret_cast(pBuffer), size) == false) { delete [] pBuffer; return 0; } pBuffer[size] = '\0'; /* Incase users do something bad; we want to protect userspace; kind of. */ pFunction->PushStringEx(pBuffer, size + 1, SM_PARAM_STRING_BINARY | SM_PARAM_STRING_COPY, 0); pFunction->PushCell(params[3]); pFunction->PushCell(size); pFunction->Execute(NULL); delete [] pBuffer; return 1; } static cell_t sm_WriteHTTPResponseBodyToFile(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } uint32_t size; if (pHTTP->GetHTTPResponseBodySize(pRequest->request, &size) == false) { return 0; } char *pBuffer = new char[size]; if (pHTTP->GetHTTPResponseBodyData(pRequest->request, reinterpret_cast(pBuffer), size) == false) { delete [] pBuffer; return 0; } char *pFilePath; pContext->LocalToString(params[2], &pFilePath); char szFinalPath[PLATFORM_MAX_PATH]; g_pSM->BuildPath(Path_Game, szFinalPath, sizeof(szFinalPath), "%s", pFilePath); FILE *pOutputFile = fopen(szFinalPath, "wb"); if (!pOutputFile) { delete [] pBuffer; return pContext->ThrowNativeError("Unable to open %s for writing. errno: %d", szFinalPath, errno); } fwrite(pBuffer, sizeof(char), size, pOutputFile); delete [] pBuffer; fclose(pOutputFile); return 1; } static cell_t sm_GetHTTPStreamingResponseBodyData(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } char *pBuffer; pContext->LocalToString(params[3], &pBuffer); return pHTTP->GetHTTPStreamingResponseBodyData(pRequest->request, params[2], reinterpret_cast(pBuffer), params[4]) ? 1 : 0; } static cell_t sm_SetHTTPRequestUserAgentInfo(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } char *pName; pContext->LocalToString(params[2], &pName); return pHTTP->SetHTTPRequestUserAgentInfo(pRequest->request, pName) ? 1 : 0; } static cell_t sm_SetHTTPRequestRequiresVerifiedCertificate(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } return pHTTP->SetHTTPRequestRequiresVerifiedCertificate(pRequest->request, !!params[2]) ? 1 : 0; } static cell_t sm_SetHTTPRequestAbsoluteTimeoutMS(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } return pHTTP->SetHTTPRequestAbsoluteTimeoutMS(pRequest->request, params[2]) ? 1 : 0; } static cell_t sm_GetHTTPRequestWasTimedOut(IPluginContext *pContext, const cell_t *params) { ISteamHTTP *pHTTP; SteamWorksHTTPRequest *pRequest = GetRequestPointer(pHTTP, pContext, params[1]); if (pRequest == NULL) { return 0; } cell_t *pData; pContext->LocalToPhysAddr(params[2], &pData); return pHTTP->GetHTTPRequestWasTimedOut(pRequest->request, reinterpret_cast(pData)) ? 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_SetHTTPRequestUserAgentInfo", sm_SetHTTPRequestUserAgentInfo}, {"SteamWorks_SetHTTPRequestRequiresVerifiedCertificate", sm_SetHTTPRequestRequiresVerifiedCertificate}, {"SteamWorks_SetHTTPRequestAbsoluteTimeoutMS", sm_SetHTTPRequestAbsoluteTimeoutMS}, {"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_GetHTTPRequestWasTimedOut", sm_GetHTTPRequestWasTimedOut}, {"SteamWorks_SetHTTPRequestRawPostBody", sm_SetHTTPRequestRawPostBody}, {"SteamWorks_SetHTTPRequestRawPostBodyFromFile", sm_SetHTTPRequestRawPostBodyFromFile}, {"SteamWorks_GetHTTPResponseBodyCallback", sm_GetHTTPResponseBodyCallback}, {"SteamWorks_WriteHTTPResponseBodyToFile", sm_WriteHTTPResponseBodyToFile}, {"SteamWorks_SendHTTPRequestAndStreamResponse", sm_SendHTTPRequestAndStreamResponse}, {"SteamWorks_GetHTTPStreamingResponseBodyData", sm_GetHTTPStreamingResponseBodyData}, /* SteamWorksHTTPRequest methodmap. These reuse the functions above; the implicit `this` handle arrives as params[1], exactly like the hHandle/hRequest first parameter of the free-function natives (and the constructor maps to the create native, whose first argument is likewise params[1]). */ {"SteamWorksHTTPRequest.SteamWorksHTTPRequest", sm_CreateHTTPRequest}, {"SteamWorksHTTPRequest.SetContextValue", sm_SetHTTPRequestContextValue}, {"SteamWorksHTTPRequest.SetNetworkActivityTimeout", sm_SetHTTPRequestNetworkActivityTimeout}, {"SteamWorksHTTPRequest.SetHeaderValue", sm_SetHTTPRequestHeaderValue}, {"SteamWorksHTTPRequest.SetGetOrPostParameter", sm_SetHTTPRequestGetOrPostParameter}, {"SteamWorksHTTPRequest.SetUserAgentInfo", sm_SetHTTPRequestUserAgentInfo}, {"SteamWorksHTTPRequest.SetRequiresVerifiedCertificate", sm_SetHTTPRequestRequiresVerifiedCertificate}, {"SteamWorksHTTPRequest.SetAbsoluteTimeoutMS", sm_SetHTTPRequestAbsoluteTimeoutMS}, {"SteamWorksHTTPRequest.SetCallbacks", sm_SetCallbacks}, {"SteamWorksHTTPRequest.Send", sm_SendHTTPRequest}, {"SteamWorksHTTPRequest.SendAndStreamResponse", sm_SendHTTPRequestAndStreamResponse}, {"SteamWorksHTTPRequest.Defer", sm_DeferHTTPRequest}, {"SteamWorksHTTPRequest.Prioritize", sm_PrioritizeHTTPRequest}, {"SteamWorksHTTPRequest.GetResponseHeaderSize", sm_GetHTTPResponseHeaderSize}, {"SteamWorksHTTPRequest.GetResponseHeaderValue", sm_GetHTTPResponseHeaderValue}, {"SteamWorksHTTPRequest.GetResponseBodySize", sm_GetHTTPResponseBodySize}, {"SteamWorksHTTPRequest.GetResponseBodyData", sm_GetHTTPResponseBodyData}, {"SteamWorksHTTPRequest.GetStreamingResponseBodyData", sm_GetHTTPStreamingResponseBodyData}, {"SteamWorksHTTPRequest.GetDownloadProgressPct", sm_GetHTTPDownloadProgressPct}, {"SteamWorksHTTPRequest.GetWasTimedOut", sm_GetHTTPRequestWasTimedOut}, {"SteamWorksHTTPRequest.SetRawPostBody", sm_SetHTTPRequestRawPostBody}, {"SteamWorksHTTPRequest.SetRawPostBodyFromFile", sm_SetHTTPRequestRawPostBodyFromFile}, {"SteamWorksHTTPRequest.GetResponseBodyCallback", sm_GetHTTPResponseBodyCallback}, {"SteamWorksHTTPRequest.WriteResponseBodyToFile", sm_WriteHTTPResponseBodyToFile}, {NULL, NULL} }; SteamWorksHTTPNatives::SteamWorksHTTPNatives() { sharesys->AddNatives(myself, httpnatives); } SteamWorksHTTPNatives::~SteamWorksHTTPNatives() { }