DDraceNetwork Documentation
Loading...
Searching...
No Matches
http.h
Go to the documentation of this file.
1#ifndef ENGINE_SHARED_HTTP_H
2#define ENGINE_SHARED_HTTP_H
3
4#include <base/hash_ctxt.h>
5#include <base/system.h>
6
7#include <engine/http.h>
9
10#include <algorithm>
11#include <atomic>
12#include <condition_variable>
13#include <deque>
14#include <mutex>
15#include <optional>
16#include <unordered_map>
17
18typedef struct _json_value json_value;
19class IStorage;
20
29
30enum class HTTPLOG
31{
35};
36
37enum class IPRESOLVE
38{
42};
43
45{
46public:
51};
52
54{
55 friend class CHttp;
56
57 enum class REQUEST
58 {
59 GET = 0,
63 };
64
65 static constexpr const char *GetRequestType(REQUEST Type)
66 {
67 switch(Type)
68 {
69 case REQUEST::GET:
70 return "GET";
71 case REQUEST::HEAD:
72 return "HEAD";
73 case REQUEST::POST:
75 return "POST";
76 }
77
78 dbg_assert_failed("unreachable");
79 }
80
81 char m_aUrl[256] = {0};
82
83 void *m_pHeaders = nullptr;
84 unsigned char *m_pBody = nullptr;
85 size_t m_BodyLength = 0;
86
88 bool m_SkipByFileTime = true;
89
91 int64_t m_MaxResponseSize = -1;
92 int64_t m_IfModifiedSince = -1;
94
95 std::optional<SHA256_DIGEST> m_ActualSha256;
97 std::optional<SHA256_DIGEST> m_ExpectedSha256;
98
99 bool m_WriteToMemory = true;
100 bool m_WriteToFile = false;
101
102 uint64_t m_ResponseLength = 0;
103
104 // If `m_WriteToMemory` is true.
105 size_t m_BufferSize = 0;
106 unsigned char *m_pBuffer = nullptr;
107
108 // If `m_WriteToFile` is true.
109 IOHANDLE m_File = nullptr;
110 int m_StorageType = 0xdeadbeef;
114
115 std::atomic<double> m_Size{0.0};
116 std::atomic<double> m_Current{0.0};
117 std::atomic<int> m_Progress{0};
120
122
123 char m_aErr[256]; // 256 == CURL_ERROR_SIZE
124 std::atomic<EHttpState> m_State{EHttpState::QUEUED};
125 std::atomic<bool> m_Abort{false};
126 std::mutex m_WaitMutex;
127 std::condition_variable m_WaitCondition;
128
130 bool m_HeadersEnded = false;
131 std::optional<int64_t> m_ResultDate = std::nullopt;
132 std::optional<int64_t> m_ResultLastModified = std::nullopt;
133
134 bool ShouldSkipRequest();
135 // Abort the request with an error if `BeforeInit()` returns false.
136 bool BeforeInit();
137 bool ConfigureHandle(void *pHandle); // void * == CURL *
138 // `pHandle` can be nullptr if no handle was ever created for this request.
139 void OnCompletionInternal(void *pHandle, unsigned int Result); // void * == CURL *, unsigned int == CURLcode
140
141 // Abort the request if `OnHeader()` returns something other than
142 // `DataSize`. `pHeader` is NOT null-terminated.
143 size_t OnHeader(char *pHeader, size_t HeaderSize);
144 // Abort the request if `OnData()` returns something other than
145 // `DataSize`.
146 size_t OnData(char *pData, size_t DataSize);
147
148 static int ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr);
149 static size_t HeaderCallback(char *pData, size_t Size, size_t Number, void *pUser);
150 static size_t WriteCallback(char *pData, size_t Size, size_t Number, void *pUser);
151
152protected:
153 // These run on the curl thread now, DO NOT STALL THE THREAD
154 virtual void OnProgress() {}
156
157public:
158 CHttpRequest(const char *pUrl);
159 virtual ~CHttpRequest();
160
162 // Skip the download if the local file is newer or as new as the remote file.
168 // Download to memory only. Get the result via `Result*`.
170 {
171 m_WriteToMemory = true;
172 m_WriteToFile = false;
173 }
174 // Download to filesystem and memory.
175 void WriteToFileAndMemory(IStorage *pStorage, const char *pDest, int StorageType);
176 // Download to the filesystem only.
177 void WriteToFile(IStorage *pStorage, const char *pDest, int StorageType);
178 // Don't place the file in the specified location until
179 // `OnValidation(true)` has been called.
181 void ExpectSha256(const SHA256_DIGEST &Sha256) { m_ExpectedSha256 = Sha256; }
183 void Post(const unsigned char *pData, size_t DataLength)
184 {
186 m_BodyLength = DataLength;
187 m_pBody = (unsigned char *)malloc(std::max((size_t)1, DataLength));
188 mem_copy(m_pBody, pData, DataLength);
189 }
190 void PostJson(const char *pJson)
191 {
193 m_BodyLength = str_length(pJson);
194 m_pBody = (unsigned char *)malloc(m_BodyLength);
196 }
197 void Header(const char *pNameColonValue);
198 void HeaderString(const char *pName, const char *pValue)
199 {
200 char aHeader[256];
201 str_format(aHeader, sizeof(aHeader), "%s: %s", pName, pValue);
202 Header(aHeader);
203 }
204 void HeaderInt(const char *pName, int Value)
205 {
206 char aHeader[256];
207 str_format(aHeader, sizeof(aHeader), "%s: %d", pName, Value);
208 Header(aHeader);
209 }
210
211 const char *Dest()
212 {
213 if(m_WriteToFile)
214 {
215 return m_aDest;
216 }
217 else
218 {
219 return nullptr;
220 }
221 }
222
223 double Current() const { return m_Current.load(std::memory_order_relaxed); }
224 double Size() const { return m_Size.load(std::memory_order_relaxed); }
225 int Progress() const { return m_Progress.load(std::memory_order_relaxed); }
226 EHttpState State() const { return m_State; }
227 bool Done() const
228 {
231 }
232 void Abort() { m_Abort = true; }
233 // If `ValidateBeforeOverwrite` is set, this needs to be called after
234 // validating that the downloaded file has the correct format.
235 //
236 // If called with `true`, it'll place the downloaded file at the final
237 // destination, if called with `false`, it'll instead delete the
238 // temporary downloaded file.
239 void OnValidation(bool Success);
240
241 void Wait();
242
243 void Result(unsigned char **ppResult, size_t *pResultLength) const;
244 json_value *ResultJson() const;
245 const SHA256_DIGEST &ResultSha256() const;
246
247 int StatusCode() const;
248 std::optional<int64_t> ResultAgeSeconds() const;
249 std::optional<int64_t> ResultLastModified() const;
250};
251
252inline std::unique_ptr<CHttpRequest> HttpHead(const char *pUrl)
253{
254 auto pResult = std::make_unique<CHttpRequest>(pUrl);
255 pResult->Head();
256 return pResult;
257}
258
259inline std::unique_ptr<CHttpRequest> HttpGet(const char *pUrl)
260{
261 return std::make_unique<CHttpRequest>(pUrl);
262}
263
264inline std::unique_ptr<CHttpRequest> HttpGetFile(const char *pUrl, IStorage *pStorage, const char *pOutputFile, int StorageType)
265{
266 std::unique_ptr<CHttpRequest> pResult = HttpGet(pUrl);
267 pResult->WriteToFile(pStorage, pOutputFile, StorageType);
268 pResult->Timeout(CTimeout{4000, 0, 500, 5});
269 return pResult;
270}
271
272inline std::unique_ptr<CHttpRequest> HttpGetBoth(const char *pUrl, IStorage *pStorage, const char *pOutputFile, int StorageType)
273{
274 std::unique_ptr<CHttpRequest> pResult = HttpGet(pUrl);
275 pResult->WriteToFileAndMemory(pStorage, pOutputFile, StorageType);
276 pResult->Timeout(CTimeout{4000, 0, 500, 5});
277 return pResult;
278}
279
280inline std::unique_ptr<CHttpRequest> HttpPost(const char *pUrl, const unsigned char *pData, size_t DataLength)
281{
282 auto pResult = std::make_unique<CHttpRequest>(pUrl);
283 pResult->Post(pData, DataLength);
284 pResult->Timeout(CTimeout{4000, 15000, 500, 5});
285 return pResult;
286}
287
288inline std::unique_ptr<CHttpRequest> HttpPostJson(const char *pUrl, const char *pJson)
289{
290 auto pResult = std::make_unique<CHttpRequest>(pUrl);
291 pResult->PostJson(pJson);
292 pResult->Timeout(CTimeout{4000, 15000, 500, 5});
293 return pResult;
294}
295
296void EscapeUrl(char *pBuf, int Size, const char *pStr);
297
298template<int N>
299void EscapeUrl(char (&aBuf)[N], const char *pStr)
300{
301 EscapeUrl(aBuf, N, pStr);
302}
303
305
306// In an ideal world this would be a kernel interface
307class CHttp : public IHttp
308{
315
316 void *m_pThread = nullptr;
317
318 std::mutex m_Lock;
319 std::condition_variable m_Cv;
320 std::atomic<EState> m_State = UNINITIALIZED;
321 std::deque<std::shared_ptr<CHttpRequest>> m_PendingRequests;
322 std::unordered_map<void *, std::shared_ptr<CHttpRequest>> m_RunningRequests; // void * == CURL *
323 std::chrono::milliseconds m_ShutdownDelay{};
324 std::optional<std::chrono::time_point<std::chrono::steady_clock>> m_ShutdownTime;
325 std::atomic<bool> m_Shutdown = false;
326
327 // Only to be used with curl_multi_wakeup
328 void *m_pMultiH = nullptr; // void * == CURLM *
329
330 static void ThreadMain(void *pUser);
331 void RunLoop();
332
333public:
334 // Startup
335 bool Init(std::chrono::milliseconds ShutdownDelay);
336
337 // User
338 void Run(std::shared_ptr<IHttpRequest> pRequest) override;
339 void Shutdown() override;
340 ~CHttp() override;
341};
342
343#endif // ENGINE_SHARED_HTTP_H
void FailOnErrorStatus(bool FailOnErrorStatus)
Definition http.h:167
void WriteToFileAndMemory(IStorage *pStorage, const char *pDest, int StorageType)
Definition http.cpp:519
bool m_SkipByFileTime
Definition http.h:88
static size_t HeaderCallback(char *pData, size_t Size, size_t Number, void *pUser)
Definition http.cpp:347
const SHA256_DIGEST & ResultSha256() const
Definition http.cpp:555
int64_t m_MaxResponseSize
Definition http.h:91
static int ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr)
Definition http.cpp:358
REQUEST
Definition http.h:58
@ POST_JSON
Definition http.h:62
@ GET
Definition http.h:59
@ POST
Definition http.h:61
@ HEAD
Definition http.h:60
bool ConfigureHandle(void *pHandle)
Definition http.cpp:145
HTTPLOG m_LogProgress
Definition http.h:118
void * m_pHeaders
Definition http.h:83
bool m_HeadersEnded
Definition http.h:130
const char * Dest()
Definition http.h:211
char m_aUrl[256]
Definition http.h:81
std::mutex m_WaitMutex
Definition http.h:126
void Result(unsigned char **ppResult, size_t *pResultLength) const
Definition http.cpp:539
virtual ~CHttpRequest()
Definition http.cpp:68
char m_aDestAbsolute[IO_MAX_PATH_LENGTH]
Definition http.h:112
std::atomic< int > m_Progress
Definition http.h:117
void IpResolve(IPRESOLVE IpResolve)
Definition http.h:166
void Abort()
Definition http.h:232
std::optional< int64_t > m_ResultLastModified
Definition http.h:132
REQUEST m_Type
Definition http.h:93
void Header(const char *pNameColonValue)
Definition http.cpp:525
static constexpr const char * GetRequestType(REQUEST Type)
Definition http.h:65
void Wait()
Definition http.cpp:530
json_value * ResultJson() const
Definition http.cpp:547
void MaxResponseSize(int64_t MaxResponseSize)
Definition http.h:164
size_t m_BodyLength
Definition http.h:85
double Size() const
Definition http.h:224
IPRESOLVE m_IpResolve
Definition http.h:119
void WriteToMemory()
Definition http.h:169
std::optional< int64_t > ResultAgeSeconds() const
Definition http.cpp:568
unsigned char * m_pBuffer
Definition http.h:106
bool m_WriteToMemory
Definition http.h:99
void OnCompletionInternal(void *pHandle, unsigned int Result)
Definition http.cpp:368
int m_StorageType
Definition http.h:110
std::optional< SHA256_DIGEST > m_ActualSha256
Definition http.h:95
void WriteToFile(IStorage *pStorage, const char *pDest, int StorageType)
Definition http.cpp:502
void Timeout(CTimeout Timeout)
Definition http.h:161
std::atomic< double > m_Size
Definition http.h:115
int StatusCode() const
Definition http.cpp:562
EHttpState State() const
Definition http.h:226
bool ShouldSkipRequest()
Definition http.cpp:102
virtual void OnCompletion(EHttpState State)
Definition http.h:155
void Head()
Definition http.h:182
void ExpectSha256(const SHA256_DIGEST &Sha256)
Definition http.h:181
std::atomic< double > m_Current
Definition http.h:116
std::optional< int64_t > ResultLastModified() const
Definition http.cpp:578
int Progress() const
Definition http.h:225
size_t OnData(char *pData, size_t DataSize)
Definition http.cpp:307
static size_t WriteCallback(char *pData, size_t Size, size_t Number, void *pUser)
Definition http.cpp:353
std::optional< int64_t > m_ResultDate
Definition http.h:131
size_t m_BufferSize
Definition http.h:105
void HeaderInt(const char *pName, int Value)
Definition http.h:204
virtual void OnProgress()
Definition http.h:154
void Post(const unsigned char *pData, size_t DataLength)
Definition http.h:183
CTimeout m_Timeout
Definition http.h:90
bool m_WriteToFile
Definition http.h:100
uint64_t m_ResponseLength
Definition http.h:102
char m_aDestAbsoluteTmp[IO_MAX_PATH_LENGTH]
Definition http.h:111
void ValidateBeforeOverwrite(bool ValidateBeforeOverwrite)
Definition http.h:180
friend class CHttp
Definition http.h:55
int m_StatusCode
Definition http.h:129
IOHANDLE m_File
Definition http.h:109
unsigned char * m_pBody
Definition http.h:84
void OnValidation(bool Success)
Definition http.cpp:477
std::atomic< EHttpState > m_State
Definition http.h:124
std::atomic< bool > m_Abort
Definition http.h:125
std::condition_variable m_WaitCondition
Definition http.h:127
char m_aDest[IO_MAX_PATH_LENGTH]
Definition http.h:113
int64_t m_IfModifiedSince
Definition http.h:92
SHA256_CTX m_ActualSha256Ctx
Definition http.h:96
bool BeforeInit()
Definition http.cpp:116
CHttpRequest(const char *pUrl)
Definition http.cpp:62
void HeaderString(const char *pName, const char *pValue)
Definition http.h:198
double Current() const
Definition http.h:223
bool m_ValidateBeforeOverwrite
Definition http.h:87
char m_aErr[256]
Definition http.h:123
std::optional< SHA256_DIGEST > m_ExpectedSha256
Definition http.h:97
bool Done() const
Definition http.h:227
void PostJson(const char *pJson)
Definition http.h:190
void SkipByFileTime(bool SkipByFileTime)
Definition http.h:163
void LogProgress(HTTPLOG LogProgress)
Definition http.h:165
bool m_FailOnErrorStatus
Definition http.h:121
size_t OnHeader(char *pHeader, size_t HeaderSize)
Definition http.cpp:261
Definition http.h:308
~CHttp() override
Definition http.cpp:823
std::atomic< bool > m_Shutdown
Definition http.h:325
void Run(std::shared_ptr< IHttpRequest > pRequest) override
Definition http.cpp:798
std::chrono::milliseconds m_ShutdownDelay
Definition http.h:323
std::atomic< EState > m_State
Definition http.h:320
std::unordered_map< void *, std::shared_ptr< CHttpRequest > > m_RunningRequests
Definition http.h:322
EState
Definition http.h:310
@ ERROR
Definition http.h:313
@ UNINITIALIZED
Definition http.h:311
@ RUNNING
Definition http.h:312
void Shutdown() override
Definition http.cpp:813
std::optional< std::chrono::time_point< std::chrono::steady_clock > > m_ShutdownTime
Definition http.h:324
std::condition_variable m_Cv
Definition http.h:319
std::mutex m_Lock
Definition http.h:318
std::deque< std::shared_ptr< CHttpRequest > > m_PendingRequests
Definition http.h:321
static void ThreadMain(void *pUser)
Definition http.cpp:605
void * m_pMultiH
Definition http.h:328
void RunLoop()
Definition http.cpp:611
bool Init(std::chrono::milliseconds ShutdownDelay)
Definition http.cpp:584
void * m_pThread
Definition http.h:316
Definition http.h:45
long m_TimeoutMs
Definition http.h:48
long m_ConnectTimeoutMs
Definition http.h:47
long m_LowSpeedLimit
Definition http.h:49
long m_LowSpeedTime
Definition http.h:50
Definition http.h:9
Definition http.h:13
Definition storage.h:21
struct _json_value json_value
Definition serverbrowser.h:18
#define dbg_assert_failed(fmt,...)
Definition dbg.h:47
void mem_copy(void *dest, const void *source, size_t size)
Definition mem.cpp:6
int str_length(const char *str)
Definition str.cpp:40
void * IOHANDLE
Definition logger.h:12
std::unique_ptr< CHttpRequest > HttpGet(const char *pUrl)
Definition http.h:259
std::unique_ptr< CHttpRequest > HttpHead(const char *pUrl)
Definition http.h:252
std::unique_ptr< CHttpRequest > HttpPost(const char *pUrl, const unsigned char *pData, size_t DataLength)
Definition http.h:280
IPRESOLVE
Definition http.h:38
@ WHATEVER
Definition http.h:39
@ V4
Definition http.h:40
@ V6
Definition http.h:41
std::unique_ptr< CHttpRequest > HttpGetFile(const char *pUrl, IStorage *pStorage, const char *pOutputFile, int StorageType)
Definition http.h:264
void EscapeUrl(char *pBuf, int Size, const char *pStr)
Definition http.cpp:48
std::unique_ptr< CHttpRequest > HttpGetBoth(const char *pUrl, IStorage *pStorage, const char *pOutputFile, int StorageType)
Definition http.h:272
std::unique_ptr< CHttpRequest > HttpPostJson(const char *pUrl, const char *pJson)
Definition http.h:288
EHttpState
Definition http.h:22
@ DONE
Definition http.h:26
@ RUNNING
Definition http.h:25
@ ABORTED
Definition http.h:27
@ QUEUED
Definition http.h:24
@ ERROR
Definition http.h:23
bool HttpHasIpresolveBug()
Definition http.cpp:55
HTTPLOG
Definition http.h:31
@ FAILURE
Definition http.h:33
@ ALL
Definition http.h:34
@ NONE
Definition http.h:32
Definition hash.h:15
#define str_format
Definition system.cpp:2794
constexpr auto IO_MAX_PATH_LENGTH
Definition types.h:49