68 #define CURL_EV_INIT_CHECK(CONTEXT) do { \
70 HPD_LOG_ERROR((CONTEXT), "Curl not initialised"); \
71 HPD_LOG_RETURN((CONTEXT), HPD_E_STATE, "Did you remember to add the curl module to hpd?"); \
79 HPD_LOG_ERROR(curl_ev->context,
"curl_ev_socket_action() failed [code: %i]", cmc);
84 ev_timer_stop(loop, w);
87 HPD_LOG_ERROR(curl_ev->context,
"curl_ev_socket_action() failed [code: %i]", cmc);
95 ev_io_stop(curl_ev->loop, &(*w)->watcher);
98 if ((cmc = curl_multi_assign(curl_ev->
mult_handle, s, (*w)))) {
99 HPD_LOG_ERROR(context,
"Curl multi return an error [code: %i]", cmc);
109 return CURLM_OUT_OF_MEMORY;
116 ev_io_set(&w->watcher, s, EV_READ);
119 ev_io_set(&w->watcher, s, EV_WRITE);
121 case CURL_POLL_INOUT:
122 ev_io_set(&w->watcher, s, EV_READ | EV_WRITE);
126 return CURLM_INTERNAL_ERROR;
129 ev_io_start(curl_ev->loop, &w->watcher);
135 ev_io_stop(curl_ev->loop, &w->watcher);
148 case CURL_POLL_INOUT: {
154 case CURL_POLL_REMOVE: {
160 return CURLM_INTERNAL_ERROR;
169 if (timeout_ms == 0) {
171 HPD_LOG_ERROR(curl_ev->context,
"curl_ev_socket_action() failed [code: %i]", cmc);
174 }
else if (timeout_ms > 0) {
175 curl_ev->
timer.repeat = timeout_ms / 1000.0;
176 ev_timer_again(curl_ev->loop, &curl_ev->
timer);
178 ev_timer_stop(curl_ev->loop, &curl_ev->
timer);
197 if ((cmc = curl_multi_add_handle(curl_ev->
mult_handle, handle->
handle)))
goto add_error;
205 HPD_LOG_ERROR(context,
"Curl remove handle return an error [code: %i]", cmc2);
218 if ((cmc = curl_multi_socket_action(curl_ev->
mult_handle, sockfd, 0, &unused)))
219 HPD_LOG_RETURN(context, cmc,
"Curl multi return an error [code: %i]", cmc);
222 while ((m = curl_multi_info_read(curl_ev->
mult_handle, &unused))) {
228 CURL *easy_handle = m->easy_handle;
231 if (handle->
handle == easy_handle) {
232 CURLcode cc = m->
data.result;
234 HPD_LOG_WARN(context,
"Curl handle error: %s [code: %i]", curl_easy_strerror(cc), cc);
238 HPD_LOG_ERROR(context,
"Failed to remove handle [code: %i]", rc);
239 return CURLM_INTERNAL_ERROR;
242 HPD_LOG_ERROR(context,
"Failed to remove handle [code: %i]", rc);
243 return CURLM_INTERNAL_ERROR;
252 return CURLM_INTERNAL_ERROR;
271 if (TAILQ_EMPTY(&curl_ev->handles)) {
291 if (TAILQ_FIRST(&curl_ev->handles) == handle) {
312 curl_ev->context = context;
314 TAILQ_INIT(&curl_ev->handles);
315 TAILQ_INIT(&curl_ev->io_watchers);
322 curl_global_cleanup();
332 while (!TAILQ_EMPTY(&curl_ev->handles)) {
337 HPD_LOG_ERROR(curl_ev->context,
"Failed to remove handle [code: %i]", rc);
357 if ((cc = curl_global_init(CURL_GLOBAL_ALL)))
363 curl_ev->loop =
loop;
368 if ((cmc = curl_multi_setopt(curl_ev->
mult_handle, CURLMOPT_SOCKETDATA, curl_ev)))
goto curl_m_error;
370 if ((cmc = curl_multi_setopt(curl_ev->
mult_handle, CURLMOPT_TIMERDATA, curl_ev)))
goto curl_m_error;
377 curl_global_cleanup();
380 curl_ev->loop = NULL;
381 curl_global_cleanup();
384 curl_ev->loop = NULL;
385 curl_global_cleanup();
398 if (handle && (cmc = curl_multi_remove_handle(curl_ev->
mult_handle, handle->
handle)))
402 ev_timer_stop(curl_ev->loop, &curl_ev->
timer);
404 TAILQ_FOREACH_SAFE(io, &curl_ev->io_watchers,
HPD_TAILQ_FIELD, io_tmp) {
409 if ((cmc = curl_multi_cleanup(curl_ev->
mult_handle)))
hpd_error_t hpd_curl_ev_remove_handle(hpd_curl_ev_handle_t *handle)
static hpd_error_t curl_ev_on_destroy(void *data)
hpd_error_t hpd_curl_ev_cleanup(hpd_curl_ev_handle_t *handle)
#define HPD_LOG_RETURN(CONTEXT, E, FMT,...)
static CURLMcode curl_ev_start_watcher(curl_ev_io_t *w, curl_socket_t s, int what, const hpd_module_t *context)
static hpd_error_t curl_ev_on_create(void **data, const hpd_module_t *context)
static CURLMcode curl_ev_on_update_timer(CURLM *multi, long timeout_ms, void *userp)
static void curl_ev_on_timeout(hpd_ev_loop_t *loop, ev_timer *w, int revents)
const hpd_module_t * context
static void curl_ev_stop_watcher(curl_ev_io_t *w)
hpd_curl_ev_done_f on_done
#define HPD_CALLOC(PTR, NUM, CAST)
Allocates and zeros a structure.
hpd_error
[HPD_NULL_TERMINATED]
TAILQ_HEAD(hpd_map, hpd_pair)
hpd_error_t hpd_curl_ev_add_handle(hpd_curl_ev_handle_t *handle)
static hpd_error_t curl_ev_on_parse_opt(void *data, const char *name, const char *arg)
static CURLMcode curl_ev_on_update_socket(CURL *easy, curl_socket_t s, int what, void *userp, void *socketp)
#define HPD_LOG_VERBOSE(CONTEXT, FMT,...)
static curl_ev_t * curl_ev
enum hpd_error hpd_error_t
#define HPD_LOG_RETURN_E_ALLOC(CONTEXT)
[Application API Callbacks]
#define HPD_LOG_RETURN_E_NULL(CONTEXT)
static hpd_error_t curl_ev_on_start(void *data, hpd_t *hpd)
#define CURL_EV_INIT_CHECK(CONTEXT)
static struct ev_loop * loop
static CURLMcode curl_ev_socket_action(int sockfd)
static void curl_ev_on_io(hpd_ev_loop_t *loop, ev_io *w, int revents)
static hpd_error_t curl_ev_on_stop(void *data, hpd_t *hpd)
static hpd_error_t curl_ev_add_next()
static CURLMcode curl_ev_get_stopped_watcher(curl_ev_io_t **w, curl_socket_t s, const hpd_module_t *context)
#define HPD_LOG_WARN(CONTEXT, FMT,...)
struct ev_loop hpd_ev_loop_t
hpd_module_def_t hpd_curl_ev
#define HPD_LOG_ERROR(CONTEXT, FMT,...)
hpd_error_t hpd_get_loop(hpd_t *hpd, hpd_ev_loop_t **loop)