1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
// *****************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
// *****************************************************************************
#ifndef CURL_WRAP_H_2879058325032785032789645
#define CURL_WRAP_H_2879058325032785032789645
#include <chrono>
#include <span>
#include <functional>
#include <zen/sys_error.h>
//-------------------------------------------------
#include <curl/curl.h>
//-------------------------------------------------
#ifndef CURLINC_CURL_H
#error curl.h header guard changed
#endif
namespace zen
{
void libcurlInit();
void libcurlTearDown();
struct CurlOption
{
template <class T>
CurlOption(CURLoption o, T val) : option(o), value(static_cast<uint64_t>(val)) { static_assert(sizeof(val) <= sizeof(value)); }
template <class T>
CurlOption(CURLoption o, T* val) : option(o), value(reinterpret_cast<uint64_t>(val)) { static_assert(sizeof(val) <= sizeof(value)); }
CURLoption option = CURLOPT_LASTENTRY;
uint64_t value = 0;
};
class HttpSession
{
public:
HttpSession(const Zstring& server, bool useTls, const Zstring& caCertFilePath /*optional*/); //throw SysError
~HttpSession();
struct Result
{
int statusCode = 0;
//std::string contentType;
};
Result perform(const std::string& serverRelPath,
const std::vector<std::string>& extraHeaders, const std::vector<CurlOption>& extraOptions,
const std::function<void (std::span<const char> buf)>& writeResponse /*throw X*/, //optional
const std::function<size_t(std::span< char> buf)>& readRequest /*throw X*/, //optional; return "bytesToRead" bytes unless end of stream!
const std::function<void (const std::string_view& header)>& receiveHeader /*throw X*/,
int timeoutSec); //throw SysError, X
std::chrono::steady_clock::time_point getLastUseTime() const { return lastSuccessfulUseTime_; }
private:
HttpSession (const HttpSession&) = delete;
HttpSession& operator=(const HttpSession&) = delete;
const std::string serverPrefix_;
const std::string caCertFilePath_; //optional
CURL* easyHandle_ = nullptr;
std::chrono::steady_clock::time_point lastSuccessfulUseTime_ = std::chrono::steady_clock::now();
};
std::wstring formatCurlStatusCode(CURLcode sc);
void applyCurlOptions(CURL* easyHandle, const std::vector<CurlOption>& options); //throw SysError
}
#else
#error Why is this header already defined? Do not include in other headers: encapsulate the gory details!
#endif //CURL_WRAP_H_2879058325032785032789645
|