curl-cpp
static c++17 wrapper for curl with -fno-exceptions support
Classes | Public Types | Public Member Functions | Public Attributes | List of all members
curl::curl_t Class Reference

#include <curl.hpp>

Collaboration diagram for curl::curl_t:
Collaboration graph

Classes

struct  Easy_deleter
 
struct  Share_deleter
 
struct  Url_deleter
 
struct  Version
 

Public Types

using malloc_callback_t = void *(*)(std::size_t size)
 
using free_callback_t = void(*)(void *ptr)
 
using realloc_callback_t = void *(*)(void *old_ptr, std::size_t size)
 
using strdup_callback_t = char *(*)(const char *str)
 
using calloc_callback_t = void *(*)(std::size_t nmemb, std::size_t size)
 
using Easy_t = std::unique_ptr< char, Easy_deleter >
 
using Url_t = std::unique_ptr< char, Url_deleter >
 
using Share_t = std::unique_ptr< char, Share_deleter >
 

Public Member Functions

 curl_t (FILE *stderr_stream_arg) noexcept
 
 curl_t (FILE *stderr_stream_arg, malloc_callback_t malloc_callback, free_callback_t free_callback, realloc_callback_t realloc_callback, strdup_callback_t strdup_callback, calloc_callback_t calloc_callback) noexcept
 
 curl_t (const curl_t &)=delete
 
 curl_t (curl_t &&)=delete
 
curl_toperator= (const curl_t &)=delete
 
curl_toperator= (curl_t &&)=delete
 
 ~curl_t ()
 
bool has_compression_support () const noexcept
 
bool has_largefile_support () const noexcept
 
bool has_protocol (const char *protocol) const noexcept
 
bool has_ssl_support () const noexcept
 
bool has_ipv6_support () const noexcept
 
bool has_erase_all_cookies_in_mem_support () const noexcept
 
bool has_erase_all_session_cookies_in_mem_support () const noexcept
 
bool has_flush_cookies_to_jar () const noexcept
 
bool has_reload_cookies_from_file () const noexcept
 
bool has_disable_signal_handling_support () const noexcept
 
bool has_private_ptr_support () const noexcept
 
bool has_readfunc_abort_support () const noexcept
 
bool has_pause_support () const noexcept
 
bool has_header_option_support () const noexcept
 
bool has_set_ip_addr_only_support () const noexcept
 
bool has_redirect_url_support () const noexcept
 
bool has_getinfo_cookie_list_support () const noexcept
 
bool has_buffer_size_tuning_support () const noexcept
 
bool has_buffer_size_growing_support () const noexcept
 
bool has_get_active_socket_support () const noexcept
 
auto create_easy (std::size_t buffer_size=0) noexcept -> Easy_t
 
auto dup_easy (const Easy_t &easy, std::size_t buffer_size=0) noexcept -> Easy_t
 
bool has_CURLU () const noexcept
 
auto create_Url () noexcept -> Url_t
 
auto dup_Url (const Url_t &url) noexcept -> Url_t
 
bool has_multi_poll_support () const noexcept
 
bool has_multi_socket_support () const noexcept
 
bool has_http2_multiplex_support () const noexcept
 
bool has_max_concurrent_stream_support () const noexcept
 
auto create_multi () noexcept -> Ret_except< Multi_t, curl::Exception >
 
bool has_ssl_session_sharing_support () const noexcept
 
bool has_connection_cache_sharing_support () const noexcept
 
bool has_psl_sharing_support () const noexcept
 
auto create_share () noexcept -> Share_t
 

Public Attributes

FILE * stderr_stream
 
const void *const version_info
 
const Version version
 
bool disable_signal_handling_v = false
 
const char *const version_str
 

Detailed Description

Warning
Must be defined before any thread is created.

There can be multiple instances of this object, as long as during ctor and dtor, there is only one thread in the program.

Examples
curl_easy_get.cc, curl_multi_poll.cc, curl_multi_poll2.cc, curl_multi_socket_action_epoll.cc, curl_multi_socket_action_event.cc, curl_multi_socket_action_uv.cc, curl_share.cc, and curl_url.cc.

Definition at line 62 of file curl.hpp.

Member Typedef Documentation

◆ Easy_t

using curl::curl_t::Easy_t = std::unique_ptr<char, Easy_deleter>

RAII wrapper for curl's easy handler.

Definition at line 278 of file curl.hpp.

◆ Url_t

using curl::curl_t::Url_t = std::unique_ptr<char, Url_deleter>

RAII wrapper for curl's Url parser.

Definition at line 338 of file curl.hpp.

◆ Share_t

using curl::curl_t::Share_t = std::unique_ptr<char, Share_deleter>

RAII wrapper for curl's Share handler.

Definition at line 384 of file curl.hpp.

Constructor & Destructor Documentation

◆ curl_t() [1/2]

curl::curl_t::curl_t ( FILE *  stderr_stream_arg)
noexcept

Since curl_t is designed to be usable as static variable, it would call errx on error.

It would make sure that Easy_ref_t::get_response_code() is usable before initializing libcurl.
As a side effect, it also make sure that Easy_ref_t::getinfo_sizeof_*, getinfo_transfer_time, getinfo_effective_url must be present.

This is not thread-safe.

Definition at line 70 of file curl.cc.

70  :
71  stderr_stream{initialize_and_return_arg(stderr_stream_arg)},
72  version_info {curl_version_info(CURLVERSION_NOW)},
73  version {static_cast<const curl_version_info_data*>(version_info)->version_num},
74  version_str {static_cast<const curl_version_info_data*>(version_info)->version}
75 {
76  if (version < Version::from(7, 4, 1))
77  errx(1, "CURLINFO_RESPONSE_CODE isn't supported in this version: %s, %" PRIu32,
78  version_str, version.num);
79 }

◆ curl_t() [2/2]

curl::curl_t::curl_t ( FILE *  stderr_stream_arg,
malloc_callback_t  malloc_callback,
free_callback_t  free_callback,
realloc_callback_t  realloc_callback,
strdup_callback_t  strdup_callback,
calloc_callback_t  calloc_callback 
)
noexcept

If you are using libcurl from multiple threads or libcurl was built with the threaded resolver option, then the callback functions must be thread safe.

The threaded resolver is a common build option to enable (and in some cases the default) so portable application should make these callback functions thread safe.

All callback arguments must be set to valid function pointers.

libcurl support this from 7.12.0.
If this wasn't supported, you binary probably would have problem during dynamic binding.
NOTE: as a side effect, it also guarantees curl_t::has_buffer_size_tuning_support() to be true.

it would call errx on error.

It would make sure that Easy_ref_t::get_response_code() is usable before initializing libcurl.
As a side effect, it also make sure that Easy_ref_t::getinfo_sizeof_*, getinfo_transfer_time, getinfo_effective_url must be present.

This is not thread-safe.

Definition at line 105 of file curl.cc.

110  :
111  stderr_stream{initialize_and_return_last_arg(malloc_callback,
112  free_callback,
113  realloc_callback,
114  strdup_callback,
115  calloc_callback,
116  stderr_stream_arg)},
117  version_info {curl_version_info(CURLVERSION_NOW)},
118  version {static_cast<const curl_version_info_data*>(version_info)->version_num},
119  version_str {static_cast<const curl_version_info_data*>(version_info)->version}
120 {
121  if (version < Version::from(7, 4, 1))
122  errx(1, "CURLINFO_RESPONSE_CODE isn't supported in this version: %s, %" PRIu32,
123  version_str, version.num);
124 }

◆ ~curl_t()

curl::curl_t::~curl_t ( )

Destructor is not thread safe.

You must not call it when any other thread in the program (i.e. a thread sharing the same memory) is running.

This doesn't just mean no other thread that is using libcurl. Because curl_global_cleanup calls functions of other libraries that are similarly thread unsafe, it could conflict with any other thread that uses these other libraries.

This dtor does not block waiting for any libcurl-created threads to terminate (such as threads used for name resolving).

If a module containing libcurl is dynamically unloaded while libcurl-created threads are still running then your program may crash or other corruption may occur.

We recommend you do not run libcurl from any module that may be unloaded dynamically.

This behavior may be addressed in the future.

Definition at line 265 of file curl.cc.

266 {
267  curl_global_cleanup();
268 }

Member Function Documentation

◆ has_protocol()

bool curl::curl_t::has_protocol ( const char *  protocol) const
noexcept
Parameters
protocolshould be lower-case

Definition at line 136 of file curl.cc.

137 {
138  auto *info = static_cast<const curl_version_info_data*>(version_info);
139  auto *protocols = info->protocols;
140 
141  for (std::size_t i = 0; protocols[i]; ++i)
142  if (std::strcmp(protocols[i], protocol) == 0)
143  return true;
144 
145  return false;
146 }

◆ create_easy()

auto curl::curl_t::create_easy ( std::size_t  buffer_size = 0) -> Easy_t
noexcept
Parameters
buffer_sizesize of receiver buffer.
               This buffer size is by default CURL_MAX_WRITE_SIZE (16kB). 
               The maximum buffer size allowed to be set is CURL_MAX_READ_SIZE (512kB). 
               The minimum buffer size allowed to be set is 1024.

               Set to 0 to use default value.

               This param is just treated as a request, not an order.
Returns
If == nullptr, then curl_easy cannot be created.
  • It can be no memory left;
  • Or, initialization code for some part of lib failed.

If stderr_stream set to non-NULL, verbose info will be printed there. If disable_signal_handling_v is set, signal handling is disabled.

As long as stderr_stream and disable_signal_handling_v is not modified when create_easy is called, this function is thread-safe.

Examples
curl_share.cc.

Definition at line 20 of file curl_easy.cc.

21 {
22  CURL *curl = curl_easy_init();
23  if (!curl)
24  return {nullptr};
25 
26  if (stderr_stream) {
27  curl_easy_setopt(curl, CURLOPT_STDERR, stderr_stream);
28  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
29  }
30 
31  // Enable TCP_keepalive
32  curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
33 
34  if (buffer_size)
35  curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, buffer_size);
36 
38  curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
39 
40  using Easy_ptr = std::unique_ptr<char, Easy_deleter>;
41  return {Easy_ptr{static_cast<char*>(curl)}};
42 }

◆ dup_easy()

auto curl::curl_t::dup_easy ( const Easy_t easy,
std::size_t  buffer_size = 0 
) -> Easy_t
noexcept
Parameters
easymust not be nullptr
buffer_sizesame as create_easy
Returns
same as create_easy

All string passed into curl_easy_setopt using char* will be pointed by the new hanlde as well. Thus they must be kept around until both handles is destroyed.

The new handle will not inherit any state information, no connections, no SSL sessions and no cookies.

It also will not inherit any share object states or options (it will be made as if CURLOPT_SHARE was set to NULL).

If stderr_stream set to non-nullptr, verbose info will be printed there. If disable_signal_handling_v is set, signal handling is disabled.

easy must not be used in any way during this function call.

Definition at line 43 of file curl_easy.cc.

44 {
45  CURL *curl = curl_easy_duphandle(e.get());
46  if (!curl)
47  return {nullptr};
48 
49  if (stderr_stream) {
50  curl_easy_setopt(curl, CURLOPT_STDERR, stderr_stream);
51  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
52  }
53 
54  if (buffer_size)
55  curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, buffer_size);
56 
58  curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
59 
60  using Easy_ptr = std::unique_ptr<char, Easy_deleter>;
61  return {Easy_ptr{static_cast<char*>(curl)}};
62 }

◆ has_CURLU()

bool curl::curl_t::has_CURLU ( ) const
noexcept

has curl::Url support

Definition at line 227 of file curl.cc.

228 {
229  return version >= Version::from(7, 63, 0);
230 }

◆ create_Url()

auto curl::curl_t::create_Url ( ) -> Url_t
noexcept
Returns
nullptr if not enough memory.

Since Url_ref_t doesn't have any other data except pointer to CURLU itself, returning std::unique_ptr instead of an object like Easy_t would make it easier to manage it in custom ways like std::shared_ptr.

It is thread-safe.

Definition at line 11 of file curl_url.cc.

12 {
13  return Url_t{static_cast<char*>(static_cast<void*>(curl_url()))};
14 }

◆ dup_Url()

auto curl::curl_t::dup_Url ( const Url_t url) -> Url_t
noexcept
Parameters
url!= nullptr

url must not be used during this function call.

Definition at line 15 of file curl_url.cc.

16 {
17  auto *new_curl_url = curl_url_dup(static_cast<CURLU*>(static_cast<void*>(url.get())));
18  return Url_t{static_cast<char*>(static_cast<void*>(new_curl_url))};
19 }

◆ has_http2_multiplex_support()

bool curl::curl_t::has_http2_multiplex_support ( ) const
noexcept

http2 multiplex is turn on by default, if supported.

Definition at line 241 of file curl.cc.

242 {
243  return version >= Version::from(7, 43, 0);
244 }

◆ create_multi()

auto curl::curl_t::create_multi ( ) -> Ret_except<Multi_t, curl::Exception>
noexcept

NOTE that http1 pipeline is always disabled.

Definition at line 7 of file curl_multi.cc.

8 {
9  auto *multi = curl_multi_init();
10  if (!multi)
11  return {curl::Exception{"curl_multi_init failed"}};
12  return {std::in_place_type<Multi_t>, multi};
13 }

◆ create_share()

auto curl::curl_t::create_share ( ) -> Share_t
noexcept

Create share handler.

It is thread-safe.

Definition at line 10 of file curl_share.cc.

11 {
12  return Share_t{static_cast<char*>(static_cast<void*>(curl_share_init()))};
13 }

Member Data Documentation

◆ stderr_stream

FILE* curl::curl_t::stderr_stream

Modification of the variable below is sure not thread-safe.

Definition at line 115 of file curl.hpp.

◆ version_info

const void* const curl::curl_t::version_info

Result of curl_version_info(CURLVERSION_NOW). Cached for faster access.

Definition at line 121 of file curl.hpp.

◆ version

const Version curl::curl_t::version

Version of the libcurl loaded dynamically.

Definition at line 125 of file curl.hpp.

◆ disable_signal_handling_v

bool curl::curl_t::disable_signal_handling_v = false

disable_signal_handling_v is placed here to compress alignment requirement for bool and Version.

Precondition
has_disable_signal_handling_support()

If your libcurl uses standard name resolver, disable signal handling might cause timeout to never occur during name resolution.

Disable signal handling makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end.

libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire.

In addition, using CURLAUTH_NTLM_WB authentication could cause a SIGCHLD signal to be raised.

Modifing this would only affect Easy_t handle created after the modification.

Definition at line 147 of file curl.hpp.

◆ version_str

const char* const curl::curl_t::version_str

Version of the libcurl linked dynamically in string.

Definition at line 152 of file curl.hpp.


The documentation for this class was generated from the following files:
curl::curl_t::Share_t
std::unique_ptr< char, Share_deleter > Share_t
Definition: curl.hpp:384
curl::Exception
Definition: curl.hpp:16
curl::curl_t::version_str
const char *const version_str
Definition: curl.hpp:152
curl::curl_t::disable_signal_handling_v
bool disable_signal_handling_v
Definition: curl.hpp:147
curl::curl_t::version_info
const void *const version_info
Definition: curl.hpp:121
curl::curl_t::stderr_stream
FILE * stderr_stream
Definition: curl.hpp:115
curl::curl_t::version
const Version version
Definition: curl.hpp:125
curl::curl_t::Url_t
std::unique_ptr< char, Url_deleter > Url_t
Definition: curl.hpp:338