Use curl
This commit is contained in:
parent
3b925519ad
commit
ed7decf8a9
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -45,3 +45,6 @@
|
|||||||
path = deps/zlib
|
path = deps/zlib
|
||||||
url = https://github.com/madler/zlib.git
|
url = https://github.com/madler/zlib.git
|
||||||
branch = develop
|
branch = develop
|
||||||
|
[submodule "deps/curl"]
|
||||||
|
path = deps/curl
|
||||||
|
url = https://github.com/curl/curl.git
|
||||||
|
1
deps/curl
vendored
Submodule
1
deps/curl
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit d64115d7bb8ae4c136b620912da523c063f1d2ee
|
73
deps/premake/curl.lua
vendored
Normal file
73
deps/premake/curl.lua
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
curl = {
|
||||||
|
source = path.join(dependencies.basePath, "curl"),
|
||||||
|
}
|
||||||
|
|
||||||
|
function curl.import()
|
||||||
|
links { "curl" }
|
||||||
|
|
||||||
|
filter "toolset:msc*"
|
||||||
|
links { "Crypt32.lib" }
|
||||||
|
filter {}
|
||||||
|
|
||||||
|
curl.includes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function curl.includes()
|
||||||
|
filter "toolset:msc*"
|
||||||
|
includedirs {
|
||||||
|
path.join(curl.source, "include"),
|
||||||
|
}
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"CURL_STRICTER",
|
||||||
|
"CURL_STATICLIB",
|
||||||
|
"CURL_DISABLE_LDAP",
|
||||||
|
}
|
||||||
|
filter {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function curl.project()
|
||||||
|
if not os.istarget("windows") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
project "curl"
|
||||||
|
language "C"
|
||||||
|
|
||||||
|
curl.includes()
|
||||||
|
|
||||||
|
includedirs {
|
||||||
|
path.join(curl.source, "lib"),
|
||||||
|
}
|
||||||
|
|
||||||
|
files {
|
||||||
|
path.join(curl.source, "lib/**.c"),
|
||||||
|
path.join(curl.source, "lib/**.h"),
|
||||||
|
}
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"BUILDING_LIBCURL",
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "toolset:msc*"
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"USE_SCHANNEL",
|
||||||
|
"USE_WINDOWS_SSPI",
|
||||||
|
"USE_THREADS_WIN32",
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "toolset:not msc*"
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"USE_GNUTLS",
|
||||||
|
"USE_THREADS_POSIX",
|
||||||
|
}
|
||||||
|
|
||||||
|
filter {}
|
||||||
|
|
||||||
|
warnings "Off"
|
||||||
|
kind "StaticLib"
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(dependencies, curl)
|
@ -138,21 +138,37 @@ namespace discord
|
|||||||
{
|
{
|
||||||
const auto data = utils::http::get_data(
|
const auto data = utils::http::get_data(
|
||||||
utils::string::va(AVATAR_URL, id.data(), avatar.data()));
|
utils::string::va(AVATAR_URL, id.data(), avatar.data()));
|
||||||
if (data.has_value())
|
if (!data.has_value())
|
||||||
{
|
{
|
||||||
materials::add(utils::string::va(AVATAR, id.data()), data.value());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& value = data.value();
|
||||||
|
if (value.code != CURLE_OK)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
materials::add(utils::string::va(AVATAR, id.data()), value.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_default_avatar = false;
|
bool has_default_avatar = false;
|
||||||
void download_default_avatar()
|
void download_default_avatar()
|
||||||
{
|
{
|
||||||
const auto data = utils::http::get_data(DEFAULT_AVATAR_URL);
|
const auto data = utils::http::get_data(DEFAULT_AVATAR_URL);
|
||||||
if (data.has_value())
|
if (!data.has_value())
|
||||||
{
|
{
|
||||||
has_default_avatar = true;
|
return;
|
||||||
materials::add(DEFAULT_AVATAR, data.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& value = data.value();
|
||||||
|
if (value.code != CURLE_OK)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
has_default_avatar = true;
|
||||||
|
materials::add(DEFAULT_AVATAR, value.buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +375,23 @@ namespace server_list
|
|||||||
insert_server(std::move(server));
|
insert_server(std::move(server));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_player_count()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(mutex);
|
||||||
|
auto count = 0;
|
||||||
|
for (const auto& server : servers)
|
||||||
|
{
|
||||||
|
count += server.clients - server.bots;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_server_count()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> _(mutex);
|
||||||
|
return static_cast<int>(servers.size());
|
||||||
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -26,9 +26,9 @@
|
|||||||
#define DATA_PATH "data/"
|
#define DATA_PATH "data/"
|
||||||
#define DATA_PATH_DEV "data-dev/"
|
#define DATA_PATH_DEV "data-dev/"
|
||||||
|
|
||||||
#define ERR_UPDATE_CHECK_FAIL "Failed to check for updates"
|
#define ERR_UPDATE_CHECK_FAIL "Failed to check for updates:\n%s"
|
||||||
#define ERR_UPDATE_CHECK_FAIL_BAD_RESPONSE "Bad response"
|
#define ERR_UPDATE_CHECK_FAIL_BAD_RESPONSE "Bad response"
|
||||||
#define ERR_DOWNLOAD_FAIL "Failed to download file "
|
#define ERR_DOWNLOAD_FAIL "Failed to download file %s:\n%s"
|
||||||
#define ERR_WRITE_FAIL "Failed to write file "
|
#define ERR_WRITE_FAIL "Failed to write file "
|
||||||
|
|
||||||
#define BINARY_NAME "h1-mod.exe"
|
#define BINARY_NAME "h1-mod.exe"
|
||||||
@ -139,7 +139,7 @@ namespace updater
|
|||||||
return utils::string::va("%i", uint32_t(time(nullptr)));
|
return utils::string::va("%i", uint32_t(time(nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> download_file(const std::string& name)
|
std::optional<utils::http::result> download_file(const std::string& name)
|
||||||
{
|
{
|
||||||
return utils::http::get_data(MASTER + select(DATA_PATH, DATA_PATH_DEV) + name + "?" + get_time_str());
|
return utils::http::get_data(MASTER + select(DATA_PATH, DATA_PATH_DEV) + name + "?" + get_time_str());
|
||||||
}
|
}
|
||||||
@ -191,6 +191,12 @@ namespace updater
|
|||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string curl_error(CURLcode code)
|
||||||
|
{
|
||||||
|
const auto str_error = curl_easy_strerror(code);
|
||||||
|
return utils::string::va("%s (%i)", str_error, code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// workaround
|
// workaround
|
||||||
@ -337,12 +343,20 @@ namespace updater
|
|||||||
|
|
||||||
if (!files_data.has_value())
|
if (!files_data.has_value())
|
||||||
{
|
{
|
||||||
set_update_check_status(true, false, ERR_UPDATE_CHECK_FAIL);
|
set_update_check_status(true, false, utils::string::va(ERR_UPDATE_CHECK_FAIL, "Unknown error"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& value = files_data.value();
|
||||||
|
if (value.code != CURLE_OK)
|
||||||
|
{
|
||||||
|
const auto error = curl_error(value.code);
|
||||||
|
set_update_check_status(true, false, utils::string::va(ERR_UPDATE_CHECK_FAIL, error.data()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rapidjson::Document j;
|
rapidjson::Document j;
|
||||||
j.Parse(files_data.value().data());
|
j.Parse(value.buffer.data());
|
||||||
|
|
||||||
if (!j.IsArray())
|
if (!j.IsArray())
|
||||||
{
|
{
|
||||||
@ -433,11 +447,19 @@ namespace updater
|
|||||||
|
|
||||||
if (!data.has_value())
|
if (!data.has_value())
|
||||||
{
|
{
|
||||||
set_update_download_status(true, false, ERR_DOWNLOAD_FAIL + file);
|
set_update_download_status(true, false, utils::string::va(ERR_DOWNLOAD_FAIL, file.data(), "Unknown error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
downloads.push_back({file, data.value()});
|
const auto& value = data.value();
|
||||||
|
if (value.code != CURLE_OK)
|
||||||
|
{
|
||||||
|
const auto error = curl_error(value.code);
|
||||||
|
set_update_download_status(true, false, utils::string::va(ERR_DOWNLOAD_FAIL, file.data(), error.data()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
downloads.push_back({file, value.buffer});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& download : downloads)
|
for (const auto& download : downloads)
|
||||||
|
@ -4,41 +4,63 @@
|
|||||||
|
|
||||||
namespace utils::http
|
namespace utils::http
|
||||||
{
|
{
|
||||||
std::optional<std::string> get_data(const std::string& url)
|
namespace
|
||||||
{
|
{
|
||||||
CComPtr<IStream> stream;
|
size_t write_callback(void* contents, const size_t size, const size_t nmemb, void* userp)
|
||||||
|
|
||||||
if (FAILED(URLOpenBlockingStreamA(nullptr, url.data(), &stream, 0, nullptr)))
|
|
||||||
{
|
{
|
||||||
return {};
|
auto* buffer = static_cast<std::string*>(userp);
|
||||||
|
|
||||||
|
const auto total_size = size * nmemb;
|
||||||
|
buffer->append(static_cast<char*>(contents), total_size);
|
||||||
|
return total_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buffer[0x1000];
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
HRESULT status{};
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
DWORD bytes_read = 0;
|
|
||||||
status = stream->Read(buffer, sizeof(buffer), &bytes_read);
|
|
||||||
|
|
||||||
if (bytes_read > 0)
|
|
||||||
{
|
|
||||||
result.append(buffer, bytes_read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (SUCCEEDED(status) && status != S_FALSE);
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {result};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::future<std::optional<std::string>> get_data_async(const std::string& url)
|
std::optional<result> get_data(const std::string& url)
|
||||||
|
{
|
||||||
|
curl_slist* header_list = nullptr;
|
||||||
|
auto* curl = curl_easy_init();
|
||||||
|
if (!curl)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto _ = gsl::finally([&]()
|
||||||
|
{
|
||||||
|
curl_slist_free_all(header_list);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::string buffer{};
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url.data());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
|
||||||
|
|
||||||
|
const auto code = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
if (code == CURLE_OK)
|
||||||
|
{
|
||||||
|
result result;
|
||||||
|
result.code = code;
|
||||||
|
result.buffer = std::move(buffer);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result result;
|
||||||
|
result.code = code;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<std::optional<result>> get_data_async(const std::string& url)
|
||||||
{
|
{
|
||||||
return std::async(std::launch::async, [url]()
|
return std::async(std::launch::async, [url]()
|
||||||
{
|
{
|
||||||
|
@ -3,9 +3,18 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <gsl/gsl>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
namespace utils::http
|
namespace utils::http
|
||||||
{
|
{
|
||||||
std::optional<std::string> get_data(const std::string& url);
|
struct result
|
||||||
std::future<std::optional<std::string>> get_data_async(const std::string& url);
|
{
|
||||||
|
CURLcode code;
|
||||||
|
std::string buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<result> get_data(const std::string& url);
|
||||||
|
std::future<std::optional<result>> get_data_async(const std::string& url);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user