50#include <sys/select.h>
56#ifdef RESTINCURL_WITH_OPENSSL_THREADS
57# include <openssl/crypto.h>
72#ifndef RESTINCURL_MAX_CONNECTIONS
73# define RESTINCURL_MAX_CONNECTIONS 32L
87#ifndef RESTINCURL_ENABLE_ASYNC
88# define RESTINCURL_ENABLE_ASYNC 1
101#ifndef RESTINCURL_IDLE_TIMEOUT_SEC
102# define RESTINCURL_IDLE_TIMEOUT_SEC 60
113#ifndef RESTINCURL_LOG_VERBOSE_ENABLE
114# define RESTINCURL_LOG_VERBOSE_ENABLE 0
117#if defined(_LOGFAULT_H) && !defined (RESTINCURL_LOG) && !defined (RESTINCURL_LOG_TRACE)
118# define RESTINCURL_LOG(msg) LFLOG_DEBUG << "restincurl: " << msg
119# if RESTINCURL_LOG_VERBOSE_ENABLE
120# define RESTINCURL_LOG_TRACE(msg) LFLOG_IFALL_TRACE("restincurl: " << msg)
124#if defined(RESTINCURL_USE_SYSLOG) || defined(RESTINCURL_USE_ANDROID_NDK_LOG)
125# ifdef RESTINCURL_USE_SYSLOG
128# ifdef RESTINCURL_USE_ANDROID_NDK_LOG
129# include <android/log.h>
132# define RESTINCURL_LOG(msg) ::restincurl::Log(restincurl::LogLevel::DEBUG).Line() << msg
149#ifndef RESTINCURL_ENABLE_DEFAULT_LOGGER
150# define RESTINCURL_ENABLE_DEFAULT_LOGGER 0
166#ifndef RESTINCURL_LOG
167# if RESTINCURL_ENABLE_DEFAULT_LOGGER
168# define RESTINCURL_LOG(msg) std::clog << msg << std::endl
170# define RESTINCURL_LOG(msg)
189#ifndef RESTINCURL_LOG_TRACE
190# if RESTINCURL_LOG_VERBOSE_ENABLE
191# define RESTINCURL_LOG_TRACE(msg) RESTINCURL_LOG(msg)
193# define RESTINCURL_LOG_TRACE(msg)
199#if defined(RESTINCURL_USE_SYSLOG) || defined(RESTINCURL_USE_ANDROID_NDK_LOG)
200 enum class LogLevel { DEBUG };
204 Log(
const LogLevel level) : level_{level} {}
206# ifdef RESTINCURL_USE_SYSLOG
207 static const std::array<int, 1> syslog_priority = { LOG_DEBUG };
208 static std::once_flag syslog_opened;
209 std::call_once(syslog_opened, [] {
210 openlog(
nullptr, 0, LOG_USER);
213# ifdef RESTINCURL_USE_ANDROID_NDK_LOG
214 static const std::array<int, 1> android_priority = { ANDROID_LOG_DEBUG };
216 const auto msg = out_.str();
218# ifdef RESTINCURL_USE_SYSLOG
219 syslog(syslog_priority.at(
static_cast<int>(level_)),
"%s", msg.c_str());
221# ifdef RESTINCURL_USE_ANDROID_NDK_LOG
222 __android_log_write(android_priority.at(
static_cast<int>(level_)),
223 "restincurl", msg.c_str());
227 std::ostringstream& Line() {
return out_; }
230 const LogLevel level_;
231 std::ostringstream out_;
237 using lock_t = std::lock_guard<std::mutex>;
245 msg = curl_easy_strerror(code);
291 Exception(
const std::string& msg) : runtime_error(msg) {}
309 :
Exception(msg +
'(' + std::to_string(err) +
"): " + curl_easy_strerror(err))
314 :
Exception(msg +
'(' + std::to_string(err) +
"): " + curl_multi_strerror(err))
318 int getErrorCode()
const noexcept {
return err_; }
326 using ptr_t = std::unique_ptr<EasyHandle>;
340 curl_easy_cleanup(handle_);
345 operator handle_t () const noexcept {
return handle_; }
348 handle_t handle_ = curl_easy_init();
364 template <
typename T>
366 const auto ret = curl_easy_setopt(eh_, opt, value);
369 std::string(
"Setting option ") + std::to_string(opt), ret);
379 Options&
Set(
const CURLoption& opt,
const std::string& value) {
380 return Set(opt, value.c_str());
404 template <
typename T>
410 static size_t write_callback(
char *ptr,
size_t size,
size_t nitems,
void *userdata) {
413 const auto bytes = size * nitems;
415 std::copy(ptr, ptr + bytes, std::back_inserter(self->data_));
431 template <
typename T>
437 static size_t read_callback(
char *bufptr,
size_t size,
size_t nitems,
void *userdata) {
440 const auto bytes = size * nitems;
441 auto out_bytes = std::min<size_t>(bytes, (self->
data_.size() - self->
sendt_bytes_));
457 using ptr_t = std::unique_ptr<Request>;
471 curl_slist_free_all(headers_);
478 completion_ = std::move(completion);
483 auto fp = fopen(path.c_str(),
"rb");
485 const auto e =
errno;
489 fp_= std::shared_ptr<FILE>(fp, std::fclose);
499 const auto result = curl_easy_perform(*eh_);
500 CallCompletion(result);
511 default_in_handler_ = std::move(ptr);
515 default_out_handler_ = std::move(ptr);
524 return default_data_buffer_;
529 mime_ = curl_mime_init(*eh_);
534 const std::string& name,
535 const std::string& remoteName,
536 const std::string& mimeType) {
540 auto * part = curl_mime_addpart(mime_);
541 curl_mime_filedata(part, path.c_str());
542 curl_mime_name(part, name.empty() ?
"file" :name.c_str());
544 if (!remoteName.empty()) {
545 curl_mime_filename(part, remoteName.c_str());
548 if (!mimeType.empty()) {
549 curl_mime_type(part, mimeType.c_str());
554 void CallCompletion(CURLcode cc) {
557 curl_easy_getinfo (*eh_, CURLINFO_RESPONSE_CODE,
558 &result.http_response_code);
559 RESTINCURL_LOG(
"Complete: http code: " << result.http_response_code);
561 if (!default_data_buffer_.empty()) {
562 result.body = std::move(default_data_buffer_);
568 void SetRequestType() {
569 switch(request_type_) {
571 curl_easy_setopt(*eh_, CURLOPT_HTTPGET, 1L);
574 headers_ = curl_slist_append(headers_,
"Transfer-Encoding: chunked");
575 curl_easy_setopt(*eh_, CURLOPT_UPLOAD, 1L);
578 headers_ = curl_slist_append(headers_,
"Transfer-Encoding: chunked");
579 curl_easy_setopt(*eh_, CURLOPT_UPLOAD, 0L);
580 curl_easy_setopt(*eh_, CURLOPT_POST, 1L);
583 curl_easy_setopt(*eh_, CURLOPT_NOBODY, 1L);
586 curl_easy_setopt(*eh_, CURLOPT_CUSTOMREQUEST,
"OPTIONS");
589 headers_ = curl_slist_append(headers_,
"Transfer-Encoding: chunked");
590 curl_easy_setopt(*eh_, CURLOPT_CUSTOMREQUEST,
"PATCH");
593 curl_easy_setopt(*eh_, CURLOPT_CUSTOMREQUEST,
"DELETE");
597 curl_easy_setopt(*eh_, CURLOPT_MIMEPOST, mime_);
600 throw Exception(
"Unsupported request type" + std::to_string(
static_cast<int>(request_type_)));
607 std::unique_ptr<DataHandlerBase> default_out_handler_;
608 std::unique_ptr<DataHandlerBase> default_in_handler_;
610 std::string default_data_buffer_;
611 std::shared_ptr<FILE> fp_;
612 curl_mime *mime_ = {};
615#if RESTINCURL_ENABLE_ASYNC
618 enum FdUsage { FD_READ = 0, FD_WRITE = 1};
624 auto status = pipe(pipefd_.data());
628 for(
auto fd : pipefd_) {
630 if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
632 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
637 for(
auto fd : pipefd_) {
645 if (write(pipefd_[FD_WRITE], &
byte, 1) != 1) {
655 while(read(pipefd_[FD_READ], &
byte, 1) > 0) {
692#ifdef RESTINCURL_WITH_OPENSSL_THREADS
693 static void opensslLockCb(
int mode,
int type,
char *,
int) {
694 if(mode & CRYPTO_LOCK) {
702 static unsigned long getThreadId(
void) {
703 return reinterpret_cast<unsigned long>(::this_thread::get_id());
707 static void tlsLockInit() {
708 CRYPTO_set_id_callback((
unsigned long (*)())getThreadId);
709 CRYPTO_set_locking_callback((
void (*)())opensslLockCb);
714 CRYPTO_set_locking_callback(NULL);
737 static void unlock() {
741 static std::mutex mutex_;
747 WorkerThread(std::function<
void ()> && fn)
748 : thread_{std::move(fn)} {}
751 if (thread_.get_id() == std::this_thread::get_id()) {
758 std::call_once(joined_, [
this] {
759 const_cast<WorkerThread *
>(
this)->thread_.join();
763 bool Joinable()
const {
764 return thread_.joinable();
767 operator std::thread& () {
return thread_; }
771 mutable std::once_flag joined_;
778 if (thread_ && thread_->Joinable()) {
786 assert(!mutex_.try_lock());
787 if (abort_ || done_) {
791 thread_ = std::make_shared<WorkerThread>([&] {
797 }
catch (
const std::exception& ex) {
810 static std::unique_ptr<Worker>
Create() {
811 return std::make_unique<Worker>();
818 queue_.push_back(std::move(req));
823 decltype(thread_) thd;
827 if (thread_ && thread_->Joinable()) {
841 close_pending_ =
true;
871 return ongoing_.size();
880 decltype(queue_) tmp;
885 tmp = std::move(queue_);
886 pending_entries_in_queue_ =
false;
890 auto it = queue_.begin();
894 assert(it != queue_.end());
895 tmp.push_back(std::move(*it));
898 queue_.erase(queue_.begin(), it);
904 pending_entries_in_queue_ =
true;
908 for(
auto& req: tmp) {
910 const auto& eh = req->GetEasyHandle();
912 ongoing_[eh] = std::move(req);
913 const auto mc = curl_multi_add_handle(handle_, eh);
914 if (mc != CURLM_OK) {
915 throw CurlException(
"curl_multi_add_handle", mc);
921 if ((handle_ = curl_multi_init()) ==
nullptr) {
922 throw std::runtime_error(
"curl_multi_init() failed");
931 curl_multi_cleanup(handle_);
936 bool EvaluateState(
const bool transfersRunning,
const bool doDequeue)
const noexcept {
940 <<
", do_dequeue=" << doDequeue
941 <<
", close_pending_=" << close_pending_);
943 return !abort_ && (transfersRunning || !close_pending_);
946 auto GetNextTimeout() const noexcept {
947 return std::chrono::steady_clock::now()
952 int transfers_running = -1;
956 bool do_dequeue =
true;
957 auto timeout = GetNextTimeout();
959 while (EvaluateState(transfers_running, do_dequeue)) {
967 const bool initial_ideling = transfers_running == -1;
968 curl_multi_perform(handle_, &transfers_running);
969 if ((transfers_running == 0) && initial_ideling) {
970 transfers_running = -1;
974 if (transfers_running <= 0) {
975 if (timeout < std::chrono::steady_clock::now()) {
976 RESTINCURL_LOG(
"Idle timeout. Will shut down the worker-thread.");
980 timeout = GetNextTimeout();
984 while (
auto m = curl_multi_info_read(handle_, &numLeft)) {
986 auto it = ongoing_.find(m->easy_handle);
987 if (it != ongoing_.end()) {
990 <<
"; with result: " << m->data.result <<
" expl: '" << curl_easy_strerror(m->data.result)
991 <<
"'; with msg: " << m->msg);
994 it->second->Complete(m->data.result, m->msg);
995 }
catch(
const std::exception& ex) {
998 if (m->msg == CURLMSG_DONE) {
999 curl_multi_remove_handle(handle_, m->easy_handle);
1001 it->second->GetEasyHandle().Close();
1012 if (abort_ || (!transfers_running && close_pending_)) {
1017 auto next_timeout = std::chrono::duration_cast<std::chrono::milliseconds>(
1018 timeout - std::chrono::steady_clock::now());
1019 long sleep_duration = std::max<long>(1, next_timeout.count());
1028 if (transfers_running > 0) {
1029 curl_multi_timeout(handle_, &sleep_duration);
1030 if (sleep_duration < 0) {
1031 sleep_duration = 1000;
1035 const auto mc = curl_multi_fdset(handle_, &fdread, &fdwrite, &fdexcep, &maxfd);
1037 if (mc != CURLM_OK) {
1038 throw CurlException(
"curl_multi_fdset", mc);
1043 sleep_duration = 50;
1047 struct timeval tv = {};
1048 tv.tv_sec = sleep_duration / 1000;
1049 tv.tv_usec = (sleep_duration % 1000) * 1000;
1051 const auto signalfd = signal_.GetReadFd();
1055 <<
" ms. Next timeout in " << next_timeout.count() <<
" ms. "
1056 << transfers_running <<
" active transfers.");
1058 FD_SET(signalfd, &fdread);
1059 maxfd = std::max(signalfd, maxfd) + 1;
1061 const auto rval = select(maxfd, &fdread, &fdwrite, &fdexcep, &tv);
1065 if (FD_ISSET(signalfd, &fdread)) {
1067 do_dequeue = signal_.WasSignalled();
1071 if (pending_entries_in_queue_) {
1078 if (close_pending_ || abort_) {
1083 bool close_pending_ {
false};
1084 bool abort_ {
false};
1086 bool pending_entries_in_queue_ =
false;
1087 decltype(curl_multi_init()) handle_ = {};
1088 mutable std::mutex mutex_;
1089 std::shared_ptr<WorkerThread> thread_;
1090 std::deque<Request::ptr_t> queue_;
1091 std::map<EasyHandle::handle_t, Request::ptr_t> ongoing_;
1105 static size_t write_callback(
char *ptr,
size_t size,
size_t nitems,
void *userdata) {
1106 const auto bytes = size * nitems;
1110 static int debug_callback(CURL *handle, curl_infotype type,
1111 char *data,
size_t size,
1119 case CURLINFO_HEADER_OUT:
1120 msg =
"=> Send header: ";
1122 case CURLINFO_DATA_OUT:
1123 msg =
"=> Send data: ";
1125 case CURLINFO_SSL_DATA_OUT:
1126 msg =
"=> Send SSL data: ";
1128 case CURLINFO_HEADER_IN:
1129 msg =
"<= Recv header: ";
1131 case CURLINFO_DATA_IN:
1132 msg =
"<= Recv data: ";
1134 case CURLINFO_SSL_DATA_IN:
1135 msg =
"<= Recv SSL data: ";
1142 std::copy(data, data + size, std::back_inserter(msg));
1148 using ptr_t = std::unique_ptr<RequestBuilder>;
1155 , options_{
std::make_unique<class
Options>(request_->GetEasyHandle())}
1240 request_->GetHeaders() = curl_slist_append(request_->GetHeaders(), value);
1252 const std::string& value) {
1253 const auto v = name +
": " + value;
1254 return Header(v.c_str());
1259 return Header(
"Content-type: Application/json; charset=utf-8");
1273 return Header(
"Accept: Application/json");
1287 template <
typename T>
1290 options_->Set(opt, value);
1303 Option(CURLOPT_DEBUGFUNCTION, debug_callback);
1304 Option(CURLOPT_VERBOSE, 1L);
1306 Option(CURLOPT_VERBOSE, 0L);
1317 request_timeout_ = timeout;
1326 connect_timeout_ = timeout;
1341 throw Exception{
"Invalid curl operation for a file upload"};
1345 request_->OpenSourceFile(path);
1346 struct stat st = {};
1347 if(fstat(fileno(request_->GetSourceFp()), &st) != 0) {
1348 const auto e =
errno;
1353 options_->Set(CURLOPT_READDATA, request_->GetSourceFp());
1354 options_->Set(CURLOPT_INFILESIZE_LARGE,
static_cast<curl_off_t
>(st.st_size));
1355 have_data_out_ =
true;
1371 const std::string& name = {},
1372 const std::string& remoteName = {},
1373 const std::string& mimeType = {}) {
1377 throw Exception{
"Must use PostMime operation to add mime attachments"};
1379 request_->AddFileAsMimeData(path, name, remoteName, mimeType);
1394 throw Exception{
"Invalid curl operation for a file upload"};
1398 request_->OpenSourceFile(path);
1399 struct stat st = {};
1400 if(fstat(fileno(request_->GetSourceFp()), &st) != 0) {
1401 const auto e =
errno;
1406 options_->Set(CURLOPT_READDATA, request_->GetSourceFp());
1407 options_->Set(CURLOPT_INFILESIZE_LARGE,
static_cast<curl_off_t
>(st.st_size));
1408 have_data_out_ =
true;
1422 template <
typename T>
1426 options_->Set(CURLOPT_READDATA, &dh);
1427 have_data_out_ =
true;
1438 template <
typename T>
1441 auto handler = std::make_unique<OutDataHandler<T>>(std::move(data));
1442 auto& handler_ref = *handler;
1443 request_->SetDefaultOutHandler(std::move(handler));
1457 template <
typename T>
1461 options_->Set(CURLOPT_WRITEDATA, &dh);
1462 have_data_in_ =
true;
1474 template <
typename T>
1477 auto handler = std::make_unique<InDataHandler<T>>(data);
1478 auto& handler_ref = *handler;
1479 request_->SetDefaultInHandler(std::move(handler));
1490 options_->Set(CURLOPT_WRITEFUNCTION, write_callback);
1491 have_data_in_ =
true;
1507 completion_ = std::move(fn);
1524 const std::string& passwd) {
1527 if (!name.empty() && !passwd.empty()) {
1528 options_->Set(CURLOPT_USERNAME, name.c_str());
1529 options_->Set(CURLOPT_PASSWORD, passwd.c_str());
1542 options_->Set(CURLOPT_READFUNCTION, handler);
1543 options_->Set(CURLOPT_READDATA, userdata);
1544 have_data_out_ =
true;
1555 options_->Set(CURLOPT_WRITEFUNCTION,handler);
1556 options_->Set(CURLOPT_WRITEDATA, userdata);
1557 have_data_in_ =
true;
1564 if (!have_data_in_) {
1566 this->
StoreData(request_->getDefaultInBuffer());
1569 if (have_data_out_) {
1570 options_->Set(CURLOPT_UPLOAD, 1L);
1573 if (request_timeout_ >= 0) {
1574 options_->Set(CURLOPT_TIMEOUT_MS, request_timeout_);
1577 if (connect_timeout_ >= 0) {
1578 options_->Set(CURLOPT_CONNECTTIMEOUT_MS, connect_timeout_);
1582 if (request_->GetHeaders()) {
1583 options_->Set(CURLOPT_HTTPHEADER, request_->GetHeaders());
1587 options_->Set(CURLOPT_URL, url_);
1591 request_->Prepare(request_type_, std::move(completion_));
1607 request_->Execute();
1610#if RESTINCURL_ENABLE_ASYNC
1625 worker_.Enqueue(std::move(request_));
1630 std::unique_ptr<Request> request_;
1631 std::unique_ptr<class Options> options_;
1634 bool have_data_in_ =
false;
1635 bool have_data_out_ =
false;
1636 bool is_built_ =
false;
1638 long request_timeout_ = 10000L;
1639 long connect_timeout_ = 3000L;
1640#if RESTINCURL_ENABLE_ASYNC
1674 static std::once_flag flag;
1675 std::call_once(flag, [] {
1677 curl_global_init(CURL_GLOBAL_DEFAULT);
1692#if RESTINCURL_ENABLE_ASYNC
1696 }
catch (
const std::exception& ex) {
1720 std::unique_ptr<RequestBuilder>
Build() {
1721 return std::make_unique<RequestBuilder>(
1728#if RESTINCURL_ENABLE_ASYNC
1734 worker_->CloseWhenFinished();
1765 return worker_->HaveThread();
1773 return worker_->GetNumActiveRequests();
1778#if RESTINCURL_ENABLE_ASYNC
1779 std::unique_ptr<Worker> worker_ = std::make_unique<Worker>();
int errno
This is free and unencumbered software released into the public domain.
std::unique_ptr< RequestBuilder > Build()
Definition restincurl.h:1720
virtual ~Client()
Definition restincurl.h:1691
void CloseWhenFinished()
Definition restincurl.h:1733
size_t GetNumActiveRequests()
Definition restincurl.h:1772
Client(const bool init=true)
Definition restincurl.h:1672
bool HaveWorker() const
Definition restincurl.h:1764
void Close()
Definition restincurl.h:1746
void WaitForFinish()
Definition restincurl.h:1756
Definition restincurl.h:306
Definition restincurl.h:324
void Close()
Definition restincurl.h:337
EasyHandle()
Definition restincurl.h:329
std::unique_ptr< EasyHandle > ptr_t
Definition restincurl.h:326
decltype(curl_easy_init()) handle_t
Definition restincurl.h:327
~EasyHandle()
Definition restincurl.h:333
Definition restincurl.h:289
Exception(const std::string &msg)
Definition restincurl.h:291
Options & Set(const CURLoption &opt, const std::string &value)
Definition restincurl.h:379
Options & Set(const CURLoption &opt, const T &value)
Definition restincurl.h:365
Options(EasyHandle &eh)
Definition restincurl.h:357
RequestBuilder & Delete(const std::string &url)
Definition restincurl.h:1223
RequestBuilder & BasicAuthentication(const std::string &name, const std::string &passwd)
Definition restincurl.h:1523
RequestBuilder & Trace(bool enable=true)
Definition restincurl.h:1301
RequestBuilder & WithJson(std::string body)
Definition restincurl.h:1266
RequestBuilder & Patch(const std::string &url)
Definition restincurl.h:1218
bool CanSendFile() const noexcept
Definition restincurl.h:1174
RequestBuilder & IgnoreIncomingData()
Definition restincurl.h:1489
RequestBuilder & RequestTimeout(const long timeout)
Definition restincurl.h:1316
void ExecuteSynchronous()
Definition restincurl.h:1605
RequestBuilder & Post(const std::string &url)
Definition restincurl.h:1203
std::unique_ptr< RequestBuilder > ptr_t
Definition restincurl.h:1148
RequestBuilder & PostMime(const std::string &url)
Definition restincurl.h:1208
RequestBuilder & AcceptJson()
Definition restincurl.h:1272
RequestBuilder & WithJson()
Definition restincurl.h:1258
RequestBuilder & SendFile(const std::string &path)
Definition restincurl.h:1337
RequestBuilder & Put(const std::string &url)
Definition restincurl.h:1213
RequestBuilder & Get(const std::string &url)
Definition restincurl.h:1193
RequestBuilder & StoreData(T &data)
Definition restincurl.h:1475
void Build()
Definition restincurl.h:1561
RequestBuilder & SetReadHandler(size_t(*handler)(char *, size_t, size_t, void *), void *userdata)
Definition restincurl.h:1541
RequestBuilder(Worker &worker)
Definition restincurl.h:1149
RequestBuilder & Prepare(RequestType rt, const std::string &url)
Definition restincurl.h:1165
void Execute()
Definition restincurl.h:1623
RequestBuilder & SetWriteHandler(size_t(*handler)(char *, size_t, size_t, void *), void *userdata)
Definition restincurl.h:1554
RequestBuilder & StoreData(InDataHandler< T > &dh)
Definition restincurl.h:1458
RequestBuilder & SendFileAsMimeData(const std::string &path, const std::string &name={}, const std::string &remoteName={}, const std::string &mimeType={})
Definition restincurl.h:1370
RequestBuilder & ConnectTimeout(const long timeout)
Definition restincurl.h:1325
RequestBuilder & Head(const std::string &url)
Definition restincurl.h:1198
RequestBuilder & Header(const std::string &name, const std::string &value)
Definition restincurl.h:1251
RequestBuilder & WithCompletion(completion_fn_t fn)
Definition restincurl.h:1505
~RequestBuilder()
Definition restincurl.h:1161
RequestBuilder & SendData(OutDataHandler< T > &dh)
Definition restincurl.h:1423
RequestBuilder & Options(const std::string &url)
Definition restincurl.h:1228
RequestBuilder & Header(const char *value)
Definition restincurl.h:1237
RequestBuilder & SendData(T data)
Definition restincurl.h:1439
RequestBuilder & SendFileAsForm(const std::string &path)
Definition restincurl.h:1390
RequestBuilder & Option(const CURLoption &opt, const T &value)
Definition restincurl.h:1288
Definition restincurl.h:455
~Request()
Definition restincurl.h:469
void SetDefaultOutHandler(std::unique_ptr< DataHandlerBase > ptr)
Definition restincurl.h:514
Request(EasyHandle::ptr_t &&eh)
Definition restincurl.h:464
void Execute()
Definition restincurl.h:498
EasyHandle & GetEasyHandle() noexcept
Definition restincurl.h:507
void InitMime()
Definition restincurl.h:527
void SetDefaultInHandler(std::unique_ptr< DataHandlerBase > ptr)
Definition restincurl.h:510
void Prepare(const RequestType rq, completion_fn_t completion)
Definition restincurl.h:475
curl_slist * headers_t
Definition restincurl.h:518
void Complete(CURLcode cc, const CURLMSG &)
Definition restincurl.h:503
Request()
Definition restincurl.h:459
RequestType GetRequestType() noexcept
Definition restincurl.h:508
FILE * GetSourceFp()
Definition restincurl.h:492
headers_t & GetHeaders()
Definition restincurl.h:519
std::unique_ptr< Request > ptr_t
Definition restincurl.h:457
std::string & getDefaultInBuffer()
Definition restincurl.h:523
void AddFileAsMimeData(const std::string &path, const std::string &name, const std::string &remoteName, const std::string &mimeType)
Definition restincurl.h:533
void OpenSourceFile(const std::string &path)
Definition restincurl.h:481
~Signaler()
Definition restincurl.h:636
void Signal()
Definition restincurl.h:642
Signaler()
Definition restincurl.h:623
int GetReadFd()
Definition restincurl.h:650
std::array< int, 2 > pipefd_t
Definition restincurl.h:621
bool WasSignalled()
Definition restincurl.h:652
Definition restincurl.h:295
int getErrorCode() const noexcept
Definition restincurl.h:299
SystemException(const std::string &msg, const int e)
Definition restincurl.h:297
Definition restincurl.h:689
static void tlsLockKill()
Definition restincurl.h:724
static void tlsLOckInit()
Definition restincurl.h:719
Definition restincurl.h:744
void Close()
Definition restincurl.h:847
size_t GetNumActiveRequests() const
Definition restincurl.h:869
static std::unique_ptr< Worker > Create()
Definition restincurl.h:810
~Worker()
Definition restincurl.h:777
void CloseWhenFinished()
Definition restincurl.h:838
void Enqueue(Request::ptr_t req)
Definition restincurl.h:814
void Join() const
Definition restincurl.h:822
bool HaveThread() const noexcept
Definition restincurl.h:861
void PrepareThread()
Definition restincurl.h:784
bool IsDone() const
Definition restincurl.h:856
Definition restincurl.h:197
RequestType
Definition restincurl.h:278
@ OPTIONS
Definition restincurl.h:278
@ DELETE
Definition restincurl.h:278
@ PUT
Definition restincurl.h:278
@ PATCH
Definition restincurl.h:278
@ GET
Definition restincurl.h:278
@ POST
Definition restincurl.h:278
@ POST_MIME
Definition restincurl.h:278
@ INVALID
Definition restincurl.h:278
@ HEAD
Definition restincurl.h:278
std::lock_guard< std::mutex > lock_t
Definition restincurl.h:237
std::function< void(const Result &result)> completion_fn_t
Definition restincurl.h:286
Namespace for the standard library.
#define RESTINCURL_LOG(msg)
Macro to log debug messages.
Definition restincurl.h:170
#define RESTINCURL_IDLE_TIMEOUT_SEC
How long to wait for the next request before the idle worker-thread is stopped.
Definition restincurl.h:102
#define RESTINCURL_MAX_CONNECTIONS
Max concurrent connections.
Definition restincurl.h:73
#define RESTINCURL_LOG_TRACE(msg)
Macro to log debug messages.
Definition restincurl.h:193
#define RESTINCURL_ENABLE_ASYNC
Enables or disables asynchronous mode.
Definition restincurl.h:88
Definition restincurl.h:392
virtual ~DataHandlerBase()=default
Definition restincurl.h:405
static size_t write_callback(char *ptr, size_t size, size_t nitems, void *userdata)
Definition restincurl.h:410
T & data_
Definition restincurl.h:420
InDataHandler(T &data)
Definition restincurl.h:406
Definition restincurl.h:432
size_t sendt_bytes_
Definition restincurl.h:452
OutDataHandler(T &&v)
Definition restincurl.h:435
static size_t read_callback(char *bufptr, size_t size, size_t nitems, void *userdata)
Definition restincurl.h:437
T data_
Definition restincurl.h:451
OutDataHandler(const T &v)
Definition restincurl.h:434
Definition restincurl.h:241
CURLcode curl_code
Definition restincurl.h:263
long http_response_code
Definition restincurl.h:266
Result(const CURLcode &code)
Definition restincurl.h:243
std::string msg
Definition restincurl.h:269
std::string body
Definition restincurl.h:275
bool isOk() const noexcept
Definition restincurl.h:249