9 auto *multi = curl_multi_init();
11 return {curl::
Exception{
"curl_multi_init failed"}};
12 return {std::in_place_type<
Multi_t>, multi};
20 curl_multi{other.curl_multi}
22 other.curl_multi =
nullptr;
24 handles = other.handles;
29 curl_multi_cleanup(curl_multi);
30 curl_multi = other.curl_multi;
31 other.curl_multi =
nullptr;
33 handles = other.handles;
40 return curl_multi !=
nullptr;
46 curl_multi_cleanup(curl_multi);
51 bool success = curl_multi_add_handle(curl_multi, easy.curl_easy) != CURLM_ADDED_ALREADY;
60 curl_multi_remove_handle(curl_multi, easy.curl_easy);
63 std::size_t
Multi_t::get_number_of_handles()
const noexcept
70 long bitmask = max_concurrent_stream != 0 ? CURLPIPE_MULTIPLEX : CURLPIPE_NOTHING;
71 curl_multi_setopt(curl_multi, CURLMOPT_PIPELINING, bitmask);
73 if (max_concurrent_stream >= 1)
74 curl_multi_setopt(curl_multi, CURLMOPT_MAX_CONCURRENT_STREAMS, max_concurrent_stream);
78 auto Multi_t::
poll(curl_waitfd *extra_fds,
unsigned extra_nfds,
int timeout)
noexcept ->
83 auto code = curl_multi_poll(curl_multi, extra_fds, extra_nfds, timeout, &numfds);
84 if (code == CURLM_OUT_OF_MEMORY)
85 return {std::bad_alloc{}};
86 else if (code == CURLM_INTERNAL_ERROR)
89 assert(code == CURLM_OK);
96 if (get_number_of_handles() == 0)
99 return poll(extra_fds
, extra_nfds
, timeout
);
105 for (CURLMsg *m; (m = curl_multi_info_read(curl_multi, &msgq)); )
106 if (m->msg == CURLMSG_DONE) {
107 Easy_ref_t easy_ref{
static_cast<
char*>(m->easy_handle)};
108 return {easy_ref, easy_ref.check_perform(m->data.result,
"")};
113 auto Multi_t::check_perform(
long code,
int running_handles,
const char *fname)
noexcept ->
116 if (code == CURLM_OUT_OF_MEMORY)
117 return {std::bad_alloc{}};
118 else if (code == CURLM_INTERNAL_ERROR)
120 else if (code == CURLM_RECURSIVE_API_CALL)
123 assert(code == CURLM_OK);
125 return {running_handles};
127 auto Multi_t::perform_impl()
noexcept -> perform_ret_t
129 int running_handles = 0;
132 while ((code = curl_multi_perform(curl_multi, &running_handles)) == CURLM_CALL_MULTI_PERFORM);
134 return check_perform(code, running_handles,
"In curl_multi_perform");
139 timer_callback_t timer_callback,
void *timer_data)
noexcept
141 curl_multi_setopt(curl_multi, CURLMOPT_SOCKETFUNCTION, socket_callback);
142 curl_multi_setopt(curl_multi, CURLMOPT_SOCKETDATA, socket_data);
144 curl_multi_setopt(curl_multi, CURLMOPT_TIMERFUNCTION, timer_callback);
145 curl_multi_setopt(curl_multi, CURLMOPT_TIMERDATA, timer_data);
149 Ret_except<
void, std::invalid_argument>
151 auto code = curl_multi_assign(curl_multi, socketfd, per_sockptr);
152 if (code == CURLM_BAD_SOCKET)
153 return {std::invalid_argument{
"In curl::Multi_t::multi_assign: socketfd is not valid."}};
157 auto Multi_t::multi_socket_action_impl(curl_socket_t socketfd,
int ev_bitmask)
noexcept -> perform_ret_t
162 while ((code = curl_multi_socket_action(curl_multi, socketfd, ev_bitmask, &running_handles)) ==
163 CURLM_CALL_MULTI_PERFORM);
165 return check_perform(code, running_handles,
"In curl_multi_socket_action");