Network: Add WebService

This commit is contained in:
SirLynix
2023-06-09 09:20:25 +02:00
committed by Jérôme Leclercq
parent b5206ebdb7
commit c65daba072
20 changed files with 899 additions and 4 deletions

View File

@@ -47,5 +47,8 @@
#include <Nazara/Network/TcpClient.hpp>
#include <Nazara/Network/TcpServer.hpp>
#include <Nazara/Network/UdpSocket.hpp>
#include <Nazara/Network/WebRequest.hpp>
#include <Nazara/Network/WebRequestResult.hpp>
#include <Nazara/Network/WebService.hpp>
#endif // NAZARA_GLOBAL_NETWORK_HPP

View File

@@ -0,0 +1,34 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// no header guards
#if !defined(NAZARA_CURL_FUNCTION)
#error You must define NAZARA_CURL_FUNCTION before including this file
#endif
#ifndef NAZARA_CURL_FUNCTION_LAST
#define NAZARA_CURL_FUNCTION_LAST(F) NAZARA_CURL_FUNCTION(F)
#endif
NAZARA_CURL_FUNCTION(easy_cleanup)
NAZARA_CURL_FUNCTION(easy_getinfo)
NAZARA_CURL_FUNCTION(easy_init)
NAZARA_CURL_FUNCTION(easy_setopt)
NAZARA_CURL_FUNCTION(easy_strerror)
NAZARA_CURL_FUNCTION(global_cleanup)
NAZARA_CURL_FUNCTION(global_init)
NAZARA_CURL_FUNCTION(multi_add_handle)
NAZARA_CURL_FUNCTION(multi_cleanup)
NAZARA_CURL_FUNCTION(multi_info_read)
NAZARA_CURL_FUNCTION(multi_init)
NAZARA_CURL_FUNCTION(multi_perform)
NAZARA_CURL_FUNCTION(multi_remove_handle)
NAZARA_CURL_FUNCTION(multi_strerror)
NAZARA_CURL_FUNCTION(slist_append)
NAZARA_CURL_FUNCTION(slist_free_all)
NAZARA_CURL_FUNCTION_LAST(version_info)
#undef NAZARA_CURL_FUNCTION
#undef NAZARA_CURL_FUNCTION_LAST

View File

@@ -0,0 +1,44 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_NETWORK_CURLLIBRARY_HPP
#define NAZARA_NETWORK_CURLLIBRARY_HPP
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Network/Config.hpp>
#include <curl/curl.h>
namespace Nz
{
class NAZARA_NETWORK_API CurlLibrary
{
public:
inline CurlLibrary();
CurlLibrary(const CurlLibrary&) = delete;
CurlLibrary(CurlLibrary&&) = delete;
inline ~CurlLibrary();
inline bool IsLoaded() const;
bool Load();
void Unload();
CurlLibrary& operator=(const CurlLibrary&) = delete;
CurlLibrary& operator=(CurlLibrary&&) = delete;
#define NAZARA_CURL_FUNCTION(name) decltype(&::curl_##name) name;
#include <Nazara/Network/CurlFunctions.hpp>
private:
DynLib m_library;
bool m_isInitialized;
};
}
#include <Nazara/Network/CurlLibrary.inl>
#endif // NAZARA_NETWORK_CURLLIBRARY_HPP

View File

@@ -0,0 +1,25 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Network/Debug.hpp>
namespace Nz
{
inline CurlLibrary::CurlLibrary() :
m_isInitialized(false)
{
}
inline CurlLibrary::~CurlLibrary()
{
Unload();
}
inline bool CurlLibrary::IsLoaded() const
{
return m_isInitialized;
}
}
#include <Nazara/Network/DebugOff.hpp>

View File

@@ -10,9 +10,12 @@
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Network/Config.hpp>
#include <memory>
namespace Nz
{
class WebService;
class NAZARA_NETWORK_API Network : public ModuleBase<Network>
{
friend ModuleBase;
@@ -20,12 +23,22 @@ namespace Nz
public:
using Dependencies = TypeList<Core>;
struct Config {};
struct Config;
Network(Config /*config*/);
Network(Config config);
~Network();
std::unique_ptr<WebService> InstantiateWebService();
struct Config
{
// Initialize web services and fails module initialization if it failed to initialize them
bool webServices = false;
};
private:
std::unique_ptr<class CurlLibrary> m_curlLibrary;
static Network* s_instance;
};
}

View File

@@ -0,0 +1,75 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_NETWORK_WEBREQUEST_HPP
#define NAZARA_NETWORK_WEBREQUEST_HPP
#include <Nazara/Network/Config.hpp>
#include <Nazara/Network/Enums.hpp>
#include <Nazara/Network/WebRequestResult.hpp>
#include <NazaraUtils/MovablePtr.hpp>
#include <functional>
#include <string>
#include <unordered_map>
struct curl_slist;
namespace Nz
{
class WebService;
class NAZARA_NETWORK_API WebRequest
{
friend WebService;
public:
using DataCallback = std::function<bool(const void* data, std::size_t length)>;
using ResultCallback = std::function<void(WebRequestResult&& result)>;
WebRequest(WebService& owner);
WebRequest(const WebRequest&) = delete;
WebRequest(WebRequest&&) = default;
~WebRequest();
void ForceProtocol(NetProtocol protocol);
inline void SetDataCallback(DataCallback callback);
inline void SetHeader(std::string header, std::string value);
void SetJSonContent(std::string_view encodedJSon);
void SetMaximumFileSize(UInt64 maxFileSize);
inline void SetResultCallback(ResultCallback callback);
void SetServiceName(const std::string_view& serviceName);
void SetURL(const std::string& url);
void SetupGet();
void SetupPost();
WebRequest& operator=(const WebRequest&) = delete;
WebRequest& operator=(WebRequest&&) = default;
static std::unique_ptr<WebRequest> Get(const std::string& url, ResultCallback callback = nullptr);
static std::unique_ptr<WebRequest> Post(const std::string& url, ResultCallback callback = nullptr);
private:
inline bool OnBodyResponse(const char* data, std::size_t length);
CURL* Prepare();
inline void TriggerCallback();
inline void TriggerCallback(std::string errorMessage);
std::string m_responseBody;
std::unordered_map<std::string, std::string> m_headers;
WebService& m_webService;
DataCallback m_dataCallback;
MovablePtr<CURL> m_curlHandle;
MovablePtr<curl_slist> m_headerList;
ResultCallback m_resultCallback;
bool m_isUserAgentSet;
};
}
#include <Nazara/Network/WebRequest.inl>
#endif // NAZARA_NETWORK_WEBREQUEST_HPP

View File

@@ -0,0 +1,47 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Network/Debug.hpp>
namespace Nz
{
inline void WebRequest::SetDataCallback(DataCallback callback)
{
m_dataCallback = std::move(callback);
}
inline void WebRequest::SetResultCallback(ResultCallback callback)
{
m_resultCallback = std::move(callback);
}
inline void WebRequest::SetHeader(std::string header, std::string value)
{
m_headers.insert_or_assign(std::move(header), std::move(value));
}
inline bool WebRequest::OnBodyResponse(const char* data, std::size_t length)
{
if (!m_dataCallback)
{
m_responseBody.append(data, length);
return true;
}
return m_dataCallback(data, length);
}
inline void WebRequest::TriggerCallback()
{
m_resultCallback(WebRequestResult(m_webService, m_curlHandle.Get(), std::move(m_responseBody)));
m_responseBody.clear();
}
inline void WebRequest::TriggerCallback(std::string errorMessage)
{
m_resultCallback(WebRequestResult(m_webService, std::move(errorMessage)));
}
}
#include <Nazara/Network/DebugOff.hpp>

View File

@@ -0,0 +1,56 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_NETWORK_WEBREQUESTRESULT_HPP
#define NAZARA_NETWORK_WEBREQUESTRESULT_HPP
#include <Nazara/Network/Config.hpp>
#include <NazaraUtils/MovablePtr.hpp>
#include <functional>
#include <string>
using CURL = void;
namespace Nz
{
class WebService;
class NAZARA_NETWORK_API WebRequestResult
{
friend class WebRequest;
public:
WebRequestResult(const WebRequestResult&) = delete;
WebRequestResult(WebRequestResult&&) = delete;
~WebRequestResult() = default;
inline std::string& GetBody();
inline const std::string& GetBody() const;
Nz::UInt64 GetDownloadedSize() const;
Nz::UInt64 GetDownloadSpeed() const;
inline const std::string& GetErrorMessage() const;
long GetReponseCode() const;
inline bool HasSucceeded() const;
inline explicit operator bool() const;
WebRequestResult& operator=(const WebRequestResult&) = delete;
WebRequestResult& operator=(WebRequestResult&&) = delete;
private:
inline WebRequestResult(WebService& webService, CURL* curl, std::string body);
inline WebRequestResult(WebService& webService, std::string errMessage);
CURL* m_curlHandle;
WebService& m_webService;
std::string m_bodyOrErr;
};
}
#include <Nazara/Network/WebRequestResult.inl>
#endif // NAZARA_NETWORK_WEBREQUESTRESULT_HPP

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Network/Debug.hpp>
namespace Nz
{
inline WebRequestResult::WebRequestResult(WebService& webService, CURL* curl, std::string body) :
m_curlHandle(curl),
m_webService(webService),
m_bodyOrErr(std::move(body))
{
}
inline WebRequestResult::WebRequestResult(WebService& webService, std::string errMessage) :
m_curlHandle(nullptr),
m_webService(webService),
m_bodyOrErr(std::move(errMessage))
{
}
inline std::string& WebRequestResult::GetBody()
{
assert(HasSucceeded());
return m_bodyOrErr;
}
inline const std::string& WebRequestResult::GetBody() const
{
assert(HasSucceeded());
return m_bodyOrErr;
}
inline const std::string& WebRequestResult::GetErrorMessage() const
{
assert(!HasSucceeded());
return m_bodyOrErr;
}
inline bool WebRequestResult::HasSucceeded() const
{
return m_curlHandle != nullptr;
}
inline WebRequestResult::operator bool() const
{
return HasSucceeded();
}
}
#include <Nazara/Network/DebugOff.hpp>

View File

@@ -0,0 +1,58 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_NETWORK_WEBSERVICE_HPP
#define NAZARA_NETWORK_WEBSERVICE_HPP
#include <Nazara/Network/Config.hpp>
#include <Nazara/Network/WebRequest.hpp>
#include <NazaraUtils/MovablePtr.hpp>
using CURLM = void;
namespace Nz
{
class CurlLibrary;
class Logger;
class NAZARA_NETWORK_API WebService
{
friend WebRequest;
friend WebRequestResult;
public:
WebService(const CurlLibrary& library);
WebService(const WebService&) = delete;
WebService(WebService&&) = delete;
~WebService();
inline std::unique_ptr<WebRequest> AllocateRequest();
inline std::unique_ptr<WebRequest> CreateGetRequest(const std::string& url, WebRequest::ResultCallback callback);
inline std::unique_ptr<WebRequest> CreatePostRequest(const std::string& url, WebRequest::ResultCallback callback);
inline const std::string& GetUserAgent() const;
void Poll();
void QueueRequest(std::unique_ptr<WebRequest>&& request);
WebService& operator=(const WebService&) = delete;
WebService& operator=(WebService&&) = delete;
private:
inline const CurlLibrary& GetCurlLibrary() const;
std::string m_userAgent;
std::unordered_map<CURL*, std::unique_ptr<WebRequest>> m_activeRequests;
const CurlLibrary& m_curl;
MovablePtr<CURLM> m_curlMulti;
};
}
#include <Nazara/Network/WebService.inl>
#endif // NAZARA_NETWORK_WEBSERVICE_HPP

View File

@@ -0,0 +1,45 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Network/Debug.hpp>
namespace Nz
{
inline std::unique_ptr<WebRequest> WebService::AllocateRequest()
{
return std::make_unique<WebRequest>(*this);
}
inline std::unique_ptr<WebRequest> WebService::CreateGetRequest(const std::string& url, WebRequest::ResultCallback callback)
{
std::unique_ptr<WebRequest> request = AllocateRequest();
request->SetURL(url);
request->SetResultCallback(std::move(callback));
request->SetupGet();
return request;
}
inline std::unique_ptr<WebRequest> WebService::CreatePostRequest(const std::string& url, WebRequest::ResultCallback callback)
{
std::unique_ptr<WebRequest> request = AllocateRequest();
request->SetURL(url);
request->SetResultCallback(std::move(callback));
request->SetupPost();
return request;
}
inline const std::string& WebService::GetUserAgent() const
{
return m_userAgent;
}
const CurlLibrary& WebService::GetCurlLibrary() const
{
return m_curl;
}
}
#include <Nazara/Network/DebugOff.hpp>