mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-12 18:42:36 +01:00
Replace cURL with WinHttp implementation on Windows
This reduces the number of third party dependencies for Windows builds. WinHttp is quite a nice straight forward API so doesn't involve too much extra code.
This commit is contained in:
@@ -53,7 +53,7 @@
|
|||||||
C4549: 'operator': operator before comma has no effect; did you intend 'operator'?
|
C4549: 'operator': operator before comma has no effect; did you intend 'operator'?
|
||||||
C4555: expression has no effect; expected expression with side-effect
|
C4555: expression has no effect; expected expression with side-effect
|
||||||
-->
|
-->
|
||||||
<PreprocessorDefinitions>__AVX2__;__SSE4_1__;OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>__AVX2__;__SSE4_1__;OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary Condition="'$(UseSharedLibs)'!='true'">MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary Condition="'$(UseSharedLibs)'!='true'">MultiThreaded</RuntimeLibrary>
|
||||||
<RuntimeLibrary Condition="'$(UseSharedLibs)'=='true'">MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary Condition="'$(UseSharedLibs)'=='true'">MultiThreadedDLL</RuntimeLibrary>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<AdditionalOptions>/utf-8 /std:c++17 /permissive- /Zc:externConstexpr</AdditionalOptions>
|
<AdditionalOptions>/utf-8 /std:c++17 /permissive- /Zc:externConstexpr</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>wininet.lib;imm32.lib;version.lib;winmm.lib;crypt32.lib;wldap32.lib;shlwapi.lib;setupapi.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>wininet.lib;imm32.lib;version.lib;winmm.lib;crypt32.lib;wldap32.lib;shlwapi.lib;setupapi.lib;bcrypt.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalOptions>/OPT:NOLBR /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/OPT:NOLBR /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>benchmarkd.lib;libbreakpadd.lib;libbreakpad_clientd.lib;bz2d.lib;discord-rpc.lib;freetyped.lib;jansson_d.lib;libcurl-d.lib;libpng16d.lib;libspeexdsp.lib;SDL2d.lib;zip.lib;zlibd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>benchmarkd.lib;libbreakpadd.lib;libbreakpad_clientd.lib;bz2d.lib;discord-rpc.lib;freetyped.lib;jansson_d.lib;libpng16d.lib;libspeexdsp.lib;SDL2d.lib;zip.lib;zlibd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>benchmark.lib;libbreakpad.lib;libbreakpad_client.lib;bz2.lib;discord-rpc.lib;freetype.lib;jansson.lib;libcurl.lib;libpng16.lib;libspeexdsp.lib;SDL2.lib;zip.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>benchmark.lib;libbreakpad.lib;libbreakpad_client.lib;bz2.lib;discord-rpc.lib;freetype.lib;jansson.lib;libpng16.lib;libspeexdsp.lib;SDL2.lib;zip.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
#include <openrct2-ui/interface/Widget.h>
|
#include <openrct2-ui/interface/Widget.h>
|
||||||
#include <openrct2-ui/windows/Window.h>
|
#include <openrct2-ui/windows/Window.h>
|
||||||
#include <openrct2/Context.h>
|
#include <openrct2/Context.h>
|
||||||
|
#include <openrct2/core/Http.h>
|
||||||
#include <openrct2/core/Json.hpp>
|
#include <openrct2/core/Json.hpp>
|
||||||
#include <openrct2/core/String.hpp>
|
#include <openrct2/core/String.hpp>
|
||||||
#include <openrct2/localisation/Localisation.h>
|
#include <openrct2/localisation/Localisation.h>
|
||||||
#include <openrct2/network/Http.h>
|
|
||||||
#include <openrct2/object/ObjectList.h>
|
#include <openrct2/object/ObjectList.h>
|
||||||
#include <openrct2/object/ObjectManager.h>
|
#include <openrct2/object/ObjectManager.h>
|
||||||
#include <openrct2/object/ObjectRepository.h>
|
#include <openrct2/object/ObjectRepository.h>
|
||||||
@@ -151,7 +151,6 @@ private:
|
|||||||
|
|
||||||
void DownloadObject(const rct_object_entry& entry, const std::string name, const std::string url)
|
void DownloadObject(const rct_object_entry& entry, const std::string name, const std::string url)
|
||||||
{
|
{
|
||||||
using namespace OpenRCT2::Networking;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::printf("Downloading %s\n", url.c_str());
|
std::printf("Downloading %s\n", url.c_str());
|
||||||
@@ -190,8 +189,6 @@ private:
|
|||||||
|
|
||||||
void NextDownload()
|
void NextDownload()
|
||||||
{
|
{
|
||||||
using namespace OpenRCT2::Networking;
|
|
||||||
|
|
||||||
if (!_downloadingObjects || _currentDownloadIndex >= _entries.size())
|
if (!_downloadingObjects || _currentDownloadIndex >= _entries.size())
|
||||||
{
|
{
|
||||||
// Finished...
|
// Finished...
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
# include <openrct2/drawing/Drawing.h>
|
# include <openrct2/drawing/Drawing.h>
|
||||||
# include <openrct2/interface/Colour.h>
|
# include <openrct2/interface/Colour.h>
|
||||||
# include <openrct2/localisation/Localisation.h>
|
# include <openrct2/localisation/Localisation.h>
|
||||||
# include <openrct2/network/Http.h>
|
|
||||||
# include <openrct2/network/ServerList.h>
|
# include <openrct2/network/ServerList.h>
|
||||||
# include <openrct2/network/network.h>
|
# include <openrct2/network/network.h>
|
||||||
# include <openrct2/platform/platform.h>
|
# include <openrct2/platform/platform.h>
|
||||||
|
|||||||
@@ -50,12 +50,10 @@ if (NOT DISABLE_NETWORK AND WIN32)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT DISABLE_HTTP)
|
if (NOT DISABLE_HTTP)
|
||||||
if (MSVC)
|
if (WIN32)
|
||||||
find_package(curl REQUIRED)
|
target_link_libraries(${PROJECT_NAME} winhttp)
|
||||||
set(LIBCURL_LIBRARIES ${CURL_LIBRARIES})
|
|
||||||
else ()
|
else ()
|
||||||
PKG_CHECK_MODULES(LIBCURL REQUIRED libcurl)
|
PKG_CHECK_MODULES(LIBCURL REQUIRED libcurl)
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${LIBCURL_INCLUDE_DIRS})
|
target_include_directories(${PROJECT_NAME} PRIVATE ${LIBCURL_INCLUDE_DIRS})
|
||||||
|
|
||||||
@@ -64,6 +62,7 @@ if (NOT DISABLE_HTTP)
|
|||||||
else ()
|
else ()
|
||||||
target_link_libraries(${PROJECT_NAME} ${LIBCURL_LIBRARIES})
|
target_link_libraries(${PROJECT_NAME} ${LIBCURL_LIBRARIES})
|
||||||
endif ()
|
endif ()
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT DISABLE_TTF)
|
if (NOT DISABLE_TTF)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "core/FileScanner.h"
|
#include "core/FileScanner.h"
|
||||||
#include "core/FileStream.hpp"
|
#include "core/FileStream.hpp"
|
||||||
#include "core/Guard.hpp"
|
#include "core/Guard.hpp"
|
||||||
|
#include "core/Http.h"
|
||||||
#include "core/MemoryStream.h"
|
#include "core/MemoryStream.h"
|
||||||
#include "core/Path.hpp"
|
#include "core/Path.hpp"
|
||||||
#include "core/String.hpp"
|
#include "core/String.hpp"
|
||||||
@@ -45,7 +46,6 @@
|
|||||||
#include "localisation/Localisation.h"
|
#include "localisation/Localisation.h"
|
||||||
#include "localisation/LocalisationService.h"
|
#include "localisation/LocalisationService.h"
|
||||||
#include "network/DiscordService.h"
|
#include "network/DiscordService.h"
|
||||||
#include "network/Http.h"
|
|
||||||
#include "network/Twitch.h"
|
#include "network/Twitch.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
#include "object/ObjectManager.h"
|
#include "object/ObjectManager.h"
|
||||||
@@ -99,9 +99,6 @@ namespace OpenRCT2
|
|||||||
std::unique_ptr<DiscordService> _discordService;
|
std::unique_ptr<DiscordService> _discordService;
|
||||||
#endif
|
#endif
|
||||||
StdInOutConsole _stdInOutConsole;
|
StdInOutConsole _stdInOutConsole;
|
||||||
#ifndef DISABLE_HTTP
|
|
||||||
Networking::Http::Http _http;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Game states
|
// Game states
|
||||||
std::unique_ptr<TitleScreen> _titleScreen;
|
std::unique_ptr<TitleScreen> _titleScreen;
|
||||||
@@ -721,15 +718,14 @@ namespace OpenRCT2
|
|||||||
{
|
{
|
||||||
#ifndef DISABLE_HTTP
|
#ifndef DISABLE_HTTP
|
||||||
// Download park and open it using its temporary filename
|
// Download park and open it using its temporary filename
|
||||||
void* data;
|
auto data = DownloadPark(gOpenRCT2StartupActionPath);
|
||||||
size_t dataSize = Networking::Http::DownloadPark(gOpenRCT2StartupActionPath, &data);
|
if (data.empty())
|
||||||
if (dataSize == 0)
|
|
||||||
{
|
{
|
||||||
title_load();
|
title_load();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ms = MemoryStream(data, dataSize, MEMORY_ACCESS::OWNER);
|
auto ms = MemoryStream(data.data(), data.size(), MEMORY_ACCESS::READ);
|
||||||
if (!LoadParkFromStream(&ms, gOpenRCT2StartupActionPath, true))
|
if (!LoadParkFromStream(&ms, gOpenRCT2StartupActionPath, true))
|
||||||
{
|
{
|
||||||
Console::Error::WriteLine("Failed to load '%s'", gOpenRCT2StartupActionPath);
|
Console::Error::WriteLine("Failed to load '%s'", gOpenRCT2StartupActionPath);
|
||||||
@@ -1083,6 +1079,34 @@ namespace OpenRCT2
|
|||||||
}
|
}
|
||||||
delete scanner;
|
delete scanner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_HTTP
|
||||||
|
std::vector<uint8_t> DownloadPark(const std::string& url)
|
||||||
|
{
|
||||||
|
// Download park to buffer in memory
|
||||||
|
Http::Request request;
|
||||||
|
request.url = url;
|
||||||
|
request.method = Http::Method::GET;
|
||||||
|
|
||||||
|
Http::Response res;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
res = Do(request);
|
||||||
|
if (res.status != Http::Status::OK)
|
||||||
|
throw std::runtime_error("bad http status");
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
Console::Error::WriteLine("Failed to download '%s', cause %s", request.url.c_str(), e.what());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> parkData;
|
||||||
|
parkData.resize(res.body.size());
|
||||||
|
std::memcpy(parkData.data(), res.body.c_str(), parkData.size());
|
||||||
|
return parkData;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
Context* Context::Instance = nullptr;
|
Context* Context::Instance = nullptr;
|
||||||
|
|||||||
223
src/openrct2/core/Http.WinHttp.cpp
Normal file
223
src/openrct2/core/Http.WinHttp.cpp
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||||
|
*
|
||||||
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
|
*
|
||||||
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(DISABLE_HTTP) && defined(_WIN32)
|
||||||
|
|
||||||
|
# include "Http.h"
|
||||||
|
|
||||||
|
# include "../Version.h"
|
||||||
|
# include "String.hpp"
|
||||||
|
|
||||||
|
# include <cstdio>
|
||||||
|
# include <stdexcept>
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# include <windows.h>
|
||||||
|
# include <winhttp.h>
|
||||||
|
|
||||||
|
namespace Http
|
||||||
|
{
|
||||||
|
static constexpr char OPENRCT2_USER_AGENT[] = "OpenRCT2/" OPENRCT2_VERSION;
|
||||||
|
|
||||||
|
static void ThrowWin32Exception(const char* methodName)
|
||||||
|
{
|
||||||
|
auto errorCode = GetLastError();
|
||||||
|
auto msg = String::StdFormat("%s failed, error: %d.", methodName, errorCode);
|
||||||
|
throw std::runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const wchar_t* GetVerb(Method method)
|
||||||
|
{
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case Method::GET:
|
||||||
|
return L"GET";
|
||||||
|
case Method::POST:
|
||||||
|
return L"POST";
|
||||||
|
case Method::PUT:
|
||||||
|
return L"PUT";
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Unsupported verb.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::wstring ReadHeader(HINTERNET hRequest, DWORD infoLevel, const wchar_t* name)
|
||||||
|
{
|
||||||
|
wchar_t headerBuffer[256]{};
|
||||||
|
auto headerBufferLen = (DWORD)std::size(headerBuffer);
|
||||||
|
if (!WinHttpQueryHeaders(hRequest, infoLevel, name, headerBuffer, &headerBufferLen, WINHTTP_NO_HEADER_INDEX))
|
||||||
|
ThrowWin32Exception("WinHttpQueryHeaders");
|
||||||
|
return std::wstring(headerBuffer, headerBufferLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t ReadStatusCode(HINTERNET hRequest)
|
||||||
|
{
|
||||||
|
auto wStatusCode = ReadHeader(hRequest, WINHTTP_QUERY_STATUS_CODE, L"StatusCode");
|
||||||
|
return std::stoi(wStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<std::string, std::string> ReadHeaders(HINTERNET hRequest)
|
||||||
|
{
|
||||||
|
DWORD dwSize{};
|
||||||
|
WinHttpQueryHeaders(
|
||||||
|
hRequest, WINHTTP_QUERY_RAW_HEADERS, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
|
||||||
|
|
||||||
|
std::wstring buffer;
|
||||||
|
buffer.resize(dwSize);
|
||||||
|
if (!WinHttpQueryHeaders(
|
||||||
|
hRequest, WINHTTP_QUERY_RAW_HEADERS, WINHTTP_HEADER_NAME_BY_INDEX, buffer.data(), &dwSize,
|
||||||
|
WINHTTP_NO_HEADER_INDEX))
|
||||||
|
ThrowWin32Exception("WinHttpQueryHeaders");
|
||||||
|
|
||||||
|
std::map<std::string, std::string> headers;
|
||||||
|
std::wstring wKey, wValue;
|
||||||
|
int state = 0;
|
||||||
|
int index = 0;
|
||||||
|
for (auto c : buffer)
|
||||||
|
{
|
||||||
|
if (c == '\0')
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
if (index != 0 && wKey.size() != 0)
|
||||||
|
{
|
||||||
|
auto key = String::ToUtf8(wKey);
|
||||||
|
auto value = String::ToUtf8(wValue);
|
||||||
|
headers[key] = value;
|
||||||
|
}
|
||||||
|
wKey.clear();
|
||||||
|
wValue.clear();
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (state == 0 && c == ':')
|
||||||
|
{
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
else if (state == 1 && c == ' ')
|
||||||
|
{
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
|
else if (state == 0)
|
||||||
|
{
|
||||||
|
wKey.push_back(c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = 2;
|
||||||
|
wValue.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string ReadBody(HINTERNET hRequest)
|
||||||
|
{
|
||||||
|
DWORD dwSize{};
|
||||||
|
std::string body;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Check for available data.
|
||||||
|
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
|
||||||
|
ThrowWin32Exception("WinHttpQueryDataAvailable");
|
||||||
|
|
||||||
|
// No more available data.
|
||||||
|
if (dwSize == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto offset = body.size();
|
||||||
|
body.resize(offset + dwSize);
|
||||||
|
auto dst = (LPVOID)&body[offset];
|
||||||
|
|
||||||
|
DWORD dwDownloaded{};
|
||||||
|
if (!WinHttpReadData(hRequest, dst, dwSize, &dwDownloaded))
|
||||||
|
ThrowWin32Exception("WinHttpReadData");
|
||||||
|
|
||||||
|
// This condition should never be reached since WinHttpQueryDataAvailable
|
||||||
|
// reported that there are bits to read.
|
||||||
|
if (dwDownloaded == 0)
|
||||||
|
break;
|
||||||
|
} while (dwSize > 0);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response Do(const Request& req)
|
||||||
|
{
|
||||||
|
HINTERNET hSession{}, hConnect{}, hRequest{};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
URL_COMPONENTS url;
|
||||||
|
ZeroMemory(&url, sizeof(url));
|
||||||
|
url.dwStructSize = sizeof(url);
|
||||||
|
url.dwSchemeLength = (DWORD)-1;
|
||||||
|
url.dwHostNameLength = (DWORD)-1;
|
||||||
|
url.dwUrlPathLength = (DWORD)-1;
|
||||||
|
url.dwExtraInfoLength = (DWORD)-1;
|
||||||
|
|
||||||
|
auto wUrl = String::ToWideChar(req.url);
|
||||||
|
if (!WinHttpCrackUrl(wUrl.c_str(), 0, 0, &url))
|
||||||
|
throw std::invalid_argument("Unable to parse URI.");
|
||||||
|
|
||||||
|
auto userAgent = String::ToWideChar(OPENRCT2_USER_AGENT);
|
||||||
|
hSession = WinHttpOpen(
|
||||||
|
userAgent.c_str(), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
||||||
|
if (hSession == nullptr)
|
||||||
|
ThrowWin32Exception("WinHttpOpen");
|
||||||
|
|
||||||
|
auto wHostName = std::wstring(url.lpszHostName, url.dwHostNameLength);
|
||||||
|
hConnect = WinHttpConnect(hSession, wHostName.c_str(), url.nPort, 0);
|
||||||
|
if (hConnect == nullptr)
|
||||||
|
ThrowWin32Exception("WinHttpConnect");
|
||||||
|
|
||||||
|
auto wVerb = GetVerb(req.method);
|
||||||
|
auto wQuery = std::wstring(url.lpszUrlPath, url.dwUrlPathLength);
|
||||||
|
hRequest = WinHttpOpenRequest(
|
||||||
|
hConnect, wVerb, wQuery.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
|
||||||
|
if (hRequest == nullptr)
|
||||||
|
ThrowWin32Exception("WinHttpOpenRequest");
|
||||||
|
|
||||||
|
for (auto header : req.header)
|
||||||
|
{
|
||||||
|
auto fullHeader = String::ToWideChar(header.first) + L": " + String::ToWideChar(header.second);
|
||||||
|
if (!WinHttpAddRequestHeaders(hRequest, fullHeader.c_str(), (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD))
|
||||||
|
ThrowWin32Exception("WinHttpAddRequestHeaders");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto reqBody = (LPVOID)req.body.data();
|
||||||
|
auto reqBodyLen = (DWORD)req.body.size();
|
||||||
|
if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, reqBody, reqBodyLen, reqBodyLen, 0))
|
||||||
|
ThrowWin32Exception("WinHttpSendRequest");
|
||||||
|
|
||||||
|
if (!WinHttpReceiveResponse(hRequest, NULL))
|
||||||
|
ThrowWin32Exception("WinHttpReceiveResponse");
|
||||||
|
|
||||||
|
auto statusCode = ReadStatusCode(hRequest);
|
||||||
|
auto contentType = ReadHeader(hRequest, WINHTTP_QUERY_CONTENT_TYPE, L"Content-Type");
|
||||||
|
auto headers = ReadHeaders(hRequest);
|
||||||
|
auto body = ReadBody(hRequest);
|
||||||
|
|
||||||
|
Response response;
|
||||||
|
response.body = std::move(body);
|
||||||
|
response.status = (Status)statusCode;
|
||||||
|
response.content_type = String::ToUtf8(contentType);
|
||||||
|
response.header = headers;
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
catch ([[maybe_unused]] const std::exception& e)
|
||||||
|
{
|
||||||
|
# ifdef DEBUG
|
||||||
|
std::fprintf(stderr, "HTTP request failed: %s\n", e.what());
|
||||||
|
# endif
|
||||||
|
WinHttpCloseHandle(hSession);
|
||||||
|
WinHttpCloseHandle(hConnect);
|
||||||
|
WinHttpCloseHandle(hRequest);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Http
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Copyright (c) 2014-2019 OpenRCT2 developers
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||||
*
|
*
|
||||||
* For a complete list of all authors, please refer to contributors.md
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
@@ -7,17 +7,16 @@
|
|||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "Http.h"
|
#if !defined(DISABLE_HTTP) && !defined(_WIN32)
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <memory>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#ifndef DISABLE_HTTP
|
|
||||||
|
|
||||||
# include "../Version.h"
|
# include "../Version.h"
|
||||||
# include "../core/Console.hpp"
|
# include "../core/Console.hpp"
|
||||||
|
# include "Http.h"
|
||||||
|
|
||||||
|
# include <cstring>
|
||||||
|
# include <memory>
|
||||||
|
# include <stdexcept>
|
||||||
|
# include <thread>
|
||||||
|
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
// cURL includes windows.h, but we don't need all of it.
|
// cURL includes windows.h, but we don't need all of it.
|
||||||
@@ -27,18 +26,8 @@
|
|||||||
|
|
||||||
# define OPENRCT2_USER_AGENT "OpenRCT2/" OPENRCT2_VERSION
|
# define OPENRCT2_USER_AGENT "OpenRCT2/" OPENRCT2_VERSION
|
||||||
|
|
||||||
namespace OpenRCT2::Networking::Http
|
namespace Http
|
||||||
{
|
{
|
||||||
Http::Http()
|
|
||||||
{
|
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
Http::~Http()
|
|
||||||
{
|
|
||||||
curl_global_cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t writeData(const char* src, size_t size, size_t nmemb, void* userdata)
|
static size_t writeData(const char* src, size_t size, size_t nmemb, void* userdata)
|
||||||
{
|
{
|
||||||
size_t realsize = size * nmemb;
|
size_t realsize = size * nmemb;
|
||||||
@@ -168,59 +157,6 @@ namespace OpenRCT2::Networking::Http
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoAsync(const Request& req, std::function<void(Response& res)> fn)
|
} // namespace Http
|
||||||
{
|
|
||||||
auto thread = std::thread([=]() {
|
|
||||||
Response res;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
res = Do(req);
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
res.error = e.what();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fn(res);
|
|
||||||
});
|
|
||||||
thread.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t DownloadPark(const char* url, void** outData)
|
|
||||||
{
|
|
||||||
// Download park to buffer in memory
|
|
||||||
Request request;
|
|
||||||
request.url = url;
|
|
||||||
request.method = Method::GET;
|
|
||||||
|
|
||||||
Response res;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
res = Do(request);
|
|
||||||
if (res.status != Status::OK)
|
|
||||||
std::runtime_error("bad http status");
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
Console::Error::WriteLine("Failed to download '%s', cause %s", request.url.c_str(), e.what());
|
|
||||||
*outData = nullptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t dataSize = res.body.size() - 1;
|
|
||||||
void* data = malloc(dataSize);
|
|
||||||
if (data == nullptr)
|
|
||||||
{
|
|
||||||
Console::Error::WriteLine("Failed to allocate memory for downloaded park.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::memcpy(data, res.body.c_str(), dataSize);
|
|
||||||
*outData = data;
|
|
||||||
|
|
||||||
return dataSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace OpenRCT2::Networking::Http
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Copyright (c) 2014-2019 OpenRCT2 developers
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||||
*
|
*
|
||||||
* For a complete list of all authors, please refer to contributors.md
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
@@ -16,8 +16,9 @@
|
|||||||
# include <functional>
|
# include <functional>
|
||||||
# include <map>
|
# include <map>
|
||||||
# include <string>
|
# include <string>
|
||||||
|
# include <thread>
|
||||||
|
|
||||||
namespace OpenRCT2::Networking::Http
|
namespace Http
|
||||||
{
|
{
|
||||||
enum class Status
|
enum class Status
|
||||||
{
|
{
|
||||||
@@ -50,24 +51,25 @@ namespace OpenRCT2::Networking::Http
|
|||||||
bool forceIPv4 = false;
|
bool forceIPv4 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Http
|
|
||||||
{
|
|
||||||
Http();
|
|
||||||
~Http();
|
|
||||||
};
|
|
||||||
|
|
||||||
Response Do(const Request& req);
|
Response Do(const Request& req);
|
||||||
void DoAsync(const Request& req, std::function<void(Response& res)> fn);
|
|
||||||
|
|
||||||
/**
|
inline void DoAsync(const Request& req, std::function<void(Response& res)> fn)
|
||||||
* Download a park via HTTP/S from the given URL into a memory buffer. This is
|
{
|
||||||
* a blocking operation.
|
auto thread = std::thread([=]() {
|
||||||
* @param url The URL to download the park from.
|
Response res;
|
||||||
* @param outData The data returned.
|
try
|
||||||
* @returns The size of the data or 0 if the download failed.
|
{
|
||||||
*/
|
res = Do(req);
|
||||||
size_t DownloadPark(const char* url, void** outData);
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
} // namespace OpenRCT2::Networking::Http
|
{
|
||||||
|
res.error = e.what();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fn(res);
|
||||||
|
});
|
||||||
|
thread.detach();
|
||||||
|
}
|
||||||
|
} // namespace Http
|
||||||
|
|
||||||
#endif // DISABLE_HTTP
|
#endif // DISABLE_HTTP
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
# include "../config/Config.h"
|
# include "../config/Config.h"
|
||||||
# include "../core/Console.hpp"
|
# include "../core/Console.hpp"
|
||||||
|
# include "../core/Http.h"
|
||||||
# include "../core/Json.hpp"
|
# include "../core/Json.hpp"
|
||||||
# include "../core/String.hpp"
|
# include "../core/String.hpp"
|
||||||
# include "../localisation/Date.h"
|
# include "../localisation/Date.h"
|
||||||
@@ -23,7 +24,6 @@
|
|||||||
# include "../util/Util.h"
|
# include "../util/Util.h"
|
||||||
# include "../world/Map.h"
|
# include "../world/Map.h"
|
||||||
# include "../world/Park.h"
|
# include "../world/Park.h"
|
||||||
# include "Http.h"
|
|
||||||
# include "Socket.h"
|
# include "Socket.h"
|
||||||
# include "network.h"
|
# include "network.h"
|
||||||
|
|
||||||
@@ -164,8 +164,6 @@ private:
|
|||||||
|
|
||||||
void SendRegistration(bool forceIPv4)
|
void SendRegistration(bool forceIPv4)
|
||||||
{
|
{
|
||||||
using namespace OpenRCT2::Networking;
|
|
||||||
|
|
||||||
_lastAdvertiseTime = platform_get_ticks();
|
_lastAdvertiseTime = platform_get_ticks();
|
||||||
|
|
||||||
// Send the registration request
|
// Send the registration request
|
||||||
@@ -199,8 +197,6 @@ private:
|
|||||||
|
|
||||||
void SendHeartbeat()
|
void SendHeartbeat()
|
||||||
{
|
{
|
||||||
using namespace OpenRCT2::Networking;
|
|
||||||
|
|
||||||
Http::Request request;
|
Http::Request request;
|
||||||
request.url = GetMasterServerUrl();
|
request.url = GetMasterServerUrl();
|
||||||
request.method = Http::Method::PUT;
|
request.method = Http::Method::PUT;
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
# include "../PlatformEnvironment.h"
|
# include "../PlatformEnvironment.h"
|
||||||
# include "../config/Config.h"
|
# include "../config/Config.h"
|
||||||
# include "../core/FileStream.hpp"
|
# include "../core/FileStream.hpp"
|
||||||
|
# include "../core/Http.h"
|
||||||
# include "../core/Json.hpp"
|
# include "../core/Json.hpp"
|
||||||
# include "../core/Memory.hpp"
|
# include "../core/Memory.hpp"
|
||||||
# include "../core/Path.hpp"
|
# include "../core/Path.hpp"
|
||||||
# include "../core/String.hpp"
|
# include "../core/String.hpp"
|
||||||
# include "../network/Http.h"
|
|
||||||
# include "../platform/platform.h"
|
# include "../platform/platform.h"
|
||||||
# include "Socket.h"
|
# include "Socket.h"
|
||||||
# include "network.h"
|
# include "network.h"
|
||||||
@@ -331,7 +331,6 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync
|
|||||||
# ifdef DISABLE_HTTP
|
# ifdef DISABLE_HTTP
|
||||||
return {};
|
return {};
|
||||||
# else
|
# else
|
||||||
using namespace OpenRCT2::Networking;
|
|
||||||
|
|
||||||
auto p = std::make_shared<std::promise<std::vector<ServerListEntry>>>();
|
auto p = std::make_shared<std::promise<std::vector<ServerListEntry>>>();
|
||||||
auto f = p->get_future();
|
auto f = p->get_future();
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace Twitch
|
|||||||
# include "../OpenRCT2.h"
|
# include "../OpenRCT2.h"
|
||||||
# include "../actions/GuestSetFlagsAction.hpp"
|
# include "../actions/GuestSetFlagsAction.hpp"
|
||||||
# include "../config/Config.h"
|
# include "../config/Config.h"
|
||||||
|
# include "../core/Http.h"
|
||||||
# include "../core/Json.hpp"
|
# include "../core/Json.hpp"
|
||||||
# include "../core/String.hpp"
|
# include "../core/String.hpp"
|
||||||
# include "../drawing/Drawing.h"
|
# include "../drawing/Drawing.h"
|
||||||
@@ -39,7 +40,6 @@ namespace Twitch
|
|||||||
# include "../platform/platform.h"
|
# include "../platform/platform.h"
|
||||||
# include "../util/Util.h"
|
# include "../util/Util.h"
|
||||||
# include "../world/Sprite.h"
|
# include "../world/Sprite.h"
|
||||||
# include "Http.h"
|
|
||||||
# include "Twitch.h"
|
# include "Twitch.h"
|
||||||
|
|
||||||
# include <jansson.h>
|
# include <jansson.h>
|
||||||
@@ -47,7 +47,6 @@ namespace Twitch
|
|||||||
# include <vector>
|
# include <vector>
|
||||||
|
|
||||||
using namespace OpenRCT2;
|
using namespace OpenRCT2;
|
||||||
using namespace OpenRCT2::Networking;
|
|
||||||
|
|
||||||
bool gTwitchEnable = false;
|
bool gTwitchEnable = false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user