[Download] Add ssl support
This commit is contained in:
parent
3b12f3d30e
commit
f6894b46c5
@ -68,6 +68,7 @@ namespace Components
|
||||
#include "Modules/Monitor.hpp"
|
||||
#include "Modules/Network.hpp"
|
||||
#include "Modules/Theatre.hpp"
|
||||
#include "Modules/QuickPatch.hpp"
|
||||
#include "Modules/Node.hpp"
|
||||
#include "Modules/RCon.hpp"
|
||||
#include "Modules/Party.hpp" // Destroys the order, but requires network classes :D
|
||||
@ -93,7 +94,6 @@ namespace Components
|
||||
#include "Modules/FileSystem.hpp"
|
||||
#include "Modules/ModelSurfs.hpp"
|
||||
#include "Modules/PlayerName.hpp"
|
||||
#include "Modules/QuickPatch.hpp"
|
||||
#include "Modules/ServerInfo.hpp"
|
||||
#include "Modules/ServerList.hpp"
|
||||
#include "Modules/SlowMotion.hpp"
|
||||
|
@ -4,7 +4,7 @@ namespace Components
|
||||
{
|
||||
mg_mgr Download::Mgr;
|
||||
Download::ClientDownload Download::CLDownload;
|
||||
std::vector<Download::ScriptDownload> Download::ScriptDownloads;
|
||||
std::vector<std::shared_ptr<Download::ScriptDownload>> Download::ScriptDownloads;
|
||||
|
||||
#pragma region Client
|
||||
|
||||
@ -748,15 +748,36 @@ namespace Components
|
||||
|
||||
QuickPatch::OnFrame([]()
|
||||
{
|
||||
int workingCount = 0;
|
||||
|
||||
for(auto i = Download::ScriptDownloads.begin(); i != Download::ScriptDownloads.end();)
|
||||
{
|
||||
i->work();
|
||||
auto download = *i;
|
||||
|
||||
if(i->isDone())
|
||||
if(download->isDone())
|
||||
{
|
||||
download->notifyDone();
|
||||
i = Download::ScriptDownloads.erase(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (download->isWorking())
|
||||
{
|
||||
download->notifyProgress();
|
||||
++workingCount;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
for(auto& download : Download::ScriptDownloads)
|
||||
{
|
||||
if (workingCount > 5) break;
|
||||
if(!download->isWorking())
|
||||
{
|
||||
download->startWorking();
|
||||
++workingCount;
|
||||
}
|
||||
else ++i;
|
||||
}
|
||||
});
|
||||
|
||||
@ -765,33 +786,36 @@ namespace Components
|
||||
Download::ScriptDownloads.clear();
|
||||
});
|
||||
|
||||
Script::AddFunction("httpGet", [](Game::scr_entref_t)
|
||||
if (Dedicated::IsEnabled() || Flags::HasFlag("scriptablehttp"))
|
||||
{
|
||||
if (Game::Scr_GetNumParam() < 1) return;
|
||||
|
||||
std::string url = Game::Scr_GetString(0);
|
||||
unsigned int object = Game::AllocObject();
|
||||
|
||||
Game::Scr_AddObject(object);
|
||||
|
||||
Download::ScriptDownloads.push_back({ url, object });
|
||||
Game::RemoveRefToObject(object);
|
||||
});
|
||||
|
||||
Script::AddFunction("httpCancel", [](Game::scr_entref_t)
|
||||
{
|
||||
if (Game::Scr_GetNumParam() < 1) return;
|
||||
|
||||
unsigned int object = Game::Scr_GetObject(0);
|
||||
for(auto& download : Download::ScriptDownloads)
|
||||
Script::AddFunction("httpGet", [](Game::scr_entref_t)
|
||||
{
|
||||
if(object == download.getObject())
|
||||
if (Game::Scr_GetNumParam() < 1) return;
|
||||
|
||||
std::string url = Game::Scr_GetString(0);
|
||||
unsigned int object = Game::AllocObject();
|
||||
|
||||
Game::Scr_AddObject(object);
|
||||
|
||||
Download::ScriptDownloads.push_back(std::make_shared<ScriptDownload>(url, object));
|
||||
Game::RemoveRefToObject(object);
|
||||
});
|
||||
|
||||
Script::AddFunction("httpCancel", [](Game::scr_entref_t)
|
||||
{
|
||||
if (Game::Scr_GetNumParam() < 1) return;
|
||||
|
||||
unsigned int object = Game::Scr_GetObject(0);
|
||||
for (auto& download : Download::ScriptDownloads)
|
||||
{
|
||||
download.notifyDone(false, std::string());
|
||||
break;
|
||||
if (object == download->getObject())
|
||||
{
|
||||
download->cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Download::~Download()
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "Game/Functions.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
@ -86,35 +87,13 @@ namespace Components
|
||||
class ScriptDownload
|
||||
{
|
||||
public:
|
||||
ScriptDownload(std::string _url, unsigned int _object) : url(_url), object(_object), mgr(new mg_mgr), totalSize(0), receivedSize(0), done(false)
|
||||
ScriptDownload(std::string _url, unsigned int _object) : url(_url), object(_object), webIO(nullptr), done(false), notifyRequired(false), totalSize(0), currentSize(0)
|
||||
{
|
||||
Game::AddRefToObject(this->getObject());
|
||||
|
||||
ZeroMemory(this->getMgr(), sizeof(*this->getMgr()));
|
||||
mg_mgr_init(this->getMgr(), this);
|
||||
mg_connect_http(this->getMgr(), ScriptDownload::Handler, this->getUrl().data(), nullptr, nullptr);
|
||||
}
|
||||
|
||||
ScriptDownload(ScriptDownload&& other) noexcept
|
||||
{
|
||||
this->operator=(std::move(other));
|
||||
}
|
||||
|
||||
ScriptDownload& operator=(ScriptDownload&& other) noexcept
|
||||
{
|
||||
this->object = other.object;
|
||||
this->done = other.done;
|
||||
this->totalSize = other.totalSize;
|
||||
this->receivedSize = other.receivedSize;
|
||||
this->url = std::move(other.url);
|
||||
this->mgr = std::move(other.mgr);
|
||||
|
||||
this->getMgr()->user_data = this;
|
||||
|
||||
other.object = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
ScriptDownload(ScriptDownload&& other) noexcept = delete;
|
||||
ScriptDownload& operator=(ScriptDownload&& other) noexcept = delete;
|
||||
|
||||
~ScriptDownload()
|
||||
{
|
||||
@ -122,105 +101,115 @@ namespace Components
|
||||
{
|
||||
Game::RemoveRefToObject(this->getObject());
|
||||
this->object = 0;
|
||||
|
||||
mg_mgr_free(this->getMgr());
|
||||
}
|
||||
}
|
||||
|
||||
void work()
|
||||
{
|
||||
mg_mgr_poll(this->getMgr(), 0);
|
||||
}
|
||||
|
||||
void notifyProgress(size_t bytes)
|
||||
{
|
||||
this->receivedSize += bytes;
|
||||
|
||||
Game::Scr_AddInt(static_cast<int>(this->totalSize));
|
||||
Game::Scr_AddInt(static_cast<int>(this->receivedSize));
|
||||
Game::Scr_NotifyId(this->getObject(), Game::SL_GetString("progress", 0), 2);
|
||||
}
|
||||
|
||||
void setSize(char* buf, size_t len)
|
||||
{
|
||||
if(buf && !this->totalSize)
|
||||
if(this->workerThread.joinable())
|
||||
{
|
||||
std::string data(buf, len);
|
||||
auto pos = data.find("Content-Length: ");
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
data = data.substr(pos + 16);
|
||||
this->workerThread.join();
|
||||
}
|
||||
|
||||
pos = data.find("\r\n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
data = data.substr(0, pos);
|
||||
this->destroyWebIO();
|
||||
}
|
||||
|
||||
this->totalSize = size_t(atoll(data.data()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->totalSize = ~0ul;
|
||||
void startWorking()
|
||||
{
|
||||
if(!this->isWorking())
|
||||
{
|
||||
this->workerThread = std::thread(std::bind(&ScriptDownload::handler, this));
|
||||
}
|
||||
}
|
||||
|
||||
void notifyDone(bool success, std::string result)
|
||||
bool isWorking()
|
||||
{
|
||||
if (this->isDone()) return;
|
||||
return this->workerThread.joinable();
|
||||
}
|
||||
|
||||
Game::Scr_AddString(result.data()); // No binary data supported yet
|
||||
Game::Scr_AddInt(success);
|
||||
Game::Scr_NotifyId(this->getObject(), Game::SL_GetString("done", 0), 2);
|
||||
void notifyProgress()
|
||||
{
|
||||
if (this->notifyRequired)
|
||||
{
|
||||
this->notifyRequired = false;
|
||||
|
||||
this->done = true;
|
||||
if (Game::Scr_IsSystemActive())
|
||||
{
|
||||
Game::Scr_AddInt(static_cast<int>(this->totalSize));
|
||||
Game::Scr_AddInt(static_cast<int>(this->currentSize));
|
||||
Game::Scr_NotifyId(this->getObject(), Game::SL_GetString("progress", 0), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateProgress(size_t _currentSize, size_t _toalSize)
|
||||
{
|
||||
this->currentSize = _currentSize;
|
||||
this->totalSize = _toalSize;
|
||||
this->notifyRequired = true;
|
||||
}
|
||||
|
||||
void notifyDone()
|
||||
{
|
||||
if (!this->isDone()) return;
|
||||
|
||||
if (Game::Scr_IsSystemActive())
|
||||
{
|
||||
Game::Scr_AddString(this->result.data()); // No binary data supported yet
|
||||
Game::Scr_AddInt(this->success);
|
||||
Game::Scr_NotifyId(this->getObject(), Game::SL_GetString("done", 0), 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool isDone() { return this->done; };
|
||||
|
||||
std::string getUrl() { return this->url; }
|
||||
mg_mgr* getMgr() { return this->mgr.get(); }
|
||||
unsigned int getObject() { return this->object; }
|
||||
|
||||
void cancel()
|
||||
{
|
||||
if(this->webIO)
|
||||
{
|
||||
this->webIO->cancelDownload();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string url;
|
||||
std::string result;
|
||||
unsigned int object;
|
||||
std::shared_ptr<mg_mgr> mgr;
|
||||
|
||||
size_t totalSize;
|
||||
size_t receivedSize;
|
||||
std::thread workerThread;
|
||||
Utils::WebIO* webIO;
|
||||
|
||||
bool done;
|
||||
bool success;
|
||||
bool notifyRequired;
|
||||
size_t totalSize;
|
||||
size_t currentSize;
|
||||
|
||||
static void Handler(mg_connection *nc, int ev, void* ev_data)
|
||||
void handler()
|
||||
{
|
||||
http_message* hm = reinterpret_cast<http_message*>(ev_data);
|
||||
ScriptDownload* object = reinterpret_cast<ScriptDownload*>(nc->mgr->user_data);
|
||||
this->destroyWebIO();
|
||||
|
||||
if (ev == MG_EV_RECV)
|
||||
{
|
||||
object->setSize(nc->recv_mbuf.buf, nc->recv_mbuf.len);
|
||||
this->webIO = new Utils::WebIO("IW4x");
|
||||
this->webIO->setProgressCallback(std::bind(&ScriptDownload::updateProgress, this, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
size_t bytes = static_cast<size_t>(*reinterpret_cast<int*>(ev_data));
|
||||
object->notifyProgress(bytes);
|
||||
}
|
||||
else if (ev == MG_EV_HTTP_REPLY)
|
||||
this->result = this->webIO->get(this->url, &this->success);
|
||||
|
||||
this->destroyWebIO();
|
||||
this->done = true;
|
||||
}
|
||||
|
||||
void destroyWebIO()
|
||||
{
|
||||
if (this->webIO)
|
||||
{
|
||||
object->notifyDone(true, std::string(hm->body.p, hm->body.len));
|
||||
}
|
||||
else if(ev == MG_EV_CONNECT)
|
||||
{
|
||||
if (*static_cast<int*>(ev_data))
|
||||
{
|
||||
object->notifyDone(false, std::string());
|
||||
}
|
||||
delete this->webIO;
|
||||
this->webIO = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static mg_mgr Mgr;
|
||||
static ClientDownload CLDownload;
|
||||
static std::vector<ScriptDownload> ScriptDownloads;
|
||||
static std::vector<std::shared_ptr<ScriptDownload>> ScriptDownloads;
|
||||
|
||||
static void EventHandler(mg_connection *nc, int ev, void *ev_data);
|
||||
static void ListHandler(mg_connection *nc, int ev, void *ev_data);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Components
|
||||
{
|
||||
int QuickPatch::FrameTime = 0;
|
||||
bool QuickPatch::ReadyPassed = false;
|
||||
Utils::Signal<QuickPatch::Callback> QuickPatch::ReadySignal;
|
||||
Utils::Signal<QuickPatch::Callback> QuickPatch::ShutdownSignal;
|
||||
@ -198,6 +199,12 @@ namespace Components
|
||||
QuickPatch::ReadyPassed = false;
|
||||
QuickPatch::Once(QuickPatch::ReadyHandler);
|
||||
|
||||
QuickPatch::FrameTime = 0;
|
||||
QuickPatch::OnFrame([]()
|
||||
{
|
||||
QuickPatch::FrameTime = Game::Sys_Milliseconds();
|
||||
});
|
||||
|
||||
// Make sure preDestroy is called when the game shuts down
|
||||
QuickPatch::OnShutdown(Loader::PreDestroy);
|
||||
|
||||
|
@ -21,8 +21,10 @@ namespace Components
|
||||
static void OnFrame(Utils::Slot<Callback> callback);
|
||||
static void OnReady(Utils::Slot<Callback> callback);
|
||||
static void Once(Utils::Slot<Callback> callback);
|
||||
static int GetFrameTime() { return FrameTime; }
|
||||
|
||||
private:
|
||||
static int FrameTime;
|
||||
static bool ReadyPassed;
|
||||
static Utils::Signal<Callback> ReadySignal;
|
||||
static Utils::Signal<Callback> ShutdownSignal;
|
||||
|
@ -230,6 +230,7 @@ namespace Game
|
||||
|
||||
Scr_RegisterFunction_t Scr_RegisterFunction = Scr_RegisterFunction_t(0x492D50);
|
||||
Scr_ShutdownAllocNode_t Scr_ShutdownAllocNode = Scr_ShutdownAllocNode_t(0x441650);
|
||||
Scr_IsSystemActive_t Scr_IsSystemActive = Scr_IsSystemActive_t(0x4B24E0);
|
||||
|
||||
Script_Alloc_t Script_Alloc = Script_Alloc_t(0x422E70);
|
||||
Script_SetupTokens_t Script_SetupTokens = Script_SetupTokens_t(0x4E6950);
|
||||
|
@ -571,6 +571,9 @@ namespace Game
|
||||
typedef void(__cdecl * Scr_RegisterFunction_t)(scr_function_t function);
|
||||
extern Scr_RegisterFunction_t Scr_RegisterFunction;
|
||||
|
||||
typedef bool(__cdecl * Scr_IsSystemActive_t)();
|
||||
extern Scr_IsSystemActive_t Scr_IsSystemActive;
|
||||
|
||||
typedef script_t* (__cdecl * Script_Alloc_t)(int length);
|
||||
extern Script_Alloc_t Script_Alloc;
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace Utils
|
||||
this->setURL(url);
|
||||
}
|
||||
|
||||
WebIO::WebIO(std::string useragent) : timeout(5000) // 5 seconds timeout by default
|
||||
WebIO::WebIO(std::string useragent) : cancel(false), timeout(5000), hSession(nullptr) // 5 seconds timeout by default
|
||||
{
|
||||
this->openSession(useragent);
|
||||
}
|
||||
@ -26,12 +26,13 @@ namespace Utils
|
||||
|
||||
void WebIO::openSession(std::string useragent)
|
||||
{
|
||||
this->closeSession();
|
||||
this->hSession = InternetOpenA(useragent.data(), INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
void WebIO::closeSession()
|
||||
{
|
||||
InternetCloseHandle(this->hSession);
|
||||
if(this->hSession) InternetCloseHandle(this->hSession);
|
||||
}
|
||||
|
||||
void WebIO::SetCredentials(std::string _username, std::string _password)
|
||||
@ -183,37 +184,37 @@ namespace Utils
|
||||
return this->execute("POST", body, headers);
|
||||
}
|
||||
|
||||
std::string WebIO::post(std::string _url, std::string body)
|
||||
std::string WebIO::post(std::string _url, std::string body, bool* success)
|
||||
{
|
||||
this->setURL(_url);
|
||||
return this->post(body);
|
||||
return this->post(body, success);
|
||||
}
|
||||
|
||||
std::string WebIO::post(std::string _url, WebIO::Params params)
|
||||
std::string WebIO::post(std::string _url, WebIO::Params params, bool* success)
|
||||
{
|
||||
this->setURL(_url);
|
||||
return this->post(params);
|
||||
return this->post(params, success);
|
||||
}
|
||||
|
||||
std::string WebIO::post(WebIO::Params params)
|
||||
std::string WebIO::post(WebIO::Params params, bool* success)
|
||||
{
|
||||
return this->post(this->buildPostBody(params));
|
||||
return this->post(this->buildPostBody(params), success);
|
||||
}
|
||||
|
||||
std::string WebIO::post(std::string body)
|
||||
std::string WebIO::post(std::string body, bool* success)
|
||||
{
|
||||
return this->execute("POST", body);
|
||||
return this->execute("POST", body, WebIO::Params(), success);
|
||||
}
|
||||
|
||||
std::string WebIO::get(std::string _url)
|
||||
std::string WebIO::get(std::string _url, bool* success)
|
||||
{
|
||||
this->setURL(_url);
|
||||
return this->get();
|
||||
return this->get(success);
|
||||
}
|
||||
|
||||
std::string WebIO::get()
|
||||
std::string WebIO::get(bool* success)
|
||||
{
|
||||
return this->execute("GET", "");
|
||||
return this->execute("GET", "", WebIO::Params(), success);
|
||||
}
|
||||
|
||||
bool WebIO::openConnection()
|
||||
@ -257,8 +258,9 @@ namespace Utils
|
||||
return this;
|
||||
}
|
||||
|
||||
std::string WebIO::execute(const char* command, std::string body, WebIO::Params headers)
|
||||
std::string WebIO::execute(const char* command, std::string body, WebIO::Params headers, bool* success)
|
||||
{
|
||||
if (success) *success = false;
|
||||
if (!this->openConnection()) return "";
|
||||
|
||||
const char *acceptTypes[] = { "application/x-www-form-urlencoded", nullptr };
|
||||
@ -307,19 +309,36 @@ namespace Utils
|
||||
return "";
|
||||
}
|
||||
|
||||
DWORD contentLength = 0;
|
||||
length = sizeof(statusCode);
|
||||
if (HttpQueryInfo(this->hFile, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_CONTENT_LENGTH, &contentLength, &length, nullptr) == FALSE)
|
||||
{
|
||||
this->closeConnection();
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string returnBuffer;
|
||||
returnBuffer.reserve(contentLength);
|
||||
|
||||
DWORD size = 0;
|
||||
char buffer[0x2001] = { 0 };
|
||||
|
||||
while (InternetReadFile(this->hFile, buffer, 0x2000, &size))
|
||||
{
|
||||
if(this->cancel)
|
||||
{
|
||||
this->closeConnection();
|
||||
return "";
|
||||
}
|
||||
|
||||
returnBuffer.append(buffer, size);
|
||||
if (this->progressCallback) this->progressCallback(returnBuffer.size(), contentLength);
|
||||
if (!size) break;
|
||||
}
|
||||
|
||||
this->closeConnection();
|
||||
|
||||
if (success) *success = true;
|
||||
return returnBuffer;
|
||||
}
|
||||
|
||||
@ -539,4 +558,9 @@ namespace Utils
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebIO::setProgressCallback(std::function<void(size_t, size_t)> callback)
|
||||
{
|
||||
this->progressCallback = callback;
|
||||
}
|
||||
}
|
||||
|
@ -30,13 +30,13 @@ namespace Utils
|
||||
std::string postFile(std::string url, std::string data, std::string fieldName, std::string fileName);
|
||||
std::string postFile(std::string data, std::string fieldName, std::string fileName);
|
||||
|
||||
std::string post(std::string url, WebIO::Params params);
|
||||
std::string post(std::string url, std::string body);
|
||||
std::string post(WebIO::Params params);
|
||||
std::string post(std::string body);
|
||||
std::string post(std::string url, WebIO::Params params, bool* success= nullptr);
|
||||
std::string post(std::string url, std::string body, bool* success = nullptr);
|
||||
std::string post(WebIO::Params params, bool* success = nullptr);
|
||||
std::string post(std::string body, bool* success = nullptr);
|
||||
|
||||
std::string get(std::string url);
|
||||
std::string get();
|
||||
std::string get(std::string url, bool* success = nullptr);
|
||||
std::string get(bool* success = nullptr);
|
||||
|
||||
WebIO* setTimeout(DWORD mseconds);
|
||||
|
||||
@ -62,6 +62,9 @@ namespace Utils
|
||||
bool uploadFileData(std::string file, std::string data);
|
||||
bool downloadFileData(std::string file, std::string &data);
|
||||
|
||||
void setProgressCallback(std::function<void(size_t, size_t)> callback);
|
||||
void cancelDownload() { this->cancel = true; }
|
||||
|
||||
private:
|
||||
|
||||
enum Command
|
||||
@ -79,6 +82,8 @@ namespace Utils
|
||||
std::string raw;
|
||||
};
|
||||
|
||||
bool cancel;
|
||||
|
||||
bool isFTP;
|
||||
std::string username;
|
||||
std::string password;
|
||||
@ -91,11 +96,13 @@ namespace Utils
|
||||
|
||||
DWORD timeout;
|
||||
|
||||
std::function<void(size_t, size_t)> progressCallback;
|
||||
|
||||
std::string buildPostBody(WebIO::Params params);
|
||||
|
||||
bool isSecuredConnection();
|
||||
|
||||
std::string execute(const char* command, std::string body, WebIO::Params headers = WebIO::Params());
|
||||
std::string execute(const char* command, std::string body, WebIO::Params headers = WebIO::Params(), bool* success = nullptr);
|
||||
|
||||
bool listElements(std::string directory, std::vector<std::string> &list, bool files);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user